1 | /* |
2 | SPDX-FileCopyrightText: 2020-2023 Alexander Lohnau <alexander.lohnau@gmx.de> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.1-or-later |
5 | */ |
6 | |
7 | #include "dialog.h" |
8 | |
9 | #include <QQmlContext> |
10 | #include <QQmlEngine> |
11 | #include <QQmlIncubationController> |
12 | #include <QQuickItem> |
13 | #include <QQuickWidget> |
14 | #include <QVBoxLayout> |
15 | |
16 | #include <KLocalizedContext> |
17 | |
18 | #include "core/enginebase.h" |
19 | #include "knewstuffwidgets_debug.h" |
20 | |
21 | using namespace KNSWidgets; |
22 | |
23 | class KNSWidgets::DialogPrivate |
24 | { |
25 | public: |
26 | KNSCore::EngineBase *engine = nullptr; |
27 | QQuickItem *item = nullptr; |
28 | QList<KNSCore::Entry> changedEntries; |
29 | void onEntryEvent(const KNSCore::Entry &entry, KNSCore::Entry::EntryEvent event) |
30 | { |
31 | if (event == KNSCore::Entry::StatusChangedEvent) { |
32 | if (entry.status() == KNSCore::Entry::Installing || entry.status() == KNSCore::Entry::Updating) { |
33 | return; // We do not care about intermediate states |
34 | } |
35 | // To make sure we have no duplicates and always the latest entry |
36 | changedEntries.removeOne(t: entry); |
37 | changedEntries.append(t: entry); |
38 | } |
39 | } |
40 | }; |
41 | |
42 | class PeriodicIncubationController : public QObject, public QQmlIncubationController |
43 | { |
44 | public: |
45 | explicit PeriodicIncubationController() |
46 | : QObject() |
47 | { |
48 | startTimer(interval: 16); |
49 | } |
50 | |
51 | protected: |
52 | void timerEvent(QTimerEvent *) override |
53 | { |
54 | incubateFor(msecs: 5); |
55 | } |
56 | }; |
57 | |
58 | Dialog::Dialog(const QString &configFile, QWidget *parent) |
59 | : QDialog(parent) |
60 | , d(new DialogPrivate()) |
61 | { |
62 | auto engine = new QQmlEngine(this); |
63 | auto context = new KLocalizedContext(engine); |
64 | engine->setIncubationController(new PeriodicIncubationController()); |
65 | |
66 | setMinimumSize(minw: 600, minh: 400); |
67 | // Keep in sync with the sizes in Dialog.qml and DialogContent.qml |
68 | // (reminder that a default gridUnit is 18px). |
69 | // TODO: It would be best to use a Kirigami.ApplicationWindow and use |
70 | // a multiple of gridUnit directly! |
71 | resize(w: 792, h: 540); |
72 | |
73 | context->setTranslationDomain(QStringLiteral("knewstuff6" )); |
74 | engine->rootContext()->setContextObject(context); |
75 | engine->rootContext()->setContextProperty(QStringLiteral("knsrcfile" ), configFile); |
76 | |
77 | auto page = new QQuickWidget(engine, this); |
78 | page->setSource(QUrl(QStringLiteral("qrc:/knswidgets/page.qml" ))); |
79 | page->setResizeMode(QQuickWidget::SizeRootObjectToView); |
80 | |
81 | auto layout = new QVBoxLayout(this); |
82 | layout->addWidget(page); |
83 | layout->setContentsMargins(left: 0, top: 0, right: 0, bottom: 0); |
84 | |
85 | if (QQuickItem *root = page->rootObject()) { |
86 | d->item = root; |
87 | d->engine = qvariant_cast<KNSCore::EngineBase *>(v: root->property(name: "engine" )); |
88 | Q_ASSERT(d->engine); |
89 | |
90 | // clang-format off |
91 | // Old-style connect, because we don't want the QML engine to be exported |
92 | connect(sender: d->engine, |
93 | SIGNAL(entryEvent(KNSCore::Entry,KNSCore::Entry::EntryEvent)), |
94 | receiver: this, |
95 | SLOT(onEntryEvent(KNSCore::Entry,KNSCore::Entry::EntryEvent))); |
96 | // clang-format on |
97 | } else { |
98 | qWarning(catFunc: KNEWSTUFFWIDGETS) << "Error creating QtQuickDialogWrapper component:" << page->errors(); |
99 | } |
100 | } |
101 | |
102 | Dialog::~Dialog() |
103 | { |
104 | delete d->item; |
105 | } |
106 | |
107 | KNSCore::EngineBase *Dialog::engine() |
108 | { |
109 | return d->engine; |
110 | } |
111 | |
112 | QList<KNSCore::Entry> Dialog::changedEntries() const |
113 | { |
114 | return d->changedEntries; |
115 | } |
116 | |
117 | void Dialog::open() |
118 | { |
119 | QDialog::open(); |
120 | d->changedEntries.clear(); |
121 | } |
122 | |
123 | #include "moc_dialog.cpp" |
124 | |