fix(labels): 标签界面基于新后端实现

This commit is contained in:
hewenfei 2024-01-22 16:03:53 +08:00
parent fba597ce54
commit e29052607f
19 changed files with 456 additions and 102 deletions

111
qml/AppUI/AppLabelPage.qml Normal file
View File

@ -0,0 +1,111 @@
/*
* Copyright (C) 2024, 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 <https://www.gnu.org/licenses/>.
*
*/
import QtQuick 2.12
import org.ukui.menu.core 1.0
import org.ukui.quick.items 1.0 as UkuiItems
import org.ukui.quick.platform 1.0 as Platform
GridView {
property var labelBottle: null
property int labelColum: labelBottle === null ? 0 : labelBottle.column
property int labelRow: Math.ceil(count / labelColum)
signal labelSelected(string label)
//
width: 200
height: childrenRect.height
cellWidth: width / labelColum
cellHeight: 40
model: labelBottle === null ? [] : labelBottle.labels
delegate: MouseArea {
width: GridView.view.cellWidth
height: GridView.view.cellHeight
focus: true
hoverEnabled: true
onClicked: {
GridView.view.labelSelected(modelData.label);
GridView.view.currentIndex = model.index
}
Keys.onPressed: (event) => {
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
GridView.view.labelSelected(modelData.label);
}
}
UkuiItems.StyleBackground {
anchors.fill: parent
radius: Platform.Theme.normalRadius
useStyleTransparency: false
paletteRole: Platform.Theme.WindowText
alpha: parent.containsPress ? 0.15 : parent.containsMouse ? 0.08 : 0.0
border.width: (parent.GridView.isCurrentItem && !mainWindow.isFullScreen) ? 2 : 0
borderColor: Platform.Theme.Highlight
Text {
anchors.fill: parent
visible: modelData.type === LabelItem.Text
text: modelData.display
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
UkuiItems.Icon {
anchors.centerIn: parent
width: parent.height/2
height: parent.height/2
visible: modelData.type === LabelItem.Icon
source: modelData.type === LabelItem.Icon ? modelData.display : ""
}
}
}
Keys.onRightPressed: {
if(currentIndex === count - 1) {
currentIndex = 0;
} else {
currentIndex++;
}
}
Keys.onLeftPressed: {
if(currentIndex === 0) {
currentIndex = count - 1;
} else {
currentIndex--;
}
}
Keys.onDownPressed: {
if(Math.floor(currentIndex / labelColum) < labelRow - 1) {
currentIndex = currentIndex + labelColum;
}
}
Keys.onUpPressed: {
if(Math.floor(currentIndex / labelColum) > 0) {
currentIndex = currentIndex - labelColum;
}
}
}

View File

@ -70,7 +70,7 @@ UkuiItems.StyleBackground {
} }
Keys.onPressed: { Keys.onPressed: {
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) { if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
pluginSortButtonRoot.model.changeProvider(0); modelData.trigger();
} }
} }
} }

View File

@ -52,7 +52,7 @@ MouseArea {
ListView { ListView {
id: listView id: listView
cacheBuffer: itemHeight * listView.count cacheBuffer: count * root.itemHeight
spacing: 4 spacing: 4
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true

View File

@ -29,7 +29,8 @@ Item {
if (appList.visible) { if (appList.visible) {
appList.resetListFocus(); appList.resetListFocus();
} else { } else {
selectionPage.viewFocusEnable(); selectionPage.focus = true;
labelPage.focus = true;
} }
} }
@ -51,7 +52,7 @@ Item {
AppList { AppList {
id: appList id: appList
anchors.fill: parent anchors.fill: parent
visible: true visible: !selectionPage.visible
model: AppPageBackend.appModel model: AppPageBackend.appModel
view.onContentYChanged: { view.onContentYChanged: {
@ -61,15 +62,95 @@ Item {
appListHeader.title = view.currentSection; appListHeader.title = view.currentSection;
} }
} }
function positionLabel(label) {
let index = model.findLabelIndex(label);
if (index >= 0) {
view.positionViewAtIndex(index, ListView.Beginning)
}
} }
SelectionPage { onLabelItemClicked: {
labelPage.labelBottle = AppPageBackend.appModel.labelBottle;
labelPage.currentIndex = 0;
selectionPage.state = "viewShowed";
}
}
MouseArea {
id: selectionPage id: selectionPage
anchors.fill: parent anchors.fill: parent
anchors.bottomMargin: 54 visible: false
visible: !appList.visible
onViewHideFinished: appList.visible = true onClicked: state = "viewHid";
onLabelSelected: appList.labelSelection(labelId)
state: "viewHid"
states: [
State {
name: "viewShowed"
changes: [
PropertyChanges {target: selectionPage; scale: 1; opacity: 1; focus: true }
]
},
State {
name: "viewHid"
changes: [
PropertyChanges {target: selectionPage; scale: 1.5; opacity: 0; focus: false }
]
}
]
transitions: [
Transition {
from: "*"; to: "viewShowed"
SequentialAnimation {
ScriptAction { script: selectionPage.visible = true; }
NumberAnimation { properties: "scale,opacity"; easing.type: Easing.InOutCubic; duration: 300}
}
},
Transition {
from: "*"; to: "viewHid"
SequentialAnimation {
NumberAnimation { properties: "scale,opacity"; easing.type: Easing.InOutCubic; duration: 300}
ScriptAction {
script: {
selectionPage.visible = false;
labelPage.labelBottle = null;
labelPage.focus = false;
appList.focus = false;
}
}
}
}
]
AppLabelPage {
id: labelPage
anchors.centerIn: parent
interactive: height > parent.height
onLabelSelected: (label) => {
appList.positionLabel(label);
selectionPage.state = "viewHid";
}
onModelChanged: {
currentIndex = -1;
}
}
function hidePage() {
state = "viewHid";
visible = false;
}
Component.onCompleted: {
mainWindow.visibleChanged.connect(hidePage)
}
Component.onDestruction: {
mainWindow.visibleChanged.disconnect(hidePage)
}
} }
} }
} }

View File

@ -107,17 +107,60 @@ UkuiItems.StyleBackground {
anchors.centerIn: parent anchors.centerIn: parent
width: 120 width: 120
height: parent.height height: parent.height
AppLabelPage {
id: appLabelPage
anchors.centerIn: parent
width: parent.width
labelBottle: AppPageBackend.appModel.labelBottle
labelColum: 1
cellHeight: 34
interactive: height > parent.height
highlightMoveDuration: 300
highlight: UkuiItems.StyleBackground {
width: appLabelPage.cellWidth
height: appLabelPage.cellHeight
useStyleTransparency: false
radius: Platform.Theme.minRadius
paletteRole: Platform.Theme.Light
alpha: 0.15; borderAlpha: 0.5
border.width: 1
borderColor: Platform.Theme.Highlight
}
onLabelSelected: (label) => {
fullScreenAppList.positionLabel(label);
}
}
} }
} }
// : [row: 1, column: 1] // : [row: 1, column: 1]
FullScreenAppList { FullScreenAppList {
id: fullScreenAppList
Layout.row: 1 Layout.row: 1
Layout.column: 1 Layout.column: 1
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
sourceModel: AppPageBackend.appModel sourceModel: AppPageBackend.appModel
function positionLabel(label) {
let index = model.findLabelIndex(label);
if (index >= 0) {
positionViewAtIndex(index, ListView.Beginning)
}
}
onContentYChanged: {
// 200
let index = indexAt(10, contentY + 200);
if (index >= 0) {
appLabelPage.currentIndex = index + 1;
}
}
} }
} }
} }

View File

@ -15,4 +15,5 @@ FullScreenContent 1.0 FullScreenContent.qml
FullScreenFooter 1.0 FullScreenFooter.qml FullScreenFooter 1.0 FullScreenFooter.qml
FullScreenAppList 1.0 FullScreenAppList.qml FullScreenAppList 1.0 FullScreenAppList.qml
FullScreenAppItem 1.0 FullScreenAppItem.qml FullScreenAppItem 1.0 FullScreenAppItem.qml
AppLabelPage 1.0 AppLabelPage.qml
Folder 1.0 Folder.qml Folder 1.0 Folder.qml

View File

@ -36,5 +36,6 @@
<file>AppUI/AppPageSearch.qml</file> <file>AppUI/AppPageSearch.qml</file>
<file>AppUI/FullScreenAppList.qml</file> <file>AppUI/FullScreenAppList.qml</file>
<file>AppUI/FullScreenAppItem.qml</file> <file>AppUI/FullScreenAppItem.qml</file>
<file>AppUI/AppLabelPage.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -17,49 +17,3 @@
*/ */
#include "commons.h" #include "commons.h"
#include <utility>
// ====== LabelItem ====== //
UkuiMenu::LabelItem::LabelItem(bool disable, int index, QString id, QString displayName)
: m_disable(disable), m_index(index), m_id(std::move(id)), m_displayName(std::move(displayName)) {}
bool UkuiMenu::LabelItem::isDisable() const
{
return m_disable;
}
void UkuiMenu::LabelItem::setDisable(bool disable)
{
LabelItem::m_disable = disable;
}
int UkuiMenu::LabelItem::index() const
{
return m_index;
}
void UkuiMenu::LabelItem::setIndex(int index)
{
LabelItem::m_index = index;
}
const QString &UkuiMenu::LabelItem::displayName() const
{
return m_id;
}
void UkuiMenu::LabelItem::setDisplayName(const QString &name)
{
LabelItem::m_id = name;
}
const QString &UkuiMenu::LabelItem::id() const
{
return m_id;
}
void UkuiMenu::LabelItem::setId(const QString &id)
{
m_id = id;
}

View File

@ -23,43 +23,6 @@
namespace UkuiMenu { namespace UkuiMenu {
// 标签项
class LabelItem
{
Q_GADGET
public:
enum PropertyName {
IsDisable = 0,
Index,
Id,
DisplayName
};
LabelItem() = default;
explicit LabelItem(bool disable, int index, QString id, QString displayName);
friend inline bool operator==(const LabelItem& a, const LabelItem& b) {
return QString::compare(a.id(), b.id(), Qt::CaseInsensitive);
}
bool isDisable() const;
void setDisable(bool disable);
int index() const;
void setIndex(int index);
const QString &id() const;
void setId(const QString &id);
const QString &displayName() const;
void setDisplayName(const QString &name);
private:
bool m_disable{true};
int m_index{0};
QString m_id;
QString m_displayName;
};
class Display { class Display {
Q_GADGET Q_GADGET
public: public:

View File

@ -22,6 +22,7 @@
#include "combined-list-model.h" #include "combined-list-model.h"
#include "app-category-model.h" #include "app-category-model.h"
#include "recently-installed-model.h" #include "recently-installed-model.h"
#include "data-entity.h"
#include "event-track.h" #include "event-track.h"
#include <QAction> #include <QAction>
@ -30,13 +31,13 @@
namespace UkuiMenu { namespace UkuiMenu {
AppCategoryPlugin::AppCategoryPlugin(QObject *parent) : AppListPluginInterface(parent) AppCategoryPlugin::AppCategoryPlugin(QObject *parent) : AppListPluginInterface(parent)
, m_dataModel(new CombinedListModel(this)) , m_dataModel(new CombinedListModel(this)), m_labelBottle(new LabelBottle(this))
{ {
auto categoryModel = new AppCategoryModel(this); m_categoryModel = new AppCategoryModel(this);
auto recentlyModel = new RecentlyInstalledModel(this); m_recentlyModel = new RecentlyInstalledModel(this);
m_dataModel->insertSubModel(recentlyModel); m_dataModel->insertSubModel(m_recentlyModel);
m_dataModel->insertSubModel(categoryModel); m_dataModel->insertSubModel(m_categoryModel);
auto categoryAction = new QAction(QIcon::fromTheme("applications-utilities-symbolic"), tr("Category"), this); auto categoryAction = new QAction(QIcon::fromTheme("applications-utilities-symbolic"), tr("Category"), this);
auto firstLatterAction = new QAction(QIcon::fromTheme("ukui-capslock-symbolic"), tr("Letter Sort"), this); auto firstLatterAction = new QAction(QIcon::fromTheme("ukui-capslock-symbolic"), tr("Letter Sort"), this);
@ -45,20 +46,22 @@ AppCategoryPlugin::AppCategoryPlugin(QObject *parent) : AppListPluginInterface(p
firstLatterAction->setCheckable(true); firstLatterAction->setCheckable(true);
connect(categoryAction, &QAction::triggered, this, [=] { connect(categoryAction, &QAction::triggered, this, [=] {
categoryModel->setMode(AppCategoryModel::Category); m_categoryModel->setMode(AppCategoryModel::Category);
categoryAction->setChecked(true); categoryAction->setChecked(true);
firstLatterAction->setChecked(false); firstLatterAction->setChecked(false);
setTitle(categoryAction->text()); setTitle(categoryAction->text());
updateLabelBottle();
QMap<QString, QVariant> map; QMap<QString, QVariant> map;
map.insert(QStringLiteral("viewName"), QStringLiteral("category")); map.insert(QStringLiteral("viewName"), QStringLiteral("category"));
EventTrack::instance()->sendClickEvent("switch_app_view", "AppView", map); EventTrack::instance()->sendClickEvent("switch_app_view", "AppView", map);
}); });
connect(firstLatterAction, &QAction::triggered, this, [=] { connect(firstLatterAction, &QAction::triggered, this, [=] {
categoryModel->setMode(AppCategoryModel::FirstLatter); m_categoryModel->setMode(AppCategoryModel::FirstLatter);
categoryAction->setChecked(false); categoryAction->setChecked(false);
firstLatterAction->setChecked(true); firstLatterAction->setChecked(true);
setTitle(firstLatterAction->text()); setTitle(firstLatterAction->text());
updateLabelBottle();
QMap<QString, QVariant> map; QMap<QString, QVariant> map;
map.insert(QStringLiteral("viewName"), QStringLiteral("letter")); map.insert(QStringLiteral("viewName"), QStringLiteral("letter"));
@ -70,6 +73,7 @@ AppCategoryPlugin::AppCategoryPlugin(QObject *parent) : AppListPluginInterface(p
categoryAction->setChecked(true); categoryAction->setChecked(true);
setTitle(categoryAction->text()); setTitle(categoryAction->text());
m_labelBottle->setColumn(2);
} }
QString AppCategoryPlugin::name() QString AppCategoryPlugin::name()
@ -107,4 +111,33 @@ void AppCategoryPlugin::setTitle(const QString &title)
Q_EMIT titleChanged(); Q_EMIT titleChanged();
} }
LabelBottle *AppCategoryPlugin::labelBottle()
{
updateLabelBottle();
return m_labelBottle;
}
void AppCategoryPlugin::updateLabelBottle()
{
QList<LabelItem> labels;
if (m_recentlyModel->rowCount() > 0) {
labels << LabelItem(tr("Recently Installed"), "search-symbolic", LabelItem::Icon);
}
QHash<QString, int> groups;
int rowCount = m_categoryModel->rowCount();
for (int row = 0; row < rowCount; ++row) {
QString group = m_categoryModel->index(row, 0, QModelIndex()).data(DataEntity::Group).toString();
if (groups.contains(group)) {
continue;
}
groups.insert(group, 0);
labels.append(LabelItem(group, group));
}
m_labelBottle->setLabels(labels);
m_labelBottle->setColumn(m_categoryModel->mode() == AppCategoryModel::FirstLatter ? 5 : 2);
}
} // UkuiMenu } // UkuiMenu

View File

@ -26,6 +26,8 @@
namespace UkuiMenu { namespace UkuiMenu {
class CombinedListModel; class CombinedListModel;
class AppCategoryModel;
class RecentlyInstalledModel;
class AppCategoryPlugin : public AppListPluginInterface class AppCategoryPlugin : public AppListPluginInterface
{ {
@ -38,13 +40,20 @@ public:
QString title() override; QString title() override;
QList<QAction *> actions() override; QList<QAction *> actions() override;
QAbstractItemModel *dataModel() override; QAbstractItemModel *dataModel() override;
LabelBottle *labelBottle() override;
private: private:
void setTitle(const QString &title); void setTitle(const QString &title);
void updateLabelBottle();
private: private:
QString m_title; QString m_title;
QList<QAction *> m_actions; QList<QAction *> m_actions;
LabelBottle *m_labelBottle {nullptr};
AppCategoryModel *m_categoryModel {nullptr};
RecentlyInstalledModel *m_recentlyModel {nullptr};
CombinedListModel *m_dataModel {nullptr}; CombinedListModel *m_dataModel {nullptr};
}; };

View File

@ -194,7 +194,7 @@ QVariant AppGroupModel::data(const QModelIndex &proxyIndex, int role) const
return QAbstractProxyModel::data(proxyIndex, role); return QAbstractProxyModel::data(proxyIndex, role);
} }
if (role == DataEntity::Name) { if (role == DataEntity::Name || role == DataEntity::Group) {
return sourceModel()->index(m_groups.at(proxyIndex.row())->first(), 0).data(DataEntity::Group); return sourceModel()->index(m_groups.at(proxyIndex.row())->first(), 0).data(DataEntity::Group);
} }
@ -345,4 +345,16 @@ void AppGroupModel::onRowsAboutToBeRemoved(const QModelIndex &parent, int first,
} }
} }
int AppGroupModel::findLabelIndex(const QString &label) const
{
int rowCount = AppGroupModel::rowCount(QModelIndex());
for (int i = 0; i < rowCount; ++i) {
if (index(i, 0, QModelIndex()).data(DataEntity::Group).toString() == label) {
return i;
}
}
return -1;
}
} // UkuiMenu } // UkuiMenu

View File

@ -54,6 +54,8 @@ public:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
QVariant data(const QModelIndex &proxyIndex, int role) const override; QVariant data(const QModelIndex &proxyIndex, int role) const override;
Q_INVOKABLE int findLabelIndex(const QString &label) const;
private Q_SLOTS: private Q_SLOTS:
void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles); void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
void onLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint); void onLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint);

View File

@ -128,6 +128,8 @@ void AppListModel::installPlugin(AppListPluginInterface *plugin)
connect(m_plugin, &AppListPluginInterface::titleChanged, this, [this, plugin] { connect(m_plugin, &AppListPluginInterface::titleChanged, this, [this, plugin] {
m_header->setTitle(plugin->title()); m_header->setTitle(plugin->title());
}); });
Q_EMIT labelBottleChanged();
} }
void AppListModel::unInstallPlugin() void AppListModel::unInstallPlugin()
@ -141,6 +143,8 @@ void AppListModel::unInstallPlugin()
QSortFilterProxyModel::setSourceModel(nullptr); QSortFilterProxyModel::setSourceModel(nullptr);
disconnect(m_plugin, nullptr, this, nullptr); disconnect(m_plugin, nullptr, this, nullptr);
m_plugin = nullptr; m_plugin = nullptr;
Q_EMIT labelBottleChanged();
} }
void AppListModel::openMenu(const int &index, MenuInfo::Location location) const void AppListModel::openMenu(const int &index, MenuInfo::Location location) const
@ -151,4 +155,26 @@ void AppListModel::openMenu(const int &index, MenuInfo::Location location) const
} }
} }
LabelBottle *AppListModel::labelBottle() const
{
if (m_plugin) {
return m_plugin->labelBottle();
}
return nullptr;
}
int AppListModel::findLabelIndex(const QString &label) const
{
// TODO: 潜在的优化空间
int count = AppListModel::rowCount();
for (int i = 0; i < count; ++i) {
if (AppListModel::sourceModel()->index(i, 0).data(DataEntity::Group).toString() == label) {
return i;
}
}
return -1;
}
} // UkuiMenu } // UkuiMenu

View File

@ -71,6 +71,7 @@ class AppListModel : public QSortFilterProxyModel
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(UkuiMenu::AppListHeader *header READ getHeader NOTIFY headerChanged) Q_PROPERTY(UkuiMenu::AppListHeader *header READ getHeader NOTIFY headerChanged)
Q_PROPERTY(UkuiMenu::LabelBottle *labelBottle READ labelBottle NOTIFY labelBottleChanged)
public: public:
explicit AppListModel(QObject *parent = nullptr); explicit AppListModel(QObject *parent = nullptr);
@ -81,15 +82,18 @@ public:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
AppListHeader *getHeader() const; AppListHeader *getHeader() const;
LabelBottle *labelBottle() const;
void installPlugin(AppListPluginInterface *plugin); void installPlugin(AppListPluginInterface *plugin);
// reset // reset
void unInstallPlugin(); void unInstallPlugin();
Q_INVOKABLE void openMenu(const int &index, MenuInfo::Location location) const; Q_INVOKABLE void openMenu(const int &index, MenuInfo::Location location) const;
Q_INVOKABLE int findLabelIndex(const QString &label) const;
Q_SIGNALS: Q_SIGNALS:
void headerChanged(); void headerChanged();
void labelBottleChanged();
private: private:
AppListHeader *m_header {nullptr}; AppListHeader *m_header {nullptr};

View File

@ -20,13 +20,15 @@
#include "app-list-plugin.h" #include "app-list-plugin.h"
#include <QDebug> #include <QDebug>
#include <utility>
namespace UkuiMenu { namespace UkuiMenu {
// ====== AppListPluginInterface ====== // // ====== AppListPluginInterface ====== //
AppListPluginInterface::AppListPluginInterface(QObject *parent) : QObject(parent) AppListPluginInterface::AppListPluginInterface(QObject *parent) : QObject(parent)
{ {
qRegisterMetaType<UkuiMenu::LabelItem>("LabelItem");
qRegisterMetaType<UkuiMenu::LabelBottle*>("LabelBottle*");
} }
void AppListPluginInterface::search(const QString &keyword) void AppListPluginInterface::search(const QString &keyword)
@ -34,4 +36,64 @@ void AppListPluginInterface::search(const QString &keyword)
Q_UNUSED(keyword) Q_UNUSED(keyword)
} }
LabelBottle *AppListPluginInterface::labelBottle()
{
return nullptr;
}
// ====== LabelItem ====== //
LabelItem::LabelItem(QString labelName, QString displayName, LabelItem::Type type)
: m_type(type), m_labelName(std::move(labelName)), m_displayName(std::move(displayName))
{
}
QString LabelItem::labelName() const
{
return m_labelName;
}
LabelItem::Type LabelItem::type() const
{
return m_type;
}
QString LabelItem::displayName() const
{
return m_displayName;
}
// ====== LabelBottle ====== //
LabelBottle::LabelBottle(QObject *parent) : QObject(parent)
{
}
int LabelBottle::column() const
{
return m_column;
}
QList<UkuiMenu::LabelItem> LabelBottle::labels() const
{
return m_labels;
}
void LabelBottle::setColumn(int column)
{
if (m_column == column) {
return;
}
m_column = column;
Q_EMIT columnChanged();
}
void LabelBottle::setLabels(const QList<UkuiMenu::LabelItem> &labels)
{
m_labels.clear();
m_labels.append(labels);
Q_EMIT labelsChanged();
}
} // UkuiMenu } // UkuiMenu

View File

@ -29,6 +29,54 @@ class QAbstractItemModel;
namespace UkuiMenu { namespace UkuiMenu {
class LabelItem
{
Q_GADGET
Q_PROPERTY(UkuiMenu::LabelItem::Type type READ type)
Q_PROPERTY(QString label READ labelName)
Q_PROPERTY(QString display READ displayName)
public:
enum Type {
Text,
Icon
};
Q_ENUM(Type)
explicit LabelItem(QString labelName = "", QString displayName = "", Type type = Text);
Type type() const;
QString labelName() const;
QString displayName() const;
private:
Type m_type;
QString m_labelName;
QString m_displayName;
};
class LabelBottle : public QObject
{
Q_OBJECT
Q_PROPERTY(int column READ column NOTIFY columnChanged)
Q_PROPERTY(QList<UkuiMenu::LabelItem> labels READ labels NOTIFY labelsChanged)
public:
explicit LabelBottle(QObject *parent = nullptr);
int column() const;
QList<UkuiMenu::LabelItem> labels() const;
void setColumn(int column);
void setLabels(const QList<UkuiMenu::LabelItem> &labels);
Q_SIGNALS:
void columnChanged();
void labelsChanged();
private:
int m_column {2};
QList<LabelItem> m_labels;
};
class AppListPluginGroup class AppListPluginGroup
{ {
Q_GADGET Q_GADGET
@ -52,6 +100,7 @@ public:
virtual QList<QAction*> actions() = 0; virtual QList<QAction*> actions() = 0;
virtual QAbstractItemModel *dataModel() = 0; virtual QAbstractItemModel *dataModel() = 0;
virtual void search(const QString &keyword); virtual void search(const QString &keyword);
virtual LabelBottle *labelBottle();
Q_SIGNALS: Q_SIGNALS:
void titleChanged(); void titleChanged();
@ -60,5 +109,7 @@ Q_SIGNALS:
} // UkuiMenu } // UkuiMenu
Q_DECLARE_METATYPE(UkuiMenu::AppListPluginGroup::Group) Q_DECLARE_METATYPE(UkuiMenu::AppListPluginGroup::Group)
Q_DECLARE_METATYPE(UkuiMenu::LabelItem)
Q_DECLARE_METATYPE(UkuiMenu::LabelBottle*)
#endif //UKUI_MENU_APP_LIST_PLUGIN_H #endif //UKUI_MENU_APP_LIST_PLUGIN_H

View File

@ -86,7 +86,7 @@ bool RecentlyInstalledModel::event(QEvent *event)
QVariant RecentlyInstalledModel::data(const QModelIndex &index, int role) const QVariant RecentlyInstalledModel::data(const QModelIndex &index, int role) const
{ {
if (role == DataEntity::Group) { if (role == DataEntity::Group) {
return QStringLiteral("RecentlyInstalled"); return tr("Recently Installed");
} }
return QSortFilterProxyModel::data(index, role); return QSortFilterProxyModel::data(index, role);

View File

@ -74,6 +74,7 @@ void UkuiMenuApplication::registerQmlTypes()
qmlRegisterUncreatableType<Display>(uri, versionMajor, versionMinor, "Display", "Use enums only."); qmlRegisterUncreatableType<Display>(uri, versionMajor, versionMinor, "Display", "Use enums only.");
qmlRegisterUncreatableType<UkuiMenu::DataType>(uri, versionMajor, versionMinor, "DataType", "Use enums only"); qmlRegisterUncreatableType<UkuiMenu::DataType>(uri, versionMajor, versionMinor, "DataType", "Use enums only");
qmlRegisterUncreatableType<UkuiMenu::MenuInfo>(uri, versionMajor, versionMinor, "MenuInfo", "Use enums only."); qmlRegisterUncreatableType<UkuiMenu::MenuInfo>(uri, versionMajor, versionMinor, "MenuInfo", "Use enums only.");
qmlRegisterUncreatableType<UkuiMenu::LabelItem>(uri, versionMajor, versionMinor, "LabelItem", "Use enums only.");
// qmlRegisterUncreatableType<UkuiMenu::DataEntity>(uri, versionMajor, versionMinor, "DataEntity", "unknown"); // qmlRegisterUncreatableType<UkuiMenu::DataEntity>(uri, versionMajor, versionMinor, "DataEntity", "unknown");
qmlRegisterUncreatableType<EventTrack>(uri, versionMajor, versionMinor, "EventTrack", "Attached only."); qmlRegisterUncreatableType<EventTrack>(uri, versionMajor, versionMinor, "EventTrack", "Attached only.");