┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dolphincontextmenu.cpp1
-rw-r--r--src/dolphinmainwindow.cpp2
-rw-r--r--src/dolphinui.rc5
-rw-r--r--src/views/dolphinview.cpp45
-rw-r--r--src/views/dolphinview.h6
-rw-r--r--src/views/dolphinviewactionhandler.cpp13
-rw-r--r--src/views/dolphinviewactionhandler.h5
7 files changed, 76 insertions, 1 deletions
diff --git a/src/dolphincontextmenu.cpp b/src/dolphincontextmenu.cpp
index 9f3967199..e80283c58 100644
--- a/src/dolphincontextmenu.cpp
+++ b/src/dolphincontextmenu.cpp
@@ -396,6 +396,7 @@ void DolphinContextMenu::insertDefaultItemActions(const KFileItemListProperties&
addAction(collection->action(KStandardAction::name(KStandardAction::Cut)));
addAction(collection->action(KStandardAction::name(KStandardAction::Copy)));
addAction(createPasteAction());
+ addAction(m_mainWindow->actionCollection()->action(QStringLiteral("duplicate")));
addSeparator();
diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp
index 642c24e60..399901688 100644
--- a/src/dolphinmainwindow.cpp
+++ b/src/dolphinmainwindow.cpp
@@ -1905,6 +1905,7 @@ void DolphinMainWindow::updateFileAndEditActions()
QAction* cutAction = col->action(KStandardAction::name(KStandardAction::Cut));
QAction* deleteWithTrashShortcut = col->action(QStringLiteral("delete_shortcut")); // see DolphinViewActionHandler
QAction* showTarget = col->action(QStringLiteral("show_target"));
+ QAction* duplicateAction = col->action(QStringLiteral("duplicate")); // see DolphinViewActionHandler
if (list.length() == 1 && list.first().isDir()) {
addToPlacesAction->setEnabled(true);
@@ -1921,6 +1922,7 @@ void DolphinMainWindow::updateFileAndEditActions()
deleteWithTrashShortcut->setEnabled(capabilities.supportsDeleting() && !enableMoveToTrash);
cutAction->setEnabled(capabilities.supportsMoving());
showTarget->setEnabled(list.length() == 1 && list.at(0).isLink());
+ duplicateAction->setEnabled(capabilities.supportsWriting());
}
}
diff --git a/src/dolphinui.rc b/src/dolphinui.rc
index e1bb9ee58..e717b67ae 100644
--- a/src/dolphinui.rc
+++ b/src/dolphinui.rc
@@ -1,5 +1,5 @@
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<kpartgui name="dolphin" version="29">
+<kpartgui name="dolphin" version="30">
<MenuBar>
<Menu name="file">
<Action name="new_menu" />
@@ -11,6 +11,7 @@
<Action name="add_to_places" />
<Separator/>
<Action name="renamefile" />
+ <Action name="duplicate" />
<Action name="movetotrash" />
<Action name="deletefile" />
<Separator/>
@@ -81,6 +82,7 @@
<Action name="edit_cut" />
<Action name="edit_copy" />
<Action name="renamefile" />
+ <Action name="duplicate" />
<Action name="movetotrash" />
<Action name="deletefile" />
<Action name="invert_selection" />
@@ -91,6 +93,7 @@
<Action name="edit_cut" />
<Action name="edit_copy" />
<Action name="renamefile" />
+ <Action name="duplicate" />
<Action name="movetotrash" />
<Action name="deletefile" />
<Action name="delete_shortcut" />
diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp
index cfece0fe6..776436032 100644
--- a/src/views/dolphinview.cpp
+++ b/src/views/dolphinview.cpp
@@ -63,6 +63,7 @@
#include <QDropEvent>
#include <QGraphicsSceneDragDropEvent>
#include <QMenu>
+#include <QMimeDatabase>
#include <QPixmapCache>
#include <QPointer>
#include <QScrollBar>
@@ -704,6 +705,50 @@ void DolphinView::pasteIntoFolder()
}
}
+void DolphinView::duplicateSelectedItems()
+{
+ const KFileItemList itemList = selectedItems();
+ if (itemList.isEmpty()) {
+ return;
+ }
+
+ const QMimeDatabase db;
+
+ // Duplicate all selected items and append "copy" to the end of the file name
+ // but before the filename extension, if present
+ QList<QUrl> newSelection;
+ for (const auto &item : itemList) {
+ const QUrl originalURL = item.url();
+ const QString originalFileName = item.name();
+ QString extension = db.suffixForFileName(originalFileName);
+
+ QUrl duplicateURL = originalURL;
+
+ // No extension; new filename is "<oldfilename> copy"
+ if (extension.isEmpty()) {
+ duplicateURL.setPath(i18nc("<file path> copy", "%1 copy", originalURL.path()));
+ // There's an extension; new filename is "<oldfilename> copy.<extension>"
+ } else {
+ // Need to add a dot since QMimeDatabase::suffixForFileName() doesn't include it
+ extension = QLatin1String(".") + extension;
+ const QString directoryPath = originalURL.adjusted(QUrl::RemoveFilename).path();
+ const QString originalFilenameWithoutExtension = originalFileName.chopped(extension.size());
+ // Preserve file's original filename extension in case the casing differs
+ // from what QMimeDatabase::suffixForFileName() returned
+ const QString originalExtension = originalFileName.right(extension.size());
+ duplicateURL.setPath(i18nc("<file path><filename> copy.<extension>", "%1%2 copy%3", directoryPath, originalFilenameWithoutExtension, originalExtension));
+ }
+
+ KIO::CopyJob* job = KIO::copyAs(originalURL, duplicateURL, KIO::HideProgressInfo);
+ KJobWidgets::setWindow(job, this);
+
+ if (job) {
+ newSelection << duplicateURL;
+ KIO::FileUndoManager::self()->recordCopyJob(job);
+ }
+ }
+}
+
void DolphinView::stopLoading()
{
m_model->cancelDirectoryLoading();
diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h
index 60ecb2a95..83c5f92a4 100644
--- a/src/views/dolphinview.h
+++ b/src/views/dolphinview.h
@@ -375,6 +375,12 @@ public slots:
void pasteIntoFolder();
/**
+ * Creates duplicates of selected items, appending "copy"
+ * to the end.
+ */
+ void duplicateSelectedItems();
+
+ /**
* Handles a drop of @p dropEvent onto widget @p dropWidget and destination @p destUrl
*/
void dropUrls(const QUrl &destUrl, QDropEvent *dropEvent, QWidget *dropWidget);
diff --git a/src/views/dolphinviewactionhandler.cpp b/src/views/dolphinviewactionhandler.cpp
index ef9f317ee..c61e1aaa9 100644
--- a/src/views/dolphinviewactionhandler.cpp
+++ b/src/views/dolphinviewactionhandler.cpp
@@ -136,6 +136,13 @@ void DolphinViewActionHandler::createActions()
deleteWithTrashShortcut->setEnabled(false);
connect(deleteWithTrashShortcut, &QAction::triggered, this, &DolphinViewActionHandler::slotDeleteItems);
+ QAction* duplicateAction = m_actionCollection->addAction(QStringLiteral("duplicate"));
+ duplicateAction->setText(i18nc("@action:inmenu File", "Duplicate Here"));
+ duplicateAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-duplicate")));
+ m_actionCollection->setDefaultShortcut(duplicateAction, Qt::CTRL | Qt::Key_D);
+ duplicateAction->setEnabled(false);
+ connect(duplicateAction, &QAction::triggered, this, &DolphinViewActionHandler::slotDuplicate);
+
QAction *propertiesAction = m_actionCollection->addAction( QStringLiteral("properties") );
// Well, it's the File menu in dolphinmainwindow and the Edit menu in dolphinpart... :)
propertiesAction->setText( i18nc("@action:inmenu File", "Properties") );
@@ -680,6 +687,12 @@ void DolphinViewActionHandler::slotAdjustViewProperties()
delete dialog;
}
+void DolphinViewActionHandler::slotDuplicate()
+{
+ emit actionBeingHandled();
+ m_currentView->duplicateSelectedItems();
+}
+
void DolphinViewActionHandler::slotProperties()
{
KPropertiesDialog* dialog = nullptr;
diff --git a/src/views/dolphinviewactionhandler.h b/src/views/dolphinviewactionhandler.h
index f931b3b9c..3228e7364 100644
--- a/src/views/dolphinviewactionhandler.h
+++ b/src/views/dolphinviewactionhandler.h
@@ -207,6 +207,11 @@ private Q_SLOTS:
void slotAdjustViewProperties();
/**
+ * Begins a duplicate operation on the selected files
+ */
+ void slotDuplicate();
+
+ /**
* Connected to the "properties" action.
* Opens the properties dialog for the selected items of the
* active view. The properties dialog shows information