Changeset View
Changeset View
Standalone View
Standalone View
plugins/projectmanagerview/projectmanagerviewplugin.cpp
Show All 26 Lines | |||||
27 | #include <QMimeData> | 27 | #include <QMimeData> | ||
28 | #include <QUrl> | 28 | #include <QUrl> | ||
29 | 29 | | |||
30 | #include <KActionCollection> | 30 | #include <KActionCollection> | ||
31 | #include <KLocalizedString> | 31 | #include <KLocalizedString> | ||
32 | #include <KMessageBox> | 32 | #include <KMessageBox> | ||
33 | #include <KParts/MainWindow> | 33 | #include <KParts/MainWindow> | ||
34 | #include <KPluginFactory> | 34 | #include <KPluginFactory> | ||
35 | #include <KIO/Paste> | ||||
36 | #include <KFileItem> | ||||
37 | #include <KUrlMimeData> | ||||
35 | 38 | | |||
36 | #include <project/projectmodel.h> | 39 | #include <project/projectmodel.h> | ||
37 | #include <project/projectbuildsetmodel.h> | 40 | #include <project/projectbuildsetmodel.h> | ||
38 | #include <interfaces/icore.h> | 41 | #include <interfaces/icore.h> | ||
39 | #include <interfaces/iproject.h> | 42 | #include <interfaces/iproject.h> | ||
40 | #include <project/interfaces/iprojectfilemanager.h> | 43 | #include <project/interfaces/iprojectfilemanager.h> | ||
41 | #include <project/interfaces/ibuildsystemmanager.h> | 44 | #include <project/interfaces/ibuildsystemmanager.h> | ||
42 | #include <interfaces/iuicontroller.h> | 45 | #include <interfaces/iuicontroller.h> | ||
Show All 10 Lines | |||||
53 | #include "projectmanagerview.h" | 56 | #include "projectmanagerview.h" | ||
54 | #include "debug.h" | 57 | #include "debug.h" | ||
55 | 58 | | |||
56 | using namespace KDevelop; | 59 | using namespace KDevelop; | ||
57 | 60 | | |||
58 | Q_LOGGING_CATEGORY(PLUGIN_PROJECTMANAGERVIEW, "kdevplatform.plugins.projectmanagerview") | 61 | Q_LOGGING_CATEGORY(PLUGIN_PROJECTMANAGERVIEW, "kdevplatform.plugins.projectmanagerview") | ||
59 | K_PLUGIN_FACTORY_WITH_JSON(ProjectManagerFactory, "kdevprojectmanagerview.json", registerPlugin<ProjectManagerViewPlugin>();) | 62 | K_PLUGIN_FACTORY_WITH_JSON(ProjectManagerFactory, "kdevprojectmanagerview.json", registerPlugin<ProjectManagerViewPlugin>();) | ||
60 | 63 | | |||
64 | static QAction* createSeparatorAction() | ||||
mwolff: instead of static, wrap it in an anonymous namespace
the result is the same, but I much prefer… | |||||
65 | { | ||||
66 | QAction* separator = new QAction(nullptr); | ||||
67 | separator->setSeparator(true); | ||||
68 | return separator; | ||||
69 | } | ||||
70 | | ||||
61 | class KDevProjectManagerViewFactory: public KDevelop::IToolViewFactory | 71 | class KDevProjectManagerViewFactory: public KDevelop::IToolViewFactory | ||
62 | { | 72 | { | ||
63 | public: | 73 | public: | ||
64 | KDevProjectManagerViewFactory( ProjectManagerViewPlugin *plugin ): mplugin( plugin ) | 74 | KDevProjectManagerViewFactory( ProjectManagerViewPlugin *plugin ): mplugin( plugin ) | ||
65 | {} | 75 | {} | ||
66 | QWidget* create( QWidget *parent = 0 ) override | 76 | QWidget* create( QWidget *parent = 0 ) override | ||
67 | { | 77 | { | ||
68 | return new ProjectManagerView( mplugin, parent ); | 78 | return new ProjectManagerView( mplugin, parent ); | ||
▲ Show 20 Lines • Show All 138 Lines • ▼ Show 20 Line(s) | 206 | { | |||
207 | 217 | | |||
208 | //TODO: also needs: removeTarget, removeFileFromTarget, runTargetsFromContextMenu | 218 | //TODO: also needs: removeTarget, removeFileFromTarget, runTargetsFromContextMenu | ||
209 | ContextMenuExtension menuExt; | 219 | ContextMenuExtension menuExt; | ||
210 | bool needsCreateFile = true; | 220 | bool needsCreateFile = true; | ||
211 | bool needsCreateFolder = true; | 221 | bool needsCreateFolder = true; | ||
212 | bool needsCloseProjects = true; | 222 | bool needsCloseProjects = true; | ||
213 | bool needsBuildItems = true; | 223 | bool needsBuildItems = true; | ||
214 | bool needsFolderItems = true; | 224 | bool needsFolderItems = true; | ||
215 | bool needsRemoveAndRename = true; | 225 | bool needsCutRenameRemove = true; | ||
216 | bool needsRemoveTargetFiles = true; | 226 | bool needsRemoveTargetFiles = true; | ||
217 | bool needsPaste = true; | 227 | bool needsPaste = true; | ||
218 | 228 | | |||
219 | //needsCreateFile if there is one item and it's a folder or target | 229 | //needsCreateFile if there is one item and it's a folder or target | ||
220 | needsCreateFile &= (items.count() == 1) && (items.first()->folder() || items.first()->target()); | 230 | needsCreateFile &= (items.count() == 1) && (items.first()->folder() || items.first()->target()); | ||
221 | //needsCreateFolder if there is one item and it's a folder | 231 | //needsCreateFolder if there is one item and it's a folder | ||
222 | needsCreateFolder &= (items.count() == 1) && (items.first()->folder()); | 232 | needsCreateFolder &= (items.count() == 1) && (items.first()->folder()); | ||
223 | needsPaste = needsCreateFolder; | 233 | needsPaste = needsCreateFolder; | ||
224 | 234 | | |||
225 | foreach( ProjectBaseItem* item, items ) { | 235 | foreach( ProjectBaseItem* item, items ) { | ||
226 | d->ctxProjectItemList << item->index(); | 236 | d->ctxProjectItemList << item->index(); | ||
227 | //needsBuildItems if items are limited to targets and buildfolders | 237 | //needsBuildItems if items are limited to targets and buildfolders | ||
228 | needsBuildItems &= item->target() || item->type() == ProjectBaseItem::BuildFolder; | 238 | needsBuildItems &= item->target() || item->type() == ProjectBaseItem::BuildFolder; | ||
229 | 239 | | |||
230 | //needsCloseProjects if items are limited to top level folders (Project Folders) | 240 | //needsCloseProjects if items are limited to top level folders (Project Folders) | ||
231 | needsCloseProjects &= item->folder() && !item->folder()->parent(); | 241 | needsCloseProjects &= item->folder() && !item->folder()->parent(); | ||
232 | 242 | | |||
233 | //needsFolderItems if items are limited to folders | 243 | //needsFolderItems if items are limited to folders | ||
234 | needsFolderItems &= (bool)item->folder(); | 244 | needsFolderItems &= (bool)item->folder(); | ||
235 | 245 | | |||
236 | //needsRemove if items are limited to non-top-level folders or files that don't belong to targets | 246 | //needsRemove if items are limited to non-top-level folders or files that don't belong to targets | ||
237 | needsRemoveAndRename &= (item->folder() && item->parent()) || (item->file() && !item->parent()->target()); | 247 | needsCutRenameRemove &= (item->folder() && item->parent()) || (item->file() && !item->parent()->target()); | ||
this means we cannot paste into the project root, no? since the project root has no parent, but is a folder? mwolff: this means we cannot paste into the project root, no? since the project root has no parent, but… | |||||
No, this means we cannot cut/rename/delete the project root. I didn't invent this logic, it has been there and worked well for a few years already. aspotashev: No, this means we cannot cut/rename/delete the project root. I didn't invent this logic, it has… | |||||
238 | 248 | | |||
239 | //needsRemoveTargets if items are limited to file items with target parents | 249 | //needsRemoveTargets if items are limited to file items with target parents | ||
240 | needsRemoveTargetFiles &= (item->file() && item->parent()->target()); | 250 | needsRemoveTargetFiles &= (item->file() && item->parent()->target()); | ||
241 | } | 251 | } | ||
242 | 252 | | |||
243 | if ( needsCreateFile ) { | 253 | if ( needsCreateFile ) { | ||
244 | QAction* action = new QAction( i18n( "Create File..." ), this ); | 254 | QAction* action = new QAction( i18n( "Create File..." ), this ); | ||
245 | action->setIcon(QIcon::fromTheme(QStringLiteral("document-new"))); | 255 | action->setIcon(QIcon::fromTheme(QStringLiteral("document-new"))); | ||
Show All 33 Lines | 285 | if ( needsCloseProjects ) { | |||
279 | menuExt.addAction( ContextMenuExtension::ProjectGroup, close ); | 289 | menuExt.addAction( ContextMenuExtension::ProjectGroup, close ); | ||
280 | } | 290 | } | ||
281 | if ( needsFolderItems ) { | 291 | if ( needsFolderItems ) { | ||
282 | QAction* action = new QAction( i18n( "Reload" ), this ); | 292 | QAction* action = new QAction( i18n( "Reload" ), this ); | ||
283 | action->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); | 293 | action->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); | ||
284 | connect( action, &QAction::triggered, this, &ProjectManagerViewPlugin::reloadFromContextMenu ); | 294 | connect( action, &QAction::triggered, this, &ProjectManagerViewPlugin::reloadFromContextMenu ); | ||
285 | menuExt.addAction( ContextMenuExtension::FileGroup, action ); | 295 | menuExt.addAction( ContextMenuExtension::FileGroup, action ); | ||
286 | } | 296 | } | ||
287 | if ( needsRemoveAndRename ) { | 297 | | ||
298 | // Populating cut/copy/paste group | ||||
299 | if (!menuExt.actions(ContextMenuExtension::FileGroup).isEmpty()) { | ||||
300 | menuExt.addAction(ContextMenuExtension::FileGroup, createSeparatorAction()); | ||||
301 | } | ||||
302 | if (needsCutRenameRemove) { | ||||
303 | QAction* cut = KStandardAction::cut(this, SLOT(cutFromContextMenu()), this); | ||||
304 | cut->setShortcutContext(Qt::WidgetShortcut); | ||||
305 | menuExt.addAction(ContextMenuExtension::FileGroup, cut); | ||||
306 | } | ||||
307 | { | ||||
308 | QAction* copy = KStandardAction::copy(this, SLOT(copyFromContextMenu()), this); | ||||
309 | copy->setShortcutContext(Qt::WidgetShortcut); | ||||
310 | menuExt.addAction( ContextMenuExtension::FileGroup, copy ); | ||||
311 | } | ||||
312 | if (needsPaste) { | ||||
313 | QAction* paste = KStandardAction::paste(this, SLOT(pasteFromContextMenu()), this); | ||||
314 | paste->setShortcutContext(Qt::WidgetShortcut); | ||||
315 | menuExt.addAction( ContextMenuExtension::FileGroup, paste ); | ||||
316 | } | ||||
317 | | ||||
318 | // Populating rename/remove group | ||||
319 | { | ||||
320 | menuExt.addAction(ContextMenuExtension::FileGroup, createSeparatorAction()); | ||||
321 | } | ||||
322 | if (needsCutRenameRemove) { | ||||
288 | QAction* remove = new QAction( i18n( "Remove" ), this ); | 323 | QAction* remove = new QAction( i18n( "Remove" ), this ); | ||
289 | remove->setIcon(QIcon::fromTheme(QStringLiteral("user-trash"))); | 324 | remove->setIcon(QIcon::fromTheme(QStringLiteral("user-trash"))); | ||
290 | connect( remove, &QAction::triggered, this, &ProjectManagerViewPlugin::removeFromContextMenu ); | 325 | connect( remove, &QAction::triggered, this, &ProjectManagerViewPlugin::removeFromContextMenu ); | ||
291 | menuExt.addAction( ContextMenuExtension::FileGroup, remove ); | 326 | menuExt.addAction( ContextMenuExtension::FileGroup, remove ); | ||
327 | | ||||
292 | QAction* rename = new QAction( i18n( "Rename..." ), this ); | 328 | QAction* rename = new QAction( i18n( "Rename..." ), this ); | ||
293 | rename->setIcon(QIcon::fromTheme(QStringLiteral("edit-rename"))); | 329 | rename->setIcon(QIcon::fromTheme(QStringLiteral("edit-rename"))); | ||
294 | connect( rename, &QAction::triggered, this, &ProjectManagerViewPlugin::renameItemFromContextMenu ); | 330 | connect( rename, &QAction::triggered, this, &ProjectManagerViewPlugin::renameItemFromContextMenu ); | ||
295 | menuExt.addAction( ContextMenuExtension::FileGroup, rename ); | 331 | menuExt.addAction( ContextMenuExtension::FileGroup, rename ); | ||
296 | } | 332 | } | ||
297 | if ( needsRemoveTargetFiles ) { | 333 | if ( needsRemoveTargetFiles ) { | ||
298 | QAction* remove = new QAction( i18n( "Remove From Target" ), this ); | 334 | QAction* remove = new QAction( i18n( "Remove From Target" ), this ); | ||
299 | remove->setIcon(QIcon::fromTheme(QStringLiteral("user-trash"))); | 335 | remove->setIcon(QIcon::fromTheme(QStringLiteral("user-trash"))); | ||
300 | connect( remove, &QAction::triggered, this, &ProjectManagerViewPlugin::removeTargetFilesFromContextMenu ); | 336 | connect( remove, &QAction::triggered, this, &ProjectManagerViewPlugin::removeTargetFilesFromContextMenu ); | ||
301 | menuExt.addAction( ContextMenuExtension::FileGroup, remove ); | 337 | menuExt.addAction( ContextMenuExtension::FileGroup, remove ); | ||
302 | } | 338 | } | ||
303 | 339 | | |||
304 | { | 340 | if (needsCutRenameRemove || needsRemoveTargetFiles) { | ||
305 | QAction* copy = KStandardAction::copy(this, SLOT(copyFromContextMenu()), this); | 341 | menuExt.addAction(ContextMenuExtension::FileGroup, createSeparatorAction()); | ||
306 | copy->setShortcutContext(Qt::WidgetShortcut); | | |||
307 | menuExt.addAction( ContextMenuExtension::FileGroup, copy ); | | |||
308 | } | | |||
309 | if (needsPaste) { | | |||
310 | QAction* paste = KStandardAction::paste(this, SLOT(pasteFromContextMenu()), this); | | |||
311 | paste->setShortcutContext(Qt::WidgetShortcut); | | |||
312 | menuExt.addAction( ContextMenuExtension::FileGroup, paste ); | | |||
313 | } | 342 | } | ||
314 | 343 | | |||
315 | return menuExt; | 344 | return menuExt; | ||
316 | } | 345 | } | ||
317 | 346 | | |||
318 | void ProjectManagerViewPlugin::closeProjects() | 347 | void ProjectManagerViewPlugin::closeProjects() | ||
319 | { | 348 | { | ||
320 | QList<KDevelop::IProject*> projectsToClose; | 349 | QList<KDevelop::IProject*> projectsToClose; | ||
▲ Show 20 Lines • Show All 330 Lines • ▼ Show 20 Line(s) | 679 | { | |||
651 | ProjectFileItem* f=createFile(folder); | 680 | ProjectFileItem* f=createFile(folder); | ||
652 | if(f) | 681 | if(f) | ||
653 | item->project()->buildSystemManager()->addFilesToTarget(QList<ProjectFileItem*>() << f, item->target()); | 682 | item->project()->buildSystemManager()->addFilesToTarget(QList<ProjectFileItem*>() << f, item->target()); | ||
654 | } | 683 | } | ||
655 | } | 684 | } | ||
656 | } | 685 | } | ||
657 | } | 686 | } | ||
658 | 687 | | |||
659 | void ProjectManagerViewPlugin::copyFromContextMenu() | 688 | QMimeData* ProjectManagerViewPlugin::createClipboardMimeData(bool cut) | ||
660 | { | 689 | { | ||
661 | KDevelop::ProjectItemContext* ctx = dynamic_cast<KDevelop::ProjectItemContext*>(ICore::self()->selectionController()->currentSelection()); | 690 | auto* ctx = dynamic_cast<KDevelop::ProjectItemContext*>( | ||
691 | ICore::self()->selectionController()->currentSelection()); | ||||
kfunk: Could do `auto ctx = ...` | |||||
662 | QList<QUrl> urls; | 692 | QList<QUrl> urls; | ||
693 | QList<QUrl> mostLocalUrls; | ||||
663 | foreach (ProjectBaseItem* item, ctx->items()) { | 694 | foreach (ProjectBaseItem* item, ctx->items()) { | ||
kfunk: Not needed | |||||
664 | if (item->folder() || item->file()) { | 695 | if (item->folder() || item->file()) { | ||
665 | urls << item->path().toUrl(); | 696 | const QUrl& url = item->path().toUrl(); | ||
697 | urls << url; | ||||
698 | mostLocalUrls << KFileItem(url).mostLocalUrl(); | ||||
kfunk: `KFileItem(url).mostLocalUrl()` should work? | |||||
666 | } | 699 | } | ||
667 | } | 700 | } | ||
668 | qCDebug(PLUGIN_PROJECTMANAGERVIEW) << urls; | 701 | qCDebug(PLUGIN_PROJECTMANAGERVIEW) << urls; | ||
669 | if (!urls.isEmpty()) { | 702 | | ||
670 | QMimeData* data = new QMimeData; | 703 | if (urls.isEmpty()) { | ||
671 | data->setUrls(urls); | 704 | return nullptr; | ||
672 | qApp->clipboard()->setMimeData(data); | 705 | } | ||
706 | | ||||
707 | QMimeData* mimeData = new QMimeData; | ||||
708 | KIO::setClipboardDataCut(mimeData, cut); | ||||
709 | KUrlMimeData::setUrls(urls, mostLocalUrls, mimeData); | ||||
710 | return mimeData; | ||||
711 | } | ||||
712 | | ||||
713 | void ProjectManagerViewPlugin::copyFromContextMenu() | ||||
714 | { | ||||
715 | qApp->clipboard()->setMimeData(createClipboardMimeData(false)); | ||||
673 | } | 716 | } | ||
717 | | ||||
718 | void ProjectManagerViewPlugin::cutFromContextMenu() | ||||
719 | { | ||||
720 | qApp->clipboard()->setMimeData(createClipboardMimeData(true)); | ||||
674 | } | 721 | } | ||
675 | 722 | | |||
676 | void ProjectManagerViewPlugin::pasteFromContextMenu() | 723 | void ProjectManagerViewPlugin::pasteFromContextMenu() | ||
677 | { | 724 | { | ||
678 | KDevelop::ProjectItemContext* ctx = dynamic_cast<KDevelop::ProjectItemContext*>(ICore::self()->selectionController()->currentSelection()); | 725 | KDevelop::ProjectItemContext* ctx = dynamic_cast<KDevelop::ProjectItemContext*>(ICore::self()->selectionController()->currentSelection()); | ||
679 | if (ctx->items().count() != 1) | 726 | if (ctx->items().count() != 1) | ||
680 | return; //do nothing if multiple or none items are selected | 727 | return; //do nothing if multiple or none items are selected | ||
681 | 728 | | |||
Show All 23 Lines | 749 | foreach (ProjectBaseItem *item, destItem->children()) { | |||
705 | } | 752 | } | ||
706 | } | 753 | } | ||
707 | } | 754 | } | ||
708 | viewCtx->view()->selectItems(newItems); | 755 | viewCtx->view()->selectItems(newItems); | ||
709 | } | 756 | } | ||
710 | } | 757 | } | ||
711 | } | 758 | } | ||
712 | 759 | | |||
713 | | ||||
714 | #include "projectmanagerviewplugin.moc" | 760 | #include "projectmanagerviewplugin.moc" | ||
Can be a free function inside namespace {}. I'd also rename to createSeparatorAction kfunk: Can be a free function inside `namespace {}`.
I'd also rename to `createSeparatorAction` | |||||
Changed to a static function instead because namespace {} takes more lines of code and is harder to read. aspotashev: Changed to a static function instead because namespace {} takes more lines of code and is… | |||||
715 | 761 | |
instead of static, wrap it in an anonymous namespace
the result is the same, but I much prefer the C++ way of doing this