remove recycle bin node

This commit is contained in:
Le Tan 2021-10-26 08:09:50 +08:00
parent c362facdd7
commit 964dfbb085
32 changed files with 349 additions and 544 deletions

View File

@ -23,6 +23,8 @@ namespace vnotex
FailToRemoveDir, FailToRemoveDir,
FileMissingOnDisk, FileMissingOnDisk,
EssentialFileMissing, EssentialFileMissing,
FileExistsOnCreate,
DirExistsOnCreate,
InvalidArgument InvalidArgument
}; };

View File

@ -254,3 +254,8 @@ TagI *BundleNotebook::tag()
{ {
return getTagMgr(); return getTagMgr();
} }
int BundleNotebook::getConfigVersion() const
{
return m_configVersion;
}

View File

@ -41,6 +41,8 @@ namespace vnotex
TagI *tag() Q_DECL_OVERRIDE; TagI *tag() Q_DECL_OVERRIDE;
int getConfigVersion() const;
// HistoryI. // HistoryI.
public: public:
HistoryI *history() Q_DECL_OVERRIDE; HistoryI *history() Q_DECL_OVERRIDE;

View File

@ -109,6 +109,24 @@ bool Node::containsChild(const QSharedPointer<Node> &p_node) const
return m_children.indexOf(p_node) != -1; return m_children.indexOf(p_node) != -1;
} }
bool Node::isLegalNameForNewChild(const QString &p_name) const
{
if (p_name.isEmpty()) {
return false;
}
auto mgr = getConfigMgr();
if (mgr->isBuiltInFile(this, p_name) || mgr->isBuiltInFolder(this, p_name)) {
return false;
}
if (containsChild(p_name, false)) {
return false;
}
return true;
}
QSharedPointer<Node> Node::findChild(const QString &p_name, bool p_caseSensitive) const QSharedPointer<Node> Node::findChild(const QString &p_name, bool p_caseSensitive) const
{ {
auto targetName = p_caseSensitive ? p_name : p_name.toLower(); auto targetName = p_caseSensitive ? p_name : p_name.toLower();
@ -356,7 +374,7 @@ bool Node::canRename(const QString &p_newName) const
} }
} }
if (m_parent->containsChild(p_newName, false)) { if (!m_parent->isLegalNameForNewChild(p_newName)) {
return false; return false;
} }

View File

@ -36,7 +36,6 @@ namespace vnotex
enum Use { enum Use {
Normal, Normal,
RecycleBin,
Root Root
}; };
@ -115,6 +114,8 @@ namespace vnotex
// Case sensitive. // Case sensitive.
bool containsContentChild(const QString &p_name) const; bool containsContentChild(const QString &p_name) const;
bool isLegalNameForNewChild(const QString &p_name) const;
void addChild(const QSharedPointer<Node> &p_node); void addChild(const QSharedPointer<Node> &p_node);
void insertChild(int p_idx, const QSharedPointer<Node> &p_node); void insertChild(int p_idx, const QSharedPointer<Node> &p_node);

View File

@ -16,6 +16,8 @@ const QString Notebook::c_defaultAttachmentFolder = QStringLiteral("vx_attachmen
const QString Notebook::c_defaultImageFolder = QStringLiteral("vx_images"); const QString Notebook::c_defaultImageFolder = QStringLiteral("vx_images");
const QString Notebook::c_defaultRecycleBinFolder = QStringLiteral("vx_recycle_bin");
static vnotex::ID generateNotebookID() static vnotex::ID generateNotebookID()
{ {
static vnotex::ID id = Notebook::InvalidId; static vnotex::ID id = Notebook::InvalidId;
@ -44,6 +46,9 @@ Notebook::Notebook(const NotebookParameters &p_paras,
if (m_attachmentFolder.isEmpty()) { if (m_attachmentFolder.isEmpty()) {
m_attachmentFolder = c_defaultAttachmentFolder; m_attachmentFolder = c_defaultAttachmentFolder;
} }
if (m_recycleBinFolder.isEmpty()) {
m_recycleBinFolder = c_defaultRecycleBinFolder;
}
m_configMgr->setNotebook(this); m_configMgr->setNotebook(this);
} }
@ -151,6 +156,28 @@ const QString &Notebook::getAttachmentFolder() const
return m_attachmentFolder; return m_attachmentFolder;
} }
const QString &Notebook::getRecycleBinFolder() const
{
return m_recycleBinFolder;
}
QString Notebook::getRecycleBinFolderAbsolutePath() const
{
if (QDir::isAbsolutePath(m_recycleBinFolder)) {
if (!QFileInfo::exists(m_recycleBinFolder)) {
QDir dir(m_recycleBinFolder);
dir.mkpath(m_recycleBinFolder);
}
return m_recycleBinFolder;
} else {
auto folderPath = getBackend()->getFullPath(m_recycleBinFolder);
if (!getBackend()->exists(m_recycleBinFolder)) {
getBackend()->makePath(m_recycleBinFolder);
}
return folderPath;
}
}
const QSharedPointer<INotebookBackend> &Notebook::getBackend() const const QSharedPointer<INotebookBackend> &Notebook::getBackend() const
{ {
return m_backend; return m_backend;
@ -176,23 +203,6 @@ const QSharedPointer<Node> &Notebook::getRootNode() const
return m_root; return m_root;
} }
QSharedPointer<Node> Notebook::getRecycleBinNode() const
{
auto root = getRootNode();
const auto &children = root->getChildrenRef();
auto it = std::find_if(children.begin(),
children.end(),
[this](const QSharedPointer<Node> &p_node) {
return isRecycleBinNode(p_node.data());
});
if (it != children.end()) {
return *it;
}
return nullptr;
}
QSharedPointer<Node> Notebook::newNode(Node *p_parent, QSharedPointer<Node> Notebook::newNode(Node *p_parent,
Node::Flags p_flags, Node::Flags p_flags,
const QString &p_name, const QString &p_name,
@ -259,27 +269,6 @@ void Notebook::removeNode(Node *p_node, bool p_force, bool p_configOnly)
removeNode(p_node->sharedFromThis(), p_force, p_configOnly); removeNode(p_node->sharedFromThis(), p_force, p_configOnly);
} }
bool Notebook::isRecycleBinNode(const Node *p_node) const
{
return p_node && p_node->getUse() == Node::Use::RecycleBin;
}
bool Notebook::isNodeInRecycleBin(const Node *p_node) const
{
if (p_node) {
p_node = p_node->getParent();
while (p_node) {
if (isRecycleBinNode(p_node)) {
return true;
}
p_node = p_node->getParent();
}
}
return false;
}
void Notebook::moveNodeToRecycleBin(Node *p_node) void Notebook::moveNodeToRecycleBin(Node *p_node)
{ {
moveNodeToRecycleBin(p_node->sharedFromThis()); moveNodeToRecycleBin(p_node->sharedFromThis());
@ -288,59 +277,41 @@ void Notebook::moveNodeToRecycleBin(Node *p_node)
void Notebook::moveNodeToRecycleBin(const QSharedPointer<Node> &p_node) void Notebook::moveNodeToRecycleBin(const QSharedPointer<Node> &p_node)
{ {
Q_ASSERT(p_node && !p_node->isRoot()); Q_ASSERT(p_node && !p_node->isRoot());
auto destNode = getOrCreateRecycleBinDateNode(); m_configMgr->removeNodeToFolder(p_node, getOrCreateRecycleBinDateFolder());
copyNodeAsChildOf(p_node, destNode.data(), true);
} }
QSharedPointer<Node> Notebook::getOrCreateRecycleBinDateNode() QString Notebook::getOrCreateRecycleBinDateFolder()
{ {
// Name after date. // Name after date.
auto dateNodeName = QDate::currentDate().toString(QStringLiteral("yyyyMMdd")); auto dateFolderName = QDate::currentDate().toString(QStringLiteral("yyyyMMdd"));
auto folderPath = PathUtils::concatenateFilePath(getRecycleBinFolder(), dateFolderName);
auto recycleBinNode = getRecycleBinNode(); if (QDir::isAbsolutePath(folderPath)) {
auto dateNode = recycleBinNode->findChild(dateNodeName, qDebug() << "using absolute recycle bin folder" << folderPath;
FileUtils::isPlatformNameCaseSensitive()); QDir dir(folderPath);
if (!dateNode) { if (dir.exists()) {
// Create a date node. dir.mkpath(folderPath);
dateNode = newNode(recycleBinNode.data(), Node::Flag::Container, dateNodeName); }
} else {
if (!getBackend()->exists(folderPath)) {
getBackend()->makePath(folderPath);
}
} }
return dateNode; return folderPath;
}
void Notebook::emptyNode(const Node *p_node, bool p_force)
{
// Empty the children.
auto children = p_node->getChildren();
for (const auto &child : children) {
removeNode(child, p_force);
}
} }
void Notebook::moveFileToRecycleBin(const QString &p_filePath) void Notebook::moveFileToRecycleBin(const QString &p_filePath)
{ {
auto node = getOrCreateRecycleBinDateNode(); auto destFilePath = PathUtils::concatenateFilePath(getOrCreateRecycleBinDateFolder(), PathUtils::fileName(p_filePath));
auto destFilePath = PathUtils::concatenateFilePath(node->fetchPath(),
PathUtils::fileName(p_filePath));
destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath); destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath);
m_backend->copyFile(p_filePath, destFilePath); m_backend->copyFile(p_filePath, destFilePath, true);
getBackend()->removeFile(p_filePath);
emit nodeUpdated(node.data());
} }
void Notebook::moveDirToRecycleBin(const QString &p_dirPath) void Notebook::moveDirToRecycleBin(const QString &p_dirPath)
{ {
auto node = getOrCreateRecycleBinDateNode(); auto destDirPath = PathUtils::concatenateFilePath(getOrCreateRecycleBinDateFolder(), PathUtils::fileName(p_dirPath));
auto destDirPath = PathUtils::concatenateFilePath(node->fetchPath(),
PathUtils::fileName(p_dirPath));
destDirPath = getBackend()->renameIfExistsCaseInsensitive(destDirPath); destDirPath = getBackend()->renameIfExistsCaseInsensitive(destDirPath);
m_backend->copyDir(p_dirPath, destDirPath); m_backend->copyDir(p_dirPath, destDirPath, true);
getBackend()->removeDir(p_dirPath);
emit nodeUpdated(node.data());
} }
QSharedPointer<Node> Notebook::addAsNode(Node *p_parent, QSharedPointer<Node> Notebook::addAsNode(Node *p_parent,
@ -416,3 +387,12 @@ TagI *Notebook::tag()
{ {
return nullptr; return nullptr;
} }
void Notebook::emptyRecycleBin()
{
QDir dir(getRecycleBinFolderAbsolutePath());
auto children = dir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
for (const auto &child : children) {
FileUtils::removeDir(dir.filePath(child));
}
}

View File

@ -61,6 +61,10 @@ namespace vnotex
const QString &getAttachmentFolder() const; const QString &getAttachmentFolder() const;
const QString &getRecycleBinFolder() const;
QString getRecycleBinFolderAbsolutePath() const;
const QDateTime &getCreatedTimeUtc() const; const QDateTime &getCreatedTimeUtc() const;
const QSharedPointer<INotebookBackend> &getBackend() const; const QSharedPointer<INotebookBackend> &getBackend() const;
@ -71,8 +75,6 @@ namespace vnotex
const QSharedPointer<Node> &getRootNode() const; const QSharedPointer<Node> &getRootNode() const;
QSharedPointer<Node> getRecycleBinNode() const;
QSharedPointer<Node> newNode(Node *p_parent, QSharedPointer<Node> newNode(Node *p_parent,
Node::Flags p_flags, Node::Flags p_flags,
const QString &p_name, const QString &p_name,
@ -116,17 +118,11 @@ namespace vnotex
// Move @p_dirPath to the recycle bin, without adding it as a child node. // Move @p_dirPath to the recycle bin, without adding it as a child node.
void moveDirToRecycleBin(const QString &p_dirPath); void moveDirToRecycleBin(const QString &p_dirPath);
virtual void emptyRecycleBin();
// Remove all files of this notebook from disk. // Remove all files of this notebook from disk.
virtual void remove() = 0; virtual void remove() = 0;
bool isRecycleBinNode(const Node *p_node) const;
bool isNodeInRecycleBin(const Node *p_node) const;
// Remove all children node of @p_node.
// @p_force: if true, just delete all folders and files under @p_node.
void emptyNode(const Node *p_node, bool p_force = false);
// Whether @p_name is a built-in file under @p_node. // Whether @p_name is a built-in file under @p_node.
bool isBuiltInFile(const Node *p_node, const QString &p_name) const; bool isBuiltInFile(const Node *p_node, const QString &p_name) const;
@ -150,6 +146,8 @@ namespace vnotex
static const QString c_defaultImageFolder; static const QString c_defaultImageFolder;
static const QString c_defaultRecycleBinFolder;
public: public:
// Return null if history is not suported. // Return null if history is not suported.
virtual HistoryI *history(); virtual HistoryI *history();
@ -168,7 +166,7 @@ namespace vnotex
virtual void initializeInternal() = 0; virtual void initializeInternal() = 0;
private: private:
QSharedPointer<Node> getOrCreateRecycleBinDateNode(); QString getOrCreateRecycleBinDateFolder();
bool m_initialized = false; bool m_initialized = false;
@ -196,6 +194,9 @@ namespace vnotex
// Name of the folder to hold attachments. // Name of the folder to hold attachments.
QString m_attachmentFolder; QString m_attachmentFolder;
// Name or path of the folder to hold deleted files.
QString m_recycleBinFolder;
QDateTime m_createdTimeUtc; QDateTime m_createdTimeUtc;
// Backend for file access and synchronization. // Backend for file access and synchronization.

View File

@ -83,13 +83,13 @@ namespace vnotex
// Copy @p_filePath to @p_destPath. // Copy @p_filePath to @p_destPath.
// @p_filePath could be outside notebook. // @p_filePath could be outside notebook.
virtual void copyFile(const QString &p_filePath, const QString &p_destPath) = 0; virtual void copyFile(const QString &p_filePath, const QString &p_destPath, bool p_move = false) = 0;
// Delete @p_filePath from disk. // Delete @p_filePath from disk.
virtual void removeFile(const QString &p_filePath) = 0; virtual void removeFile(const QString &p_filePath) = 0;
// Copy @p_dirPath to as @p_destPath. // Copy @p_dirPath to as @p_destPath.
virtual void copyDir(const QString &p_dirPath, const QString &p_destPath) = 0; virtual void copyDir(const QString &p_dirPath, const QString &p_destPath, bool p_move = false) = 0;
// Delete @p_dirPath from disk if it is empty. // Delete @p_dirPath from disk if it is empty.
// Return false if it is not deleted due to non-empty. // Return false if it is not deleted due to non-empty.

View File

@ -123,7 +123,7 @@ void LocalNotebookBackend::renameDir(const QString &p_dirPath, const QString &p_
FileUtils::renameFile(dirPath, p_name); FileUtils::renameFile(dirPath, p_name);
} }
void LocalNotebookBackend::copyFile(const QString &p_filePath, const QString &p_destPath) void LocalNotebookBackend::copyFile(const QString &p_filePath, const QString &p_destPath, bool p_move)
{ {
auto filePath = p_filePath; auto filePath = p_filePath;
if (QFileInfo(filePath).isRelative()) { if (QFileInfo(filePath).isRelative()) {
@ -132,10 +132,10 @@ void LocalNotebookBackend::copyFile(const QString &p_filePath, const QString &p_
Q_ASSERT(QFileInfo(filePath).isFile()); Q_ASSERT(QFileInfo(filePath).isFile());
FileUtils::copyFile(filePath, getFullPath(p_destPath)); FileUtils::copyFile(filePath, getFullPath(p_destPath), p_move);
} }
void LocalNotebookBackend::copyDir(const QString &p_dirPath, const QString &p_destPath) void LocalNotebookBackend::copyDir(const QString &p_dirPath, const QString &p_destPath, bool p_move)
{ {
auto dirPath = p_dirPath; auto dirPath = p_dirPath;
if (QFileInfo(dirPath).isRelative()) { if (QFileInfo(dirPath).isRelative()) {
@ -144,7 +144,7 @@ void LocalNotebookBackend::copyDir(const QString &p_dirPath, const QString &p_de
Q_ASSERT(QFileInfo(dirPath).isDir()); Q_ASSERT(QFileInfo(dirPath).isDir());
FileUtils::copyDir(dirPath, getFullPath(p_destPath)); FileUtils::copyDir(dirPath, getFullPath(p_destPath), p_move);
} }
void LocalNotebookBackend::removeFile(const QString &p_filePath) void LocalNotebookBackend::removeFile(const QString &p_filePath)

View File

@ -69,10 +69,10 @@ namespace vnotex
// Copy @p_filePath to @p_destPath. // Copy @p_filePath to @p_destPath.
// @p_filePath may beyond this notebook backend. // @p_filePath may beyond this notebook backend.
void copyFile(const QString &p_filePath, const QString &p_destPath) Q_DECL_OVERRIDE; void copyFile(const QString &p_filePath, const QString &p_destPath, bool p_move = false) Q_DECL_OVERRIDE;
// Copy @p_dirPath to as @p_destPath. // Copy @p_dirPath to as @p_destPath.
void copyDir(const QString &p_dirPath, const QString &p_destPath) Q_DECL_OVERRIDE; void copyDir(const QString &p_dirPath, const QString &p_destPath, bool p_move = false) Q_DECL_OVERRIDE;
QString renameIfExistsCaseInsensitive(const QString &p_path) const Q_DECL_OVERRIDE; QString renameIfExistsCaseInsensitive(const QString &p_path) const Q_DECL_OVERRIDE;

View File

@ -95,12 +95,14 @@ bool BundleNotebookConfigMgr::isBuiltInFile(const Node *p_node, const QString &p
bool BundleNotebookConfigMgr::isBuiltInFolder(const Node *p_node, const QString &p_name) const bool BundleNotebookConfigMgr::isBuiltInFolder(const Node *p_node, const QString &p_name) const
{ {
if (p_node->isRoot()) { if (p_node->isRoot()) {
return p_name.toLower() == c_configFolderName; const auto name = p_name.toLower();
return (name == c_configFolderName
|| name == getNotebook()->getRecycleBinFolder().toLower());
} }
return false; return false;
} }
int BundleNotebookConfigMgr::getCodeVersion() const int BundleNotebookConfigMgr::getCodeVersion() const
{ {
return 2; return 3;
} }

View File

@ -69,6 +69,8 @@ namespace vnotex
virtual void removeNode(const QSharedPointer<Node> &p_node, bool p_force, bool p_configOnly) = 0; virtual void removeNode(const QSharedPointer<Node> &p_node, bool p_force, bool p_configOnly) = 0;
virtual void removeNodeToFolder(const QSharedPointer<Node> &p_node, const QString &p_destFolder) = 0;
// Whether @p_name is a built-in file under @p_node. // Whether @p_name is a built-in file under @p_node.
virtual bool isBuiltInFile(const Node *p_node, const QString &p_name) const = 0; virtual bool isBuiltInFile(const Node *p_node, const QString &p_name) const = 0;

View File

@ -22,6 +22,7 @@
#include <utils/contentmediautils.h> #include <utils/contentmediautils.h>
#include "vxnodeconfig.h" #include "vxnodeconfig.h"
#include "vxnotebookconfigmgrfactory.h"
using namespace vnotex; using namespace vnotex;
@ -29,19 +30,12 @@ using namespace vnotex::vx_node_config;
const QString VXNotebookConfigMgr::c_nodeConfigName = "vx.json"; const QString VXNotebookConfigMgr::c_nodeConfigName = "vx.json";
const QString VXNotebookConfigMgr::c_recycleBinFolderName = "vx_recycle_bin";
bool VXNotebookConfigMgr::s_initialized = false; bool VXNotebookConfigMgr::s_initialized = false;
QVector<QRegExp> VXNotebookConfigMgr::s_externalNodeExcludePatterns; QVector<QRegExp> VXNotebookConfigMgr::s_externalNodeExcludePatterns;
VXNotebookConfigMgr::VXNotebookConfigMgr(const QString &p_name, VXNotebookConfigMgr::VXNotebookConfigMgr(const QSharedPointer<INotebookBackend> &p_backend, QObject *p_parent)
const QString &p_displayName, : BundleNotebookConfigMgr(p_backend, p_parent)
const QString &p_description,
const QSharedPointer<INotebookBackend> &p_backend,
QObject *p_parent)
: BundleNotebookConfigMgr(p_backend, p_parent),
m_info(p_name, p_displayName, p_description)
{ {
if (!s_initialized) { if (!s_initialized) {
s_initialized = true; s_initialized = true;
@ -58,17 +52,17 @@ VXNotebookConfigMgr::VXNotebookConfigMgr(const QString &p_name,
QString VXNotebookConfigMgr::getName() const QString VXNotebookConfigMgr::getName() const
{ {
return m_info.m_name; return VXNotebookConfigMgrFactory::c_name;
} }
QString VXNotebookConfigMgr::getDisplayName() const QString VXNotebookConfigMgr::getDisplayName() const
{ {
return m_info.m_displayName; return VXNotebookConfigMgrFactory::c_displayName;
} }
QString VXNotebookConfigMgr::getDescription() const QString VXNotebookConfigMgr::getDescription() const
{ {
return m_info.m_description; return VXNotebookConfigMgrFactory::c_description;
} }
void VXNotebookConfigMgr::createEmptySkeleton(const NotebookParameters &p_paras) void VXNotebookConfigMgr::createEmptySkeleton(const NotebookParameters &p_paras)
@ -97,29 +91,21 @@ QSharedPointer<Node> VXNotebookConfigMgr::loadRootNode()
root->setExists(true); root->setExists(true);
Q_ASSERT(root->isLoaded()); Q_ASSERT(root->isLoaded());
if (!markRecycleBinNode(root)) { if (static_cast<BundleNotebook *>(getNotebook())->getConfigVersion() < 3) {
const_cast<VXNotebookConfigMgr *>(this)->createRecycleBinNode(root); removeLegacyRecycleBinNode(root);
} }
return root; return root;
} }
bool VXNotebookConfigMgr::markRecycleBinNode(const QSharedPointer<Node> &p_root) void VXNotebookConfigMgr::removeLegacyRecycleBinNode(const QSharedPointer<Node> &p_root)
{ {
auto node = p_root->findChild(c_recycleBinFolderName, // Do not support recycle bin node as it complicates everything.
auto node = p_root->findChild(QStringLiteral("vx_recycle_bin"),
FileUtils::isPlatformNameCaseSensitive()); FileUtils::isPlatformNameCaseSensitive());
if (node) { if (node) {
if (!node->exists()) {
removeNode(node, true, true); removeNode(node, true, true);
return false;
} }
node->setUse(Node::Use::RecycleBin);
markNodeReadOnly(node.data());
return true;
}
return false;
} }
void VXNotebookConfigMgr::markNodeReadOnly(Node *p_node) const void VXNotebookConfigMgr::markNodeReadOnly(Node *p_node) const
@ -134,15 +120,6 @@ void VXNotebookConfigMgr::markNodeReadOnly(Node *p_node) const
} }
} }
void VXNotebookConfigMgr::createRecycleBinNode(const QSharedPointer<Node> &p_root)
{
Q_ASSERT(p_root->isRoot());
auto node = newNode(p_root.data(), Node::Flag::Container, c_recycleBinFolderName, "");
node->setUse(Node::Use::RecycleBin);
markNodeReadOnly(node.data());
}
QSharedPointer<NodeConfig> VXNotebookConfigMgr::readNodeConfig(const QString &p_path) const QSharedPointer<NodeConfig> VXNotebookConfigMgr::readNodeConfig(const QString &p_path) const
{ {
auto backend = getBackend(); auto backend = getBackend();
@ -314,6 +291,13 @@ QSharedPointer<Node> VXNotebookConfigMgr::newFileNode(Node *p_parent,
// Write empty file. // Write empty file.
if (p_create) { if (p_create) {
if (getBackend()->childExistsCaseInsensitive(p_parent->fetchPath(), p_name)) {
// File already exists. Exception.
Exception::throwOne(Exception::Type::FileExistsOnCreate,
QString("file (%1) already exists when creating new node").arg(node->fetchPath()));
return nullptr;
}
getBackend()->writeFile(node->fetchPath(), p_content); getBackend()->writeFile(node->fetchPath(), p_content);
node->setExists(true); node->setExists(true);
} else { } else {
@ -343,6 +327,13 @@ QSharedPointer<Node> VXNotebookConfigMgr::newFolderNode(Node *p_parent,
// Make folder. // Make folder.
if (p_create) { if (p_create) {
if (getBackend()->childExistsCaseInsensitive(p_parent->fetchPath(), p_name)) {
// Dir already exists. Exception.
Exception::throwOne(Exception::Type::DirExistsOnCreate,
QString("dir (%1) already exists when creating new node").arg(node->fetchPath()));
return nullptr;
}
getBackend()->makePath(node->fetchPath()); getBackend()->makePath(node->fetchPath());
node->setExists(true); node->setExists(true);
} else { } else {
@ -513,22 +504,9 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFileNodeAsChildOf(const QSharedPoi
bool p_move, bool p_move,
bool p_updateDatabase) bool p_updateDatabase)
{ {
// Copy source file itself. QString destFilePath;
auto srcFilePath = p_src->fetchAbsolutePath(); QString attachmentFolder;
auto destFilePath = PathUtils::concatenateFilePath(p_dest->fetchPath(), copyFilesOfFileNode(p_src, p_dest->fetchPath(), destFilePath, attachmentFolder);
PathUtils::fileName(srcFilePath));
destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath);
getBackend()->copyFile(srcFilePath, destFilePath);
// Copy media files fetched from content.
ContentMediaUtils::copyMediaFiles(p_src.data(), getBackend().data(), destFilePath);
// Copy attachment folder. Rename attachment folder if conflicts.
QString attachmentFolder = p_src->getAttachmentFolder();
if (!attachmentFolder.isEmpty()) {
auto destAttachmentFolderPath = fetchNodeAttachmentFolder(destFilePath, attachmentFolder);
ContentMediaUtils::copyAttachment(p_src.data(), getBackend().data(), destFilePath, destAttachmentFolderPath);
}
// Create a file node. // Create a file node.
auto notebook = getNotebook(); auto notebook = getNotebook();
@ -571,7 +549,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFileNodeAsChildOf(const QSharedPoi
if (p_move) { if (p_move) {
if (sameNotebook) { if (sameNotebook) {
// The same notebook. Do not directly call removeNode() since we need to update the record // The same notebook. Do not directly call removeNode() since we already update the record
// in database directly. // in database directly.
removeNode(p_src, false, false, false); removeNode(p_src, false, false, false);
} else { } else {
@ -587,9 +565,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFolderNodeAsChildOf(const QSharedP
bool p_move, bool p_move,
bool p_updateDatabase) bool p_updateDatabase)
{ {
auto srcFolderPath = p_src->fetchAbsolutePath(); auto destFolderPath = PathUtils::concatenateFilePath(p_dest->fetchPath(), p_src->getName());
auto destFolderPath = PathUtils::concatenateFilePath(p_dest->fetchPath(),
PathUtils::fileName(srcFolderPath));
destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath); destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath);
// Make folder. // Make folder.
@ -662,7 +638,6 @@ void VXNotebookConfigMgr::removeNode(const QSharedPointer<Node> &p_node,
bool p_configOnly, bool p_configOnly,
bool p_updateDatabase) bool p_updateDatabase)
{ {
auto parentNode = p_node->getParent();
if (!p_configOnly && p_node->exists()) { if (!p_configOnly && p_node->exists()) {
// Remove all children. // Remove all children.
auto children = p_node->getChildren(); auto children = p_node->getChildren();
@ -683,7 +658,7 @@ void VXNotebookConfigMgr::removeNode(const QSharedPointer<Node> &p_node,
removeNodeFromDatabase(p_node.data()); removeNodeFromDatabase(p_node.data());
} }
if (parentNode) { if (auto parentNode = p_node->getParent()) {
parentNode->removeChild(p_node); parentNode->removeChild(p_node);
writeNodeConfig(parentNode); writeNodeConfig(parentNode);
} }
@ -722,6 +697,70 @@ void VXNotebookConfigMgr::removeFilesOfNode(Node *p_node, bool p_force)
} }
} }
void VXNotebookConfigMgr::removeNodeToFolder(const QSharedPointer<Node> &p_node, const QString &p_destFolder)
{
if (p_node->isContainer()) {
removeFolderNodeToFolder(p_node, p_destFolder);
} else {
removeFileNodeToFolder(p_node, p_destFolder);
}
}
void VXNotebookConfigMgr::removeFolderNodeToFolder(const QSharedPointer<Node> &p_node, const QString &p_destFolder)
{
auto destFolderPath = PathUtils::concatenateFilePath(p_destFolder, p_node->getName());
destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath);
// Make folder.
getBackend()->makePath(destFolderPath);
// Children.
auto children = p_node->getChildren();
for (const auto &child : children) {
removeNodeToFolder(child, destFolderPath);
}
removeNode(p_node, false, false);
}
void VXNotebookConfigMgr::removeFileNodeToFolder(const QSharedPointer<Node> &p_node, const QString &p_destFolder)
{
// Use a wrapper folder.
auto destFolderPath = PathUtils::concatenateFilePath(p_destFolder, p_node->getName());
destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath);
// Make folder.
getBackend()->makePath(destFolderPath);
QString destFilePath;
QString attachmentFolder;
copyFilesOfFileNode(p_node, destFolderPath, destFilePath, attachmentFolder);
removeNode(p_node, false, false);
}
void VXNotebookConfigMgr::copyFilesOfFileNode(const QSharedPointer<Node> &p_node,
const QString &p_destFolder,
QString &p_destFilePath,
QString &p_attachmentFolder)
{
// Copy source file itself.
auto nodeFilePath = p_node->fetchAbsolutePath();
p_destFilePath = PathUtils::concatenateFilePath(p_destFolder, PathUtils::fileName(nodeFilePath));
p_destFilePath = getBackend()->renameIfExistsCaseInsensitive(p_destFilePath);
getBackend()->copyFile(nodeFilePath, p_destFilePath);
// Copy media files fetched from content.
ContentMediaUtils::copyMediaFiles(p_node.data(), getBackend().data(), p_destFilePath);
// Copy attachment folder. Rename attachment folder if conflicts.
p_attachmentFolder = p_node->getAttachmentFolder();
if (!p_attachmentFolder.isEmpty()) {
auto destAttachmentFolderPath = fetchNodeAttachmentFolder(p_destFilePath, p_attachmentFolder);
ContentMediaUtils::copyAttachment(p_node.data(), getBackend().data(), p_destFilePath, destAttachmentFolderPath);
}
}
QString VXNotebookConfigMgr::fetchNodeImageFolderPath(Node *p_node) QString VXNotebookConfigMgr::fetchNodeImageFolderPath(Node *p_node)
{ {
auto pa = PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_node->fetchAbsolutePath()), auto pa = PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_node->fetchAbsolutePath()),
@ -783,9 +822,9 @@ bool VXNotebookConfigMgr::isBuiltInFile(const Node *p_node, const QString &p_nam
bool VXNotebookConfigMgr::isBuiltInFolder(const Node *p_node, const QString &p_name) const bool VXNotebookConfigMgr::isBuiltInFolder(const Node *p_node, const QString &p_name) const
{ {
const auto name = p_name.toLower(); const auto name = p_name.toLower();
if (name == c_recycleBinFolderName const auto &nb = getNotebook();
|| name == getNotebook()->getImageFolder().toLower() if (name == nb->getImageFolder().toLower()
|| name == getNotebook()->getAttachmentFolder().toLower() || name == nb->getAttachmentFolder().toLower()
|| name == QStringLiteral("_v_images") || name == QStringLiteral("_v_images")
|| name == QStringLiteral("_v_attachments")) { || name == QStringLiteral("_v_attachments")) {
return true; return true;
@ -946,7 +985,7 @@ bool VXNotebookConfigMgr::checkNodeExists(Node *p_node)
QStringList VXNotebookConfigMgr::scanAndImportExternalFiles(Node *p_node) QStringList VXNotebookConfigMgr::scanAndImportExternalFiles(Node *p_node)
{ {
QStringList files; QStringList files;
if (!p_node->isContainer() || p_node->getUse() == Node::Use::RecycleBin) { if (!p_node->isContainer()) {
return files; return files;
} }

View File

@ -27,11 +27,7 @@ namespace vnotex
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit VXNotebookConfigMgr(const QString &p_name, VXNotebookConfigMgr(const QSharedPointer<INotebookBackend> &p_backend, QObject *p_parent = nullptr);
const QString &p_displayName,
const QString &p_description,
const QSharedPointer<INotebookBackend> &p_backend,
QObject *p_parent = nullptr);
QString getName() const Q_DECL_OVERRIDE; QString getName() const Q_DECL_OVERRIDE;
@ -71,6 +67,8 @@ namespace vnotex
void removeNode(const QSharedPointer<Node> &p_node, bool p_force = false, bool p_configOnly = false) Q_DECL_OVERRIDE; void removeNode(const QSharedPointer<Node> &p_node, bool p_force = false, bool p_configOnly = false) Q_DECL_OVERRIDE;
void removeNodeToFolder(const QSharedPointer<Node> &p_node, const QString &p_destFolder) Q_DECL_OVERRIDE;
bool isBuiltInFile(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE; bool isBuiltInFile(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE;
bool isBuiltInFolder(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE; bool isBuiltInFolder(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE;
@ -137,11 +135,9 @@ namespace vnotex
void removeFilesOfNode(Node *p_node, bool p_force); void removeFilesOfNode(Node *p_node, bool p_force);
bool markRecycleBinNode(const QSharedPointer<Node> &p_root);
void markNodeReadOnly(Node *p_node) const; void markNodeReadOnly(Node *p_node) const;
void createRecycleBinNode(const QSharedPointer<Node> &p_root); void removeLegacyRecycleBinNode(const QSharedPointer<Node> &p_root);
// Generate node attachment folder. // Generate node attachment folder.
// @p_folderName: suggested folder name if not empty, may be renamed due to conflicts. // @p_folderName: suggested folder name if not empty, may be renamed due to conflicts.
@ -171,9 +167,16 @@ namespace vnotex
bool sameNotebook(const Node *p_node) const; bool sameNotebook(const Node *p_node) const;
static bool isLikelyImageFolder(const QString &p_dirPath); void removeFolderNodeToFolder(const QSharedPointer<Node> &p_node, const QString &p_destFolder);
Info m_info; void removeFileNodeToFolder(const QSharedPointer<Node> &p_node, const QString &p_destFolder);
void copyFilesOfFileNode(const QSharedPointer<Node> &p_node,
const QString &p_destFolder,
QString &p_destFilePath,
QString &p_attachmentFolder);
static bool isLikelyImageFolder(const QString &p_dirPath);
static bool s_initialized; static bool s_initialized;
@ -181,9 +184,6 @@ namespace vnotex
// Name of the node's config file. // Name of the node's config file.
static const QString c_nodeConfigName; static const QString c_nodeConfigName;
// Name of the recycle bin folder which should be a child of the root node.
static const QString c_recycleBinFolderName;
}; };
} // ns vnotex } // ns vnotex

View File

@ -7,29 +7,32 @@
using namespace vnotex; using namespace vnotex;
const QString VXNotebookConfigMgrFactory::c_name = QStringLiteral("vx.vnotex");
const QString VXNotebookConfigMgrFactory::c_displayName = QObject::tr("VNoteX Notebook Configuration");
const QString VXNotebookConfigMgrFactory::c_description = QObject::tr("Built-in VNoteX notebook configuration");
VXNotebookConfigMgrFactory::VXNotebookConfigMgrFactory() VXNotebookConfigMgrFactory::VXNotebookConfigMgrFactory()
{ {
} }
QString VXNotebookConfigMgrFactory::getName() const QString VXNotebookConfigMgrFactory::getName() const
{ {
return QStringLiteral("vx.vnotex"); return c_name;
} }
QString VXNotebookConfigMgrFactory::getDisplayName() const QString VXNotebookConfigMgrFactory::getDisplayName() const
{ {
return QObject::tr("VNoteX Notebook Configuration"); return c_displayName;
} }
QString VXNotebookConfigMgrFactory::getDescription() const QString VXNotebookConfigMgrFactory::getDescription() const
{ {
return QObject::tr("Built-in VNoteX notebook configuration"); return c_description;
} }
QSharedPointer<INotebookConfigMgr> VXNotebookConfigMgrFactory::createNotebookConfigMgr(const QSharedPointer<INotebookBackend> &p_backend) QSharedPointer<INotebookConfigMgr> VXNotebookConfigMgrFactory::createNotebookConfigMgr(const QSharedPointer<INotebookBackend> &p_backend)
{ {
return QSharedPointer<VXNotebookConfigMgr>::create(getName(), return QSharedPointer<VXNotebookConfigMgr>::create(p_backend);
getDisplayName(),
getDescription(),
p_backend);
} }

View File

@ -19,6 +19,12 @@ namespace vnotex
QString getDescription()const Q_DECL_OVERRIDE; QString getDescription()const Q_DECL_OVERRIDE;
QSharedPointer<INotebookConfigMgr> createNotebookConfigMgr(const QSharedPointer<INotebookBackend> &p_backend) Q_DECL_OVERRIDE; QSharedPointer<INotebookConfigMgr> createNotebookConfigMgr(const QSharedPointer<INotebookBackend> &p_backend) Q_DECL_OVERRIDE;
static const QString c_name;
static const QString c_displayName;
static const QString c_description;
}; };
} // ns vnotex } // ns vnotex

View File

@ -114,11 +114,7 @@ void SessionConfig::loadCore(const QJsonObject &p_session)
if (!isUndefinedKey(coreObj, QStringLiteral("system_title_bar"))) { if (!isUndefinedKey(coreObj, QStringLiteral("system_title_bar"))) {
m_systemTitleBarEnabled = readBool(coreObj, QStringLiteral("system_title_bar")); m_systemTitleBarEnabled = readBool(coreObj, QStringLiteral("system_title_bar"));
} else { } else {
#ifdef Q_OS_WIN
m_systemTitleBarEnabled = false;
#else
m_systemTitleBarEnabled = true; m_systemTitleBarEnabled = true;
#endif
} }
if (!isUndefinedKey(coreObj, QStringLiteral("minimize_to_system_tray"))) { if (!isUndefinedKey(coreObj, QStringLiteral("minimize_to_system_tray"))) {
@ -318,9 +314,6 @@ void SessionConfig::doVersionSpecificOverride()
{ {
// In a new version, we may want to change one value by force. // In a new version, we may want to change one value by force.
// SHOULD set the in memory variable only, or will override the notebook list. // SHOULD set the in memory variable only, or will override the notebook list.
#ifdef Q_OS_WIN
m_systemTitleBarEnabled = false;
#endif
} }
const ExportOption &SessionConfig::getExportOption() const const ExportOption &SessionConfig::getExportOption() const

View File

@ -31,7 +31,6 @@ void WidgetConfig::init(const QJsonObject &p_app,
{ {
m_nodeExplorerViewOrder = READINT(QStringLiteral("node_explorer_view_order")); m_nodeExplorerViewOrder = READINT(QStringLiteral("node_explorer_view_order"));
m_nodeExplorerRecycleBinNodeVisible = READBOOL(QStringLiteral("node_explorer_recycle_bin_node_visible"));
m_nodeExplorerExternalFilesVisible = READBOOL(QStringLiteral("node_explorer_external_files_visible")); m_nodeExplorerExternalFilesVisible = READBOOL(QStringLiteral("node_explorer_external_files_visible"));
m_nodeExplorerAutoImportExternalFilesEnabled = READBOOL(QStringLiteral("node_explorer_auto_import_external_files_enabled")); m_nodeExplorerAutoImportExternalFilesEnabled = READBOOL(QStringLiteral("node_explorer_auto_import_external_files_enabled"));
m_nodeExplorerCloseBeforeOpenWithEnabled = READBOOL(QStringLiteral("node_explorer_close_before_open_with_enabled")); m_nodeExplorerCloseBeforeOpenWithEnabled = READBOOL(QStringLiteral("node_explorer_close_before_open_with_enabled"));
@ -55,7 +54,6 @@ QJsonObject WidgetConfig::toJson() const
obj[QStringLiteral("find_and_replace_options")] = static_cast<int>(m_findAndReplaceOptions); obj[QStringLiteral("find_and_replace_options")] = static_cast<int>(m_findAndReplaceOptions);
obj[QStringLiteral("node_explorer_view_order")] = m_nodeExplorerViewOrder; obj[QStringLiteral("node_explorer_view_order")] = m_nodeExplorerViewOrder;
obj[QStringLiteral("node_explorer_recycle_bin_node_visible")] = m_nodeExplorerRecycleBinNodeVisible;
obj[QStringLiteral("node_explorer_external_files_visible")] = m_nodeExplorerExternalFilesVisible; obj[QStringLiteral("node_explorer_external_files_visible")] = m_nodeExplorerExternalFilesVisible;
obj[QStringLiteral("node_explorer_auto_import_external_files_enabled")] = m_nodeExplorerAutoImportExternalFilesEnabled; obj[QStringLiteral("node_explorer_auto_import_external_files_enabled")] = m_nodeExplorerAutoImportExternalFilesEnabled;
obj[QStringLiteral("node_explorer_close_before_open_with_enabled")] = m_nodeExplorerCloseBeforeOpenWithEnabled; obj[QStringLiteral("node_explorer_close_before_open_with_enabled")] = m_nodeExplorerCloseBeforeOpenWithEnabled;
@ -108,16 +106,6 @@ void WidgetConfig::setNodeExplorerViewOrder(int p_viewOrder)
updateConfig(m_nodeExplorerViewOrder, p_viewOrder, this); updateConfig(m_nodeExplorerViewOrder, p_viewOrder, this);
} }
bool WidgetConfig::isNodeExplorerRecycleBinNodeVisible() const
{
return m_nodeExplorerRecycleBinNodeVisible;
}
void WidgetConfig::setNodeExplorerRecycleBinNodeVisible(bool p_visible)
{
updateConfig(m_nodeExplorerRecycleBinNodeVisible, p_visible, this);
}
bool WidgetConfig::isNodeExplorerExternalFilesVisible() const bool WidgetConfig::isNodeExplorerExternalFilesVisible() const
{ {
return m_nodeExplorerExternalFilesVisible; return m_nodeExplorerExternalFilesVisible;

View File

@ -30,9 +30,6 @@ namespace vnotex
int getNodeExplorerViewOrder() const; int getNodeExplorerViewOrder() const;
void setNodeExplorerViewOrder(int p_viewOrder); void setNodeExplorerViewOrder(int p_viewOrder);
bool isNodeExplorerRecycleBinNodeVisible() const;
void setNodeExplorerRecycleBinNodeVisible(bool p_visible);
bool isNodeExplorerExternalFilesVisible() const; bool isNodeExplorerExternalFilesVisible() const;
void setNodeExplorerExternalFilesVisible(bool p_visible); void setNodeExplorerExternalFilesVisible(bool p_visible);
@ -63,8 +60,6 @@ namespace vnotex
int m_nodeExplorerViewOrder = 0; int m_nodeExplorerViewOrder = 0;
bool m_nodeExplorerRecycleBinNodeVisible = false;
bool m_nodeExplorerExternalFilesVisible = true; bool m_nodeExplorerExternalFilesVisible = true;
bool m_nodeExplorerAutoImportExternalFilesEnabled = true; bool m_nodeExplorerAutoImportExternalFilesEnabled = true;

View File

@ -373,7 +373,6 @@
"find_and_replace_options" : 16, "find_and_replace_options" : 16,
"//comment" : "View order of the node explorer", "//comment" : "View order of the node explorer",
"node_explorer_view_order" : 0, "node_explorer_view_order" : 0,
"node_explorer_recycle_bin_node_visible" : false,
"node_explorer_external_files_visible" : true, "node_explorer_external_files_visible" : true,
"node_explorer_auto_import_external_files_enabled" : true, "node_explorer_auto_import_external_files_enabled" : true,
"//comment" : "Whether close the file before opening it with external program", "//comment" : "Whether close the file before opening it with external program",

View File

@ -470,11 +470,6 @@ bool Searcher::firstPhaseSearch(Notebook *p_notebook, QVector<SearchSecondPhaseI
return true; return true;
} }
if (p_notebook->isRecycleBinNode(child.data())) {
qDebug() << "skipped searching recycle bin";
continue;
}
if (child->hasContent() && testTarget(SearchTarget::SearchFile)) { if (child->hasContent() && testTarget(SearchTarget::SearchFile)) {
if (!firstPhaseSearch(child.data(), p_secondPhaseItems)) { if (!firstPhaseSearch(child.data(), p_secondPhaseItems)) {
return false; return false;

View File

@ -260,7 +260,7 @@ void ManageNotebooksDialog::closeNotebook(const Notebook *p_notebook)
int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Question, int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Question,
tr("Close notebook (%1)?") tr("Close notebook (%1)?")
.arg(p_notebook->getName()), .arg(p_notebook->getName()),
tr("The notebook could be imported again later."), tr("The notebook could be opened by VNote again."),
tr("Notebook location: %1").arg(p_notebook->getRootFolderAbsolutePath()), tr("Notebook location: %1").arg(p_notebook->getRootFolderAbsolutePath()),
this); this);
if (ret != QMessageBox::Ok) { if (ret != QMessageBox::Ok) {
@ -289,14 +289,18 @@ void ManageNotebooksDialog::removeNotebook(const Notebook *p_notebook)
int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Warning, int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Warning,
tr("Please close the notebook in VNote first and delete the notebook root folder files manually."), tr("Please close the notebook in VNote first and delete the notebook root folder files manually."),
tr("Press \"Ok\" to open the location of the notebook root folder."), tr("Press \"Ok\" to close the notebook and open the location of the notebook root folder."),
tr("Notebook location: %1").arg(p_notebook->getRootFolderAbsolutePath()), tr("Notebook location: %1").arg(p_notebook->getRootFolderAbsolutePath()),
this); this);
if (ret != QMessageBox::Ok) { if (ret != QMessageBox::Ok) {
return; return;
} }
WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(p_notebook->getRootFolderAbsolutePath())); const auto rootFolder = p_notebook->getRootFolderAbsolutePath();
closeNotebook(p_notebook);
WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(rootFolder));
} }
bool ManageNotebooksDialog::checkUnsavedChanges() bool ManageNotebooksDialog::checkUnsavedChanges()

View File

@ -57,8 +57,8 @@ bool NewFolderDialog::validateNameInput(QString &p_msg)
return false; return false;
} }
if (m_infoWidget->getParentNode()->containsChild(name, false)) { if (!m_infoWidget->getParentNode()->isLegalNameForNewChild(name)) {
p_msg = tr("Name conflicts with existing folder."); p_msg = tr("Name conflicts with existing or built-in folder.");
return false; return false;
} }

View File

@ -93,8 +93,8 @@ bool NewNoteDialog::validateNameInput(QString &p_msg)
return false; return false;
} }
if (m_infoWidget->getParentNode()->containsChild(name, false)) { if (!m_infoWidget->getParentNode()->isLegalNameForNewChild(name)) {
p_msg = tr("Name conflicts with existing note."); p_msg = tr("Name conflicts with existing or built-in note.");
return false; return false;
} }

View File

@ -629,7 +629,7 @@ void MainWindow::exportNotes()
auto currentNotebook = m_notebookExplorer->currentNotebook().data(); auto currentNotebook = m_notebookExplorer->currentNotebook().data();
auto viewWindow = m_viewArea->getCurrentViewWindow(); auto viewWindow = m_viewArea->getCurrentViewWindow();
auto folderNode = m_notebookExplorer->currentExploredFolderNode(); auto folderNode = m_notebookExplorer->currentExploredFolderNode();
if (folderNode && (folderNode->isRoot() || currentNotebook->isRecycleBinNode(folderNode))) { if (folderNode && (folderNode->isRoot())) {
folderNode = nullptr; folderNode = nullptr;
} }
auto noteNode = m_notebookExplorer->currentExploredNode(); auto noteNode = m_notebookExplorer->currentExploredNode();

View File

@ -81,7 +81,6 @@ void NotebookExplorer::setupUI()
const auto &widgetConfig = ConfigMgr::getInst().getWidgetConfig(); const auto &widgetConfig = ConfigMgr::getInst().getWidgetConfig();
m_nodeExplorer = new NotebookNodeExplorer(this); m_nodeExplorer = new NotebookNodeExplorer(this);
m_nodeExplorer->setRecycleBinNodeVisible(widgetConfig.isNodeExplorerRecycleBinNodeVisible());
m_nodeExplorer->setViewOrder(widgetConfig.getNodeExplorerViewOrder()); m_nodeExplorer->setViewOrder(widgetConfig.getNodeExplorerViewOrder());
m_nodeExplorer->setExternalFilesVisible(widgetConfig.isNodeExplorerExternalFilesVisible()); m_nodeExplorer->setExternalFilesVisible(widgetConfig.isNodeExplorerExternalFilesVisible());
connect(m_nodeExplorer, &NotebookNodeExplorer::nodeActivated, connect(m_nodeExplorer, &NotebookNodeExplorer::nodeActivated,
@ -122,15 +121,9 @@ TitleBar *NotebookExplorer::setupTitleBar(QWidget *p_parent)
} }
{ {
auto btn = titleBar->addActionButton(QStringLiteral("recycle_bin.svg"), tr("Toggle Recycle Bin Node")); auto recycleBinMenu = WidgetsFactory::createMenu(titleBar);
btn->defaultAction()->setCheckable(true); setupRecycleBinMenu(recycleBinMenu);
btn->defaultAction()->setChecked(widgetConfig.isNodeExplorerRecycleBinNodeVisible()); titleBar->addActionButton(QStringLiteral("recycle_bin.svg"), tr("Recycle Bin"), recycleBinMenu);
connect(btn, &QToolButton::triggered,
this, [this](QAction *p_act) {
const bool checked = p_act->isChecked();
ConfigMgr::getInst().getWidgetConfig().setNodeExplorerRecycleBinNodeVisible(checked);
m_nodeExplorer->setRecycleBinNodeVisible(checked);
});
} }
{ {
@ -260,15 +253,6 @@ void NotebookExplorer::newFolder()
return; return;
} }
if (m_currentNotebook->isRecycleBinNode(node)) {
node = m_currentNotebook->getRootNode().data();
} else if (m_currentNotebook->isNodeInRecycleBin(node)) {
MessageBoxHelper::notify(MessageBoxHelper::Information,
tr("Could not create folder within Recycle Bin."),
VNoteX::getInst().getMainWindow());
return;
}
NewFolderDialog dialog(node, VNoteX::getInst().getMainWindow()); NewFolderDialog dialog(node, VNoteX::getInst().getMainWindow());
if (dialog.exec() == QDialog::Accepted) { if (dialog.exec() == QDialog::Accepted) {
m_nodeExplorer->setCurrentNode(dialog.getNewNode().data()); m_nodeExplorer->setCurrentNode(dialog.getNewNode().data());
@ -282,15 +266,6 @@ void NotebookExplorer::newNote()
return; return;
} }
if (m_currentNotebook->isRecycleBinNode(node)) {
node = m_currentNotebook->getRootNode().data();
} else if (m_currentNotebook->isNodeInRecycleBin(node)) {
MessageBoxHelper::notify(MessageBoxHelper::Information,
tr("Could not create note within Recycle Bin."),
VNoteX::getInst().getMainWindow());
return;
}
NewNoteDialog dialog(node, VNoteX::getInst().getMainWindow()); NewNoteDialog dialog(node, VNoteX::getInst().getMainWindow());
if (dialog.exec() == QDialog::Accepted) { if (dialog.exec() == QDialog::Accepted) {
m_nodeExplorer->setCurrentNode(dialog.getNewNode().data()); m_nodeExplorer->setCurrentNode(dialog.getNewNode().data());
@ -340,15 +315,6 @@ void NotebookExplorer::importFile()
return; return;
} }
if (m_currentNotebook->isRecycleBinNode(node)) {
node = m_currentNotebook->getRootNode().data();
} else if (m_currentNotebook->isNodeInRecycleBin(node)) {
MessageBoxHelper::notify(MessageBoxHelper::Information,
tr("Could not create note within Recycle Bin."),
VNoteX::getInst().getMainWindow());
return;
}
static QString lastFolderPath = QDir::homePath(); static QString lastFolderPath = QDir::homePath();
QStringList files = QFileDialog::getOpenFileNames(VNoteX::getInst().getMainWindow(), QStringList files = QFileDialog::getOpenFileNames(VNoteX::getInst().getMainWindow(),
tr("Select Files To Import"), tr("Select Files To Import"),
@ -381,15 +347,6 @@ void NotebookExplorer::importFolder()
return; return;
} }
if (m_currentNotebook->isRecycleBinNode(node)) {
node = m_currentNotebook->getRootNode().data();
} else if (m_currentNotebook->isNodeInRecycleBin(node)) {
MessageBoxHelper::notify(MessageBoxHelper::Information,
tr("Could not create folder within Recycle Bin."),
VNoteX::getInst().getMainWindow());
return;
}
ImportFolderDialog dialog(node, VNoteX::getInst().getMainWindow()); ImportFolderDialog dialog(node, VNoteX::getInst().getMainWindow());
if (dialog.exec() == QDialog::Accepted) { if (dialog.exec() == QDialog::Accepted) {
m_nodeExplorer->setCurrentNode(dialog.getNewNode().data()); m_nodeExplorer->setCurrentNode(dialog.getNewNode().data());
@ -483,6 +440,33 @@ void NotebookExplorer::setupViewMenu(QMenu *p_menu)
}); });
} }
void NotebookExplorer::setupRecycleBinMenu(QMenu *p_menu)
{
p_menu->addAction(tr("Open Recycle Bin"),
this,
[this]() {
if (m_currentNotebook) {
WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(m_currentNotebook->getRecycleBinFolderAbsolutePath()));
}
});
p_menu->addAction(tr("Empty Recycle Bin"),
this,
[this]() {
if (!m_currentNotebook) {
return;
}
int okRet = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Warning,
tr("Empty the recycle bin of notebook (%1)?").arg(m_currentNotebook->getName()),
tr("CAUTION! All the files under the recycle bin folder will be deleted and unrecoverable!"),
tr("Recycle bin folder: %1").arg(m_currentNotebook->getRecycleBinFolderAbsolutePath()),
VNoteX::getInst().getMainWindow());
if (okRet == QMessageBox::Ok) {
m_currentNotebook->emptyRecycleBin();
}
});
}
void NotebookExplorer::saveSession() void NotebookExplorer::saveSession()
{ {
updateSession(); updateSession();

View File

@ -69,6 +69,8 @@ namespace vnotex
void setupViewMenu(QMenu *p_menu); void setupViewMenu(QMenu *p_menu);
void setupRecycleBinMenu(QMenu *p_menu);
void saveSession(); void saveSession();
void loadSession(); void loadSession();

View File

@ -192,13 +192,11 @@ void NotebookNodeExplorer::initNodeIcons() const
const QString folderIconName("folder_node.svg"); const QString folderIconName("folder_node.svg");
const QString fileIconName("file_node.svg"); const QString fileIconName("file_node.svg");
const QString recycleBinIconName("recycle_bin.svg");
s_nodeIcons[NodeIcon::FolderNode] = IconUtils::fetchIcon(themeMgr.getIconFile(folderIconName), fg); s_nodeIcons[NodeIcon::FolderNode] = IconUtils::fetchIcon(themeMgr.getIconFile(folderIconName), fg);
s_nodeIcons[NodeIcon::FileNode] = IconUtils::fetchIcon(themeMgr.getIconFile(fileIconName), fg); s_nodeIcons[NodeIcon::FileNode] = IconUtils::fetchIcon(themeMgr.getIconFile(fileIconName), fg);
s_nodeIcons[NodeIcon::InvalidFolderNode] = IconUtils::fetchIcon(themeMgr.getIconFile(folderIconName), invalidFg); s_nodeIcons[NodeIcon::InvalidFolderNode] = IconUtils::fetchIcon(themeMgr.getIconFile(folderIconName), invalidFg);
s_nodeIcons[NodeIcon::InvalidFileNode] = IconUtils::fetchIcon(themeMgr.getIconFile(fileIconName), invalidFg); s_nodeIcons[NodeIcon::InvalidFileNode] = IconUtils::fetchIcon(themeMgr.getIconFile(fileIconName), invalidFg);
s_nodeIcons[NodeIcon::RecycleBinNode] = IconUtils::fetchIcon(themeMgr.getIconFile(recycleBinIconName), fg);
s_nodeIcons[NodeIcon::ExternalFolderNode] = IconUtils::fetchIcon(themeMgr.getIconFile(folderIconName), externalFg); s_nodeIcons[NodeIcon::ExternalFolderNode] = IconUtils::fetchIcon(themeMgr.getIconFile(folderIconName), externalFg);
s_nodeIcons[NodeIcon::ExternalFileNode] = IconUtils::fetchIcon(themeMgr.getIconFile(fileIconName), externalFg); s_nodeIcons[NodeIcon::ExternalFileNode] = IconUtils::fetchIcon(themeMgr.getIconFile(fileIconName), externalFg);
} }
@ -341,7 +339,6 @@ void NotebookNodeExplorer::generateNodeTree()
if (currentNode) { if (currentNode) {
setCurrentNode(currentNode); setCurrentNode(currentNode);
} else { } else {
// Do not focus the recycle bin.
focusNormalNode(); focusNormalNode();
} }
@ -352,12 +349,6 @@ void NotebookNodeExplorer::loadRootNode(const Node *p_node) const
{ {
Q_ASSERT(p_node->isLoaded() && p_node->isContainer()); Q_ASSERT(p_node->isLoaded() && p_node->isContainer());
// Render recycle bin node first.
auto recycleBinNode = m_notebook->getRecycleBinNode();
if (recycleBinNode) {
loadRecycleBinNode(recycleBinNode.data());
}
// External children. // External children.
if (m_externalFilesVisible) { if (m_externalFilesVisible) {
auto externalChildren = p_node->fetchExternalChildren(); auto externalChildren = p_node->fetchExternalChildren();
@ -372,10 +363,6 @@ void NotebookNodeExplorer::loadRootNode(const Node *p_node) const
auto children = p_node->getChildren(); auto children = p_node->getChildren();
sortNodes(children); sortNodes(children);
for (const auto &child : children) { for (const auto &child : children) {
if (recycleBinNode == child) {
continue;
}
auto item = new QTreeWidgetItem(m_masterExplorer); auto item = new QTreeWidgetItem(m_masterExplorer);
loadNode(item, child.data(), 1); loadNode(item, child.data(), 1);
} }
@ -444,43 +431,6 @@ void NotebookNodeExplorer::loadChildren(QTreeWidgetItem *p_item, Node *p_node, i
} }
} }
void NotebookNodeExplorer::loadRecycleBinNode(Node *p_node) const
{
if (!m_recycleBinNodeVisible) {
return;
}
auto item = new QTreeWidgetItem();
item->setWhatsThis(Column::Name,
tr("Recycle bin of this notebook. Deleted files could be found here. "
"It is organized in folders named by date. Nodes could be moved to "
"other folders by Cut and Paste."));
m_masterExplorer->insertTopLevelItem(0, item);
loadRecycleBinNode(item, p_node, 1);
}
void NotebookNodeExplorer::loadRecycleBinNode(QTreeWidgetItem *p_item, Node *p_node, int p_level) const
{
if (!m_recycleBinNodeVisible) {
return;
}
if (!p_node->isLoaded()) {
p_node->load();
}
clearTreeWigetItemChildren(p_item);
setItemNodeData(p_item, NodeData(p_node, true));
p_item->setText(Column::Name, tr("Recycle Bin"));
p_item->setIcon(Column::Name, getNodeItemIcon(p_node));
loadChildren(p_item, p_node, p_level - 1);
// No need to restore state.
}
void NotebookNodeExplorer::fillTreeItem(QTreeWidgetItem *p_item, Node *p_node, bool p_loaded) const void NotebookNodeExplorer::fillTreeItem(QTreeWidgetItem *p_item, Node *p_node, bool p_loaded) const
{ {
setItemNodeData(p_item, NodeData(p_node, p_loaded)); setItemNodeData(p_item, NodeData(p_node, p_loaded));
@ -502,10 +452,6 @@ const QIcon &NotebookNodeExplorer::getNodeItemIcon(const Node *p_node) const
if (p_node->hasContent()) { if (p_node->hasContent()) {
return p_node->exists() ? s_nodeIcons[NodeIcon::FileNode] : s_nodeIcons[NodeIcon::InvalidFileNode]; return p_node->exists() ? s_nodeIcons[NodeIcon::FileNode] : s_nodeIcons[NodeIcon::InvalidFileNode];
} else { } else {
if (p_node->getUse() == Node::Use::RecycleBin) {
return s_nodeIcons[NodeIcon::RecycleBinNode];
}
return p_node->exists() ? s_nodeIcons[NodeIcon::FolderNode] : s_nodeIcons[NodeIcon::InvalidFolderNode]; return p_node->exists() ? s_nodeIcons[NodeIcon::FolderNode] : s_nodeIcons[NodeIcon::InvalidFolderNode];
} }
} }
@ -561,20 +507,9 @@ void NotebookNodeExplorer::updateNode(Node *p_node)
if (item) { if (item) {
bool expanded = item->isExpanded(); bool expanded = item->isExpanded();
item->setExpanded(false); item->setExpanded(false);
if (m_notebook->isRecycleBinNode(p_node)) {
loadRecycleBinNode(item, p_node, 1);
} else {
loadNode(item, p_node, 1); loadNode(item, p_node, 1);
}
item->setExpanded(expanded); item->setExpanded(expanded);
} else { } else {
if (m_notebook->isRecycleBinNode(p_node) && !m_recycleBinNodeVisible) {
// No need to update.
return;
}
saveNotebookTreeState(false); saveNotebookTreeState(false);
generateNodeTree(); generateNodeTree();
@ -762,49 +697,7 @@ void NotebookNodeExplorer::createContextMenuOnRoot(QMenu *p_menu)
void NotebookNodeExplorer::createContextMenuOnNode(QMenu *p_menu, const Node *p_node) void NotebookNodeExplorer::createContextMenuOnNode(QMenu *p_menu, const Node *p_node)
{ {
const int selectedSize = m_masterExplorer->selectedItems().size(); const int selectedSize = m_masterExplorer->selectedItems().size();
if (m_notebook->isRecycleBinNode(p_node)) {
// Recycle bin node.
createAndAddAction(Action::Reload, p_menu);
createAndAddAction(Action::ReloadIndex, p_menu);
if (selectedSize == 1) {
createAndAddAction(Action::EmptyRecycleBin, p_menu);
createAndAddAction(Action::OpenLocation, p_menu);
}
} else if (m_notebook->isNodeInRecycleBin(p_node)) {
// Node in recycle bin.
createAndAddAction(Action::Open, p_menu);
addOpenWithMenu(p_menu);
p_menu->addSeparator();
if (selectedSize == 1 && p_node->isContainer()) {
createAndAddAction(Action::ExpandAll, p_menu);
}
p_menu->addSeparator();
createAndAddAction(Action::Cut, p_menu);
createAndAddAction(Action::DeleteFromRecycleBin, p_menu);
p_menu->addSeparator();
createAndAddAction(Action::Reload, p_menu);
createAndAddAction(Action::ReloadIndex, p_menu);
if (selectedSize == 1) {
p_menu->addSeparator();
createAndAddAction(Action::CopyPath, p_menu);
createAndAddAction(Action::OpenLocation, p_menu);
}
} else {
createAndAddAction(Action::Open, p_menu); createAndAddAction(Action::Open, p_menu);
addOpenWithMenu(p_menu); addOpenWithMenu(p_menu);
@ -863,7 +756,6 @@ void NotebookNodeExplorer::createContextMenuOnNode(QMenu *p_menu, const Node *p_
createAndAddAction(Action::Properties, p_menu); createAndAddAction(Action::Properties, p_menu);
} }
} }
}
void NotebookNodeExplorer::createContextMenuOnExternalNode(QMenu *p_menu, const ExternalNode *p_node) void NotebookNodeExplorer::createContextMenuOnExternalNode(QMenu *p_menu, const ExternalNode *p_node)
{ {
@ -901,7 +793,7 @@ QAction *NotebookNodeExplorer::createAction(Action p_act, QObject *p_parent)
switch (p_act) { switch (p_act) {
case Action::NewNote: case Action::NewNote:
act = new QAction(generateMenuActionIcon("new_note.svg"), act = new QAction(generateMenuActionIcon("new_note.svg"),
tr("New N&ote"), tr("New &Note"),
p_parent); p_parent);
connect(act, &QAction::triggered, connect(act, &QAction::triggered,
this, []() { this, []() {
@ -1033,47 +925,10 @@ QAction *NotebookNodeExplorer::createAction(Action p_act, QObject *p_parent)
}); });
break; break;
case Action::EmptyRecycleBin:
act = new QAction(tr("&Empty"), p_parent);
connect(act, &QAction::triggered,
this, [this]() {
auto rbNode = m_notebook->getRecycleBinNode().data();
auto rbNodePath = rbNode->fetchAbsolutePath();
int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Warning,
tr("Empty the recycle bin of this notebook?"),
tr("All files in recycle bin will be deleted permanently."),
tr("Location of recycle bin: %1").arg(rbNodePath));
if (ret != QMessageBox::Ok) {
return;
}
try {
m_notebook->emptyNode(rbNode, true);
} catch (Exception &p_e) {
MessageBoxHelper::notify(MessageBoxHelper::Critical,
tr("Failed to empty recycle bin (%1) (%2).").arg(rbNodePath, p_e.what()),
VNoteX::getInst().getMainWindow());
}
updateNode(rbNode);
});
break;
case Action::Delete: case Action::Delete:
act = new QAction(tr("&Delete"), p_parent); act = new QAction(tr("&Delete"), p_parent);
connect(act, &QAction::triggered, connect(act, &QAction::triggered,
this, [this]() { this, &NotebookNodeExplorer::removeSelectedNodes);
removeSelectedNodes(false);
});
break;
case Action::DeleteFromRecycleBin:
// It is fine to have &D with Action::Delete since they won't be at the same context.
act = new QAction(tr("&Delete From Recycle Bin"), p_parent);
connect(act, &QAction::triggered,
this, [this]() {
removeSelectedNodes(true);
});
break; break;
case Action::RemoveFromConfig: case Action::RemoveFromConfig:
@ -1417,21 +1272,12 @@ void NotebookNodeExplorer::selectNodes(const QVector<const Node *> &p_nodes)
} }
} }
void NotebookNodeExplorer::removeSelectedNodes(bool p_skipRecycleBin) void NotebookNodeExplorer::removeSelectedNodes()
{ {
QString text; const QString text = tr("Delete these folders and notes?");
QString info; const QString info = tr("Deleted files could be found in the recycle bin of notebook.");
if (p_skipRecycleBin) {
text = tr("Delete these folders and notes permanently?");
info = tr("Files will be deleted permanently and could not be found even "
"in operating system's recycle bin.");
} else {
text = tr("Delete these folders and notes?");
info = tr("Deleted files could be found in the recycle bin of notebook.");
}
auto nodes = confirmSelectedNodes(tr("Confirm Deletion"), text, info); auto nodes = confirmSelectedNodes(tr("Confirm Deletion"), text, info);
removeNodes(nodes, p_skipRecycleBin, false); removeNodes(nodes, false);
} }
QVector<Node *> NotebookNodeExplorer::confirmSelectedNodes(const QString &p_title, QVector<Node *> NotebookNodeExplorer::confirmSelectedNodes(const QString &p_title,
@ -1471,9 +1317,7 @@ QVector<Node *> NotebookNodeExplorer::confirmSelectedNodes(const QString &p_titl
return nodesToDelete; return nodesToDelete;
} }
void NotebookNodeExplorer::removeNodes(QVector<Node *> p_nodes, void NotebookNodeExplorer::removeNodes(QVector<Node *> p_nodes, bool p_configOnly)
bool p_skipRecycleBin,
bool p_configOnly)
{ {
if (p_nodes.isEmpty()) { if (p_nodes.isEmpty()) {
return; return;
@ -1494,8 +1338,8 @@ void NotebookNodeExplorer::removeNodes(QVector<Node *> p_nodes,
continue; continue;
} }
if (p_configOnly || p_skipRecycleBin) { if (p_configOnly) {
m_notebook->removeNode(node, false, p_configOnly); m_notebook->removeNode(node, false, true);
} else { } else {
m_notebook->moveNodeToRecycleBin(node); m_notebook->moveNodeToRecycleBin(node);
} }
@ -1515,10 +1359,6 @@ void NotebookNodeExplorer::removeNodes(QVector<Node *> p_nodes,
updateNode(node); updateNode(node);
} }
if (!p_configOnly && !p_skipRecycleBin && m_recycleBinNodeVisible) {
updateNode(m_notebook->getRecycleBinNode().data());
}
VNoteX::getInst().showStatusMessageShort(tr("Deleted/Removed %n item(s)", "", nrDeleted)); VNoteX::getInst().showStatusMessageShort(tr("Deleted/Removed %n item(s)", "", nrDeleted));
} }
@ -1527,7 +1367,7 @@ void NotebookNodeExplorer::removeSelectedNodesFromConfig()
auto nodes = confirmSelectedNodes(tr("Confirm Removal"), auto nodes = confirmSelectedNodes(tr("Confirm Removal"),
tr("Remove these folders and notes from index?"), tr("Remove these folders and notes from index?"),
tr("Files are not touched but just removed from notebook index.")); tr("Files are not touched but just removed from notebook index."));
removeNodes(nodes, false, true); removeNodes(nodes, true);
} }
void NotebookNodeExplorer::filterAwayChildrenNodes(QVector<Node *> &p_nodes) void NotebookNodeExplorer::filterAwayChildrenNodes(QVector<Node *> &p_nodes)
@ -1569,29 +1409,6 @@ bool NotebookNodeExplorer::allSelectedItemsSameType() const
} }
} }
if (type == NodeData::NodeType::Node) {
bool hasNormalNode = false;
bool hasNodeInRecycleBin = false;
for (auto &item : items) {
auto node = getItemNodeData(item).getNode();
if (m_notebook->isRecycleBinNode(node)) {
return false;
} else if (m_notebook->isNodeInRecycleBin(node)) {
if (hasNormalNode) {
return false;
}
hasNodeInRecycleBin = true;
} else {
if (hasNodeInRecycleBin) {
return false;
}
hasNormalNode = true;
}
}
}
return true; return true;
} }
@ -1603,12 +1420,11 @@ void NotebookNodeExplorer::reload()
void NotebookNodeExplorer::focusNormalNode() void NotebookNodeExplorer::focusNormalNode()
{ {
auto item = m_masterExplorer->currentItem(); auto item = m_masterExplorer->currentItem();
if (item && (!m_recycleBinNodeVisible || item != m_masterExplorer->topLevelItem(0))) { if (item) {
// Not recycle bin.
return; return;
} }
m_masterExplorer->setCurrentItem(m_masterExplorer->topLevelItem(m_recycleBinNodeVisible ? 1 : 0)); m_masterExplorer->setCurrentItem(m_masterExplorer->topLevelItem(0));
} }
void NotebookNodeExplorer::sortNodes(QVector<QSharedPointer<Node>> &p_nodes) const void NotebookNodeExplorer::sortNodes(QVector<QSharedPointer<Node>> &p_nodes) const
@ -1688,16 +1504,6 @@ void NotebookNodeExplorer::sortNodes(QVector<QSharedPointer<Node>> &p_nodes, int
} }
} }
void NotebookNodeExplorer::setRecycleBinNodeVisible(bool p_visible)
{
if (m_recycleBinNodeVisible == p_visible) {
return;
}
m_recycleBinNodeVisible = p_visible;
reload();
}
void NotebookNodeExplorer::setExternalFilesVisible(bool p_visible) void NotebookNodeExplorer::setExternalFilesVisible(bool p_visible)
{ {
if (m_externalFilesVisible == p_visible) { if (m_externalFilesVisible == p_visible) {
@ -1748,11 +1554,7 @@ void NotebookNodeExplorer::manualSort()
const auto &children = parentNode->getChildrenRef(); const auto &children = parentNode->getChildrenRef();
for (int i = 0; i < children.size(); ++i) { for (int i = 0; i < children.size(); ++i) {
const auto &child = children[i]; const auto &child = children[i];
if (m_notebook->isRecycleBinNode(child.data())) { const bool selected = sortFolders ? child->isContainer() : !child->isContainer();
continue;
}
bool selected = sortFolders ? child->isContainer() : !child->isContainer();
if (selected) { if (selected) {
selectedIdx.push_back(i); selectedIdx.push_back(i);

View File

@ -103,8 +103,6 @@ namespace vnotex
void reload(); void reload();
void setRecycleBinNodeVisible(bool p_visible);
void setViewOrder(int p_order); void setViewOrder(int p_order);
void setExternalFilesVisible(bool p_visible); void setExternalFilesVisible(bool p_visible);
@ -146,9 +144,7 @@ namespace vnotex
Copy, Copy,
Cut, Cut,
Paste, Paste,
EmptyRecycleBin,
Delete, Delete,
DeleteFromRecycleBin,
RemoveFromConfig, RemoveFromConfig,
Sort, Sort,
Reload, Reload,
@ -180,10 +176,6 @@ namespace vnotex
void loadNode(QTreeWidgetItem *p_item, const QSharedPointer<ExternalNode> &p_node) const; void loadNode(QTreeWidgetItem *p_item, const QSharedPointer<ExternalNode> &p_node) const;
void loadRecycleBinNode(Node *p_node) const;
void loadRecycleBinNode(QTreeWidgetItem *p_item, Node *p_node, int p_level) const;
void fillTreeItem(QTreeWidgetItem *p_item, Node *p_node, bool p_loaded) const; void fillTreeItem(QTreeWidgetItem *p_item, Node *p_node, bool p_loaded) const;
void fillTreeItem(QTreeWidgetItem *p_item, const QSharedPointer<ExternalNode> &p_node) const; void fillTreeItem(QTreeWidgetItem *p_item, const QSharedPointer<ExternalNode> &p_node) const;
@ -225,7 +217,7 @@ namespace vnotex
QPair<QVector<Node *>, QVector<QSharedPointer<ExternalNode>>> getSelectedNodes() const; QPair<QVector<Node *>, QVector<QSharedPointer<ExternalNode>>> getSelectedNodes() const;
void removeSelectedNodes(bool p_skipRecycleBin); void removeSelectedNodes();
void removeSelectedNodesFromConfig(); void removeSelectedNodesFromConfig();
@ -241,8 +233,7 @@ namespace vnotex
void selectNodes(const QVector<const Node *> &p_nodes); void selectNodes(const QVector<const Node *> &p_nodes);
// @p_skipRecycleBin is irrelevant if @p_configOnly is true. void removeNodes(QVector<Node *> p_nodes, bool p_configOnly);
void removeNodes(QVector<Node *> p_nodes, bool p_skipRecycleBin, bool p_configOnly);
void filterAwayChildrenNodes(QVector<Node *> &p_nodes); void filterAwayChildrenNodes(QVector<Node *> &p_nodes);
@ -251,7 +242,6 @@ namespace vnotex
// Check if all selected items are the same type for operations. // Check if all selected items are the same type for operations.
bool allSelectedItemsSameType() const; bool allSelectedItemsSameType() const;
// Skip the recycle bin node if possible.
void focusNormalNode(); void focusNormalNode();
void sortNodes(QVector<QSharedPointer<Node>> &p_nodes) const; void sortNodes(QVector<QSharedPointer<Node>> &p_nodes) const;
@ -298,8 +288,6 @@ namespace vnotex
QScopedPointer<NavigationModeWrapper<QTreeWidget, QTreeWidgetItem>> m_navigationWrapper; QScopedPointer<NavigationModeWrapper<QTreeWidget, QTreeWidgetItem>> m_navigationWrapper;
bool m_recycleBinNodeVisible = false;
int m_viewOrder = ViewOrder::OrderedByConfiguration; int m_viewOrder = ViewOrder::OrderedByConfiguration;
bool m_externalFilesVisible = true; bool m_externalFilesVisible = true;
@ -312,7 +300,6 @@ namespace vnotex
FileNode, FileNode,
InvalidFolderNode, InvalidFolderNode,
InvalidFileNode, InvalidFileNode,
RecycleBinNode,
ExternalFolderNode, ExternalFolderNode,
ExternalFileNode, ExternalFileNode,
MaxIcons MaxIcons

View File

@ -448,7 +448,7 @@ SearchState SearchPanel::search(const QSharedPointer<SearchOption> &p_option)
break; break;
} }
auto folder = m_provider->getCurrentFolder(); auto folder = m_provider->getCurrentFolder();
if (folder && (folder->isRoot() || notebook->isRecycleBinNode(folder))) { if (folder && (folder->isRoot())) {
folder = nullptr; folder = nullptr;
} }
if (!folder) { if (!folder) {

View File

@ -239,11 +239,6 @@ void TagExplorer::updateNodeList(const QString &p_tag)
continue; continue;
} }
if (m_notebook->isNodeInRecycleBin(node.data())) {
qDebug() << "skipped node in recycle bin" << p_tag << pa;
continue;
}
auto item = new QListWidgetItem(m_nodeList); auto item = new QListWidgetItem(m_nodeList);
item->setText(node->getName()); item->setText(node->getName());
item->setToolTip(NotebookNodeExplorer::generateToolTip(node.data())); item->setToolTip(NotebookNodeExplorer::generateToolTip(node.data()));