File indexing completed on 2024-05-19 03:59:01

0001 /*
0002     SPDX-FileCopyrightText: 2020-2023 Alexander Lohnau <alexander.lohnau@gmx.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-or-later
0005 */
0006 
0007 #include "dialog.h"
0008 
0009 #include <QQmlContext>
0010 #include <QQmlEngine>
0011 #include <QQmlIncubationController>
0012 #include <QQuickItem>
0013 #include <QQuickWidget>
0014 #include <QVBoxLayout>
0015 
0016 #include <KLocalizedContext>
0017 
0018 #include "core/enginebase.h"
0019 #include "knewstuffwidgets_debug.h"
0020 
0021 using namespace KNSWidgets;
0022 
0023 class KNSWidgets::DialogPrivate
0024 {
0025 public:
0026     KNSCore::EngineBase *engine = nullptr;
0027     QQuickItem *item = nullptr;
0028     QList<KNSCore::Entry> changedEntries;
0029     void onEntryEvent(const KNSCore::Entry &entry, KNSCore::Entry::EntryEvent event)
0030     {
0031         if (event == KNSCore::Entry::StatusChangedEvent) {
0032             if (entry.status() == KNSCore::Entry::Installing || entry.status() == KNSCore::Entry::Updating) {
0033                 return; // We do not care about intermediate states
0034             }
0035             // To make sure we have no duplicates and always the latest entry
0036             changedEntries.removeOne(entry);
0037             changedEntries.append(entry);
0038         }
0039     }
0040 };
0041 
0042 class PeriodicIncubationController : public QObject, public QQmlIncubationController
0043 {
0044 public:
0045     explicit PeriodicIncubationController()
0046         : QObject()
0047     {
0048         startTimer(16);
0049     }
0050 
0051 protected:
0052     void timerEvent(QTimerEvent *) override
0053     {
0054         incubateFor(5);
0055     }
0056 };
0057 
0058 Dialog::Dialog(const QString &configFile, QWidget *parent)
0059     : QDialog(parent)
0060     , d(new DialogPrivate())
0061 {
0062     auto engine = new QQmlEngine(this);
0063     auto context = new KLocalizedContext(engine);
0064     engine->setIncubationController(new PeriodicIncubationController());
0065 
0066     // TODO: It would be best to use a Kirigami.ApplicationWindow and use
0067     // a multiple of gridUnit for our default and minimum size
0068     setMinimumSize(600, 400);
0069     resize(600, 400);
0070 
0071     context->setTranslationDomain(QStringLiteral("knewstuff6"));
0072     engine->rootContext()->setContextObject(context);
0073     engine->rootContext()->setContextProperty(QStringLiteral("knsrcfile"), configFile);
0074 
0075     auto page = new QQuickWidget(engine, this);
0076     page->setSource(QUrl(QStringLiteral("qrc:/knswidgets/page.qml")));
0077     page->setResizeMode(QQuickWidget::SizeRootObjectToView);
0078 
0079     auto layout = new QVBoxLayout(this);
0080     layout->addWidget(page);
0081     layout->setContentsMargins(0, 0, 0, 0);
0082 
0083     if (QQuickItem *root = page->rootObject()) {
0084         d->item = root;
0085         d->engine = qvariant_cast<KNSCore::EngineBase *>(root->property("engine"));
0086         Q_ASSERT(d->engine);
0087 
0088         // clang-format off
0089         // Old-style connect, because we don't want the QML engine to be exported
0090         connect(d->engine,
0091                 SIGNAL(entryEvent(KNSCore::Entry,KNSCore::Entry::EntryEvent)),
0092                 this,
0093                 SLOT(onEntryEvent(KNSCore::Entry,KNSCore::Entry::EntryEvent)));
0094         // clang-format on
0095     } else {
0096         qWarning(KNEWSTUFFWIDGETS) << "Error creating QtQuickDialogWrapper component:" << page->errors();
0097     }
0098 }
0099 
0100 Dialog::~Dialog()
0101 {
0102     delete d->item;
0103 }
0104 
0105 KNSCore::EngineBase *Dialog::engine()
0106 {
0107     return d->engine;
0108 }
0109 
0110 QList<KNSCore::Entry> Dialog::changedEntries() const
0111 {
0112     return d->changedEntries;
0113 }
0114 
0115 void Dialog::open()
0116 {
0117     QDialog::open();
0118     d->changedEntries.clear();
0119 }
0120 
0121 #include "moc_dialog.cpp"