From 06d2b5309e3d112f1b7c55b1f080b01859bf1046 Mon Sep 17 00:00:00 2001 From: xust Date: Wed, 19 Jun 2024 10:04:48 +0800 Subject: [PATCH] feat: [desktop] new organize mode 1. add more dconfigs; 2. files are inserted into desktop not into collection on created; 3. new menu action: organize desktop, renamed action: Organize desktop- >enable desktop organizition; 4. organize files on file renamed; 5. drag files from canvas to collections; 6. drag files from collections to canvas; 7. move 'Enable organize' from contextmenu to option dialog; Log: as contents. Task: https://pms.uniontech.com/task-view-354097.html --- .../org.deepin.dde.file-manager.desktop.json | 4 +- ...in.dde.file-manager.desktop.organizer.json | 13 ++- .../config/configpresenter.cpp | 11 ++ .../config/configpresenter.h | 6 + .../menus/extendcanvasscene.cpp | 40 +++++-- .../menus/organizermenu_defines.h | 7 +- .../mode/collectiondataprovider.h | 4 +- .../mode/normalized/normalizedmode_p.h | 2 +- .../mode/normalized/type/typeclassifier.cpp | 23 ++-- .../mode/normalizedmode.cpp | 104 ++++++++++++++++-- .../ddplugin-organizer/mode/normalizedmode.h | 4 +- .../options/optionswindow.cpp | 11 ++ .../options/optionswindow_p.h | 5 +- .../ddplugin-organizer/organizer_defines.h | 5 + .../view/collectionview.cpp | 35 ++++-- .../view/collectionview_p.h | 2 +- 16 files changed, 228 insertions(+), 48 deletions(-) diff --git a/assets/configs/org.deepin.dde.file-manager.desktop.json b/assets/configs/org.deepin.dde.file-manager.desktop.json index 88a6fadeff..058e7dcd54 100644 --- a/assets/configs/org.deepin.dde.file-manager.desktop.json +++ b/assets/configs/org.deepin.dde.file-manager.desktop.json @@ -12,7 +12,7 @@ "description": "It's used to control whether the auto align on desktop is enabled.", "permissions": "readwrite", "visibility": "public" - }, + }, "maskLogoUri": { "value": "", "serial": 0, @@ -80,4 +80,4 @@ "visibility": "public" } } -} \ No newline at end of file +} diff --git a/assets/configs/org.deepin.dde.file-manager.desktop.organizer.json b/assets/configs/org.deepin.dde.file-manager.desktop.organizer.json index eb2ac2eb18..be93565415 100644 --- a/assets/configs/org.deepin.dde.file-manager.desktop.organizer.json +++ b/assets/configs/org.deepin.dde.file-manager.desktop.organizer.json @@ -45,6 +45,17 @@ "description": "Prompt dialog for turning on/off hidden collections.", "permissions": "readwrite", "visibility": "public" - } + }, + "organizeAction": { + "value": 0, + "serial": 0, + "flags": [], + "name": "Organize action", + "name[zh_CN]": "整理动作", + "description[zh_CN]": "单次整理(0)或自动整理(1),当选择单次整理时,整理行为仅在用户触发整理时发生,新建的文件不会被整理到集合中", + "description": "Single-time organization (0) or automatic organization (1): When single-time organization is selected, the organization action only occurs when triggered by the user, and newly created files will not be organized into the collection.", + "permissions": "readwrite", + "visibility": "public" + } } } diff --git a/src/plugins/desktop/ddplugin-organizer/config/configpresenter.cpp b/src/plugins/desktop/ddplugin-organizer/config/configpresenter.cpp index 92d3963989..d12bd88d15 100644 --- a/src/plugins/desktop/ddplugin-organizer/config/configpresenter.cpp +++ b/src/plugins/desktop/ddplugin-organizer/config/configpresenter.cpp @@ -238,6 +238,17 @@ void ConfigPresenter::setEnabledTypeCategories(ItemCategories flags) conf->sync(); } +OrganizeAction ConfigPresenter::organizeAction() const +{ + int val = DConfigManager::instance()->value(kConfName, "organizeAction", 0).toInt(); + return val == 0 ? kOnTrigger : kAlways; +} + +bool ConfigPresenter::organizeOnTriggered() const +{ + return OrganizeAction() == kOnTrigger; +} + CollectionStyle ConfigPresenter::normalStyle(const QString &key) const { if (key.isEmpty()) diff --git a/src/plugins/desktop/ddplugin-organizer/config/configpresenter.h b/src/plugins/desktop/ddplugin-organizer/config/configpresenter.h index 748208a5cd..f9d9d9c5d3 100644 --- a/src/plugins/desktop/ddplugin-organizer/config/configpresenter.h +++ b/src/plugins/desktop/ddplugin-organizer/config/configpresenter.h @@ -61,6 +61,10 @@ class ConfigPresenter : public QObject public: ItemCategories enabledTypeCategories() const; void setEnabledTypeCategories(ItemCategories flags); + + OrganizeAction organizeAction() const; + bool organizeOnTriggered() const; + signals: // use Qt::QueuedConnection void changeEnableState(bool e); @@ -71,6 +75,8 @@ class ConfigPresenter : public QObject void changeDisplaySize(int); void newCollection(const QList &); void showOptionWindow(); + void reorganizeDesktop(); + public slots: protected: explicit ConfigPresenter(QObject *parent = nullptr); diff --git a/src/plugins/desktop/ddplugin-organizer/menus/extendcanvasscene.cpp b/src/plugins/desktop/ddplugin-organizer/menus/extendcanvasscene.cpp index f45fe459f5..1110267bb5 100644 --- a/src/plugins/desktop/ddplugin-organizer/menus/extendcanvasscene.cpp +++ b/src/plugins/desktop/ddplugin-organizer/menus/extendcanvasscene.cpp @@ -33,11 +33,12 @@ ExtendCanvasScenePrivate::ExtendCanvasScenePrivate(ExtendCanvasScene *qq) void ExtendCanvasScenePrivate::emptyMenu(QMenu *parent) { - QAction *tempAction = parent->addAction(predicateName.value(ActionID::kOrganizeDesktop)); - predicateAction[ActionID::kOrganizeDesktop] = tempAction; - tempAction->setProperty(ActionPropertyKey::kActionID, QString(ActionID::kOrganizeDesktop)); - tempAction->setCheckable(true); - tempAction->setChecked(turnOn); + QAction *tempAction = nullptr; + // tempAction = parent->addAction(predicateName.value(ActionID::kOrganizeEnable)); + // predicateAction[ActionID::kOrganizeEnable] = tempAction; + // tempAction->setProperty(ActionPropertyKey::kActionID, QString(ActionID::kOrganizeEnable)); + // tempAction->setCheckable(true); + // tempAction->setChecked(turnOn); if (turnOn) { #ifdef EnableCollectionModeMenu @@ -46,6 +47,11 @@ void ExtendCanvasScenePrivate::emptyMenu(QMenu *parent) predicateAction[ActionID::kOrganizeBy] = tempAction; tempAction->setProperty(ActionPropertyKey::kActionID, QString(ActionID::kOrganizeBy)); #endif + if (ConfigPresenter::instance()->organizeOnTriggered()) { + tempAction = new QAction(predicateName.value(ActionID::kOrganizeTrigger), parent); + predicateAction[ActionID::kOrganizeTrigger] = tempAction; + tempAction->setProperty(ActionPropertyKey::kActionID, QString(ActionID::kOrganizeTrigger)); + } } tempAction = parent->addAction(predicateName.value(ActionID::kOrganizeOptions)); @@ -84,7 +90,7 @@ void ExtendCanvasScenePrivate::updateEmptyMenu(QMenu *parent) << "display-settings"; } else { QAction *indexAction = actions[pos]; - parent->insertAction(indexAction, predicateAction[ActionID::kOrganizeDesktop]); + parent->insertAction(indexAction, predicateAction[ActionID::kOrganizeEnable]); if (turnOn) { parent->insertAction(indexAction, predicateAction[ActionID::kOrganizeBy]); parent->insertAction(indexAction, predicateAction[ActionID::kOrganizeOptions]); @@ -104,6 +110,21 @@ void ExtendCanvasScenePrivate::updateEmptyMenu(QMenu *parent) parent->insertAction(indexAction, predicateAction[ActionID::kOrganizeOptions]); } } + + if (turnOn) { + auto refreshPos = std::find_if(actions.begin(), actions.end(), [](QAction *action) { + return action->property(ActionPropertyKey::kActionID).toString() == "refresh"; + }); + if (refreshPos == actions.end()) { + parent->addAction(predicateAction[ActionID::kOrganizeTrigger]); + } else { + int idx = int(std::distance(actions.begin(), refreshPos)) + 1; + if (idx < actions.count()) { + auto act = actions.at(idx); + parent->insertAction(act, predicateAction[ActionID::kOrganizeTrigger]); + } + } + } } } @@ -206,7 +227,8 @@ bool ExtendCanvasScenePrivate::triggerSortby(const QString &actionId) ExtendCanvasScene::ExtendCanvasScene(QObject *parent) : AbstractMenuScene(parent), d(new ExtendCanvasScenePrivate(this)) { - d->predicateName[ActionID::kOrganizeDesktop] = tr("Organize desktop"); + d->predicateName[ActionID::kOrganizeEnable] = tr("Enable desktop organization"); + d->predicateName[ActionID::kOrganizeTrigger] = tr("Organize desktop"); d->predicateName[ActionID::kOrganizeOptions] = tr("View options"); d->predicateName[ActionID::kOrganizeBy] = tr("Organize by"); @@ -283,7 +305,7 @@ bool ExtendCanvasScene::triggered(QAction *action) auto actionId = action->property(ActionPropertyKey::kActionID).toString(); if (d->predicateAction.values().contains(action)) { fmDebug() << "organizer for canvas:" << actionId; - if (actionId == ActionID::kOrganizeDesktop) { + if (actionId == ActionID::kOrganizeEnable) { emit CfgPresenter->changeEnableState(action->isChecked()); } else if (actionId == ActionID::kOrganizeByCustom) { emit CfgPresenter->switchToCustom(); @@ -299,6 +321,8 @@ bool ExtendCanvasScene::triggered(QAction *action) emit CfgPresenter->newCollection(d->selectFiles); } else if (actionId == ActionID::kOrganizeOptions) { emit CfgPresenter->showOptionWindow(); + } else if (actionId == ActionID::kOrganizeTrigger) { + emit CfgPresenter->reorganizeDesktop(); } return true; } diff --git a/src/plugins/desktop/ddplugin-organizer/menus/organizermenu_defines.h b/src/plugins/desktop/ddplugin-organizer/menus/organizermenu_defines.h index 3d6fb8843b..e6d85d3a6b 100644 --- a/src/plugins/desktop/ddplugin-organizer/menus/organizermenu_defines.h +++ b/src/plugins/desktop/ddplugin-organizer/menus/organizermenu_defines.h @@ -10,7 +10,8 @@ namespace ddplugin_organizer { namespace ActionID { -inline constexpr char kOrganizeDesktop[] = "organize-desktop"; +inline constexpr char kOrganizeEnable[] = "organize-enable"; +inline constexpr char kOrganizeTrigger[] = "organize-trigger"; inline constexpr char kOrganizeOptions[] = "organize-options"; inline constexpr char kOrganizeBy[] = "organize-by"; inline constexpr char kOrganizeByType[] = "organize-by-type"; @@ -19,7 +20,7 @@ inline constexpr char kOrganizeByTimeModified[] = "organize-by-time-modified"; inline constexpr char kOrganizeByTimeCreated[] = "organize-by-time-created"; inline constexpr char kOrganizeByCustom[] = "custom-collection"; inline constexpr char kCreateACollection[] = "create-a-collection"; -} // namespace ActionID +} // namespace ActionID namespace CollectionMenuParams { inline constexpr char kOnColletion[] = "OnColletion"; @@ -27,4 +28,4 @@ inline constexpr char kColletionView[] = "ColletionView"; } } -#endif // ORGANIZERMENU_DEFINES_H +#endif // ORGANIZERMENU_DEFINES_H diff --git a/src/plugins/desktop/ddplugin-organizer/mode/collectiondataprovider.h b/src/plugins/desktop/ddplugin-organizer/mode/collectiondataprovider.h index fafc1e006c..f2b4cc182e 100644 --- a/src/plugins/desktop/ddplugin-organizer/mode/collectiondataprovider.h +++ b/src/plugins/desktop/ddplugin-organizer/mode/collectiondataprovider.h @@ -30,7 +30,6 @@ class CollectionDataProvider : public QObject virtual void addPreItems(const QString &targetKey, const QList &urls, int targetIndex); virtual bool checkPreItem(const QUrl &url, QString &key, int &index); virtual bool takePreItem(const QUrl &url, QString &key, int &index); -protected: virtual QString replace(const QUrl &oldUrl, const QUrl &newUrl) = 0; virtual QString append(const QUrl &) = 0; virtual QString prepend(const QUrl &) = 0; @@ -40,6 +39,7 @@ class CollectionDataProvider : public QObject signals: void nameChanged(const QString &key, const QString &name); void itemsChanged(const QString &key); + protected: QHash collections; QHash>> preCollectionItems; @@ -47,4 +47,4 @@ class CollectionDataProvider : public QObject } -#endif // COLLECTIONDATAPROVIDER_H +#endif // COLLECTIONDATAPROVIDER_H diff --git a/src/plugins/desktop/ddplugin-organizer/mode/normalized/normalizedmode_p.h b/src/plugins/desktop/ddplugin-organizer/mode/normalized/normalizedmode_p.h index f399f48b47..3f3224e6d7 100644 --- a/src/plugins/desktop/ddplugin-organizer/mode/normalized/normalizedmode_p.h +++ b/src/plugins/desktop/ddplugin-organizer/mode/normalized/normalizedmode_p.h @@ -40,7 +40,7 @@ public slots: void updateHolderSurfaceIndex(QWidget *surface); public: - void restore(const QList &cfgs); + void restore(const QList &cfgs, bool reorganized = false); FileClassifier *classifier = nullptr; QHash holders; NormalizedModeBroker *broker = nullptr; diff --git a/src/plugins/desktop/ddplugin-organizer/mode/normalized/type/typeclassifier.cpp b/src/plugins/desktop/ddplugin-organizer/mode/normalized/type/typeclassifier.cpp index 0154152f92..980891afe1 100644 --- a/src/plugins/desktop/ddplugin-organizer/mode/normalized/type/typeclassifier.cpp +++ b/src/plugins/desktop/ddplugin-organizer/mode/normalized/type/typeclassifier.cpp @@ -37,17 +37,18 @@ inline const char kTypeSuffixApp[] = "desktop"; *tablePtr = tablePtr->fromList(QString(suffix).split(',')); \ } TypeClassifierPrivate::TypeClassifierPrivate(TypeClassifier *qq) - : q(qq) { - //todo(zy) 类型后缀支持可配置 - InitSuffixTable(docSuffix, kTypeSuffixDoc) - InitSuffixTable(picSuffix, kTypeSuffixPic) - InitSuffixTable(muzSuffix, kTypeSuffixMuz) - InitSuffixTable(vidSuffix, kTypeSuffixVid) - InitSuffixTable(appSuffix, kTypeSuffixApp) - //InitSuffixTable(appMimeType, kTypeMimeApp) - } - - TypeClassifierPrivate::~TypeClassifierPrivate() + : q(qq) +{ + //todo(zy) 类型后缀支持可配置 + InitSuffixTable(docSuffix, kTypeSuffixDoc); + InitSuffixTable(picSuffix, kTypeSuffixPic); + InitSuffixTable(muzSuffix, kTypeSuffixMuz); + InitSuffixTable(vidSuffix, kTypeSuffixVid); + InitSuffixTable(appSuffix, kTypeSuffixApp); + //InitSuffixTable(appMimeType, kTypeMimeApp); +} + +TypeClassifierPrivate::~TypeClassifierPrivate() { } diff --git a/src/plugins/desktop/ddplugin-organizer/mode/normalizedmode.cpp b/src/plugins/desktop/ddplugin-organizer/mode/normalizedmode.cpp index 2ac8e62b78..1b8b3ada63 100644 --- a/src/plugins/desktop/ddplugin-organizer/mode/normalizedmode.cpp +++ b/src/plugins/desktop/ddplugin-organizer/mode/normalizedmode.cpp @@ -7,6 +7,8 @@ #include "config/configpresenter.h" #include "interface/canvasviewshell.h" #include "interface/canvasmanagershell.h" +#include "interface/canvasgridshell.h" +#include "interface/canvasmodelshell.h" #include "utils/fileoperator.h" #include "view/collectionview.h" #include "view/collectionframe.h" @@ -14,6 +16,7 @@ #include #include +#include #include #include @@ -261,7 +264,7 @@ void NormalizedModePrivate::updateHolderSurfaceIndex(QWidget *surface) } } -void NormalizedModePrivate::restore(const QList &cfgs) +void NormalizedModePrivate::restore(const QList &cfgs, bool reorganized) { // order by config for (const CollectionBaseDataPtr &cfg : cfgs) { @@ -275,7 +278,10 @@ void NormalizedModePrivate::restore(const QList &cfgs) } } - ordered.append(org); + // those are not in config files should not be organized. + if (reorganized || !CfgPresenter->organizeOnTriggered()) + ordered.append(org); + base->items = ordered; } } @@ -331,7 +337,9 @@ bool NormalizedMode::initialize(CollectionModel *m) connect(model, &CollectionModel::dataReplaced, this, &NormalizedMode::onFileRenamed, Qt::DirectConnection); connect(model, &CollectionModel::dataChanged, this, &NormalizedMode::onFileDataChanged, Qt::QueuedConnection); - connect(model, &CollectionModel::modelReset, this, &NormalizedMode::rebuild, Qt::QueuedConnection); + connect(model, &CollectionModel::modelReset, this, [this] { rebuild(); }, Qt::QueuedConnection); + + connect(CfgPresenter, &ConfigPresenter::reorganizeDesktop, this, &NormalizedMode::onReorganizeDesktop, Qt::QueuedConnection); // creating if there already are files. if (!model->files().isEmpty()) @@ -488,7 +496,7 @@ void NormalizedMode::detachLayout() } } -void NormalizedMode::rebuild() +void NormalizedMode::rebuild(bool reorganize) { // 使用分类器对文件进行分类,后续性能问题需考虑异步分类 QTime time; @@ -498,7 +506,7 @@ void NormalizedMode::rebuild() d->classifier->reset(files); // order item as config - d->restore(CfgPresenter->normalProfile()); + d->restore(CfgPresenter->normalProfile(), reorganize); fmInfo() << QString("Classifying %0 files takes %1 ms").arg(files.size()).arg(time.elapsed()); time.restart(); @@ -542,7 +550,24 @@ void NormalizedMode::rebuild() void NormalizedMode::onFileRenamed(const QUrl &oldUrl, const QUrl &newUrl) { - d->classifier->replace(oldUrl, newUrl); + if (CfgPresenter->organizeOnTriggered()) { + QString oldType = d->classifier->key(oldUrl); + if (oldType.isEmpty()) // old item is not in collection + return; + QString newType = d->classifier->classify(newUrl); + if (newType == oldType) { + auto idx = d->classifier->baseData(oldType)->items.indexOf(oldUrl); + d->classifier->baseData(oldType)->items.replace(idx, newUrl); + } else { + d->classifier->baseData(oldType)->items.removeAll(oldUrl); + dpfSlotChannel->push("ddplugin_canvas", "slot_CanvasView_Select", QList { newUrl }); + } + + Q_EMIT d->classifier->itemsChanged(oldType); + } else { + d->classifier->replace(oldUrl, newUrl); + } + d->switchCollection(); const auto &renameFileData = FileOperatorIns->renameFileData(); @@ -565,6 +590,9 @@ void NormalizedMode::onFileRenamed(const QUrl &oldUrl, const QUrl &newUrl) void NormalizedMode::onFileInserted(const QModelIndex &parent, int first, int last) { + if (ConfigPresenter::instance()->organizeOnTriggered()) + return; + QList urls; for (int i = first; i <= last; i++) { QModelIndex index = model->index(i, 0, parent); @@ -606,6 +634,13 @@ void NormalizedMode::onFileDataChanged(const QModelIndex &topLeft, const QModelI } } +void NormalizedMode::onReorganizeDesktop() +{ + rebuild(true); + for (auto type : d->classifier->classes()) + Q_EMIT d->classifier->itemsChanged(type); // to update the collection view's vertical scroll range. +} + void NormalizedMode::onCollectionEditStatusChanged(bool editing) { this->editing = editing; @@ -634,6 +669,44 @@ void NormalizedMode::deactiveAllPredictors() } } +bool NormalizedMode::filterDropData(int viewIndex, const QMimeData *mimeData, const QPoint &viewPoint) +{ + if (!CfgPresenter->organizeOnTriggered()) + return false; + + auto urls = mimeData->urls(); + QList collectionItems; + QStringList files; + for (auto url : urls) { + QString &&key = d->classifier->key(url); + if (key.isEmpty()) + continue; + collectionItems << url; + files << url.toString(); + } + + if (collectionItems.isEmpty()) + return false; + + QPoint gridPos = canvasViewShell->gridPos(viewIndex, viewPoint); + if (!canvasGridShell->item(viewIndex, gridPos).isEmpty()) + return false; + + canvasGridShell->tryAppendAfter(files, viewIndex, gridPos); + + for (auto url : collectionItems) { + d->classifier->remove(url); + canvasModelShell->fetch(url); + } + + dpfSlotChannel->push("ddplugin_canvas", "slot_CanvasView_Select", collectionItems); + QTimer::singleShot(0, this, [this] { // to hide collection if all items are moved outside. + d->switchCollection(); + }); + + return true; +} + bool NormalizedMode::filterDataRested(QList *urls) { bool filter { false }; @@ -660,6 +733,9 @@ bool NormalizedMode::filterDataRested(QList *urls) bool NormalizedMode::filterDataInserted(const QUrl &url) { + if (ConfigPresenter::instance()->organizeOnTriggered()) + return false; + if (d->classifier) return d->classifier->acceptInsert(url); @@ -668,11 +744,21 @@ bool NormalizedMode::filterDataInserted(const QUrl &url) bool NormalizedMode::filterDataRenamed(const QUrl &oldUrl, const QUrl &newUrl) { - Q_UNUSED(oldUrl); - if (d->classifier) + if (!d->classifier) + return false; + + if (!CfgPresenter->organizeOnTriggered()) return d->classifier->acceptRename(oldUrl, newUrl); - return false; + QString oldType = d->classifier->key(oldUrl); + if (oldType.isEmpty()) // old item is not in collection. + return false; + + QString newType = d->classifier->classify(newUrl); + if (newType != oldType) // the renamed result should be placed on desktop not in collection + return false; + + return true; } bool NormalizedMode::filterShortcutkeyPress(int viewIndex, int key, int modifiers) const diff --git a/src/plugins/desktop/ddplugin-organizer/mode/normalizedmode.h b/src/plugins/desktop/ddplugin-organizer/mode/normalizedmode.h index e194386da8..3309ceb7b6 100644 --- a/src/plugins/desktop/ddplugin-organizer/mode/normalizedmode.h +++ b/src/plugins/desktop/ddplugin-organizer/mode/normalizedmode.h @@ -27,13 +27,15 @@ class NormalizedMode : public CanvasOrganizer void detachLayout() override; public slots: - void rebuild(); + void rebuild(bool reorganize = false); void onFileRenamed(const QUrl &oldUrl, const QUrl &newUrl); void onFileInserted(const QModelIndex &parent, int first, int last); void onFileAboutToBeRemoved(const QModelIndex &parent, int first, int last); void onFileDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles); + void onReorganizeDesktop(); protected slots: + bool filterDropData(int viewIndex, const QMimeData *mimeData, const QPoint &viewPoint) override; bool filterDataRested(QList *urls) override; bool filterDataInserted(const QUrl &url) override; bool filterDataRenamed(const QUrl &oldUrl, const QUrl &newUrl) override; diff --git a/src/plugins/desktop/ddplugin-organizer/options/optionswindow.cpp b/src/plugins/desktop/ddplugin-organizer/options/optionswindow.cpp index 2fd9202909..08a632d7df 100644 --- a/src/plugins/desktop/ddplugin-organizer/options/optionswindow.cpp +++ b/src/plugins/desktop/ddplugin-organizer/options/optionswindow.cpp @@ -121,6 +121,17 @@ bool OptionsWindow::initialize() contentLayout->addWidget(d->sizeSlider); contentLayout->addSpacing(10); + // enable desktop organizer + d->enableOrganize = new SwitchWidget(tr("Enable desktop organizer"), this); + d->enableOrganize->setChecked(CfgPresenter->isEnable()); + d->enableOrganize->setFixedHeight(48); + d->enableOrganize->setRoundEdge(SwitchWidget::kBoth); + contentLayout->addWidget(d->enableOrganize); + connect(d->enableOrganize, &SwitchWidget::checkedChanged, this, [](bool check) { + CfgPresenter->changeEnableState(check); + }); + contentLayout->addSpacing(10); + // organization d->organization = new OrganizationGroup(d->contentWidget); d->organization->reset(); diff --git a/src/plugins/desktop/ddplugin-organizer/options/optionswindow_p.h b/src/plugins/desktop/ddplugin-organizer/options/optionswindow_p.h index a6a7f2096b..ba146fbe4a 100644 --- a/src/plugins/desktop/ddplugin-organizer/options/optionswindow_p.h +++ b/src/plugins/desktop/ddplugin-organizer/options/optionswindow_p.h @@ -27,6 +27,7 @@ class OptionsWindowPrivate : public QObject void setAutoArrange(bool on); void enableChanged(bool enable); void autoArrangeChanged(bool on); + public: QVBoxLayout *mainLayout = nullptr; DTK_WIDGET_NAMESPACE::DTitlebar *titlebar = nullptr; @@ -34,11 +35,13 @@ class OptionsWindowPrivate : public QObject QWidget *contentWidget = nullptr; QVBoxLayout *contentLayout = nullptr; SwitchWidget *autoArrange = nullptr; + SwitchWidget *enableOrganize = nullptr; OrganizationGroup *organization = nullptr; SizeSlider *sizeSlider = nullptr; + private: OptionsWindow *q; }; } -#endif // OPTIONSWINDOW_P_H +#endif // OPTIONSWINDOW_P_H diff --git a/src/plugins/desktop/ddplugin-organizer/organizer_defines.h b/src/plugins/desktop/ddplugin-organizer/organizer_defines.h index e371680f40..058f3d86d3 100644 --- a/src/plugins/desktop/ddplugin-organizer/organizer_defines.h +++ b/src/plugins/desktop/ddplugin-organizer/organizer_defines.h @@ -22,6 +22,11 @@ enum OrganizerMode { kCustom }; +enum OrganizeAction { + kOnTrigger, + kAlways +}; + enum Classifier { kType = 0, kTimeCreated, diff --git a/src/plugins/desktop/ddplugin-organizer/view/collectionview.cpp b/src/plugins/desktop/ddplugin-organizer/view/collectionview.cpp index 9739bcbf37..f7a2f0f533 100644 --- a/src/plugins/desktop/ddplugin-organizer/view/collectionview.cpp +++ b/src/plugins/desktop/ddplugin-organizer/view/collectionview.cpp @@ -14,6 +14,7 @@ #include "broker/collectionhookinterface.h" #include "models/itemselectionmodel.h" #include "config/configpresenter.h" +#include "mode/normalized/fileclassifier.h" #include #include @@ -833,11 +834,11 @@ bool CollectionViewPrivate::dropFromCanvas(QDropEvent *event) const return false; auto firstUrl = urls.first(); - auto firstIndex = q->model()->index(firstUrl); - if (firstIndex.isValid()) { - fmWarning() << "source file belong collection:" << firstUrl; - return false; - } + // auto firstIndex = q->model()->index(firstUrl); + // if (firstIndex.isValid()) { + // fmWarning() << "source file belong collection:" << firstUrl; + // return false; + // } QString errString; auto itemInfo = InfoFactory::create(firstUrl, Global::CreateFileInfoType::kCreateFileInfoAuto, &errString); @@ -863,10 +864,14 @@ bool CollectionViewPrivate::dropFromCanvas(QDropEvent *event) const provider->addPreItems(id, urls, index); + for (auto url : urls) + provider->prepend(url); + selectItems(urls); + for (auto url : urls) canvasModelShell->take(url); - q->model()->fetch(urls); + // q->model()->fetch(urls); return true; } @@ -1029,8 +1034,21 @@ void CollectionViewPrivate::updateDFMMimeData(QDropEvent *event) dfmmimeData = DFMMimeData::fromByteArray(data->data(DFMGLOBAL_NAMESPACE::Mime::kDFMMimeDataKey)); } -bool CollectionViewPrivate::checkTargetEnable(const QUrl &targetUrl) +bool CollectionViewPrivate::checkTargetEnable(QDropEvent *event, const QUrl &targetUrl) { + auto rootUrl = q->model()->rootUrl(); + if (rootUrl == targetUrl) { + auto classfier = dynamic_cast(provider.data()); + if (classfier) { + auto dragUrls = event->mimeData()->urls(); + for (auto url : dragUrls) { + auto type = classfier->classify(url); + if (type != id) + return false; + } + } + } + if (!dfmmimeData.isValid()) return true; @@ -2128,8 +2146,9 @@ void CollectionView::dragMoveEvent(QDragMoveEvent *event) auto pos = event->pos(); auto hoverIndex = indexAt(pos); auto currentUrl = hoverIndex.isValid() ? model()->fileUrl(hoverIndex) : model()->fileUrl(model()->rootIndex()); - if (!d->checkTargetEnable(currentUrl)) { + if (!d->checkTargetEnable(event, currentUrl)) { event->ignore(); + return; } else if (hoverIndex.isValid()) { if (auto fileInfo = model()->fileInfo(hoverIndex)) { // hook diff --git a/src/plugins/desktop/ddplugin-organizer/view/collectionview_p.h b/src/plugins/desktop/ddplugin-organizer/view/collectionview_p.h index 5e5cfc3aef..0901bf7ad3 100644 --- a/src/plugins/desktop/ddplugin-organizer/view/collectionview_p.h +++ b/src/plugins/desktop/ddplugin-organizer/view/collectionview_p.h @@ -90,7 +90,7 @@ class CollectionViewPrivate : public QObject QModelIndex findIndex(const QString &key, bool matchStart, const QModelIndex ¤t, bool reverseOrder, bool excludeCurrent) const; void updateDFMMimeData(QDropEvent *event); - bool checkTargetEnable(const QUrl &targetUrl); + bool checkTargetEnable(QDropEvent *event, const QUrl &targetUrl); private: void updateRowCount(const int &viewHeight, const int &itemHeight);