diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -35,6 +35,7 @@ KF5::ItemViews # KWidgetItemDelegate KF5::XmlGui # KAboutApplicationDialog KF5::QuickAddons + KF5::Declarative KF5::Package ) set_target_properties(KF5KCMUtils PROPERTIES diff --git a/src/kcmoduleqml.cpp b/src/kcmoduleqml.cpp --- a/src/kcmoduleqml.cpp +++ b/src/kcmoduleqml.cpp @@ -31,29 +31,39 @@ #include #include +#include #include #include #include #include +#include class KCModuleQmlPrivate { public: - KCModuleQmlPrivate(KQuickAddons::ConfigModule *cm) - : quickWindow(nullptr), + KCModuleQmlPrivate(KQuickAddons::ConfigModule *cm, KCModuleQml *q) + : q(q), + quickWindow(nullptr), configModule(cm) { } + ~KCModuleQmlPrivate() + { + } + + KCModuleQml *q; QQuickWindow *quickWindow; QQuickWidget *quickWidget; QQuickItem *rootPlaceHolder; + QQuickItem *pageRow; KQuickAddons::ConfigModule *configModule; + KDeclarative::QmlObjectSharedEngine *qmlObject; }; KCModuleQml::KCModuleQml(KQuickAddons::ConfigModule *configModule, QWidget* parent, const QVariantList& args) : KCModule(parent, args), - d(new KCModuleQmlPrivate(configModule)) + d(new KCModuleQmlPrivate(configModule, this)) { connect(configModule, &KQuickAddons::ConfigModule::quickHelpChanged, @@ -92,25 +102,17 @@ connect(configModule, &KQuickAddons::ConfigModule::authActionNameChanged, [=] { setAuthAction(d->configModule->authActionName()); }); + setAboutData(d->configModule->aboutData()); setFocusPolicy(Qt::StrongFocus); -} -KCModuleQml::~KCModuleQml() -{ - delete d; -} -void KCModuleQml::showEvent(QShowEvent *event) -{ - if (d->quickWindow || !d->configModule->mainUi()) { - KCModule::showEvent(event); - return; - } + //Build the UI QVBoxLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); - d->quickWidget = new QQuickWidget(d->configModule->engine(), this); + d->qmlObject = new KDeclarative::QmlObjectSharedEngine(this); + d->quickWidget = new QQuickWidget(d->qmlObject->engine(), this); d->quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); d->quickWidget->setFocusPolicy(Qt::StrongFocus); d->quickWidget->installEventFilter(this); @@ -120,24 +122,78 @@ d->quickWindow->setColor(QGuiApplication::palette().window().color()); }); - QQmlComponent *component = new QQmlComponent(d->configModule->engine(), this); + QQmlComponent *component = new QQmlComponent(d->qmlObject->engine(), this); //this has activeFocusOnTab to notice when the navigation wraps //around, so when we need to go outside and inside + //pushPage/popPage are needed as push of StackView can't be directly invoked from c++ + //because its parameters are QQmlV4Function which is not public //the managers of onEnter/ReturnPressed are a workaround of //Qt bug https://bugreports.qt.io/browse/QTBUG-70934 - component->setData(QByteArrayLiteral("import QtQuick 2.3\nItem{activeFocusOnTab:true;Keys.onReturnPressed:{event.accepted=true}Keys.onEnterPressed:{event.accepted=true}}"), QUrl()); + component->setData(QByteArrayLiteral("import QtQuick 2.3\n" + "import org.kde.kirigami 2.4 as Kirigami\n" + "Kirigami.ApplicationItem{" + //purely cosmetic space + "header: Item {height: Kirigami.Units.largeSpacing}" + // allow only one column by default + "pageStack.defaultColumnWidth:width;" + "pageStack.separatorVisible:false;" + "pageStack.globalToolBar.style: pageStack.wideScreen ? Kirigami.ApplicationHeaderStyle.Titles : Kirigami.ApplicationHeaderStyle.Breadcrumb;" + "pageStack.globalToolBar.showNavigationButtons:false;" + "pageStack.globalToolBar.preferredHeight:Kirigami.Units.gridUnit*1.6;" + "pageStack.globalToolBar.separatorVisible:false;" + "activeFocusOnTab:true;" + "Keys.onReturnPressed:{event.accepted=true}" + "Keys.onEnterPressed:{event.accepted=true}" + "}"), QUrl()); + d->rootPlaceHolder = qobject_cast(component->create()); d->quickWidget->setContent(QUrl(), component, d->rootPlaceHolder); - d->configModule->mainUi()->setParentItem(d->quickWidget->rootObject()); - - //set anchors - QQmlExpression expr(d->configModule->engine()->rootContext(), d->configModule->mainUi(), QStringLiteral("parent")); - QQmlProperty prop(d->configModule->mainUi(), QStringLiteral("anchors.fill")); - prop.write(expr.evaluate()); + d->pageRow = d->rootPlaceHolder->property("pageStack").value(); + if (d->pageRow) { + QMetaObject::invokeMethod(d->pageRow, "push", Qt::DirectConnection, Q_ARG(QVariant, QVariant::fromValue(d->configModule->mainUi())), Q_ARG(QVariant, QVariant())); + connect(d->configModule, &KQuickAddons::ConfigModule::pagePushed, this, [this](QQuickItem *page) { + QMetaObject::invokeMethod(d->pageRow, "push", Qt::DirectConnection, Q_ARG(QVariant, QVariant::fromValue(page)), Q_ARG(QVariant, QVariant())); + } + ); + connect(d->configModule, &KQuickAddons::ConfigModule::pageRemoved, this, [this]() { + QMetaObject::invokeMethod(d->pageRow, "pop", Qt::DirectConnection, Q_ARG(QVariant, QVariant())); + } + ); + + auto syncColumnWidth = [this](){ + d->pageRow->setProperty("defaultColumnWidth", d->configModule->columnWidth() > 0 ? d->configModule->columnWidth() : d->rootPlaceHolder->width()); + }; + syncColumnWidth(); + + connect(d->configModule, &KQuickAddons::ConfigModule::columnWidthChanged, + this, syncColumnWidth); + connect(d->rootPlaceHolder, &QQuickItem::widthChanged, + this, syncColumnWidth); + + //HACK: in order to work with old Systemsettings + //search if we are in a KPageWidget, search ofr its page, and if it has + //an header set, disable our own title + //FIXME: eventually remove this hack + QObject *candidate = this; + while (candidate) { + candidate = candidate->parent(); + KPageWidget *page = qobject_cast(candidate); + if (page && !page->currentPage()->header().isEmpty()) { + QObject *globalToolBar = d->pageRow->property("globalToolBar").value(); + //5 is None + globalToolBar->setProperty("style", 5); + } + } + } + layout->addWidget(d->quickWidget); - KCModule::showEvent(event); +} + +KCModuleQml::~KCModuleQml() +{ + delete d; } bool KCModuleQml::eventFilter(QObject* watched, QEvent* event) diff --git a/src/kcmultidialog.cpp b/src/kcmultidialog.cpp --- a/src/kcmultidialog.cpp +++ b/src/kcmultidialog.cpp @@ -25,6 +25,7 @@ #include "kcmultidialog.h" #include "kcmultidialog_p.h" +#include "kcmoduleqml_p.h" #include "kcmoduleproxy.h" #include @@ -448,6 +449,10 @@ // qDebug() << moduleInfo.moduleName(); KPageWidgetItem *item = new KPageWidgetItem(moduleScroll, moduleInfo.moduleName()); + if (qobject_cast(kcm->realModule())) { + item->setHeaderVisible(false); + } + if (kcm->realModule() && kcm->realModule()->useRootOnlyMessage()) { item->setHeader(QStringLiteral("") + moduleInfo.comment() +