diff --git a/CMakeLists.txt b/CMakeLists.txt index 3245a23..8b96f18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,6 +96,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/extension/extensions/favorite-extension.cpp src/extension/extensions/favorite-extension.h ) # qrc文件 diff --git a/qml/AppControls2/CollectionItem.qml b/qml/AppControls2/CollectionItem.qml deleted file mode 100644 index a193c43..0000000 --- a/qml/AppControls2/CollectionItem.qml +++ /dev/null @@ -1,30 +0,0 @@ -import QtQuick 2.0 -import QtQuick.Controls 2.5 -import QtQuick.Layouts 1.12 -import org.ukui.menu.core 1.0 - -RoundButton { - id: control - property string appName: "" - property string appIcon: "" - - height: 104 - width: height - radius: 10 - scale: control.pressed ? 1.1 : 1.0 - hoverEnabled: true - - contentItem: IconLabel { - anchors.fill: parent - appName: control.appName - appIcon: control.appIcon - display: Display.TextUnderIcon - } - - background: StyleBackground { - radius: control.radius - useStyleTransparent: false - alpha: control.pressed ? 0.75 : control.hovered ? 0.6 : 0.40 - } -} - diff --git a/qml/AppControls2/qmldir b/qml/AppControls2/qmldir index 5101b70..16675b3 100644 --- a/qml/AppControls2/qmldir +++ b/qml/AppControls2/qmldir @@ -5,3 +5,4 @@ ScrollBar 1.0 ScrollBar.qml AppItem 1.0 AppItem.qml FolderItem 1.0 FolderItem.qml LabelItem 1.0 LabelItem.qml +IconLabel 1.0 IconLabel.qml diff --git a/qml/extensions/FavoriteExtension.qml b/qml/extensions/FavoriteExtension.qml new file mode 100644 index 0000000..3ca1810 --- /dev/null +++ b/qml/extensions/FavoriteExtension.qml @@ -0,0 +1,163 @@ +/* + * 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 . + * + */ + +import QtQuick 2.12 +import QtQml.Models 2.1 +import QtQuick.Controls 2.5 +import org.ukui.menu.core 1.0 +import org.ukui.menu.extension 1.0 +import AppControls2 1.0 as AppControls2 + +UkuiMenuExtension { + Component.onCompleted: { + visualModel.model = extensionData.favoriteAppsModel + } + + MouseArea { + id: viewMouseArea + anchors.fill: parent + hoverEnabled: true + + GridView { + id: favoriteView + anchors.fill: parent + anchors.leftMargin: 16 + anchors.topMargin: 14 + cellWidth: itemHeight + spacing; cellHeight: cellWidth + property int exchangedStartIndex: 0 + property int spacing: 4 + property int itemHeight: 104 + + ScrollBar.vertical: AppControls2.ScrollBar { + id: scrollBar + visible: viewMouseArea.containsMouse + width: 14; height: favoriteView.height + } + + displaced: Transition { + NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad; duration: 200 } + } + + model: DelegateModel { + id: visualModel + delegate: DropArea { + id: delegateRoot + property int visualIndex: DelegateModel.itemsIndex + width: favoriteView.cellWidth; height: favoriteView.cellHeight + onEntered: visualModel.items.move(drag.source.visualIndex, icon.visualIndex) + + Binding { target: icon; property: "visualIndex"; value: visualIndex } + + AppControls2.StyleBackground { + id: icon + height: favoriteView.itemHeight; width: height + property bool hold: false + property int visualIndex: 0 + x: 0; y: 0 + + radius: 8 + useStyleTransparent: false + scale: icon.hold ? 1.1 :1.0 + alpha: control.containsPress ? 0.75 : control.containsMouse ? 0.6 : 0.40 + + Behavior on scale { + NumberAnimation { duration: 300; easing.type: Easing.InOutCubic } + } + + AppControls2.IconLabel { + height: icon.height + width: icon.width - 14 + anchors.centerIn: parent + appName: model.name + appIcon: model.icon + display: Display.TextUnderIcon + scale: (control.containsPress && !icon.hold) ? 1.1 : 1.0 + + Behavior on scale { + NumberAnimation { duration: 300; easing.type: Easing.InOutCubic } + } + } + + MouseArea { + id: control + anchors.fill: parent + hoverEnabled: true + pressAndHoldInterval: 300 + acceptedButtons: Qt.LeftButton | Qt.RightButton + + onPressed: { + if (mouse.button === Qt.RightButton) { + console.log("RightButtononPressed:",mouse.x,mouse.y); + } + } + onClicked: { + if (mouse.button === Qt.LeftButton) { + var data = {"id": model.id}; + send(data); + } + } + onPressAndHold: { + if (mouse.button === Qt.LeftButton) { + drag.target = icon; + icon.hold = true; + favoriteView.exchangedStartIndex = icon.visualIndex; + } + } + onReleased: { + icon.hold = false; + drag.target = null; + } + } + + onHoldChanged: { + if (hold) { + favoriteView.interactive = false; + } else { + favoriteView.interactive = true; + visualModel.model.exchangedAppsOrder(favoriteView.exchangedStartIndex, icon.visualIndex); + } + } + + Drag.active: control.drag.active + Drag.source: icon + Drag.hotSpot.x: icon.width / 2 + Drag.hotSpot.y: icon.height / 2 + + Drag.onActiveChanged: { + if (Drag.active) { + icon.parent = favoriteView; + } else { + iconResetAnimation.start(); + } + } + ParallelAnimation { + id: iconResetAnimation + NumberAnimation { target: icon; property: "x"; to: delegateRoot.x; easing.type: Easing.OutQuad; duration: 300 } + NumberAnimation { target: icon; property: "y"; to: delegateRoot.y; easing.type: Easing.OutQuad; duration: 300 } + + onFinished: { + icon.parent = delegateRoot; + icon.x = 0; icon.y = 0; + } + } + } + } + } + } + } +} diff --git a/qml/qml.qrc b/qml/qml.qrc index dc9f9f3..56d95ac 100644 --- a/qml/qml.qrc +++ b/qml/qml.qrc @@ -14,7 +14,6 @@ AppControls2/qmldir AppControls2/App.qml AppControls2/ScrollBar.qml - AppControls2/CollectionItem.qml AppControls2/StyleBackground.qml AppControls2/StyleText.qml AppControls2/IconLabel.qml @@ -23,5 +22,6 @@ AppControls2/FolderItem.qml extensions/FolderExtension.qml extensions/RecentFileExtension.qml + extensions/FavoriteExtension.qml diff --git a/src/extension/extensions/favorite-extension.cpp b/src/extension/extensions/favorite-extension.cpp new file mode 100644 index 0000000..0316822 --- /dev/null +++ b/src/extension/extensions/favorite-extension.cpp @@ -0,0 +1,165 @@ +/* + * 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 "favorite-extension.h" +#include "app-data-manager.h" +#include "app-manager.h" +#include "commons.h" +#include +#include +#include + +namespace UkuiMenu { + +class FavoriteAppsModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum RoleMessage + { + Id = Qt::UserRole, + Icon = Qt::UserRole + 1, + Name = Qt::UserRole + 2 + }; + + explicit FavoriteAppsModel(QObject *parent = nullptr); + int rowCount(const QModelIndex &parent) const override; + QHash roleNames() const override; + QVariant data(const QModelIndex &index, int role) const override; + void setFavoriteAppsData(QVector &apps); + +public Q_SLOTS: + void exchangedAppsOrder(int startIndex, int endIndex); + +private: + QVector m_favoriteAppsData; + UkuiSearch::AppInfoTable *m_appInfoTable = nullptr; +}; + +FavoriteExtension::FavoriteExtension(QObject *parent) : MenuExtensionIFace(parent) +{ + qRegisterMetaType("FavoriteAppsModel*"); + + m_favoriteAppsModel = new FavoriteAppsModel(this); + m_data.insert("favoriteAppsModel", QVariant::fromValue(m_favoriteAppsModel)); + + updateFavoriteData(); + connect(AppDataManager::instance(),&AppDataManager::favoriteAppChanged, this,&FavoriteExtension::updateFavoriteData); +} + +FavoriteExtension::~FavoriteExtension() +{ + +} + +void FavoriteExtension::receive(QVariantMap data) +{ + QString path = data.value("id").toString(); + openFavoriteApp(path); +} + +int FavoriteExtension::index() +{ + return 0; +} + +QString FavoriteExtension::name() +{ + return "Favorite"; +} + +QUrl FavoriteExtension::url() +{ + return {"qrc:///qml/extensions/FavoriteExtension.qml"}; +} + +QVariantMap FavoriteExtension::data() +{ + return m_data; +} + +void FavoriteExtension::openFavoriteApp(const QString &path) +{ + bool status = AppManager::instance()->launchApp(path); + if (!status) { + qWarning() << "open favoriteApp failed!"; + } +} + +void FavoriteExtension::updateFavoriteData() +{ + QVector favoriteApps = AppDataManager::instance()->favoriteApps(); + m_favoriteAppsModel->setFavoriteAppsData(favoriteApps); +} + +FavoriteAppsModel::FavoriteAppsModel(QObject *parent) : QAbstractListModel(parent) +{ + m_appInfoTable = new UkuiSearch::AppInfoTable(this); +} + +int FavoriteAppsModel::rowCount(const QModelIndex &parent) const +{ + return m_favoriteAppsData.count(); +} + +QHash FavoriteAppsModel::roleNames() const +{ + QHash names; + names.insert(Id,"id"); + names.insert(Icon,"icon"); + names.insert(Name,"name"); + return names; +} + +QVariant FavoriteAppsModel::data(const QModelIndex &index, int role) const +{ + int row = index.row(); + if (row < 0 || row > m_favoriteAppsData.count()) { + return {}; + } + + switch (role) { + case Id: + return m_favoriteAppsData.at(row).id(); + case Icon: + return m_favoriteAppsData.at(row).icon(); + case Name: + return m_favoriteAppsData.at(row).name(); + default: + break; + } + return {}; +} + +void FavoriteAppsModel::setFavoriteAppsData(QVector &apps) +{ + beginResetModel(); + m_favoriteAppsData.swap(apps); + endResetModel(); +} + +void FavoriteAppsModel::exchangedAppsOrder(int startIndex, int endIndex) +{ + int endNum = m_favoriteAppsData.at(endIndex).favorite(); + QString startId = m_favoriteAppsData.at(startIndex).id(); + m_appInfoTable->changeFavoriteAppPos(startId,endNum); +} + +} // UkuiMenu + +#include "favorite-extension.moc" diff --git a/src/extension/extensions/favorite-extension.h b/src/extension/extensions/favorite-extension.h new file mode 100644 index 0000000..b250a3b --- /dev/null +++ b/src/extension/extensions/favorite-extension.h @@ -0,0 +1,52 @@ +/* + * 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_FAVORITE_EXTENSION_H +#define UKUI_MENU_FAVORITE_EXTENSION_H + +#include "../menu-extension-iface.h" + +namespace UkuiMenu { + +class FavoriteAppsModel; + +class FavoriteExtension : public MenuExtensionIFace +{ + Q_OBJECT +public: + explicit FavoriteExtension(QObject *parent = nullptr); + ~FavoriteExtension(); + + void receive(QVariantMap data) override; + int index() override; + QString name() override; + QUrl url() override; + QVariantMap data() override; + +private: + QVariantMap m_data; + FavoriteAppsModel *m_favoriteAppsModel = nullptr; + +private: + void updateFavoriteData(); + void openFavoriteApp(const QString &path); +}; + +} // UkuiMenu + +#endif //UKUI_MENU_FAVORITE_EXTENSION_H diff --git a/src/extension/extensions/folder-extension.cpp b/src/extension/extensions/folder-extension.cpp index f2c34d0..f4a48e5 100644 --- a/src/extension/extensions/folder-extension.cpp +++ b/src/extension/extensions/folder-extension.cpp @@ -38,7 +38,7 @@ FolderExtension::FolderExtension(QObject *parent) : MenuExtensionIFace(parent) int FolderExtension::index() { - return 0; + return 2; } QString FolderExtension::name() diff --git a/src/extension/menu-extension.cpp b/src/extension/menu-extension.cpp index 0eb3057..5ed546d 100644 --- a/src/extension/menu-extension.cpp +++ b/src/extension/menu-extension.cpp @@ -19,6 +19,7 @@ #include "menu-extension.h" #include "extensions/folder-extension.h" #include "extensions/recent-file-extension.h" +#include "extensions/favorite-extension.h" #include #include @@ -40,6 +41,7 @@ MenuExtension::MenuExtension() // register extension. registerExtension(new FolderExtension(this)); registerExtension(new RecentFileExtension(this)); + registerExtension(new FavoriteExtension(this)); initModel(); }