diff --git a/CMakeLists.txt b/CMakeLists.txt
index 023a3a4..d0a6fe4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -100,6 +100,7 @@ set(SOURCE_FILES
src/utils/app-page-header-utils.cpp src/utils/app-page-header-utils.h
src/utils/power-button.cpp src/utils/power-button.h
src/utils/app-manager.cpp src/utils/app-manager.h
+ src/model/label-model.cpp src/model/label-model.h
)
# qrc文件
diff --git a/qml/AppControls2/AppItem.qml b/qml/AppControls2/AppItem.qml
index cc399e9..c2b3523 100644
--- a/qml/AppControls2/AppItem.qml
+++ b/qml/AppControls2/AppItem.qml
@@ -4,7 +4,6 @@ import QtQuick.Controls 2.5
import org.ukui.menu.core 1.0
StyleBackground {
- anchors.fill: parent
radius: 4
useStyleTransparent: false
alpha: control.containsPress ? 0.82 : control.containsMouse ? 0.55 : 0.00
diff --git a/qml/AppControls2/LabelItem.qml b/qml/AppControls2/LabelItem.qml
index 273c04b..ec7d9cb 100644
--- a/qml/AppControls2/LabelItem.qml
+++ b/qml/AppControls2/LabelItem.qml
@@ -1,24 +1,43 @@
import QtQuick 2.0
import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.5
+
+StyleBackground {
+ radius: 4
+ useStyleTransparent: false
+ alpha: control.containsPress ? 0.82 : control.containsMouse ? 0.55 : 0.00
+ ToolTip.text: qsTr("Open the label selection interface")
+ ToolTip.visible: control.containsMouse
-Item {
RowLayout {
anchors.fill: parent
- Text {
- Layout.fillWidth: true
- Layout.fillHeight: true
- Layout.leftMargin: 5
+ StyleText {
+ Layout.preferredHeight: parent.height
+ Layout.preferredWidth: contentWidth
+ Layout.leftMargin: 12
horizontalAlignment: Qt.AlignLeft
verticalAlignment: Qt.AlignVCenter
+ font.pixelSize: 14
+ font.bold: true
text: name
}
Image {
- Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
- Layout.preferredWidth: 32
- Layout.preferredHeight: 32
- source: icon
+ visible: control.containsMouse
+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
+ Layout.preferredWidth: 24
+ Layout.preferredHeight: 24
+ Layout.rightMargin: 16
+ source: "image://appicon/open-menu-symbolic"
+ }
+ }
+ MouseArea {
+ id: control
+ hoverEnabled: true
+ anchors.fill: parent
+ onClicked: {
+ appList.labelItemClicked();
}
}
}
diff --git a/qml/AppControls2/StyleText.qml b/qml/AppControls2/StyleText.qml
index 89422c2..8f23661 100644
--- a/qml/AppControls2/StyleText.qml
+++ b/qml/AppControls2/StyleText.qml
@@ -3,9 +3,10 @@ import org.ukui.menu.core 1.0
Text {
property int paletteRole: Palette.Text
+ property real alpha: 1.0
function updateColor() {
- color = themePalette.paletteColor(paletteRole)
+ color = themePalette.paletteColorWithCustomTransparency(paletteRole, Palette.Active, alpha)
}
Component.onCompleted: {
@@ -19,4 +20,7 @@ Text {
onPaletteRoleChanged: {
updateColor()
}
+ onAlphaChanged: {
+ updateColor()
+ }
}
diff --git a/qml/AppUI/AppList.qml b/qml/AppUI/AppList.qml
index bae67b8..42ffdff 100644
--- a/qml/AppUI/AppList.qml
+++ b/qml/AppUI/AppList.qml
@@ -26,6 +26,10 @@ import org.ukui.menu.core 1.0
Item {
property string title: ""
+ function labelSelection(labelId) {
+ appListView.positionViewAtIndex(appListView.model.currentAppIndex(labelId), ListView.Beginning)
+ }
+
MouseArea {
id: appListArea
hoverEnabled: true
@@ -51,8 +55,11 @@ Item {
Layout.fillHeight: true
Layout.fillWidth: true
ScrollBar.vertical: appListScrollBar
- model: modelManager.getAppModel()
+ highlightMoveDuration: 0
+ boundsBehavior: Flickable.StopAtBounds
+
+ model: modelManager.getAppModel()
delegate: Component {
Loader {
width: ListView.view ? ListView.view.width : 0
@@ -80,7 +87,7 @@ Item {
id: appListScrollBar
Layout.fillHeight: true
Layout.preferredWidth: 14
- visible: appListArea.containsMouse
+ visual: appListArea.containsMouse
}
}
}
diff --git a/qml/AppUI/AppPage.qml b/qml/AppUI/AppPage.qml
index d43a934..21063db 100644
--- a/qml/AppUI/AppPage.qml
+++ b/qml/AppUI/AppPage.qml
@@ -36,8 +36,7 @@ AppControls2.StyleBackground {
Layout.preferredHeight: 40
}
- AppList {
- clip: true
+ AppPageContent {
Layout.fillWidth: true
Layout.fillHeight: true
}
diff --git a/qml/AppUI/AppPageContent.qml b/qml/AppUI/AppPageContent.qml
new file mode 100644
index 0000000..d0e3574
--- /dev/null
+++ b/qml/AppUI/AppPageContent.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.0
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.5
+import AppControls2 1.0 as AppControls2
+import org.ukui.menu.core 1.0
+
+Item {
+ AppList {
+ id: appList
+ clip: true
+ anchors.fill: parent
+ anchors.leftMargin: 4
+ function labelItemClicked() {
+ appList.visible = false;
+ selectionPage.viewShowStart();
+ }
+ }
+
+ SelectionPage {
+ id: selectionPage
+ anchors.fill: parent
+ anchors.bottomMargin: 54
+ visible: !appList.visible
+ onViewHideFinished: appList.visible = true
+ onLabelSelected: appList.labelSelection(labelId)
+ }
+}
diff --git a/qml/AppUI/AppPageHeader.qml b/qml/AppUI/AppPageHeader.qml
index e69b3c2..b2c3ef1 100644
--- a/qml/AppUI/AppPageHeader.qml
+++ b/qml/AppUI/AppPageHeader.qml
@@ -78,8 +78,7 @@ Item {
Layout.fillHeight: true
radius: 16
useStyleTransparent: false
- onTextChanged:
- {
+ onTextChanged: {
if (text === "") {
sortMenu.sortMenuModel.reactivateProvider();
} else {
@@ -87,7 +86,6 @@ Item {
appPageHeaderUtils.startSearch(text);
}
}
-
}
AppControls2.RoundButton {
@@ -109,6 +107,7 @@ Item {
RowLayout {
anchors.fill: parent
anchors.leftMargin: 16
+ spacing: 12
Text {
Layout.fillWidth: true
Layout.fillHeight: true
diff --git a/qml/AppUI/SelectionPage.qml b/qml/AppUI/SelectionPage.qml
new file mode 100644
index 0000000..1b28a37
--- /dev/null
+++ b/qml/AppUI/SelectionPage.qml
@@ -0,0 +1,85 @@
+import QtQuick 2.12
+import QtQuick.Layouts 1.2
+import org.ukui.menu.core 1.0
+import AppControls2 1.0 as AppControls2
+
+Item {
+ id: root
+ signal viewHideFinished()
+ signal labelSelected(string labelId)
+
+ function viewShowStart() {
+ viewShow.start();
+ }
+
+ ParallelAnimation {
+ id: viewShow
+ NumberAnimation { target: selectionArea; property: "scale"; easing.type: Easing.InOutCubic; from: 1.5; to: 1.0; duration: 300}
+ NumberAnimation { target: selectionArea; property: "opacity"; easing.type: Easing.InOutCubic; from: 0; to: 1.0; duration: 300}
+ }
+
+ ParallelAnimation {
+ id: viewHide
+ NumberAnimation { target: selectionArea; property: "scale"; easing.type: Easing.InOutCubic; from: 1.0; to: 1.5 ;duration: 300}
+ NumberAnimation { target: selectionArea; property: "opacity"; easing.type: Easing.InOutCubic; from: 1.0; to: 0 ;duration: 300}
+ onFinished: {
+ viewHideFinished();
+ }
+ }
+
+ GridView {
+ id: selectionArea
+ anchors.centerIn: parent
+ interactive: false
+ property int itemWidth: 0
+ property int itemHeight: 40
+ cellWidth: itemWidth; cellHeight: itemHeight
+
+ state: count < 20 ? "functionArea" : "AlphabetArea"
+ states: [
+ State {
+ name: "functionArea"
+ PropertyChanges { target: selectionArea; itemWidth: 80; width: itemWidth * 2; height: itemHeight * 7 }
+ },
+ State {
+ name: "AlphabetArea"
+ PropertyChanges { target: selectionArea; itemWidth: 40; width: itemWidth * 5; height: itemHeight * 6 }
+ }
+ ]
+
+ model: modelManager.getLabelModel()
+ onCountChanged: {
+ if (count === 0) {
+ viewHide.start();
+ }
+ }
+
+ delegate: AppControls2.StyleBackground {
+ height: selectionArea.itemHeight; width: selectionArea.itemWidth
+ alpha: itemMouseArea.containsPress ? 0.82 : itemMouseArea.containsMouse ? 0.55 : 0.00
+ useStyleTransparent: false
+ radius: 8
+
+ AppControls2.StyleText {
+ anchors.fill: parent
+ text: model.displayName
+ alpha: model.isDisable ? 0.2 : 0.9
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
+ }
+
+ MouseArea {
+ id: itemMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ visible: !model.isDisable
+ onClicked: {
+ viewHide.start();
+ root.labelSelected(model.id);
+ }
+ }
+ }
+ }
+}
+
diff --git a/qml/qml.qrc b/qml/qml.qrc
index f51be11..3e3d069 100644
--- a/qml/qml.qrc
+++ b/qml/qml.qrc
@@ -25,5 +25,7 @@
extensions/RecentFileExtension.qml
extensions/FavoriteExtension.qml
AppControls2/RoundButton.qml
+ AppUI/SelectionPage.qml
+ AppUI/AppPageContent.qml
diff --git a/src/appdata/data-provider-manager.cpp b/src/appdata/data-provider-manager.cpp
index 0bf306a..db6de64 100644
--- a/src/appdata/data-provider-manager.cpp
+++ b/src/appdata/data-provider-manager.cpp
@@ -78,6 +78,11 @@ void DataProviderManager::registerProvider(DataProviderPluginIFace *provider)
Q_EMIT dataChanged(data, mode, index);
});
+
+ connect(provider, &AllAppDataProvider::labelChanged, this, [this, provider]() {
+ if (m_activatedPlugin != provider->id()) { return; }
+ Q_EMIT labelChanged();
+ });
}
QVector DataProviderManager::data() const
@@ -85,6 +90,11 @@ QVector DataProviderManager::data() const
return m_providers.value(m_activatedPlugin)->data();
}
+QVector DataProviderManager::labels() const
+{
+ return m_providers.value(m_activatedPlugin)->labels();
+}
+
QString DataProviderManager::activatedProvider() const
{
return m_activatedPlugin;
diff --git a/src/appdata/data-provider-manager.h b/src/appdata/data-provider-manager.h
index e05ac3c..6c3e30a 100644
--- a/src/appdata/data-provider-manager.h
+++ b/src/appdata/data-provider-manager.h
@@ -50,12 +50,14 @@ public:
QString activatedProvider() const;
void activateProvider(const QString &id);
QVector data() const;
+ QVector labels() const;
void forceUpdate() const;
void forceUpdate(QString &key) const;
Q_SIGNALS:
void pluginChanged(const QString &id, PluginGroup::Group group);
void dataChanged(QVector data, DataUpdateMode::Mode mode, quint32 index);
+ void labelChanged();
private:
DataProviderManager();
diff --git a/src/commons.h b/src/commons.h
index 7302e5b..003fb5b 100644
--- a/src/commons.h
+++ b/src/commons.h
@@ -29,6 +29,12 @@ class LabelItem
{
Q_GADGET
public:
+ enum PropertyName {
+ IsDisable = 0,
+ Index,
+ Id,
+ DisplayName
+ };
LabelItem() = default;
explicit LabelItem(bool disable, int index, QString id, QString displayName);
diff --git a/src/model/label-model.cpp b/src/model/label-model.cpp
new file mode 100644
index 0000000..14a2d6c
--- /dev/null
+++ b/src/model/label-model.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2023, KylinSoft Co., Ltd.
+ *
+ * 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 3 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "label-model.h"
+#include "data-provider-manager.h"
+
+namespace UkuiMenu {
+
+LabelModel::LabelModel(QObject *parent) : QAbstractListModel(parent)
+{
+ reloadLabelData();
+ connect(DataProviderManager::instance(),&DataProviderManager::pluginChanged, this,&LabelModel::reloadLabelData);
+ connect(DataProviderManager::instance(),&DataProviderManager::labelChanged, this,&LabelModel::reloadLabelData);
+}
+
+int LabelModel::rowCount(const QModelIndex &parent) const
+{
+ return m_labels.size();
+}
+
+QVariant LabelModel::data(const QModelIndex &index, int role) const
+{
+ int i = index.row();
+ if (i < 0 || i >= m_labels.size()) {
+ return {};
+ }
+
+ switch (role) {
+ case LabelItem::IsDisable:
+ return m_labels.at(i).isDisable();
+ case LabelItem::Id:
+ return m_labels.at(i).id();
+ case LabelItem::Index:
+ return m_labels.at(i).index();
+ case LabelItem::DisplayName:
+ return m_labels.at(i).displayName();
+ default:
+ break;
+ }
+
+ return {};
+}
+
+QHash LabelModel::roleNames() const
+{
+ QHash names;
+ names.insert(LabelItem::IsDisable, "isDisable");
+ names.insert(LabelItem::Id, "id");
+ names.insert(LabelItem::Index, "index");
+ names.insert(LabelItem::DisplayName, "displayName");
+ return names;
+}
+
+void LabelModel::reloadLabelData()
+{
+ QVector labels = DataProviderManager::instance()->labels();
+ Q_EMIT beginResetModel();
+ m_labels.swap(labels);
+ Q_EMIT endResetModel();
+}
+
+} // UkuiMenu
diff --git a/src/model/label-model.h b/src/model/label-model.h
new file mode 100644
index 0000000..757aa9e
--- /dev/null
+++ b/src/model/label-model.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023, KylinSoft Co., Ltd.
+ *
+ * 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 3 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#ifndef UKUI_MENU_LABEL_MODEL_H
+#define UKUI_MENU_LABEL_MODEL_H
+
+#include
+
+#include "commons.h"
+
+namespace UkuiMenu {
+
+class LabelModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ explicit LabelModel(QObject *parent = nullptr);
+ int rowCount(const QModelIndex &parent) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+ QHash roleNames() const override;
+
+private Q_SLOTS:
+ void reloadLabelData();
+
+private:
+ QVector m_labels;
+};
+
+} // UkuiMenu
+
+#endif //UKUI_MENU_LABEL_MODEL_H
diff --git a/src/model/model-manager.cpp b/src/model/model-manager.cpp
index 1756f4f..9d16dad 100644
--- a/src/model/model-manager.cpp
+++ b/src/model/model-manager.cpp
@@ -17,6 +17,7 @@
*/
#include "model-manager.h"
+#include "label-model.h"
#include "model.h"
namespace UkuiMenu {
@@ -24,11 +25,13 @@ namespace UkuiMenu {
void ModelManager::registerMetaTypes()
{
qRegisterMetaType("AppModel*");
+ qRegisterMetaType("LabelModel*");
}
ModelManager::ModelManager(QObject *parent) : QObject(parent)
{
appModel = new AppModel(this);
+ labelModel = new LabelModel(this);
}
AppModel *ModelManager::getAppModel()
@@ -39,4 +42,12 @@ AppModel *ModelManager::getAppModel()
return nullptr;
}
+LabelModel *ModelManager::getLabelModel()
+{
+ if (labelModel) {
+ return labelModel;
+ }
+ return nullptr;
+}
+
} // UkuiMenu
diff --git a/src/model/model-manager.h b/src/model/model-manager.h
index 6f80aa4..1aae278 100644
--- a/src/model/model-manager.h
+++ b/src/model/model-manager.h
@@ -24,6 +24,7 @@
namespace UkuiMenu {
class AppModel;
+class LabelModel;
class ModelManager : public QObject
{
@@ -34,9 +35,11 @@ public:
~ModelManager() override = default;
Q_INVOKABLE AppModel *getAppModel();
+ Q_INVOKABLE LabelModel *getLabelModel();
private:
AppModel *appModel{nullptr};
+ LabelModel *labelModel{nullptr};
};
} // UkuiMenu
diff --git a/src/model/model.cpp b/src/model/model.cpp
index f243c55..131b84c 100644
--- a/src/model/model.cpp
+++ b/src/model/model.cpp
@@ -73,6 +73,16 @@ QHash AppModel::roleNames() const
return names;
}
+int AppModel::currentAppIndex(const QString &id)
+{
+ for (int index = 0; index < m_apps.count(); ++index) {
+ if (m_apps.at(index).type() == DataType::Label && m_apps.at(index).id() == id) {
+ return index;
+ }
+ }
+ return -1;
+}
+
QVariantList AppModel::folderApps(const QString &folderName)
{
DataEntity item1{DataType::Normal, "name 1", "icon", "comment", "extra"};
diff --git a/src/model/model.h b/src/model/model.h
index 0dae383..391bf60 100644
--- a/src/model/model.h
+++ b/src/model/model.h
@@ -37,6 +37,7 @@ public:
QVariant data(const QModelIndex &index, int role) const override;
QHash roleNames() const override;
+ Q_INVOKABLE int currentAppIndex(const QString &id);
Q_INVOKABLE QVariantList folderApps(const QString &folderName);
Q_INVOKABLE void appClicked(const int &index);