feat: 左侧应用区添加批量编辑功能

This commit is contained in:
youdiansaodongxi 2023-12-07 10:59:26 +08:00 committed by hewenfei
parent 1c86a7a981
commit dd31bd9822
17 changed files with 113 additions and 74 deletions

View File

@ -2,6 +2,7 @@ import QtQuick 2.12
import QtQuick.Layouts 1.12 import QtQuick.Layouts 1.12
import QtQuick.Controls 2.5 import QtQuick.Controls 2.5
import org.ukui.menu.core 1.0 import org.ukui.menu.core 1.0
import org.ukui.quick.items 1.0 as UkuiItems
MouseArea { MouseArea {
id: control id: control
@ -11,36 +12,20 @@ MouseArea {
when: control.activeFocus when: control.activeFocus
PropertyChanges { PropertyChanges {
target: controlBase target: controlBase
borderColor: Palette.Highlight borderColor: UkuiItems.Theme.Highlight
border.width: 2 border.width: 2
} }
} }
ToolTip { UkuiItems.StyleBackground {
property bool isVisible: controlBase.isTextTruncated && control.containsMouse
id: tip
x: mouseX + 15
y: mouseY + 15
text: name
visible: controlBase.isTextTruncated && control.containsMouse
delay: 500
}
onPositionChanged: {
if (tip.isVisible) {
if (tip.visible) {
tip.hide();
} else {
tip.show(name);
}
}
}
StyleBackground {
property bool isTextTruncated: content.textTruncated
id: controlBase id: controlBase
anchors.fill: parent anchors.fill: parent
radius: 4 radius: 4
useStyleTransparent: false useStyleTransparency: false
paletteRole: Palette.Light paletteRole: UkuiItems.Theme.Text
alpha: isSelect ? 1.00 : control.containsPress ? 0.82 : control.containsMouse ? 0.55 : 0.00 alpha: isSelect ? 1.00 : control.containsPress ? 0.16 : control.containsMouse ? 0.08 : 0.00
ToolTip.visible: content.textTruncated && control.containsMouse
ToolTip.text: name
ToolTip.delay: 500
RowLayout { RowLayout {
anchors.fill: parent anchors.fill: parent
@ -60,36 +45,34 @@ MouseArea {
Loader { Loader {
id: tag id: tag
property bool recentInsatlled: (recentInstall === undefined) ? false : recentInstall visible: mainWindow.editMode
property bool fixToTop: (toTop !== undefined) && (toTop !== 0)
visible: fixToTop || recentInsatlled
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Layout.maximumWidth: visible ? 16 : 0 Layout.maximumWidth: visible ? 28 : 0
Layout.maximumHeight: width Layout.maximumHeight: width
Layout.rightMargin: visible ? 25 : 0 Layout.rightMargin: visible ? 4 : 0
Component { Component {
id: tagImage id: editImage
Image { UkuiItems.Button {
source: "image://appicon/ukui-fixed-symbolic" width: 28
} height: 28
} icon.width: 16
icon.height: 16
background.paletteRole: UkuiItems.Theme.Light
background.alpha: 1
activeFocusOnTab: false
Component { onClicked: {
id: tagPoint appManager.changeFavoriteState(id, favorite);
Item {
StyleBackground {
anchors.centerIn: parent
width: 8; height: width
radius: width / 2
paletteRole: Palette.Highlight
useStyleTransparent: false
} }
background.radius: width / 2
icon.source: favorite ? "ukui-cancel-star-symbolic" : "non-starred-symbolic"
} }
} }
sourceComponent: tag.fixToTop ? tagImage : tag.recentInsatlled ? tagPoint : null sourceComponent: mainWindow.editMode ? editImage : null
} }
} }
} }

View File

@ -67,8 +67,7 @@ Item {
property string name: model.name property string name: model.name
property string icon: model.icon property string icon: model.icon
property string comment: model.comment // label tooltip property string comment: model.comment // label tooltip
property int toTop: model.top property bool favorite: model.favorite
property bool recentInstall: model.recentInstall
sourceComponent: { sourceComponent: {
if (type === DataType.Normal) { if (type === DataType.Normal) {
return appItemComponent; return appItemComponent;

View File

@ -35,7 +35,7 @@ public:
Q_SIGNALS: Q_SIGNALS:
void appAdded(QList<DataEntity> apps); void appAdded(QList<DataEntity> apps);
void appUpdated(QList<DataEntity> apps); void appUpdated(QList<DataEntity> apps, bool totalUpdate);
void appDeleted(QStringList idList); void appDeleted(QStringList idList);
void favoriteAppChanged(); void favoriteAppChanged();
void appDataBaseOpenFailed(); void appDataBaseOpenFailed();
@ -56,7 +56,7 @@ public Q_SLOTS:
private: private:
void updateFavoriteApps(); void updateFavoriteApps();
void removeApps(QStringList& appIdList, QStringList &removedIdList); void removeApps(QStringList& appIdList, QStringList &removedIdList);
void updateApps(const UkuiSearch::ApplicationInfoMap &infos, QList<DataEntity> &apps); bool updateApps(const UkuiSearch::ApplicationInfoMap &infos, QList<DataEntity> &apps);
void updateAppsAll(const QStringList &infos, QList<DataEntity> &apps); void updateAppsAll(const QStringList &infos, QList<DataEntity> &apps);
void appendApps(const QStringList &infos, QList<DataEntity> &apps); void appendApps(const QStringList &infos, QList<DataEntity> &apps);
void addInfoToApp(const UkuiSearch::ApplicationPropertyMap &info, DataEntity &app); void addInfoToApp(const UkuiSearch::ApplicationPropertyMap &info, DataEntity &app);
@ -211,11 +211,11 @@ void AppDataWorker::onAppUpdated(const UkuiSearch::ApplicationInfoMap &infos)
} }
QList<DataEntity> apps; QList<DataEntity> apps;
updateApps(infos, apps); bool totalUpdate = updateApps(infos, apps);
if (apps.isEmpty()) { if (apps.isEmpty()) {
return; return;
} }
Q_EMIT appUpdated(apps); Q_EMIT appUpdated(apps, totalUpdate);
updateFavoriteApps(); updateFavoriteApps();
} }
@ -231,18 +231,18 @@ void AppDataWorker::onAppUpdatedAll(const QStringList &infos)
if (apps.isEmpty()) { if (apps.isEmpty()) {
return; return;
} }
Q_EMIT appUpdated(apps); Q_EMIT appUpdated(apps, true);
updateFavoriteApps(); updateFavoriteApps();
} }
void AppDataWorker::updateApps(const UkuiSearch::ApplicationInfoMap &infos, QList<DataEntity> &apps) bool AppDataWorker::updateApps(const UkuiSearch::ApplicationInfoMap &infos, QList<DataEntity> &apps)
{ {
QMutexLocker locker(&m_appManager->m_mutex); QMutexLocker locker(&m_appManager->m_mutex);
if (infos.isEmpty()) { if (infos.isEmpty()) {
return; return false;
} }
bool totalUpdate = false;
for (const QString &info : infos.keys()) { for (const QString &info : infos.keys()) {
if (m_appManager->m_normalApps.contains(info)) { if (m_appManager->m_normalApps.contains(info)) {
DataEntity &app = m_appManager->m_normalApps[info]; DataEntity &app = m_appManager->m_normalApps[info];
@ -271,9 +271,11 @@ void AppDataWorker::updateApps(const UkuiSearch::ApplicationInfoMap &infos, QLis
break; break;
case UkuiSearch::ApplicationProperty::Property::Category: case UkuiSearch::ApplicationProperty::Property::Category:
app.setCategory(infos.value(info).value(UkuiSearch::ApplicationProperty::Property::Category).toString()); app.setCategory(infos.value(info).value(UkuiSearch::ApplicationProperty::Property::Category).toString());
totalUpdate = true;
break; break;
case UkuiSearch::ApplicationProperty::Property::FirstLetterAll: case UkuiSearch::ApplicationProperty::Property::FirstLetterAll:
app.setFirstLetter(infos.value(info).value(UkuiSearch::ApplicationProperty::Property::FirstLetterAll).toString()); app.setFirstLetter(infos.value(info).value(UkuiSearch::ApplicationProperty::Property::FirstLetterAll).toString());
totalUpdate = true;
break; break;
case UkuiSearch::ApplicationProperty::Property::InsertTime: case UkuiSearch::ApplicationProperty::Property::InsertTime:
app.setInsertTime(infos.value(info).value(UkuiSearch::ApplicationProperty::Property::InsertTime).toString()); app.setInsertTime(infos.value(info).value(UkuiSearch::ApplicationProperty::Property::InsertTime).toString());
@ -288,6 +290,7 @@ void AppDataWorker::updateApps(const UkuiSearch::ApplicationInfoMap &infos, QLis
apps.append(app); apps.append(app);
} }
} }
return totalUpdate;
} }
void AppDataWorker::updateAppsAll(const QStringList &infos, QList<DataEntity> &apps) void AppDataWorker::updateAppsAll(const QStringList &infos, QList<DataEntity> &apps)

View File

@ -52,7 +52,7 @@ public:
Q_SIGNALS: Q_SIGNALS:
void appAdded(QList<DataEntity> apps); void appAdded(QList<DataEntity> apps);
void appUpdated(QList<DataEntity> apps); void appUpdated(QList<DataEntity> apps, bool totalUpdate);
void appDeleted(QStringList idList); void appDeleted(QStringList idList);
void appDataChanged(); void appDataChanged();
void favoriteAppChanged(); void favoriteAppChanged();

View File

@ -49,7 +49,8 @@ public:
Reset = 0, Reset = 0,
Append, Append,
Prepend, Prepend,
Insert Insert,
Update
}; };
Q_ENUM(Mode) Q_ENUM(Mode)
}; };

View File

@ -52,6 +52,7 @@ AppCategoryPlugin::AppCategoryPlugin() : d(new AppCategoryPluginPrivate)
connect(AppDataManager::instance(), &AppDataManager::appAdded, this, &AppCategoryPlugin::onAppAdded); connect(AppDataManager::instance(), &AppDataManager::appAdded, this, &AppCategoryPlugin::onAppAdded);
connect(AppDataManager::instance(), &AppDataManager::appDeleted, this, &AppCategoryPlugin::onAppDeleted); connect(AppDataManager::instance(), &AppDataManager::appDeleted, this, &AppCategoryPlugin::onAppDeleted);
connect(AppDataManager::instance(), &AppDataManager::appUpdated, this, &AppCategoryPlugin::onAppUpdated);
} }
AppCategoryPlugin::~AppCategoryPlugin() AppCategoryPlugin::~AppCategoryPlugin()
@ -238,4 +239,14 @@ void AppCategoryPlugin::onAppDeleted(const QStringList& idList)
Q_EMIT labelChanged(); Q_EMIT labelChanged();
} }
void AppCategoryPlugin::onAppUpdated(const QList<DataEntity> &apps, bool totalUpdate)
{
if (totalUpdate) {
reLoadApps();
updateData();
} else {
Q_EMIT dataChanged(apps.toVector(), DataUpdateMode::Update);
}
}
} // UkuiMenu } // UkuiMenu

View File

@ -45,6 +45,7 @@ public:
private Q_SLOTS: private Q_SLOTS:
void onAppAdded(const QList<DataEntity>& apps); void onAppAdded(const QList<DataEntity>& apps);
void onAppDeleted(const QStringList& idList); void onAppDeleted(const QStringList& idList);
void onAppUpdated(const QList<DataEntity>& apps, bool totalUpdate);
private: private:
void reLoadApps(); void reLoadApps();

View File

@ -88,10 +88,13 @@ void AppLetterSortPlugin::onAppDeleted(QStringList idList)
updateAppData(); updateAppData();
} }
void AppLetterSortPlugin::onAppUpdated(const QList<DataEntity> &apps) void AppLetterSortPlugin::onAppUpdated(const QList<DataEntity> &apps, bool totalUpdate)
{ {
Q_UNUSED(apps); if (totalUpdate) {
updateAppData(); updateAppData();
} else {
Q_EMIT dataChanged(apps.toVector(), DataUpdateMode::Update);
}
} }
void AppLetterSortPlugin::updateAppData() void AppLetterSortPlugin::updateAppData()

View File

@ -42,7 +42,7 @@ public:
private Q_SLOTS: private Q_SLOTS:
void onAppAdded(const QList<DataEntity>& apps); void onAppAdded(const QList<DataEntity>& apps);
void onAppDeleted(QStringList idList); void onAppDeleted(QStringList idList);
void onAppUpdated(const QList<DataEntity>& apps); void onAppUpdated(const QList<DataEntity>& apps, bool totalUpdate);
private: private:
void updateAppData(); void updateAppData();

View File

@ -222,8 +222,7 @@ QHash<int, QByteArray> DataEntity::AppRoleNames()
names.insert(DataEntity::Name, "name"); names.insert(DataEntity::Name, "name");
names.insert(DataEntity::Comment, "comment"); names.insert(DataEntity::Comment, "comment");
names.insert(DataEntity::ExtraData, "extraData"); names.insert(DataEntity::ExtraData, "extraData");
names.insert(DataEntity::Top, "top"); names.insert(DataEntity::Favorite, "favorite");
names.insert(DataEntity::RecentInstall, "recentInstall");
return names; return names;
} }

View File

@ -58,8 +58,7 @@ public:
Name, Name,
Comment, Comment,
ExtraData, ExtraData,
Top, Favorite
RecentInstall
}; };
DataEntity(); DataEntity();
DataEntity(DataType::Type type, const QString& name, const QString& icon, const QString& comment, const QString& extraData); DataEntity(DataType::Type type, const QString& name, const QString& icon, const QString& comment, const QString& extraData);

View File

@ -60,16 +60,8 @@ QVariant AppModel::data(const QModelIndex &index, int role) const
return m_apps.at(i).comment(); return m_apps.at(i).comment();
case DataEntity::ExtraData: case DataEntity::ExtraData:
return m_apps.at(i).extraData(); return m_apps.at(i).extraData();
case DataEntity::Top: case DataEntity::Favorite:
if (DataProviderManager::instance()->activatedProvider() == "all") { return m_apps.at(i).favorite() == 0 ? false : true;
return m_apps.at(i).top();
}
return 0;
case DataEntity::RecentInstall:
if (DataProviderManager::instance()->activatedProvider() == "all") {
return m_apps.at(i).isRecentInstall();
}
return false;
default: default:
break; break;
} }
@ -156,6 +148,10 @@ void AppModel::onPluginDataChanged(QVector<DataEntity> data, DataUpdateMode::Mod
insertData(data, static_cast<int>(index)); insertData(data, static_cast<int>(index));
break; break;
} }
case DataUpdateMode::Update: {
updateData(data);
break;
}
} }
} }
@ -197,6 +193,19 @@ void AppModel::insertData(QVector<DataEntity> &data, int index)
Q_EMIT endInsertRows(); Q_EMIT endInsertRows();
} }
void AppModel::updateData(QVector<DataEntity> &data)
{
for (const DataEntity &item : data) {
for (int i = 0; i < m_apps.length(); i++) {
if (item.id() == m_apps.at(i).id()) {
m_apps.replace(i, item);
Q_EMIT dataChanged(index(i, 0), index(i, 0));
break;
}
}
}
}
void AppModel::openMenu(const int &index, MenuInfo::Location location) void AppModel::openMenu(const int &index, MenuInfo::Location location)
{ {
if (index < 0 || index >= m_apps.size()) { if (index < 0 || index >= m_apps.size()) {

View File

@ -61,6 +61,7 @@ private:
void appendData(QVector<DataEntity> &data); void appendData(QVector<DataEntity> &data);
void prependData(QVector<DataEntity> &data); void prependData(QVector<DataEntity> &data);
void insertData(QVector<DataEntity> &data, int index); void insertData(QVector<DataEntity> &data, int index);
void updateData(QVector<DataEntity> &data);
private: private:
QVector<DataEntity> m_apps; QVector<DataEntity> m_apps;

View File

@ -113,6 +113,15 @@ void AppManager::launchAppWithArguments(const QString &desktopFile, const QStrin
}); });
} }
void AppManager::changeFavoriteState(const QString &desktopFilePath, bool isFavorite)
{
if (isFavorite) {
Q_EMIT AppDataManager::instance()->fixToFavoriteSignal(desktopFilePath, 0);
} else {
Q_EMIT AppDataManager::instance()->fixToFavoriteSignal(desktopFilePath, 1);
}
}
QString AppManager::parseDesktopFile(const QString &desktopFilePath) QString AppManager::parseDesktopFile(const QString &desktopFilePath)
{ {
// TODO: try QSettings? // TODO: try QSettings?

View File

@ -36,6 +36,7 @@ public:
Q_INVOKABLE void launchApp(const QString &desktopFilePath); Q_INVOKABLE void launchApp(const QString &desktopFilePath);
Q_INVOKABLE void launchBinaryApp(const QString &app, const QString &args = QString()); Q_INVOKABLE void launchBinaryApp(const QString &app, const QString &args = QString());
Q_INVOKABLE void launchAppWithArguments(const QString &desktopFile, const QStringList &args, const QString &applicationName); Q_INVOKABLE void launchAppWithArguments(const QString &desktopFile, const QStringList &args, const QString &applicationName);
Q_INVOKABLE void changeFavoriteState(const QString &desktopFilePath, bool isFavorite);
private: private:
explicit AppManager(QObject *parent = nullptr); explicit AppManager(QObject *parent = nullptr);

View File

@ -550,4 +550,19 @@ int MenuWindow::panelPos() const
return m_geometryHelper->getPanelPos(); return m_geometryHelper->getPanelPos();
} }
bool MenuWindow::editMode() const
{
return m_editMode;
}
void MenuWindow::setEditMode(bool mode)
{
if (mode == m_editMode) {
return;
}
m_editMode = mode;
Q_EMIT editModeChanged();
}
} // UkuiMenu } // UkuiMenu

View File

@ -107,6 +107,7 @@ class MenuWindow : public QQuickView
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool isFullScreen READ isFullScreen WRITE setFullScreen NOTIFY fullScreenChanged) Q_PROPERTY(bool isFullScreen READ isFullScreen WRITE setFullScreen NOTIFY fullScreenChanged)
Q_PROPERTY(bool effectEnabled READ effectEnabled NOTIFY effectEnabledChanged) Q_PROPERTY(bool effectEnabled READ effectEnabled NOTIFY effectEnabledChanged)
Q_PROPERTY(bool editMode READ editMode WRITE setEditMode NOTIFY editModeChanged)
Q_PROPERTY(double transparency READ transparency NOTIFY transparencyChanged) Q_PROPERTY(double transparency READ transparency NOTIFY transparencyChanged)
Q_PROPERTY(int panelPos READ panelPos NOTIFY panelPosChanged) Q_PROPERTY(int panelPos READ panelPos NOTIFY panelPosChanged)
@ -119,6 +120,8 @@ public:
double transparency() const; double transparency() const;
void setFullScreen(bool isFullScreen); void setFullScreen(bool isFullScreen);
int panelPos() const; int panelPos() const;
bool editMode() const;
void setEditMode(bool mode);
Q_INVOKABLE void changeWindowBlurRegion(int x, int y, int width, int height); Q_INVOKABLE void changeWindowBlurRegion(int x, int y, int width, int height);
Q_INVOKABLE QRect normalScreenSize(); Q_INVOKABLE QRect normalScreenSize();
@ -132,6 +135,7 @@ Q_SIGNALS:
void beforeFullScreenChanged(); void beforeFullScreenChanged();
void beforeFullScreenExited(); void beforeFullScreenExited();
void panelPosChanged(); void panelPosChanged();
void editModeChanged();
protected: protected:
void exposeEvent(QExposeEvent *event) override; void exposeEvent(QExposeEvent *event) override;
@ -144,6 +148,7 @@ private:
void updateGeometry(); void updateGeometry();
private: private:
bool m_editMode {false};
bool m_isFullScreen{false}; bool m_isFullScreen{false};
WindowGeometryHelper *m_geometryHelper{nullptr}; WindowGeometryHelper *m_geometryHelper{nullptr};
}; };