File indexing completed on 2024-04-28 16:54:57

0001 /*
0002     SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "currentcontainmentactionsmodel.h"
0008 
0009 #include <QMouseEvent>
0010 
0011 #include <QDebug>
0012 #include <QDialog>
0013 #include <QDialogButtonBox>
0014 #include <QQuickItem>
0015 #include <QQuickWindow>
0016 #include <QVBoxLayout>
0017 #include <QWindow>
0018 
0019 #include <KAboutPluginDialog>
0020 #include <klocalizedstring.h>
0021 
0022 #include <Plasma/Containment>
0023 #include <Plasma/ContainmentActions>
0024 #include <Plasma/Corona>
0025 #include <Plasma/PluginLoader>
0026 
0027 CurrentContainmentActionsModel::CurrentContainmentActionsModel(Plasma::Containment *containment, QObject *parent)
0028     : QStandardItemModel(parent)
0029     , m_containment(containment)
0030     , m_tempConfigParent(QString(), KConfig::SimpleConfig)
0031 {
0032     m_baseCfg = KConfigGroup(m_containment->corona()->config(), "ActionPlugins");
0033     m_baseCfg = KConfigGroup(&m_baseCfg, QString::number(m_containment->containmentType()));
0034 
0035     QHash<QString, Plasma::ContainmentActions *> actions = containment->containmentActions();
0036 
0037     QHashIterator<QString, Plasma::ContainmentActions *> i(actions);
0038     while (i.hasNext()) {
0039         i.next();
0040 
0041         QStandardItem *item = new QStandardItem();
0042         item->setData(i.key(), ActionRole);
0043         item->setData(i.value()->metadata().pluginId(), PluginNameRole);
0044 
0045         m_plugins[i.key()] = Plasma::PluginLoader::self()->loadContainmentActions(m_containment, i.value()->metadata().pluginId());
0046         m_plugins[i.key()]->setContainment(m_containment);
0047         KConfigGroup cfg(&m_baseCfg, i.key());
0048         m_plugins[i.key()]->restore(cfg);
0049         item->setData(m_plugins[i.key()]->metadata().rawData().value(QStringLiteral("X-Plasma-HasConfigurationInterface")).toBool(),
0050                       HasConfigurationInterfaceRole);
0051 
0052         appendRow(item);
0053     }
0054 }
0055 
0056 CurrentContainmentActionsModel::~CurrentContainmentActionsModel()
0057 {
0058 }
0059 
0060 QHash<int, QByteArray> CurrentContainmentActionsModel::roleNames() const
0061 {
0062     return {
0063         {ActionRole, "action"},
0064         {PluginNameRole, "pluginName"},
0065         {HasConfigurationInterfaceRole, "hasConfigurationInterface"},
0066     };
0067 }
0068 
0069 QString CurrentContainmentActionsModel::mouseEventString(int mouseButton, int modifiers)
0070 {
0071     QMouseEvent *mouse =
0072         new QMouseEvent(QEvent::MouseButtonRelease, QPoint(), (Qt::MouseButton)mouseButton, (Qt::MouseButton)mouseButton, (Qt::KeyboardModifiers)modifiers);
0073 
0074     const QString string = Plasma::ContainmentActions::eventToString(mouse);
0075 
0076     delete mouse;
0077 
0078     return string;
0079 }
0080 
0081 QString CurrentContainmentActionsModel::wheelEventString(QObject *quickWheelEvent)
0082 {
0083     const QPoint angleDelta = quickWheelEvent->property("angleDelta").toPoint();
0084     const auto buttons = Qt::MouseButtons(quickWheelEvent->property("buttons").toInt());
0085     const auto modifiers = Qt::KeyboardModifiers(quickWheelEvent->property("modifiers").toInt());
0086 
0087     QWheelEvent wheel(QPointF(), QPointF(), QPoint(), angleDelta, buttons, modifiers, Qt::NoScrollPhase, false);
0088 
0089     return Plasma::ContainmentActions::eventToString(&wheel);
0090 }
0091 
0092 bool CurrentContainmentActionsModel::isTriggerUsed(const QString &trigger)
0093 {
0094     return m_plugins.contains(trigger);
0095 }
0096 
0097 bool CurrentContainmentActionsModel::append(const QString &action, const QString &plugin)
0098 {
0099     if (m_plugins.contains(action)) {
0100         return false;
0101     }
0102 
0103     QStandardItem *item = new QStandardItem();
0104     item->setData(action, ActionRole);
0105     item->setData(plugin, PluginNameRole);
0106 
0107     Plasma::ContainmentActions *actions = Plasma::PluginLoader::self()->loadContainmentActions(m_containment, plugin);
0108 
0109     if (!actions) {
0110         return false;
0111     }
0112 
0113     m_plugins[action] = actions;
0114     m_plugins[action]->setContainment(m_containment);
0115     // empty config: the new one will ne in default state
0116     KConfigGroup tempConfig(&m_tempConfigParent, "test");
0117     m_plugins[action]->restore(tempConfig);
0118     item->setData(m_plugins[action]->metadata().rawData().value(QStringLiteral("X-Plasma-HasConfigurationInterface")).toBool(), HasConfigurationInterfaceRole);
0119     m_removedTriggers.removeAll(action);
0120 
0121     appendRow(item);
0122 
0123     Q_EMIT configurationChanged();
0124     return true;
0125 }
0126 
0127 void CurrentContainmentActionsModel::update(int row, const QString &action, const QString &plugin)
0128 {
0129     const QString oldPlugin = itemData(index(row, 0)).value(PluginNameRole).toString();
0130     const QString oldTrigger = itemData(index(row, 0)).value(ActionRole).toString();
0131 
0132     if (oldTrigger == action && oldPlugin == plugin) {
0133         return;
0134     }
0135 
0136     QModelIndex idx = index(row, 0);
0137 
0138     if (idx.isValid()) {
0139         setData(idx, action, ActionRole);
0140         setData(idx, plugin, PluginNameRole);
0141 
0142         delete m_plugins[oldTrigger];
0143         m_plugins.remove(oldTrigger);
0144 
0145         if (oldPlugin != plugin) {
0146             m_removedTriggers << oldTrigger;
0147         }
0148 
0149         if (!m_plugins.contains(action) || oldPlugin != plugin) {
0150             delete m_plugins[action];
0151             m_plugins[action] = Plasma::PluginLoader::self()->loadContainmentActions(m_containment, plugin);
0152             m_plugins[action]->setContainment(m_containment);
0153             // empty config: the new one will ne in default state
0154             KConfigGroup tempConfig(&m_tempConfigParent, "test");
0155             m_plugins[action]->restore(tempConfig);
0156             setData(idx,
0157                     m_plugins[action]->metadata().rawData().value(QStringLiteral("X-Plasma-HasConfigurationInterface")).toBool(),
0158                     HasConfigurationInterfaceRole);
0159         }
0160 
0161         Q_EMIT configurationChanged();
0162     }
0163 }
0164 
0165 void CurrentContainmentActionsModel::remove(int row)
0166 {
0167     const QString action = itemData(index(row, 0)).value(ActionRole).toString();
0168     removeRows(row, 1);
0169 
0170     if (m_plugins.contains(action)) {
0171         delete m_plugins[action];
0172         m_plugins.remove(action);
0173         m_removedTriggers << action;
0174         Q_EMIT configurationChanged();
0175     }
0176 }
0177 
0178 void CurrentContainmentActionsModel::showConfiguration(int row, QQuickItem *ctx)
0179 {
0180     const QString action = itemData(index(row, 0)).value(ActionRole).toString();
0181 
0182     if (!m_plugins.contains(action)) {
0183         return;
0184     }
0185 
0186     QDialog *configDlg = new QDialog();
0187     configDlg->setAttribute(Qt::WA_DeleteOnClose);
0188     QLayout *lay = new QVBoxLayout(configDlg);
0189     configDlg->setLayout(lay);
0190     if (ctx && ctx->window()) {
0191         configDlg->setWindowModality(Qt::WindowModal);
0192         configDlg->winId(); // so it creates the windowHandle();
0193         configDlg->windowHandle()->setTransientParent(ctx->window());
0194     }
0195 
0196     Plasma::ContainmentActions *pluginInstance = m_plugins[action];
0197     // put the config in the dialog
0198     QWidget *w = pluginInstance->createConfigurationInterface(configDlg);
0199     QString title;
0200     if (w) {
0201         lay->addWidget(w);
0202         title = w->windowTitle();
0203     }
0204 
0205     configDlg->setWindowTitle(title.isEmpty() ? i18n("Configure Mouse Actions Plugin") : title);
0206     // put buttons below
0207     QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, configDlg);
0208     lay->addWidget(buttons);
0209 
0210     connect(buttons, &QDialogButtonBox::accepted, configDlg, &QDialog::accept);
0211     connect(buttons, &QDialogButtonBox::rejected, configDlg, &QDialog::reject);
0212 
0213     QObject::connect(configDlg, &QDialog::accepted, pluginInstance, [pluginInstance]() {
0214         pluginInstance->configurationAccepted();
0215     });
0216 
0217     connect(configDlg, &QDialog::accepted, this, &CurrentContainmentActionsModel::configurationChanged);
0218 
0219     connect(pluginInstance, &QObject::destroyed, configDlg, &QDialog::reject);
0220 
0221     configDlg->show();
0222 }
0223 
0224 QVariant CurrentContainmentActionsModel::aboutMetaData(int row) const
0225 {
0226     const QString action = itemData(index(row, 0)).value(ActionRole).toString();
0227 
0228     if (!m_plugins.contains(action)) {
0229         return QVariant();
0230     }
0231 
0232     return QVariant::fromValue(m_plugins[action]->metadata());
0233 }
0234 
0235 void CurrentContainmentActionsModel::save()
0236 {
0237     foreach (const QString &removedTrigger, m_removedTriggers) {
0238         m_containment->setContainmentActions(removedTrigger, QString());
0239     }
0240     m_removedTriggers.clear();
0241 
0242     QHashIterator<QString, Plasma::ContainmentActions *> i(m_plugins);
0243     while (i.hasNext()) {
0244         i.next();
0245 
0246         KConfigGroup cfg(&m_baseCfg, i.key());
0247         i.value()->save(cfg);
0248 
0249         m_containment->setContainmentActions(i.key(), i.value()->metadata().pluginId());
0250     }
0251 }
0252 
0253 #include "moc_currentcontainmentactionsmodel.cpp"