mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
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:
parent
6f1cab39ba
commit
e5cd014762
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user