diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 2aab0dbc8a4..c057cb7082e 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -98,18 +98,19 @@ set( final_src ${3rdparty_SRC} ) +add_library(owncloudGui SHARED ${final_src}) +set_target_properties(owncloudGui PROPERTIES AUTOUIC ON AUTORCC ON) + add_subdirectory(newwizard) add_subdirectory(folderwizard) add_subdirectory(loginrequireddialog) -add_library(owncloudGui SHARED ${final_src}) -set_target_properties(owncloudGui PROPERTIES AUTOUIC ON AUTORCC ON) # for the generated qml module -target_include_directories(owncloudGui PRIVATE models spaces) +target_include_directories(owncloudGui PRIVATE models spaces newwizard) target_link_libraries(owncloudGui PUBLIC Qt::Widgets Qt::Network Qt::Xml Qt::Quick Qt::QuickWidgets Qt::QuickControls2 - newwizard folderwizard loginrequireddialog + folderwizard loginrequireddialog libsync Qt6Keychain::Qt6Keychain ) @@ -127,6 +128,8 @@ ecm_add_qml_module(owncloudGui spaces/qml/SpaceDelegate.qml spaces/qml/SpacesView.qml + + newwizard/qml/Navigation.qml ) generate_export_header(owncloudGui diff --git a/src/gui/accountmodalwidget.cpp b/src/gui/accountmodalwidget.cpp index afca47c3ef8..63f86f1e5a9 100644 --- a/src/gui/accountmodalwidget.cpp +++ b/src/gui/accountmodalwidget.cpp @@ -15,6 +15,8 @@ #include "accountmodalwidget.h" #include "ui_accountmodalwidget.h" +#include "gui/qmlutils.h" + namespace OCC { AccountModalWidget::AccountModalWidget(const QString &title, QWidget *widget, QWidget *parent) @@ -29,6 +31,18 @@ AccountModalWidget::AccountModalWidget(const QString &title, QWidget *widget, QW connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &AccountModalWidget::reject); } + +AccountModalWidget::AccountModalWidget(const QString &title, const QUrl &qmlSource, QObject *qmlContext, QWidget *parent) + : AccountModalWidget( + title, + [&] { + auto *out = new QmlUtils::OCQuickWidget; + out->setOCContext(qmlSource, parent, qmlContext, QJSEngine::JavaScriptOwnership); + return out; + }(), + parent) +{ +} void AccountModalWidget::setStandardButtons(QDialogButtonBox::StandardButtons buttons) { ui->buttonBox->setStandardButtons(buttons); diff --git a/src/gui/accountmodalwidget.h b/src/gui/accountmodalwidget.h index 0e69e29201d..ebd2fe59083 100644 --- a/src/gui/accountmodalwidget.h +++ b/src/gui/accountmodalwidget.h @@ -14,6 +14,8 @@ #pragma once +#include "gui/qmlutils.h" + #include namespace OCC { @@ -27,6 +29,7 @@ class AccountModalWidget : public QWidget Q_OBJECT public: AccountModalWidget(const QString &title, QWidget *widget, QWidget *parent); + AccountModalWidget(const QString &title, const QUrl &qmlSource, QObject *qmlContext, QWidget *parent); enum class Result { Rejected, Accepted }; Q_ENUM(Result) diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp index 58d60549963..2c6b19c6f5c 100644 --- a/src/gui/accountsettings.cpp +++ b/src/gui/accountsettings.cpp @@ -74,7 +74,7 @@ AccountSettings::AccountSettings(const AccountStatePtr &accountState, QWidget *p _sortModel = weightedModel; ui->quickWidget->engine()->addImageProvider(QStringLiteral("space"), new Spaces::SpaceImageProvider(_accountState->account())); - QmlUtils::initQuickWidget(ui->quickWidget, QUrl(QStringLiteral("qrc:/qt/qml/org/ownCloud/gui/qml/FolderDelegate.qml")), this); + ui->quickWidget->setOCContext(QUrl(QStringLiteral("qrc:/qt/qml/org/ownCloud/gui/qml/FolderDelegate.qml")), this); connect(FolderMan::instance(), &FolderMan::folderListChanged, _model, &FolderStatusModel::resetFolders); if (accountsState()->supportsSpaces()) { diff --git a/src/gui/newwizard/CMakeLists.txt b/src/gui/newwizard/CMakeLists.txt index 910a835e362..fbd857a09d9 100644 --- a/src/gui/newwizard/CMakeLists.txt +++ b/src/gui/newwizard/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(newwizard STATIC +target_sources(owncloudGui PRIVATE enums.cpp pages/abstractsetupwizardpage.h @@ -57,7 +57,3 @@ add_library(newwizard STATIC setupwizardcontext.cpp ) -target_link_libraries(newwizard PUBLIC Qt::Widgets libsync owncloudResources) -set_target_properties(newwizard PROPERTIES AUTOUIC ON AUTORCC ON) -target_include_directories(newwizard PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") -apply_common_target_settings(newwizard) diff --git a/src/gui/newwizard/enums.h b/src/gui/newwizard/enums.h index 9f5604bd170..ee1758767ec 100644 --- a/src/gui/newwizard/enums.h +++ b/src/gui/newwizard/enums.h @@ -17,9 +17,11 @@ #include "common/utility.h" #include +#include namespace OCC::Wizard { Q_NAMESPACE +QML_ELEMENT enum class SetupWizardState { ServerUrlState, diff --git a/src/gui/newwizard/navigation.cpp b/src/gui/newwizard/navigation.cpp index 882b9ae38dc..7bf8ff0a304 100644 --- a/src/gui/newwizard/navigation.cpp +++ b/src/gui/newwizard/navigation.cpp @@ -6,77 +6,40 @@ namespace OCC::Wizard { Navigation::Navigation(QWidget *parent) - : QWidget(parent) + : OCQuickWidget(parent) { - // this class manages its own layout - setLayout(new QHBoxLayout(this)); + setOCContext(QUrl(QStringLiteral("qrc:/qt/qml/org/ownCloud/gui/newwizard/qml/Navigation.qml")), this->parentWidget(), this, QJSEngine::CppOwnership); } -void Navigation::setEntries(const QList &newEntries) +void Navigation::setStates(const QList &newEntries) { - // TODO: more advanced implementation (reuse existing buttons within layout) - // current active page is also lost that way - removeAllItems(); - - for (const auto state : newEntries) { - const QString text = Utility::enumToDisplayName(state); - - auto newButton = new QRadioButton(text, this); - - _entries.insert(state, newButton); - layout()->addWidget(newButton); - - connect(newButton, &QRadioButton::clicked, this, [this, state]() { - // clicks to the current state button should be ignored - // this used to be handled by disabling the button - if (state != _activeState) { - Q_EMIT paginationEntryClicked(state); - } - }); + if (_states != newEntries) { + _states = newEntries; + Q_EMIT statesChanged(); } - - enableOrDisableButtons(); } -// needed to clean up widgets we added to the layout -Navigation::~Navigation() noexcept +QList Navigation::states() const { - removeAllItems(); + return _states; } -void Navigation::removeAllItems() +void Navigation::setActiveState(SetupWizardState newState) { - qDeleteAll(_entries); + if (_activeState != newState) { + _activeState = newState; + Q_EMIT activeStatesChanged(); + } } -void Navigation::enableOrDisableButtons() +SetupWizardState Navigation::activeState() const { - for (const auto state : _entries.keys()) { - auto button = _entries.value(state); - - const auto enabled = [&state, this]() { - if (_enabled) { - return state <= _activeState; - } - - return false; - }(); - - // we just ignore clicks to the current page - button->setEnabled(enabled); - } + return _activeState; } -void Navigation::setActiveState(SetupWizardState newState) +QString Navigation::stateDisplayName(SetupWizardState state) const { - _activeState = newState; - - for (const auto key : _entries.keys()) { - auto button = _entries.value(key); - button->setChecked(key == _activeState); - } - - enableOrDisableButtons(); + return Utility::enumToDisplayName(state); } } diff --git a/src/gui/newwizard/navigation.h b/src/gui/newwizard/navigation.h index 35d7d858e98..be4796540e4 100644 --- a/src/gui/newwizard/navigation.h +++ b/src/gui/newwizard/navigation.h @@ -16,6 +16,8 @@ #include "enums.h" +#include "gui/qmlutils.h" + #include #include #include @@ -27,42 +29,46 @@ namespace OCC::Wizard { /** * Provides a radio button based quick navigation on the wizard's bottom side. */ -class Navigation : public QWidget +class Navigation : public QmlUtils::OCQuickWidget { Q_OBJECT + Q_PROPERTY(QList states READ states NOTIFY statesChanged) + Q_PROPERTY(SetupWizardState activeState READ activeState WRITE setActiveState NOTIFY activeStatesChanged) + QML_ELEMENT + QML_UNCREATABLE("C++") public: explicit Navigation(QWidget *parent = nullptr); - ~Navigation() noexcept override; /** * Set or replace entries in the navigation. * This method creates the corresponding buttons. * @param newEntries ordered list of wizard states to be rendered in the navigation */ - void setEntries(const QList &newEntries); + void setStates(const QList &newEntries); + QList states() const; -Q_SIGNALS: /** - * Emitted when a pagination entry is clicked. - * This event is only emitted for previous states. - * @param clickedState state the user wants to switch to + * Change to another state. Applies changes to hosted UI elements (e.g., disables buttons, ) */ - void paginationEntryClicked(SetupWizardState clickedState); + void setActiveState(SetupWizardState activeState); + SetupWizardState activeState() const; + + Q_INVOKABLE QString stateDisplayName(SetupWizardState state) const; -public Q_SLOTS: +Q_SIGNALS: /** - * Change to another state. Applies changes to hosted UI elements (e.g., disables buttons, ) - * @param newState state to activate + * Emitted when a state is clicked. + * This event is only emitted for previous states. + * @param clickedState state the user wants to switch to */ - void setActiveState(SetupWizardState newState); + void stateClicked(SetupWizardState clickedState); + void statesChanged(); + void activeStatesChanged(); private: - void removeAllItems(); - void enableOrDisableButtons(); - - QMap _entries; + QList _states; SetupWizardState _activeState = SetupWizardState::FirstState; bool _enabled = true; }; diff --git a/src/gui/newwizard/qml/Navigation.qml b/src/gui/newwizard/qml/Navigation.qml new file mode 100644 index 00000000000..0e6e33b2312 --- /dev/null +++ b/src/gui/newwizard/qml/Navigation.qml @@ -0,0 +1,69 @@ +/* + * Copyright (C) by Hannah von Reth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import org.ownCloud.gui 1.0 +import org.ownCloud.libsync 1.0 +import org.ownCloud.resources 1.0 + +Pane { + id: navigationBar + readonly property Navigation navigation: ocContext + + // Connections { + // target: ocParentWidget + + // function onFocusFirst() { + // if (accountButtons.count === 0) { + // addAccountButton.forceActiveFocus(Qt.TabFocusReason); + // } else { + // accountButtons.itemAt(0).forceActiveFocus(Qt.TabFocusReason); + // } + // } + + // function onFocusLast() { + // quitButton.forceActiveFocus(Qt.TabFocusReason); + // } + // } + + RowLayout { + anchors.fill: parent + + Item { + Layout.fillWidth: true + } + + Repeater { + id: statesRepeater + + model: navigation.states + + delegate: RadioButton { + property int wizardState: modelData + Accessible.role: Accessible.PageTab + checked: navigation.currentState === wizardState + text: navigation.stateDisplayName(wizardState) + onClicked: { + // settingsDialog.currentAccount = accountState.account; + } + } + } + } + + Item { + Layout.fillWidth: true + } +} diff --git a/src/gui/newwizard/setupwizardwidget.cpp b/src/gui/newwizard/setupwizardwidget.cpp index 3cd138fdede..c92a30b135d 100644 --- a/src/gui/newwizard/setupwizardwidget.cpp +++ b/src/gui/newwizard/setupwizardwidget.cpp @@ -64,7 +64,7 @@ SetupWizardWidget::SetupWizardWidget(SettingsDialog *parent) Q_EMIT backButtonClicked(); }); - connect(_ui->navigation, &Navigation::paginationEntryClicked, this, [this](SetupWizardState clickedState) { + connect(_ui->navigation, &Navigation::stateClicked, this, [this](SetupWizardState clickedState) { slotStartTransition(); Q_EMIT navigationEntryClicked(clickedState); }); @@ -178,7 +178,7 @@ void SetupWizardWidget::showErrorMessage(const QString &errorMessage) void SetupWizardWidget::setNavigationEntries(const QList &entries) { - _ui->navigation->setEntries(entries); + _ui->navigation->setStates(entries); } void SetupWizardWidget::slotUpdateNextButton() diff --git a/src/gui/newwizard/setupwizardwidget.h b/src/gui/newwizard/setupwizardwidget.h index 83844e94c14..1081962b0d8 100644 --- a/src/gui/newwizard/setupwizardwidget.h +++ b/src/gui/newwizard/setupwizardwidget.h @@ -14,10 +14,11 @@ #pragma once +#include "gui/newwizard/navigation.h" +#include "gui/newwizard/pages/abstractsetupwizardpage.h" +#include "gui/newwizard/setupwizardaccountbuilder.h" +#include "gui/qmlutils.h" #include "gui/settingsdialog.h" -#include "navigation.h" -#include "pages/abstractsetupwizardpage.h" -#include "setupwizardaccountbuilder.h" namespace Ui { class SetupWizardWidget; @@ -31,7 +32,7 @@ namespace OCC::Wizard { class SetupWizardWidget : public QWidget { Q_OBJECT - + OC_DECLARE_WIDGET_FOCUS public: explicit SetupWizardWidget(SettingsDialog *parent); ~SetupWizardWidget() noexcept override; diff --git a/src/gui/newwizard/setupwizardwidget.ui b/src/gui/newwizard/setupwizardwidget.ui index 0295d74a2b9..87e5d18462e 100644 --- a/src/gui/newwizard/setupwizardwidget.ui +++ b/src/gui/newwizard/setupwizardwidget.ui @@ -81,7 +81,7 @@ - :/client/resources/light/warning.svg + :/client/resources/light/warning.svg true @@ -91,7 +91,7 @@ - Qt::RichText + Qt::TextFormat::RichText @@ -118,33 +118,14 @@ - - - Qt::Horizontal + + + + 0 + 0 + - - - 40 - 20 - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - + @@ -180,8 +161,6 @@ 1 - - - + diff --git a/src/gui/qml/AccountBar.qml b/src/gui/qml/AccountBar.qml index 66d0c7a3654..4fc84d59249 100644 --- a/src/gui/qml/AccountBar.qml +++ b/src/gui/qml/AccountBar.qml @@ -25,7 +25,7 @@ Pane { Accessible.name: qsTr("Navigation bar") Connections { - target: settingsDialog + target: ocParentWidget function onFocusFirst() { if (accountButtons.count === 0) { @@ -82,7 +82,7 @@ Pane { Keys.onBacktabPressed: event => { if (index === 0) { // We're the first button, handle the back-tab - settingsDialog.focusPrevious(); + ocParentWidget.focusPrevious(); } else { event.accepted = false; } @@ -104,7 +104,7 @@ Pane { Keys.onBacktabPressed: event => { // If there are no account buttons, we're the first button, so handle the back-tab if (accountButtons.count === 0) { - settingsDialog.focusPrevious(); + ocParentWidget.focusPrevious(); } else { event.accepted = false; } @@ -171,7 +171,7 @@ Pane { text: qsTr("Quit") Keys.onTabPressed: { - settingsDialog.focusNext(); + ocParentWidget.focusNext(); } onClicked: { Qt.quit(); diff --git a/src/gui/qml/FolderDelegate.qml b/src/gui/qml/FolderDelegate.qml index a861f823aa3..65b4b55b38c 100644 --- a/src/gui/qml/FolderDelegate.qml +++ b/src/gui/qml/FolderDelegate.qml @@ -29,7 +29,7 @@ Pane { Accessible.name: qsTr("Folder Sync") Connections { - target: accountSettings + target: ocParentWidget function onFocusFirst() { listView.currentIndex = 0; @@ -108,7 +108,7 @@ Pane { } Keys.onBacktabPressed: { - accountSettings.focusPrevious(); + ocParentWidget.focusPrevious(); } Keys.onTabPressed: { moreButton.forceActiveFocus(Qt.TabFocusReason); @@ -201,7 +201,7 @@ Pane { if (addSyncButton.enabled) { addSyncButton.forceActiveFocus(Qt.TabFocusReason); } else { - accountSettings.focusNext(); + ocParentWidget.focusNext(); } } @@ -247,7 +247,7 @@ Pane { } Keys.onTabPressed: { - accountSettings.focusNext(); + ocParentWidget.focusNext(); } } Item { diff --git a/src/gui/qmlutils.cpp b/src/gui/qmlutils.cpp index b4dc4991a55..2c351b19b7c 100644 --- a/src/gui/qmlutils.cpp +++ b/src/gui/qmlutils.cpp @@ -14,6 +14,7 @@ #include "gui/qmlutils.h" +#include "common/asserts.h" #include "resources/resources.h" #include @@ -21,22 +22,29 @@ #include #include -void OCC::QmlUtils::initQuickWidget(OCQuickWidget *widget, const QUrl &src, QObject *ocContext) +void OCC::QmlUtils::OCQuickWidget::setOCContext(const QUrl &src, QWidget *parentWidget, QObject *ocContext, QJSEngine::ObjectOwnership ownership) { - widget->rootContext()->setContextProperty(QStringLiteral("ocContext"), ocContext); - widget->engine()->addImageProvider(QStringLiteral("ownCloud"), new OCC::Resources::CoreImageProvider()); - widget->setResizeMode(QQuickWidget::SizeRootObjectToView); - widget->setSource(src); - if (!widget->errors().isEmpty()) { - auto box = new QMessageBox(QMessageBox::Critical, QStringLiteral("QML Error"), QDebug::toString(widget->errors())); + rootContext()->setContextProperty(QStringLiteral("ocParentWidget"), parentWidget); + rootContext()->setContextProperty(QStringLiteral("ocContext"), ocContext); + engine()->setObjectOwnership(ocContext, ownership); + engine()->addImageProvider(QStringLiteral("ownCloud"), new OCC::Resources::CoreImageProvider()); + setResizeMode(QQuickWidget::SizeRootObjectToView); + setSource(src); + if (!errors().isEmpty()) { + auto box = new QMessageBox(QMessageBox::Critical, QStringLiteral("QML Error"), QDebug::toString(errors())); box->setAttribute(Qt::WA_DeleteOnClose); box->exec(); - qFatal("A qml error occured %s", qPrintable(QDebug::toString(widget->errors()))); + qFatal("A qml error occured %s", qPrintable(QDebug::toString(errors()))); } - // string based connects as they are provided by OC_DECLARE_WIDGET_FOCUS and not inherited - QObject::connect(widget, SIGNAL(focusFirst()), ocContext, SIGNAL(focusFirst())); - QObject::connect(widget, SIGNAL(focusLast()), ocContext, SIGNAL(focusLast())); + // string based connects as they are provided by OC_DECLARE_WIDGET_FOCUS and not inherited, assert to ensure the connection works + OC_ASSERT(QObject::connect(this, SIGNAL(focusFirst()), parentWidget, SIGNAL(focusFirst()))); + OC_ASSERT(QObject::connect(this, SIGNAL(focusLast()), parentWidget, SIGNAL(focusLast()))); +} + +void OCC::QmlUtils::OCQuickWidget::setOCContext(const QUrl &src, QWidget *ocContext) +{ + setOCContext(src, ocContext, ocContext, QJSEngine::ObjectOwnership::CppOwnership); } void OCC::QmlUtils::OCQuickWidget::focusInEvent(QFocusEvent *event) diff --git a/src/gui/qmlutils.h b/src/gui/qmlutils.h index b9e8a4d2839..7bb6f54470b 100644 --- a/src/gui/qmlutils.h +++ b/src/gui/qmlutils.h @@ -13,6 +13,7 @@ */ #pragma once +#include #include class QUrl; @@ -40,6 +41,8 @@ class OCQuickWidget : public QQuickWidget Q_OBJECT public: using QQuickWidget::QQuickWidget; + void setOCContext(const QUrl &src, QWidget *parentWidget, QObject *ocContext, QJSEngine::ObjectOwnership ownership); + void setOCContext(const QUrl &src, QWidget *ocContext); Q_SIGNALS: void focusFirst(); @@ -50,6 +53,4 @@ class OCQuickWidget : public QQuickWidget bool event(QEvent *event) override; }; - -void initQuickWidget(OCQuickWidget *widget, const QUrl &src, QObject *ocContext); } diff --git a/src/gui/settingsdialog.cpp b/src/gui/settingsdialog.cpp index 42af311e07c..5d5c0de90c0 100644 --- a/src/gui/settingsdialog.cpp +++ b/src/gui/settingsdialog.cpp @@ -98,7 +98,7 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent) // TODO: fix sizing _ui->quickWidget->setFixedHeight(minimumHeight() * 0.13); _ui->quickWidget->engine()->addImageProvider(QStringLiteral("avatar"), new AvatarImageProvider); - QmlUtils::initQuickWidget(_ui->quickWidget, QUrl(QStringLiteral("qrc:/qt/qml/org/ownCloud/gui/qml/AccountBar.qml")), this); + _ui->quickWidget->setOCContext(QUrl(QStringLiteral("qrc:/qt/qml/org/ownCloud/gui/qml/AccountBar.qml")), this); connect( _ui->quickWidget->engine(), &QQmlEngine::quit, QApplication::instance(), [this] { diff --git a/src/gui/spaces/qml/SpaceDelegate.qml b/src/gui/spaces/qml/SpaceDelegate.qml index 328201d0605..8c506ac431c 100644 --- a/src/gui/spaces/qml/SpaceDelegate.qml +++ b/src/gui/spaces/qml/SpaceDelegate.qml @@ -24,7 +24,7 @@ Item { property alias imageSource: image.source property alias statusSource: statusIcon.source - default property alias content: colLayout.children + default property alias content: colLayout.data ColumnLayout { anchors.fill: parent diff --git a/src/gui/spaces/qml/SpacesView.qml b/src/gui/spaces/qml/SpacesView.qml index 1ef2499abdc..20f99ddddc7 100644 --- a/src/gui/spaces/qml/SpacesView.qml +++ b/src/gui/spaces/qml/SpacesView.qml @@ -37,7 +37,7 @@ Pane { ScrollBar.vertical.policy: ScrollBar.AlwaysOn Connections { - target: spacesBrowser + target: ocParentWidget function onFocusFirst() { listView.currentIndex = 0; @@ -101,11 +101,11 @@ Pane { focus: true Keys.onBacktabPressed: { - spacesBrowser.focusPrevious(); + ocParentWidget.focusPrevious(); } Keys.onTabPressed: { - spacesBrowser.focusNext(); + ocParentWidget.focusNext(); } background: Rectangle { diff --git a/src/gui/spaces/spacesbrowser.cpp b/src/gui/spaces/spacesbrowser.cpp index feb397681ae..0a276f4ba49 100644 --- a/src/gui/spaces/spacesbrowser.cpp +++ b/src/gui/spaces/spacesbrowser.cpp @@ -51,7 +51,7 @@ SpacesBrowser::SpacesBrowser(QWidget *parent) _sortModel->setSortRole(static_cast(SpacesModel::Roles::Priority)); _sortModel->sort(0, Qt::DescendingOrder); - QmlUtils::initQuickWidget(ui->quickWidget, QUrl(QStringLiteral("qrc:/qt/qml/org/ownCloud/gui/spaces/qml/SpacesView.qml")), this); + ui->quickWidget->setOCContext(QUrl(QStringLiteral("qrc:/qt/qml/org/ownCloud/gui/spaces/qml/SpacesView.qml")), this); setFocusProxy(ui->quickWidget); }