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;
This commit is contained in:
Le Tan 2017-09-26 19:27:11 +08:00
parent 6f1cab39ba
commit e5cd014762
10 changed files with 129 additions and 53 deletions

View File

@ -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

View File

@ -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,7 +790,33 @@ bool VUtils::deleteFile(const VNotebook *p_notebook,
return file.remove();
} else {
// Move it to the recycle bin folder.
QString binPath = getRecycleBinSubFolderToUse(p_notebook);
return deleteFile(p_notebook->getRecycleBinFolderPath(), 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 {
// 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);
@ -829,25 +830,11 @@ bool VUtils::deleteFile(const VNotebook *p_notebook,
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);
qWarning() << "fail to move" << p_path << "to" << binDir.filePath(destName);
return false;
}
return true;
}
}
bool VUtils::deleteFile(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();
}
}
QVector<VElementRegion> VUtils::fetchImageRegionsUsingParser(const QString &p_content)

View File

@ -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;
};

View File

@ -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();

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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;
};