refactor VFile and VOrphanFile

1. Make VFile a real abstract class;
2. Use VNoteFile for internal note file;
3. Use VOrphanFile for external orphan file;
This commit is contained in:
Le Tan 2017-09-21 19:33:37 +08:00
parent eb24360aa9
commit a64d01ea86
27 changed files with 625 additions and 552 deletions

View File

@ -1,30 +1,31 @@
#include <QtWidgets> #include <QtWidgets>
#include "vfileinfodialog.h" #include "vfileinfodialog.h"
#include "vdirectory.h" #include "vdirectory.h"
#include "vfile.h" #include "vnotefile.h"
#include "vconfigmanager.h" #include "vconfigmanager.h"
#include "utils/vutils.h" #include "utils/vutils.h"
extern VConfigManager *g_config; extern VConfigManager *g_config;
VFileInfoDialog::VFileInfoDialog(const QString &title, const QString &info, VFileInfoDialog::VFileInfoDialog(const QString &title,
VDirectory *directory, const VFile *file, const QString &info,
VDirectory *directory,
const VNoteFile *file,
QWidget *parent) QWidget *parent)
: QDialog(parent), title(title), info(info), : QDialog(parent), m_directory(directory), m_file(file)
m_directory(directory), m_file(file)
{ {
setupUI(); setupUI(title, info);
connect(nameEdit, &QLineEdit::textChanged, this, &VFileInfoDialog::handleInputChanged); connect(nameEdit, &QLineEdit::textChanged, this, &VFileInfoDialog::handleInputChanged);
handleInputChanged(); handleInputChanged();
} }
void VFileInfoDialog::setupUI() void VFileInfoDialog::setupUI(const QString &p_title, const QString &p_info)
{ {
QLabel *infoLabel = NULL; QLabel *infoLabel = NULL;
if (!info.isEmpty()) { if (!p_info.isEmpty()) {
infoLabel = new QLabel(info); infoLabel = new QLabel(p_info);
} }
// File name. // File name.
@ -78,7 +79,7 @@ void VFileInfoDialog::setupUI()
mainLayout->setSizeConstraint(QLayout::SetFixedSize); mainLayout->setSizeConstraint(QLayout::SetFixedSize);
setLayout(mainLayout); setLayout(mainLayout);
setWindowTitle(title); setWindowTitle(p_title);
} }
void VFileInfoDialog::handleInputChanged() void VFileInfoDialog::handleInputChanged()
@ -89,7 +90,7 @@ void VFileInfoDialog::handleInputChanged()
if (nameOk && name != m_file->getName()) { if (nameOk && name != m_file->getName()) {
// Check if the name conflicts with existing note name. // Check if the name conflicts with existing note name.
// Case-insensitive when creating note. // Case-insensitive when creating note.
const VFile *file = m_directory->findFile(name, false); const VNoteFile *file = m_directory->findFile(name, false);
if (file && file != m_file) { if (file && file != m_file) {
nameOk = false; nameOk = false;
showWarnLabel = true; showWarnLabel = true;

View File

@ -8,32 +8,33 @@ class QLineEdit;
class QDialogButtonBox; class QDialogButtonBox;
class QString; class QString;
class VDirectory; class VDirectory;
class VFile; class VNoteFile;
// File information dialog for internal note file.
class VFileInfoDialog : public QDialog class VFileInfoDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
VFileInfoDialog(const QString &title, const QString &info, VFileInfoDialog(const QString &title,
VDirectory *directory, const VFile *file, const QString &info,
VDirectory *directory,
const VNoteFile *file,
QWidget *parent = 0); QWidget *parent = 0);
QString getNameInput() const; QString getNameInput() const;
private slots: private slots:
void handleInputChanged(); void handleInputChanged();
private: private:
void setupUI(); void setupUI(const QString &p_title, const QString &p_info);
QLineEdit *nameEdit; QLineEdit *nameEdit;
QLabel *m_warnLabel; QLabel *m_warnLabel;
QDialogButtonBox *m_btnBox; QDialogButtonBox *m_btnBox;
QString title;
QString info;
VDirectory *m_directory; VDirectory *m_directory;
const VFile *m_file; const VNoteFile *m_file;
}; };
#endif // VFILEINFODIALOG_H #endif // VFILEINFODIALOG_H

View File

@ -74,7 +74,8 @@ SOURCES += main.cpp\
dialog/vorphanfileinfodialog.cpp \ dialog/vorphanfileinfodialog.cpp \
vtextblockdata.cpp \ vtextblockdata.cpp \
utils/vpreviewutils.cpp \ utils/vpreviewutils.cpp \
dialog/vconfirmdeletiondialog.cpp dialog/vconfirmdeletiondialog.cpp \
vnotefile.cpp
HEADERS += vmainwindow.h \ HEADERS += vmainwindow.h \
vdirectorytree.h \ vdirectorytree.h \
@ -136,7 +137,8 @@ HEADERS += vmainwindow.h \
dialog/vorphanfileinfodialog.h \ dialog/vorphanfileinfodialog.h \
vtextblockdata.h \ vtextblockdata.h \
utils/vpreviewutils.h \ utils/vpreviewutils.h \
dialog/vconfirmdeletiondialog.h dialog/vconfirmdeletiondialog.h \
vnotefile.h
RESOURCES += \ RESOURCES += \
vnote.qrc \ vnote.qrc \

View File

@ -820,6 +820,19 @@ bool VUtils::deleteFile(const VNotebook *p_notebook,
} }
} }
bool VUtils::deleteFile(const QString &p_path,
bool p_skipRecycleBin)
{
if (p_skipRecycleBin) {
QFile file(p_path);
return file.remove();
} else {
// TODO: Move it to the recycle bin folder.
QFile file(p_path);
return file.remove();
}
}
QVector<VElementRegion> VUtils::fetchImageRegionsUsingParser(const QString &p_content) QVector<VElementRegion> VUtils::fetchImageRegionsUsingParser(const QString &p_content)
{ {
Q_ASSERT(!p_content.isEmpty()); Q_ASSERT(!p_content.isEmpty());

View File

@ -146,6 +146,12 @@ public:
const QString &p_path, const QString &p_path,
bool p_skipRecycleBin = false); bool p_skipRecycleBin = false);
// Delete file specified by @p_path.
// Will just move the file to the recycle bin of VNote if
// @p_skipRecycleBin is false.
static bool deleteFile(const QString &p_path,
bool p_skipRecycleBin = false);
// Regular expression for image link. // Regular expression for image link.
// ![image title]( http://github.com/tamlok/vnote.jpg "alt \" text" ) // ![image title]( http://github.com/tamlok/vnote.jpg "alt \" text" )
// Captured texts (need to be trimmed): // Captured texts (need to be trimmed):

View File

@ -7,9 +7,9 @@
// Container: a composite file containing multiple files; // Container: a composite file containing multiple files;
enum class DocType { Html = 0, Markdown, List, Container, Invalid }; enum class DocType { Html = 0, Markdown, List, Container, Invalid };
// Normal: note file managed by VNote; // Note: note file managed by VNote;
// Orphan: external file; // Orphan: external file;
enum class FileType { Normal, Orphan }; enum class FileType { Note, Orphan };
enum class ClipboardOpType { Invalid, CopyFile, CopyDir }; enum class ClipboardOpType { Invalid, CopyFile, CopyDir };
enum class OpenFileMode {Read = 0, Edit}; enum class OpenFileMode {Read = 0, Edit};

View File

@ -4,7 +4,7 @@
#include <QJsonArray> #include <QJsonArray>
#include <QDebug> #include <QDebug>
#include "vconfigmanager.h" #include "vconfigmanager.h"
#include "vfile.h" #include "vnotefile.h"
#include "utils/vutils.h" #include "utils/vutils.h"
extern VConfigManager *g_config; extern VConfigManager *g_config;
@ -53,9 +53,9 @@ bool VDirectory::open()
QJsonArray fileJson = configJson[DirConfig::c_files].toArray(); QJsonArray fileJson = configJson[DirConfig::c_files].toArray();
for (int i = 0; i < fileJson.size(); ++i) { for (int i = 0; i < fileJson.size(); ++i) {
QJsonObject fileItem = fileJson[i].toObject(); QJsonObject fileItem = fileJson[i].toObject();
VFile *file = VFile::fromJson(fileItem, VNoteFile *file = VNoteFile::fromJson(this,
this, fileItem,
FileType::Normal, FileType::Note,
true); true);
m_files.append(file); m_files.append(file);
} }
@ -78,7 +78,7 @@ void VDirectory::close()
m_subDirs.clear(); m_subDirs.clear();
for (int i = 0; i < m_files.size(); ++i) { for (int i = 0; i < m_files.size(); ++i) {
VFile *file = m_files[i]; VNoteFile *file = m_files[i];
file->close(); file->close();
delete file; delete file;
} }
@ -237,7 +237,7 @@ VDirectory *VDirectory::findSubDirectory(const QString &p_name, bool p_caseSensi
return NULL; return NULL;
} }
VFile *VDirectory::findFile(const QString &p_name, bool p_caseSensitive) VNoteFile *VDirectory::findFile(const QString &p_name, bool p_caseSensitive)
{ {
if (!open()) { if (!open()) {
return NULL; return NULL;
@ -271,7 +271,7 @@ bool VDirectory::containsFile(const VFile *p_file) const
return false; return false;
} }
VFile *VDirectory::createFile(const QString &p_name) VNoteFile *VDirectory::createFile(const QString &p_name)
{ {
Q_ASSERT(!p_name.isEmpty()); Q_ASSERT(!p_name.isEmpty());
if (!open()) { if (!open()) {
@ -288,9 +288,9 @@ VFile *VDirectory::createFile(const QString &p_name)
file.close(); file.close();
QDateTime dateTime = QDateTime::currentDateTimeUtc(); QDateTime dateTime = QDateTime::currentDateTimeUtc();
VFile *ret = new VFile(this, VNoteFile *ret = new VNoteFile(this,
p_name, p_name,
FileType::Normal, FileType::Note,
true, true,
dateTime, dateTime,
dateTime); dateTime);
@ -307,7 +307,7 @@ VFile *VDirectory::createFile(const QString &p_name)
return ret; return ret;
} }
bool VDirectory::addFile(VFile *p_file, int p_index) bool VDirectory::addFile(VNoteFile *p_file, int p_index)
{ {
if (!open()) { if (!open()) {
return false; return false;
@ -336,16 +336,16 @@ bool VDirectory::addFile(VFile *p_file, int p_index)
return true; return true;
} }
VFile *VDirectory::addFile(const QString &p_name, int p_index) VNoteFile *VDirectory::addFile(const QString &p_name, int p_index)
{ {
if (!open() || p_name.isEmpty()) { if (!open() || p_name.isEmpty()) {
return NULL; return NULL;
} }
QDateTime dateTime = QDateTime::currentDateTimeUtc(); QDateTime dateTime = QDateTime::currentDateTimeUtc();
VFile *file = new VFile(this, VNoteFile *file = new VNoteFile(this,
p_name, p_name,
FileType::Normal, FileType::Note,
true, true,
dateTime, dateTime,
dateTime); dateTime);
@ -450,7 +450,7 @@ bool VDirectory::removeSubDirectory(VDirectory *p_dir)
return true; return true;
} }
bool VDirectory::removeFile(VFile *p_file) bool VDirectory::removeFile(VNoteFile *p_file)
{ {
V_ASSERT(m_opened); V_ASSERT(m_opened);
V_ASSERT(p_file); V_ASSERT(p_file);
@ -468,7 +468,7 @@ bool VDirectory::removeFile(VFile *p_file)
return true; return true;
} }
void VDirectory::deleteFile(VFile *p_file) void VDirectory::deleteFile(VNoteFile *p_file)
{ {
removeFile(p_file); removeFile(p_file);
@ -476,7 +476,7 @@ void VDirectory::deleteFile(VFile *p_file)
V_ASSERT(!p_file->isOpened()); V_ASSERT(!p_file->isOpened());
V_ASSERT(p_file->parent()); V_ASSERT(p_file->parent());
p_file->deleteDiskFile(); p_file->deleteFile();
delete p_file; delete p_file;
} }
@ -512,8 +512,8 @@ bool VDirectory::rename(const QString &p_name)
return true; return true;
} }
VFile *VDirectory::copyFile(VDirectory *p_destDir, const QString &p_destName, VNoteFile *VDirectory::copyFile(VDirectory *p_destDir, const QString &p_destName,
VFile *p_srcFile, bool p_cut) VNoteFile *p_srcFile, bool p_cut)
{ {
QString srcPath = QDir::cleanPath(p_srcFile->fetchPath()); QString srcPath = QDir::cleanPath(p_srcFile->fetchPath());
QString destPath = QDir::cleanPath(QDir(p_destDir->fetchPath()).filePath(p_destName)); QString destPath = QDir::cleanPath(QDir(p_destDir->fetchPath()).filePath(p_destName));
@ -536,9 +536,9 @@ VFile *VDirectory::copyFile(VDirectory *p_destDir, const QString &p_destName,
return NULL; return NULL;
} }
// Handle VDirectory and VFile // Handle VDirectory and VNoteFile
int index = -1; int index = -1;
VFile *destFile = NULL; VNoteFile *destFile = NULL;
if (p_cut) { if (p_cut) {
// Remove the file from config // Remove the file from config
srcDir->removeFile(p_srcFile); srcDir->removeFile(p_srcFile);
@ -710,7 +710,7 @@ void VDirectory::reorderFiles(int p_first, int p_last, int p_destStart)
} }
} }
VFile *VDirectory::tryLoadFile(QStringList &p_filePath) VNoteFile *VDirectory::tryLoadFile(QStringList &p_filePath)
{ {
qDebug() << "directory" << m_name << "tryLoadFile()" << p_filePath.join("/"); qDebug() << "directory" << m_name << "tryLoadFile()" << p_filePath.join("/");
if (p_filePath.isEmpty()) { if (p_filePath.isEmpty()) {
@ -722,7 +722,7 @@ VFile *VDirectory::tryLoadFile(QStringList &p_filePath)
return NULL; return NULL;
} }
VFile *file = NULL; VNoteFile *file = NULL;
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
bool caseSensitive = false; bool caseSensitive = false;

View File

@ -10,6 +10,7 @@
#include "vnotebook.h" #include "vnotebook.h"
class VFile; class VFile;
class VNoteFile;
class VDirectory : public QObject class VDirectory : public QObject
{ {
@ -27,20 +28,20 @@ public:
// Returns the VDirectory with the name @p_name directly in this directory. // Returns the VDirectory with the name @p_name directly in this directory.
VDirectory *findSubDirectory(const QString &p_name, bool p_caseSensitive); VDirectory *findSubDirectory(const QString &p_name, bool p_caseSensitive);
// Returns the VFile with the name @p_name directly in this directory. // Returns the VNoteFile with the name @p_name directly in this directory.
VFile *findFile(const QString &p_name, bool p_caseSensitive); VNoteFile *findFile(const QString &p_name, bool p_caseSensitive);
// If current dir or its sub-dir contains @p_file. // If current dir or its sub-dir contains @p_file.
bool containsFile(const VFile *p_file) const; bool containsFile(const VFile *p_file) const;
VFile *createFile(const QString &p_name); VNoteFile *createFile(const QString &p_name);
// Remove and delete subdirectory @p_subDir. // Remove and delete subdirectory @p_subDir.
void deleteSubDirectory(VDirectory *p_subDir, bool p_skipRecycleBin = false); void deleteSubDirectory(VDirectory *p_subDir, bool p_skipRecycleBin = false);
// Remove the file in the config and m_files without deleting it in the disk. // Remove the file in the config and m_files without deleting it in the disk.
// It won't change the parent of @p_file to enable it find its path. // It won't change the parent of @p_file to enable it find its path.
bool removeFile(VFile *p_file); bool removeFile(VNoteFile *p_file);
// Remove the directory in the config and m_subDirs without deleting it in the disk. // Remove the directory in the config and m_subDirs without deleting it in the disk.
// It won't change the parent of @p_dir to enable it find its path. // It won't change the parent of @p_dir to enable it find its path.
@ -48,20 +49,20 @@ public:
// Add the file in the config and m_files. If @p_index is -1, add it at the end. // Add the file in the config and m_files. If @p_index is -1, add it at the end.
// @p_name: the file name of the file to add. // @p_name: the file name of the file to add.
// Return the VFile if succeed. // Return the VNoteFile if succeed.
VFile *addFile(const QString &p_name, int p_index); VNoteFile *addFile(const QString &p_name, int p_index);
// Delete @p_file both from disk and config, as well as its local images. // Delete @p_file both from disk and config, as well as its local images.
void deleteFile(VFile *p_file); void deleteFile(VNoteFile *p_file);
// Rename current directory to @p_name. // Rename current directory to @p_name.
bool rename(const QString &p_name); bool rename(const QString &p_name);
// Copy @p_srcFile to @p_destDir, setting new name to @p_destName. // Copy @p_srcFile to @p_destDir, setting new name to @p_destName.
// @p_cut: copy or cut. // @p_cut: copy or cut.
// Returns the dest VFile. // Returns the dest VNoteFile.
static VFile *copyFile(VDirectory *p_destDir, const QString &p_destName, static VNoteFile *copyFile(VDirectory *p_destDir, const QString &p_destName,
VFile *p_srcFile, bool p_cut); VNoteFile *p_srcFile, bool p_cut);
static VDirectory *copyDirectory(VDirectory *p_destDir, const QString &p_destName, static VDirectory *copyDirectory(VDirectory *p_destDir, const QString &p_destName,
VDirectory *p_srcDir, bool p_cut); VDirectory *p_srcDir, bool p_cut);
@ -74,7 +75,7 @@ public:
const VDirectory *getParentDirectory() const; const VDirectory *getParentDirectory() const;
VNotebook *getNotebook(); VNotebook *getNotebook();
const VNotebook *getNotebook() const; const VNotebook *getNotebook() const;
const QVector<VFile *> &getFiles() const; const QVector<VNoteFile *> &getFiles() const;
QString fetchPath() const; QString fetchPath() const;
QString fetchBasePath() const; QString fetchBasePath() const;
QString fetchRelativePath() const; QString fetchRelativePath() const;
@ -97,7 +98,7 @@ public:
bool writeToConfig() const; bool writeToConfig() const;
// Try to load file given relative path @p_filePath. // Try to load file given relative path @p_filePath.
VFile *tryLoadFile(QStringList &p_filePath); VNoteFile *tryLoadFile(QStringList &p_filePath);
QDateTime getCreatedTimeUtc() const; QDateTime getCreatedTimeUtc() const;
@ -115,7 +116,7 @@ private:
void addNotebookConfig(QJsonObject &p_json) const; void addNotebookConfig(QJsonObject &p_json) const;
// Add the file in the config and m_files. If @p_index is -1, add it at the end. // Add the file in the config and m_files. If @p_index is -1, add it at the end.
bool addFile(VFile *p_file, int p_index); bool addFile(VNoteFile *p_file, int p_index);
// Add the directory in the config and m_subDirs. If @p_index is -1, add it at the end. // Add the directory in the config and m_subDirs. If @p_index is -1, add it at the end.
// Return the VDirectory if succeed. // Return the VDirectory if succeed.
@ -134,7 +135,7 @@ private:
QVector<VDirectory *> m_subDirs; QVector<VDirectory *> m_subDirs;
// Owner of the files // Owner of the files
QVector<VFile *> m_files; QVector<VNoteFile *> m_files;
// Whether the directory has been opened. // Whether the directory has been opened.
bool m_opened; bool m_opened;
@ -177,7 +178,7 @@ inline const VDirectory *VDirectory::getParentDirectory() const
return (const VDirectory *)this->parent(); return (const VDirectory *)this->parent();
} }
inline const QVector<VFile *> &VDirectory::getFiles() const inline const QVector<VNoteFile *> &VDirectory::getFiles() const
{ {
return m_files; return m_files;
} }

View File

@ -11,7 +11,7 @@
#include <QFontMetrics> #include <QFontMetrics>
#include "vconstants.h" #include "vconstants.h"
#include "vtoc.h" #include "vtoc.h"
#include "vfile.h" #include "vnotefile.h"
class VEditOperations; class VEditOperations;
class QLabel; class QLabel;

View File

@ -125,8 +125,9 @@ void VEditWindow::initTabActions()
VEditTab *editor = getTab(tab); VEditTab *editor = getTab(tab);
QPointer<VFile> file = editor->getFile(); QPointer<VFile> file = editor->getFile();
Q_ASSERT(file); Q_ASSERT(file);
if (file->getType() == FileType::Normal) { if (file->getType() == FileType::Note) {
g_vnote->getMainWindow()->getFileList()->fileInfo(file); VNoteFile *tmpFile = dynamic_cast<VNoteFile *>((VFile *)file);
g_vnote->getMainWindow()->getFileList()->fileInfo(tmpFile);
} else if (file->getType() == FileType::Orphan) { } else if (file->getType() == FileType::Orphan) {
g_vnote->getMainWindow()->editOrphanFileInfo(file); g_vnote->getMainWindow()->editOrphanFileInfo(file);
} }
@ -554,7 +555,7 @@ void VEditWindow::tabbarContextMenuRequested(QPoint p_pos)
VEditTab *editor = getTab(tab); VEditTab *editor = getTab(tab);
VFile *file = editor->getFile(); VFile *file = editor->getFile();
if (file->getType() == FileType::Normal) { if (file->getType() == FileType::Note) {
// Locate to folder. // Locate to folder.
m_locateAct->setData(tab); m_locateAct->setData(tab);
menu.addAction(m_locateAct); menu.addAction(m_locateAct);
@ -565,7 +566,7 @@ void VEditWindow::tabbarContextMenuRequested(QPoint p_pos)
m_noteInfoAct->setData(tab); m_noteInfoAct->setData(tab);
menu.addAction(m_noteInfoAct); menu.addAction(m_noteInfoAct);
} else if (file->getType() == FileType::Orphan } else if (file->getType() == FileType::Orphan
&& !dynamic_cast<VOrphanFile *>(file)->isSystemFile()) { && !(dynamic_cast<VOrphanFile *>(file)->isSystemFile())) {
m_openLocationAct->setData(tab); m_openLocationAct->setData(tab);
menu.addAction(m_openLocationAct); menu.addAction(m_openLocationAct);
@ -761,7 +762,7 @@ void VEditWindow::handleLocateAct()
int tab = m_locateAct->data().toInt(); int tab = m_locateAct->data().toInt();
VEditTab *editor = getTab(tab); VEditTab *editor = getTab(tab);
QPointer<VFile> file = editor->getFile(); QPointer<VFile> file = editor->getFile();
if (file->getType() == FileType::Normal) { if (file->getType() == FileType::Note) {
vnote->getMainWindow()->locateFile(file); vnote->getMainWindow()->locateFile(file);
} }
} }

View File

@ -10,11 +10,11 @@
#include "vedittab.h" #include "vedittab.h"
#include "vtoc.h" #include "vtoc.h"
#include "vconstants.h" #include "vconstants.h"
#include "vnotefile.h"
class VNote; class VNote;
class QPushButton; class QPushButton;
class QActionGroup; class QActionGroup;
class VFile;
class VEditArea; class VEditArea;
class VEditWindow : public QTabWidget class VEditWindow : public QTabWidget
@ -184,8 +184,14 @@ inline QString VEditWindow::generateTooltip(const VFile *p_file) const
if (!p_file) { if (!p_file) {
return ""; return "";
} }
// [Notebook]path // [Notebook]path
return QString("[%1] %2").arg(p_file->getNotebookName()).arg(p_file->fetchPath()); if (p_file->getType() == FileType::Note) {
const VNoteFile *tmpFile = dynamic_cast<const VNoteFile *>(p_file);
return QString("[%1] %2").arg(tmpFile->getNotebookName()).arg(tmpFile->fetchPath());
} else {
return QString("%1").arg(p_file->fetchPath());
}
} }
inline QString VEditWindow::generateTabText(int p_index, const QString &p_name, inline QString VEditWindow::generateTabText(int p_index, const QString &p_name,

View File

@ -30,17 +30,18 @@ VFile::~VFile()
bool VFile::open() bool VFile::open()
{ {
Q_ASSERT(!m_name.isEmpty());
if (m_opened) { if (m_opened) {
return true; return true;
} }
Q_ASSERT(!m_name.isEmpty());
Q_ASSERT(m_content.isEmpty()); Q_ASSERT(m_content.isEmpty());
QString path = fetchPath();
qDebug() << "path" << path; QString filePath = fetchPath();
m_content = VUtils::readFileFromDisk(path); Q_ASSERT(QFileInfo::exists(filePath));
m_content = VUtils::readFileFromDisk(filePath);
m_modified = false; m_modified = false;
m_opened = true; m_opened = true;
qDebug() << "file" << m_name << "opened";
return true; return true;
} }
@ -49,164 +50,24 @@ void VFile::close()
if (!m_opened) { if (!m_opened) {
return; return;
} }
m_content.clear(); m_content.clear();
m_modified = false;
m_opened = false; m_opened = false;
} }
void VFile::deleteDiskFile()
{
V_ASSERT(parent());
// Delete local images if it is Markdown.
if (m_docType == DocType::Markdown) {
deleteLocalImages();
}
// Delete the file
QString filePath = fetchPath();
if (VUtils::deleteFile(getNotebook(), filePath, false)) {
qDebug() << "deleted" << filePath;
} else {
qWarning() << "fail to delete" << filePath;
}
}
bool VFile::save() bool VFile::save()
{ {
Q_ASSERT(m_opened); Q_ASSERT(m_opened);
bool ret = VUtils::writeFileToDisk(fetchPath(), m_content); bool ret = VUtils::writeFileToDisk(fetchPath(), m_content);
if (ret) { if (ret) {
m_modifiedTimeUtc = QDateTime::currentDateTimeUtc(); m_modifiedTimeUtc = QDateTime::currentDateTimeUtc();
m_modified = false;
} }
return ret; return ret;
} }
void VFile::setModified(bool p_modified)
{
m_modified = p_modified;
}
void VFile::deleteLocalImages()
{
V_ASSERT(m_docType == DocType::Markdown);
QVector<ImageLink> images = VUtils::fetchImagesFromMarkdownFile(this,
ImageLink::LocalRelativeInternal);
int deleted = 0;
for (int i = 0; i < images.size(); ++i) {
if (VUtils::deleteFile(getNotebook(), images[i].m_path, false)) {
++deleted;
}
}
qDebug() << "delete" << deleted << "images for" << fetchPath();
}
void VFile::setName(const QString &p_name)
{
m_name = p_name;
DocType newType = VUtils::docTypeFromName(p_name);
if (newType != m_docType) {
qWarning() << "setName() change the DocType. A convertion should be followed";
}
}
const QString &VFile::getName() const
{
return m_name;
}
VDirectory *VFile::getDirectory()
{
Q_ASSERT(parent());
return (VDirectory *)parent();
}
const VDirectory *VFile::getDirectory() const
{
Q_ASSERT(parent());
return (const VDirectory *)parent();
}
DocType VFile::getDocType() const
{
return m_docType;
}
const QString &VFile::getContent() const
{
return m_content;
}
QString VFile::getNotebookName() const
{
return getDirectory()->getNotebookName();
}
const VNotebook *VFile::getNotebook() const
{
return getDirectory()->getNotebook();
}
VNotebook *VFile::getNotebook()
{
return getDirectory()->getNotebook();
}
QString VFile::fetchPath() const
{
QString dirPath = getDirectory()->fetchPath();
return QDir(dirPath).filePath(m_name);
}
QString VFile::fetchRelativePath() const
{
QString dirRelativePath = getDirectory()->fetchRelativePath();
return QDir(dirRelativePath).filePath(m_name);
}
QString VFile::fetchBasePath() const
{
return getDirectory()->fetchPath();
}
QString VFile::fetchImagePath() const
{
return QDir(fetchBasePath()).filePath(getNotebook()->getImageFolder());
}
void VFile::setContent(const QString &p_content)
{
m_content = p_content;
}
bool VFile::isModified() const
{
return m_modified;
}
bool VFile::isModifiable() const
{
return m_modifiable;
}
bool VFile::isOpened() const
{
return m_opened;
}
FileType VFile::getType() const
{
return m_type;
}
bool VFile::isInternalImageFolder(const QString &p_path) const
{
return VUtils::equalPath(VUtils::basePathFromPath(p_path),
getDirectory()->fetchPath());
}
QUrl VFile::getBaseUrl() const QUrl VFile::getBaseUrl() const
{ {
// Need to judge the path: Url, local file, resource file. // Need to judge the path: Url, local file, resource file.
@ -229,71 +90,15 @@ QUrl VFile::getBaseUrl() const
return baseUrl; return baseUrl;
} }
bool VFile::rename(const QString &p_name) bool VFile::isInternalImageFolder(const QString &p_path) const
{ {
if (m_name == p_name) { return VUtils::equalPath(VUtils::basePathFromPath(p_path),
return true; fetchBasePath())
} || VUtils::equalPath(p_path, fetchImageFolderPath());
QString oldName = m_name;
VDirectory *dir = getDirectory();
V_ASSERT(dir);
// Rename it in disk.
QDir diskDir(dir->fetchPath());
if (!diskDir.rename(m_name, p_name)) {
qWarning() << "fail to rename note" << m_name << "to" << p_name << "in disk";
return false;
}
m_name = p_name;
// Update parent directory's config file.
if (!dir->writeToConfig()) {
m_name = oldName;
diskDir.rename(p_name, m_name);
return false;
}
// Can't not change doc type.
Q_ASSERT(m_docType == VUtils::docTypeFromName(m_name));
qDebug() << "note renamed from" << oldName << "to" << m_name;
return true;
} }
bool VFile::isRelativeImageFolder() const void VFile::setModified(bool p_modified)
{ {
return true; m_modified = p_modified;
} }
QString VFile::getImageFolderInLink() const
{
return getNotebook()->getImageFolder();
}
VFile *VFile::fromJson(const QJsonObject &p_json,
QObject *p_parent,
FileType p_type,
bool p_modifiable)
{
return new VFile(p_parent,
p_json[DirConfig::c_name].toString(),
p_type,
p_modifiable,
QDateTime::fromString(p_json[DirConfig::c_createdTime].toString(),
Qt::ISODate),
QDateTime::fromString(p_json[DirConfig::c_modifiedTime].toString(),
Qt::ISODate));
}
QJsonObject VFile::toConfigJson() const
{
QJsonObject item;
item[DirConfig::c_name] = m_name;
item[DirConfig::c_createdTime] = m_createdTimeUtc.toString(Qt::ISODate);
item[DirConfig::c_modifiedTime] = m_modifiedTimeUtc.toString(Qt::ISODate);
return item;
}

View File

@ -5,11 +5,9 @@
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>
#include <QDateTime> #include <QDateTime>
#include "vdirectory.h"
#include "vconstants.h" #include "vconstants.h"
class VNotebook; // VFile is an abstract class representing a file in VNote.
class VFile : public QObject class VFile : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -22,57 +20,56 @@ public:
QDateTime p_modifiedTimeUtc); QDateTime p_modifiedTimeUtc);
virtual ~VFile(); virtual ~VFile();
// Open the file to load content into m_content.
// Init m_opened, m_modified, and m_content.
virtual bool open(); virtual bool open();
// Close the file.
// Clear m_modified, m_content, m_opened.
virtual void close(); virtual void close();
// Save m_content to the file.
virtual bool save(); virtual bool save();
const QString &getName() const; const QString &getName() const;
virtual void setName(const QString &p_name);
virtual VDirectory *getDirectory();
virtual const VDirectory *getDirectory() const;
DocType getDocType() const;
const QString &getContent() const;
virtual void setContent(const QString &p_content);
virtual const VNotebook *getNotebook() const;
virtual VNotebook *getNotebook();
virtual QString getNotebookName() const;
virtual QString fetchPath() const;
virtual QString fetchRelativePath() const;
virtual QString fetchBasePath() const;
// The path of the image folder. DocType getDocType() const;
virtual QString fetchImagePath() const;
bool isModified() const; bool isModified() const;
bool isModifiable() const; bool isModifiable() const;
bool isOpened() const; bool isOpened() const;
FileType getType() const; FileType getType() const;
const QString &getContent() const;
void setContent(const QString &p_content);
// Get the absolute full path of the file.
virtual QString fetchPath() const = 0;
// Get the absolute full path of the directory containing the file.
virtual QString fetchBasePath() const = 0;
// The path of the image folder to store images of this file.
virtual QString fetchImageFolderPath() const = 0;
// Return the base URL for this file when loaded in VWebView. // Return the base URL for this file when loaded in VWebView.
QUrl getBaseUrl() const; QUrl getBaseUrl() const;
// Whether the directory @p_path is an internal image folder of this file. // Whether the directory @p_path is an internal image folder of this file.
// It is true only when the folder is in the same directory as the parent // It is true only when the folder is in the same directory as the parent
// directory of this file. // directory of this file or equals to fetchImageFolderPath().
virtual bool isInternalImageFolder(const QString &p_path) const; bool isInternalImageFolder(const QString &p_path) const;
// Rename the file. // Whether use a relative image folder.
virtual bool rename(const QString &p_name); virtual bool useRelativeImageFolder() const = 0;
// Whether the image folder is a relative path.
virtual bool isRelativeImageFolder() const;
// Return the image folder part in an image link. // Return the image folder part in an image link.
virtual QString getImageFolderInLink() const; virtual QString getImageFolderInLink() const = 0;
// Create a VFile from @p_json Json object.
static VFile *fromJson(const QJsonObject &p_json,
QObject *p_parent,
FileType p_type,
bool p_modifiable);
// Create a Json object from current instance.
QJsonObject toConfigJson() const;
QDateTime getCreatedTimeUtc() const; QDateTime getCreatedTimeUtc() const;
@ -82,19 +79,13 @@ public slots:
void setModified(bool p_modified); void setModified(bool p_modified);
protected: protected:
// Delete the file and corresponding images
void deleteDiskFile();
// Delete local images of DocType::Markdown.
void deleteLocalImages();
// Name of this file. // Name of this file.
QString m_name; QString m_name;
// Whether this file has been opened. // Whether this file has been opened (content loaded).
bool m_opened; bool m_opened;
// File has been modified in editor // m_content is different from that in the disk.
bool m_modified; bool m_modified;
// DocType of this file: Html, Markdown. // DocType of this file: Html, Markdown.
@ -103,6 +94,7 @@ protected:
// Content of this file. // Content of this file.
QString m_content; QString m_content;
// FileType of this file: Note, Orphan.
FileType m_type; FileType m_type;
// Whether this file is modifiable. // Whether this file is modifiable.
@ -113,10 +105,50 @@ protected:
// UTC time of last modification to this file in VNote. // UTC time of last modification to this file in VNote.
QDateTime m_modifiedTimeUtc; QDateTime m_modifiedTimeUtc;
friend class VDirectory;
}; };
inline const QString &VFile::getName() const
{
return m_name;
}
inline DocType VFile::getDocType() const
{
return m_docType;
}
inline bool VFile::isModified() const
{
return m_modified;
}
inline bool VFile::isModifiable() const
{
return m_modifiable;
}
inline bool VFile::isOpened() const
{
return m_opened;
}
inline FileType VFile::getType() const
{
return m_type;
}
inline const QString &VFile::getContent() const
{
Q_ASSERT(m_opened);
return m_content;
}
inline void VFile::setContent(const QString &p_content)
{
m_content = p_content;
m_modified = true;
}
inline QDateTime VFile::getCreatedTimeUtc() const inline QDateTime VFile::getCreatedTimeUtc() const
{ {
return m_createdTimeUtc; return m_createdTimeUtc;

View File

@ -8,7 +8,7 @@
#include "vnote.h" #include "vnote.h"
#include "veditarea.h" #include "veditarea.h"
#include "utils/vutils.h" #include "utils/vutils.h"
#include "vfile.h" #include "vnotefile.h"
#include "vconfigmanager.h" #include "vconfigmanager.h"
#include "vmdedit.h" #include "vmdedit.h"
#include "vmdtab.h" #include "vmdtab.h"
@ -182,9 +182,10 @@ void VFileList::updateFileList()
if (!m_directory->open()) { if (!m_directory->open()) {
return; return;
} }
const QVector<VFile *> &files = m_directory->getFiles();
const QVector<VNoteFile *> &files = m_directory->getFiles();
for (int i = 0; i < files.size(); ++i) { for (int i = 0; i < files.size(); ++i) {
VFile *file = files[i]; VNoteFile *file = files[i];
insertFileListItem(file); insertFileListItem(file);
} }
} }
@ -205,7 +206,7 @@ void VFileList::openFileLocation() const
QDesktopServices::openUrl(url); QDesktopServices::openUrl(url);
} }
void VFileList::fileInfo(VFile *p_file) void VFileList::fileInfo(VNoteFile *p_file)
{ {
if (!p_file) { if (!p_file) {
return; return;
@ -239,7 +240,7 @@ void VFileList::fileInfo(VFile *p_file)
} }
} }
void VFileList::fillItem(QListWidgetItem *p_item, const VFile *p_file) void VFileList::fillItem(QListWidgetItem *p_item, const VNoteFile *p_file)
{ {
unsigned long long ptr = (long long)p_file; unsigned long long ptr = (long long)p_file;
p_item->setData(Qt::UserRole, ptr); p_item->setData(Qt::UserRole, ptr);
@ -249,7 +250,7 @@ void VFileList::fillItem(QListWidgetItem *p_item, const VFile *p_file)
V_ASSERT(sizeof(p_file) <= sizeof(ptr)); V_ASSERT(sizeof(p_file) <= sizeof(ptr));
} }
QListWidgetItem* VFileList::insertFileListItem(VFile *file, bool atFront) QListWidgetItem* VFileList::insertFileListItem(VNoteFile *file, bool atFront)
{ {
V_ASSERT(file); V_ASSERT(file);
QListWidgetItem *item = new QListWidgetItem(); QListWidgetItem *item = new QListWidgetItem();
@ -300,7 +301,7 @@ void VFileList::newFile()
defaultName = VUtils::getFileNameWithSequence(m_directory->fetchPath(), defaultName); defaultName = VUtils::getFileNameWithSequence(m_directory->fetchPath(), defaultName);
VNewFileDialog dialog(tr("Create Note"), info, defaultName, m_directory, this); VNewFileDialog dialog(tr("Create Note"), info, defaultName, m_directory, this);
if (dialog.exec() == QDialog::Accepted) { if (dialog.exec() == QDialog::Accepted) {
VFile *file = m_directory->createFile(dialog.getNameInput()); VNoteFile *file = m_directory->createFile(dialog.getNameInput());
if (!file) { if (!file) {
VUtils::showMessage(QMessageBox::Warning, tr("Warning"), VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
tr("Fail to create note <span style=\"%1\">%2</span>.") tr("Fail to create note <span style=\"%1\">%2</span>.")
@ -355,14 +356,14 @@ void VFileList::newFile()
QVector<QListWidgetItem *> VFileList::updateFileListAdded() QVector<QListWidgetItem *> VFileList::updateFileListAdded()
{ {
QVector<QListWidgetItem *> ret; QVector<QListWidgetItem *> ret;
const QVector<VFile *> &files = m_directory->getFiles(); const QVector<VNoteFile *> &files = m_directory->getFiles();
for (int i = 0; i < files.size(); ++i) { for (int i = 0; i < files.size(); ++i) {
VFile *file = files[i]; VNoteFile *file = files[i];
if (i >= fileList->count()) { if (i >= fileList->count()) {
QListWidgetItem *item = insertFileListItem(file, false); QListWidgetItem *item = insertFileListItem(file, false);
ret.append(item); ret.append(item);
} else { } else {
VFile *itemFile = getVFile(fileList->item(i)); VNoteFile *itemFile = getVFile(fileList->item(i));
if (itemFile != file) { if (itemFile != file) {
QListWidgetItem *item = insertFileListItem(file, false); QListWidgetItem *item = insertFileListItem(file, false);
ret.append(item); ret.append(item);
@ -384,11 +385,12 @@ void VFileList::deleteFile()
} }
// @p_file may or may not be listed in VFileList // @p_file may or may not be listed in VFileList
void VFileList::deleteFile(VFile *p_file) void VFileList::deleteFile(VNoteFile *p_file)
{ {
if (!p_file) { if (!p_file) {
return; return;
} }
VDirectory *dir = p_file->getDirectory(); VDirectory *dir = p_file->getDirectory();
QString fileName = p_file->getName(); QString fileName = p_file->getName();
int ret = VUtils::showMessage(QMessageBox::Warning, tr("Warning"), int ret = VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
@ -427,7 +429,7 @@ void VFileList::contextMenuRequested(QPoint pos)
} }
if (item && fileList->selectedItems().size() == 1) { if (item && fileList->selectedItems().size() == 1) {
VFile *file = getVFile(item); VNoteFile *file = getVFile(item);
if (file && file->getDocType() == DocType::Markdown) { if (file && file->getDocType() == DocType::Markdown) {
menu.addAction(m_openInReadAct); menu.addAction(m_openInReadAct);
menu.addAction(m_openInEditAct); menu.addAction(m_openInEditAct);
@ -464,7 +466,7 @@ void VFileList::contextMenuRequested(QPoint pos)
menu.exec(fileList->mapToGlobal(pos)); menu.exec(fileList->mapToGlobal(pos));
} }
QListWidgetItem* VFileList::findItem(const VFile *p_file) QListWidgetItem* VFileList::findItem(const VNoteFile *p_file)
{ {
if (!p_file || p_file->getDirectory() != m_directory) { if (!p_file || p_file->getDirectory() != m_directory) {
return NULL; return NULL;
@ -477,6 +479,7 @@ QListWidgetItem* VFileList::findItem(const VFile *p_file)
return item; return item;
} }
} }
return NULL; return NULL;
} }
@ -515,7 +518,7 @@ bool VFileList::importFile(const QString &p_srcFilePath)
return false; return false;
} }
VFile *destFile = m_directory->addFile(srcName, -1); VNoteFile *destFile = m_directory->addFile(srcName, -1);
if (destFile) { if (destFile) {
return insertFileListItem(destFile, false); return insertFileListItem(destFile, false);
} }
@ -531,7 +534,7 @@ void VFileList::copySelectedFiles(bool p_isCut)
QJsonArray files; QJsonArray files;
m_copiedFiles.clear(); m_copiedFiles.clear();
for (int i = 0; i < items.size(); ++i) { for (int i = 0; i < items.size(); ++i) {
VFile *file = getVFile(items[i]); VNoteFile *file = getVFile(items[i]);
QJsonObject fileJson; QJsonObject fileJson;
fileJson["notebook"] = file->getNotebookName(); fileJson["notebook"] = file->getNotebookName();
fileJson["path"] = file->fetchPath(); fileJson["path"] = file->fetchPath();
@ -579,10 +582,11 @@ void VFileList::pasteFiles(VDirectory *p_destDir)
int nrPasted = 0; int nrPasted = 0;
for (int i = 0; i < m_copiedFiles.size(); ++i) { for (int i = 0; i < m_copiedFiles.size(); ++i) {
QPointer<VFile> srcFile = m_copiedFiles[i]; QPointer<VNoteFile> srcFile = m_copiedFiles[i];
if (!srcFile) { if (!srcFile) {
continue; continue;
} }
QString fileName = srcFile->getName(); QString fileName = srcFile->getName();
VDirectory *srcDir = srcFile->getDirectory(); VDirectory *srcDir = srcFile->getDirectory();
if (srcDir == p_destDir && !isCut) { if (srcDir == p_destDir && !isCut) {
@ -606,7 +610,7 @@ void VFileList::pasteFiles(VDirectory *p_destDir)
m_copiedFiles.clear(); m_copiedFiles.clear();
} }
bool VFileList::copyFile(VDirectory *p_destDir, const QString &p_destName, VFile *p_file, bool p_cut) bool VFileList::copyFile(VDirectory *p_destDir, const QString &p_destName, VNoteFile *p_file, bool p_cut)
{ {
QString srcPath = QDir::cleanPath(p_file->fetchPath()); QString srcPath = QDir::cleanPath(p_file->fetchPath());
QString destPath = QDir::cleanPath(QDir(p_destDir->fetchPath()).filePath(p_destName)); QString destPath = QDir::cleanPath(QDir(p_destDir->fetchPath()).filePath(p_destName));
@ -617,7 +621,7 @@ bool VFileList::copyFile(VDirectory *p_destDir, const QString &p_destName, VFile
// DocType is not allowed to change. // DocType is not allowed to change.
Q_ASSERT(p_file->getDocType() == VUtils::docTypeFromName(destPath)); Q_ASSERT(p_file->getDocType() == VUtils::docTypeFromName(destPath));
VFile *destFile = VDirectory::copyFile(p_destDir, p_destName, p_file, p_cut); VNoteFile *destFile = VDirectory::copyFile(p_destDir, p_destName, p_file, p_cut);
updateFileList(); updateFileList();
if (destFile) { if (destFile) {
emit fileUpdated(destFile); emit fileUpdated(destFile);
@ -676,7 +680,7 @@ void VFileList::focusInEvent(QFocusEvent * /* p_event */)
fileList->setFocus(); fileList->setFocus();
} }
bool VFileList::locateFile(const VFile *p_file) bool VFileList::locateFile(const VNoteFile *p_file)
{ {
if (p_file) { if (p_file) {
if (p_file->getDirectory() != m_directory) { if (p_file->getDirectory() != m_directory) {
@ -704,7 +708,7 @@ void VFileList::handleRowsMoved(const QModelIndex &p_parent, int p_start, int p_
bool VFileList::identicalListWithDirectory() const bool VFileList::identicalListWithDirectory() const
{ {
const QVector<VFile *> files = m_directory->getFiles(); const QVector<VNoteFile *> files = m_directory->getFiles();
int nrItems = fileList->count(); int nrItems = fileList->count();
if (nrItems != files.size()) { if (nrItems != files.size()) {
return false; return false;

View File

@ -11,7 +11,7 @@
#include "vnotebook.h" #include "vnotebook.h"
#include "vconstants.h" #include "vconstants.h"
#include "vdirectory.h" #include "vdirectory.h"
#include "vfile.h" #include "vnotefile.h"
#include "vnavigationmode.h" #include "vnavigationmode.h"
class QAction; class QAction;
@ -29,9 +29,9 @@ public:
explicit VFileList(QWidget *parent = 0); explicit VFileList(QWidget *parent = 0);
bool importFile(const QString &p_srcFilePath); bool importFile(const QString &p_srcFilePath);
inline void setEditArea(VEditArea *editArea); inline void setEditArea(VEditArea *editArea);
void fileInfo(VFile *p_file); void fileInfo(VNoteFile *p_file);
void deleteFile(VFile *p_file); void deleteFile(VNoteFile *p_file);
bool locateFile(const VFile *p_file); bool locateFile(const VNoteFile *p_file);
inline const VDirectory *currentDirectory() const; inline const VDirectory *currentDirectory() const;
// Implementations for VNavigationMode. // Implementations for VNavigationMode.
@ -41,16 +41,16 @@ public:
bool handleKeyNavigation(int p_key, bool &p_succeed) Q_DECL_OVERRIDE; bool handleKeyNavigation(int p_key, bool &p_succeed) Q_DECL_OVERRIDE;
signals: signals:
void fileClicked(VFile *p_file, OpenFileMode mode = OpenFileMode::Read); void fileClicked(VNoteFile *p_file, OpenFileMode mode = OpenFileMode::Read);
void fileCreated(VFile *p_file, OpenFileMode mode = OpenFileMode::Read); void fileCreated(VNoteFile *p_file, OpenFileMode mode = OpenFileMode::Read);
void fileUpdated(const VFile *p_file); void fileUpdated(const VNoteFile *p_file);
private slots: private slots:
void contextMenuRequested(QPoint pos); void contextMenuRequested(QPoint pos);
void handleItemClicked(QListWidgetItem *currentItem); void handleItemClicked(QListWidgetItem *currentItem);
void fileInfo(); void fileInfo();
void openFileLocation() const; void openFileLocation() const;
// m_copiedFiles will keep the files's VFile. // m_copiedFiles will keep the files's VNoteFile.
void copySelectedFiles(bool p_isCut = false); void copySelectedFiles(bool p_isCut = false);
void cutSelectedFiles(); void cutSelectedFiles();
void pasteFilesInCurDir(); void pasteFilesInCurDir();
@ -72,32 +72,36 @@ private:
void initShortcuts(); void initShortcuts();
void updateFileList(); void updateFileList();
QListWidgetItem *insertFileListItem(VFile *file, bool atFront = false);
QListWidgetItem *insertFileListItem(VNoteFile *file, bool atFront = false);
void removeFileListItem(QListWidgetItem *item); void removeFileListItem(QListWidgetItem *item);
// Init actions. // Init actions.
void initActions(); void initActions();
// Return the corresponding QListWidgetItem of @p_file. // Return the corresponding QListWidgetItem of @p_file.
QListWidgetItem *findItem(const VFile *p_file); QListWidgetItem *findItem(const VNoteFile *p_file);
void copyFileInfoToClipboard(const QJsonArray &p_files, bool p_isCut); void copyFileInfoToClipboard(const QJsonArray &p_files, bool p_isCut);
void pasteFiles(VDirectory *p_destDir); void pasteFiles(VDirectory *p_destDir);
bool copyFile(VDirectory *p_destDir, const QString &p_destName, VFile *p_file, bool p_cut); bool copyFile(VDirectory *p_destDir, const QString &p_destName, VNoteFile *p_file, bool p_cut);
// New items have been added to direcotry. Update file list accordingly. // New items have been added to direcotry. Update file list accordingly.
QVector<QListWidgetItem *> updateFileListAdded(); QVector<QListWidgetItem *> updateFileListAdded();
inline QPointer<VFile> getVFile(QListWidgetItem *p_item) const;
inline QPointer<VNoteFile> getVFile(QListWidgetItem *p_item) const;
// Check if the list items match exactly the contents of the directory. // Check if the list items match exactly the contents of the directory.
bool identicalListWithDirectory() const; bool identicalListWithDirectory() const;
QList<QListWidgetItem *> getVisibleItems() const; QList<QListWidgetItem *> getVisibleItems() const;
// Fill the info of @p_item according to @p_file. // Fill the info of @p_item according to @p_file.
void fillItem(QListWidgetItem *p_item, const VFile *p_file); void fillItem(QListWidgetItem *p_item, const VNoteFile *p_file);
VEditArea *editArea; VEditArea *editArea;
QListWidget *fileList; QListWidget *fileList;
QPointer<VDirectory> m_directory; QPointer<VDirectory> m_directory;
QVector<QPointer<VFile> > m_copiedFiles; QVector<QPointer<VNoteFile> > m_copiedFiles;
// Actions // Actions
QAction *m_openInReadAct; QAction *m_openInReadAct;
@ -126,10 +130,10 @@ inline void VFileList::setEditArea(VEditArea *editArea)
this->editArea = editArea; this->editArea = editArea;
} }
inline QPointer<VFile> VFileList::getVFile(QListWidgetItem *p_item) const inline QPointer<VNoteFile> VFileList::getVFile(QListWidgetItem *p_item) const
{ {
Q_ASSERT(p_item); Q_ASSERT(p_item);
return (VFile *)p_item->data(Qt::UserRole).toULongLong(); return (VNoteFile *)p_item->data(Qt::UserRole).toULongLong();
} }
inline const VDirectory *VFileList::currentDirectory() const inline const VDirectory *VFileList::currentDirectory() const

View File

@ -26,6 +26,7 @@
#include "vorphanfile.h" #include "vorphanfile.h"
#include "dialog/vorphanfileinfodialog.h" #include "dialog/vorphanfileinfodialog.h"
#include "vsingleinstanceguard.h" #include "vsingleinstanceguard.h"
#include "vnotefile.h"
extern VConfigManager *g_config; extern VConfigManager *g_config;
@ -464,7 +465,6 @@ void VMainWindow::initHelpMenu()
} }
VFile *file = vnote->getOrphanFile(docName, false, true); VFile *file = vnote->getOrphanFile(docName, false, true);
(dynamic_cast<VOrphanFile *>(file))->setNotebookName(tr("[Help]"));
editArea->openFile(file, OpenFileMode::Read); editArea->openFile(file, OpenFileMode::Read);
}); });
@ -1508,7 +1508,7 @@ void VMainWindow::updateActionStateFromTabStatusChange(const VFile *p_file,
editNoteAct->setEnabled(p_file && p_file->isModifiable() && !p_editMode); editNoteAct->setEnabled(p_file && p_file->isModifiable() && !p_editMode);
editNoteAct->setVisible(!saveExitAct->isVisible()); editNoteAct->setVisible(!saveExitAct->isVisible());
saveNoteAct->setEnabled(p_file && p_editMode); saveNoteAct->setEnabled(p_file && p_editMode);
deleteNoteAct->setEnabled(p_file && p_file->getType() == FileType::Normal); deleteNoteAct->setEnabled(p_file && p_file->getType() == FileType::Note);
noteInfoAct->setEnabled(p_file && !systemFile); noteInfoAct->setEnabled(p_file && !systemFile);
m_insertImageAct->setEnabled(p_file && p_editMode); m_insertImageAct->setEnabled(p_file && p_editMode);
@ -1545,7 +1545,13 @@ void VMainWindow::handleAreaTabStatusUpdated(const VEditTabInfo &p_info)
if (m_curFile) { if (m_curFile) {
m_findReplaceDialog->updateState(m_curFile->getDocType(), editMode); m_findReplaceDialog->updateState(m_curFile->getDocType(), editMode);
title = QString("[%1] %2").arg(m_curFile->getNotebookName()).arg(m_curFile->fetchPath()); if (m_curFile->getType() == FileType::Note) {
const VNoteFile *tmpFile = dynamic_cast<const VNoteFile *>((VFile *)m_curFile);
title = QString("[%1] %2").arg(tmpFile->getNotebookName()).arg(tmpFile->fetchPath());
} else {
title = QString("%1").arg(m_curFile->fetchPath());
}
if (m_curFile->isModifiable()) { if (m_curFile->isModifiable()) {
if (m_curFile->isModified()) { if (m_curFile->isModified()) {
title.append('*'); title.append('*');
@ -1636,8 +1642,10 @@ void VMainWindow::curEditFileInfo()
{ {
Q_ASSERT(m_curFile); Q_ASSERT(m_curFile);
if (m_curFile->getType() == FileType::Normal) { if (m_curFile->getType() == FileType::Note) {
fileList->fileInfo(m_curFile); VNoteFile *file = dynamic_cast<VNoteFile *>((VFile *)m_curFile);
Q_ASSERT(file);
fileList->fileInfo(file);
} else if (m_curFile->getType() == FileType::Orphan) { } else if (m_curFile->getType() == FileType::Orphan) {
VOrphanFile *file = dynamic_cast<VOrphanFile *>((VFile *)m_curFile); VOrphanFile *file = dynamic_cast<VOrphanFile *>((VFile *)m_curFile);
Q_ASSERT(file); Q_ASSERT(file);
@ -1649,11 +1657,12 @@ void VMainWindow::curEditFileInfo()
void VMainWindow::deleteCurNote() void VMainWindow::deleteCurNote()
{ {
if (!m_curFile || m_curFile->getType() != FileType::Normal) { if (!m_curFile || m_curFile->getType() != FileType::Note) {
return; return;
} }
fileList->deleteFile(m_curFile); VNoteFile *file = dynamic_cast<VNoteFile *>((VFile *)m_curFile);
fileList->deleteFile(file);
} }
void VMainWindow::closeEvent(QCloseEvent *event) void VMainWindow::closeEvent(QCloseEvent *event)
@ -1793,23 +1802,24 @@ void VMainWindow::insertImage()
bool VMainWindow::locateFile(VFile *p_file) bool VMainWindow::locateFile(VFile *p_file)
{ {
bool ret = false; bool ret = false;
if (!p_file || p_file->getType() != FileType::Normal) { if (!p_file || p_file->getType() != FileType::Note) {
return ret; return ret;
} }
VNotebook *notebook = p_file->getNotebook(); VNoteFile *file = dynamic_cast<VNoteFile *>(p_file);
VNotebook *notebook = file->getNotebook();
if (notebookSelector->locateNotebook(notebook)) { if (notebookSelector->locateNotebook(notebook)) {
while (directoryTree->currentNotebook() != notebook) { while (directoryTree->currentNotebook() != notebook) {
QCoreApplication::sendPostedEvents(); QCoreApplication::sendPostedEvents();
} }
VDirectory *dir = p_file->getDirectory(); VDirectory *dir = file->getDirectory();
if (directoryTree->locateDirectory(dir)) { if (directoryTree->locateDirectory(dir)) {
while (fileList->currentDirectory() != dir) { while (fileList->currentDirectory() != dir) {
QCoreApplication::sendPostedEvents(); QCoreApplication::sendPostedEvents();
} }
if (fileList->locateFile(p_file)) { if (fileList->locateFile(file)) {
ret = true; ret = true;
fileList->setFocus(); fileList->setFocus();
} }
@ -1933,7 +1943,6 @@ void VMainWindow::shortcutHelp()
} }
VFile *file = vnote->getOrphanFile(docName, false, true); VFile *file = vnote->getOrphanFile(docName, false, true);
(dynamic_cast<VOrphanFile *>(file))->setNotebookName(tr("[Help]"));
editArea->openFile(file, OpenFileMode::Read); editArea->openFile(file, OpenFileMode::Read);
} }

View File

@ -219,7 +219,7 @@ void VMdEdit::imageInserted(const QString &p_path)
{ {
ImageLink link; ImageLink link;
link.m_path = p_path; link.m_path = p_path;
if (m_file->isRelativeImageFolder()) { if (m_file->useRelativeImageFolder()) {
link.m_type = ImageLink::LocalRelativeInternal; link.m_type = ImageLink::LocalRelativeInternal;
} else { } else {
link.m_type = ImageLink::LocalAbsolute; link.m_type = ImageLink::LocalAbsolute;
@ -300,7 +300,15 @@ void VMdEdit::clearUnusedImages()
} }
for (int i = 0; i < unusedImages.size(); ++i) { for (int i = 0; i < unusedImages.size(); ++i) {
if (!VUtils::deleteFile(m_file->getNotebook(), unusedImages[i], false)) { bool ret = false;
if (m_file->getType() == FileType::Note) {
const VNoteFile *tmpFile = dynamic_cast<const VNoteFile *>((VFile *)m_file);
ret = VUtils::deleteFile(tmpFile->getNotebook(), unusedImages[i], false);
} else {
ret = VUtils::deleteFile(unusedImages[i], false);
}
if (!ret) {
qWarning() << "fail to delete unused original image" << unusedImages[i]; qWarning() << "fail to delete unused original image" << unusedImages[i];
} else { } else {
qDebug() << "delete unused image" << unusedImages[i]; qDebug() << "delete unused image" << unusedImages[i];

View File

@ -45,7 +45,7 @@ bool VMdEditOperations::insertImageFromMimeData(const QMimeData *source)
dialog.setImage(image); dialog.setImage(image);
if (dialog.exec() == QDialog::Accepted) { if (dialog.exec() == QDialog::Accepted) {
insertImageFromQImage(dialog.getImageTitleInput(), insertImageFromQImage(dialog.getImageTitleInput(),
m_file->fetchImagePath(), m_file->fetchImageFolderPath(),
m_file->getImageFolderInLink(), m_file->getImageFolderInLink(),
image); image);
} }
@ -170,12 +170,12 @@ bool VMdEditOperations::insertImageFromURL(const QUrl &imageUrl)
if (dialog.exec() == QDialog::Accepted) { if (dialog.exec() == QDialog::Accepted) {
if (isLocal) { if (isLocal) {
insertImageFromPath(dialog.getImageTitleInput(), insertImageFromPath(dialog.getImageTitleInput(),
m_file->fetchImagePath(), m_file->fetchImageFolderPath(),
m_file->getImageFolderInLink(), m_file->getImageFolderInLink(),
imagePath); imagePath);
} else { } else {
insertImageFromQImage(dialog.getImageTitleInput(), insertImageFromQImage(dialog.getImageTitleInput(),
m_file->fetchImagePath(), m_file->fetchImageFolderPath(),
m_file->getImageFolderInLink(), m_file->getImageFolderInLink(),
dialog.getImage()); dialog.getImage());
} }
@ -192,7 +192,7 @@ bool VMdEditOperations::insertImage()
QString imagePath = dialog.getPathInput(); QString imagePath = dialog.getPathInput();
qDebug() << "insert image from" << imagePath << "as" << title; qDebug() << "insert image from" << imagePath << "as" << title;
insertImageFromPath(title, insertImageFromPath(title,
m_file->fetchImagePath(), m_file->fetchImageFolderPath(),
m_file->getImageFolderInLink(), m_file->getImageFolderInLink(),
imagePath); imagePath);
} }

View File

@ -12,6 +12,7 @@
#include "vconfigmanager.h" #include "vconfigmanager.h"
#include "vmainwindow.h" #include "vmainwindow.h"
#include "vorphanfile.h" #include "vorphanfile.h"
#include "vnotefile.h"
extern VConfigManager *g_config; extern VConfigManager *g_config;
@ -281,7 +282,7 @@ const QString &VNote::getMonospacedFont() const
return font; return font;
} }
VFile *VNote::getOrphanFile(const QString &p_path, bool p_modifiable, bool p_systemFile) VOrphanFile *VNote::getOrphanFile(const QString &p_path, bool p_modifiable, bool p_systemFile)
{ {
if (p_path.isEmpty()) { if (p_path.isEmpty()) {
return NULL; return NULL;
@ -290,17 +291,15 @@ VFile *VNote::getOrphanFile(const QString &p_path, bool p_modifiable, bool p_sys
QString path = QDir::cleanPath(p_path); QString path = QDir::cleanPath(p_path);
// See if the file has already been opened before. // See if the file has already been opened before.
for (auto const &file : m_externalFiles) { for (auto const &file : m_externalFiles) {
Q_ASSERT(file->getType() == FileType::Orphan); if (VUtils::equalPath(QDir::cleanPath(file->fetchPath()), path)) {
VOrphanFile *oFile = dynamic_cast<VOrphanFile *>(file); Q_ASSERT(file->isModifiable() == p_modifiable);
if (VUtils::equalPath(QDir::cleanPath(oFile->fetchPath()), path)) { Q_ASSERT(file->isSystemFile() == p_systemFile);
Q_ASSERT(oFile->isModifiable() == p_modifiable);
Q_ASSERT(oFile->isSystemFile() == p_systemFile);
return file; return file;
} }
} }
for (int i = 0; i < m_externalFiles.size(); ++i) { for (int i = 0; i < m_externalFiles.size(); ++i) {
VFile *file = m_externalFiles[i]; VOrphanFile *file = m_externalFiles[i];
if (!file->isOpened()) { if (!file->isOpened()) {
qDebug() << "release orphan file" << file; qDebug() << "release orphan file" << file;
m_externalFiles.removeAt(i); m_externalFiles.removeAt(i);
@ -310,14 +309,14 @@ VFile *VNote::getOrphanFile(const QString &p_path, bool p_modifiable, bool p_sys
} }
// Create a VOrphanFile for path. // Create a VOrphanFile for path.
VOrphanFile *file = new VOrphanFile(path, this, p_modifiable, p_systemFile); VOrphanFile *file = new VOrphanFile(this, path, p_modifiable, p_systemFile);
m_externalFiles.append(file); m_externalFiles.append(file);
return file; return file;
} }
VFile *VNote::getInternalFile(const QString &p_path) VNoteFile *VNote::getInternalFile(const QString &p_path)
{ {
VFile *file = NULL; VNoteFile *file = NULL;
for (auto & nb : m_notebooks) { for (auto & nb : m_notebooks) {
file = nb->tryLoadFile(p_path); file = nb->tryLoadFile(p_path);
if (file) { if (file) {

View File

@ -14,7 +14,8 @@
#include "vconstants.h" #include "vconstants.h"
class VMainWindow; class VMainWindow;
class VFile; class VOrphanFile;
class VNoteFile;
class VNote : public QObject class VNote : public QObject
{ {
@ -80,14 +81,15 @@ public:
QString getNavigationLabelStyle(const QString &p_str) const; QString getNavigationLabelStyle(const QString &p_str) const;
// Given the path of an external file, create a VFile struct. // Given the path of an external file, create a VOrphanFile struct.
VFile *getOrphanFile(const QString &p_path, bool p_modifiable, VOrphanFile *getOrphanFile(const QString &p_path,
bool p_modifiable,
bool p_systemFile = false); bool p_systemFile = false);
// Given the path of a file, try to find it in all notebooks. // Given the path of a file, try to find it in all notebooks.
// Returns a VFile struct if it is a note in one notebook. // Returns a VNoteFile struct if it is a note in one notebook.
// Otherwise, returns NULL. // Otherwise, returns NULL.
VFile *getInternalFile(const QString &p_path); VNoteFile *getInternalFile(const QString &p_path);
public slots: public slots:
void updateTemplate(); void updateTemplate();
@ -102,7 +104,7 @@ private:
// Hold all external file: Orphan File. // Hold all external file: Orphan File.
// Need to clean up periodly. // Need to clean up periodly.
QList<VFile *> m_externalFiles; QList<VOrphanFile *> m_externalFiles;
}; };
inline const QVector<QPair<QString, QString> >& VNote::getPalette() const inline const QVector<QPair<QString, QString> >& VNote::getPalette() const

View File

@ -4,7 +4,7 @@
#include "vdirectory.h" #include "vdirectory.h"
#include "utils/vutils.h" #include "utils/vutils.h"
#include "vconfigmanager.h" #include "vconfigmanager.h"
#include "vfile.h" #include "vnotefile.h"
extern VConfigManager *g_config; extern VConfigManager *g_config;
@ -221,7 +221,7 @@ bool VNotebook::containsFile(const VFile *p_file) const
return m_rootDir->containsFile(p_file); return m_rootDir->containsFile(p_file);
} }
VFile *VNotebook::tryLoadFile(const QString &p_path) VNoteFile *VNotebook::tryLoadFile(const QString &p_path)
{ {
QFileInfo fi(p_path); QFileInfo fi(p_path);
Q_ASSERT(fi.isAbsolute()); Q_ASSERT(fi.isAbsolute());
@ -240,7 +240,7 @@ VFile *VNotebook::tryLoadFile(const QString &p_path)
return NULL; return NULL;
} }
VFile *file = m_rootDir->tryLoadFile(filePath); VNoteFile *file = m_rootDir->tryLoadFile(filePath);
if (!file && !opened) { if (!file && !opened) {
close(); close();

View File

@ -7,6 +7,7 @@
class VDirectory; class VDirectory;
class VFile; class VFile;
class VNoteFile;
class VNotebook : public QObject class VNotebook : public QObject
{ {
@ -29,11 +30,11 @@ public:
bool containsFile(const VFile *p_file) const; bool containsFile(const VFile *p_file) const;
// Try to load the file @p_path. // Try to load the file @p_path.
// Returns the corresponding VFile struct if @p_path is a note inside this notebook. // Returns the corresponding VNoteFile struct if @p_path is a note inside this notebook.
// Otherwise, returns NULL. // Otherwise, returns NULL.
// If notebook is not opened currently, it will open itself and close itself // If notebook is not opened currently, it will open itself and close itself
// if @p_path is not inside this notebook. // if @p_path is not inside this notebook.
VFile *tryLoadFile(const QString &p_path); VNoteFile *tryLoadFile(const QString &p_path);
const QString &getName() const; const QString &getName() const;
const QString &getPath() const; const QString &getPath() const;

187
src/vnotefile.cpp Normal file
View File

@ -0,0 +1,187 @@
#include "vnotefile.h"
#include <QDir>
#include <QDebug>
#include <QTextEdit>
#include <QFileInfo>
#include <QDebug>
#include "utils/vutils.h"
#include "vdirectory.h"
VNoteFile::VNoteFile(VDirectory *p_directory,
const QString &p_name,
FileType p_type,
bool p_modifiable,
QDateTime p_createdTimeUtc,
QDateTime p_modifiedTimeUtc)
: VFile(p_directory, p_name, p_type, p_modifiable, p_createdTimeUtc, p_modifiedTimeUtc)
{
}
QString VNoteFile::fetchPath() const
{
return QDir(getDirectory()->fetchPath()).filePath(m_name);
}
QString VNoteFile::fetchBasePath() const
{
return getDirectory()->fetchPath();
}
QString VNoteFile::fetchImageFolderPath() const
{
return QDir(fetchBasePath()).filePath(getNotebook()->getImageFolder());
}
bool VNoteFile::useRelativeImageFolder() const
{
// Always use relative image folder.
return true;
}
QString VNoteFile::getImageFolderInLink() const
{
return getNotebook()->getImageFolder();
}
void VNoteFile::setName(const QString &p_name)
{
Q_ASSERT(m_name.isEmpty()
|| (m_docType == VUtils::docTypeFromName(p_name)));
m_name = p_name;
}
bool VNoteFile::rename(const QString &p_name)
{
if (m_name == p_name) {
return true;
}
QString oldName = m_name;
VDirectory *dir = getDirectory();
Q_ASSERT(dir);
// Rename it in disk.
QDir diskDir(dir->fetchPath());
if (!diskDir.rename(m_name, p_name)) {
qWarning() << "fail to rename file" << m_name << "to" << p_name << "in disk";
return false;
}
m_name = p_name;
// Update parent directory's config file.
if (!dir->writeToConfig()) {
m_name = oldName;
diskDir.rename(p_name, m_name);
return false;
}
// Can't not change doc type.
Q_ASSERT(m_docType == VUtils::docTypeFromName(m_name));
qDebug() << "file renamed from" << oldName << "to" << m_name;
return true;
}
VDirectory *VNoteFile::getDirectory()
{
Q_ASSERT(parent());
return (VDirectory *)parent();
}
const VDirectory *VNoteFile::getDirectory() const
{
Q_ASSERT(parent());
return (const VDirectory *)parent();
}
VNotebook *VNoteFile::getNotebook()
{
return getDirectory()->getNotebook();
}
const VNotebook *VNoteFile::getNotebook() const
{
return getDirectory()->getNotebook();
}
QString VNoteFile::getNotebookName() const
{
return getDirectory()->getNotebookName();
}
QString VNoteFile::fetchRelativePath() const
{
return QDir(getDirectory()->fetchRelativePath()).filePath(m_name);
}
VNoteFile *VNoteFile::fromJson(VDirectory *p_directory,
const QJsonObject &p_json,
FileType p_type,
bool p_modifiable)
{
return new VNoteFile(p_directory,
p_json[DirConfig::c_name].toString(),
p_type,
p_modifiable,
QDateTime::fromString(p_json[DirConfig::c_createdTime].toString(),
Qt::ISODate),
QDateTime::fromString(p_json[DirConfig::c_modifiedTime].toString(),
Qt::ISODate));
}
QJsonObject VNoteFile::toConfigJson() const
{
QJsonObject item;
item[DirConfig::c_name] = m_name;
item[DirConfig::c_createdTime] = m_createdTimeUtc.toString(Qt::ISODate);
item[DirConfig::c_modifiedTime] = m_modifiedTimeUtc.toString(Qt::ISODate);
return item;
}
bool VNoteFile::deleteFile()
{
Q_ASSERT(parent());
bool ret = false;
// Delete local images if it is Markdown.
if (m_docType == DocType::Markdown) {
deleteInternalImages();
}
// TODO: Delete attachments.
// Delete the file.
QString filePath = fetchPath();
if (VUtils::deleteFile(getNotebook(), filePath, false)) {
ret = true;
qDebug() << "deleted" << m_name << filePath;
} else {
qWarning() << "fail to delete" << m_name << filePath;
}
return ret;
}
void VNoteFile::deleteInternalImages()
{
Q_ASSERT(parent() && m_docType == DocType::Markdown);
QVector<ImageLink> images = VUtils::fetchImagesFromMarkdownFile(this,
ImageLink::LocalRelativeInternal);
int deleted = 0;
for (int i = 0; i < images.size(); ++i) {
if (VUtils::deleteFile(getNotebook(), images[i].m_path, false)) {
++deleted;
}
}
qDebug() << "delete" << deleted << "images for" << m_name << fetchPath();
}

66
src/vnotefile.h Normal file
View File

@ -0,0 +1,66 @@
#ifndef VNOTEFILE_H
#define VNOTEFILE_H
#include "vfile.h"
class VDirectory;
class VNotebook;
class VNoteFile : public VFile
{
Q_OBJECT
public:
VNoteFile(VDirectory *p_directory,
const QString &p_name,
FileType p_type,
bool p_modifiable,
QDateTime p_createdTimeUtc,
QDateTime p_modifiedTimeUtc);
QString fetchPath() const Q_DECL_OVERRIDE;
QString fetchBasePath() const Q_DECL_OVERRIDE;
QString fetchImageFolderPath() const Q_DECL_OVERRIDE;
bool useRelativeImageFolder() const Q_DECL_OVERRIDE;
QString getImageFolderInLink() const Q_DECL_OVERRIDE;
// Set the name of this file.
void setName(const QString &p_name);
// Rename the name of this file in disk and config.
bool rename(const QString &p_name);
VDirectory *getDirectory();
const VDirectory *getDirectory() const;
VNotebook *getNotebook();
const VNotebook *getNotebook() const;
QString getNotebookName() const;
// Get the relative path related to the notebook.
QString fetchRelativePath() const;
// Create a VNoteFile from @p_json Json object.
static VNoteFile *fromJson(VDirectory *p_directory,
const QJsonObject &p_json,
FileType p_type,
bool p_modifiable);
// Create a Json object from current instance.
QJsonObject toConfigJson() const;
// Delete this file in disk as well as all its images/attachments.
bool deleteFile();
private:
// Delete internal images of this file.
void deleteInternalImages();
};
#endif // VNOTEFILE_H

View File

@ -8,7 +8,7 @@
#include <QStyleFactory> #include <QStyleFactory>
#include "veditwindow.h" #include "veditwindow.h"
#include "vfile.h" #include "vnotefile.h"
#include "vedittab.h" #include "vedittab.h"
#include "vdirectory.h" #include "vdirectory.h"
#include "utils/vutils.h" #include "utils/vutils.h"
@ -18,8 +18,19 @@ static const int c_cmdTime = 1 * 1000;
static bool fileComp(const VOpenedListMenu::ItemInfo &a, static bool fileComp(const VOpenedListMenu::ItemInfo &a,
const VOpenedListMenu::ItemInfo &b) const VOpenedListMenu::ItemInfo &b)
{ {
QString notebooka = a.file->getNotebookName().toLower(); QString notebooka, notebookb;
QString notebookb = b.file->getNotebookName().toLower(); if (a.file->getType() == FileType::Note) {
notebooka = dynamic_cast<const VNoteFile *>(a.file)->getNotebookName().toLower();
} else {
notebooka = "EXTERNAL_FILES";
}
if (b.file->getType() == FileType::Note) {
notebookb = dynamic_cast<const VNoteFile *>(b.file)->getNotebookName().toLower();
} else {
notebookb = "EXTERNAL_FILES";
}
if (notebooka < notebookb) { if (notebooka < notebookb) {
return true; return true;
} else if (notebooka > notebookb) { } else if (notebooka > notebookb) {
@ -87,11 +98,20 @@ void VOpenedListMenu::updateOpenedList()
int index = files[i].index; int index = files[i].index;
// Whether add separator. // Whether add separator.
QString curNotebook = file->getNotebookName(); QString curNotebook;
const VDirectory *curDirectory = NULL;
if (file->getType() == FileType::Note) {
const VNoteFile *tmpFile = dynamic_cast<const VNoteFile *>((VFile *)file);
curNotebook = tmpFile->getNotebookName();
curDirectory = tmpFile->getDirectory();
} else {
curNotebook = "EXTERNAL_FILES";
}
if (curNotebook != notebook if (curNotebook != notebook
|| file->getDirectory() != directory) { || curDirectory != directory) {
notebook = curNotebook; notebook = curNotebook;
directory = file->getDirectory(); directory = curDirectory;
QString dirName; QString dirName;
if (directory) { if (directory) {
dirName = directory->getName(); dirName = directory->getName();
@ -127,8 +147,14 @@ QString VOpenedListMenu::generateDescription(const VFile *p_file) const
if (!p_file) { if (!p_file) {
return ""; return "";
} }
// [Notebook]path // [Notebook]path
return QString("[%1] %2").arg(p_file->getNotebookName()).arg(p_file->fetchPath()); if (p_file->getType() == FileType::Note) {
const VNoteFile *tmpFile = dynamic_cast<const VNoteFile *>(p_file);
return QString("[%1] %2").arg(tmpFile->getNotebookName()).arg(tmpFile->fetchPath());
} else {
return QString("%1").arg(p_file->fetchPath());
}
} }
void VOpenedListMenu::handleItemTriggered(QAction *p_action) void VOpenedListMenu::handleItemTriggered(QAction *p_action)

View File

@ -8,33 +8,19 @@
extern VConfigManager *g_config; extern VConfigManager *g_config;
VOrphanFile::VOrphanFile(const QString &p_path, QObject *p_parent, VOrphanFile::VOrphanFile(QObject *p_parent,
bool p_modifiable, bool p_systemFile) const QString &p_path,
bool p_modifiable,
bool p_systemFile)
: VFile(p_parent, : VFile(p_parent,
VUtils::fileNameFromPath(p_path), VUtils::fileNameFromPath(p_path),
FileType::Orphan, FileType::Orphan,
p_modifiable, p_modifiable,
QDateTime(), QDateTime(),
QDateTime()), QDateTime()),
m_path(p_path), m_notebookName(tr("[EXTERNAL]")), m_systemFile(p_systemFile) m_path(p_path),
m_systemFile(p_systemFile)
{ {
qDebug() << "VOrphanFile" << p_path << m_name << p_modifiable;
}
bool VOrphanFile::open()
{
Q_ASSERT(!m_name.isEmpty());
if (m_opened) {
return true;
}
Q_ASSERT(m_content.isEmpty());
Q_ASSERT(QFileInfo::exists(m_path));
m_content = VUtils::readFileFromDisk(m_path);
m_modified = false;
m_opened = true;
return true;
} }
QString VOrphanFile::fetchPath() const QString VOrphanFile::fetchPath() const
@ -42,17 +28,12 @@ QString VOrphanFile::fetchPath() const
return m_path; return m_path;
} }
QString VOrphanFile::fetchRelativePath() const
{
return m_path;
}
QString VOrphanFile::fetchBasePath() const QString VOrphanFile::fetchBasePath() const
{ {
return VUtils::basePathFromPath(m_path); return VUtils::basePathFromPath(m_path);
} }
QString VOrphanFile::fetchImagePath() const QString VOrphanFile::fetchImageFolderPath() const
{ {
QString folder = m_imageFolder; QString folder = m_imageFolder;
if (m_imageFolder.isEmpty()) { if (m_imageFolder.isEmpty()) {
@ -67,76 +48,7 @@ QString VOrphanFile::fetchImagePath() const
} }
} }
bool VOrphanFile::save() bool VOrphanFile::useRelativeImageFolder() const
{
Q_ASSERT(m_opened);
Q_ASSERT(m_modifiable);
return VUtils::writeFileToDisk(fetchPath(), m_content);
}
void VOrphanFile::setName(const QString & /* p_name */)
{
V_ASSERT(false);
}
VDirectory *VOrphanFile::getDirectory()
{
return NULL;
}
const VDirectory *VOrphanFile::getDirectory() const
{
return NULL;
}
QString VOrphanFile::getNotebookName() const
{
return m_notebookName;
}
void VOrphanFile::setNotebookName(const QString &p_notebook)
{
m_notebookName = p_notebook;
}
VNotebook *VOrphanFile::getNotebook()
{
return NULL;
}
void VOrphanFile::setContent(const QString & p_content)
{
m_content = p_content;
}
bool VOrphanFile::isInternalImageFolder(const QString &p_path) const
{
return VUtils::equalPath(VUtils::basePathFromPath(p_path),
fetchBasePath())
|| VUtils::equalPath(p_path, fetchImagePath());
}
bool VOrphanFile::rename(const QString &p_name)
{
QDir dir(fetchBasePath());
if (!dir.rename(m_name, p_name)) {
qWarning() << "fail to rename note" << m_name << "to" << p_name << "in disk";
return false;
}
m_name = p_name;
m_path = dir.filePath(m_name);
return true;
}
void VOrphanFile::setImageFolder(const QString &p_path)
{
qDebug() << "orphan file" << fetchPath() << "image folder"
<< m_imageFolder << "->" << p_path;
m_imageFolder = p_path;
}
bool VOrphanFile::isRelativeImageFolder() const
{ {
QString folder = m_imageFolder; QString folder = m_imageFolder;
if (m_imageFolder.isEmpty()) { if (m_imageFolder.isEmpty()) {

View File

@ -3,78 +3,65 @@
#include "vfile.h" #include "vfile.h"
// VOrphanFile is file not belong to any notebooks or directories. // VOrphanFile is a file not belonging to any notebooks or directories.
// Such as external files, system files.
// It uses the file path to locate and identify a file.
class VOrphanFile : public VFile class VOrphanFile : public VFile
{ {
Q_OBJECT Q_OBJECT
public: public:
VOrphanFile(const QString &p_path, QObject *p_parent, VOrphanFile(QObject *p_parent,
bool p_modifiable, bool p_systemFile = false); const QString &p_path,
bool p_modifiable,
bool p_systemFile = false);
bool open() Q_DECL_OVERRIDE;
QString fetchPath() const Q_DECL_OVERRIDE; QString fetchPath() const Q_DECL_OVERRIDE;
QString fetchRelativePath() const Q_DECL_OVERRIDE;
QString fetchBasePath() const Q_DECL_OVERRIDE; QString fetchBasePath() const Q_DECL_OVERRIDE;
VDirectory *getDirectory() Q_DECL_OVERRIDE;
const VDirectory *getDirectory() const Q_DECL_OVERRIDE;
QString getNotebookName() const Q_DECL_OVERRIDE;
void setNotebookName(const QString &p_notebook); QString fetchImageFolderPath() const Q_DECL_OVERRIDE;
VNotebook *getNotebook() Q_DECL_OVERRIDE; // Whether use a relative image folder.
bool useRelativeImageFolder() const Q_DECL_OVERRIDE;
// Rename file.
bool rename(const QString &p_name) Q_DECL_OVERRIDE;
void setImageFolder(const QString &p_path);
const QString getImageFolder() const;
// Whether the image folder is a relative path.
bool isRelativeImageFolder() const Q_DECL_OVERRIDE;
// Return the image folder part in an image link. // Return the image folder part in an image link.
QString getImageFolderInLink() const Q_DECL_OVERRIDE; QString getImageFolderInLink() const Q_DECL_OVERRIDE;
// Return image folder config.
const QString getImageFolder() const;
// Set the image folder config.
void setImageFolder(const QString &p_path);
bool isSystemFile() const; bool isSystemFile() const;
private: private:
bool save() Q_DECL_OVERRIDE; // Full path of this file.
void setName(const QString &p_name) Q_DECL_OVERRIDE;
QString fetchImagePath() const Q_DECL_OVERRIDE;
void setContent(const QString &p_content) Q_DECL_OVERRIDE;
bool isInternalImageFolder(const QString &p_path) const Q_DECL_OVERRIDE;
static VFile *fromJson(const QJsonObject &p_json,
QObject *p_parent,
FileType p_type,
bool p_modifiable);
QJsonObject toConfigJson() const;
QString m_path; QString m_path;
QString m_notebookName;
// Image folder path of this file. // Image folder path of this file.
// It could be an absolute or relative path. // It could be an absolute or relative path.
// Empty to use the global default config. // Empty to use the global default config.
// Valid only within a session.
QString m_imageFolder; QString m_imageFolder;
// Whether it is a system internal file. // Whether it is a system internal file.
bool m_systemFile; bool m_systemFile;
friend class VDirectory;
}; };
inline bool VOrphanFile::isSystemFile() const
{
return m_systemFile;
}
inline const QString VOrphanFile::getImageFolder() const inline const QString VOrphanFile::getImageFolder() const
{ {
return m_imageFolder; return m_imageFolder;
} }
inline void VOrphanFile::setImageFolder(const QString &p_path)
{
m_imageFolder = p_path;
}
inline bool VOrphanFile::isSystemFile() const
{
return m_systemFile;
}
#endif // VORPHANFILE_H #endif // VORPHANFILE_H