1/*
2 SPDX-FileCopyrightText: 2015 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
3
4 SPDX-License-Identifier: LGPL-2.1-or-later
5*/
6
7#include "menu.h"
8#include <KLocalizedQmlContext>
9#include <QDebug>
10#include <QPointer>
11#include <QQmlApplicationEngine>
12#include <QQmlContext>
13#include <purpose/alternativesmodel.h>
14#include <purpose/configuration.h>
15#include <qqml.h>
16
17using namespace Purpose;
18
19class Purpose::MenuPrivate : public QObject
20{
21 Q_OBJECT
22public:
23 MenuPrivate(Menu *qq)
24 : QObject(qq)
25 , m_model(new AlternativesModel(qq))
26 , q(qq)
27 {
28 }
29
30 ~MenuPrivate() override
31 {
32 if (m_engine) {
33 m_engine->deleteLater();
34 }
35 }
36
37 void trigger(int row)
38 {
39 if (!m_engine) {
40 m_engine = new QQmlApplicationEngine;
41 m_engine->rootContext()->setContextObject(new KLocalizedQmlContext(this));
42 m_engine->load(url: QUrl(QStringLiteral("qrc:/org.kde.purpose/JobDialog.qml")));
43 }
44
45 Q_ASSERT(!m_engine->rootObjects().isEmpty());
46 QObject *o = m_engine->rootObjects().at(i: 0);
47
48 if (!o) {
49 qWarning() << Q_FUNC_INFO << "object is NULL at m_engine" << m_engine << "rootObjects=" << m_engine->rootObjects();
50 return;
51 }
52
53 o->setProperty(name: "model", value: QVariant::fromValue(value: m_model.data()));
54 o->setProperty(name: "index", value: row);
55 o->setProperty(name: "visible", value: true);
56 o->setProperty(name: "menu", value: QVariant::fromValue<QObject *>(value: q));
57 o->setParent(q);
58
59 QMetaObject::invokeMethod(obj: o, member: "start");
60 }
61
62public:
63 QQmlApplicationEngine *m_engine = nullptr;
64 QPointer<AlternativesModel> m_model;
65 Purpose::Menu *q;
66};
67
68Menu::Menu(QWidget *parent)
69 : QMenu(parent)
70 , d_ptr(new MenuPrivate(this))
71{
72 qmlRegisterUncreatableType<Menu>(uri: "org.kde.purpose.private.widgets", versionMajor: 1, versionMinor: 0, qmlName: "Menu", reason: QString());
73
74 connect(sender: d_ptr->m_model.data(), signal: &AlternativesModel::inputDataChanged, context: this, slot: &Menu::reload);
75 connect(sender: this, signal: &QMenu::triggered, context: this, slot: [this](QAction *action) {
76 Q_D(Menu);
77 const int row = action->property(name: "row").toInt();
78 Q_EMIT aboutToShare();
79 d->trigger(row);
80 });
81}
82
83void Menu::reload()
84{
85 Q_D(Menu);
86 clear();
87
88 const auto getSortedModelIndices = [d] {
89 QList<QModelIndex> indices;
90 for (int i = 0, c = d->m_model->rowCount(); i != c; ++i) {
91 indices << d->m_model->index(row: i);
92 }
93 std::sort(first: indices.begin(), last: indices.end(), comp: [](const QModelIndex &left, const QModelIndex &right) {
94 return left.data(arole: AlternativesModel::ActionDisplayRole).toString() < right.data(arole: AlternativesModel::ActionDisplayRole).toString();
95 });
96
97 return indices;
98 };
99
100 const QList<QModelIndex> sortedIndices = getSortedModelIndices();
101
102 for (const QModelIndex &idx : sortedIndices) {
103 QAction *a = addAction(text: idx.data(arole: AlternativesModel::ActionDisplayRole).toString());
104 a->setToolTip(idx.data(arole: Qt::ToolTipRole).toString());
105 a->setIcon(idx.data(arole: Qt::DecorationRole).value<QIcon>());
106 a->setProperty(name: "pluginId", value: idx.data(arole: AlternativesModel::PluginIdRole));
107 a->setProperty(name: "row", value: idx.row());
108 }
109
110 setEnabled(!isEmpty());
111}
112
113AlternativesModel *Menu::model() const
114{
115 Q_D(const Menu);
116 return d->m_model.data();
117}
118
119#include "menu.moc"
120#include "moc_menu.cpp"
121

source code of purpose/src/widgets/menu.cpp