VNotebook: refine logics of building notebook from existing file structures

This commit is contained in:
Le Tan 2018-08-05 22:41:42 +08:00
parent 09c610e3a9
commit 2298338094
7 changed files with 178 additions and 58 deletions

View File

@ -198,13 +198,6 @@ void VNewNotebookDialog::showEvent(QShowEvent *event)
void VNewNotebookDialog::handleInputChanged()
{
QString warnText = tr("<span style=\"%1\">WARNING</span>: The folder chosen is NOT empty! "
"It is highly recommended to use an EMPTY and EXCLUSIVE folder for a new notebook.")
.arg(g_config->c_warningTextStyle);
QString infoText = tr("<span style=\"%1\">INFO</span>: The folder chosen seems to be a root "
"folder of a notebook created by VNote before. "
"VNote will try to import it by reading the configuration file.")
.arg("font-weight:bold;");
bool pathOk = false;
bool configExist = false;
bool showWarnLabel = false;
@ -236,20 +229,25 @@ void VNewNotebookDialog::handleInputChanged()
// Folder is not empty.
configExist = VConfigManager::directoryConfigExist(path);
if (configExist) {
QString infoText = tr("<span style=\"%1\">INFO</span>: The folder chosen seems to be a root "
"folder of a notebook created by VNote before. "
"VNote will try to import it by reading the configuration file.")
.arg("font-weight:bold;");
m_warnLabel->setText(infoText);
} else {
QString warnText = tr("<span style=\"%1\">WARNING</span>: The folder chosen is NOT empty! "
"VNote will try to create a new notebook and import existing files.")
"It is highly recommended to use an EMPTY and EXCLUSIVE folder for a new notebook. "
"If continue, VNote will try to create a notebook based on existing "
"folders and files recursively.")
.arg(g_config->c_warningTextStyle);
m_warnLabel->setText(warnText);
m_importExternalProject = true;
// If ok button is clicked, automatically create a configuration file
configExist = true;
}
showWarnLabel = true;
}
pathOk = true;
} else {
pathOk = true;

View File

@ -740,3 +740,65 @@ QList<QString> VDirectory::collectFiles()
return files;
}
VDirectory *VDirectory::buildDirectory(const QString &p_path,
VDirectory *p_parent,
QString *p_errMsg)
{
VDirectory *ret = new VDirectory(p_parent->getNotebook(),
p_parent,
VUtils::directoryNameFromPath(p_path),
QDateTime::currentDateTimeUtc());
QDir rootDir(p_path);
// Process all the folders.
QVector<VDirectory *> &subdirs = ret->getSubDirs();
QFileInfoList dirList = rootDir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot);
for (auto const & sub : dirList) {
VDirectory *dir = VDirectory::buildDirectory(sub.absoluteFilePath(),
ret,
p_errMsg);
if (dir) {
subdirs.append(dir);
}
}
// Process all the files.
QVector<VNoteFile *> &files = ret->getFiles();
QDateTime dateTime = QDateTime::currentDateTimeUtc();
QList<QString> suffixes = g_config->getDocSuffixes()[(int)DocType::Markdown];
QStringList filters;
for (auto const & suf : suffixes) {
filters << ("*." + suf);
}
QStringList fileList = rootDir.entryList(filters, QDir::Files);
for (auto const & fileName : fileList) {
VNoteFile *file = new VNoteFile(ret,
fileName,
FileType::Note,
true,
dateTime,
dateTime);
if (!file) {
VUtils::addErrMsg(p_errMsg, tr("Skip file %1.").arg(rootDir.absoluteFilePath(fileName)));
} else {
files.append(file);
}
}
if (subdirs.isEmpty() && files.isEmpty()) {
delete ret;
VUtils::addErrMsg(p_errMsg, tr("Skip folder %1.").arg(p_path));
return NULL;
}
if (!ret->writeToConfig()) {
delete ret;
VUtils::addErrMsg(p_errMsg, tr("Fail to write configuration of folder %1.").arg(p_path));
return NULL;
}
return ret;
}

View File

@ -68,6 +68,7 @@ public:
QString *p_errMsg = NULL);
const QVector<VDirectory *> &getSubDirs() const;
QVector<VDirectory *> &getSubDirs();
const QString &getName() const;
void setName(const QString &p_name);
@ -76,7 +77,11 @@ public:
const VDirectory *getParentDirectory() const;
VNotebook *getNotebook();
const VNotebook *getNotebook() const;
const QVector<VNoteFile *> &getFiles() const;
QVector<VNoteFile *> &getFiles();
QString fetchPath() const;
QString fetchBasePath() const;
QString fetchRelativePath() const;
@ -122,6 +127,10 @@ public:
bool p_skipRecycleBin = false,
QString *p_errMsg = NULL);
static VDirectory *buildDirectory(const QString &p_path,
VDirectory *p_parent,
QString *p_errMsg);
private:
// Get the path of @p_dir recursively
QString fetchPath(const VDirectory *p_dir) const;
@ -173,6 +182,11 @@ inline const QVector<VDirectory *> &VDirectory::getSubDirs() const
return m_subDirs;
}
inline QVector<VDirectory *> &VDirectory::getSubDirs()
{
return m_subDirs;
}
inline const QString &VDirectory::getName() const
{
return m_name;
@ -203,6 +217,11 @@ inline const QVector<VNoteFile *> &VDirectory::getFiles() const
return m_files;
}
inline QVector<VNoteFile *> &VDirectory::getFiles()
{
return m_files;
}
inline QString VDirectory::getNotebookName() const
{
return m_notebook->getName();

View File

@ -457,3 +457,43 @@ void VNotebook::removeTag(const QString &p_tag)
}
}
}
bool VNotebook::buildNotebook(const QString &p_name,
const QString &p_path,
const QString &p_imgFolder,
const QString &p_attachmentFolder,
QString *p_errMsg)
{
VNotebook *nb = new VNotebook(p_name, p_path);
nb->setImageFolder(p_imgFolder);
QString attachmentFolder = p_attachmentFolder;
if (p_attachmentFolder.isEmpty()) {
nb->setAttachmentFolder(g_config->getAttachmentFolder());
} else {
nb->setAttachmentFolder(p_attachmentFolder);
}
// Process all the folders.
QVector<VDirectory *> &subdirs = nb->getRootDir()->getSubDirs();
QDir rootDir(p_path);
QFileInfoList dirList = rootDir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot);
for (auto const & sub : dirList) {
VDirectory *dir = VDirectory::buildDirectory(sub.absoluteFilePath(),
nb->getRootDir(),
p_errMsg);
if (dir) {
subdirs.append(dir);
}
}
if (!nb->writeToConfig()) {
delete nb;
VUtils::addErrMsg(p_errMsg,
tr("Fail to write notebook configuration file."));
return false;
}
delete nb;
return true;
}

View File

@ -111,6 +111,14 @@ public:
QList<QString> collectFiles();
// Create configuration files recursively to build a notebook based on
// a external directory.
static bool buildNotebook(const QString &p_name,
const QString &p_path,
const QString &p_imgFolder,
const QString &p_attachmentFolder,
QString *p_errMsg = NULL);
private:
// Serialize current instance to json.
QJsonObject toConfigJson() const;

View File

@ -1,7 +1,6 @@
#include "vnotebookselector.h"
#include <QDebug>
#include <QJsonObject>
#include <QJsonArray>
#include <QListWidget>
#include <QAction>
#include <QMenu>
@ -10,6 +9,7 @@
#include <QLabel>
#include <QDesktopServices>
#include <QUrl>
#include "vnotebook.h"
#include "vconfigmanager.h"
#include "dialog/vnewnotebookdialog.h"
@ -119,46 +119,6 @@ int VNotebookSelector::itemIndexOfNotebook(const VNotebook *p_notebook) const
return -1;
}
void VNotebookSelector::createConfigFiles(const QString &p_path)
{
QDir root(p_path);
QStringList filters;
filters << "*.md" << "*.markdown";
QJsonObject dirJson;
dirJson[DirConfig::c_version] = "1";
dirJson[DirConfig::c_createdTime] = QDateTime::currentDateTime().toString(Qt::ISODate);
QJsonArray subDirs;
QJsonArray files;
QFileInfoList dirInfoList = root.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
QFileInfoList fileInfoList = root.entryInfoList(filters,QDir::Files);
for(const QFileInfo &dirInfo : dirInfoList) {
const QString dirname = dirInfo.fileName();
if (dirname != "_v_recycle_bin") {
QJsonObject item;
item[DirConfig::c_name] = dirname;
subDirs.append(item);
createConfigFiles(dirInfo.absoluteFilePath());
}
}
for(const QFileInfo &fileInfo : fileInfoList) {
QJsonObject item;
item[DirConfig::c_createdTime] = fileInfo.created().toString(Qt::ISODate);
item[DirConfig::c_name] = fileInfo.fileName();
files.append(item);
}
dirJson[DirConfig::c_subDirectories] = subDirs;
dirJson[DirConfig::c_files] = files;
g_config->writeDirectoryConfig(p_path,dirJson);
}
void VNotebookSelector::insertAddNotebookItem()
{
QListWidgetItem *item = new QListWidgetItem();
@ -230,6 +190,9 @@ bool VNotebookSelector::newNotebook()
info += "\n";
info += tr("* A previously created notebook could be imported into VNote "
"by choosing its root folder.");
info += "\n";
info += tr("* When a non-empty folder is chosen, VNote will create a notebook "
"based on the folders and files in it recursively.");
// Use empty default name and path to let the dialog to auto generate a name
// under the default VNote notebook folder.
@ -240,18 +203,51 @@ bool VNotebookSelector::newNotebook()
m_notebooks,
this);
if (dialog.exec() == QDialog::Accepted) {
bool isImport = dialog.isImportExistingNotebook();
if(dialog.isImportExternalProject()) {
createConfigFiles(dialog.getPathInput());
QString msg;
bool ret = VNotebook::buildNotebook(dialog.getNameInput(),
dialog.getPathInput(),
dialog.getImageFolder(),
dialog.getAttachmentFolder(),
&msg);
QList<QString> suffixes = g_config->getDocSuffixes()[(int)DocType::Markdown];
QString sufs;
for (auto const & suf : suffixes) {
if (sufs.isEmpty()) {
sufs = "*." + suf;
} else {
sufs += ",*." + suf;
}
}
QString info = ret ? tr("Successfully build notebook recursively (%1).").arg(sufs)
: tr("Fail to build notebook recursively.");
if (!ret || !msg.isEmpty()) {
VUtils::showMessage(ret ? QMessageBox::Information : QMessageBox::Warning,
ret ? tr("Information") : tr("Warning"),
info,
msg,
QMessageBox::Ok,
QMessageBox::Ok,
this);
}
if (!ret) {
return false;
}
isImport = true;
}
createNotebook(dialog.getNameInput(),
dialog.getPathInput(),
dialog.isImportExistingNotebook(),
isImport,
dialog.getImageFolder(),
dialog.getAttachmentFolder());
emit notebookCreated(dialog.getNameInput(), dialog.isImportExistingNotebook());
emit notebookCreated(dialog.getNameInput(), isImport);
return true;
}

View File

@ -71,9 +71,6 @@ private:
// Return the item index of @p_notebook.
int itemIndexOfNotebook(const VNotebook *p_notebook) const;
// Recursively create config files
void createConfigFiles(const QString &p_path);
// If @p_import is true, we will use the existing config file.
// If @p_imageFolder is empty, we will use the global one.
// If @p_attachmentFolder is empty, we will use the global one.