From fb5564708151b0ca9cedcef5a8b908c225b4d09c Mon Sep 17 00:00:00 2001 From: Wang Zichong Date: Sat, 16 Nov 2024 17:30:43 +0800 Subject: [PATCH] refactor: assign appgroup data keep synced MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 之前的 groupmanager 管理分组内 item 的逻辑问题比较多,依次处理后仍然发现行为不符合预期,故决定直接复用启动器现有的分组管理逻辑(略有调整以对接原有 dconfig 配置)。 此提交起,应用信息即会自动分配分组(新应用分配到顶层分组,即编号 0 的文件夹,原有已知存在分组的应用保持不变),应用模型变动时即存储信息回 dconfig。 Log: --- applets/dde-apps/CMakeLists.txt | 2 + applets/dde-apps/amappitemmodel.cpp | 1 - applets/dde-apps/appgroup.cpp | 50 +++-- applets/dde-apps/appgroup.h | 14 +- applets/dde-apps/appgroupmanager.cpp | 190 ++++++++++------ applets/dde-apps/appgroupmanager.h | 19 +- applets/dde-apps/itemspage.cpp | 284 ++++++++++++++++++++++++ applets/dde-apps/itemspage.h | 62 ++++++ panels/dock/taskmanager/taskmanager.cpp | 1 + 9 files changed, 525 insertions(+), 98 deletions(-) create mode 100644 applets/dde-apps/itemspage.cpp create mode 100644 applets/dde-apps/itemspage.h diff --git a/applets/dde-apps/CMakeLists.txt b/applets/dde-apps/CMakeLists.txt index 922889ef7..e21172bd5 100644 --- a/applets/dde-apps/CMakeLists.txt +++ b/applets/dde-apps/CMakeLists.txt @@ -53,6 +53,8 @@ add_library(dde-apps SHARED ${DBUS_INTERFACES} appslaunchtimes.h categoryutils.cpp categoryutils.h + itemspage.cpp + itemspage.h ) target_link_libraries(dde-apps PRIVATE diff --git a/applets/dde-apps/amappitemmodel.cpp b/applets/dde-apps/amappitemmodel.cpp index 8d14ec53a..522e0a57f 100644 --- a/applets/dde-apps/amappitemmodel.cpp +++ b/applets/dde-apps/amappitemmodel.cpp @@ -10,7 +10,6 @@ #include #include -#include Q_LOGGING_CATEGORY(appsLog, "dde.shell.dde-apps.amappitemmodel") diff --git a/applets/dde-apps/appgroup.cpp b/applets/dde-apps/appgroup.cpp index da0c60368..e01b9e4d8 100644 --- a/applets/dde-apps/appgroup.cpp +++ b/applets/dde-apps/appgroup.cpp @@ -5,6 +5,7 @@ #include "appgroup.h" #include "appgroupmanager.h" #include "appitemmodel.h" +#include "itemspage.h" #include #include @@ -14,38 +15,36 @@ Q_LOGGING_CATEGORY(appGroupLog, "org.deepin.ds.dde-apps.appgroup") namespace apps { AppGroup::AppGroup(const QString &groupId, const QString &name, const QList &appIDs) : AppItem(groupId, AppItemModel::FolderItemType) + , m_itemsPage(new ItemsPage(name, groupId == QStringLiteral("internal/folder/0") ? (4 * 8) : (3 * 4))) { - if (groupId == QStringLiteral("internal/folder/0")) { - setItemsPerPage(4 * 8); - } else { - setItemsPerPage(3 * 4); + setItemsPerPage(m_itemsPage->maxItemCountPerPage()); + setAppName(m_itemsPage->name()); + // folder id is a part of its groupId: "internal/folder/{folderId}" + setFolderId(groupId.section('/', -1).toInt()); + + for (const QStringList &items : appIDs) { + m_itemsPage->appendPage(items); } - setAppName(name); - setAppItems(appIDs); } -QList AppGroup::appItems() const +AppGroup::~AppGroup() { - QList res; - auto pages = data(AppGroupManager::GroupAppItemsRole).toList(); - std::transform(pages.begin(), pages.end(), std::back_inserter(res), [](const QVariant &data) { - return data.toStringList(); - }); + delete m_itemsPage; +} - return res; +int AppGroup::folderId() const +{ + return data(AppGroupManager::GroupIdRole).toInt(); } -void AppGroup::setAppItems(const QList &items) +QList AppGroup::pages() const { - QVariantList data; - std::transform(items.begin(), items.end(), std::back_inserter(data), [](const QStringList &c) { - QVariantList tmp; - std::transform(c.begin(), c.end(), std::back_inserter(tmp), [](const QString &s) { - return s; - }); - return tmp; - }); - return setData(data, AppGroupManager::GroupAppItemsRole); + return m_itemsPage->allPagedItems(); +} + +ItemsPage *AppGroup::itemsPage() +{ + return m_itemsPage; } void AppGroup::setItemsPerPage(int number) @@ -53,5 +52,10 @@ void AppGroup::setItemsPerPage(int number) return setData(number, AppGroupManager::GroupItemsPerPageRole); } +void AppGroup::setFolderId(int folderId) +{ + setData(folderId, AppGroupManager::GroupIdRole); +} + } diff --git a/applets/dde-apps/appgroup.h b/applets/dde-apps/appgroup.h index 84506eaec..a735d5a8b 100644 --- a/applets/dde-apps/appgroup.h +++ b/applets/dde-apps/appgroup.h @@ -6,18 +6,22 @@ #include "appitem.h" +class ItemsPage; namespace apps { class AppGroup : public AppItem { public: explicit AppGroup(const QString &groupId, const QString &name, const QList &appItemIDs); + ~AppGroup() override; - QString name() const; - void setName(const QString &name); - - QList appItems() const; - void setAppItems(const QList &items); + int folderId() const; + QList pages() const; + ItemsPage * itemsPage(); +private: void setItemsPerPage(int number); + void setFolderId(int folderId); + + ItemsPage * m_itemsPage; }; } diff --git a/applets/dde-apps/appgroupmanager.cpp b/applets/dde-apps/appgroupmanager.cpp index c3144aea6..dd3342853 100644 --- a/applets/dde-apps/appgroupmanager.cpp +++ b/applets/dde-apps/appgroupmanager.cpp @@ -4,9 +4,10 @@ #include "appgroupmanager.h" #include "appgroup.h" +#include "itemspage.h" #include "amappitemmodel.h" -#include +#define TOPLEVEL_FOLDERID 0 namespace apps { @@ -21,10 +22,18 @@ AppGroupManager::AppGroupManager(AMAppItemModel * referenceModel, QObject *paren loadAppGroupInfo(); + connect(m_referenceModel, &AMAppItemModel::rowsInserted, this, [this](){ + onReferenceModelChanged(); + saveAppGroupInfo(); + }); + connect(m_referenceModel, &AMAppItemModel::rowsRemoved, this, [this](){ + onReferenceModelChanged(); + saveAppGroupInfo(); + }); connect(m_dumpTimer, &QTimer::timeout, this, [this](){ - dumpAppGroupInfo(); + saveAppGroupInfo(); }); - connect(this, &AppGroupManager::dataChanged, this, &AppGroupManager::dumpAppGroupInfo); + connect(this, &AppGroupManager::dataChanged, this, &AppGroupManager::saveAppGroupInfo); } QVariant AppGroupManager::data(const QModelIndex &index, int role) const @@ -39,85 +48,134 @@ QVariant AppGroupManager::data(const QModelIndex &index, int role) const return QStandardItemModel::data(index, role); } -std::tuple AppGroupManager::getAppGroupInfo(const QString &appId) +// Find the item's location. If folderId is -1, search all folders. +std::tuple AppGroupManager::findItem(const QString &appId, int folderId) { - std::tuple res = {-1, -1, -1}; - do { - int groupPos, pagePos; - std::tie(groupPos, pagePos) = m_map.value(appId, std::make_tuple(-1, -1)); - auto groupIndex = index(groupPos, 0); - - if (!groupIndex.isValid()) - break; + int page, idx; - auto pages = groupIndex.data(GroupAppItemsRole).toList(); - if (pages.length() == 0) - break; - - auto items = pages.value(pagePos).toStringList(); - if (items.length() == 0) - break; - - auto itemPos = items.indexOf(appId); - res = std::make_tuple(groupPos, pagePos, itemPos); - } while (0); + for (int i = 0; i < rowCount(); i++) { + auto group = static_cast(itemFromIndex(index(i, 0))); + if (folderId >= 0 && group->folderId() != folderId) { + continue; + } + std::tie(page, idx) = group->itemsPage()->findItem(appId); + if (page != -1) { + return std::make_tuple(group->folderId(), page, idx); + } + } - return res; + return std::make_tuple(-1, -1, -1); } -void AppGroupManager::setAppGroupInfo(const QString &appId, std::tuple groupInfo) +void AppGroupManager::appendItemToGroup(const QString &appId, int groupId) { - int groupPos, pagePos, itemPos; - std::tie(groupPos, pagePos, itemPos) = groupInfo; - - auto groupIndex = index(groupPos, 0); - if (!groupIndex.isValid()) { - return; - } - - auto appItems = groupIndex.data(GroupAppItemsRole).value>(); - int groupItemsPerPage = groupIndex.data(GroupItemsPerPageRole).toInt(); - - for (int i = pagePos; i < appItems.length() - 1; i++) { - appItems[i].insert(itemPos, appId); - m_map.insert(appId, std::make_tuple(groupPos, pagePos)); + auto folder = group(groupId); + Q_CHECK_PTR(folder); + folder->itemsPage()->appendItem(appId); +} - // 本页最后一位元素插入到下页 - if (appItems[i].length() > groupItemsPerPage) { - auto item = appItems[i].takeLast(); +bool AppGroupManager::removeItemFromGroup(const QString &appId, int groupId) +{ + auto folder = group(groupId); + Q_CHECK_PTR(folder); + return folder->itemsPage()->removeItem(appId); +} - appItems[i + 1].insert(0, item); - m_map.insert(item, std::make_tuple(groupPos, i + 1)); +QModelIndex AppGroupManager::groupIndexById(int groupId) +{ + for (int i = 0; i < rowCount(); i++) { + auto groupIndex = index(i, 0); + auto data = groupIndex.data(GroupIdRole); + if (data.toInt() == groupId) { + return groupIndex; } } + return QModelIndex(); +} - if (appItems.length() > 1 && appItems.last().length() > groupItemsPerPage) { - auto item = appItems.last().takeLast(); - appItems.append({item}); +AppGroup * AppGroupManager::group(int groupId) +{ + auto groupIndex = groupIndexById(groupId); + if (!groupIndex.isValid()) { + return nullptr; } + auto group = static_cast(itemFromIndex(groupIndex)); + return group; +} - if (pagePos > appItems.length()) { - appItems.append({appId}); +AppGroup * AppGroupManager::group(QModelIndex idx) +{ + if (!idx.isValid()) { + return nullptr; } + auto group = static_cast(itemFromIndex(idx)); + return group; +} +QVariantList AppGroupManager::fromListOfStringList(const QList & list) +{ QVariantList data; - std::transform(appItems.begin(), appItems.end(), std::back_inserter(data), [](const QStringList &items) { + std::transform(list.begin(), list.end(), std::back_inserter(data), [](const QStringList &items) { QVariantList tmp; std::transform(items.begin(), items.end(), std::back_inserter(tmp), [](const auto &item) { return QVariant::fromValue(item); }); - return tmp; + return items; }); - setData(groupIndex, data); + return data; +} + +// On AM model changed, add newly installed apps to group (if any) and remove apps that are no longer exists. +void AppGroupManager::onReferenceModelChanged() +{ + // Avoid remove all existing records when first time (AM model is not ready). + if (m_referenceModel->rowCount() == 0) { + qDebug() << "referenceModel not ready, wait for next time"; + return; + } + + QSet appSet; + for (int i = 0; i < m_referenceModel->rowCount(); i++) { + const auto modelIndex = m_referenceModel->index(i, 0); + const bool noDisplay = m_referenceModel->data(modelIndex, AppItemModel::NoDisplayRole).toBool(); + if (noDisplay) { + continue; + } + const QString & desktopId = m_referenceModel->data(m_referenceModel->index(i, 0), AppItemModel::DesktopIdRole).toString(); + appSet.insert(desktopId); + // add all existing ones if they are not already in + int folder, page, idx; + std::tie(folder, std::ignore, std::ignore) = findItem(desktopId); + if (folder == -1) { + appendItemToGroup(desktopId, TOPLEVEL_FOLDERID); + } + } + + // remove all non-existing ones + for (int i = rowCount() - 1; i >= 0; i--) { + auto folder = group(index(i, 0)); + Q_CHECK_PTR(folder); + folder->itemsPage()->removeItemsNotIn(appSet); + // check if group itself is also empty, remove them too. + if (folder->itemsPage()->itemCount() == 0 && folder->folderId() != TOPLEVEL_FOLDERID) { + QString groupId = folder->appId(); + removeRow(i); + removeItemFromGroup(groupId, TOPLEVEL_FOLDERID); + } + } + + // TODO: emit datachanged signal? + // TODO: save item arrangement to user data? } void AppGroupManager::loadAppGroupInfo() { auto groups = m_config->value("Groups").toList(); + for (int i = 0; i < groups.length(); i++) { auto group = groups[i].toMap(); - auto folderId = group.value("folderId", "").toString(); + auto groupId = group.value("groupId", "").toString(); auto name = group.value("name", "").toString(); auto pages = group.value("appItems", QVariantList()).toList(); QList items; @@ -125,28 +183,32 @@ void AppGroupManager::loadAppGroupInfo() for (int j = 0; j < pages.length(); j++) { auto page = pages[j].toStringList(); items << page; - std::for_each(page.begin(), page.end(), [this, i, j](const QString &item) { - m_map.insert(item, std::make_tuple(i, j)); - }); } - if (folderId.isEmpty()) { - folderId = assignGroupId(); + if (groupId.isEmpty()) { + groupId = assignGroupId(); } - auto p = new AppGroup(folderId, name, items); + auto p = new AppGroup(groupId, name, items); + appendRow(p); + } + + // always ensure top-level group exists + if (rowCount() == 0) { + auto p = new AppGroup(assignGroupId(), "Top Level", {}); + Q_ASSERT(p->folderId() == TOPLEVEL_FOLDERID); appendRow(p); } } -void AppGroupManager::dumpAppGroupInfo() +void AppGroupManager::saveAppGroupInfo() { QVariantList list; for (int i = 0; i < rowCount(); i++) { - auto data = index(i, 0); + auto folder = group(index(i, 0)); QVariantMap valueMap; - valueMap.insert("name", data.data(AppItemModel::NameRole)); - valueMap.insert("folderId", data.data(AppItemModel::DesktopIdRole)); - valueMap.insert("appItems", data.data(GroupAppItemsRole)); + valueMap.insert("name", folder->data(AppItemModel::NameRole)); + valueMap.insert("groupId", folder->appId()); + valueMap.insert("appItems", fromListOfStringList(folder->pages())); list << valueMap; } diff --git a/applets/dde-apps/appgroupmanager.h b/applets/dde-apps/appgroupmanager.h index d75c82f57..f71e8aa4c 100644 --- a/applets/dde-apps/appgroupmanager.h +++ b/applets/dde-apps/appgroupmanager.h @@ -12,6 +12,7 @@ #include #include +class ItemsPage; namespace apps { class AMAppItemModel; class AppGroup; @@ -27,24 +28,32 @@ class AppGroupManager : public QStandardItemModel enum Roles { GroupIdRole = Qt::UserRole + 1, GroupItemsPerPageRole, - GroupAppItemsRole, ExtendRole = 0x1000, }; explicit AppGroupManager(AMAppItemModel * referenceModel, QObject* parent = nullptr); QVariant data(const QModelIndex &index, int role = GroupIdRole) const override; - std::tuple getAppGroupInfo(const QString &appId); - void setAppGroupInfo(const QString &appId, std::tuple groupInfo); + std::tuple findItem(const QString &appId, int folderId = -1); + void appendItemToGroup(const QString &appId, int groupId); + bool removeItemFromGroup(const QString &appId, int groupId); + QModelIndex groupIndexById(int groupId); + AppGroup * group(int groupId); + AppGroup * group(QModelIndex idx); + void appendAppToGroup(const QString &appId, int groupId); + + static QVariantList fromListOfStringList(const QList & list); private: + void onReferenceModelChanged(); + void loadAppGroupInfo(); - void dumpAppGroupInfo(); + void saveAppGroupInfo(); QString assignGroupId() const; private: + bool m_appGroupInitialized; AMAppItemModel * m_referenceModel; - QHash> m_map; QTimer* m_dumpTimer; Dtk::Core::DConfig *m_config; }; diff --git a/applets/dde-apps/itemspage.cpp b/applets/dde-apps/itemspage.cpp new file mode 100644 index 000000000..4c068cb16 --- /dev/null +++ b/applets/dde-apps/itemspage.cpp @@ -0,0 +1,284 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "itemspage.h" + +#include +#include + +ItemsPage::ItemsPage(const QString &name, int maxItemCountPerPage, QObject *parent) + : QObject(parent) + , m_maxItemCountPerPage(maxItemCountPerPage) + , m_displayName(name) +{ + Q_ASSERT(m_maxItemCountPerPage >= 1); +} + +ItemsPage::ItemsPage(int maxItemCountPerPage, QObject *parent) + : ItemsPage(QString(), maxItemCountPerPage, parent) +{ + +} + +ItemsPage::~ItemsPage() +{ + +} + +QString ItemsPage::name() const +{ + return m_displayName; +} + +void ItemsPage::setName(const QString &name) +{ + m_displayName = name; + emit nameChanged(); +} + +int ItemsPage::maxItemCountPerPage() const +{ + return m_maxItemCountPerPage; +} + +int ItemsPage::pageCount() const +{ + return m_pages.size(); +} + +QStringList ItemsPage::items(int page) const +{ + return m_pages.at(page); +} + +QStringList ItemsPage::firstNItems(int count) +{ + QStringList result; + + for (const QStringList & pageItems : std::as_const(m_pages)) { + for (const QString & item : pageItems) { + result.append(item); + if (result.count() >= count) { + return result; + } + } + } + + return result; +} + +void ItemsPage::appendEmptyPage() +{ + m_pages.append(QStringList()); + + emit pageCountChanged(); + emit sigPageAdded(m_pages.count() - 1, m_pages.count() - 1); +} + +// if length of items larger than max item count per page, there will be another page get appended +void ItemsPage::appendPage(const QStringList items) +{ + const int len = items.size(); + const int pages = len / m_maxItemCountPerPage; + + if (len == 0) return; + + int first = m_pages.count(); + + QList::const_iterator begin = items.constBegin(); + + for (int i = 1; i <= pages; i++) { + QStringList newList; + std::copy(begin, begin + m_maxItemCountPerPage, std::back_inserter(newList)); + m_pages.append(newList); + + begin += m_maxItemCountPerPage; + } + + if (begin != items.constEnd()) { + QStringList newList; + std::copy(begin, items.end(), std::back_inserter(newList)); + m_pages.append(newList); + } + + emit pageCountChanged(); + emit sigPageAdded(first, m_pages.count() - 1); +} + +// find a page with empty place and append the item to that page. +void ItemsPage::appendItem(const QString id, int page) +{ + Q_ASSERT(page < m_pages.count()); + + if (page < 0) page = qMax(m_pages.count() - 1, 0); + + const int pageCount = m_pages.count(); + + for (; page < pageCount; page++) { + if (m_pages.at(page).size() < m_maxItemCountPerPage) break; + } + + if (page == pageCount) { + appendPage({id}); + } else { + m_pages[page].append(id); + } +} + +void ItemsPage::insertItem(const QString id, int page, int pos) +{ + Q_ASSERT(page >= 0 && page < m_pages.size()); + + if (m_pages[page].count() < pos) + pos = m_pages[page].count(); + + m_pages[page].insert(pos, id); + if (m_pages[page].size() > m_maxItemCountPerPage) { + QString last = m_pages[page].takeLast(); + if (page + 1 == m_pages.size()) { + appendPage({last}); + } else { + insertItem(last, page + 1, 0); + } + } +} + +void ItemsPage::insertItemToPage(const QString &id, int toPage) +{ + Q_ASSERT(toPage < m_pages.count()); + + if (toPage < 0) toPage = qMax(m_pages.count() - 1, 0); + + insertItem(id, toPage, m_pages[toPage].count()); +} + +void ItemsPage::moveItemPosition(int fromPage, int fromIndex, int toPage, int toIndex, bool appendToIndexItem) +{ + if (fromPage == toPage && fromIndex > toIndex && appendToIndexItem) { + if (fromIndex == (toIndex+1)) { + // same page, append operate, do nothing + return; + } + + toIndex += 1; + } + + bool needRemoveEmptyPage = false; + if (m_pages[fromPage].count() == 1) { + needRemoveEmptyPage = true; + } + + moveItem(fromPage, fromIndex, toPage, toIndex); + + if (needRemoveEmptyPage) { + removeEmptyPages(); + } +} + +bool ItemsPage::removeItem(const QString id, bool removePageIfPageIsEmpty) +{ + int page, idx; + std::tie(page, idx) = findItem(id); + + if (idx != -1) { + m_pages[page].removeAt(idx); + + if (removePageIfPageIsEmpty && m_pages.at(page).isEmpty()) { + m_pages.removeAt(page); + emit pageCountChanged(); + emit sigPageRemoved(m_pages.count() - 1, m_pages.count() - 1); + } + + return true; + } + + return false; +} + +void ItemsPage::removeItemsNotIn(const QSet &itemSet) +{ + for (int i = 0; i < m_pages.count(); i++) { + for (int j = m_pages.at(i).count() - 1; j >= 0; j--) { + const QString & item(m_pages.at(i).at(j)); + if (itemSet.contains(item)) continue; + if (item.startsWith(QLatin1String("internal/"))) continue; + m_pages[i].removeAt(j); + } + } + removeEmptyPages(); +} + +void ItemsPage::removeEmptyPages() +{ + int count = m_pages.size(); + m_pages.removeAll({}); + if (count != m_pages.size()) { + emit pageCountChanged(); + emit sigPageRemoved(m_pages.count() - 1, m_pages.count() - 1); + } +} + +// +std::tuple ItemsPage::findItem(const QString &id) const +{ + for (int i = 0; i < m_pages.count(); i++) { + int idx = m_pages.at(i).indexOf(id); + if (idx != -1) { + return std::make_tuple(i, idx); + } + } + + return std::make_tuple(-1, -1); +} + +bool ItemsPage::contains(const QString &id) const +{ + int i, j; + std::tie(i, j) = findItem(id); + return i != -1; +} + +QStringList ItemsPage::allArrangedItems() const +{ + QStringList result; + for (const QStringList &pageItems : std::as_const(m_pages)) { + result.append(pageItems); + } + + return result; +} + +QList ItemsPage::allPagedItems() const +{ + return m_pages; +} + +int ItemsPage::itemCount() const +{ + int count = 0; + for (const QStringList &pageItems : m_pages) { + count += pageItems.count(); + } + return count; +} + +int ItemsPage::itemCount(int page) const +{ + if (page >= pageCount()) + return 0; + + return items(page).count(); +} + +// item will be moved to the index +void ItemsPage::moveItem(int fromPage, int fromIndex, int toPage, int toIndex) +{ + if (fromPage == toPage) { + auto toIndexItem = m_pages[fromPage].takeAt(fromIndex); + m_pages[fromPage].insert(toIndex, toIndexItem); + } else { + QString id = m_pages[fromPage].takeAt(fromIndex); + insertItem(id, toPage, toIndex); + } +} diff --git a/applets/dde-apps/itemspage.h b/applets/dde-apps/itemspage.h new file mode 100644 index 000000000..26f074271 --- /dev/null +++ b/applets/dde-apps/itemspage.h @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include + +class ItemsPage : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(int pageCount READ pageCount NOTIFY pageCountChanged) + Q_PROPERTY(int maxItemCountPerPage READ maxItemCountPerPage CONSTANT) + +public: + explicit ItemsPage(int maxItemCountPerPage, QObject * parent = nullptr); + explicit ItemsPage(const QString & name, int maxItemCountPerPage, QObject * parent = nullptr); + ~ItemsPage(); + + QString name() const; + void setName(const QString & name); + + int maxItemCountPerPage() const; + + int pageCount() const; + QStringList items(int page = 0) const; + QStringList firstNItems(int count = 4); + QStringList allArrangedItems() const; + QList allPagedItems() const; + int itemCount() const; + int itemCount(int page) const; + + void appendEmptyPage(); + void appendPage(const QStringList items); + void appendItem(const QString id, int page = -1); + void insertItem(const QString id, int page, int pos = 0); + void insertItemToPage(const QString &id, int toPage); + void moveItemPosition(int fromPage, int fromIndex, int toPage, int toIndex, bool appendToIndexItem); + bool removeItem(const QString id, bool removePageIfPageIsEmpty = true); + void removeItemsNotIn(const QSet & itemSet); + void removeEmptyPages(); + + std::tuple findItem(const QString & id) const; + bool contains(const QString & id) const; + +private: + void moveItem(int fromPage, int fromIndex, int toPage, int toIndex); + +signals: + void nameChanged(); + void pageCountChanged(); + void sigPageAdded(int first, int last); + void sigPageRemoved(int first, int last); + +private: + int m_maxItemCountPerPage; + QString m_displayName; + QList m_pages; +}; diff --git a/panels/dock/taskmanager/taskmanager.cpp b/panels/dock/taskmanager/taskmanager.cpp index a5a59f981..868c15f9c 100644 --- a/panels/dock/taskmanager/taskmanager.cpp +++ b/panels/dock/taskmanager/taskmanager.cpp @@ -84,6 +84,7 @@ bool TaskManager::init() DS_NAMESPACE::DAppletBridge bridge("org.deepin.ds.dde-apps"); if (auto applet = bridge.applet()) { auto model = applet->property("appModel").value(); + Q_ASSERT(model); m_activeAppModel = new RoleCombineModel(m_windowMonitor.data(), model, AbstractWindow::identityRole, [](QVariant data, QAbstractItemModel *model) -> QModelIndex { auto roleNames = model->roleNames();