mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 05:49:53 +08:00
remove recycle bin node
This commit is contained in:
parent
c362facdd7
commit
964dfbb085
@ -23,6 +23,8 @@ namespace vnotex
|
||||
FailToRemoveDir,
|
||||
FileMissingOnDisk,
|
||||
EssentialFileMissing,
|
||||
FileExistsOnCreate,
|
||||
DirExistsOnCreate,
|
||||
InvalidArgument
|
||||
};
|
||||
|
||||
|
@ -254,3 +254,8 @@ TagI *BundleNotebook::tag()
|
||||
{
|
||||
return getTagMgr();
|
||||
}
|
||||
|
||||
int BundleNotebook::getConfigVersion() const
|
||||
{
|
||||
return m_configVersion;
|
||||
}
|
||||
|
@ -41,6 +41,8 @@ namespace vnotex
|
||||
|
||||
TagI *tag() Q_DECL_OVERRIDE;
|
||||
|
||||
int getConfigVersion() const;
|
||||
|
||||
// HistoryI.
|
||||
public:
|
||||
HistoryI *history() Q_DECL_OVERRIDE;
|
||||
|
@ -109,6 +109,24 @@ bool Node::containsChild(const QSharedPointer<Node> &p_node) const
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,6 @@ namespace vnotex
|
||||
|
||||
enum Use {
|
||||
Normal,
|
||||
RecycleBin,
|
||||
Root
|
||||
};
|
||||
|
||||
@ -115,6 +114,8 @@ namespace vnotex
|
||||
// Case sensitive.
|
||||
bool containsContentChild(const QString &p_name) const;
|
||||
|
||||
bool isLegalNameForNewChild(const QString &p_name) const;
|
||||
|
||||
void addChild(const QSharedPointer<Node> &p_node);
|
||||
|
||||
void insertChild(int p_idx, const QSharedPointer<Node> &p_node);
|
||||
|
@ -16,6 +16,8 @@ const QString Notebook::c_defaultAttachmentFolder = QStringLiteral("vx_attachmen
|
||||
|
||||
const QString Notebook::c_defaultImageFolder = QStringLiteral("vx_images");
|
||||
|
||||
const QString Notebook::c_defaultRecycleBinFolder = QStringLiteral("vx_recycle_bin");
|
||||
|
||||
static vnotex::ID generateNotebookID()
|
||||
{
|
||||
static vnotex::ID id = Notebook::InvalidId;
|
||||
@ -44,6 +46,9 @@ Notebook::Notebook(const NotebookParameters &p_paras,
|
||||
if (m_attachmentFolder.isEmpty()) {
|
||||
m_attachmentFolder = c_defaultAttachmentFolder;
|
||||
}
|
||||
if (m_recycleBinFolder.isEmpty()) {
|
||||
m_recycleBinFolder = c_defaultRecycleBinFolder;
|
||||
}
|
||||
|
||||
m_configMgr->setNotebook(this);
|
||||
}
|
||||
@ -151,6 +156,28 @@ const QString &Notebook::getAttachmentFolder() const
|
||||
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
|
||||
{
|
||||
return m_backend;
|
||||
@ -176,23 +203,6 @@ const QSharedPointer<Node> &Notebook::getRootNode() const
|
||||
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,
|
||||
Node::Flags p_flags,
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
moveNodeToRecycleBin(p_node->sharedFromThis());
|
||||
@ -288,59 +277,41 @@ void Notebook::moveNodeToRecycleBin(Node *p_node)
|
||||
void Notebook::moveNodeToRecycleBin(const QSharedPointer<Node> &p_node)
|
||||
{
|
||||
Q_ASSERT(p_node && !p_node->isRoot());
|
||||
auto destNode = getOrCreateRecycleBinDateNode();
|
||||
copyNodeAsChildOf(p_node, destNode.data(), true);
|
||||
m_configMgr->removeNodeToFolder(p_node, getOrCreateRecycleBinDateFolder());
|
||||
}
|
||||
|
||||
QSharedPointer<Node> Notebook::getOrCreateRecycleBinDateNode()
|
||||
QString Notebook::getOrCreateRecycleBinDateFolder()
|
||||
{
|
||||
// Name after date.
|
||||
auto dateNodeName = QDate::currentDate().toString(QStringLiteral("yyyyMMdd"));
|
||||
|
||||
auto recycleBinNode = getRecycleBinNode();
|
||||
auto dateNode = recycleBinNode->findChild(dateNodeName,
|
||||
FileUtils::isPlatformNameCaseSensitive());
|
||||
if (!dateNode) {
|
||||
// Create a date node.
|
||||
dateNode = newNode(recycleBinNode.data(), Node::Flag::Container, dateNodeName);
|
||||
auto dateFolderName = QDate::currentDate().toString(QStringLiteral("yyyyMMdd"));
|
||||
auto folderPath = PathUtils::concatenateFilePath(getRecycleBinFolder(), dateFolderName);
|
||||
if (QDir::isAbsolutePath(folderPath)) {
|
||||
qDebug() << "using absolute recycle bin folder" << folderPath;
|
||||
QDir dir(folderPath);
|
||||
if (dir.exists()) {
|
||||
dir.mkpath(folderPath);
|
||||
}
|
||||
} else {
|
||||
if (!getBackend()->exists(folderPath)) {
|
||||
getBackend()->makePath(folderPath);
|
||||
}
|
||||
}
|
||||
|
||||
return dateNode;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return folderPath;
|
||||
}
|
||||
|
||||
void Notebook::moveFileToRecycleBin(const QString &p_filePath)
|
||||
{
|
||||
auto node = getOrCreateRecycleBinDateNode();
|
||||
auto destFilePath = PathUtils::concatenateFilePath(node->fetchPath(),
|
||||
PathUtils::fileName(p_filePath));
|
||||
auto destFilePath = PathUtils::concatenateFilePath(getOrCreateRecycleBinDateFolder(), PathUtils::fileName(p_filePath));
|
||||
destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath);
|
||||
m_backend->copyFile(p_filePath, destFilePath);
|
||||
|
||||
getBackend()->removeFile(p_filePath);
|
||||
|
||||
emit nodeUpdated(node.data());
|
||||
m_backend->copyFile(p_filePath, destFilePath, true);
|
||||
}
|
||||
|
||||
void Notebook::moveDirToRecycleBin(const QString &p_dirPath)
|
||||
{
|
||||
auto node = getOrCreateRecycleBinDateNode();
|
||||
auto destDirPath = PathUtils::concatenateFilePath(node->fetchPath(),
|
||||
PathUtils::fileName(p_dirPath));
|
||||
auto destDirPath = PathUtils::concatenateFilePath(getOrCreateRecycleBinDateFolder(), PathUtils::fileName(p_dirPath));
|
||||
destDirPath = getBackend()->renameIfExistsCaseInsensitive(destDirPath);
|
||||
m_backend->copyDir(p_dirPath, destDirPath);
|
||||
|
||||
getBackend()->removeDir(p_dirPath);
|
||||
|
||||
emit nodeUpdated(node.data());
|
||||
m_backend->copyDir(p_dirPath, destDirPath, true);
|
||||
}
|
||||
|
||||
QSharedPointer<Node> Notebook::addAsNode(Node *p_parent,
|
||||
@ -416,3 +387,12 @@ TagI *Notebook::tag()
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,10 @@ namespace vnotex
|
||||
|
||||
const QString &getAttachmentFolder() const;
|
||||
|
||||
const QString &getRecycleBinFolder() const;
|
||||
|
||||
QString getRecycleBinFolderAbsolutePath() const;
|
||||
|
||||
const QDateTime &getCreatedTimeUtc() const;
|
||||
|
||||
const QSharedPointer<INotebookBackend> &getBackend() const;
|
||||
@ -71,8 +75,6 @@ namespace vnotex
|
||||
|
||||
const QSharedPointer<Node> &getRootNode() const;
|
||||
|
||||
QSharedPointer<Node> getRecycleBinNode() const;
|
||||
|
||||
QSharedPointer<Node> newNode(Node *p_parent,
|
||||
Node::Flags p_flags,
|
||||
const QString &p_name,
|
||||
@ -116,17 +118,11 @@ namespace vnotex
|
||||
// Move @p_dirPath to the recycle bin, without adding it as a child node.
|
||||
void moveDirToRecycleBin(const QString &p_dirPath);
|
||||
|
||||
virtual void emptyRecycleBin();
|
||||
|
||||
// Remove all files of this notebook from disk.
|
||||
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.
|
||||
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_defaultRecycleBinFolder;
|
||||
|
||||
public:
|
||||
// Return null if history is not suported.
|
||||
virtual HistoryI *history();
|
||||
@ -168,7 +166,7 @@ namespace vnotex
|
||||
virtual void initializeInternal() = 0;
|
||||
|
||||
private:
|
||||
QSharedPointer<Node> getOrCreateRecycleBinDateNode();
|
||||
QString getOrCreateRecycleBinDateFolder();
|
||||
|
||||
bool m_initialized = false;
|
||||
|
||||
@ -196,6 +194,9 @@ namespace vnotex
|
||||
// Name of the folder to hold attachments.
|
||||
QString m_attachmentFolder;
|
||||
|
||||
// Name or path of the folder to hold deleted files.
|
||||
QString m_recycleBinFolder;
|
||||
|
||||
QDateTime m_createdTimeUtc;
|
||||
|
||||
// Backend for file access and synchronization.
|
||||
|
@ -83,13 +83,13 @@ namespace vnotex
|
||||
|
||||
// Copy @p_filePath to @p_destPath.
|
||||
// @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.
|
||||
virtual void removeFile(const QString &p_filePath) = 0;
|
||||
|
||||
// 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.
|
||||
// Return false if it is not deleted due to non-empty.
|
||||
|
@ -123,7 +123,7 @@ void LocalNotebookBackend::renameDir(const QString &p_dirPath, const QString &p_
|
||||
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;
|
||||
if (QFileInfo(filePath).isRelative()) {
|
||||
@ -132,10 +132,10 @@ void LocalNotebookBackend::copyFile(const QString &p_filePath, const QString &p_
|
||||
|
||||
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;
|
||||
if (QFileInfo(dirPath).isRelative()) {
|
||||
@ -144,7 +144,7 @@ void LocalNotebookBackend::copyDir(const QString &p_dirPath, const QString &p_de
|
||||
|
||||
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)
|
||||
|
@ -69,10 +69,10 @@ namespace vnotex
|
||||
|
||||
// Copy @p_filePath to @p_destPath.
|
||||
// @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.
|
||||
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;
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
int BundleNotebookConfigMgr::getCodeVersion() const
|
||||
{
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
@ -69,6 +69,8 @@ namespace vnotex
|
||||
|
||||
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.
|
||||
virtual bool isBuiltInFile(const Node *p_node, const QString &p_name) const = 0;
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <utils/contentmediautils.h>
|
||||
|
||||
#include "vxnodeconfig.h"
|
||||
#include "vxnotebookconfigmgrfactory.h"
|
||||
|
||||
using namespace vnotex;
|
||||
|
||||
@ -29,19 +30,12 @@ using namespace vnotex::vx_node_config;
|
||||
|
||||
const QString VXNotebookConfigMgr::c_nodeConfigName = "vx.json";
|
||||
|
||||
const QString VXNotebookConfigMgr::c_recycleBinFolderName = "vx_recycle_bin";
|
||||
|
||||
bool VXNotebookConfigMgr::s_initialized = false;
|
||||
|
||||
QVector<QRegExp> VXNotebookConfigMgr::s_externalNodeExcludePatterns;
|
||||
|
||||
VXNotebookConfigMgr::VXNotebookConfigMgr(const QString &p_name,
|
||||
const QString &p_displayName,
|
||||
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)
|
||||
VXNotebookConfigMgr::VXNotebookConfigMgr(const QSharedPointer<INotebookBackend> &p_backend, QObject *p_parent)
|
||||
: BundleNotebookConfigMgr(p_backend, p_parent)
|
||||
{
|
||||
if (!s_initialized) {
|
||||
s_initialized = true;
|
||||
@ -58,17 +52,17 @@ VXNotebookConfigMgr::VXNotebookConfigMgr(const QString &p_name,
|
||||
|
||||
QString VXNotebookConfigMgr::getName() const
|
||||
{
|
||||
return m_info.m_name;
|
||||
return VXNotebookConfigMgrFactory::c_name;
|
||||
}
|
||||
|
||||
QString VXNotebookConfigMgr::getDisplayName() const
|
||||
{
|
||||
return m_info.m_displayName;
|
||||
return VXNotebookConfigMgrFactory::c_displayName;
|
||||
}
|
||||
|
||||
QString VXNotebookConfigMgr::getDescription() const
|
||||
{
|
||||
return m_info.m_description;
|
||||
return VXNotebookConfigMgrFactory::c_description;
|
||||
}
|
||||
|
||||
void VXNotebookConfigMgr::createEmptySkeleton(const NotebookParameters &p_paras)
|
||||
@ -97,29 +91,21 @@ QSharedPointer<Node> VXNotebookConfigMgr::loadRootNode()
|
||||
root->setExists(true);
|
||||
Q_ASSERT(root->isLoaded());
|
||||
|
||||
if (!markRecycleBinNode(root)) {
|
||||
const_cast<VXNotebookConfigMgr *>(this)->createRecycleBinNode(root);
|
||||
if (static_cast<BundleNotebook *>(getNotebook())->getConfigVersion() < 3) {
|
||||
removeLegacyRecycleBinNode(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());
|
||||
if (node) {
|
||||
if (!node->exists()) {
|
||||
removeNode(node, true, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
node->setUse(Node::Use::RecycleBin);
|
||||
markNodeReadOnly(node.data());
|
||||
return true;
|
||||
removeNode(node, true, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
auto backend = getBackend();
|
||||
@ -314,6 +291,13 @@ QSharedPointer<Node> VXNotebookConfigMgr::newFileNode(Node *p_parent,
|
||||
|
||||
// Write empty file.
|
||||
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);
|
||||
node->setExists(true);
|
||||
} else {
|
||||
@ -343,6 +327,13 @@ QSharedPointer<Node> VXNotebookConfigMgr::newFolderNode(Node *p_parent,
|
||||
|
||||
// Make folder.
|
||||
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());
|
||||
node->setExists(true);
|
||||
} else {
|
||||
@ -513,22 +504,9 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFileNodeAsChildOf(const QSharedPoi
|
||||
bool p_move,
|
||||
bool p_updateDatabase)
|
||||
{
|
||||
// Copy source file itself.
|
||||
auto srcFilePath = p_src->fetchAbsolutePath();
|
||||
auto destFilePath = PathUtils::concatenateFilePath(p_dest->fetchPath(),
|
||||
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);
|
||||
}
|
||||
QString destFilePath;
|
||||
QString attachmentFolder;
|
||||
copyFilesOfFileNode(p_src, p_dest->fetchPath(), destFilePath, attachmentFolder);
|
||||
|
||||
// Create a file node.
|
||||
auto notebook = getNotebook();
|
||||
@ -571,7 +549,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFileNodeAsChildOf(const QSharedPoi
|
||||
|
||||
if (p_move) {
|
||||
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.
|
||||
removeNode(p_src, false, false, false);
|
||||
} else {
|
||||
@ -587,9 +565,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFolderNodeAsChildOf(const QSharedP
|
||||
bool p_move,
|
||||
bool p_updateDatabase)
|
||||
{
|
||||
auto srcFolderPath = p_src->fetchAbsolutePath();
|
||||
auto destFolderPath = PathUtils::concatenateFilePath(p_dest->fetchPath(),
|
||||
PathUtils::fileName(srcFolderPath));
|
||||
auto destFolderPath = PathUtils::concatenateFilePath(p_dest->fetchPath(), p_src->getName());
|
||||
destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath);
|
||||
|
||||
// Make folder.
|
||||
@ -662,7 +638,6 @@ void VXNotebookConfigMgr::removeNode(const QSharedPointer<Node> &p_node,
|
||||
bool p_configOnly,
|
||||
bool p_updateDatabase)
|
||||
{
|
||||
auto parentNode = p_node->getParent();
|
||||
if (!p_configOnly && p_node->exists()) {
|
||||
// Remove all children.
|
||||
auto children = p_node->getChildren();
|
||||
@ -683,7 +658,7 @@ void VXNotebookConfigMgr::removeNode(const QSharedPointer<Node> &p_node,
|
||||
removeNodeFromDatabase(p_node.data());
|
||||
}
|
||||
|
||||
if (parentNode) {
|
||||
if (auto parentNode = p_node->getParent()) {
|
||||
parentNode->removeChild(p_node);
|
||||
writeNodeConfig(parentNode);
|
||||
}
|
||||
@ -722,10 +697,74 @@ 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)
|
||||
{
|
||||
auto pa = PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_node->fetchAbsolutePath()),
|
||||
getNotebook()->getImageFolder());
|
||||
getNotebook()->getImageFolder());
|
||||
// Do not make the folder when it is a folder node request.
|
||||
if (p_node->hasContent()) {
|
||||
getBackend()->makePath(pa);
|
||||
@ -736,7 +775,7 @@ QString VXNotebookConfigMgr::fetchNodeImageFolderPath(Node *p_node)
|
||||
QString VXNotebookConfigMgr::fetchNodeAttachmentFolderPath(Node *p_node)
|
||||
{
|
||||
auto notebookFolder = PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_node->fetchAbsolutePath()),
|
||||
getNotebook()->getAttachmentFolder());
|
||||
getNotebook()->getAttachmentFolder());
|
||||
if (p_node->hasContent()) {
|
||||
auto nodeFolder = p_node->getAttachmentFolder();
|
||||
if (nodeFolder.isEmpty()) {
|
||||
@ -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
|
||||
{
|
||||
const auto name = p_name.toLower();
|
||||
if (name == c_recycleBinFolderName
|
||||
|| name == getNotebook()->getImageFolder().toLower()
|
||||
|| name == getNotebook()->getAttachmentFolder().toLower()
|
||||
const auto &nb = getNotebook();
|
||||
if (name == nb->getImageFolder().toLower()
|
||||
|| name == nb->getAttachmentFolder().toLower()
|
||||
|| name == QStringLiteral("_v_images")
|
||||
|| name == QStringLiteral("_v_attachments")) {
|
||||
return true;
|
||||
@ -946,7 +985,7 @@ bool VXNotebookConfigMgr::checkNodeExists(Node *p_node)
|
||||
QStringList VXNotebookConfigMgr::scanAndImportExternalFiles(Node *p_node)
|
||||
{
|
||||
QStringList files;
|
||||
if (!p_node->isContainer() || p_node->getUse() == Node::Use::RecycleBin) {
|
||||
if (!p_node->isContainer()) {
|
||||
return files;
|
||||
}
|
||||
|
||||
|
@ -27,11 +27,7 @@ namespace vnotex
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VXNotebookConfigMgr(const QString &p_name,
|
||||
const QString &p_displayName,
|
||||
const QString &p_description,
|
||||
const QSharedPointer<INotebookBackend> &p_backend,
|
||||
QObject *p_parent = nullptr);
|
||||
VXNotebookConfigMgr(const QSharedPointer<INotebookBackend> &p_backend, QObject *p_parent = nullptr);
|
||||
|
||||
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 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 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);
|
||||
|
||||
bool markRecycleBinNode(const QSharedPointer<Node> &p_root);
|
||||
|
||||
void markNodeReadOnly(Node *p_node) const;
|
||||
|
||||
void createRecycleBinNode(const QSharedPointer<Node> &p_root);
|
||||
void removeLegacyRecycleBinNode(const QSharedPointer<Node> &p_root);
|
||||
|
||||
// Generate node attachment folder.
|
||||
// @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;
|
||||
|
||||
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;
|
||||
|
||||
@ -181,9 +184,6 @@ namespace vnotex
|
||||
|
||||
// Name of the node's config file.
|
||||
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
|
||||
|
||||
|
@ -7,29 +7,32 @@
|
||||
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
||||
QString VXNotebookConfigMgrFactory::getName() const
|
||||
{
|
||||
return QStringLiteral("vx.vnotex");
|
||||
return c_name;
|
||||
}
|
||||
|
||||
QString VXNotebookConfigMgrFactory::getDisplayName() const
|
||||
{
|
||||
return QObject::tr("VNoteX Notebook Configuration");
|
||||
return c_displayName;
|
||||
}
|
||||
|
||||
QString VXNotebookConfigMgrFactory::getDescription() const
|
||||
{
|
||||
return QObject::tr("Built-in VNoteX notebook configuration");
|
||||
return c_description;
|
||||
}
|
||||
|
||||
QSharedPointer<INotebookConfigMgr> VXNotebookConfigMgrFactory::createNotebookConfigMgr(const QSharedPointer<INotebookBackend> &p_backend)
|
||||
{
|
||||
return QSharedPointer<VXNotebookConfigMgr>::create(getName(),
|
||||
getDisplayName(),
|
||||
getDescription(),
|
||||
p_backend);
|
||||
return QSharedPointer<VXNotebookConfigMgr>::create(p_backend);
|
||||
}
|
||||
|
@ -19,6 +19,12 @@ namespace vnotex
|
||||
QString getDescription()const 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
|
||||
|
||||
|
@ -114,11 +114,7 @@ void SessionConfig::loadCore(const QJsonObject &p_session)
|
||||
if (!isUndefinedKey(coreObj, QStringLiteral("system_title_bar"))) {
|
||||
m_systemTitleBarEnabled = readBool(coreObj, QStringLiteral("system_title_bar"));
|
||||
} else {
|
||||
#ifdef Q_OS_WIN
|
||||
m_systemTitleBarEnabled = false;
|
||||
#else
|
||||
m_systemTitleBarEnabled = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
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.
|
||||
// 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
|
||||
|
@ -31,7 +31,6 @@ void WidgetConfig::init(const QJsonObject &p_app,
|
||||
|
||||
{
|
||||
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_nodeExplorerAutoImportExternalFilesEnabled = READBOOL(QStringLiteral("node_explorer_auto_import_external_files_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("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_auto_import_external_files_enabled")] = m_nodeExplorerAutoImportExternalFilesEnabled;
|
||||
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);
|
||||
}
|
||||
|
||||
bool WidgetConfig::isNodeExplorerRecycleBinNodeVisible() const
|
||||
{
|
||||
return m_nodeExplorerRecycleBinNodeVisible;
|
||||
}
|
||||
|
||||
void WidgetConfig::setNodeExplorerRecycleBinNodeVisible(bool p_visible)
|
||||
{
|
||||
updateConfig(m_nodeExplorerRecycleBinNodeVisible, p_visible, this);
|
||||
}
|
||||
|
||||
bool WidgetConfig::isNodeExplorerExternalFilesVisible() const
|
||||
{
|
||||
return m_nodeExplorerExternalFilesVisible;
|
||||
|
@ -30,9 +30,6 @@ namespace vnotex
|
||||
int getNodeExplorerViewOrder() const;
|
||||
void setNodeExplorerViewOrder(int p_viewOrder);
|
||||
|
||||
bool isNodeExplorerRecycleBinNodeVisible() const;
|
||||
void setNodeExplorerRecycleBinNodeVisible(bool p_visible);
|
||||
|
||||
bool isNodeExplorerExternalFilesVisible() const;
|
||||
void setNodeExplorerExternalFilesVisible(bool p_visible);
|
||||
|
||||
@ -63,8 +60,6 @@ namespace vnotex
|
||||
|
||||
int m_nodeExplorerViewOrder = 0;
|
||||
|
||||
bool m_nodeExplorerRecycleBinNodeVisible = false;
|
||||
|
||||
bool m_nodeExplorerExternalFilesVisible = true;
|
||||
|
||||
bool m_nodeExplorerAutoImportExternalFilesEnabled = true;
|
||||
|
@ -373,7 +373,6 @@
|
||||
"find_and_replace_options" : 16,
|
||||
"//comment" : "View order of the node explorer",
|
||||
"node_explorer_view_order" : 0,
|
||||
"node_explorer_recycle_bin_node_visible" : false,
|
||||
"node_explorer_external_files_visible" : true,
|
||||
"node_explorer_auto_import_external_files_enabled" : true,
|
||||
"//comment" : "Whether close the file before opening it with external program",
|
||||
|
@ -470,11 +470,6 @@ bool Searcher::firstPhaseSearch(Notebook *p_notebook, QVector<SearchSecondPhaseI
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p_notebook->isRecycleBinNode(child.data())) {
|
||||
qDebug() << "skipped searching recycle bin";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child->hasContent() && testTarget(SearchTarget::SearchFile)) {
|
||||
if (!firstPhaseSearch(child.data(), p_secondPhaseItems)) {
|
||||
return false;
|
||||
|
@ -118,7 +118,7 @@ void FileUtils::copyFile(const QString &p_filePath,
|
||||
QDir dir;
|
||||
if (!dir.mkpath(PathUtils::parentDirPath(p_destPath))) {
|
||||
Exception::throwOne(Exception::Type::FailToCreateDir,
|
||||
QString("failed to create directory: %1").arg(PathUtils::parentDirPath(p_destPath)));
|
||||
QString("failed to create directory: %1").arg(PathUtils::parentDirPath(p_destPath)));
|
||||
}
|
||||
|
||||
bool failed = false;
|
||||
|
@ -260,7 +260,7 @@ void ManageNotebooksDialog::closeNotebook(const Notebook *p_notebook)
|
||||
int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Question,
|
||||
tr("Close notebook (%1)?")
|
||||
.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()),
|
||||
this);
|
||||
if (ret != QMessageBox::Ok) {
|
||||
@ -289,14 +289,18 @@ void ManageNotebooksDialog::removeNotebook(const Notebook *p_notebook)
|
||||
|
||||
int ret = MessageBoxHelper::questionOkCancel(MessageBoxHelper::Warning,
|
||||
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()),
|
||||
this);
|
||||
if (ret != QMessageBox::Ok) {
|
||||
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()
|
||||
|
@ -57,8 +57,8 @@ bool NewFolderDialog::validateNameInput(QString &p_msg)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_infoWidget->getParentNode()->containsChild(name, false)) {
|
||||
p_msg = tr("Name conflicts with existing folder.");
|
||||
if (!m_infoWidget->getParentNode()->isLegalNameForNewChild(name)) {
|
||||
p_msg = tr("Name conflicts with existing or built-in folder.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -93,8 +93,8 @@ bool NewNoteDialog::validateNameInput(QString &p_msg)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_infoWidget->getParentNode()->containsChild(name, false)) {
|
||||
p_msg = tr("Name conflicts with existing note.");
|
||||
if (!m_infoWidget->getParentNode()->isLegalNameForNewChild(name)) {
|
||||
p_msg = tr("Name conflicts with existing or built-in note.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -629,7 +629,7 @@ void MainWindow::exportNotes()
|
||||
auto currentNotebook = m_notebookExplorer->currentNotebook().data();
|
||||
auto viewWindow = m_viewArea->getCurrentViewWindow();
|
||||
auto folderNode = m_notebookExplorer->currentExploredFolderNode();
|
||||
if (folderNode && (folderNode->isRoot() || currentNotebook->isRecycleBinNode(folderNode))) {
|
||||
if (folderNode && (folderNode->isRoot())) {
|
||||
folderNode = nullptr;
|
||||
}
|
||||
auto noteNode = m_notebookExplorer->currentExploredNode();
|
||||
|
@ -81,7 +81,6 @@ void NotebookExplorer::setupUI()
|
||||
|
||||
const auto &widgetConfig = ConfigMgr::getInst().getWidgetConfig();
|
||||
m_nodeExplorer = new NotebookNodeExplorer(this);
|
||||
m_nodeExplorer->setRecycleBinNodeVisible(widgetConfig.isNodeExplorerRecycleBinNodeVisible());
|
||||
m_nodeExplorer->setViewOrder(widgetConfig.getNodeExplorerViewOrder());
|
||||
m_nodeExplorer->setExternalFilesVisible(widgetConfig.isNodeExplorerExternalFilesVisible());
|
||||
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"));
|
||||
btn->defaultAction()->setCheckable(true);
|
||||
btn->defaultAction()->setChecked(widgetConfig.isNodeExplorerRecycleBinNodeVisible());
|
||||
connect(btn, &QToolButton::triggered,
|
||||
this, [this](QAction *p_act) {
|
||||
const bool checked = p_act->isChecked();
|
||||
ConfigMgr::getInst().getWidgetConfig().setNodeExplorerRecycleBinNodeVisible(checked);
|
||||
m_nodeExplorer->setRecycleBinNodeVisible(checked);
|
||||
});
|
||||
auto recycleBinMenu = WidgetsFactory::createMenu(titleBar);
|
||||
setupRecycleBinMenu(recycleBinMenu);
|
||||
titleBar->addActionButton(QStringLiteral("recycle_bin.svg"), tr("Recycle Bin"), recycleBinMenu);
|
||||
}
|
||||
|
||||
{
|
||||
@ -260,15 +253,6 @@ void NotebookExplorer::newFolder()
|
||||
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());
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
m_nodeExplorer->setCurrentNode(dialog.getNewNode().data());
|
||||
@ -282,15 +266,6 @@ void NotebookExplorer::newNote()
|
||||
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());
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
m_nodeExplorer->setCurrentNode(dialog.getNewNode().data());
|
||||
@ -340,15 +315,6 @@ void NotebookExplorer::importFile()
|
||||
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();
|
||||
QStringList files = QFileDialog::getOpenFileNames(VNoteX::getInst().getMainWindow(),
|
||||
tr("Select Files To Import"),
|
||||
@ -381,15 +347,6 @@ void NotebookExplorer::importFolder()
|
||||
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());
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
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()
|
||||
{
|
||||
updateSession();
|
||||
|
@ -69,6 +69,8 @@ namespace vnotex
|
||||
|
||||
void setupViewMenu(QMenu *p_menu);
|
||||
|
||||
void setupRecycleBinMenu(QMenu *p_menu);
|
||||
|
||||
void saveSession();
|
||||
|
||||
void loadSession();
|
||||
|
@ -192,13 +192,11 @@ void NotebookNodeExplorer::initNodeIcons() const
|
||||
|
||||
const QString folderIconName("folder_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::FileNode] = IconUtils::fetchIcon(themeMgr.getIconFile(fileIconName), fg);
|
||||
s_nodeIcons[NodeIcon::InvalidFolderNode] = IconUtils::fetchIcon(themeMgr.getIconFile(folderIconName), 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::ExternalFileNode] = IconUtils::fetchIcon(themeMgr.getIconFile(fileIconName), externalFg);
|
||||
}
|
||||
@ -341,7 +339,6 @@ void NotebookNodeExplorer::generateNodeTree()
|
||||
if (currentNode) {
|
||||
setCurrentNode(currentNode);
|
||||
} else {
|
||||
// Do not focus the recycle bin.
|
||||
focusNormalNode();
|
||||
}
|
||||
|
||||
@ -352,12 +349,6 @@ void NotebookNodeExplorer::loadRootNode(const Node *p_node) const
|
||||
{
|
||||
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.
|
||||
if (m_externalFilesVisible) {
|
||||
auto externalChildren = p_node->fetchExternalChildren();
|
||||
@ -372,10 +363,6 @@ void NotebookNodeExplorer::loadRootNode(const Node *p_node) const
|
||||
auto children = p_node->getChildren();
|
||||
sortNodes(children);
|
||||
for (const auto &child : children) {
|
||||
if (recycleBinNode == child) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto item = new QTreeWidgetItem(m_masterExplorer);
|
||||
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
|
||||
{
|
||||
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()) {
|
||||
return p_node->exists() ? s_nodeIcons[NodeIcon::FileNode] : s_nodeIcons[NodeIcon::InvalidFileNode];
|
||||
} 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];
|
||||
}
|
||||
}
|
||||
@ -561,20 +507,9 @@ void NotebookNodeExplorer::updateNode(Node *p_node)
|
||||
if (item) {
|
||||
bool expanded = item->isExpanded();
|
||||
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);
|
||||
} else {
|
||||
if (m_notebook->isRecycleBinNode(p_node) && !m_recycleBinNodeVisible) {
|
||||
// No need to update.
|
||||
return;
|
||||
}
|
||||
|
||||
saveNotebookTreeState(false);
|
||||
|
||||
generateNodeTree();
|
||||
@ -762,106 +697,63 @@ void NotebookNodeExplorer::createContextMenuOnRoot(QMenu *p_menu)
|
||||
void NotebookNodeExplorer::createContextMenuOnNode(QMenu *p_menu, const Node *p_node)
|
||||
{
|
||||
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);
|
||||
createAndAddAction(Action::Open, p_menu);
|
||||
|
||||
if (selectedSize == 1) {
|
||||
createAndAddAction(Action::EmptyRecycleBin, p_menu);
|
||||
addOpenWithMenu(p_menu);
|
||||
|
||||
createAndAddAction(Action::OpenLocation, p_menu);
|
||||
}
|
||||
} else if (m_notebook->isNodeInRecycleBin(p_node)) {
|
||||
// Node in recycle bin.
|
||||
createAndAddAction(Action::Open, p_menu);
|
||||
p_menu->addSeparator();
|
||||
|
||||
addOpenWithMenu(p_menu);
|
||||
if (selectedSize == 1 && p_node->isContainer()) {
|
||||
createAndAddAction(Action::ExpandAll, p_menu);
|
||||
}
|
||||
|
||||
p_menu->addSeparator();
|
||||
|
||||
createAndAddAction(Action::NewNote, p_menu);
|
||||
|
||||
createAndAddAction(Action::NewFolder, p_menu);
|
||||
|
||||
p_menu->addSeparator();
|
||||
|
||||
createAndAddAction(Action::Copy, p_menu);
|
||||
|
||||
createAndAddAction(Action::Cut, p_menu);
|
||||
|
||||
if (selectedSize == 1 && isPasteOnNodeAvailable(p_node)) {
|
||||
createAndAddAction(Action::Paste, p_menu);
|
||||
}
|
||||
|
||||
createAndAddAction(Action::Delete, p_menu);
|
||||
|
||||
createAndAddAction(Action::RemoveFromConfig, p_menu);
|
||||
|
||||
p_menu->addSeparator();
|
||||
|
||||
createAndAddAction(Action::Reload, p_menu);
|
||||
|
||||
createAndAddAction(Action::ReloadIndex, p_menu);
|
||||
|
||||
createAndAddAction(Action::Sort, p_menu);
|
||||
|
||||
if (selectedSize == 1
|
||||
&& m_notebook->tag()
|
||||
&& !p_node->isContainer()) {
|
||||
p_menu->addSeparator();
|
||||
|
||||
if (selectedSize == 1 && p_node->isContainer()) {
|
||||
createAndAddAction(Action::ExpandAll, p_menu);
|
||||
}
|
||||
createAndAddAction(Action::Tag, p_menu);
|
||||
}
|
||||
|
||||
p_menu->addSeparator();
|
||||
p_menu->addSeparator();
|
||||
|
||||
createAndAddAction(Action::Cut, p_menu);
|
||||
createAndAddAction(Action::PinToQuickAccess, p_menu);
|
||||
|
||||
createAndAddAction(Action::DeleteFromRecycleBin, p_menu);
|
||||
if (selectedSize == 1) {
|
||||
createAndAddAction(Action::CopyPath, p_menu);
|
||||
|
||||
p_menu->addSeparator();
|
||||
createAndAddAction(Action::OpenLocation, p_menu);
|
||||
|
||||
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);
|
||||
|
||||
addOpenWithMenu(p_menu);
|
||||
|
||||
p_menu->addSeparator();
|
||||
|
||||
if (selectedSize == 1 && p_node->isContainer()) {
|
||||
createAndAddAction(Action::ExpandAll, p_menu);
|
||||
}
|
||||
|
||||
p_menu->addSeparator();
|
||||
|
||||
createAndAddAction(Action::NewNote, p_menu);
|
||||
|
||||
createAndAddAction(Action::NewFolder, p_menu);
|
||||
|
||||
p_menu->addSeparator();
|
||||
|
||||
createAndAddAction(Action::Copy, p_menu);
|
||||
|
||||
createAndAddAction(Action::Cut, p_menu);
|
||||
|
||||
if (selectedSize == 1 && isPasteOnNodeAvailable(p_node)) {
|
||||
createAndAddAction(Action::Paste, p_menu);
|
||||
}
|
||||
|
||||
createAndAddAction(Action::Delete, p_menu);
|
||||
|
||||
createAndAddAction(Action::RemoveFromConfig, p_menu);
|
||||
|
||||
p_menu->addSeparator();
|
||||
|
||||
createAndAddAction(Action::Reload, p_menu);
|
||||
|
||||
createAndAddAction(Action::ReloadIndex, p_menu);
|
||||
|
||||
createAndAddAction(Action::Sort, p_menu);
|
||||
|
||||
if (selectedSize == 1
|
||||
&& m_notebook->tag()
|
||||
&& !p_node->isContainer()) {
|
||||
p_menu->addSeparator();
|
||||
|
||||
createAndAddAction(Action::Tag, p_menu);
|
||||
}
|
||||
|
||||
p_menu->addSeparator();
|
||||
|
||||
createAndAddAction(Action::PinToQuickAccess, p_menu);
|
||||
|
||||
if (selectedSize == 1) {
|
||||
createAndAddAction(Action::CopyPath, p_menu);
|
||||
|
||||
createAndAddAction(Action::OpenLocation, p_menu);
|
||||
|
||||
createAndAddAction(Action::Properties, p_menu);
|
||||
}
|
||||
createAndAddAction(Action::Properties, p_menu);
|
||||
}
|
||||
}
|
||||
|
||||
@ -901,7 +793,7 @@ QAction *NotebookNodeExplorer::createAction(Action p_act, QObject *p_parent)
|
||||
switch (p_act) {
|
||||
case Action::NewNote:
|
||||
act = new QAction(generateMenuActionIcon("new_note.svg"),
|
||||
tr("New N&ote"),
|
||||
tr("New &Note"),
|
||||
p_parent);
|
||||
connect(act, &QAction::triggered,
|
||||
this, []() {
|
||||
@ -1033,47 +925,10 @@ QAction *NotebookNodeExplorer::createAction(Action p_act, QObject *p_parent)
|
||||
});
|
||||
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:
|
||||
act = new QAction(tr("&Delete"), p_parent);
|
||||
connect(act, &QAction::triggered,
|
||||
this, [this]() {
|
||||
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);
|
||||
});
|
||||
this, &NotebookNodeExplorer::removeSelectedNodes);
|
||||
break;
|
||||
|
||||
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;
|
||||
QString info;
|
||||
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.");
|
||||
}
|
||||
|
||||
const QString text = tr("Delete these folders and notes?");
|
||||
const QString info = tr("Deleted files could be found in the recycle bin of notebook.");
|
||||
auto nodes = confirmSelectedNodes(tr("Confirm Deletion"), text, info);
|
||||
removeNodes(nodes, p_skipRecycleBin, false);
|
||||
removeNodes(nodes, false);
|
||||
}
|
||||
|
||||
QVector<Node *> NotebookNodeExplorer::confirmSelectedNodes(const QString &p_title,
|
||||
@ -1471,9 +1317,7 @@ QVector<Node *> NotebookNodeExplorer::confirmSelectedNodes(const QString &p_titl
|
||||
return nodesToDelete;
|
||||
}
|
||||
|
||||
void NotebookNodeExplorer::removeNodes(QVector<Node *> p_nodes,
|
||||
bool p_skipRecycleBin,
|
||||
bool p_configOnly)
|
||||
void NotebookNodeExplorer::removeNodes(QVector<Node *> p_nodes, bool p_configOnly)
|
||||
{
|
||||
if (p_nodes.isEmpty()) {
|
||||
return;
|
||||
@ -1494,8 +1338,8 @@ void NotebookNodeExplorer::removeNodes(QVector<Node *> p_nodes,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p_configOnly || p_skipRecycleBin) {
|
||||
m_notebook->removeNode(node, false, p_configOnly);
|
||||
if (p_configOnly) {
|
||||
m_notebook->removeNode(node, false, true);
|
||||
} else {
|
||||
m_notebook->moveNodeToRecycleBin(node);
|
||||
}
|
||||
@ -1515,10 +1359,6 @@ void NotebookNodeExplorer::removeNodes(QVector<Node *> p_nodes,
|
||||
updateNode(node);
|
||||
}
|
||||
|
||||
if (!p_configOnly && !p_skipRecycleBin && m_recycleBinNodeVisible) {
|
||||
updateNode(m_notebook->getRecycleBinNode().data());
|
||||
}
|
||||
|
||||
VNoteX::getInst().showStatusMessageShort(tr("Deleted/Removed %n item(s)", "", nrDeleted));
|
||||
}
|
||||
|
||||
@ -1527,7 +1367,7 @@ void NotebookNodeExplorer::removeSelectedNodesFromConfig()
|
||||
auto nodes = confirmSelectedNodes(tr("Confirm Removal"),
|
||||
tr("Remove these folders and notes from 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)
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -1603,12 +1420,11 @@ void NotebookNodeExplorer::reload()
|
||||
void NotebookNodeExplorer::focusNormalNode()
|
||||
{
|
||||
auto item = m_masterExplorer->currentItem();
|
||||
if (item && (!m_recycleBinNodeVisible || item != m_masterExplorer->topLevelItem(0))) {
|
||||
// Not recycle bin.
|
||||
if (item) {
|
||||
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
|
||||
@ -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)
|
||||
{
|
||||
if (m_externalFilesVisible == p_visible) {
|
||||
@ -1748,11 +1554,7 @@ void NotebookNodeExplorer::manualSort()
|
||||
const auto &children = parentNode->getChildrenRef();
|
||||
for (int i = 0; i < children.size(); ++i) {
|
||||
const auto &child = children[i];
|
||||
if (m_notebook->isRecycleBinNode(child.data())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool selected = sortFolders ? child->isContainer() : !child->isContainer();
|
||||
const bool selected = sortFolders ? child->isContainer() : !child->isContainer();
|
||||
if (selected) {
|
||||
selectedIdx.push_back(i);
|
||||
|
||||
|
@ -103,8 +103,6 @@ namespace vnotex
|
||||
|
||||
void reload();
|
||||
|
||||
void setRecycleBinNodeVisible(bool p_visible);
|
||||
|
||||
void setViewOrder(int p_order);
|
||||
|
||||
void setExternalFilesVisible(bool p_visible);
|
||||
@ -146,9 +144,7 @@ namespace vnotex
|
||||
Copy,
|
||||
Cut,
|
||||
Paste,
|
||||
EmptyRecycleBin,
|
||||
Delete,
|
||||
DeleteFromRecycleBin,
|
||||
RemoveFromConfig,
|
||||
Sort,
|
||||
Reload,
|
||||
@ -180,10 +176,6 @@ namespace vnotex
|
||||
|
||||
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, const QSharedPointer<ExternalNode> &p_node) const;
|
||||
@ -225,7 +217,7 @@ namespace vnotex
|
||||
|
||||
QPair<QVector<Node *>, QVector<QSharedPointer<ExternalNode>>> getSelectedNodes() const;
|
||||
|
||||
void removeSelectedNodes(bool p_skipRecycleBin);
|
||||
void removeSelectedNodes();
|
||||
|
||||
void removeSelectedNodesFromConfig();
|
||||
|
||||
@ -241,8 +233,7 @@ namespace vnotex
|
||||
|
||||
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_skipRecycleBin, bool p_configOnly);
|
||||
void removeNodes(QVector<Node *> p_nodes, bool p_configOnly);
|
||||
|
||||
void filterAwayChildrenNodes(QVector<Node *> &p_nodes);
|
||||
|
||||
@ -251,7 +242,6 @@ namespace vnotex
|
||||
// Check if all selected items are the same type for operations.
|
||||
bool allSelectedItemsSameType() const;
|
||||
|
||||
// Skip the recycle bin node if possible.
|
||||
void focusNormalNode();
|
||||
|
||||
void sortNodes(QVector<QSharedPointer<Node>> &p_nodes) const;
|
||||
@ -298,8 +288,6 @@ namespace vnotex
|
||||
|
||||
QScopedPointer<NavigationModeWrapper<QTreeWidget, QTreeWidgetItem>> m_navigationWrapper;
|
||||
|
||||
bool m_recycleBinNodeVisible = false;
|
||||
|
||||
int m_viewOrder = ViewOrder::OrderedByConfiguration;
|
||||
|
||||
bool m_externalFilesVisible = true;
|
||||
@ -312,7 +300,6 @@ namespace vnotex
|
||||
FileNode,
|
||||
InvalidFolderNode,
|
||||
InvalidFileNode,
|
||||
RecycleBinNode,
|
||||
ExternalFolderNode,
|
||||
ExternalFileNode,
|
||||
MaxIcons
|
||||
|
@ -448,7 +448,7 @@ SearchState SearchPanel::search(const QSharedPointer<SearchOption> &p_option)
|
||||
break;
|
||||
}
|
||||
auto folder = m_provider->getCurrentFolder();
|
||||
if (folder && (folder->isRoot() || notebook->isRecycleBinNode(folder))) {
|
||||
if (folder && (folder->isRoot())) {
|
||||
folder = nullptr;
|
||||
}
|
||||
if (!folder) {
|
||||
|
@ -239,11 +239,6 @@ void TagExplorer::updateNodeList(const QString &p_tag)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_notebook->isNodeInRecycleBin(node.data())) {
|
||||
qDebug() << "skipped node in recycle bin" << p_tag << pa;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto item = new QListWidgetItem(m_nodeList);
|
||||
item->setText(node->getName());
|
||||
item->setToolTip(NotebookNodeExplorer::generateToolTip(node.data()));
|
||||
|
Loading…
x
Reference in New Issue
Block a user