Browse Source

support recycle bin folder for extern files

1. Add external_recycle_bin_folder config;
2. By default, each external file will use _v_recycle_bin in the same
directory as its recycle bin folder to hold deleted images;
Le Tan 8 years ago
parent
commit
e5cd014762

+ 3 - 0
src/resources/vnote.ini

@@ -113,6 +113,9 @@ markdownit_opt_linkify=true
 ; Default name of the recycle bin of notebook
 recycle_bin_folder=_v_recycle_bin
 
+; Default name of the recycle bin of external files
+external_recycle_bin_folder=_v_recycle_bin
+
 ; Confirm before deleting unused images
 confirm_images_clean_up=true
 

+ 37 - 50
src/utils/vutils.cpp

@@ -22,7 +22,7 @@
 #include <QRegExp>
 #include <QKeySequence>
 
-#include "vfile.h"
+#include "vorphanfile.h"
 #include "vnote.h"
 #include "vnotebook.h"
 #include "hgmarkdownhighlighter.h"
@@ -740,13 +740,6 @@ QString VUtils::getShortcutText(const QString &p_keySeq)
     return QKeySequence(p_keySeq).toString(QKeySequence::NativeText);
 }
 
-static QString getRecycleBinSubFolderToUse(const VNotebook *p_notebook)
-{
-    QString folderPath = p_notebook->getRecycleBinFolderPath();
-    QDir dir(folderPath);
-    return QDir::cleanPath(dir.absoluteFilePath(QDateTime::currentDateTime().toString("yyyyMMdd")));
-}
-
 bool VUtils::deleteDirectory(const VNotebook *p_notebook,
                              const QString &p_path,
                              bool p_skipRecycleBin)
@@ -756,25 +749,7 @@ bool VUtils::deleteDirectory(const VNotebook *p_notebook,
         return dir.removeRecursively();
     } else {
         // Move it to the recycle bin folder.
-        QString binPath = getRecycleBinSubFolderToUse(p_notebook);
-        QDir binDir(binPath);
-        if (!binDir.exists()) {
-            binDir.mkpath(binPath);
-            if (!binDir.exists()) {
-                return false;
-            }
-        }
-
-        QString destName = getFileNameWithSequence(binPath,
-                                                   directoryNameFromPath(p_path));
-
-        qDebug() << "try to move" << p_path << "to" << binPath << "as" << destName;
-        if (!binDir.rename(p_path, binDir.filePath(destName))) {
-            qWarning() << "fail to move directory" << p_path << "to" << binDir.filePath(destName);
-            return false;
-        }
-
-        return true;
+        return deleteFile(p_notebook->getRecycleBinFolderPath(), p_path);
     }
 }
 
@@ -815,39 +790,51 @@ bool VUtils::deleteFile(const VNotebook *p_notebook,
         return file.remove();
     } else {
         // Move it to the recycle bin folder.
-        QString binPath = getRecycleBinSubFolderToUse(p_notebook);
-        QDir binDir(binPath);
-        if (!binDir.exists()) {
-            binDir.mkpath(binPath);
-            if (!binDir.exists()) {
-                return false;
-            }
-        }
-
-        QString destName = getFileNameWithSequence(binPath,
-                                                   fileNameFromPath(p_path));
-
-        qDebug() << "try to move" << p_path << "to" << binPath << "as" << destName;
-        if (!binDir.rename(p_path, binDir.filePath(destName))) {
-            qWarning() << "fail to move file" << p_path << "to" << binDir.filePath(destName);
-            return false;
-        }
-
-        return true;
+        return deleteFile(p_notebook->getRecycleBinFolderPath(), p_path);
     }
 }
 
-bool VUtils::deleteFile(const QString &p_path,
+bool VUtils::deleteFile(const VOrphanFile *p_file,
+                        const QString &p_path,
                         bool p_skipRecycleBin)
 {
     if (p_skipRecycleBin) {
         QFile file(p_path);
         return file.remove();
     } else {
-        // TODO: Move it to the recycle bin folder.
-        QFile file(p_path);
-        return file.remove();
+        // Move it to the recycle bin folder.
+        return deleteFile(p_file->fetchRecycleBinFolderPath(), p_path);
+    }
+}
+
+static QString getRecycleBinSubFolderToUse(const QString &p_folderPath)
+{
+    QDir dir(p_folderPath);
+    return QDir::cleanPath(dir.absoluteFilePath(QDateTime::currentDateTime().toString("yyyyMMdd")));
+}
+
+bool VUtils::deleteFile(const QString &p_recycleBinFolderPath,
+                        const QString &p_path)
+{
+    QString binPath = getRecycleBinSubFolderToUse(p_recycleBinFolderPath);
+    QDir binDir(binPath);
+    if (!binDir.exists()) {
+        binDir.mkpath(binPath);
+        if (!binDir.exists()) {
+            return false;
+        }
     }
+
+    QString destName = getFileNameWithSequence(binPath,
+                                               fileNameFromPath(p_path));
+
+    qDebug() << "try to move" << p_path << "to" << binPath << "as" << destName;
+    if (!binDir.rename(p_path, binDir.filePath(destName))) {
+        qWarning() << "fail to move" << p_path << "to" << binDir.filePath(destName);
+        return false;
+    }
+
+    return true;
 }
 
 QVector<VElementRegion> VUtils::fetchImageRegionsUsingParser(const QString &p_content)

+ 9 - 2
src/utils/vutils.h

@@ -13,6 +13,7 @@
 
 class QKeyEvent;
 class VFile;
+class VOrphanFile;
 class VNotebook;
 
 #if !defined(V_ASSERT)
@@ -151,9 +152,10 @@ public:
                            bool p_skipRecycleBin = false);
 
     // Delete file specified by @p_path.
-    // Will just move the file to the recycle bin of VNote if
+    // Will just move the file to the recycle bin of VOrphanFile if
     // @p_skipRecycleBin is false.
-    static bool deleteFile(const QString &p_path,
+    static bool deleteFile(const VOrphanFile *p_file,
+                           const QString &p_path,
                            bool p_skipRecycleBin = false);
 
     static QString displayDateTime(const QDateTime &p_dateTime);
@@ -203,6 +205,11 @@ private:
     // Use HGMarkdownParser to parse @p_content to get all image link regions.
     static QVector<VElementRegion> fetchImageRegionsUsingParser(const QString &p_content);
 
+    // Delete file/directory specified by @p_path by moving it to the recycle bin
+    // folder @p_recycleBinFolderPath.
+    static bool deleteFile(const QString &p_recycleBinFolderPath,
+                           const QString &p_path);
+
     // <value, name>
     static QVector<QPair<QString, QString>> s_availableLanguages;
 };

+ 3 - 0
src/vconfigmanager.cpp

@@ -208,6 +208,9 @@ void VConfigManager::initialize()
     m_recycleBinFolder = getConfigFromSettings("global",
                                                "recycle_bin_folder").toString();
 
+    m_recycleBinFolderExt = getConfigFromSettings("global",
+                                                  "external_recycle_bin_folder").toString();
+
     m_confirmImagesCleanUp = getConfigFromSettings("global",
                                                    "confirm_images_clean_up").toBool();
 

+ 10 - 0
src/vconfigmanager.h

@@ -271,6 +271,8 @@ public:
 
     const QString &getRecycleBinFolder() const;
 
+    const QString &getRecycleBinFolderExt() const;
+
     bool getConfirmImagesCleanUp() const;
     void setConfirmImagesCleanUp(bool p_enabled);
 
@@ -553,6 +555,9 @@ private:
     // Default name of the recycle bin folder of notebook.
     QString m_recycleBinFolder;
 
+    // Default name of the recycle bin folder of external files.
+    QString m_recycleBinFolderExt;
+
     // Confirm before deleting unused images.
     bool m_confirmImagesCleanUp;
 
@@ -1439,6 +1444,11 @@ inline const QString &VConfigManager::getRecycleBinFolder() const
     return m_recycleBinFolder;
 }
 
+inline const QString &VConfigManager::getRecycleBinFolderExt() const
+{
+    return m_recycleBinFolderExt;
+}
+
 inline bool VConfigManager::getConfirmImagesCleanUp() const
 {
     return m_confirmImagesCleanUp;

+ 35 - 0
src/veditwindow.cpp

@@ -146,6 +146,33 @@ void VEditWindow::initTabActions()
                 QUrl url = QUrl::fromLocalFile(file->fetchBasePath());
                 QDesktopServices::openUrl(url);
             });
+
+    m_recycleBinAct = new QAction(QIcon(":/resources/icons/recycle_bin.svg"),
+                                  tr("&Recycle Bin"), this);
+    m_recycleBinAct->setToolTip(tr("Open the recycle bin of this note"));
+    connect(m_recycleBinAct, &QAction::triggered,
+            this, [this]() {
+                int tab = this->m_closeTabAct->data().toInt();
+                Q_ASSERT(tab != -1);
+
+                VEditTab *editor = getTab(tab);
+                VFile *file = editor->getFile();
+                Q_ASSERT(file);
+
+                QString folderPath;
+                if (file->getType() == FileType::Note) {
+                    const VNoteFile *tmpFile = dynamic_cast<const VNoteFile *>((VFile *)file);
+                    folderPath = tmpFile->getNotebook()->getRecycleBinFolderPath();
+                } else if (file->getType() == FileType::Orphan) {
+                    const VOrphanFile *tmpFile = dynamic_cast<const VOrphanFile *>((VFile *)file);
+                    folderPath = tmpFile->fetchRecycleBinFolderPath();
+                } else {
+                    Q_ASSERT(false);
+                }
+
+                QUrl url = QUrl::fromLocalFile(folderPath);
+                QDesktopServices::openUrl(url);
+            });
 }
 
 void VEditWindow::setupCornerWidget()
@@ -560,6 +587,11 @@ void VEditWindow::tabbarContextMenuRequested(QPoint p_pos)
         m_locateAct->setData(tab);
         menu.addAction(m_locateAct);
 
+        menu.addSeparator();
+
+        m_recycleBinAct->setData(tab);
+        menu.addAction(m_recycleBinAct);
+
         m_openLocationAct->setData(tab);
         menu.addAction(m_openLocationAct);
 
@@ -567,6 +599,9 @@ void VEditWindow::tabbarContextMenuRequested(QPoint p_pos)
         menu.addAction(m_noteInfoAct);
     } else if (file->getType() == FileType::Orphan
                && !(dynamic_cast<VOrphanFile *>(file)->isSystemFile())) {
+        m_recycleBinAct->setData(tab);
+        menu.addAction(m_recycleBinAct);
+
         m_openLocationAct->setData(tab);
         menu.addAction(m_openLocationAct);
 

+ 3 - 0
src/veditwindow.h

@@ -177,6 +177,9 @@ private:
 
     // Open the location (the folder containing this file) of this note.
     QAction *m_openLocationAct;
+
+    // Open the recycle bin folder of this note.
+    QAction *m_recycleBinAct;
 };
 
 inline QString VEditWindow::generateTooltip(const VFile *p_file) const

+ 5 - 1
src/vmdedit.cpp

@@ -13,6 +13,7 @@
 #include "dialog/vconfirmdeletiondialog.h"
 #include "vimagepreviewer.h"
 #include "vtextblockdata.h"
+#include "vorphanfile.h"
 
 extern VConfigManager *g_config;
 extern VNote *g_vnote;
@@ -308,8 +309,11 @@ void VMdEdit::clearUnusedImages()
             if (m_file->getType() == FileType::Note) {
                 const VNoteFile *tmpFile = dynamic_cast<const VNoteFile *>((VFile *)m_file);
                 ret = VUtils::deleteFile(tmpFile->getNotebook(), unusedImages[i], false);
+            } else if (m_file->getType() == FileType::Orphan) {
+                const VOrphanFile *tmpFile = dynamic_cast<const VOrphanFile *>((VFile *)m_file);
+                ret = VUtils::deleteFile(tmpFile, unusedImages[i], false);
             } else {
-                ret = VUtils::deleteFile(unusedImages[i], false);
+                Q_ASSERT(false);
             }
 
             if (!ret) {

+ 15 - 0
src/vorphanfile.cpp

@@ -67,3 +67,18 @@ QString VOrphanFile::getImageFolderInLink() const
 
     return folder;
 }
+
+QString VOrphanFile::fetchRecycleBinFolderPath() const
+{
+    QString folder = m_recycleBinFolder;
+    if (m_recycleBinFolder.isEmpty()) {
+        folder = g_config->getRecycleBinFolderExt();
+    }
+
+    QFileInfo fi(folder);
+    if (fi.isAbsolute()) {
+        return folder;
+    } else {
+        return QDir(fetchBasePath()).filePath(folder);
+    }
+}

+ 9 - 0
src/vorphanfile.h

@@ -35,6 +35,9 @@ public:
 
     bool isSystemFile() const;
 
+    // Get the recycle bin folder for this file.
+    QString fetchRecycleBinFolderPath() const;
+
 private:
     // Full path of this file.
     QString m_path;
@@ -45,6 +48,12 @@ private:
     // Valid only within a session.
     QString m_imageFolder;
 
+    // Recycle bin forlder.
+    // May be absolute or relative path.
+    // Empty to use the global default config.
+    // Valid only within a session.
+    QString m_recycleBinFolder;
+
     // Whether it is a system internal file.
     bool m_systemFile;
 };