mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-26 14:23:09 +00:00
When a quicksetting is changed to not available, it should be removed from the model. The proper API call to beginRemoveRows() has the index of the last removed element as last parameter and will fail with null. This patch makes dynamically removing a quicksetting by changing the available property to false. Signed-off-by: Sebastian Kügler <sebas@kde.org>
218 lines
6.9 KiB
C++
218 lines
6.9 KiB
C++
/*
|
|
* SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>
|
|
* SPDX-FileCopyrightText: 2022-2024 Devin Lin <devin@kde.org>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
|
*/
|
|
|
|
#include "quicksettingsmodel.h"
|
|
|
|
#include <KPackage/PackageLoader>
|
|
|
|
#include <KLocalizedContext>
|
|
#include <QFileInfo>
|
|
#include <QQmlContext>
|
|
#include <QQmlEngine>
|
|
|
|
QuickSettingsModel::QuickSettingsModel(QObject *parent)
|
|
: QAbstractListModel{parent}
|
|
, m_savedQuickSettings{new SavedQuickSettings{this}}
|
|
{
|
|
// Listen to events to enabled quicksettings, and update accordingly
|
|
connect(m_savedQuickSettings->enabledQuickSettingsModel(), &SavedQuickSettingsModel::modelReset, this, [this]() {
|
|
loadQuickSettings();
|
|
});
|
|
connect(m_savedQuickSettings->enabledQuickSettingsModel(), &SavedQuickSettingsModel::rowsInserted, this, [this](const QModelIndex &, int first, int last) {
|
|
for (int i = first; i <= last; ++i) {
|
|
KPluginMetaData metaData = m_savedQuickSettings->enabledQuickSettingsModel()->takeRow(i);
|
|
loadQuickSetting(metaData, true);
|
|
}
|
|
});
|
|
connect(m_savedQuickSettings->enabledQuickSettingsModel(),
|
|
&SavedQuickSettingsModel::rowsAboutToBeRemoved,
|
|
this,
|
|
[this](const QModelIndex &, int first, int last) {
|
|
for (int i = first; i <= last; ++i) {
|
|
KPluginMetaData metaData = m_savedQuickSettings->enabledQuickSettingsModel()->takeRow(i);
|
|
auto index = m_quickSettingsMetaData.indexOf(metaData);
|
|
removeQuickSetting(index);
|
|
}
|
|
});
|
|
connect(m_savedQuickSettings->enabledQuickSettingsModel(),
|
|
&SavedQuickSettingsModel::rowsMoved,
|
|
this,
|
|
[this](const QModelIndex &, int sourceStart, int sourceEnd, const QModelIndex &, int) {
|
|
for (int i = sourceStart; i <= sourceEnd; ++i) {
|
|
KPluginMetaData metaData = m_savedQuickSettings->enabledQuickSettingsModel()->takeRow(i);
|
|
auto index = m_quickSettingsMetaData.indexOf(metaData);
|
|
removeQuickSetting(index);
|
|
loadQuickSetting(metaData, true);
|
|
}
|
|
});
|
|
}
|
|
|
|
void QuickSettingsModel::classBegin()
|
|
{
|
|
m_loaded = true;
|
|
loadQuickSettings();
|
|
}
|
|
|
|
void QuickSettingsModel::componentComplete()
|
|
{
|
|
}
|
|
|
|
QHash<int, QByteArray> QuickSettingsModel::roleNames() const
|
|
{
|
|
return {{Qt::UserRole, "modelData"}};
|
|
}
|
|
|
|
int QuickSettingsModel::rowCount(const QModelIndex &parent) const
|
|
{
|
|
Q_UNUSED(parent)
|
|
return m_quickSettings.size();
|
|
}
|
|
|
|
QVariant QuickSettingsModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (!index.isValid() || index.row() >= rowCount({}) || role != Qt::UserRole) {
|
|
return {};
|
|
}
|
|
|
|
QObject *obj = m_quickSettings[index.row()];
|
|
return QVariant::fromValue<QObject *>(obj);
|
|
}
|
|
|
|
QuickSetting *QuickSettingsModel::loadQuickSettingComponent(KPluginMetaData metaData)
|
|
{
|
|
// Load KPackage
|
|
const KPackage::Package package = KPackage::PackageLoader::self()->loadPackage("KPackage/GenericQML", QFileInfo(metaData.fileName()).path());
|
|
if (!package.isValid()) {
|
|
return nullptr;
|
|
}
|
|
|
|
// Create translation context
|
|
QQmlEngine *engine = qmlEngine(this);
|
|
KLocalizedContext *i18nContext = new KLocalizedContext(engine);
|
|
i18nContext->setTranslationDomain(QLatin1String("plasma_") + metaData.pluginId());
|
|
engine->rootContext()->setContextObject(i18nContext);
|
|
|
|
// Create component synchronously
|
|
QQmlComponent component(engine, package.fileUrl("mainscript"));
|
|
if (component.isError()) {
|
|
qWarning() << "Unable to load quick setting element:" << metaData.pluginId();
|
|
for (auto error : component.errors()) {
|
|
qWarning() << error;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
// Create object
|
|
QObject *object = component.create(engine->rootContext());
|
|
if (!object) {
|
|
qWarning() << "Unable to create quick setting element:" << metaData.pluginId();
|
|
return nullptr;
|
|
}
|
|
|
|
auto createdSetting = qobject_cast<QuickSetting *>(object);
|
|
if (createdSetting && createdSetting->isAvailable()) {
|
|
// Connect availability signal
|
|
connect(createdSetting, &QuickSetting::availableChanged, this, [this, metaData, createdSetting]() {
|
|
availabilityChanged(metaData, createdSetting);
|
|
});
|
|
return createdSetting;
|
|
} else {
|
|
object->deleteLater();
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
void QuickSettingsModel::loadQuickSettings()
|
|
{
|
|
if (!m_loaded) {
|
|
return;
|
|
}
|
|
|
|
beginResetModel();
|
|
|
|
for (auto *quickSetting : m_quickSettings) {
|
|
quickSetting->deleteLater();
|
|
}
|
|
m_quickSettings.clear();
|
|
m_quickSettingsMetaData.clear();
|
|
|
|
// Loop through enabled quick settings and load them synchronously
|
|
for (const auto &metaData : m_savedQuickSettings->enabledQuickSettingsModel()->list()) {
|
|
if (auto *setting = loadQuickSettingComponent(metaData)) {
|
|
m_quickSettings.append(setting);
|
|
m_quickSettingsMetaData.append(metaData);
|
|
}
|
|
}
|
|
|
|
endResetModel();
|
|
Q_EMIT countChanged();
|
|
}
|
|
|
|
void QuickSettingsModel::loadQuickSetting(KPluginMetaData metaData, bool emitInsertSignal)
|
|
{
|
|
if (!m_loaded) {
|
|
return;
|
|
}
|
|
|
|
if (auto *setting = loadQuickSettingComponent(metaData)) {
|
|
insertQuickSettingToModel(metaData, setting, emitInsertSignal);
|
|
}
|
|
}
|
|
|
|
void QuickSettingsModel::removeQuickSetting(int index)
|
|
{
|
|
if (index >= 0) {
|
|
beginRemoveRows({}, index, index);
|
|
m_quickSettings.removeAt(index);
|
|
m_quickSettingsMetaData.removeAt(index);
|
|
endRemoveRows();
|
|
Q_EMIT countChanged();
|
|
}
|
|
}
|
|
|
|
void QuickSettingsModel::insertQuickSettingToModel(KPluginMetaData metaData, QuickSetting *quickSetting, bool emitInsertSignal)
|
|
{
|
|
// Insert into correct position based on the saved quick settings order
|
|
int insertIndex = 0;
|
|
auto list = m_savedQuickSettings->enabledQuickSettingsModel()->list();
|
|
for (int i = 0; i < list.size(); ++i) {
|
|
if (insertIndex >= m_quickSettingsMetaData.size()) {
|
|
break;
|
|
}
|
|
|
|
if (list[i].pluginId() == m_quickSettingsMetaData[insertIndex].pluginId()) {
|
|
if (metaData.pluginId() == list[i].pluginId()) {
|
|
break;
|
|
}
|
|
++insertIndex;
|
|
}
|
|
}
|
|
|
|
if (emitInsertSignal) {
|
|
beginInsertRows({}, insertIndex, insertIndex);
|
|
}
|
|
|
|
m_quickSettings.insert(insertIndex, quickSetting);
|
|
m_quickSettingsMetaData.insert(insertIndex, metaData);
|
|
|
|
if (emitInsertSignal) {
|
|
endInsertRows();
|
|
}
|
|
Q_EMIT countChanged();
|
|
}
|
|
|
|
void QuickSettingsModel::availabilityChanged(KPluginMetaData metaData, QuickSetting *quickSetting)
|
|
{
|
|
if (quickSetting->isAvailable()) {
|
|
if (!m_quickSettings.contains(quickSetting)) {
|
|
insertQuickSettingToModel(metaData, quickSetting, true);
|
|
}
|
|
} else {
|
|
auto idx = m_quickSettings.indexOf(quickSetting);
|
|
removeQuickSetting(idx);
|
|
}
|
|
}
|