diff --git a/qml/AppUI/PluginSelectMenu.qml b/qml/AppUI/PluginSelectMenu.qml index 4a930c8..2377be2 100644 --- a/qml/AppUI/PluginSelectMenu.qml +++ b/qml/AppUI/PluginSelectMenu.qml @@ -48,10 +48,9 @@ RowLayout { onClicked: { if(sortMenuSelector.state === "sortMenuClose") { - sortMenuSelector.state = "sortMenuOpen" - } else { - sortMenuSelector.state = "sortMenuClose" + sortMenuSelector.state = "sortMenuOpen"; } + pluginSelectMenuRoot.model.openMenu(pluginSelectButton.height - y - mouseY + 8); } ThemeIcon { @@ -66,116 +65,41 @@ RowLayout { State { name: "sortMenuOpen" PropertyChanges { target: sortMenuSelector; rotation: 0 } - PropertyChanges { target: sortMenu; visible: true } }, State { name: "sortMenuClose" PropertyChanges { target: sortMenuSelector; rotation: 180 } - PropertyChanges { target: sortMenu; visible: false } } ] transitions: [ Transition { to: "sortMenuOpen" - RotationAnimation { duration: 300; direction: RotationAnimation.Counterclockwise} + RotationAnimation { duration: 100; direction: RotationAnimation.Counterclockwise} }, Transition { to: "sortMenuClose" - RotationAnimation { duration: 300; direction: RotationAnimation.Clockwise } + RotationAnimation { duration: 100; direction: RotationAnimation.Clockwise } } ] - } - - - Menu { - id: sortMenu - width: 128; height: 120 - padding: 8 - clip: true - opacity: visible - x: parent.width - width - - enter: Transition { - ParallelAnimation { - NumberAnimation { property: "opacity"; from: 0.0; to: 1.0 } - NumberAnimation { property: "y"; from: pluginSelectButton.height - 20; to: pluginSelectButton.height } - } - - } - exit: Transition { - ParallelAnimation { - NumberAnimation { property: "opacity"; from: 1.0; to: 0.0 } - NumberAnimation { property: "y"; from: pluginSelectButton.height; to: pluginSelectButton.height - 20 } - } - } - - onClosed: sortMenuSelector.state = "sortMenuClose" - - // TODO 添加边框阴影 - background: AppControls2.StyleBackground { - paletteRole: Palette.Window - useStyleTransparent: false - radius: 8 - } - - contentItem: ListView { - clip: true - spacing: 4 - model: pluginSelectMenuRoot.model - - delegate: AppControls2.StyleBackground { - width: ListView.view ? ListView.view.width : 0 - height: 32 - radius: 4 - alpha: mouseArea.containsMouse ? 0.2 : 0 - paletteRole: Palette.Text - useStyleTransparent: false - - Item { - anchors.fill: parent - anchors.margins: 8 - Image { - visible: model.isChecked - anchors.verticalCenter: parent.verticalCenter - width: 16 - height: 16 - source: "image://appicon/object-select.symbolic" - } - AppControls2.StyleText { - x: 24 - verticalAlignment: Text.AlignVCenter - width: parent.width - x - height: parent.height - text: model.name - } - } - - MouseArea { - id: mouseArea - anchors.fill: parent - hoverEnabled: true - onClicked: { - if (model.isChecked) { - return; - } - appPageHeaderUtils.activateProvider(model.id); - } - } - } - } Component.onCompleted: { updateProviderIcon(); pluginSelectMenuRoot.model.currentIndexChanged.connect(updateProviderIcon); + pluginSelectMenuRoot.model.menuClosed.connect(changeMenuStatus); } Component.onDestruction: { pluginSelectMenuRoot.model.currentIndexChanged.disconnect(updateProviderIcon); + pluginSelectMenuRoot.model.menuClosed.disconnect(changeMenuStatus); } function updateProviderIcon() { pluginSelectButton.buttonIcon = pluginSelectMenuRoot.model.currentProviderIcon(); } + + function changeMenuStatus() { + sortMenuSelector.state = "sortMenuClose"; + } } } } diff --git a/src/utils/app-page-header-utils.cpp b/src/utils/app-page-header-utils.cpp index f09690d..4e07957 100644 --- a/src/utils/app-page-header-utils.cpp +++ b/src/utils/app-page-header-utils.cpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace UkuiMenu { @@ -42,8 +43,11 @@ public: Q_INVOKABLE void autoSwitchProvider(); Q_INVOKABLE QString currentProviderIcon(); + Q_INVOKABLE void openMenu(int offset); + Q_SIGNALS: void currentIndexChanged(); + void menuClosed(); private: int indexOfProvider(const QString &providerId); @@ -142,6 +146,32 @@ QString ProviderModel::currentProviderIcon() return data(createIndex(m_currentIndex, 0), Icon).toString(); } +void ProviderModel::openMenu(int offset) +{ + QMenu menu; + + if (m_providers.isEmpty()) { + return; + } + + for (const ProviderInfo &info : m_providers) { + QAction *action = new QAction(info.name, &menu); + action->setCheckable(true); + connect(action, &QAction::triggered, &menu, [info]() { + DataProviderManager::instance()->activateProvider(info.id); + }); + menu.addAction(action); + } + + menu.actions().at(m_currentIndex)->setChecked(true); + + int x = QCursor::pos().x() - menu.sizeHint().width(); + int y = QCursor::pos().y() + offset; + menu.exec(QPoint(x, y)); + + Q_EMIT menuClosed(); +} + void ProviderModel::reactivateProvider() { DataProviderManager::instance()->activateProvider(m_providers.at(m_currentIndex).id);