refactor Node interface (#1681)

This commit is contained in:
Le Tan 2021-02-01 20:42:39 +08:00 committed by GitHub
parent 508610d304
commit 7595b03639
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 1073 additions and 927 deletions

View File

@ -105,9 +105,9 @@ QString Buffer::getContentPath() const
return m_provider->getContentPath(); return m_provider->getContentPath();
} }
QString Buffer::getContentBasePath() const QString Buffer::getResourcePath() const
{ {
return PathUtils::parentDirPath(getContentPath()); return m_provider->getResourcePath();
} }
ID Buffer::getID() const ID Buffer::getID() const
@ -337,7 +337,7 @@ void Buffer::writeBackupFile()
{ {
if (m_backupFilePath.isEmpty()) { if (m_backupFilePath.isEmpty()) {
const auto &config = ConfigMgr::getInst().getEditorConfig(); const auto &config = ConfigMgr::getInst().getEditorConfig();
QString backupDirPath(QDir(getContentBasePath()).filePath(config.getBackupFileDirectory())); QString backupDirPath(QDir(getResourcePath()).filePath(config.getBackupFileDirectory()));
backupDirPath = QDir::cleanPath(backupDirPath); backupDirPath = QDir::cleanPath(backupDirPath);
auto backupFileName = FileUtils::generateFileNameWithSequence(backupDirPath, auto backupFileName = FileUtils::generateFileNameWithSequence(backupDirPath,
getName(), getName(),
@ -365,7 +365,7 @@ void Buffer::checkBackupFileOfPreviousSession()
return; return;
} }
QString backupDirPath(QDir(getContentBasePath()).filePath(config.getBackupFileDirectory())); QString backupDirPath(QDir(getResourcePath()).filePath(config.getBackupFileDirectory()));
backupDirPath = QDir::cleanPath(backupDirPath); backupDirPath = QDir::cleanPath(backupDirPath);
QDir backupDir(backupDirPath); QDir backupDir(backupDirPath);
QStringList backupFiles; QStringList backupFiles;

View File

@ -81,7 +81,7 @@ namespace vnotex
QString getContentPath() const; QString getContentPath() const;
// Get the base path to resolve resources. // Get the base path to resolve resources.
QString getContentBasePath() const; QString getResourcePath() const;
ID getID() const; ID getID() const;

View File

@ -34,6 +34,8 @@ namespace vnotex
virtual QString getContentPath() const = 0; virtual QString getContentPath() const = 0;
virtual QString getResourcePath() const = 0;
virtual void write(const QString &p_content) = 0; virtual void write(const QString &p_content) = 0;
virtual QString read() const = 0; virtual QString read() const = 0;

View File

@ -5,15 +5,16 @@
#include <utils/pathutils.h> #include <utils/pathutils.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <notebook/node.h> #include <notebook/node.h>
#include <core/file.h>
using namespace vnotex; using namespace vnotex;
FileBufferProvider::FileBufferProvider(const QString &p_filePath, FileBufferProvider::FileBufferProvider(const QSharedPointer<File> &p_file,
Node *p_nodeAttachedTo, Node *p_nodeAttachedTo,
bool p_readOnly, bool p_readOnly,
QObject *p_parent) QObject *p_parent)
: BufferProvider(p_parent), : BufferProvider(p_parent),
c_filePath(p_filePath), m_file(p_file),
c_nodeAttachedTo(p_nodeAttachedTo), c_nodeAttachedTo(p_nodeAttachedTo),
m_readOnly(p_readOnly) m_readOnly(p_readOnly)
{ {
@ -32,42 +33,49 @@ bool FileBufferProvider::match(const Node *p_node) const
bool FileBufferProvider::match(const QString &p_filePath) const bool FileBufferProvider::match(const QString &p_filePath) const
{ {
return PathUtils::areSamePaths(c_filePath, p_filePath); return PathUtils::areSamePaths(m_file->getFilePath(), p_filePath);
} }
QString FileBufferProvider::getName() const QString FileBufferProvider::getName() const
{ {
return PathUtils::fileName(c_filePath); return m_file->getName();
} }
QString FileBufferProvider::getPath() const QString FileBufferProvider::getPath() const
{ {
return c_filePath; return m_file->getFilePath();
} }
QString FileBufferProvider::getContentPath() const QString FileBufferProvider::getContentPath() const
{ {
// TODO. return m_file->getContentPath();
return getPath(); }
QString FileBufferProvider::getResourcePath() const
{
return m_file->getResourcePath();
} }
void FileBufferProvider::write(const QString &p_content) void FileBufferProvider::write(const QString &p_content)
{ {
FileUtils::writeFile(getContentPath(), p_content); m_file->write(p_content);
m_lastModified = getLastModifiedFromFile(); m_lastModified = getLastModifiedFromFile();
} }
QString FileBufferProvider::read() const QString FileBufferProvider::read() const
{ {
const_cast<FileBufferProvider *>(this)->m_lastModified = getLastModifiedFromFile(); const_cast<FileBufferProvider *>(this)->m_lastModified = getLastModifiedFromFile();
return FileUtils::readTextFile(getContentPath()); return m_file->read();
} }
QString FileBufferProvider::fetchImageFolderPath() QString FileBufferProvider::fetchImageFolderPath()
{ {
auto pa = PathUtils::concatenateFilePath(PathUtils::parentDirPath(getContentPath()), QStringLiteral("vx_images")); auto file = m_file->getImageInterface();
QDir().mkpath(pa); if (file) {
return pa; return file->fetchImageFolderPath();
} else {
return QString();
}
} }
bool FileBufferProvider::isChildOf(const Node *p_node) const bool FileBufferProvider::isChildOf(const Node *p_node) const
@ -130,23 +138,30 @@ void FileBufferProvider::removeAttachment(const QStringList &p_paths)
QString FileBufferProvider::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) QString FileBufferProvider::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName)
{ {
const auto imageFolderPath = fetchImageFolderPath(); auto file = m_file->getImageInterface();
auto destFilePath = FileUtils::renameIfExistsCaseInsensitive(PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName)); if (file) {
FileUtils::copyFile(p_srcImagePath, destFilePath); return file->insertImage(p_srcImagePath, p_imageFileName);
return destFilePath; } else {
return QString();
}
} }
QString FileBufferProvider::insertImage(const QImage &p_image, const QString &p_imageFileName) QString FileBufferProvider::insertImage(const QImage &p_image, const QString &p_imageFileName)
{ {
const auto imageFolderPath = fetchImageFolderPath(); auto file = m_file->getImageInterface();
auto destFilePath = FileUtils::renameIfExistsCaseInsensitive(PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName)); if (file) {
p_image.save(destFilePath); return file->insertImage(p_image, p_imageFileName);
return destFilePath; } else {
return QString();
}
} }
void FileBufferProvider::removeImage(const QString &p_imagePath) void FileBufferProvider::removeImage(const QString &p_imagePath)
{ {
FileUtils::removeFile(p_imagePath); auto file = m_file->getImageInterface();
if (file) {
file->removeImage(p_imagePath);
}
} }
bool FileBufferProvider::isAttachmentSupported() const bool FileBufferProvider::isAttachmentSupported() const

View File

@ -5,12 +5,14 @@
namespace vnotex namespace vnotex
{ {
class File;
// Buffer provider based on external file. // Buffer provider based on external file.
class FileBufferProvider : public BufferProvider class FileBufferProvider : public BufferProvider
{ {
Q_OBJECT Q_OBJECT
public: public:
FileBufferProvider(const QString &p_filePath, FileBufferProvider(const QSharedPointer<File> &m_file,
Node *p_nodeAttachedTo, Node *p_nodeAttachedTo,
bool p_readOnly, bool p_readOnly,
QObject *p_parent = nullptr); QObject *p_parent = nullptr);
@ -27,6 +29,8 @@ namespace vnotex
QString getContentPath() const Q_DECL_OVERRIDE; QString getContentPath() const Q_DECL_OVERRIDE;
QString getResourcePath() const Q_DECL_OVERRIDE;
void write(const QString &p_content) Q_DECL_OVERRIDE; void write(const QString &p_content) Q_DECL_OVERRIDE;
QString read() const Q_DECL_OVERRIDE; QString read() const Q_DECL_OVERRIDE;
@ -62,7 +66,7 @@ namespace vnotex
bool isReadOnly() const Q_DECL_OVERRIDE; bool isReadOnly() const Q_DECL_OVERRIDE;
private: private:
const QString c_filePath; QSharedPointer<File> m_file;
Node *c_nodeAttachedTo = nullptr; Node *c_nodeAttachedTo = nullptr;

View File

@ -35,7 +35,7 @@ void MarkdownBuffer::fetchInitialImages()
{ {
Q_ASSERT(m_initialImages.isEmpty()); Q_ASSERT(m_initialImages.isEmpty());
m_initialImages = vte::MarkdownUtils::fetchImagesFromMarkdownText(getContent(), m_initialImages = vte::MarkdownUtils::fetchImagesFromMarkdownText(getContent(),
getContentBasePath(), getResourcePath(),
vte::MarkdownLink::TypeFlag::LocalRelativeInternal); vte::MarkdownLink::TypeFlag::LocalRelativeInternal);
} }
@ -56,7 +56,7 @@ QSet<QString> MarkdownBuffer::clearObsoleteImages()
const bool discarded = state() & StateFlag::Discarded; const bool discarded = state() & StateFlag::Discarded;
const auto latestImages = const auto latestImages =
vte::MarkdownUtils::fetchImagesFromMarkdownText(!discarded ? getContent() : m_provider->read(), vte::MarkdownUtils::fetchImagesFromMarkdownText(!discarded ? getContent() : m_provider->read(),
getContentBasePath(), getResourcePath(),
vte::MarkdownLink::TypeFlag::LocalRelativeInternal); vte::MarkdownLink::TypeFlag::LocalRelativeInternal);
QSet<QString> latestImagesPath; QSet<QString> latestImagesPath;
for (const auto &link : latestImages) { for (const auto &link : latestImages) {

View File

@ -4,15 +4,16 @@
#include <notebook/node.h> #include <notebook/node.h>
#include <utils/pathutils.h> #include <utils/pathutils.h>
#include <core/file.h>
using namespace vnotex; using namespace vnotex;
NodeBufferProvider::NodeBufferProvider(Node *p_node, QObject *p_parent) NodeBufferProvider::NodeBufferProvider(const QSharedPointer<Node> &p_node, QObject *p_parent)
: BufferProvider(p_parent), : BufferProvider(p_parent),
m_node(p_node), m_node(p_node),
m_path(m_node->fetchAbsolutePath()), m_nodeFile(p_node->getContentFile())
m_contentPath(m_node->fetchContentPath())
{ {
Q_ASSERT(m_nodeFile);
} }
Buffer::ProviderType NodeBufferProvider::getType() const Buffer::ProviderType NodeBufferProvider::getType() const
@ -22,7 +23,7 @@ Buffer::ProviderType NodeBufferProvider::getType() const
bool NodeBufferProvider::match(const Node *p_node) const bool NodeBufferProvider::match(const Node *p_node) const
{ {
return m_node == p_node; return m_node.data() == p_node;
} }
bool NodeBufferProvider::match(const QString &p_filePath) const bool NodeBufferProvider::match(const QString &p_filePath) const
@ -37,34 +38,45 @@ QString NodeBufferProvider::getName() const
QString NodeBufferProvider::getPath() const QString NodeBufferProvider::getPath() const
{ {
return m_path; return m_nodeFile->getFilePath();
} }
QString NodeBufferProvider::getContentPath() const QString NodeBufferProvider::getContentPath() const
{ {
return m_contentPath; return m_nodeFile->getContentPath();
}
QString NodeBufferProvider::getResourcePath() const
{
return m_nodeFile->getResourcePath();
} }
void NodeBufferProvider::write(const QString &p_content) void NodeBufferProvider::write(const QString &p_content)
{ {
m_node->write(p_content); m_nodeFile->write(p_content);
m_lastModified = getLastModifiedFromFile(); m_lastModified = getLastModifiedFromFile();
} }
QString NodeBufferProvider::read() const QString NodeBufferProvider::read() const
{ {
const_cast<NodeBufferProvider *>(this)->m_lastModified = getLastModifiedFromFile(); const_cast<NodeBufferProvider *>(this)->m_lastModified = getLastModifiedFromFile();
return m_node->read(); return m_nodeFile->read();
} }
QString NodeBufferProvider::fetchImageFolderPath() QString NodeBufferProvider::fetchImageFolderPath()
{ {
return m_node->fetchImageFolderPath(); auto file = m_nodeFile->getImageInterface();
if (file) {
return file->fetchImageFolderPath();
} else {
Q_ASSERT(false);
return getContentPath();
}
} }
bool NodeBufferProvider::isChildOf(const Node *p_node) const bool NodeBufferProvider::isChildOf(const Node *p_node) const
{ {
return Node::isAncestor(p_node, m_node); return Node::isAncestor(p_node, m_node.data());
} }
QString NodeBufferProvider::getAttachmentFolder() const QString NodeBufferProvider::getAttachmentFolder() const
@ -104,17 +116,30 @@ void NodeBufferProvider::removeAttachment(const QStringList &p_paths)
QString NodeBufferProvider::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) QString NodeBufferProvider::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName)
{ {
return m_node->insertImage(p_srcImagePath, p_imageFileName); auto file = m_nodeFile->getImageInterface();
if (file) {
return file->insertImage(p_srcImagePath, p_imageFileName);
} else {
return QString();
}
} }
QString NodeBufferProvider::insertImage(const QImage &p_image, const QString &p_imageFileName) QString NodeBufferProvider::insertImage(const QImage &p_image, const QString &p_imageFileName)
{ {
return m_node->insertImage(p_image, p_imageFileName); auto file = m_nodeFile->getImageInterface();
if (file) {
return file->insertImage(p_image, p_imageFileName);
} else {
return QString();
}
} }
void NodeBufferProvider::removeImage(const QString &p_imagePath) void NodeBufferProvider::removeImage(const QString &p_imagePath)
{ {
m_node->removeImage(p_imagePath); auto file = m_nodeFile->getImageInterface();
if (file) {
file->removeImage(p_imagePath);
}
} }
bool NodeBufferProvider::isAttachmentSupported() const bool NodeBufferProvider::isAttachmentSupported() const
@ -124,7 +149,7 @@ bool NodeBufferProvider::isAttachmentSupported() const
Node *NodeBufferProvider::getNode() const Node *NodeBufferProvider::getNode() const
{ {
return m_node; return m_node.data();
} }
bool NodeBufferProvider::isReadOnly() const bool NodeBufferProvider::isReadOnly() const

View File

@ -1,16 +1,21 @@
#ifndef NODEBUFFERPROVIDER_H #ifndef NODEBUFFERPROVIDER_H
#define NODEBUFFERPROVIDER_H #define NODEBUFFERPROVIDER_H
#include <QSharedPointer>
#include "bufferprovider.h" #include "bufferprovider.h"
namespace vnotex namespace vnotex
{ {
class File;
class IFileWithImage;
// Buffer provider based on an internal node. // Buffer provider based on an internal node.
class NodeBufferProvider : public BufferProvider class NodeBufferProvider : public BufferProvider
{ {
Q_OBJECT Q_OBJECT
public: public:
NodeBufferProvider(Node *p_node, QObject *p_parent = nullptr); NodeBufferProvider(const QSharedPointer<Node> &p_node, QObject *p_parent = nullptr);
Buffer::ProviderType getType() const Q_DECL_OVERRIDE; Buffer::ProviderType getType() const Q_DECL_OVERRIDE;
@ -24,6 +29,8 @@ namespace vnotex
QString getContentPath() const Q_DECL_OVERRIDE; QString getContentPath() const Q_DECL_OVERRIDE;
QString getResourcePath() const Q_DECL_OVERRIDE;
void write(const QString &p_content) Q_DECL_OVERRIDE; void write(const QString &p_content) Q_DECL_OVERRIDE;
QString read() const Q_DECL_OVERRIDE; QString read() const Q_DECL_OVERRIDE;
@ -59,13 +66,9 @@ namespace vnotex
bool isReadOnly() const Q_DECL_OVERRIDE; bool isReadOnly() const Q_DECL_OVERRIDE;
private: private:
Node *m_node = nullptr; QSharedPointer<Node> m_node;
// Used as cache. QSharedPointer<File> m_nodeFile;
QString m_path;
// Used as cache.
QString m_contentPath;
}; };
} }

View File

@ -13,6 +13,7 @@
#include <utils/widgetutils.h> #include <utils/widgetutils.h>
#include "notebookmgr.h" #include "notebookmgr.h"
#include "vnotex.h" #include "vnotex.h"
#include "externalfile.h"
#include "fileopenparameters.h" #include "fileopenparameters.h"
@ -54,7 +55,7 @@ void BufferMgr::open(Node *p_node, const QSharedPointer<FileOpenParameters> &p_p
return; return;
} }
if (p_node->getType() == Node::Type::Folder) { if (p_node->isContainer()) {
return; return;
} }
@ -71,7 +72,7 @@ void BufferMgr::open(Node *p_node, const QSharedPointer<FileOpenParameters> &p_p
} }
BufferParameters paras; BufferParameters paras;
paras.m_provider.reset(new NodeBufferProvider(p_node)); paras.m_provider.reset(new NodeBufferProvider(p_node->sharedFromThis()));
buffer = factory->createBuffer(paras, this); buffer = factory->createBuffer(paras, this);
addBuffer(buffer); addBuffer(buffer);
} }
@ -95,7 +96,7 @@ void BufferMgr::open(const QString &p_filePath, const QSharedPointer<FileOpenPar
// Check if it is an internal node or not. // Check if it is an internal node or not.
auto node = loadNodeByPath(p_filePath); auto node = loadNodeByPath(p_filePath);
if (node) { if (node) {
if (node->getType() == Node::File) { if (node->hasContent()) {
open(node.data(), p_paras); open(node.data(), p_paras);
return; return;
} else { } else {
@ -123,7 +124,7 @@ void BufferMgr::open(const QString &p_filePath, const QSharedPointer<FileOpenPar
} }
BufferParameters paras; BufferParameters paras;
paras.m_provider.reset(new FileBufferProvider(p_filePath, paras.m_provider.reset(new FileBufferProvider(QSharedPointer<ExternalFile>::create(p_filePath),
p_paras->m_nodeAttachedTo, p_paras->m_nodeAttachedTo,
p_paras->m_readOnly)); p_paras->m_readOnly));
buffer = factory->createBuffer(paras, this); buffer = factory->createBuffer(paras, this);

View File

@ -15,6 +15,8 @@ SOURCES += \
$$PWD/configmgr.cpp \ $$PWD/configmgr.cpp \
$$PWD/coreconfig.cpp \ $$PWD/coreconfig.cpp \
$$PWD/editorconfig.cpp \ $$PWD/editorconfig.cpp \
$$PWD/externalfile.cpp \
$$PWD/file.cpp \
$$PWD/htmltemplatehelper.cpp \ $$PWD/htmltemplatehelper.cpp \
$$PWD/logger.cpp \ $$PWD/logger.cpp \
$$PWD/mainconfig.cpp \ $$PWD/mainconfig.cpp \
@ -36,6 +38,8 @@ HEADERS += \
$$PWD/coreconfig.h \ $$PWD/coreconfig.h \
$$PWD/editorconfig.h \ $$PWD/editorconfig.h \
$$PWD/events.h \ $$PWD/events.h \
$$PWD/externalfile.h \
$$PWD/file.h \
$$PWD/filelocator.h \ $$PWD/filelocator.h \
$$PWD/fileopenparameters.h \ $$PWD/fileopenparameters.h \
$$PWD/htmltemplatehelper.h \ $$PWD/htmltemplatehelper.h \

79
src/core/externalfile.cpp Normal file
View File

@ -0,0 +1,79 @@
#include "externalfile.h"
#include <utils/fileutils.h>
#include <utils/pathutils.h>
using namespace vnotex;
ExternalFile::ExternalFile(const QString &p_filePath)
: c_filePath(p_filePath)
{
}
QString ExternalFile::read() const
{
return FileUtils::readTextFile(getContentPath());
}
void ExternalFile::write(const QString &p_content)
{
FileUtils::writeFile(getContentPath(), p_content);
}
QString ExternalFile::getName() const
{
return PathUtils::fileName(c_filePath);
}
QString ExternalFile::getFilePath() const
{
return c_filePath;
}
QString ExternalFile::getContentPath() const
{
return c_filePath;
}
QString ExternalFile::getResourcePath() const
{
return PathUtils::parentDirPath(getContentPath());
}
IFileWithImage *ExternalFile::getImageInterface()
{
return this;
}
Node *ExternalFile::getNode() const
{
return nullptr;
}
QString ExternalFile::fetchImageFolderPath()
{
auto pa = PathUtils::concatenateFilePath(getResourcePath(), QStringLiteral("vx_images"));
QDir().mkpath(pa);
return pa;
}
QString ExternalFile::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName)
{
const auto imageFolderPath = fetchImageFolderPath();
auto destFilePath = FileUtils::renameIfExistsCaseInsensitive(PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName));
FileUtils::copyFile(p_srcImagePath, destFilePath);
return destFilePath;
}
QString ExternalFile::insertImage(const QImage &p_image, const QString &p_imageFileName)
{
const auto imageFolderPath = fetchImageFolderPath();
auto destFilePath = FileUtils::renameIfExistsCaseInsensitive(PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName));
p_image.save(destFilePath);
return destFilePath;
}
void ExternalFile::removeImage(const QString &p_imagePath)
{
FileUtils::removeFile(p_imagePath);
}

48
src/core/externalfile.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef EXTERNALFILE_H
#define EXTERNALFILE_H
#include "file.h"
namespace vnotex
{
class ExternalFile : public File, public IFileWithImage
{
public:
explicit ExternalFile(const QString &p_filePath);
QString read() const Q_DECL_OVERRIDE;
void write(const QString &p_content) Q_DECL_OVERRIDE;
QString getName() const Q_DECL_OVERRIDE;
QString getFilePath() const Q_DECL_OVERRIDE;
QString getContentPath() const Q_DECL_OVERRIDE;
// Path to resolve resources.
QString getResourcePath() const Q_DECL_OVERRIDE;
IFileWithImage *getImageInterface() Q_DECL_OVERRIDE;
// Get the corresponding node if available.
Node *getNode() const Q_DECL_OVERRIDE;
// IFileWithImage interfaces.
public:
QString fetchImageFolderPath() Q_DECL_OVERRIDE;
// Insert image from @p_srcImagePath.
// Return inserted image file path.
QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) Q_DECL_OVERRIDE;
QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE;
void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE;
private:
QString c_filePath;
};
}
#endif // EXTERNALFILE_H

13
src/core/file.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "file.h"
using namespace vnotex;
const FileType &File::getContentType() const
{
return FileTypeHelper::getInst().getFileType(m_contentType);
}
void File::setContentType(FileTypeHelper::Type p_type)
{
m_contentType = p_type;
}

70
src/core/file.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef FILE_H
#define FILE_H
#include <QString>
#include <buffer/filetypehelper.h>
class QImage;
namespace vnotex
{
class Node;
class IFileWithImage
{
public:
IFileWithImage() = default;
virtual ~IFileWithImage() = default;
virtual QString fetchImageFolderPath() = 0;
// Insert image from @p_srcImagePath.
// Return inserted image file path.
virtual QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) = 0;
virtual QString insertImage(const QImage &p_image, const QString &p_imageFileName) = 0;
virtual void removeImage(const QString &p_imagePath) = 0;
};
// Abstract file interface.
class File
{
public:
File() = default;
virtual ~File() = default;
virtual QString read() const = 0;
virtual void write(const QString &p_content) = 0;
virtual QString getName() const = 0;
virtual QString getFilePath() const = 0;
// The main content file of File.
// In bundle case, getFilePath() may point to a folder, getContentPath() points to the real content file.
virtual QString getContentPath() const = 0;
// Path to resolve resources.
virtual QString getResourcePath() const = 0;
virtual IFileWithImage *getImageInterface() = 0;
// Get the corresponding node if available.
virtual Node *getNode() const = 0;
const FileType &getContentType() const;
protected:
void setContentType(FileTypeHelper::Type p_type);
private:
FileTypeHelper::Type m_contentType = FileTypeHelper::Others;
};
}
#endif // FILE_H

View File

@ -1,135 +0,0 @@
#include "filenode.h"
#include <notebookconfigmgr/inotebookconfigmgr.h>
#include <notebookbackend/inotebookbackend.h>
#include <utils/pathutils.h>
#include <utils/fileutils.h>
#include "notebook.h"
using namespace vnotex;
FileNode::FileNode(ID p_id,
const QString &p_name,
const QDateTime &p_createdTimeUtc,
const QDateTime &p_modifiedTimeUtc,
const QString &p_attachmentFolder,
const QStringList &p_tags,
Notebook *p_notebook,
Node *p_parent)
: Node(Node::Type::File,
p_id,
p_name,
p_createdTimeUtc,
p_notebook,
p_parent),
m_modifiedTimeUtc(p_modifiedTimeUtc),
m_attachmentFolder(p_attachmentFolder),
m_tags(p_tags)
{
}
QVector<QSharedPointer<Node>> FileNode::getChildren() const
{
return QVector<QSharedPointer<Node>>();
}
int FileNode::getChildrenCount() const
{
return 0;
}
void FileNode::addChild(const QSharedPointer<Node> &p_node)
{
Q_ASSERT(false);
Q_UNUSED(p_node);
}
void FileNode::insertChild(int p_idx, const QSharedPointer<Node> &p_node)
{
Q_ASSERT(false);
Q_UNUSED(p_idx);
Q_UNUSED(p_node);
}
void FileNode::removeChild(const QSharedPointer<Node> &p_child)
{
Q_ASSERT(false);
Q_UNUSED(p_child);
}
QDateTime FileNode::getModifiedTimeUtc() const
{
return m_modifiedTimeUtc;
}
void FileNode::setModifiedTimeUtc()
{
m_modifiedTimeUtc = QDateTime::currentDateTimeUtc();
}
QString FileNode::getAttachmentFolder() const
{
return m_attachmentFolder;
}
void FileNode::setAttachmentFolder(const QString &p_folder)
{
m_attachmentFolder = p_folder;
}
QStringList FileNode::addAttachment(const QString &p_destFolderPath, const QStringList &p_files)
{
QStringList addedFiles;
for (const auto &file : p_files) {
if (PathUtils::isDir(file)) {
qWarning() << "skip adding folder as attachment" << file;
continue;
}
auto destFilePath = m_backend->renameIfExistsCaseInsensitive(
PathUtils::concatenateFilePath(p_destFolderPath, PathUtils::fileName(file)));
m_backend->copyFile(file, destFilePath);
addedFiles << destFilePath;
}
return addedFiles;
}
QString FileNode::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name)
{
auto destFilePath = m_backend->renameIfExistsCaseInsensitive(
PathUtils::concatenateFilePath(p_destFolderPath, p_name));
m_backend->writeFile(destFilePath, QByteArray());
return destFilePath;
}
QString FileNode::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name)
{
auto destFilePath = m_backend->renameIfExistsCaseInsensitive(
PathUtils::concatenateFilePath(p_destFolderPath, p_name));
m_backend->makePath(destFilePath);
return destFilePath;
}
QString FileNode::renameAttachment(const QString &p_path, const QString &p_name)
{
m_backend->renameFile(p_path, p_name);
return p_name;
}
void FileNode::removeAttachment(const QStringList &p_paths)
{
// Just move it to recycle bin but not added as a child node of recycle bin.
for (const auto &pa : p_paths) {
if (QFileInfo(pa).isDir()) {
m_notebook->moveDirToRecycleBin(pa);
} else {
m_notebook->moveFileToRecycleBin(pa);
}
}
}
QStringList FileNode::getTags() const
{
return m_tags;
}

View File

@ -1,60 +0,0 @@
#ifndef FILENODE_H
#define FILENODE_H
#include "node.h"
namespace vnotex
{
// File node of notebook.
class FileNode : public Node
{
public:
FileNode(ID p_id,
const QString &p_name,
const QDateTime &p_createdTimeUtc,
const QDateTime &p_modifiedTimeUtc,
const QString &p_attachmentFolder,
const QStringList &p_tags,
Notebook *p_notebook,
Node *p_parent = nullptr);
QVector<QSharedPointer<Node>> getChildren() const Q_DECL_OVERRIDE;
int getChildrenCount() const Q_DECL_OVERRIDE;
void addChild(const QSharedPointer<Node> &p_node) Q_DECL_OVERRIDE;
void insertChild(int p_idx, const QSharedPointer<Node> &p_node) Q_DECL_OVERRIDE;
void removeChild(const QSharedPointer<Node> &p_child) Q_DECL_OVERRIDE;
QDateTime getModifiedTimeUtc() const Q_DECL_OVERRIDE;
void setModifiedTimeUtc() Q_DECL_OVERRIDE;
QString getAttachmentFolder() const Q_DECL_OVERRIDE;
void setAttachmentFolder(const QString &p_folder) Q_DECL_OVERRIDE;
QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files) Q_DECL_OVERRIDE;
QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE;
QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE;
QString renameAttachment(const QString &p_path, const QString &p_name) Q_DECL_OVERRIDE;
void removeAttachment(const QStringList &p_paths) Q_DECL_OVERRIDE;
QStringList getTags() const Q_DECL_OVERRIDE;
private:
QDateTime m_modifiedTimeUtc;
QString m_attachmentFolder;
QStringList m_tags;
};
}
#endif // FILENODE_H

View File

@ -1,65 +0,0 @@
#include "foldernode.h"
using namespace vnotex;
FolderNode::FolderNode(const QString &p_name,
Notebook *p_notebook,
Node *p_parent)
: Node(Node::Type::Folder,
p_name,
p_notebook,
p_parent)
{
}
void FolderNode::loadFolder(ID p_id,
const QDateTime &p_createdTimeUtc,
const QVector<QSharedPointer<Node>> &p_children)
{
Node::loadInfo(p_id, p_createdTimeUtc);
m_children = p_children;
}
QVector<QSharedPointer<Node>> FolderNode::getChildren() const
{
return m_children;
}
int FolderNode::getChildrenCount() const
{
return m_children.size();
}
void FolderNode::addChild(const QSharedPointer<Node> &p_node)
{
insertChild(m_children.size(), p_node);
}
void FolderNode::insertChild(int p_idx, const QSharedPointer<Node> &p_node)
{
p_node->setParent(this);
m_children.insert(p_idx, p_node);
}
void FolderNode::removeChild(const QSharedPointer<Node> &p_child)
{
if (m_children.removeOne(p_child)) {
p_child->setParent(nullptr);
}
}
QDateTime FolderNode::getModifiedTimeUtc() const
{
return getCreatedTimeUtc();
}
void FolderNode::setModifiedTimeUtc()
{
Q_ASSERT(false);
}
QDir FolderNode::toDir() const
{
return QDir(fetchAbsolutePath());
}

View File

@ -1,40 +0,0 @@
#ifndef FOLDERNODE_H
#define FOLDERNODE_H
#include "node.h"
namespace vnotex
{
class FolderNode : public Node
{
public:
FolderNode(const QString &p_name,
Notebook *p_notebook,
Node *p_parent = nullptr);
void loadFolder(ID p_id,
const QDateTime &p_createdTimeUtc,
const QVector<QSharedPointer<Node>> &p_children);
QVector<QSharedPointer<Node>> getChildren() const Q_DECL_OVERRIDE;
int getChildrenCount() const Q_DECL_OVERRIDE;
void addChild(const QSharedPointer<Node> &p_node) Q_DECL_OVERRIDE;
void insertChild(int p_idx, const QSharedPointer<Node> &p_node) Q_DECL_OVERRIDE;
void removeChild(const QSharedPointer<Node> &p_child) Q_DECL_OVERRIDE;
QDateTime getModifiedTimeUtc() const Q_DECL_OVERRIDE;
void setModifiedTimeUtc() Q_DECL_OVERRIDE;
QDir toDir() const Q_DECL_OVERRIDE;
private:
QVector<QSharedPointer<Node>> m_children;
};
} // ns vnotex
#endif // FOLDERNODE_H

View File

@ -10,39 +10,39 @@
using namespace vnotex; using namespace vnotex;
Node::Node(Type p_type, Node::Node(Flags p_flags,
ID p_id, ID p_id,
const QString &p_name, const QString &p_name,
const QDateTime &p_createdTimeUtc, const QDateTime &p_createdTimeUtc,
const QDateTime &p_modifiedTimeUtc,
const QStringList &p_tags,
const QString &p_attachmentFolder,
Notebook *p_notebook, Notebook *p_notebook,
Node *p_parent) Node *p_parent)
: m_notebook(p_notebook), : m_notebook(p_notebook),
m_type(p_type), m_loaded(true),
m_flags(p_flags),
m_id(p_id), m_id(p_id),
m_name(p_name), m_name(p_name),
m_createdTimeUtc(p_createdTimeUtc), m_createdTimeUtc(p_createdTimeUtc),
m_loaded(true), m_modifiedTimeUtc(p_modifiedTimeUtc),
m_tags(p_tags),
m_attachmentFolder(p_attachmentFolder),
m_parent(p_parent) m_parent(p_parent)
{ {
if (m_notebook) { Q_ASSERT(m_notebook);
m_configMgr = m_notebook->getConfigMgr();
m_backend = m_notebook->getBackend();
}
} }
Node::Node(Type p_type, Node::Node(Flags p_flags,
const QString &p_name, const QString &p_name,
Notebook *p_notebook, Notebook *p_notebook,
Node *p_parent) Node *p_parent)
: m_notebook(p_notebook), : m_notebook(p_notebook),
m_type(p_type), m_flags(p_flags),
m_name(p_name), m_name(p_name),
m_parent(p_parent) m_parent(p_parent)
{ {
if (m_notebook) { Q_ASSERT(m_notebook);
m_configMgr = m_notebook->getConfigMgr();
m_backend = m_notebook->getBackend();
}
} }
Node::~Node() Node::~Node()
@ -54,23 +54,24 @@ bool Node::isLoaded() const
return m_loaded; return m_loaded;
} }
void Node::setLoaded(bool p_loaded) void Node::loadCompleteInfo(ID p_id,
{ const QDateTime &p_createdTimeUtc,
m_loaded = p_loaded; const QDateTime &p_modifiedTimeUtc,
} const QStringList &p_tags,
const QVector<QSharedPointer<Node>> &p_children)
void Node::loadInfo(ID p_id, const QDateTime &p_createdTimeUtc)
{ {
Q_ASSERT(!m_loaded); Q_ASSERT(!m_loaded);
m_id = p_id; m_id = p_id;
m_createdTimeUtc = p_createdTimeUtc; m_createdTimeUtc = p_createdTimeUtc;
m_modifiedTimeUtc = p_modifiedTimeUtc;
m_tags = p_tags;
m_children = p_children;
m_loaded = true; m_loaded = true;
} }
bool Node::isRoot() const bool Node::isRoot() const
{ {
return !m_parent; return !m_parent && m_use == Use::Root;
} }
const QString &Node::getName() const const QString &Node::getName() const
@ -78,12 +79,29 @@ const QString &Node::getName() const
return m_name; return m_name;
} }
bool Node::hasChild(const QString &p_name, bool p_caseSensitive) const void Node::setName(const QString &p_name)
{
m_name = p_name;
}
void Node::updateName(const QString &p_name)
{
if (m_name == p_name) {
return;
}
getConfigMgr()->renameNode(this, p_name);
Q_ASSERT(m_name == p_name);
emit m_notebook->nodeUpdated(this);
}
bool Node::containsChild(const QString &p_name, bool p_caseSensitive) const
{ {
return findChild(p_name, p_caseSensitive) != nullptr; return findChild(p_name, p_caseSensitive) != nullptr;
} }
bool Node::hasChild(const QSharedPointer<Node> &p_node) const bool Node::containsChild(const QSharedPointer<Node> &p_node) const
{ {
return getChildren().indexOf(p_node) != -1; return getChildren().indexOf(p_node) != -1;
} }
@ -111,21 +129,11 @@ Node *Node::getParent() const
return m_parent; return m_parent;
} }
Node::Type Node::getType() const
{
return m_type;
}
Node::Flags Node::getFlags() const Node::Flags Node::getFlags() const
{ {
return m_flags; return m_flags;
} }
void Node::setFlags(Node::Flags p_flags)
{
m_flags = p_flags;
}
Node::Use Node::getUse() const Node::Use Node::getUse() const
{ {
return m_use; return m_use;
@ -146,58 +154,52 @@ const QDateTime &Node::getCreatedTimeUtc() const
return m_createdTimeUtc; return m_createdTimeUtc;
} }
const QDateTime &Node::getModifiedTimeUtc() const
{
return m_modifiedTimeUtc;
}
void Node::setModifiedTimeUtc()
{
m_modifiedTimeUtc = QDateTime::currentDateTimeUtc();
}
const QVector<QSharedPointer<Node>> &Node::getChildren() const
{
return m_children;
}
int Node::getChildrenCount() const
{
return m_children.size();
}
void Node::addChild(const QSharedPointer<Node> &p_node)
{
insertChild(m_children.size(), p_node);
}
void Node::insertChild(int p_idx, const QSharedPointer<Node> &p_node)
{
Q_ASSERT(isContainer());
p_node->setParent(this);
m_children.insert(p_idx, p_node);
}
void Node::removeChild(const QSharedPointer<Node> &p_child)
{
if (m_children.removeOne(p_child)) {
p_child->setParent(nullptr);
}
}
Notebook *Node::getNotebook() const Notebook *Node::getNotebook() const
{ {
return m_notebook; return m_notebook;
} }
QString Node::fetchRelativePath() const
{
if (!m_parent) {
return QString();
} else {
return PathUtils::concatenateFilePath(m_parent->fetchRelativePath(), m_name);
}
}
QString Node::fetchAbsolutePath() const
{
return PathUtils::concatenateFilePath(m_notebook->getRootFolderAbsolutePath(),
fetchRelativePath());
}
QString Node::fetchContentPath() const
{
return fetchAbsolutePath();
}
void Node::load()
{
Q_ASSERT(m_notebook);
m_notebook->load(this);
}
void Node::save()
{
Q_ASSERT(m_notebook);
m_notebook->save(this);
}
void Node::setName(const QString &p_name)
{
m_name = p_name;
}
void Node::updateName(const QString &p_name)
{
if (m_name == p_name) {
return;
}
m_notebook->rename(this, p_name);
Q_ASSERT(m_name == p_name);
}
bool Node::isAncestor(const Node *p_ancestor, const Node *p_child) bool Node::isAncestor(const Node *p_ancestor, const Node *p_child)
{ {
if (!p_ancestor || !p_child) { if (!p_ancestor || !p_child) {
@ -214,122 +216,82 @@ bool Node::isAncestor(const Node *p_ancestor, const Node *p_child)
return false; return false;
} }
bool Node::existsOnDisk() const const QStringList &Node::getTags() const
{ {
return m_configMgr->nodeExistsOnDisk(this); return m_tags;
}
QString Node::read() const
{
return m_configMgr->readNode(this);
}
void Node::write(const QString &p_content)
{
m_configMgr->writeNode(this, p_content);
}
QString Node::fetchImageFolderPath()
{
return m_configMgr->fetchNodeImageFolderPath(this);
}
QString Node::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName)
{
const auto imageFolderPath = fetchImageFolderPath();
auto destFilePath = m_backend->renameIfExistsCaseInsensitive(PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName));
m_backend->copyFile(p_srcImagePath, destFilePath);
return destFilePath;
}
QString Node::insertImage(const QImage &p_image, const QString &p_imageFileName)
{
const auto imageFolderPath = fetchImageFolderPath();
auto destFilePath = m_backend->renameIfExistsCaseInsensitive(PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName));
p_image.save(destFilePath);
m_backend->addFile(destFilePath);
return destFilePath;
}
void Node::removeImage(const QString &p_imagePath)
{
// Just move it to recycle bin but not added as a child node of recycle bin.
m_notebook->moveFileToRecycleBin(p_imagePath);
}
QString Node::getAttachmentFolder() const
{
Q_ASSERT(false);
return QString();
}
void Node::setAttachmentFolder(const QString &p_folder)
{
Q_UNUSED(p_folder);
Q_ASSERT(false);
}
QString Node::fetchAttachmentFolderPath()
{
return m_configMgr->fetchNodeAttachmentFolderPath(this);
}
QStringList Node::addAttachment(const QString &p_destFolderPath, const QStringList &p_files)
{
Q_UNUSED(p_destFolderPath);
Q_UNUSED(p_files);
Q_ASSERT(false);
return QStringList();
}
QString Node::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name)
{
Q_UNUSED(p_destFolderPath);
Q_UNUSED(p_name);
Q_ASSERT(false);
return QString();
}
QString Node::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name)
{
Q_UNUSED(p_destFolderPath);
Q_UNUSED(p_name);
Q_ASSERT(false);
return QString();
}
QString Node::renameAttachment(const QString &p_path, const QString &p_name)
{
Q_UNUSED(p_path);
Q_UNUSED(p_name);
Q_ASSERT(false);
return QString();
}
void Node::removeAttachment(const QStringList &p_paths)
{
Q_UNUSED(p_paths);
Q_ASSERT(false);
}
QStringList Node::getTags() const
{
Q_ASSERT(false);
return QStringList();
}
QDir Node::toDir() const
{
Q_ASSERT(false);
return QDir();
}
INotebookBackend *Node::getBackend() const
{
return m_backend.data();
} }
bool Node::isReadOnly() const bool Node::isReadOnly() const
{ {
return m_flags & Flag::ReadOnly; return m_flags & Flag::ReadOnly;
} }
void Node::setReadOnly(bool p_readOnly)
{
if (p_readOnly) {
m_flags |= Flag::ReadOnly;
} else {
m_flags &= ~Flag::ReadOnly;
}
}
QString Node::fetchPath() const
{
if (!m_parent) {
return QString();
} else {
return PathUtils::concatenateFilePath(m_parent->fetchPath(), m_name);
}
}
bool Node::isContainer() const
{
return m_flags & Flag::Container;
}
bool Node::hasContent() const
{
return m_flags & Flag::Content;
}
QDir Node::toDir() const
{
if (isContainer()) {
return QDir(fetchAbsolutePath());
}
}
void Node::load()
{
getConfigMgr()->loadNode(this);
}
void Node::save()
{
getConfigMgr()->saveNode(this);
}
INotebookConfigMgr *Node::getConfigMgr() const
{
return m_notebook->getConfigMgr().data();
}
const QString &Node::getAttachmentFolder() const
{
return m_attachmentFolder;
}
void Node::setAttachmentFolder(const QString &p_attachmentFolder)
{
m_attachmentFolder = p_attachmentFolder;
}
QString Node::fetchAttachmentFolderPath()
{
return getConfigMgr()->fetchNodeAttachmentFolderPath(this);
}
INotebookBackend *Node::getBackend() const
{
return m_notebook->getBackend().data();
}

View File

@ -5,6 +5,7 @@
#include <QVector> #include <QVector>
#include <QSharedPointer> #include <QSharedPointer>
#include <QDir> #include <QDir>
#include <QEnableSharedFromThis>
#include <global.h> #include <global.h>
@ -13,6 +14,7 @@ namespace vnotex
class Notebook; class Notebook;
class INotebookConfigMgr; class INotebookConfigMgr;
class INotebookBackend; class INotebookBackend;
class File;
// Used when add/new a node. // Used when add/new a node.
struct NodeParameters struct NodeParameters
@ -24,43 +26,46 @@ namespace vnotex
}; };
// Node of notebook. // Node of notebook.
class Node class Node : public QEnableSharedFromThis<Node>
{ {
public: public:
enum Type {
Folder,
File
};
enum Flag { enum Flag {
None = 0, None = 0,
ReadOnly = 0x1 // A node with content.
Content = 0x1,
// A node with children.
Container = 0x2,
ReadOnly = 0x4
}; };
Q_DECLARE_FLAGS(Flags, Flag) Q_DECLARE_FLAGS(Flags, Flag)
enum Use { enum Use {
Normal, Normal,
RecycleBin RecycleBin,
Root
}; };
enum { InvalidId = 0 };
// Constructor with all information loaded. // Constructor with all information loaded.
Node(Type p_type, Node(Flags p_flags,
ID p_id, ID p_id,
const QString &p_name, const QString &p_name,
const QDateTime &p_createdTimeUtc, const QDateTime &p_createdTimeUtc,
const QDateTime &p_modifiedTimeUtc,
const QStringList &p_tags,
const QString &p_attachmentFolder,
Notebook *p_notebook, Notebook *p_notebook,
Node *p_parent = nullptr); Node *p_parent);
// Constructor not loaded. // Constructor not loaded.
Node(Type p_type, Node(Flags p_flags,
const QString &p_name, const QString &p_name,
Notebook *p_notebook, Notebook *p_notebook,
Node *p_parent = nullptr); Node *p_parent);
virtual ~Node(); virtual ~Node();
enum { InvalidId = 0 };
bool isLoaded() const; bool isLoaded() const;
bool isRoot() const; bool isRoot() const;
@ -68,13 +73,20 @@ namespace vnotex
const QString &getName() const; const QString &getName() const;
void setName(const QString &p_name); void setName(const QString &p_name);
// Change the config and backend file as well.
void updateName(const QString &p_name); void updateName(const QString &p_name);
Node::Type getType() const; // Fetch path of this node within notebook.
// This may not be the same as the actual file path. It depends on the config mgr.
virtual QString fetchPath() const;
// Fetch absolute file path if available.
virtual QString fetchAbsolutePath() const = 0;
bool isContainer() const;
bool hasContent() const;
Node::Flags getFlags() const; Node::Flags getFlags() const;
void setFlags(Node::Flags p_flags);
Node::Use getUse() const; Node::Use getUse() const;
void setUse(Node::Use p_use); void setUse(Node::Use p_use);
@ -83,97 +95,74 @@ namespace vnotex
const QDateTime &getCreatedTimeUtc() const; const QDateTime &getCreatedTimeUtc() const;
virtual QDateTime getModifiedTimeUtc() const = 0; const QDateTime &getModifiedTimeUtc() const;
virtual void setModifiedTimeUtc() = 0; void setModifiedTimeUtc();
virtual QString getAttachmentFolder() const; const QVector<QSharedPointer<Node>> &getChildren() const;
virtual void setAttachmentFolder(const QString &p_folder); int getChildrenCount() const;
virtual QVector<QSharedPointer<Node>> getChildren() const = 0;
virtual int getChildrenCount() const = 0;
QSharedPointer<Node> findChild(const QString &p_name, bool p_caseSensitive = true) const; QSharedPointer<Node> findChild(const QString &p_name, bool p_caseSensitive = true) const;
bool hasChild(const QString &p_name, bool p_caseSensitive = true) const; bool containsChild(const QString &p_name, bool p_caseSensitive = true) const;
bool hasChild(const QSharedPointer<Node> &p_node) const; bool containsChild(const QSharedPointer<Node> &p_node) const;
virtual void addChild(const QSharedPointer<Node> &p_node) = 0; void addChild(const QSharedPointer<Node> &p_node);
virtual void insertChild(int p_idx, const QSharedPointer<Node> &p_node) = 0; void insertChild(int p_idx, const QSharedPointer<Node> &p_node);
virtual void removeChild(const QSharedPointer<Node> &p_node) = 0; void removeChild(const QSharedPointer<Node> &p_node);
void setParent(Node *p_parent); void setParent(Node *p_parent);
Node *getParent() const; Node *getParent() const;
Notebook *getNotebook() const; Notebook *getNotebook() const;
// Path to the node. void load();
QString fetchRelativePath() const; void save();
QString fetchAbsolutePath() const; const QStringList &getTags() const;
// A node may be a container of all the stuffs, so the node's path may not be identical with const QString &getAttachmentFolder() const;
// the content file path, like TextBundle. void setAttachmentFolder(const QString &p_attachmentFolder);
virtual QString fetchContentPath() const;
// Get image folder path. QString fetchAttachmentFolderPath();
virtual QString fetchImageFolderPath();
virtual void load(); virtual QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files) = 0;
virtual void save();
static bool isAncestor(const Node *p_ancestor, const Node *p_child); virtual QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) = 0;
bool existsOnDisk() const; virtual QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) = 0;
QString read() const; virtual QString renameAttachment(const QString &p_path, const QString &p_name) = 0;
void write(const QString &p_content);
// Insert image from @p_srcImagePath. virtual void removeAttachment(const QStringList &p_paths) = 0;
// Return inserted image file path.
virtual QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName);
virtual QString insertImage(const QImage &p_image, const QString &p_imageFileName); QDir toDir() const;
virtual void removeImage(const QString &p_imagePath); bool isReadOnly() const;
void setReadOnly(bool p_readOnly);
// Get attachment folder path. // Get File if this node has content.
virtual QString fetchAttachmentFolderPath(); virtual QSharedPointer<File> getContentFile() = 0;
virtual QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files); void loadCompleteInfo(ID p_id,
const QDateTime &p_createdTimeUtc,
const QDateTime &p_modifiedTimeUtc,
const QStringList &p_tags,
const QVector<QSharedPointer<Node>> &p_children);
virtual QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name); INotebookConfigMgr *getConfigMgr() const;
virtual QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name);
virtual QString renameAttachment(const QString &p_path, const QString &p_name);
virtual void removeAttachment(const QStringList &p_paths);
virtual QStringList getTags() const;
virtual QDir toDir() const;
INotebookBackend *getBackend() const; INotebookBackend *getBackend() const;
bool isReadOnly() const; static bool isAncestor(const Node *p_ancestor, const Node *p_child);
protected: protected:
void loadInfo(ID p_id, const QDateTime &p_createdTimeUtc);
void setLoaded(bool p_loaded);
Notebook *m_notebook = nullptr; Notebook *m_notebook = nullptr;
QSharedPointer<INotebookConfigMgr> m_configMgr;
QSharedPointer<INotebookBackend> m_backend;
private: private:
Type m_type = Type::Folder; bool m_loaded = false;
Flags m_flags = Flag::None; Flags m_flags = Flag::None;
@ -185,9 +174,15 @@ namespace vnotex
QDateTime m_createdTimeUtc; QDateTime m_createdTimeUtc;
bool m_loaded = false; QDateTime m_modifiedTimeUtc;
QStringList m_tags;
QString m_attachmentFolder;
Node *m_parent = nullptr; Node *m_parent = nullptr;
QVector<QSharedPointer<Node>> m_children;
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS(Node::Flags) Q_DECLARE_OPERATORS_FOR_FLAGS(Node::Flags)

View File

@ -152,6 +152,7 @@ const QSharedPointer<Node> &Notebook::getRootNode() const
{ {
if (!m_root) { if (!m_root) {
const_cast<Notebook *>(this)->m_root = m_configMgr->loadRootNode(); const_cast<Notebook *>(this)->m_root = m_configMgr->loadRootNode();
Q_ASSERT(m_root->isRoot());
} }
return m_root; return m_root;
@ -174,9 +175,9 @@ QSharedPointer<Node> Notebook::getRecycleBinNode() const
return nullptr; return nullptr;
} }
QSharedPointer<Node> Notebook::newNode(Node *p_parent, Node::Type p_type, const QString &p_name) QSharedPointer<Node> Notebook::newNode(Node *p_parent, Node::Flags p_flags, const QString &p_name)
{ {
return m_configMgr->newNode(p_parent, p_type, p_name); return m_configMgr->newNode(p_parent, p_flags, p_name);
} }
const QDateTime &Notebook::getCreatedTimeUtc() const const QDateTime &Notebook::getCreatedTimeUtc() const
@ -184,30 +185,6 @@ const QDateTime &Notebook::getCreatedTimeUtc() const
return m_createdTimeUtc; return m_createdTimeUtc;
} }
void Notebook::load(Node *p_node)
{
Q_ASSERT(p_node->getNotebook() == this);
if (p_node->isLoaded()) {
return;
}
m_configMgr->loadNode(p_node);
}
void Notebook::save(const Node *p_node)
{
Q_ASSERT(p_node->getNotebook() == this);
m_configMgr->saveNode(p_node);
}
void Notebook::rename(Node *p_node, const QString &p_name)
{
Q_ASSERT(p_node->getNotebook() == this);
m_configMgr->renameNode(p_node, p_name);
emit nodeUpdated(p_node);
}
QSharedPointer<Node> Notebook::loadNodeByPath(const QString &p_path) QSharedPointer<Node> Notebook::loadNodeByPath(const QString &p_path)
{ {
if (!PathUtils::pathContains(m_rootFolderPath, p_path)) { if (!PathUtils::pathContains(m_rootFolderPath, p_path)) {
@ -237,7 +214,7 @@ QSharedPointer<Node> Notebook::copyNodeAsChildOf(const QSharedPointer<Node> &p_s
if (Node::isAncestor(p_src.data(), p_dest)) { if (Node::isAncestor(p_src.data(), p_dest)) {
Exception::throwOne(Exception::Type::InvalidArgument, Exception::throwOne(Exception::Type::InvalidArgument,
QString("source (%1) is the ancestor of destination (%2)") QString("source (%1) is the ancestor of destination (%2)")
.arg(p_src->fetchRelativePath(), p_dest->fetchRelativePath())); .arg(p_src->fetchPath(), p_dest->fetchPath()));
return nullptr; return nullptr;
} }
@ -314,7 +291,7 @@ QSharedPointer<Node> Notebook::getOrCreateRecycleBinDateNode()
FileUtils::isPlatformNameCaseSensitive()); FileUtils::isPlatformNameCaseSensitive());
if (!dateNode) { if (!dateNode) {
// Create a date node. // Create a date node.
dateNode = newNode(recycleBinNode.data(), Node::Type::Folder, dateNodeName); dateNode = newNode(recycleBinNode.data(), Node::Flag::Container, dateNodeName);
} }
return dateNode; return dateNode;
@ -331,7 +308,7 @@ void Notebook::emptyNode(const Node *p_node, bool p_force)
void Notebook::moveFileToRecycleBin(const QString &p_filePath) void Notebook::moveFileToRecycleBin(const QString &p_filePath)
{ {
auto node = getOrCreateRecycleBinDateNode(); auto node = getOrCreateRecycleBinDateNode();
auto destFilePath = PathUtils::concatenateFilePath(node->fetchRelativePath(), auto destFilePath = PathUtils::concatenateFilePath(node->fetchPath(),
PathUtils::fileName(p_filePath)); PathUtils::fileName(p_filePath));
destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath); destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath);
m_backend->copyFile(p_filePath, destFilePath); m_backend->copyFile(p_filePath, destFilePath);
@ -344,7 +321,7 @@ void Notebook::moveFileToRecycleBin(const QString &p_filePath)
void Notebook::moveDirToRecycleBin(const QString &p_dirPath) void Notebook::moveDirToRecycleBin(const QString &p_dirPath)
{ {
auto node = getOrCreateRecycleBinDateNode(); auto node = getOrCreateRecycleBinDateNode();
auto destDirPath = PathUtils::concatenateFilePath(node->fetchRelativePath(), auto destDirPath = PathUtils::concatenateFilePath(node->fetchPath(),
PathUtils::fileName(p_dirPath)); PathUtils::fileName(p_dirPath));
destDirPath = getBackend()->renameIfExistsCaseInsensitive(destDirPath); destDirPath = getBackend()->renameIfExistsCaseInsensitive(destDirPath);
m_backend->copyDir(p_dirPath, destDirPath); m_backend->copyDir(p_dirPath, destDirPath);
@ -355,11 +332,11 @@ void Notebook::moveDirToRecycleBin(const QString &p_dirPath)
} }
QSharedPointer<Node> Notebook::addAsNode(Node *p_parent, QSharedPointer<Node> Notebook::addAsNode(Node *p_parent,
Node::Type p_type, Node::Flags p_flags,
const QString &p_name, const QString &p_name,
const NodeParameters &p_paras) const NodeParameters &p_paras)
{ {
return m_configMgr->addAsNode(p_parent, p_type, p_name, p_paras); return m_configMgr->addAsNode(p_parent, p_flags, p_name, p_paras);
} }
bool Notebook::isBuiltInFile(const Node *p_node, const QString &p_name) const bool Notebook::isBuiltInFile(const Node *p_node, const QString &p_name) const
@ -373,8 +350,8 @@ bool Notebook::isBuiltInFolder(const Node *p_node, const QString &p_name) const
} }
QSharedPointer<Node> Notebook::copyAsNode(Node *p_parent, QSharedPointer<Node> Notebook::copyAsNode(Node *p_parent,
Node::Type p_type, Node::Flags p_flags,
const QString &p_path) const QString &p_path)
{ {
return m_configMgr->copyAsNode(p_parent, p_type, p_path); return m_configMgr->copyAsNode(p_parent, p_flags, p_path);
} }

View File

@ -65,28 +65,25 @@ namespace vnotex
QSharedPointer<Node> getRecycleBinNode() const; QSharedPointer<Node> getRecycleBinNode() const;
QSharedPointer<Node> newNode(Node *p_parent, Node::Type p_type, const QString &p_name); QSharedPointer<Node> newNode(Node *p_parent,
Node::Flags p_flags,
const QString &p_name);
// Add @p_name under @p_parent to add as a new node @p_type. // Add @p_name under @p_parent to add as a new node @p_type.
QSharedPointer<Node> addAsNode(Node *p_parent, QSharedPointer<Node> addAsNode(Node *p_parent,
Node::Type p_type, Node::Flags p_flags,
const QString &p_name, const QString &p_name,
const NodeParameters &p_paras); const NodeParameters &p_paras);
// Copy @p_path to @p_parent and add as a new node @p_type. // Copy @p_path to @p_parent and add as a new node @p_type.
QSharedPointer<Node> copyAsNode(Node *p_parent, QSharedPointer<Node> copyAsNode(Node *p_parent,
Node::Type p_type, Node::Flags p_flags,
const QString &p_path); const QString &p_path);
virtual ID getNextNodeId() const = 0; virtual ID getNextNodeId() const = 0;
virtual ID getAndUpdateNextNodeId() = 0; virtual ID getAndUpdateNextNodeId() = 0;
virtual void load(Node *p_node);
virtual void save(const Node *p_node);
virtual void rename(Node *p_node, const QString &p_name);
virtual void updateNotebookConfig() = 0; virtual void updateNotebookConfig() = 0;
virtual void removeNotebookConfig() = 0; virtual void removeNotebookConfig() = 0;

View File

@ -4,8 +4,8 @@ SOURCES += \
$$PWD/notebookparameters.cpp \ $$PWD/notebookparameters.cpp \
$$PWD/bundlenotebook.cpp \ $$PWD/bundlenotebook.cpp \
$$PWD/node.cpp \ $$PWD/node.cpp \
$$PWD/filenode.cpp \ $$PWD/vxnode.cpp \
$$PWD/foldernode.cpp $$PWD/vxnodefile.cpp
HEADERS += \ HEADERS += \
$$PWD/notebook.h \ $$PWD/notebook.h \
@ -14,5 +14,5 @@ HEADERS += \
$$PWD/notebookparameters.h \ $$PWD/notebookparameters.h \
$$PWD/bundlenotebook.h \ $$PWD/bundlenotebook.h \
$$PWD/node.h \ $$PWD/node.h \
$$PWD/filenode.h \ $$PWD/vxnode.h \
$$PWD/foldernode.h $$PWD/vxnodefile.h

View File

@ -0,0 +1,117 @@
#include "vxnode.h"
#include <QDir>
#include <utils/pathutils.h>
#include <notebookbackend/inotebookbackend.h>
#include <notebookconfigmgr/inotebookconfigmgr.h>
#include "notebook.h"
#include "vxnodefile.h"
using namespace vnotex;
VXNode::VXNode(ID p_id,
const QString &p_name,
const QDateTime &p_createdTimeUtc,
const QDateTime &p_modifiedTimeUtc,
const QStringList &p_tags,
const QString &p_attachmentFolder,
Notebook *p_notebook,
Node *p_parent)
: Node(Node::Flag::Content,
p_id,
p_name,
p_createdTimeUtc,
p_modifiedTimeUtc,
p_tags,
p_attachmentFolder,
p_notebook,
p_parent)
{
}
VXNode::VXNode(const QString &p_name,
Notebook *p_notebook,
Node *p_parent)
: Node(Node::Flag::Container,
p_name,
p_notebook,
p_parent)
{
}
QString VXNode::fetchAbsolutePath() const
{
return PathUtils::concatenateFilePath(m_notebook->getRootFolderAbsolutePath(),
fetchPath());
}
QSharedPointer<File> VXNode::getContentFile()
{
// We should not keep the shared ptr of VXNodeFile, or there is a cyclic ref.
return QSharedPointer<VXNodeFile>::create(sharedFromThis().dynamicCast<VXNode>());
}
QStringList VXNode::addAttachment(const QString &p_destFolderPath, const QStringList &p_files)
{
Q_ASSERT(PathUtils::pathContains(fetchAttachmentFolderPath(), p_destFolderPath));
auto backend = getBackend();
QStringList addedFiles;
for (const auto &file : p_files) {
if (PathUtils::isDir(file)) {
qWarning() << "skip adding folder as attachment" << file;
continue;
}
auto destFilePath = backend->renameIfExistsCaseInsensitive(
PathUtils::concatenateFilePath(p_destFolderPath, PathUtils::fileName(file)));
backend->copyFile(file, destFilePath);
addedFiles << destFilePath;
}
return addedFiles;
}
QString VXNode::newAttachmentFile(const QString &p_destFolderPath, const QString &p_name)
{
Q_ASSERT(PathUtils::pathContains(fetchAttachmentFolderPath(), p_destFolderPath));
auto backend = getBackend();
auto destFilePath = backend->renameIfExistsCaseInsensitive(
PathUtils::concatenateFilePath(p_destFolderPath, p_name));
backend->writeFile(destFilePath, QByteArray());
return destFilePath;
}
QString VXNode::newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name)
{
Q_ASSERT(PathUtils::pathContains(fetchAttachmentFolderPath(), p_destFolderPath));
auto backend = getBackend();
auto destFilePath = backend->renameIfExistsCaseInsensitive(
PathUtils::concatenateFilePath(p_destFolderPath, p_name));
backend->makePath(destFilePath);
return destFilePath;
}
QString VXNode::renameAttachment(const QString &p_path, const QString &p_name)
{
Q_ASSERT(PathUtils::pathContains(fetchAttachmentFolderPath(), p_path));
getBackend()->renameFile(p_path, p_name);
return p_name;
}
void VXNode::removeAttachment(const QStringList &p_paths)
{
auto attaFolderPath = fetchAttachmentFolderPath();
// Just move it to recycle bin but not added as a child node of recycle bin.
for (const auto &pa : p_paths) {
Q_ASSERT(PathUtils::pathContains(attaFolderPath, pa));
if (QFileInfo(pa).isDir()) {
m_notebook->moveDirToRecycleBin(pa);
} else {
m_notebook->moveFileToRecycleBin(pa);
}
}
}

View File

@ -0,0 +1,45 @@
#ifndef VXNODE_H
#define VXNODE_H
#include "node.h"
namespace vnotex
{
// Node of VXNotebookConfigMgr.
class VXNode : public Node
{
public:
// For content node.
VXNode(ID p_id,
const QString &p_name,
const QDateTime &p_createdTimeUtc,
const QDateTime &p_modifiedTimeUtc,
const QStringList &p_tags,
const QString &p_attachmentFolder,
Notebook *p_notebook,
Node *p_parent);
// For container node.
VXNode(const QString &p_name,
Notebook *p_notebook,
Node *p_parent);
QString fetchAbsolutePath() const Q_DECL_OVERRIDE;
QSharedPointer<File> getContentFile() Q_DECL_OVERRIDE;
QStringList addAttachment(const QString &p_destFolderPath, const QStringList &p_files) Q_DECL_OVERRIDE;
QString newAttachmentFile(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE;
QString newAttachmentFolder(const QString &p_destFolderPath, const QString &p_name) Q_DECL_OVERRIDE;
QString renameAttachment(const QString &p_path, const QString &p_name) Q_DECL_OVERRIDE;
void removeAttachment(const QStringList &p_paths) Q_DECL_OVERRIDE;
private:
};
}
#endif // VXNODE_H

View File

@ -0,0 +1,92 @@
#include "vxnodefile.h"
#include <QImage>
#include <notebookbackend/inotebookbackend.h>
#include <notebookconfigmgr/inotebookconfigmgr.h>
#include <notebookconfigmgr/vxnotebookconfigmgr.h>
#include <utils/pathutils.h>
#include "vxnode.h"
#include "notebook.h"
using namespace vnotex;
VXNodeFile::VXNodeFile(const QSharedPointer<VXNode> &p_node)
: m_node(p_node)
{
Q_ASSERT(m_node && m_node->hasContent());
}
QString VXNodeFile::read() const
{
return m_node->getBackend()->readTextFile(m_node->fetchPath());
}
void VXNodeFile::write(const QString &p_content)
{
m_node->getBackend()->writeFile(m_node->fetchPath(), p_content);
m_node->setModifiedTimeUtc();
m_node->save();
}
QString VXNodeFile::getName() const
{
return m_node->getName();
}
QString VXNodeFile::getFilePath() const
{
return m_node->fetchAbsolutePath();
}
QString VXNodeFile::getContentPath() const
{
return m_node->fetchAbsolutePath();
}
QString VXNodeFile::getResourcePath() const
{
return PathUtils::parentDirPath(getContentPath());
}
IFileWithImage *VXNodeFile::getImageInterface()
{
return this;
}
Node *VXNodeFile::getNode() const
{
return m_node.data();
}
QString VXNodeFile::fetchImageFolderPath()
{
auto configMgr = dynamic_cast<VXNotebookConfigMgr *>(m_node->getConfigMgr());
return configMgr->fetchNodeImageFolderPath(m_node.data());
}
QString VXNodeFile::insertImage(const QString &p_srcImagePath, const QString &p_imageFileName)
{
auto backend = m_node->getBackend();
const auto imageFolderPath = fetchImageFolderPath();
auto destFilePath = backend->renameIfExistsCaseInsensitive(PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName));
backend->copyFile(p_srcImagePath, destFilePath);
return destFilePath;
}
QString VXNodeFile::insertImage(const QImage &p_image, const QString &p_imageFileName)
{
auto backend = m_node->getBackend();
const auto imageFolderPath = fetchImageFolderPath();
auto destFilePath = backend->renameIfExistsCaseInsensitive(PathUtils::concatenateFilePath(imageFolderPath, p_imageFileName));
p_image.save(destFilePath);
backend->addFile(destFilePath);
return destFilePath;
}
void VXNodeFile::removeImage(const QString &p_imagePath)
{
// Just move it to recycle bin but not added as a child node of recycle bin.
m_node->getNotebook()->moveFileToRecycleBin(p_imagePath);
}

View File

@ -0,0 +1,52 @@
#ifndef VXNODEFILE_H
#define VXNODEFILE_H
#include <QSharedPointer>
#include <core/file.h>
namespace vnotex
{
class VXNode;
// File from VXNode.
class VXNodeFile : public File, public IFileWithImage
{
public:
explicit VXNodeFile(const QSharedPointer<VXNode> &p_node);
QString read() const Q_DECL_OVERRIDE;
void write(const QString &p_content) Q_DECL_OVERRIDE;
QString getName() const Q_DECL_OVERRIDE;
QString getFilePath() const Q_DECL_OVERRIDE;
QString getContentPath() const Q_DECL_OVERRIDE;
QString getResourcePath() const Q_DECL_OVERRIDE;
IFileWithImage *getImageInterface() Q_DECL_OVERRIDE;
// Get the corresponding node if available.
Node *getNode() const Q_DECL_OVERRIDE;
// IFileWithImage interfaces.
public:
QString fetchImageFolderPath() Q_DECL_OVERRIDE;
// Insert image from @p_srcImagePath.
// Return inserted image file path.
QString insertImage(const QString &p_srcImagePath, const QString &p_imageFileName) Q_DECL_OVERRIDE;
QString insertImage(const QImage &p_image, const QString &p_imageFileName) Q_DECL_OVERRIDE;
void removeImage(const QString &p_imagePath) Q_DECL_OVERRIDE;
private:
QSharedPointer<VXNode> m_node;
};
}
#endif // VXNODEFILE_H

View File

@ -44,16 +44,16 @@ namespace vnotex
virtual void renameNode(Node *p_node, const QString &p_name) = 0; virtual void renameNode(Node *p_node, const QString &p_name) = 0;
virtual QSharedPointer<Node> newNode(Node *p_parent, virtual QSharedPointer<Node> newNode(Node *p_parent,
Node::Type p_type, Node::Flags p_flags,
const QString &p_name) = 0; const QString &p_name) = 0;
virtual QSharedPointer<Node> addAsNode(Node *p_parent, virtual QSharedPointer<Node> addAsNode(Node *p_parent,
Node::Type p_type, Node::Flags p_flags,
const QString &p_name, const QString &p_name,
const NodeParameters &p_paras) = 0; const NodeParameters &p_paras) = 0;
virtual QSharedPointer<Node> copyAsNode(Node *p_parent, virtual QSharedPointer<Node> copyAsNode(Node *p_parent,
Node::Type p_type, Node::Flags p_flags,
const QString &p_path) = 0; const QString &p_path) = 0;
Notebook *getNotebook() const; Notebook *getNotebook() const;
@ -68,20 +68,13 @@ 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 bool nodeExistsOnDisk(const Node *p_node) const = 0;
virtual QString readNode(const Node *p_node) const = 0;
virtual void writeNode(Node *p_node, const QString &p_content) = 0;
virtual QString fetchNodeImageFolderPath(Node *p_node) = 0;
virtual QString fetchNodeAttachmentFolderPath(Node *p_node) = 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;
virtual bool isBuiltInFolder(const Node *p_node, const QString &p_name) const = 0; virtual bool isBuiltInFolder(const Node *p_node, const QString &p_name) const = 0;
virtual QString fetchNodeAttachmentFolderPath(Node *p_node) = 0;
protected: protected:
// Version of the config processing code. // Version of the config processing code.
virtual QString getCodeVersion() const; virtual QString getCodeVersion() const;

View File

@ -22,7 +22,8 @@ void NodeContentMediaUtils::copyMediaFiles(const Node *p_node,
INotebookBackend *p_backend, INotebookBackend *p_backend,
const QString &p_destFilePath) const QString &p_destFilePath)
{ {
Q_ASSERT(p_node->getType() == Node::Type::File); Q_ASSERT(p_node->hasContent());
/*
const auto &fileType = FileTypeHelper::getInst().getFileType(p_node->fetchAbsolutePath()); const auto &fileType = FileTypeHelper::getInst().getFileType(p_node->fetchAbsolutePath());
if (fileType.m_type == FileTypeHelper::Markdown) { if (fileType.m_type == FileTypeHelper::Markdown) {
copyMarkdownMediaFiles(p_node->read(), copyMarkdownMediaFiles(p_node->read(),
@ -30,12 +31,14 @@ void NodeContentMediaUtils::copyMediaFiles(const Node *p_node,
p_backend, p_backend,
p_destFilePath); p_destFilePath);
} }
*/
} }
void NodeContentMediaUtils::copyMediaFiles(const QString &p_filePath, void NodeContentMediaUtils::copyMediaFiles(const QString &p_filePath,
INotebookBackend *p_backend, INotebookBackend *p_backend,
const QString &p_destFilePath) const QString &p_destFilePath)
{ {
/*
const auto &fileType = FileTypeHelper::getInst().getFileType(p_filePath); const auto &fileType = FileTypeHelper::getInst().getFileType(p_filePath);
if (fileType.m_type == FileTypeHelper::Markdown) { if (fileType.m_type == FileTypeHelper::Markdown) {
copyMarkdownMediaFiles(FileUtils::readTextFile(p_filePath), copyMarkdownMediaFiles(FileUtils::readTextFile(p_filePath),
@ -43,6 +46,7 @@ void NodeContentMediaUtils::copyMediaFiles(const QString &p_filePath,
p_backend, p_backend,
p_destFilePath); p_destFilePath);
} }
*/
} }
void NodeContentMediaUtils::copyMarkdownMediaFiles(const QString &p_content, void NodeContentMediaUtils::copyMarkdownMediaFiles(const QString &p_content,
@ -50,6 +54,7 @@ void NodeContentMediaUtils::copyMarkdownMediaFiles(const QString &p_content,
INotebookBackend *p_backend, INotebookBackend *p_backend,
const QString &p_destFilePath) const QString &p_destFilePath)
{ {
/*
auto content = p_content; auto content = p_content;
// Images. // Images.
@ -107,19 +112,23 @@ void NodeContentMediaUtils::copyMarkdownMediaFiles(const QString &p_content,
if (!renamedImages.isEmpty()) { if (!renamedImages.isEmpty()) {
p_backend->writeFile(p_destFilePath, content); p_backend->writeFile(p_destFilePath, content);
} }
*/
} }
void NodeContentMediaUtils::removeMediaFiles(const Node *p_node) void NodeContentMediaUtils::removeMediaFiles(const Node *p_node)
{ {
/*
Q_ASSERT(p_node->getType() == Node::Type::File); Q_ASSERT(p_node->getType() == Node::Type::File);
const auto &fileType = FileTypeHelper::getInst().getFileType(p_node->fetchAbsolutePath()); const auto &fileType = FileTypeHelper::getInst().getFileType(p_node->fetchAbsolutePath());
if (fileType.m_type == FileTypeHelper::Markdown) { if (fileType.m_type == FileTypeHelper::Markdown) {
removeMarkdownMediaFiles(p_node); removeMarkdownMediaFiles(p_node);
} }
*/
} }
void NodeContentMediaUtils::removeMarkdownMediaFiles(const Node *p_node) void NodeContentMediaUtils::removeMarkdownMediaFiles(const Node *p_node)
{ {
/*
auto content = p_node->read(); auto content = p_node->read();
// Images. // Images.
@ -143,6 +152,7 @@ void NodeContentMediaUtils::removeMarkdownMediaFiles(const Node *p_node)
} }
backend->removeFile(link.m_path); backend->removeFile(link.m_path);
} }
*/
} }
void NodeContentMediaUtils::copyAttachment(Node *p_node, void NodeContentMediaUtils::copyAttachment(Node *p_node,
@ -150,6 +160,7 @@ void NodeContentMediaUtils::copyAttachment(Node *p_node,
const QString &p_destFilePath, const QString &p_destFilePath,
const QString &p_destAttachmentFolderPath) const QString &p_destAttachmentFolderPath)
{ {
/*
Q_ASSERT(p_node->getType() == Node::Type::File); Q_ASSERT(p_node->getType() == Node::Type::File);
Q_ASSERT(!p_node->getAttachmentFolder().isEmpty()); Q_ASSERT(!p_node->getAttachmentFolder().isEmpty());
@ -166,6 +177,7 @@ void NodeContentMediaUtils::copyAttachment(Node *p_node,
if (fileType.m_type == FileTypeHelper::Markdown) { if (fileType.m_type == FileTypeHelper::Markdown) {
fixMarkdownLinks(srcAttachmentFolderPath, p_backend, p_destFilePath, p_destAttachmentFolderPath); fixMarkdownLinks(srcAttachmentFolderPath, p_backend, p_destFilePath, p_destAttachmentFolderPath);
} }
*/
} }
void NodeContentMediaUtils::fixMarkdownLinks(const QString &p_srcFolderPath, void NodeContentMediaUtils::fixMarkdownLinks(const QString &p_srcFolderPath,

View File

@ -7,8 +7,7 @@
#include <notebookbackend/inotebookbackend.h> #include <notebookbackend/inotebookbackend.h>
#include <notebook/notebookparameters.h> #include <notebook/notebookparameters.h>
#include <notebook/filenode.h> #include <notebook/vxnode.h>
#include <notebook/foldernode.h>
#include <notebook/bundlenotebook.h> #include <notebook/bundlenotebook.h>
#include <utils/utils.h> #include <utils/utils.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
@ -97,10 +96,12 @@ VXNotebookConfigMgr::NodeConfig::NodeConfig()
VXNotebookConfigMgr::NodeConfig::NodeConfig(const QString &p_version, VXNotebookConfigMgr::NodeConfig::NodeConfig(const QString &p_version,
ID p_id, ID p_id,
const QDateTime &p_createdTimeUtc) const QDateTime &p_createdTimeUtc,
const QDateTime &p_modifiedTimeUtc)
: m_version(p_version), : m_version(p_version),
m_id(p_id), m_id(p_id),
m_createdTimeUtc(p_createdTimeUtc) m_createdTimeUtc(p_createdTimeUtc),
m_modifiedTimeUtc(p_modifiedTimeUtc)
{ {
} }
@ -111,6 +112,7 @@ QJsonObject VXNotebookConfigMgr::NodeConfig::toJson() const
jobj[NodeConfig::c_version] = m_version; jobj[NodeConfig::c_version] = m_version;
jobj[NodeConfig::c_id] = QString::number(m_id); jobj[NodeConfig::c_id] = QString::number(m_id);
jobj[NodeConfig::c_createdTimeUtc] = Utils::dateTimeStringUniform(m_createdTimeUtc); jobj[NodeConfig::c_createdTimeUtc] = Utils::dateTimeStringUniform(m_createdTimeUtc);
jobj[NodeConfig::c_modifiedTimeUtc] = Utils::dateTimeStringUniform(m_modifiedTimeUtc);
QJsonArray files; QJsonArray files;
for (const auto &file : m_files) { for (const auto &file : m_files) {
@ -141,6 +143,7 @@ void VXNotebookConfigMgr::NodeConfig::fromJson(const QJsonObject &p_jobj)
} }
m_createdTimeUtc = Utils::dateTimeFromStringUniform(p_jobj[NodeConfig::c_createdTimeUtc].toString()); m_createdTimeUtc = Utils::dateTimeFromStringUniform(p_jobj[NodeConfig::c_createdTimeUtc].toString());
m_modifiedTimeUtc = Utils::dateTimeFromStringUniform(p_jobj[NodeConfig::c_modifiedTimeUtc].toString());
auto filesJson = p_jobj[NodeConfig::c_files].toArray(); auto filesJson = p_jobj[NodeConfig::c_files].toArray();
m_files.resize(filesJson.size()); m_files.resize(filesJson.size());
@ -194,9 +197,11 @@ void VXNotebookConfigMgr::createEmptySkeleton(const NotebookParameters &p_paras)
void VXNotebookConfigMgr::createEmptyRootNode() void VXNotebookConfigMgr::createEmptyRootNode()
{ {
auto currentTime = QDateTime::currentDateTimeUtc();
NodeConfig node(getCodeVersion(), NodeConfig node(getCodeVersion(),
BundleNotebookConfigMgr::RootNodeId, BundleNotebookConfigMgr::RootNodeId,
QDateTime::currentDateTimeUtc()); currentTime,
currentTime);
writeNodeConfig(c_nodeConfigName, node); writeNodeConfig(c_nodeConfigName, node);
} }
@ -204,6 +209,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::loadRootNode() const
{ {
auto nodeConfig = readNodeConfig(""); auto nodeConfig = readNodeConfig("");
QSharedPointer<Node> root = nodeConfigToNode(*nodeConfig, "", nullptr); QSharedPointer<Node> root = nodeConfigToNode(*nodeConfig, "", nullptr);
root->setUse(Node::Use::Root);
Q_ASSERT(root->isLoaded()); Q_ASSERT(root->isLoaded());
if (!markRecycleBinNode(root)) { if (!markRecycleBinNode(root)) {
@ -228,12 +234,11 @@ bool VXNotebookConfigMgr::markRecycleBinNode(const QSharedPointer<Node> &p_root)
void VXNotebookConfigMgr::markNodeReadOnly(Node *p_node) const void VXNotebookConfigMgr::markNodeReadOnly(Node *p_node) const
{ {
auto flags = p_node->getFlags(); if (p_node->isReadOnly()) {
if (flags & Node::Flag::ReadOnly) {
return; return;
} }
p_node->setFlags(flags | Node::Flag::ReadOnly); p_node->setReadOnly(true);
for (auto &child : p_node->getChildren()) { for (auto &child : p_node->getChildren()) {
markNodeReadOnly(child.data()); markNodeReadOnly(child.data());
} }
@ -243,7 +248,7 @@ void VXNotebookConfigMgr::createRecycleBinNode(const QSharedPointer<Node> &p_roo
{ {
Q_ASSERT(p_root->isRoot()); Q_ASSERT(p_root->isRoot());
auto node = newNode(p_root.data(), Node::Type::Folder, c_recycleBinFolderName); auto node = newNode(p_root.data(), Node::Flag::Container, c_recycleBinFolderName);
node->setUse(Node::Use::RecycleBin); node->setUse(Node::Use::RecycleBin);
markNodeReadOnly(node.data()); markNodeReadOnly(node.data());
} }
@ -272,8 +277,8 @@ QSharedPointer<VXNotebookConfigMgr::NodeConfig> VXNotebookConfigMgr::readNodeCon
QString VXNotebookConfigMgr::getNodeConfigFilePath(const Node *p_node) const QString VXNotebookConfigMgr::getNodeConfigFilePath(const Node *p_node) const
{ {
Q_ASSERT(p_node->getType() == Node::Type::Folder); Q_ASSERT(p_node->isContainer());
return PathUtils::concatenateFilePath(p_node->fetchRelativePath(), c_nodeConfigName); return PathUtils::concatenateFilePath(p_node->fetchPath(), c_nodeConfigName);
} }
void VXNotebookConfigMgr::writeNodeConfig(const QString &p_path, const NodeConfig &p_config) const void VXNotebookConfigMgr::writeNodeConfig(const QString &p_path, const NodeConfig &p_config) const
@ -291,18 +296,18 @@ QSharedPointer<Node> VXNotebookConfigMgr::nodeConfigToNode(const NodeConfig &p_c
const QString &p_name, const QString &p_name,
Node *p_parent) const Node *p_parent) const
{ {
auto node = QSharedPointer<FolderNode>::create(p_name, getNotebook(), p_parent); auto node = QSharedPointer<VXNode>::create(p_name, getNotebook(), p_parent);
loadFolderNode(node.data(), p_config); loadFolderNode(node.data(), p_config);
return node; return node;
} }
void VXNotebookConfigMgr::loadFolderNode(FolderNode *p_node, const NodeConfig &p_config) const void VXNotebookConfigMgr::loadFolderNode(Node *p_node, const NodeConfig &p_config) const
{ {
QVector<QSharedPointer<Node>> children; QVector<QSharedPointer<Node>> children;
children.reserve(p_config.m_files.size() + p_config.m_folders.size()); children.reserve(p_config.m_files.size() + p_config.m_folders.size());
for (const auto &folder : p_config.m_folders) { for (const auto &folder : p_config.m_folders) {
auto folderNode = QSharedPointer<FolderNode>::create(folder.m_name, auto folderNode = QSharedPointer<VXNode>::create(folder.m_name,
getNotebook(), getNotebook(),
p_node); p_node);
inheritNodeFlags(p_node, folderNode.data()); inheritNodeFlags(p_node, folderNode.data());
@ -310,78 +315,73 @@ void VXNotebookConfigMgr::loadFolderNode(FolderNode *p_node, const NodeConfig &p
} }
for (const auto &file : p_config.m_files) { for (const auto &file : p_config.m_files) {
auto fileNode = QSharedPointer<FileNode>::create(file.m_id, auto fileNode = QSharedPointer<VXNode>::create(file.m_id,
file.m_name, file.m_name,
file.m_createdTimeUtc, file.m_createdTimeUtc,
file.m_modifiedTimeUtc, file.m_modifiedTimeUtc,
file.m_attachmentFolder,
file.m_tags, file.m_tags,
file.m_attachmentFolder,
getNotebook(), getNotebook(),
p_node); p_node);
inheritNodeFlags(p_node, fileNode.data()); inheritNodeFlags(p_node, fileNode.data());
children.push_back(fileNode); children.push_back(fileNode);
} }
p_node->loadFolder(p_config.m_id, p_config.m_createdTimeUtc, children); p_node->loadCompleteInfo(p_config.m_id,
p_config.m_createdTimeUtc,
p_config.m_modifiedTimeUtc,
QStringList(),
children);
} }
QSharedPointer<Node> VXNotebookConfigMgr::newNode(Node *p_parent, QSharedPointer<Node> VXNotebookConfigMgr::newNode(Node *p_parent,
Node::Type p_type, Node::Flags p_flags,
const QString &p_name) const QString &p_name)
{ {
Q_ASSERT(p_parent && p_parent->getType() == Node::Type::Folder); Q_ASSERT(p_parent && p_parent->isContainer());
QSharedPointer<Node> node; QSharedPointer<Node> node;
switch (p_type) { if (p_flags & Node::Flag::Content) {
case Node::Type::File: Q_ASSERT(!(p_flags & Node::Flag::Container));
node = newFileNode(p_parent, p_name, true, NodeParameters()); node = newFileNode(p_parent, p_name, true, NodeParameters());
break; } else {
case Node::Type::Folder:
node = newFolderNode(p_parent, p_name, true, NodeParameters()); node = newFolderNode(p_parent, p_name, true, NodeParameters());
break;
} }
return node; return node;
} }
QSharedPointer<Node> VXNotebookConfigMgr::addAsNode(Node *p_parent, QSharedPointer<Node> VXNotebookConfigMgr::addAsNode(Node *p_parent,
Node::Type p_type, Node::Flags p_flags,
const QString &p_name, const QString &p_name,
const NodeParameters &p_paras) const NodeParameters &p_paras)
{ {
Q_ASSERT(p_parent && p_parent->getType() == Node::Type::Folder); Q_ASSERT(p_parent && p_parent->isContainer());
QSharedPointer<Node> node; QSharedPointer<Node> node;
switch (p_type) { if (p_flags & Node::Flag::Content) {
case Node::Type::File: Q_ASSERT(!(p_flags & Node::Flag::Container));
node = newFileNode(p_parent, p_name, false, p_paras); node = newFileNode(p_parent, p_name, false, p_paras);
break; } else {
case Node::Type::Folder:
node = newFolderNode(p_parent, p_name, false, p_paras); node = newFolderNode(p_parent, p_name, false, p_paras);
break;
} }
return node; return node;
} }
QSharedPointer<Node> VXNotebookConfigMgr::copyAsNode(Node *p_parent, QSharedPointer<Node> VXNotebookConfigMgr::copyAsNode(Node *p_parent,
Node::Type p_type, Node::Flags p_flags,
const QString &p_path) const QString &p_path)
{ {
Q_ASSERT(p_parent && p_parent->getType() == Node::Type::Folder); Q_ASSERT(p_parent && p_parent->isContainer());
QSharedPointer<Node> node; QSharedPointer<Node> node;
switch (p_type) { if (p_flags & Node::Flag::Content) {
case Node::Type::File: Q_ASSERT(!(p_flags & Node::Flag::Container));
node = copyFileAsChildOf(p_path, p_parent); node = copyFileAsChildOf(p_path, p_parent);
break; } else {
case Node::Type::Folder:
node = copyFolderAsChildOf(p_path, p_parent); node = copyFolderAsChildOf(p_path, p_parent);
break;
} }
return node; return node;
@ -395,18 +395,18 @@ QSharedPointer<Node> VXNotebookConfigMgr::newFileNode(Node *p_parent,
auto notebook = getNotebook(); auto notebook = getNotebook();
// Create file node. // Create file node.
auto node = QSharedPointer<FileNode>::create(Node::InvalidId, auto node = QSharedPointer<VXNode>::create(Node::InvalidId,
p_name, p_name,
p_paras.m_createdTimeUtc, p_paras.m_createdTimeUtc,
p_paras.m_modifiedTimeUtc, p_paras.m_modifiedTimeUtc,
p_paras.m_attachmentFolder,
p_paras.m_tags, p_paras.m_tags,
p_paras.m_attachmentFolder,
notebook, notebook,
p_parent); p_parent);
// Write empty file. // Write empty file.
if (p_create) { if (p_create) {
getBackend()->writeFile(node->fetchRelativePath(), QString()); getBackend()->writeFile(node->fetchPath(), QString());
} }
addChildNode(p_parent, node); addChildNode(p_parent, node);
@ -423,14 +423,16 @@ QSharedPointer<Node> VXNotebookConfigMgr::newFolderNode(Node *p_parent,
auto notebook = getNotebook(); auto notebook = getNotebook();
// Create folder node. // Create folder node.
auto node = QSharedPointer<FolderNode>::create(p_name, notebook, p_parent); auto node = QSharedPointer<VXNode>::create(p_name, notebook, p_parent);
node->loadFolder(Node::InvalidId, node->loadCompleteInfo(Node::InvalidId,
p_paras.m_createdTimeUtc, p_paras.m_createdTimeUtc,
p_paras.m_modifiedTimeUtc,
QStringList(),
QVector<QSharedPointer<Node>>()); QVector<QSharedPointer<Node>>());
// Make folder. // Make folder.
if (p_create) { if (p_create) {
getBackend()->makePath(node->fetchRelativePath()); getBackend()->makePath(node->fetchPath());
} }
writeNodeConfig(node.data()); writeNodeConfig(node.data());
@ -443,16 +445,15 @@ QSharedPointer<Node> VXNotebookConfigMgr::newFolderNode(Node *p_parent,
QSharedPointer<VXNotebookConfigMgr::NodeConfig> VXNotebookConfigMgr::nodeToNodeConfig(const Node *p_node) const QSharedPointer<VXNotebookConfigMgr::NodeConfig> VXNotebookConfigMgr::nodeToNodeConfig(const Node *p_node) const
{ {
Q_ASSERT(p_node->getType() == Node::Type::Folder); Q_ASSERT(p_node->isContainer());
auto config = QSharedPointer<NodeConfig>::create(getCodeVersion(), auto config = QSharedPointer<NodeConfig>::create(getCodeVersion(),
p_node->getId(), p_node->getId(),
p_node->getCreatedTimeUtc()); p_node->getCreatedTimeUtc(),
p_node->getModifiedTimeUtc());
for (const auto &child : p_node->getChildren()) { for (const auto &child : p_node->getChildren()) {
switch (child->getType()) { if (child->hasContent()) {
case Node::Type::File:
{
NodeFileConfig fileConfig; NodeFileConfig fileConfig;
fileConfig.m_name = child->getName(); fileConfig.m_name = child->getName();
fileConfig.m_id = child->getId(); fileConfig.m_id = child->getId();
@ -462,17 +463,12 @@ QSharedPointer<VXNotebookConfigMgr::NodeConfig> VXNotebookConfigMgr::nodeToNodeC
fileConfig.m_tags = child->getTags(); fileConfig.m_tags = child->getTags();
config->m_files.push_back(fileConfig); config->m_files.push_back(fileConfig);
break; } else {
} Q_ASSERT(child->isContainer());
case Node::Type::Folder:
{
NodeFolderConfig folderConfig; NodeFolderConfig folderConfig;
folderConfig.m_name = child->getName(); folderConfig.m_name = child->getName();
config->m_folders.push_back(folderConfig); config->m_folders.push_back(folderConfig);
break;
}
} }
} }
@ -485,16 +481,16 @@ void VXNotebookConfigMgr::loadNode(Node *p_node) const
return; return;
} }
auto config = readNodeConfig(p_node->fetchRelativePath()); auto config = readNodeConfig(p_node->fetchPath());
auto folderNode = dynamic_cast<FolderNode *>(p_node); Q_ASSERT(p_node->isContainer());
loadFolderNode(folderNode, *config); loadFolderNode(p_node, *config);
} }
void VXNotebookConfigMgr::saveNode(const Node *p_node) void VXNotebookConfigMgr::saveNode(const Node *p_node)
{ {
Q_ASSERT(!p_node->isRoot()); Q_ASSERT(!p_node->isRoot());
if (p_node->getType() == Node::Type::Folder) { if (p_node->isContainer()) {
writeNodeConfig(p_node); writeNodeConfig(p_node);
} else { } else {
writeNodeConfig(p_node->getParent()); writeNodeConfig(p_node->getParent());
@ -504,14 +500,10 @@ void VXNotebookConfigMgr::saveNode(const Node *p_node)
void VXNotebookConfigMgr::renameNode(Node *p_node, const QString &p_name) void VXNotebookConfigMgr::renameNode(Node *p_node, const QString &p_name)
{ {
Q_ASSERT(!p_node->isRoot()); Q_ASSERT(!p_node->isRoot());
switch (p_node->getType()) { if (p_node->isContainer()) {
case Node::Type::Folder: getBackend()->renameDir(p_node->fetchPath(), p_name);
getBackend()->renameDir(p_node->fetchRelativePath(), p_name); } else {
break; getBackend()->renameFile(p_node->fetchPath(), p_name);
case Node::Type::File:
getBackend()->renameFile(p_node->fetchRelativePath(), p_name);
break;
} }
p_node->setName(p_name); p_node->setName(p_name);
@ -520,26 +512,18 @@ void VXNotebookConfigMgr::renameNode(Node *p_node, const QString &p_name)
void VXNotebookConfigMgr::addChildNode(Node *p_parent, const QSharedPointer<Node> &p_child) const void VXNotebookConfigMgr::addChildNode(Node *p_parent, const QSharedPointer<Node> &p_child) const
{ {
// Add @p_child after the last node of same type. if (p_child->isContainer()) {
const auto type = p_child->getType();
switch (type) {
case Node::Type::Folder:
{
int idx = 0; int idx = 0;
auto children = p_parent->getChildren(); auto children = p_parent->getChildren();
for (; idx < children.size(); ++idx) { for (; idx < children.size(); ++idx) {
if (children[idx]->getType() != type) { if (!children[idx]->isContainer()) {
break; break;
} }
} }
p_parent->insertChild(idx, p_child); p_parent->insertChild(idx, p_child);
break; } else {
}
case Node::Type::File:
p_parent->addChild(p_child); p_parent->addChild(p_child);
break;
} }
inheritNodeFlags(p_parent, p_child.data()); inheritNodeFlags(p_parent, p_child.data());
@ -573,22 +557,13 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyNodeAsChildOf(const QSharedPointer
Node *p_dest, Node *p_dest,
bool p_move) bool p_move)
{ {
Q_ASSERT(p_dest->getType() == Node::Type::Folder); Q_ASSERT(p_dest->isContainer());
if (!p_src->existsOnDisk()) {
Exception::throwOne(Exception::Type::FileMissingOnDisk,
QString("source node missing on disk (%1)").arg(p_src->fetchAbsolutePath()));
return nullptr;
}
QSharedPointer<Node> node; QSharedPointer<Node> node;
switch (p_src->getType()) { if (p_src->isContainer()) {
case Node::Type::File:
node = copyFileNodeAsChildOf(p_src, p_dest, p_move);
break;
case Node::Type::Folder:
node = copyFolderNodeAsChildOf(p_src, p_dest, p_move); node = copyFolderNodeAsChildOf(p_src, p_dest, p_move);
break; } else {
node = copyFileNodeAsChildOf(p_src, p_dest, p_move);
} }
return node; return node;
@ -600,7 +575,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFileNodeAsChildOf(const QSharedPoi
{ {
// Copy source file itself. // Copy source file itself.
auto srcFilePath = p_src->fetchAbsolutePath(); auto srcFilePath = p_src->fetchAbsolutePath();
auto destFilePath = PathUtils::concatenateFilePath(p_dest->fetchRelativePath(), auto destFilePath = PathUtils::concatenateFilePath(p_dest->fetchPath(),
PathUtils::fileName(srcFilePath)); PathUtils::fileName(srcFilePath));
destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath); destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath);
getBackend()->copyFile(srcFilePath, destFilePath); getBackend()->copyFile(srcFilePath, destFilePath);
@ -623,12 +598,12 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFileNodeAsChildOf(const QSharedPoi
id = notebook->getAndUpdateNextNodeId(); id = notebook->getAndUpdateNextNodeId();
} }
auto destNode = QSharedPointer<FileNode>::create(id, auto destNode = QSharedPointer<VXNode>::create(id,
PathUtils::fileName(destFilePath), PathUtils::fileName(destFilePath),
p_src->getCreatedTimeUtc(), p_src->getCreatedTimeUtc(),
p_src->getModifiedTimeUtc(), p_src->getModifiedTimeUtc(),
attachmentFolder,
p_src->getTags(), p_src->getTags(),
attachmentFolder,
notebook, notebook,
p_dest); p_dest);
addChildNode(p_dest, destNode); addChildNode(p_dest, destNode);
@ -647,7 +622,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFolderNodeAsChildOf(const QSharedP
bool p_move) bool p_move)
{ {
auto srcFolderPath = p_src->fetchAbsolutePath(); auto srcFolderPath = p_src->fetchAbsolutePath();
auto destFolderPath = PathUtils::concatenateFilePath(p_dest->fetchRelativePath(), auto destFolderPath = PathUtils::concatenateFilePath(p_dest->fetchPath(),
PathUtils::fileName(srcFolderPath)); PathUtils::fileName(srcFolderPath));
destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath); destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath);
@ -661,10 +636,14 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFolderNodeAsChildOf(const QSharedP
// Use a new id. // Use a new id.
id = notebook->getAndUpdateNextNodeId(); id = notebook->getAndUpdateNextNodeId();
} }
auto destNode = QSharedPointer<FolderNode>::create(PathUtils::fileName(destFolderPath), auto destNode = QSharedPointer<VXNode>::create(PathUtils::fileName(destFolderPath),
notebook, notebook,
p_dest); p_dest);
destNode->loadFolder(id, p_src->getCreatedTimeUtc(), QVector<QSharedPointer<Node>>()); destNode->loadCompleteInfo(id,
p_src->getCreatedTimeUtc(),
p_src->getModifiedTimeUtc(),
QStringList(),
QVector<QSharedPointer<Node>>());
writeNodeConfig(destNode.data()); writeNodeConfig(destNode.data());
@ -704,9 +683,7 @@ void VXNotebookConfigMgr::removeNode(const QSharedPointer<Node> &p_node, bool p_
void VXNotebookConfigMgr::removeFilesOfNode(Node *p_node, bool p_force) void VXNotebookConfigMgr::removeFilesOfNode(Node *p_node, bool p_force)
{ {
Q_ASSERT(p_node->getNotebook() == getNotebook()); Q_ASSERT(p_node->getNotebook() == getNotebook());
switch (p_node->getType()) { if (!p_node->isContainer()) {
case Node::Type::File:
{
// Delete attachment. // Delete attachment.
if (!p_node->getAttachmentFolder().isEmpty()) { if (!p_node->getAttachmentFolder().isEmpty()) {
getBackend()->removeDir(p_node->fetchAttachmentFolderPath()); getBackend()->removeDir(p_node->fetchAttachmentFolderPath());
@ -716,18 +693,14 @@ void VXNotebookConfigMgr::removeFilesOfNode(Node *p_node, bool p_force)
NodeContentMediaUtils::removeMediaFiles(p_node); NodeContentMediaUtils::removeMediaFiles(p_node);
// Delete node file itself. // Delete node file itself.
auto filePath = p_node->fetchRelativePath(); auto filePath = p_node->fetchPath();
getBackend()->removeFile(filePath); getBackend()->removeFile(filePath);
break; } else {
}
case Node::Type::Folder:
{
Q_ASSERT(p_node->getChildrenCount() == 0); Q_ASSERT(p_node->getChildrenCount() == 0);
// Delete node config file and the dir if it is empty. // Delete node config file and the dir if it is empty.
auto configFilePath = getNodeConfigFilePath(p_node); auto configFilePath = getNodeConfigFilePath(p_node);
getBackend()->removeFile(configFilePath); getBackend()->removeFile(configFilePath);
auto folderPath = p_node->fetchRelativePath(); auto folderPath = p_node->fetchPath();
if (p_force) { if (p_force) {
getBackend()->removeDir(folderPath); getBackend()->removeDir(folderPath);
} else { } else {
@ -737,37 +710,15 @@ void VXNotebookConfigMgr::removeFilesOfNode(Node *p_node, bool p_force)
qWarning() << "folder is not deleted since it is not empty" << folderPath; qWarning() << "folder is not deleted since it is not empty" << folderPath;
} }
} }
break;
} }
} }
}
bool VXNotebookConfigMgr::nodeExistsOnDisk(const Node *p_node) const
{
return getBackend()->exists(p_node->fetchRelativePath());
}
QString VXNotebookConfigMgr::readNode(const Node *p_node) const
{
Q_ASSERT(p_node->getType() == Node::Type::File);
return getBackend()->readTextFile(p_node->fetchRelativePath());
}
void VXNotebookConfigMgr::writeNode(Node *p_node, const QString &p_content)
{
Q_ASSERT(p_node->getType() == Node::Type::File);
getBackend()->writeFile(p_node->fetchRelativePath(), p_content);
p_node->setModifiedTimeUtc();
writeNodeConfig(p_node->getParent());
}
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()),
getNotebook()->getImageFolder()); getNotebook()->getImageFolder());
// Do not make the folder when it is a folder node request. // Do not make the folder when it is a folder node request.
if (p_node->getType() == Node::Type::File) { if (p_node->hasContent()) {
getBackend()->makePath(pa); getBackend()->makePath(pa);
} }
return pa; return pa;
@ -777,7 +728,7 @@ QString VXNotebookConfigMgr::fetchNodeAttachmentFolderPath(Node *p_node)
{ {
auto notebookFolder = PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_node->fetchAbsolutePath()), auto notebookFolder = PathUtils::concatenateFilePath(PathUtils::parentDirPath(p_node->fetchAbsolutePath()),
getNotebook()->getAttachmentFolder()); getNotebook()->getAttachmentFolder());
if (p_node->getType() == Node::Type::File) { if (p_node->hasContent()) {
auto nodeFolder = p_node->getAttachmentFolder(); auto nodeFolder = p_node->getAttachmentFolder();
if (nodeFolder.isEmpty()) { if (nodeFolder.isEmpty()) {
auto folderPath = fetchNodeAttachmentFolder(p_node->fetchAbsolutePath(), nodeFolder); auto folderPath = fetchNodeAttachmentFolder(p_node->fetchAbsolutePath(), nodeFolder);
@ -830,7 +781,7 @@ bool VXNotebookConfigMgr::isBuiltInFolder(const Node *p_node, const QString &p_n
QSharedPointer<Node> VXNotebookConfigMgr::copyFileAsChildOf(const QString &p_srcPath, Node *p_dest) QSharedPointer<Node> VXNotebookConfigMgr::copyFileAsChildOf(const QString &p_srcPath, Node *p_dest)
{ {
// Copy source file itself. // Copy source file itself.
auto destFilePath = PathUtils::concatenateFilePath(p_dest->fetchRelativePath(), auto destFilePath = PathUtils::concatenateFilePath(p_dest->fetchPath(),
PathUtils::fileName(p_srcPath)); PathUtils::fileName(p_srcPath));
destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath); destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath);
getBackend()->copyFile(p_srcPath, destFilePath); getBackend()->copyFile(p_srcPath, destFilePath);
@ -840,12 +791,12 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFileAsChildOf(const QString &p_src
// Create a file node. // Create a file node.
auto currentTime = QDateTime::currentDateTimeUtc(); auto currentTime = QDateTime::currentDateTimeUtc();
auto destNode = QSharedPointer<FileNode>::create(getNotebook()->getAndUpdateNextNodeId(), auto destNode = QSharedPointer<VXNode>::create(getNotebook()->getAndUpdateNextNodeId(),
PathUtils::fileName(destFilePath), PathUtils::fileName(destFilePath),
currentTime, currentTime,
currentTime, currentTime,
QString(),
QStringList(), QStringList(),
QString(),
getNotebook(), getNotebook(),
p_dest); p_dest);
addChildNode(p_dest, destNode); addChildNode(p_dest, destNode);
@ -856,7 +807,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFileAsChildOf(const QString &p_src
QSharedPointer<Node> VXNotebookConfigMgr::copyFolderAsChildOf(const QString &p_srcPath, Node *p_dest) QSharedPointer<Node> VXNotebookConfigMgr::copyFolderAsChildOf(const QString &p_srcPath, Node *p_dest)
{ {
auto destFolderPath = PathUtils::concatenateFilePath(p_dest->fetchRelativePath(), auto destFolderPath = PathUtils::concatenateFilePath(p_dest->fetchPath(),
PathUtils::fileName(p_srcPath)); PathUtils::fileName(p_srcPath));
destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath); destFolderPath = getBackend()->renameIfExistsCaseInsensitive(destFolderPath);
@ -865,10 +816,15 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFolderAsChildOf(const QString &p_s
// Create a folder node. // Create a folder node.
auto notebook = getNotebook(); auto notebook = getNotebook();
auto destNode = QSharedPointer<FolderNode>::create(PathUtils::fileName(destFolderPath), auto destNode = QSharedPointer<VXNode>::create(PathUtils::fileName(destFolderPath),
notebook, notebook,
p_dest); p_dest);
destNode->loadFolder(notebook->getAndUpdateNextNodeId(), QDateTime::currentDateTimeUtc(), QVector<QSharedPointer<Node>>()); auto currentTime = QDateTime::currentDateTimeUtc();
destNode->loadCompleteInfo(notebook->getAndUpdateNextNodeId(),
currentTime,
currentTime,
QStringList(),
QVector<QSharedPointer<Node>>());
writeNodeConfig(destNode.data()); writeNodeConfig(destNode.data());
@ -880,7 +836,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyFolderAsChildOf(const QString &p_s
void VXNotebookConfigMgr::inheritNodeFlags(const Node *p_node, Node *p_child) const void VXNotebookConfigMgr::inheritNodeFlags(const Node *p_node, Node *p_child) const
{ {
if (p_node->getFlags() & Node::Flag::ReadOnly) { if (p_node->isReadOnly()) {
markNodeReadOnly(p_child); markNodeReadOnly(p_child);
} }
} }

View File

@ -12,8 +12,6 @@ class QJsonObject;
namespace vnotex namespace vnotex
{ {
class FolderNode;
// Config manager for VNoteX's bundle notebook. // Config manager for VNoteX's bundle notebook.
class VXNotebookConfigMgr : public BundleNotebookConfigMgr class VXNotebookConfigMgr : public BundleNotebookConfigMgr
{ {
@ -41,16 +39,16 @@ namespace vnotex
void renameNode(Node *p_node, const QString &p_name) Q_DECL_OVERRIDE; void renameNode(Node *p_node, const QString &p_name) Q_DECL_OVERRIDE;
QSharedPointer<Node> newNode(Node *p_parent, QSharedPointer<Node> newNode(Node *p_parent,
Node::Type p_type, Node::Flags p_flags,
const QString &p_name) Q_DECL_OVERRIDE; const QString &p_name) Q_DECL_OVERRIDE;
QSharedPointer<Node> addAsNode(Node *p_parent, QSharedPointer<Node> addAsNode(Node *p_parent,
Node::Type p_type, Node::Flags p_flags,
const QString &p_name, const QString &p_name,
const NodeParameters &p_paras) Q_DECL_OVERRIDE; const NodeParameters &p_paras) Q_DECL_OVERRIDE;
QSharedPointer<Node> copyAsNode(Node *p_parent, QSharedPointer<Node> copyAsNode(Node *p_parent,
Node::Type p_type, Node::Flags p_flags,
const QString &p_path) Q_DECL_OVERRIDE; const QString &p_path) Q_DECL_OVERRIDE;
QSharedPointer<Node> loadNodeByPath(const QSharedPointer<Node> &p_root, QSharedPointer<Node> loadNodeByPath(const QSharedPointer<Node> &p_root,
@ -62,13 +60,11 @@ 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;
bool nodeExistsOnDisk(const Node *p_node) const Q_DECL_OVERRIDE; bool isBuiltInFile(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE;
QString readNode(const Node *p_node) const Q_DECL_OVERRIDE; bool isBuiltInFolder(const Node *p_node, const QString &p_name) const Q_DECL_OVERRIDE;
void writeNode(Node *p_node, const QString &p_content) Q_DECL_OVERRIDE; QString fetchNodeImageFolderPath(Node *p_node);
QString fetchNodeImageFolderPath(Node *p_node) Q_DECL_OVERRIDE;
QString fetchNodeAttachmentFolderPath(Node *p_node) Q_DECL_OVERRIDE; QString fetchNodeAttachmentFolderPath(Node *p_node) Q_DECL_OVERRIDE;
@ -105,7 +101,8 @@ namespace vnotex
NodeConfig(const QString &p_version, NodeConfig(const QString &p_version,
ID p_id, ID p_id,
const QDateTime &p_createdTimeUtc); const QDateTime &p_createdTimeUtc,
const QDateTime &p_modifiedTimeUtc);
QJsonObject toJson() const; QJsonObject toJson() const;
@ -114,6 +111,7 @@ namespace vnotex
QString m_version; QString m_version;
ID m_id = Node::InvalidId; ID m_id = Node::InvalidId;
QDateTime m_createdTimeUtc; QDateTime m_createdTimeUtc;
QDateTime m_modifiedTimeUtc;
QVector<NodeFileConfig> m_files; QVector<NodeFileConfig> m_files;
QVector<NodeFolderConfig> m_folders; QVector<NodeFolderConfig> m_folders;
@ -147,7 +145,7 @@ namespace vnotex
const QString &p_name, const QString &p_name,
Node *p_parent = nullptr) const; Node *p_parent = nullptr) const;
void loadFolderNode(FolderNode *p_node, const NodeConfig &p_config) const; void loadFolderNode(Node *p_node, const NodeConfig &p_config) const;
QSharedPointer<VXNotebookConfigMgr::NodeConfig> nodeToNodeConfig(const Node *p_node) const; QSharedPointer<VXNotebookConfigMgr::NodeConfig> nodeToNodeConfig(const Node *p_node) const;
@ -186,10 +184,6 @@ namespace vnotex
// Return the attachment folder path. // Return the attachment folder path.
QString fetchNodeAttachmentFolder(const QString &p_nodePath, QString &p_folderName); QString fetchNodeAttachmentFolder(const QString &p_nodePath, QString &p_folderName);
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;
void inheritNodeFlags(const Node *p_node, Node *p_child) const; void inheritNodeFlags(const Node *p_node, Node *p_child) const;
Info m_info; Info m_info;

View File

@ -15,7 +15,7 @@ QByteArray FileUtils::readFile(const QString &p_filePath)
QFile file(p_filePath); QFile file(p_filePath);
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
Exception::throwOne(Exception::Type::FailToReadFile, Exception::throwOne(Exception::Type::FailToReadFile,
QString("fail to read file: %1").arg(p_filePath)); QString("failed to read file: %1").arg(p_filePath));
} }
return file.readAll(); return file.readAll();
@ -26,7 +26,7 @@ QString FileUtils::readTextFile(const QString &p_filePath)
QFile file(p_filePath); QFile file(p_filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
Exception::throwOne(Exception::Type::FailToReadFile, Exception::throwOne(Exception::Type::FailToReadFile,
QString("fail to read file: %1").arg(p_filePath)); QString("failed to read file: %1").arg(p_filePath));
} }
QString text(file.readAll()); QString text(file.readAll());
@ -39,7 +39,7 @@ void FileUtils::writeFile(const QString &p_filePath, const QByteArray &p_data)
QFile file(p_filePath); QFile file(p_filePath);
if (!file.open(QIODevice::WriteOnly)) { if (!file.open(QIODevice::WriteOnly)) {
Exception::throwOne(Exception::Type::FailToWriteFile, Exception::throwOne(Exception::Type::FailToWriteFile,
QString("fail to write to file: %1").arg(p_filePath)); QString("failed to write to file: %1").arg(p_filePath));
} }
file.write(p_data); file.write(p_data);
@ -51,7 +51,7 @@ void FileUtils::writeFile(const QString &p_filePath, const QString &p_text)
QFile file(p_filePath); QFile file(p_filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
Exception::throwOne(Exception::Type::FailToWriteFile, Exception::throwOne(Exception::Type::FailToWriteFile,
QString("fail to write to file: %1").arg(p_filePath)); QString("failed to write to file: %1").arg(p_filePath));
} }
QTextStream stream(&file); QTextStream stream(&file);
@ -66,7 +66,7 @@ void FileUtils::renameFile(const QString &p_path, const QString &p_name)
QFile file(p_path); QFile file(p_path);
if (!file.exists() || !file.rename(newFilePath)) { if (!file.exists() || !file.rename(newFilePath)) {
Exception::throwOne(Exception::Type::FailToRenameFile, Exception::throwOne(Exception::Type::FailToRenameFile,
QString("fail to rename file: %1").arg(p_path)); QString("failed to rename file: %1").arg(p_path));
} }
} }
@ -104,7 +104,7 @@ void FileUtils::copyFile(const QString &p_filePath,
QDir dir; QDir dir;
if (!dir.mkpath(PathUtils::parentDirPath(p_destPath))) { if (!dir.mkpath(PathUtils::parentDirPath(p_destPath))) {
Exception::throwOne(Exception::Type::FailToCreateDir, Exception::throwOne(Exception::Type::FailToCreateDir,
QString("fail to create directory: %1").arg(PathUtils::parentDirPath(p_destPath))); QString("failed to create directory: %1").arg(PathUtils::parentDirPath(p_destPath)));
} }
bool failed = false; bool failed = false;
@ -121,7 +121,7 @@ void FileUtils::copyFile(const QString &p_filePath,
if (failed) { if (failed) {
Exception::throwOne(Exception::Type::FailToCopyFile, Exception::throwOne(Exception::Type::FailToCopyFile,
QString("fail to copy file: %1 %2").arg(p_filePath, p_destPath)); QString("failed to copy file: %1 %2").arg(p_filePath, p_destPath));
} }
} }
@ -144,7 +144,7 @@ void FileUtils::copyDir(const QString &p_dirPath,
QDir destDir(p_destPath); QDir destDir(p_destPath);
if (!destDir.mkpath(p_destPath)) { if (!destDir.mkpath(p_destPath)) {
Exception::throwOne(Exception::Type::FailToCreateDir, Exception::throwOne(Exception::Type::FailToCreateDir,
QString("fail to create directory: %1").arg(p_destPath)); QString("failed to create directory: %1").arg(p_destPath));
} }
// Copy directory contents recursively. // Copy directory contents recursively.
@ -167,7 +167,7 @@ void FileUtils::copyDir(const QString &p_dirPath,
if (p_move) { if (p_move) {
if (!destDir.rmdir(p_dirPath)) { if (!destDir.rmdir(p_dirPath)) {
Exception::throwOne(Exception::Type::FailToRemoveDir, Exception::throwOne(Exception::Type::FailToRemoveDir,
QString("fail to remove source directory after move: %1").arg(p_dirPath)); QString("failed to remove source directory after move: %1").arg(p_dirPath));
} }
} }
} }
@ -198,7 +198,7 @@ void FileUtils::removeFile(const QString &p_filePath)
QFile file(p_filePath); QFile file(p_filePath);
if (!file.remove()) { if (!file.remove()) {
Exception::throwOne(Exception::Type::FailToRemoveFile, Exception::throwOne(Exception::Type::FailToRemoveFile,
QString("fail to remove file: %1").arg(p_filePath)); QString("failed to remove file: %1").arg(p_filePath));
} }
} }
@ -211,7 +211,7 @@ bool FileUtils::removeDirIfEmpty(const QString &p_dirPath)
if (!dir.rmdir(p_dirPath)) { if (!dir.rmdir(p_dirPath)) {
Exception::throwOne(Exception::Type::FailToRemoveFile, Exception::throwOne(Exception::Type::FailToRemoveFile,
QString("fail to remove directory: %1").arg(p_dirPath)); QString("failed to remove directory: %1").arg(p_dirPath));
return false; return false;
} }
@ -223,7 +223,7 @@ void FileUtils::removeDir(const QString &p_dirPath)
QDir dir(p_dirPath); QDir dir(p_dirPath);
if (!dir.removeRecursively()) { if (!dir.removeRecursively()) {
Exception::throwOne(Exception::Type::FailToRemoveFile, Exception::throwOne(Exception::Type::FailToRemoveFile,
QString("fail to remove directory recursively: %1").arg(p_dirPath)); QString("failed to remove directory recursively: %1").arg(p_dirPath));
} }
} }

View File

@ -64,7 +64,7 @@ bool FolderPropertiesDialog::validateNameInput(QString &p_msg)
} }
if (name != m_node->getName() if (name != m_node->getName()
&& m_infoWidget->getParentNode()->hasChild(name, false)) { && m_infoWidget->getParentNode()->containsChild(name, false)) {
p_msg = tr("Name conflicts with existing folder."); p_msg = tr("Name conflicts with existing folder.");
return false; return false;
} }

View File

@ -86,7 +86,7 @@ bool ImportFolderDialog::importFolder()
auto nb = m_parentNode->getNotebook(); auto nb = m_parentNode->getNotebook();
m_newNode = nullptr; m_newNode = nullptr;
try { try {
m_newNode = nb->copyAsNode(m_parentNode, Node::Type::Folder, folder); m_newNode = nb->copyAsNode(m_parentNode, Node::Flag::Container, folder);
} catch (Exception &p_e) { } catch (Exception &p_e) {
auto msg = tr("Failed to add folder (%1) as node (%2).").arg(folder, p_e.what()); auto msg = tr("Failed to add folder (%1) as node (%2).").arg(folder, p_e.what());
qCritical() << msg; qCritical() << msg;

View File

@ -23,7 +23,7 @@ void ImportFolderUtils::importFolderContents(Notebook *p_notebook,
QSharedPointer<Node> node; QSharedPointer<Node> node;
try { try {
node = p_notebook->addAsNode(p_node, Node::Type::Folder, child.fileName(), NodeParameters()); node = p_notebook->addAsNode(p_node, Node::Flag::Container, child.fileName(), NodeParameters());
} catch (Exception &p_e) { } catch (Exception &p_e) {
Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to add folder (%1) as node (%2).").arg(child.fileName(), p_e.what())); Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to add folder (%1) as node (%2).").arg(child.fileName(), p_e.what()));
continue; continue;
@ -33,7 +33,7 @@ void ImportFolderUtils::importFolderContents(Notebook *p_notebook,
} else if (!p_notebook->isBuiltInFile(p_node, child.fileName())) { } else if (!p_notebook->isBuiltInFile(p_node, child.fileName())) {
if (p_suffixes.contains(child.suffix())) { if (p_suffixes.contains(child.suffix())) {
try { try {
p_notebook->addAsNode(p_node, Node::Type::File, child.fileName(), NodeParameters()); p_notebook->addAsNode(p_node, Node::Flag::Content, child.fileName(), NodeParameters());
} catch (Exception &p_e) { } catch (Exception &p_e) {
Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to add file (%1) as node (%2).").arg(child.filePath(), p_e.what())); Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to add file (%1) as node (%2).").arg(child.filePath(), p_e.what()));
} }
@ -69,7 +69,7 @@ void ImportFolderUtils::importFolderContentsByLegacyConfig(Notebook *p_notebook,
try { try {
NodeParameters paras; NodeParameters paras;
paras.m_createdTimeUtc = LegacyNotebookUtils::getCreatedTimeUtcOfFolder(rootDir.filePath(name)); paras.m_createdTimeUtc = LegacyNotebookUtils::getCreatedTimeUtcOfFolder(rootDir.filePath(name));
node = p_notebook->addAsNode(p_node, Node::Type::Folder, name, paras); node = p_notebook->addAsNode(p_node, Node::Flag::Container, name, paras);
} catch (Exception &p_e) { } catch (Exception &p_e) {
Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to add folder (%1) as node (%2).").arg(name, p_e.what())); Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to add folder (%1) as node (%2).").arg(name, p_e.what()));
return; return;
@ -97,7 +97,7 @@ void ImportFolderUtils::importFolderContentsByLegacyConfig(Notebook *p_notebook,
paras.m_modifiedTimeUtc = info.m_modifiedTimeUtc; paras.m_modifiedTimeUtc = info.m_modifiedTimeUtc;
paras.m_attachmentFolder = info.m_attachmentFolder; paras.m_attachmentFolder = info.m_attachmentFolder;
paras.m_tags = info.m_tags; paras.m_tags = info.m_tags;
node = p_notebook->addAsNode(p_node, Node::Type::File, info.m_name, paras); node = p_notebook->addAsNode(p_node, Node::Flag::Content, info.m_name, paras);
} catch (Exception &p_e) { } catch (Exception &p_e) {
Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to add file (%1) as node (%2).").arg(info.m_name, p_e.what())); Utils::appendMsg(p_errMsg, ImportFolderUtilsTranslate::tr("Failed to add file (%1) as node (%2).").arg(info.m_name, p_e.what()));
return; return;

View File

@ -33,7 +33,7 @@ void NewFolderDialog::setupUI(const Node *p_node)
void NewFolderDialog::setupNodeInfoWidget(const Node *p_node, QWidget *p_parent) void NewFolderDialog::setupNodeInfoWidget(const Node *p_node, QWidget *p_parent)
{ {
m_infoWidget = new NodeInfoWidget(p_node, Node::Type::Folder, p_parent); m_infoWidget = new NodeInfoWidget(p_node, Node::Flag::Container, p_parent);
connect(m_infoWidget, &NodeInfoWidget::inputEdited, connect(m_infoWidget, &NodeInfoWidget::inputEdited,
this, &NewFolderDialog::validateInputs); this, &NewFolderDialog::validateInputs);
} }
@ -59,7 +59,7 @@ bool NewFolderDialog::validateNameInput(QString &p_msg)
return false; return false;
} }
if (m_infoWidget->getParentNode()->hasChild(name, false)) { if (m_infoWidget->getParentNode()->containsChild(name, false)) {
p_msg = tr("Name conflicts with existing folder."); p_msg = tr("Name conflicts with existing folder.");
return false; return false;
} }
@ -81,7 +81,7 @@ bool NewFolderDialog::newFolder()
Notebook *notebook = const_cast<Notebook *>(m_infoWidget->getNotebook()); Notebook *notebook = const_cast<Notebook *>(m_infoWidget->getNotebook());
Node *parentNode = const_cast<Node *>(m_infoWidget->getParentNode()); Node *parentNode = const_cast<Node *>(m_infoWidget->getParentNode());
try { try {
m_newNode = notebook->newNode(parentNode, Node::Type::Folder, m_infoWidget->getName()); m_newNode = notebook->newNode(parentNode, Node::Flag::Container, m_infoWidget->getName());
} catch (Exception &p_e) { } catch (Exception &p_e) {
QString msg = tr("Failed to create folder under (%1) in (%2) (%3).").arg(parentNode->getName(), QString msg = tr("Failed to create folder under (%1) in (%2) (%3).").arg(parentNode->getName(),
notebook->getName(), notebook->getName(),

View File

@ -37,7 +37,7 @@ void NewNoteDialog::setupUI(const Node *p_node)
void NewNoteDialog::setupNodeInfoWidget(const Node *p_node, QWidget *p_parent) void NewNoteDialog::setupNodeInfoWidget(const Node *p_node, QWidget *p_parent)
{ {
m_infoWidget = new NodeInfoWidget(p_node, Node::Type::File, p_parent); m_infoWidget = new NodeInfoWidget(p_node, Node::Flag::Content, p_parent);
connect(m_infoWidget, &NodeInfoWidget::inputEdited, connect(m_infoWidget, &NodeInfoWidget::inputEdited,
this, &NewNoteDialog::validateInputs); this, &NewNoteDialog::validateInputs);
} }
@ -63,7 +63,7 @@ bool NewNoteDialog::validateNameInput(QString &p_msg)
return false; return false;
} }
if (m_infoWidget->getParentNode()->hasChild(name, false)) { if (m_infoWidget->getParentNode()->containsChild(name, false)) {
p_msg = tr("Name conflicts with existing note."); p_msg = tr("Name conflicts with existing note.");
return false; return false;
} }
@ -85,7 +85,7 @@ bool NewNoteDialog::newNote()
Notebook *notebook = const_cast<Notebook *>(m_infoWidget->getNotebook()); Notebook *notebook = const_cast<Notebook *>(m_infoWidget->getNotebook());
Node *parentNode = const_cast<Node *>(m_infoWidget->getParentNode()); Node *parentNode = const_cast<Node *>(m_infoWidget->getParentNode());
try { try {
m_newNode = notebook->newNode(parentNode, Node::Type::File, m_infoWidget->getName()); m_newNode = notebook->newNode(parentNode, Node::Flag::Content, m_infoWidget->getName());
} catch (Exception &p_e) { } catch (Exception &p_e) {
QString msg = tr("Failed to create note under (%1) in (%2) (%3).").arg(parentNode->getName(), QString msg = tr("Failed to create note under (%1) in (%2) (%3).").arg(parentNode->getName(),
notebook->getName(), notebook->getName(),

View File

@ -17,24 +17,24 @@ NodeInfoWidget::NodeInfoWidget(const Node *p_node, QWidget *p_parent)
: QWidget(p_parent), : QWidget(p_parent),
m_mode(Mode::Edit) m_mode(Mode::Edit)
{ {
setupUI(p_node->getParent(), p_node->getType()); setupUI(p_node->getParent(), p_node->getFlags());
setNode(p_node); setNode(p_node);
} }
NodeInfoWidget::NodeInfoWidget(const Node *p_parentNode, NodeInfoWidget::NodeInfoWidget(const Node *p_parentNode,
Node::Type p_typeToCreate, Node::Flags p_flags,
QWidget *p_parent) QWidget *p_parent)
: QWidget(p_parent), : QWidget(p_parent),
m_mode(Mode::Create) m_mode(Mode::Create)
{ {
setupUI(p_parentNode, p_typeToCreate); setupUI(p_parentNode, p_flags);
} }
void NodeInfoWidget::setupUI(const Node *p_parentNode, Node::Type p_newNodeType) void NodeInfoWidget::setupUI(const Node *p_parentNode, Node::Flags p_newNodeFlags)
{ {
const bool createMode = m_mode == Mode::Create; const bool createMode = m_mode == Mode::Create;
const bool isNote = p_newNodeType == Node::Type::File; const bool isNote = p_newNodeFlags & Node::Flag::Content;
m_mainLayout = WidgetUtils::createFormLayout(this); m_mainLayout = WidgetUtils::createFormLayout(this);

View File

@ -24,7 +24,7 @@ namespace vnotex
NodeInfoWidget(const Node *p_node, QWidget *p_parent = nullptr); NodeInfoWidget(const Node *p_node, QWidget *p_parent = nullptr);
NodeInfoWidget(const Node *p_parentNode, NodeInfoWidget(const Node *p_parentNode,
Node::Type p_typeToCreate, Node::Flags p_flags,
QWidget *p_parent = nullptr); QWidget *p_parent = nullptr);
QLineEdit *getNameLineEdit() const; QLineEdit *getNameLineEdit() const;
@ -39,7 +39,7 @@ namespace vnotex
void inputEdited(); void inputEdited();
private: private:
void setupUI(const Node *p_parentNode, Node::Type p_newNodeType); void setupUI(const Node *p_parentNode, Node::Flags p_newNodeFlags);
void setupFileTypeComboBox(QWidget *p_parent); void setupFileTypeComboBox(QWidget *p_parent);

View File

@ -45,7 +45,7 @@ void NodeLabelWithUpButton::setupUI()
void NodeLabelWithUpButton::updateLabelAndButton() void NodeLabelWithUpButton::updateLabelAndButton()
{ {
m_label->setText(m_node->fetchRelativePath()); m_label->setText(m_node->fetchPath());
m_upButton->setVisible(!m_readOnly && !m_node->isRoot()); m_upButton->setVisible(!m_readOnly && !m_node->isRoot());
} }

View File

@ -66,7 +66,7 @@ bool NotePropertiesDialog::validateNameInput(QString &p_msg)
} }
if (name != m_node->getName() if (name != m_node->getName()
&& m_infoWidget->getParentNode()->hasChild(name, false)) { && m_infoWidget->getParentNode()->containsChild(name, false)) {
p_msg = tr("Name conflicts with existing note."); p_msg = tr("Name conflicts with existing note.");
return false; return false;
} }

View File

@ -460,7 +460,7 @@ void MarkdownViewWindow::syncTextEditorFromBuffer(bool p_syncPositionFromReadMod
m_editor->setBuffer(buffer); m_editor->setBuffer(buffer);
if (buffer) { if (buffer) {
m_editor->setReadOnly(buffer->isReadOnly()); m_editor->setReadOnly(buffer->isReadOnly());
m_editor->setBasePath(buffer->getContentBasePath()); m_editor->setBasePath(buffer->getResourcePath());
m_editor->setText(buffer->getContent()); m_editor->setText(buffer->getContent());
m_editor->setModified(buffer->isModified()); m_editor->setModified(buffer->isModified());

View File

@ -183,10 +183,10 @@ Node *NotebookExplorer::currentExploredFolderNode() const
auto node = m_nodeExplorer->getCurrentNode(); auto node = m_nodeExplorer->getCurrentNode();
if (node) { if (node) {
if (node->getType() == Node::Type::File) { if (!node->isContainer()) {
node = node->getParent(); node = node->getParent();
} }
Q_ASSERT(node && node->getType() == Node::Type::Folder); Q_ASSERT(node && node->isContainer());
} else { } else {
node = m_currentNotebook->getRootNode().data(); node = m_currentNotebook->getRootNode().data();
} }
@ -241,7 +241,7 @@ void NotebookExplorer::importFile()
QString errMsg; QString errMsg;
for (const auto &file : files) { for (const auto &file : files) {
try { try {
m_currentNotebook->copyAsNode(node, Node::Type::File, file); m_currentNotebook->copyAsNode(node, Node::Flag::Content, file);
} catch (Exception &p_e) { } catch (Exception &p_e) {
errMsg += tr("Failed to add file (%1) as node (%2).\n").arg(file, p_e.what()); errMsg += tr("Failed to add file (%1) as node (%2).\n").arg(file, p_e.what());
} }

View File

@ -419,19 +419,15 @@ void NotebookNodeExplorer::fillTreeItem(QTreeWidgetItem *p_item, Node *p_node, b
QIcon NotebookNodeExplorer::getNodeItemIcon(const Node *p_node) const QIcon NotebookNodeExplorer::getNodeItemIcon(const Node *p_node) const
{ {
switch (p_node->getType()) { if (p_node->hasContent()) {
case Node::Type::File:
return s_fileNodeIcon; return s_fileNodeIcon;
} else {
case Node::Type::Folder:
{
if (p_node->getUse() == Node::Use::RecycleBin) { if (p_node->getUse() == Node::Use::RecycleBin) {
return s_recycleBinNodeIcon; return s_recycleBinNodeIcon;
} }
return s_folderNodeIcon; return s_folderNodeIcon;
} }
}
return QIcon(); return QIcon();
} }
@ -794,18 +790,12 @@ QAction *NotebookNodeExplorer::createAction(Action p_act, QObject *p_parent)
} }
int ret = QDialog::Rejected; int ret = QDialog::Rejected;
switch (node->getType()) { if (node->hasContent()) {
case Node::Type::File:
{
NotePropertiesDialog dialog(node, VNoteX::getInst().getMainWindow()); NotePropertiesDialog dialog(node, VNoteX::getInst().getMainWindow());
ret = dialog.exec(); ret = dialog.exec();
break; } else {
}
case Node::Type::Folder:
FolderPropertiesDialog dialog(node, VNoteX::getInst().getMainWindow()); FolderPropertiesDialog dialog(node, VNoteX::getInst().getMainWindow());
ret = dialog.exec(); ret = dialog.exec();
break;
} }
if (ret == QDialog::Accepted) { if (ret == QDialog::Accepted) {
@ -822,7 +812,7 @@ QAction *NotebookNodeExplorer::createAction(Action p_act, QObject *p_parent)
auto node = getCurrentNode(); auto node = getCurrentNode();
if (node) { if (node) {
locationPath = node->fetchAbsolutePath(); locationPath = node->fetchAbsolutePath();
if (node->getType() == Node::Type::File) { if (!node->isContainer()) {
locationPath = PathUtils::parentDirPath(locationPath); locationPath = PathUtils::parentDirPath(locationPath);
} }
} else if (m_notebook) { } else if (m_notebook) {
@ -940,7 +930,7 @@ void NotebookNodeExplorer::copySelectedNodes(bool p_move)
p_move ? ClipboardData::MoveNode : ClipboardData::CopyNode); p_move ? ClipboardData::MoveNode : ClipboardData::CopyNode);
for (auto node : nodes) { for (auto node : nodes) {
auto item = QSharedPointer<NodeClipboardDataItem>::create(node->getNotebook()->getId(), auto item = QSharedPointer<NodeClipboardDataItem>::create(node->getNotebook()->getId(),
node->fetchRelativePath()); node->fetchPath());
cdata.addItem(item); cdata.addItem(item);
} }
@ -1012,7 +1002,7 @@ static QSharedPointer<Node> getNodeFromClipboardDataItem(const NodeClipboardData
} }
auto node = notebook->loadNodeByPath(p_item->m_nodeRelativePath); auto node = notebook->loadNodeByPath(p_item->m_nodeRelativePath);
Q_ASSERT(!node || node->fetchRelativePath() == p_item->m_nodeRelativePath); Q_ASSERT(!node || node->fetchPath() == p_item->m_nodeRelativePath);
return node; return node;
} }
@ -1024,12 +1014,12 @@ void NotebookNodeExplorer::pasteNodesFromClipboard()
destNode = m_notebook->getRootNode().data(); destNode = m_notebook->getRootNode().data();
} else { } else {
// Current node may be a file node. // Current node may be a file node.
if (destNode->getType() == Node::Type::File) { if (!destNode->isContainer()) {
destNode = destNode->getParent(); destNode = destNode->getParent();
} }
} }
Q_ASSERT(destNode && destNode->getType() == Node::Type::Folder); Q_ASSERT(destNode && destNode->isContainer());
// Fetch source nodes from clipboard. // Fetch source nodes from clipboard.
auto cdata = tryFetchClipboardData(); auto cdata = tryFetchClipboardData();