Changeset View
Changeset View
Standalone View
Standalone View
src/views/dolphinviewactionhandler.cpp
Show All 29 Lines | |||||
30 | #endif | 30 | #endif | ||
31 | #include <KActionCollection> | 31 | #include <KActionCollection> | ||
32 | #include <KActionMenu> | 32 | #include <KActionMenu> | ||
33 | #include <KLocalizedString> | 33 | #include <KLocalizedString> | ||
34 | #include <KNewFileMenu> | 34 | #include <KNewFileMenu> | ||
35 | #include <KPropertiesDialog> | 35 | #include <KPropertiesDialog> | ||
36 | #include <KProtocolManager> | 36 | #include <KProtocolManager> | ||
37 | 37 | | |||
38 | #include "kitemviews/kitemlistselectionmanager.h" | ||||
39 | #include "dolphin_generalsettings.h" | ||||
40 | #include "dolphinitemlistview.h" | ||||
41 | | ||||
42 | #include <KIO/CopyJob> | ||||
43 | #include <KIO/Paste> | ||||
44 | #include <KIO/PasteJob> | ||||
45 | #include <KJobWidgets> | ||||
46 | #include <KIO/DeleteJob> | ||||
47 | #include <KIO/JobUiDelegate> | ||||
48 | #include <KIO/RenameFileDialog> | ||||
49 | #include <KDirModel> | ||||
50 | | ||||
38 | #include <QMenu> | 51 | #include <QMenu> | ||
39 | #include <QPointer> | 52 | #include <QPointer> | ||
53 | #include <QMimeDatabase> | ||||
54 | #include <QMimeData> | ||||
55 | #include <QClipboard> | ||||
56 | #include <QApplication> | ||||
40 | 57 | | |||
41 | DolphinViewActionHandler::DolphinViewActionHandler(KActionCollection* collection, QObject* parent) : | 58 | DolphinViewActionHandler::DolphinViewActionHandler(KActionCollection* collection, QObject* parent) : | ||
42 | QObject(parent), | 59 | QObject(parent), | ||
43 | m_actionCollection(collection), | 60 | m_actionCollection(collection), | ||
44 | m_currentView(nullptr), | 61 | m_currentView(nullptr), | ||
62 | m_currentSelectionManager(nullptr), | ||||
63 | m_currentItemListView(nullptr), | ||||
45 | m_sortByActions(), | 64 | m_sortByActions(), | ||
46 | m_visibleRoles() | 65 | m_visibleRoles() | ||
47 | { | 66 | { | ||
48 | Q_ASSERT(m_actionCollection); | 67 | Q_ASSERT(m_actionCollection); | ||
49 | createActions(); | 68 | createActions(); | ||
50 | } | 69 | } | ||
51 | 70 | | |||
52 | void DolphinViewActionHandler::setCurrentView(DolphinView* view) | 71 | void DolphinViewActionHandler::setCurrentView(DolphinView* view) | ||
Show All 21 Lines | 72 | { | |||
74 | connect(view, &DolphinView::hiddenFilesShownChanged, | 93 | connect(view, &DolphinView::hiddenFilesShownChanged, | ||
75 | this, &DolphinViewActionHandler::slotHiddenFilesShownChanged); | 94 | this, &DolphinViewActionHandler::slotHiddenFilesShownChanged); | ||
76 | connect(view, &DolphinView::sortRoleChanged, | 95 | connect(view, &DolphinView::sortRoleChanged, | ||
77 | this, &DolphinViewActionHandler::slotSortRoleChanged); | 96 | this, &DolphinViewActionHandler::slotSortRoleChanged); | ||
78 | connect(view, &DolphinView::zoomLevelChanged, | 97 | connect(view, &DolphinView::zoomLevelChanged, | ||
79 | this, &DolphinViewActionHandler::slotZoomLevelChanged); | 98 | this, &DolphinViewActionHandler::slotZoomLevelChanged); | ||
80 | connect(view, &DolphinView::writeStateChanged, | 99 | connect(view, &DolphinView::writeStateChanged, | ||
81 | this, &DolphinViewActionHandler::slotWriteStateChanged); | 100 | this, &DolphinViewActionHandler::slotWriteStateChanged); | ||
101 | connect(view, &DolphinView::requestRenameSelectedItems, | ||||
102 | this, &DolphinViewActionHandler::slotRename); | ||||
103 | | ||||
104 | m_currentSelectionManager = view->selectionManager(); | ||||
82 | } | 105 | } | ||
83 | 106 | | |||
84 | DolphinView* DolphinViewActionHandler::currentView() | 107 | DolphinView* DolphinViewActionHandler::currentView() | ||
85 | { | 108 | { | ||
86 | return m_currentView; | 109 | return m_currentView; | ||
87 | } | 110 | } | ||
88 | 111 | | |||
112 | void DolphinViewActionHandler::setCurrentSelectionManager(KItemListSelectionManager* selectionManager) | ||||
113 | { | ||||
114 | m_currentSelectionManager = selectionManager; | ||||
115 | } | ||||
116 | | ||||
117 | void DolphinViewActionHandler::setCurrentItemListView(KFileItemListView* view) | ||||
118 | { | ||||
119 | m_currentItemListView = view; | ||||
120 | } | ||||
121 | | ||||
89 | void DolphinViewActionHandler::createActions() | 122 | void DolphinViewActionHandler::createActions() | ||
90 | { | 123 | { | ||
91 | // This action doesn't appear in the GUI, it's for the shortcut only. | 124 | // This action doesn't appear in the GUI, it's for the shortcut only. | ||
92 | // KNewFileMenu takes care of the GUI stuff. | 125 | // KNewFileMenu takes care of the GUI stuff. | ||
93 | QAction* newDirAction = m_actionCollection->addAction(QStringLiteral("create_dir")); | 126 | QAction* newDirAction = m_actionCollection->addAction(QStringLiteral("create_dir")); | ||
94 | newDirAction->setText(i18nc("@action", "Create Folder...")); | 127 | newDirAction->setText(i18nc("@action", "Create Folder...")); | ||
95 | m_actionCollection->setDefaultShortcut(newDirAction, Qt::Key_F10); | 128 | m_actionCollection->setDefaultShortcut(newDirAction, Qt::Key_F10); | ||
96 | newDirAction->setIcon(QIcon::fromTheme(QStringLiteral("folder-new"))); | 129 | newDirAction->setIcon(QIcon::fromTheme(QStringLiteral("folder-new"))); | ||
▲ Show 20 Lines • Show All 269 Lines • ▼ Show 20 Line(s) | 356 | foreach (const KFileItemModel::RoleInfo& info, rolesInfo) { | |||
366 | } else { | 399 | } else { | ||
367 | m_visibleRoles.insert(info.role, action); | 400 | m_visibleRoles.insert(info.role, action); | ||
368 | } | 401 | } | ||
369 | } | 402 | } | ||
370 | 403 | | |||
371 | return rolesActionGroup; | 404 | return rolesActionGroup; | ||
372 | } | 405 | } | ||
373 | 406 | | |||
407 | | ||||
408 | QMimeData* DolphinViewActionHandler::selectionMimeData() | ||||
409 | { | ||||
410 | return m_currentSelectionManager->model()->createMimeData(selectedItemSet()); | ||||
411 | } | ||||
412 | | ||||
413 | KItemSet DolphinViewActionHandler::selectedItemSet() | ||||
414 | { | ||||
415 | return m_currentSelectionManager->selectedItems(); | ||||
416 | } | ||||
417 | | ||||
418 | KFileItemList DolphinViewActionHandler::selectedItems() | ||||
419 | { | ||||
420 | KFileItemList selectedItems; | ||||
421 | const auto items = selectedItemSet(); | ||||
422 | const auto model = qobject_cast<KFileItemModel *>(m_currentSelectionManager->model()); | ||||
423 | | ||||
424 | selectedItems.reserve(items.count()); | ||||
425 | for (int index : items) { | ||||
426 | selectedItems.append(model->fileItem(index)); | ||||
427 | } | ||||
428 | return selectedItems; | ||||
429 | } | ||||
430 | | ||||
431 | QList<QUrl> DolphinViewActionHandler::simplifiedSelectedUrls() | ||||
432 | { | ||||
433 | QList<QUrl> urls; | ||||
434 | | ||||
435 | const KFileItemList items = selectedItems(); | ||||
436 | urls.reserve(items.count()); | ||||
437 | for (const KFileItem& item: items) { | ||||
438 | urls.append(item.url()); | ||||
439 | } | ||||
440 | | ||||
441 | if (m_currentView->itemsExpandable()) { | ||||
442 | urls = KDirModel::simplifiedUrlList(urls); | ||||
443 | } | ||||
444 | | ||||
445 | return urls; | ||||
446 | } | ||||
447 | | ||||
448 | void DolphinViewActionHandler::cut() | ||||
449 | { | ||||
450 | QMimeData* mimeData = selectionMimeData(); | ||||
451 | KIO::setClipboardDataCut(mimeData, true); | ||||
452 | QApplication::clipboard()->setMimeData(mimeData); | ||||
453 | } | ||||
454 | | ||||
455 | void DolphinViewActionHandler::copy() | ||||
456 | { | ||||
457 | QMimeData* mimeData = selectionMimeData(); | ||||
458 | QApplication::clipboard()->setMimeData(mimeData); | ||||
459 | } | ||||
460 | | ||||
461 | void DolphinViewActionHandler::paste() | ||||
462 | { | ||||
463 | auto* model = qobject_cast<KFileItemModel *>(m_currentSelectionManager->model()); | ||||
464 | // first selected item | ||||
465 | const KFileItem& item = model->fileItem(*m_currentSelectionManager->selectedItems().constBegin()); | ||||
466 | | ||||
467 | KIO::PasteJob *job = KIO::paste(QApplication::clipboard()->mimeData(), item.url()); | ||||
468 | KJobWidgets::setWindow(job, m_currentView->window()); | ||||
469 | | ||||
470 | // issue with m_markFirstNewlySelectedItemAsCurrent + m_markFirstNewlySelectedItemAsCurrent | ||||
471 | connect(job, &KIO::PasteJob::itemCreated, m_currentView, &DolphinView::slotItemCreated); | ||||
472 | connect(job, &KIO::PasteJob::result, m_currentView, &DolphinView::slotPasteJobResult); | ||||
473 | } | ||||
474 | | ||||
475 | void DolphinViewActionHandler::pasteIntoFolder() | ||||
476 | { | ||||
477 | const KFileItemList items = selectedItems(); | ||||
478 | if (items.count() == 1) { | ||||
479 | | ||||
480 | const KFileItem& item = items.at(0); | ||||
481 | if (item.isDir()) { | ||||
482 | | ||||
483 | m_currentView->prepareToPaste(); | ||||
484 | | ||||
485 | KIO::PasteJob *job = KIO::paste(QApplication::clipboard()->mimeData(), item.url()); | ||||
486 | KJobWidgets::setWindow(job, m_currentView->window()); | ||||
487 | | ||||
488 | connect(job, &KIO::PasteJob::itemCreated, m_currentView, &DolphinView::slotItemCreated); | ||||
489 | connect(job, &KIO::PasteJob::result, m_currentView, &DolphinView::slotPasteJobResult); | ||||
490 | } | ||||
491 | } | ||||
492 | } | ||||
493 | | ||||
374 | void DolphinViewActionHandler::slotViewModeActionTriggered(QAction* action) | 494 | void DolphinViewActionHandler::slotViewModeActionTriggered(QAction* action) | ||
375 | { | 495 | { | ||
376 | const DolphinView::Mode mode = action->data().value<DolphinView::Mode>(); | 496 | const DolphinView::Mode mode = action->data().value<DolphinView::Mode>(); | ||
377 | m_currentView->setMode(mode); | 497 | m_currentView->setMode(mode); | ||
378 | 498 | | |||
379 | QAction* viewModeMenu = m_actionCollection->action(QStringLiteral("view_mode")); | 499 | QAction* viewModeMenu = m_actionCollection->action(QStringLiteral("view_mode")); | ||
380 | viewModeMenu->setIcon(action->icon()); | 500 | viewModeMenu->setIcon(action->icon()); | ||
381 | } | 501 | } | ||
382 | 502 | | |||
383 | void DolphinViewActionHandler::slotRename() | 503 | void DolphinViewActionHandler::slotRename() | ||
384 | { | 504 | { | ||
385 | emit actionBeingHandled(); | 505 | emit actionBeingHandled(); | ||
386 | m_currentView->renameSelectedItems(); | 506 | const KFileItemList items = selectedItems(); | ||
507 | if (items.isEmpty()) { | ||||
508 | return; | ||||
509 | } | ||||
510 | | ||||
511 | bool listEditInview = items.count() == 1 && GeneralSettings::renameInline(); | ||||
512 | int index; | ||||
513 | if (listEditInview) { | ||||
514 | const auto model = qobject_cast<KFileItemModel *>(m_currentSelectionManager->model()); | ||||
515 | index = model->index(items.first()); | ||||
516 | listEditInview = index != -1; | ||||
517 | } | ||||
518 | if (listEditInview) { | ||||
519 | if (m_currentSelectionManager == m_currentView->selectionManager()) { | ||||
520 | m_currentView->listView()->editRole(index, "text"); | ||||
521 | } else if (m_currentItemListView != nullptr) { | ||||
522 | m_currentItemListView->editRole(index, "text"); | ||||
523 | } | ||||
524 | m_currentView->hideToolTip(); | ||||
525 | | ||||
526 | connect(m_currentView->listView(), &DolphinItemListView::roleEditingFinished, | ||||
527 | m_currentView, &DolphinView::slotRoleEditingFinished); | ||||
528 | | ||||
529 | } else { | ||||
530 | KIO::RenameFileDialog* dialog = new KIO::RenameFileDialog(items, m_currentView); | ||||
531 | connect(dialog, &KIO::RenameFileDialog::renamingFinished, | ||||
532 | m_currentView, &DolphinView::slotRenameDialogRenamingFinished); | ||||
533 | | ||||
534 | dialog->open(); | ||||
535 | } | ||||
387 | } | 536 | } | ||
388 | 537 | | |||
389 | void DolphinViewActionHandler::slotTrashActivated() | 538 | void DolphinViewActionHandler::slotTrashActivated() | ||
390 | { | 539 | { | ||
391 | emit actionBeingHandled(); | 540 | emit actionBeingHandled(); | ||
392 | m_currentView->trashSelectedItems(); | 541 | const QList<QUrl> list = simplifiedSelectedUrls(); | ||
542 | KIO::JobUiDelegate uiDelegate; | ||||
543 | uiDelegate.setWindow(m_currentView->window()); | ||||
544 | if (uiDelegate.askDeleteConfirmation(list, KIO::JobUiDelegate::Trash, KIO::JobUiDelegate::DefaultConfirmation)) { | ||||
545 | KIO::Job* job = KIO::trash(list); | ||||
546 | KIO::FileUndoManager::self()->recordJob(KIO::FileUndoManager::Trash, list, QUrl(QStringLiteral("trash:/")), job); | ||||
547 | KJobWidgets::setWindow(job, m_currentView->window()); | ||||
548 | | ||||
549 | // signal to view | ||||
550 | connect(job, &KIO::Job::result, | ||||
551 | m_currentView, &DolphinView::slotTrashFileFinished); | ||||
552 | } | ||||
393 | } | 553 | } | ||
394 | 554 | | |||
395 | void DolphinViewActionHandler::slotDeleteItems() | 555 | void DolphinViewActionHandler::slotDeleteItems() | ||
396 | { | 556 | { | ||
397 | emit actionBeingHandled(); | 557 | emit actionBeingHandled(); | ||
398 | m_currentView->deleteSelectedItems(); | 558 | const QList<QUrl> list = simplifiedSelectedUrls(); | ||
559 | KIO::JobUiDelegate uiDelegate; | ||||
560 | uiDelegate.setWindow(m_currentView->window()); | ||||
561 | if (uiDelegate.askDeleteConfirmation(list, KIO::JobUiDelegate::Delete, KIO::JobUiDelegate::DefaultConfirmation)) { | ||||
562 | KIO::Job* job = KIO::del(list); | ||||
563 | KJobWidgets::setWindow(job, m_currentView->window()); | ||||
564 | | ||||
565 | // signal to view | ||||
566 | connect(job, &KIO::Job::result, m_currentView, &DolphinView::slotDeleteFileFinished); | ||||
567 | } | ||||
399 | } | 568 | } | ||
400 | 569 | | |||
401 | void DolphinViewActionHandler::togglePreview(bool show) | 570 | void DolphinViewActionHandler::togglePreview(bool show) | ||
402 | { | 571 | { | ||
403 | emit actionBeingHandled(); | 572 | emit actionBeingHandled(); | ||
404 | m_currentView->setPreviewsShown(show); | 573 | m_currentView->setPreviewsShown(show); | ||
405 | } | 574 | } | ||
406 | 575 | | |||
▲ Show 20 Lines • Show All 278 Lines • ▼ Show 20 Line(s) | 852 | { | |||
685 | QPointer<ViewPropertiesDialog> dialog = new ViewPropertiesDialog(m_currentView); | 854 | QPointer<ViewPropertiesDialog> dialog = new ViewPropertiesDialog(m_currentView); | ||
686 | dialog->exec(); | 855 | dialog->exec(); | ||
687 | delete dialog; | 856 | delete dialog; | ||
688 | } | 857 | } | ||
689 | 858 | | |||
690 | void DolphinViewActionHandler::slotDuplicate() | 859 | void DolphinViewActionHandler::slotDuplicate() | ||
691 | { | 860 | { | ||
692 | emit actionBeingHandled(); | 861 | emit actionBeingHandled(); | ||
693 | m_currentView->duplicateSelectedItems(); | 862 | const KFileItemList itemList = selectedItems(); | ||
863 | if (itemList.isEmpty()) { | ||||
864 | return; | ||||
865 | } | ||||
866 | | ||||
867 | const QMimeDatabase db; | ||||
868 | | ||||
869 | // Duplicate all selected items and append "copy" to the end of the file name | ||||
870 | // but before the filename extension, if present | ||||
871 | QList<QUrl> newSelection; | ||||
872 | for (const auto &item : itemList) { | ||||
873 | const QUrl originalURL = item.url(); | ||||
874 | const QString originalDirectoryPath = originalURL.adjusted(QUrl::RemoveFilename).path(); | ||||
875 | const QString originalFileName = item.name(); | ||||
876 | | ||||
877 | QString extension = db.suffixForFileName(originalFileName); | ||||
878 | | ||||
879 | QUrl duplicateURL = originalURL; | ||||
880 | | ||||
881 | // No extension; new filename is "<oldfilename> copy" | ||||
882 | if (extension.isEmpty()) { | ||||
883 | duplicateURL.setPath(originalDirectoryPath + i18nc("<filename> copy", "%1 copy", originalFileName)); | ||||
884 | // There's an extension; new filename is "<oldfilename> copy.<extension>" | ||||
885 | } else { | ||||
886 | // Need to add a dot since QMimeDatabase::suffixForFileName() doesn't include it | ||||
887 | extension = QLatin1String(".") + extension; | ||||
888 | const QString originalFilenameWithoutExtension = originalFileName.chopped(extension.size()); | ||||
889 | // Preserve file's original filename extension in case the casing differs | ||||
890 | // from what QMimeDatabase::suffixForFileName() returned | ||||
891 | const QString originalExtension = originalFileName.right(extension.size()); | ||||
892 | duplicateURL.setPath(originalDirectoryPath + i18nc("<filename> copy", "%1 copy", originalFilenameWithoutExtension) + originalExtension); | ||||
893 | } | ||||
894 | | ||||
895 | KIO::CopyJob* job = KIO::copyAs(originalURL, duplicateURL, KIO::HideProgressInfo); | ||||
896 | KJobWidgets::setWindow(job, m_currentView); | ||||
897 | | ||||
898 | if (job) { | ||||
899 | newSelection << duplicateURL; | ||||
900 | KIO::FileUndoManager::self()->recordCopyJob(job); | ||||
901 | } | ||||
902 | } | ||||
903 | | ||||
904 | m_currentView->forceUrlsSelection(newSelection.first(), newSelection); | ||||
694 | } | 905 | } | ||
695 | 906 | | |||
696 | void DolphinViewActionHandler::slotProperties() | 907 | void DolphinViewActionHandler::slotProperties() | ||
697 | { | 908 | { | ||
698 | KPropertiesDialog* dialog = nullptr; | 909 | KPropertiesDialog* dialog = nullptr; | ||
699 | const KFileItemList list = m_currentView->selectedItems(); | 910 | const KFileItemList list = selectedItems(); | ||
700 | if (list.isEmpty()) { | 911 | if (list.isEmpty()) { | ||
701 | const QUrl url = m_currentView->url(); | 912 | const QUrl url = m_currentView->url(); | ||
702 | dialog = new KPropertiesDialog(url, m_currentView); | 913 | dialog = new KPropertiesDialog(url, m_currentView); | ||
703 | } else { | 914 | } else { | ||
704 | dialog = new KPropertiesDialog(list, m_currentView); | 915 | dialog = new KPropertiesDialog(list, m_currentView); | ||
705 | } | 916 | } | ||
706 | 917 | | |||
707 | dialog->setAttribute(Qt::WA_DeleteOnClose); | 918 | dialog->setAttribute(Qt::WA_DeleteOnClose); | ||
708 | dialog->show(); | 919 | dialog->show(); | ||
709 | dialog->raise(); | 920 | dialog->raise(); | ||
710 | dialog->activateWindow(); | 921 | dialog->activateWindow(); | ||
711 | } | 922 | } |