66#include " appgroup.h"
77#include " itemspage.h"
88#include " amappitemmodel.h"
9+ #include " amappitem.h"
910
1011#define TOPLEVEL_FOLDERID 0
1112
@@ -20,6 +21,7 @@ AppGroupManager::AppGroupManager(AMAppItemModel * referenceModel, QObject *paren
2021 m_dumpTimer->setSingleShot (true );
2122 m_dumpTimer->setInterval (1000 );
2223
24+ launchpadArrangementConfigMigration ();
2325 loadAppGroupInfo ();
2426
2527 connect (m_referenceModel, &AMAppItemModel::rowsInserted, this , [this ](){
@@ -49,7 +51,7 @@ QVariant AppGroupManager::data(const QModelIndex &index, int role) const
4951}
5052
5153// Find the item's location. If folderId is -1, search all folders.
52- std::tuple< int , int , int > AppGroupManager::findItem (const QString &appId, int folderId)
54+ ItemPosition AppGroupManager::findItem (const QString &appId, int folderId)
5355{
5456 int page, idx;
5557
@@ -60,11 +62,11 @@ std::tuple<int, int, int> AppGroupManager::findItem(const QString &appId, int fo
6062 }
6163 std::tie (page, idx) = group->itemsPage ()->findItem (appId);
6264 if (page != -1 ) {
63- return std::make_tuple (group->folderId (), page, idx);
65+ return ItemPosition (group->folderId (), page, idx);
6466 }
6567 }
6668
67- return std::make_tuple (- 1 , - 1 , - 1 );
69+ return ItemPosition ( );
6870}
6971
7072void AppGroupManager::appendItemToGroup (const QString &appId, int groupId)
@@ -112,6 +114,115 @@ AppGroup * AppGroupManager::group(QModelIndex idx)
112114 return group;
113115}
114116
117+ ItemsPage * AppGroupManager::groupPages (int groupId)
118+ {
119+ AppGroup * folder = group (groupId);
120+ if (!folder) return nullptr ;
121+ return folder->itemsPage ();
122+ }
123+
124+ void AppGroupManager::bringToFromt (const QString & id)
125+ {
126+ const ItemPosition origPos = findItem (id);
127+
128+ // can only bring top-level item to front
129+ Q_ASSERT (origPos.group () != TOPLEVEL_FOLDERID);
130+ if (origPos.group () != TOPLEVEL_FOLDERID) {
131+ return ;
132+ }
133+
134+ // already at front
135+ if (origPos.page () == 0 && origPos.pos () == 0 ) {
136+ return ;
137+ }
138+
139+ auto * topLevel = groupPages (0 );
140+ topLevel->moveItemPosition (origPos.page (), origPos.pos (), 0 , 0 , false );
141+
142+ saveAppGroupInfo ();
143+
144+ // TODO: emit signal to refresh the view
145+ }
146+
147+ void AppGroupManager::commitRearrangeOperation (const QString & dragId, const QString & dropId, DndOperation operation, int pageHint)
148+ {
149+ if (dragId == dropId) return ;
150+
151+ const ItemPosition dragOrigPos = findItem (dragId);
152+ const ItemPosition dropOrigPos = findItem (dropId);
153+
154+ Q_ASSERT (dragOrigPos.group () != -1 );
155+ if (dragOrigPos.group () == -1 ) {
156+ qWarning () << " Cannot found" << dragId << " in current item arrangement." ;
157+ return ;
158+ }
159+
160+ if (operation != DndOperation::DndJoin) {
161+ // move to dropId's front or back
162+ if (dragOrigPos.group () == dropOrigPos.group ()) {
163+ // same folder item re-arrangement
164+ ItemsPage * folder = groupPages (dropOrigPos.group ());
165+ folder->moveItemPosition (dragOrigPos.page (), dragOrigPos.pos (), dropOrigPos.page (), dropOrigPos.pos (), operation == DndOperation::DndAppend);
166+ } else {
167+ // different folder item arrangement
168+ ItemsPage * srcFolder = groupPages (dragOrigPos.group ());
169+ ItemsPage * dstFolder = groupPages (dropOrigPos.group ());
170+ srcFolder->removeItem (dragId);
171+ if (srcFolder->pageCount () == 0 && srcFolder != dstFolder) {
172+ removeGroup (dragOrigPos.group ());
173+ }
174+ dstFolder->insertItem (dropId, dropOrigPos.page (), dropOrigPos.pos ());
175+ }
176+ } else {
177+ if (AppGroup::idIsFolder (dragId) && dropId != " internal/folders/0" ) return ; // cannot drag folder onto something
178+ if (dropOrigPos.group () != TOPLEVEL_FOLDERID && dropId != " internal/folders/0" ) return ; // folder inside folder is not allowed
179+
180+ // the source item will be inside a new folder anyway.
181+ ItemsPage * srcFolder = groupPages (dragOrigPos.group ());
182+
183+ if (AppGroup::idIsFolder (dropId)) {
184+ // drop into existing folder
185+ ItemsPage * dstFolder = groupPages (AppGroup::parseGroupId (dropId));
186+ const int fromPage = dragOrigPos.page ();
187+ const int toPage = pageHint;
188+ if (srcFolder == dstFolder) {
189+ if (srcFolder->pageCount () == 1 ||
190+ (fromPage == toPage && srcFolder->itemCount (fromPage) == 1 )) { // dnd the only item to the same page
191+ return ;
192+ }
193+ }
194+
195+ // hold the empty page avoid access out of page range!
196+ srcFolder->removeItem (dragId, false );
197+ if (srcFolder->itemCount () == 0 && srcFolder != dstFolder) {
198+ removeGroup (dragOrigPos.group ());
199+ }
200+ dstFolder->insertItemToPage (dragId, toPage);
201+
202+ // clear empty page
203+ srcFolder->removeEmptyPages ();
204+ } else {
205+ srcFolder->removeItem (dragId);
206+ // we need the app info for the new folder name...
207+ AMAppItem * item = m_referenceModel->appItem (dropId);
208+ AppItemModel::DDECategories dropCategories = item ? item->ddeCategories () : AppItemModel::Others;
209+ // make a new folder, move two items into the folder
210+ QString dstFolderId = assignGroupId ();
211+ appendGroup (dstFolderId, " internal/category/" + QString::number (dropCategories), {{dragId, dropId}});
212+ if (srcFolder->pageCount () == 0 && dragOrigPos.group () != 0 ) {
213+ removeGroup (dragOrigPos.group ());
214+ }
215+ auto * topLevel = groupPages (0 );
216+ topLevel->insertItem (dstFolderId, dropOrigPos.page (), dropOrigPos.pos ());
217+ topLevel->removeItem (dropId);
218+ }
219+ }
220+
221+ saveAppGroupInfo ();
222+
223+ // TODO: emit signal to refresh the view
224+ }
225+
115226QVariantList AppGroupManager::fromListOfStringList (const QList<QStringList> & list)
116227{
117228 QVariantList data;
@@ -145,9 +256,8 @@ void AppGroupManager::onReferenceModelChanged()
145256 const QString & desktopId = m_referenceModel->data (m_referenceModel->index (i, 0 ), AppItemModel::DesktopIdRole).toString ();
146257 appSet.insert (desktopId);
147258 // add all existing ones if they are not already in
148- int folder, page, idx;
149- std::tie (folder, std::ignore, std::ignore) = findItem (desktopId);
150- if (folder == -1 ) {
259+ ItemPosition itemPos = findItem (desktopId);
260+ if (itemPos.group () == -1 ) {
151261 appendItemToGroup (desktopId, TOPLEVEL_FOLDERID);
152262 }
153263 }
@@ -169,6 +279,52 @@ void AppGroupManager::onReferenceModelChanged()
169279 // TODO: save item arrangement to user data?
170280}
171281
282+ void AppGroupManager::launchpadArrangementConfigMigration ()
283+ {
284+ const QString arrangementSettingBasePath (QStandardPaths::writableLocation (QStandardPaths::GenericConfigLocation));
285+ const QString arrangementSettingPath (QDir (arrangementSettingBasePath).absoluteFilePath (" deepin/dde-launchpad/item-arrangement.ini" ));
286+ if (!QFile::exists (arrangementSettingPath)) return ;
287+ QSettings itemArrangementSettings (arrangementSettingPath, QSettings::NativeFormat);
288+
289+ itemArrangementSettings.beginGroup (" fullscreen" );
290+ const QStringList folderGroups (itemArrangementSettings.childGroups ());
291+
292+ QVariantList list;
293+
294+ for (const QString & groupName : folderGroups) {
295+ itemArrangementSettings.beginGroup (groupName);
296+ QString folderName = itemArrangementSettings.value (" name" , QString ()).toString ();
297+ int pageCount = itemArrangementSettings.value (" pageCount" , 0 ).toInt ();
298+ bool isTopLevel = groupName == " toplevel" ;
299+
300+ QVariantMap valueMap;
301+ valueMap.insert (" name" , folderName);
302+ valueMap.insert (" groupId" , groupName.toInt ());
303+
304+ QList<QStringList> pages;
305+ for (int i = 0 ; i < pageCount; i++) {
306+ QStringList items = itemArrangementSettings.value (QString::asprintf (" pageItems/%d" , i)).toStringList ();
307+ // check if items have ".desktop" suffix, and remove the suffix
308+ std::transform (items.begin (), items.end (), items.begin (), [](QString &item) {
309+ if (item.endsWith (" .desktop" )) {
310+ item.remove (" .desktop" );
311+ }
312+ return item;
313+ });
314+ pages.append (items);
315+ }
316+
317+ valueMap.insert (" appItems" , fromListOfStringList (pages));
318+ list.append (valueMap);
319+
320+ itemArrangementSettings.endGroup ();
321+ }
322+
323+ m_config->setValue (" Groups" , list);
324+
325+ // TODO: delete the old configuration file
326+ }
327+
172328void AppGroupManager::loadAppGroupInfo ()
173329{
174330 auto groups = m_config->value (" Groups" ).toList ();
@@ -188,15 +344,13 @@ void AppGroupManager::loadAppGroupInfo()
188344 if (groupId.isEmpty ()) {
189345 groupId = assignGroupId ();
190346 }
191- auto p = new AppGroup (groupId, name, items);
192- appendRow (p);
347+ auto p = appendGroup (groupId, name, items);
193348 }
194349
195350 // always ensure top-level group exists
196351 if (rowCount () == 0 ) {
197- auto p = new AppGroup (assignGroupId (), " Top Level" , {});
352+ auto p = appendGroup (assignGroupId (), " Top Level" , {});
198353 Q_ASSERT (p->folderId () == TOPLEVEL_FOLDERID);
199- appendRow (p);
200354 }
201355}
202356
@@ -231,4 +385,24 @@ QString AppGroupManager::assignGroupId() const
231385 return QString (" internal/group/%1" ).arg (idNumber);
232386}
233387
388+ AppGroup * AppGroupManager::appendGroup (int groupId, QString groupName, const QList<QStringList> &appItemIDs)
389+ {
390+ Q_ASSERT (!groupIndexById (groupId).isValid ());
391+ return appendGroup (AppGroup::groupIdFromNumber (groupId), groupName, appItemIDs);
392+ }
393+
394+ AppGroup * AppGroupManager::appendGroup (QString groupId, QString groupName, const QList<QStringList> &appItemIDs)
395+ {
396+ auto p = new AppGroup (groupId, groupName, appItemIDs);
397+ appendRow (p);
398+ return p;
399+ }
400+
401+ void AppGroupManager::removeGroup (int groupId)
402+ {
403+ auto groupIndex = groupIndexById (groupId);
404+ Q_ASSERT (groupIndex.isValid ());
405+ removeRow (groupIndex.row ());
406+ }
407+
234408}
0 commit comments