diff --git a/src/dialog/vnewnotebookdialog.cpp b/src/dialog/vnewnotebookdialog.cpp index b5cba5b3..3047200c 100644 --- a/src/dialog/vnewnotebookdialog.cpp +++ b/src/dialog/vnewnotebookdialog.cpp @@ -198,13 +198,6 @@ void VNewNotebookDialog::showEvent(QShowEvent *event) void VNewNotebookDialog::handleInputChanged() { - QString warnText = tr("WARNING: 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("INFO: 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("INFO: 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("WARNING: 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; diff --git a/src/vdirectory.cpp b/src/vdirectory.cpp index 17cb1f1c..82f3321c 100644 --- a/src/vdirectory.cpp +++ b/src/vdirectory.cpp @@ -740,3 +740,65 @@ QList 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 &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 &files = ret->getFiles(); + QDateTime dateTime = QDateTime::currentDateTimeUtc(); + QList 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; +} diff --git a/src/vdirectory.h b/src/vdirectory.h index 5c431540..52a9700f 100644 --- a/src/vdirectory.h +++ b/src/vdirectory.h @@ -68,6 +68,7 @@ public: QString *p_errMsg = NULL); const QVector &getSubDirs() const; + QVector &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 &getFiles() const; + + QVector &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::getSubDirs() const return m_subDirs; } +inline QVector &VDirectory::getSubDirs() +{ + return m_subDirs; +} + inline const QString &VDirectory::getName() const { return m_name; @@ -203,6 +217,11 @@ inline const QVector &VDirectory::getFiles() const return m_files; } +inline QVector &VDirectory::getFiles() +{ + return m_files; +} + inline QString VDirectory::getNotebookName() const { return m_notebook->getName(); diff --git a/src/vnotebook.cpp b/src/vnotebook.cpp index 227defcc..11b5736e 100644 --- a/src/vnotebook.cpp +++ b/src/vnotebook.cpp @@ -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 &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; +} diff --git a/src/vnotebook.h b/src/vnotebook.h index 5d94d13e..891367bf 100644 --- a/src/vnotebook.h +++ b/src/vnotebook.h @@ -111,6 +111,14 @@ public: QList 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; diff --git a/src/vnotebookselector.cpp b/src/vnotebookselector.cpp index 24d6bcd8..c1f50d42 100644 --- a/src/vnotebookselector.cpp +++ b/src/vnotebookselector.cpp @@ -1,7 +1,6 @@ #include "vnotebookselector.h" #include #include -#include #include #include #include @@ -10,6 +9,7 @@ #include #include #include + #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 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; } diff --git a/src/vnotebookselector.h b/src/vnotebookselector.h index 35605078..43985a2c 100644 --- a/src/vnotebookselector.h +++ b/src/vnotebookselector.h @@ -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.