From 8ca97919467873c0e6c1a0d540ba9626af61a69b Mon Sep 17 00:00:00 2001 From: "J.D. Purcell" Date: Thu, 5 Oct 2023 19:03:23 -0400 Subject: [PATCH] Add "Delete Permanently" action (i.e. delete without trash) --- src/actionmanager.cpp | 12 +++++- src/mainwindow.cpp | 91 ++++++++++++++++++++++++++--------------- src/mainwindow.h | 4 +- src/qvcocoafunctions.h | 2 +- src/qvcocoafunctions.mm | 5 +-- src/shortcutmanager.cpp | 5 +++ 6 files changed, 80 insertions(+), 39 deletions(-) diff --git a/src/actionmanager.cpp b/src/actionmanager.cpp index aa5aa522..7b4802e5 100644 --- a/src/actionmanager.cpp +++ b/src/actionmanager.cpp @@ -184,7 +184,7 @@ QMenuBar *ActionManager::buildMenuBar(QWidget *parent) addCloneOfAction(fileMenu, "closeallwindows"); #endif #ifdef COCOA_LOADED - QVCocoaFunctions::setAlternates(fileMenu, fileMenu->actions().length()-1, fileMenu->actions().length()-2); + QVCocoaFunctions::setAlternate(fileMenu, fileMenu->actions().length()-1); #endif fileMenu->addSeparator(); fileMenu->addMenu(buildOpenWithMenu(fileMenu)); @@ -206,6 +206,10 @@ QMenuBar *ActionManager::buildMenuBar(QWidget *parent) addCloneOfAction(editMenu, "rename"); editMenu->addSeparator(); addCloneOfAction(editMenu, "delete"); + addCloneOfAction(editMenu, "deletepermanent"); +#ifdef COCOA_LOADED + QVCocoaFunctions::setAlternate(editMenu, editMenu->actions().length()-1); +#endif menuBar->addMenu(editMenu); // End of edit menu @@ -613,6 +617,8 @@ void ActionManager::actionTriggered(QAction *triggeredAction, MainWindow *releva relevantWindow->showFileInfo(); } else if (key == "delete") { relevantWindow->askDeleteFile(); + } else if (key == "deletepermanent") { + relevantWindow->askDeleteFile(true); } else if (key == "undo") { relevantWindow->undoDelete(); } else if (key == "copy") { @@ -720,6 +726,10 @@ void ActionManager::initializeActionLibrary() deleteAction->setData({"disable"}); actionLibrary.insert("delete", deleteAction); + auto *deletePermanentAction = new QAction(QIcon::fromTheme("edit-delete"), tr("Delete Permanently")); + deletePermanentAction->setData({"disable"}); + actionLibrary.insert("deletepermanent", deletePermanentAction); + auto *undoAction = new QAction(QIcon::fromTheme("edit-undo"), tr("&Restore from Trash")); #ifdef Q_OS_WIN undoAction->setText(tr("&Undo Delete")); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f4968c7c..20bbdb12 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -935,11 +935,11 @@ void MainWindow::showFileInfo() info->raise(); } -void MainWindow::askDeleteFile() +void MainWindow::askDeleteFile(bool permanent) { - if (!qvApp->getSettingsManager().getBoolean("askdelete")) + if (!permanent && !qvApp->getSettingsManager().getBoolean("askdelete")) { - deleteFile(); + deleteFile(permanent); return; } @@ -952,60 +952,85 @@ void MainWindow::askDeleteFile() return; } - auto trashString = tr("Are you sure you want to move %1 to the Trash?").arg(fileName); + QString messageText; + if (permanent) + { + messageText = tr("Are you sure you want to delete %1 permanently? This can't be undone.").arg(fileName); + } + else + { #ifdef Q_OS_WIN - trashString = tr("Are you sure you want to move %1 to the Recycle Bin?").arg(fileName); + messageText = tr("Are you sure you want to move %1 to the Recycle Bin?").arg(fileName); +#else + messageText = tr("Are you sure you want to move %1 to the Trash?").arg(fileName); #endif + } - auto *msgBox = new QMessageBox(QMessageBox::Question, tr("Delete"), trashString, + auto *msgBox = new QMessageBox(QMessageBox::Question, tr("Delete"), messageText, QMessageBox::Yes | QMessageBox::No, this); - msgBox->setCheckBox(new QCheckBox(tr("Do not ask again"))); + if (!permanent) + msgBox->setCheckBox(new QCheckBox(tr("Do not ask again"))); - connect(msgBox, &QMessageBox::finished, this, [this, msgBox](int result){ - if (result != 16384) + connect(msgBox, &QMessageBox::finished, this, [this, msgBox, permanent](int result){ + if (result != QMessageBox::Yes) return; - QSettings settings; - settings.beginGroup("options"); - settings.setValue("askdelete", !msgBox->checkBox()->isChecked()); - qvApp->getSettingsManager().loadSettings(); - this->deleteFile(); + if (!permanent) + { + QSettings settings; + settings.beginGroup("options"); + settings.setValue("askdelete", !msgBox->checkBox()->isChecked()); + qvApp->getSettingsManager().loadSettings(); + } + this->deleteFile(permanent); }); msgBox->open(); } -void MainWindow::deleteFile() +void MainWindow::deleteFile(bool permanent) { const QFileInfo &fileInfo = getCurrentFileDetails().fileInfo; const QString filePath = fileInfo.absoluteFilePath(); const QString fileName = fileInfo.fileName(); - QString trashFilePath = ""; graphicsView->closeImage(); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) - QFile file(filePath); - bool success = file.moveToTrash(); - if (!success || QFile::exists(filePath)) + bool success; + QString trashFilePath; + if (permanent) { - openFile(filePath); - QMessageBox::critical(this, tr("Error"), tr("Can't delete %1.").arg(fileName)); - return; + success = QFile::remove(filePath); } - - trashFilePath = file.fileName(); + else + { +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + QFile file(filePath); + success = file.moveToTrash(); + if (success) + trashFilePath = file.fileName(); #elif defined Q_OS_MACOS && COCOA_LOADED - QString trashedFile = QVCocoaFunctions::deleteFile(filePath); - trashFilePath = QUrl(trashedFile).toLocalFile(); // remove file:// protocol + QString trashedFile = QVCocoaFunctions::deleteFile(filePath); + success = !trashedFile.isEmpty(); + if (success) + trashFilePath = QUrl(trashedFile).toLocalFile(); // remove file:// protocol #elif defined Q_OS_UNIX && !defined Q_OS_MACOS - trashFilePath = deleteFileLinuxFallback(filePath, false); + trashFilePath = deleteFileLinuxFallback(filePath, false); + success = !trashFilePath.isEmpty(); #else - QMessageBox::critical(this, tr("Not Supported"), tr("This program was compiled with an old version of Qt and this feature is not available.\n" - "If you see this message, please report a bug!")); + QMessageBox::critical(this, tr("Not Supported"), tr("This program was compiled with an old version of Qt and this feature is not available.\n" + "If you see this message, please report a bug!")); - return; + return; #endif + } + + if (!success || QFile::exists(filePath)) + { + openFile(filePath); + QMessageBox::critical(this, tr("Error"), tr("Can't delete %1.").arg(fileName)); + return; + } auto afterDelete = qvApp->getSettingsManager().getEnum("afterdelete"); if (afterDelete == Qv::AfterDelete::MoveForward) @@ -1013,7 +1038,9 @@ void MainWindow::deleteFile() else if (afterDelete == Qv::AfterDelete::MoveBack) previousFile(); - lastDeletedFiles.push({trashFilePath, filePath}); + if (!trashFilePath.isEmpty()) + lastDeletedFiles.push({trashFilePath, filePath}); + disableActions(); } diff --git a/src/mainwindow.h b/src/mainwindow.h index e7c25419..493a1939 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -71,9 +71,9 @@ class MainWindow : public QMainWindow void showFileInfo(); - void askDeleteFile(); + void askDeleteFile(bool permanent = false); - void deleteFile(); + void deleteFile(bool permanent); QString deleteFileLinuxFallback(const QString &path, bool putBack); diff --git a/src/qvcocoafunctions.h b/src/qvcocoafunctions.h index 8619166b..5898268f 100644 --- a/src/qvcocoafunctions.h +++ b/src/qvcocoafunctions.h @@ -27,7 +27,7 @@ class QVCocoaFunctions static void setWindowMenu(QMenu *menu); - static void setAlternates(QMenu *menu, int index0, int index1); + static void setAlternate(QMenu *menu, int index); static void setDockRecents(const QStringList &recentPathsList); diff --git a/src/qvcocoafunctions.mm b/src/qvcocoafunctions.mm index 69d8e785..0f58b47a 100644 --- a/src/qvcocoafunctions.mm +++ b/src/qvcocoafunctions.mm @@ -164,11 +164,10 @@ static void fixNativeMenuEccentricities(QMenu *menu, NSMenu *nativeMenu) [[NSApplication sharedApplication] setWindowsMenu:nativeMenu]; } -void QVCocoaFunctions::setAlternates(QMenu *menu, int index0, int index1) +void QVCocoaFunctions::setAlternate(QMenu *menu, int index) { NSMenu *nativeMenu = menu->toNSMenu(); - [[nativeMenu.itemArray objectAtIndex:index0] setAlternate:true]; - [[nativeMenu.itemArray objectAtIndex:index1] setAlternate:true]; + [[nativeMenu.itemArray objectAtIndex:index] setAlternate:true]; } void QVCocoaFunctions::setDockRecents(const QStringList &recentPathsList) diff --git a/src/shortcutmanager.cpp b/src/shortcutmanager.cpp index fac19f42..a8bd2b79 100644 --- a/src/shortcutmanager.cpp +++ b/src/shortcutmanager.cpp @@ -71,6 +71,11 @@ void ShortcutManager::initializeShortcutsList() shortcutsList.last().defaultShortcuts.prepend(QKeySequence(Qt::CTRL | Qt::Key_Backspace).toString()); #ifdef Q_OS_WIN shortcutsList.last().readableName = tr("Delete"); +#endif + shortcutsList.append({tr("Delete Permanently"), "deletepermanent", QStringList(QKeySequence(Qt::SHIFT | Qt::Key_Delete).toString()), {}}); +#ifdef Q_OS_MACOS + // cmd+option+backspace + shortcutsList.last().defaultShortcuts.prepend(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Backspace).toString()); #endif shortcutsList.append({tr("First File"), "firstfile", QStringList(QKeySequence(Qt::Key_Home).toString()), {}}); shortcutsList.append({tr("Previous File"), "previousfile", QStringList(QKeySequence(Qt::Key_Left).toString()), {}});