mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-06 06:19:52 +08:00
VNotebook: refine logics of building notebook from existing file structures
This commit is contained in:
parent
09c610e3a9
commit
2298338094
@ -198,13 +198,6 @@ void VNewNotebookDialog::showEvent(QShowEvent *event)
|
|||||||
|
|
||||||
void VNewNotebookDialog::handleInputChanged()
|
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 pathOk = false;
|
||||||
bool configExist = false;
|
bool configExist = false;
|
||||||
bool showWarnLabel = false;
|
bool showWarnLabel = false;
|
||||||
@ -236,20 +229,25 @@ void VNewNotebookDialog::handleInputChanged()
|
|||||||
// Folder is not empty.
|
// Folder is not empty.
|
||||||
configExist = VConfigManager::directoryConfigExist(path);
|
configExist = VConfigManager::directoryConfigExist(path);
|
||||||
if (configExist) {
|
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);
|
m_warnLabel->setText(infoText);
|
||||||
} else {
|
} else {
|
||||||
QString warnText = tr("<span style=\"%1\">WARNING</span>: The folder chosen is NOT empty! "
|
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);
|
.arg(g_config->c_warningTextStyle);
|
||||||
m_warnLabel->setText(warnText);
|
m_warnLabel->setText(warnText);
|
||||||
|
|
||||||
m_importExternalProject = true;
|
m_importExternalProject = true;
|
||||||
// If ok button is clicked, automatically create a configuration file
|
|
||||||
configExist = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
showWarnLabel = true;
|
showWarnLabel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pathOk = true;
|
pathOk = true;
|
||||||
} else {
|
} else {
|
||||||
pathOk = true;
|
pathOk = true;
|
||||||
|
@ -740,3 +740,65 @@ QList<QString> VDirectory::collectFiles()
|
|||||||
|
|
||||||
return files;
|
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;
|
||||||
|
}
|
||||||
|
@ -68,6 +68,7 @@ public:
|
|||||||
QString *p_errMsg = NULL);
|
QString *p_errMsg = NULL);
|
||||||
|
|
||||||
const QVector<VDirectory *> &getSubDirs() const;
|
const QVector<VDirectory *> &getSubDirs() const;
|
||||||
|
QVector<VDirectory *> &getSubDirs();
|
||||||
|
|
||||||
const QString &getName() const;
|
const QString &getName() const;
|
||||||
void setName(const QString &p_name);
|
void setName(const QString &p_name);
|
||||||
@ -76,7 +77,11 @@ public:
|
|||||||
const VDirectory *getParentDirectory() const;
|
const VDirectory *getParentDirectory() const;
|
||||||
VNotebook *getNotebook();
|
VNotebook *getNotebook();
|
||||||
const VNotebook *getNotebook() const;
|
const VNotebook *getNotebook() const;
|
||||||
|
|
||||||
const QVector<VNoteFile *> &getFiles() const;
|
const QVector<VNoteFile *> &getFiles() const;
|
||||||
|
|
||||||
|
QVector<VNoteFile *> &getFiles();
|
||||||
|
|
||||||
QString fetchPath() const;
|
QString fetchPath() const;
|
||||||
QString fetchBasePath() const;
|
QString fetchBasePath() const;
|
||||||
QString fetchRelativePath() const;
|
QString fetchRelativePath() const;
|
||||||
@ -122,6 +127,10 @@ public:
|
|||||||
bool p_skipRecycleBin = false,
|
bool p_skipRecycleBin = false,
|
||||||
QString *p_errMsg = NULL);
|
QString *p_errMsg = NULL);
|
||||||
|
|
||||||
|
static VDirectory *buildDirectory(const QString &p_path,
|
||||||
|
VDirectory *p_parent,
|
||||||
|
QString *p_errMsg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Get the path of @p_dir recursively
|
// Get the path of @p_dir recursively
|
||||||
QString fetchPath(const VDirectory *p_dir) const;
|
QString fetchPath(const VDirectory *p_dir) const;
|
||||||
@ -173,6 +182,11 @@ inline const QVector<VDirectory *> &VDirectory::getSubDirs() const
|
|||||||
return m_subDirs;
|
return m_subDirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline QVector<VDirectory *> &VDirectory::getSubDirs()
|
||||||
|
{
|
||||||
|
return m_subDirs;
|
||||||
|
}
|
||||||
|
|
||||||
inline const QString &VDirectory::getName() const
|
inline const QString &VDirectory::getName() const
|
||||||
{
|
{
|
||||||
return m_name;
|
return m_name;
|
||||||
@ -203,6 +217,11 @@ inline const QVector<VNoteFile *> &VDirectory::getFiles() const
|
|||||||
return m_files;
|
return m_files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline QVector<VNoteFile *> &VDirectory::getFiles()
|
||||||
|
{
|
||||||
|
return m_files;
|
||||||
|
}
|
||||||
|
|
||||||
inline QString VDirectory::getNotebookName() const
|
inline QString VDirectory::getNotebookName() const
|
||||||
{
|
{
|
||||||
return m_notebook->getName();
|
return m_notebook->getName();
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -111,6 +111,14 @@ public:
|
|||||||
|
|
||||||
QList<QString> collectFiles();
|
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:
|
private:
|
||||||
// Serialize current instance to json.
|
// Serialize current instance to json.
|
||||||
QJsonObject toConfigJson() const;
|
QJsonObject toConfigJson() const;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include "vnotebookselector.h"
|
#include "vnotebookselector.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
@ -10,6 +9,7 @@
|
|||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include "vnotebook.h"
|
#include "vnotebook.h"
|
||||||
#include "vconfigmanager.h"
|
#include "vconfigmanager.h"
|
||||||
#include "dialog/vnewnotebookdialog.h"
|
#include "dialog/vnewnotebookdialog.h"
|
||||||
@ -119,46 +119,6 @@ int VNotebookSelector::itemIndexOfNotebook(const VNotebook *p_notebook) const
|
|||||||
return -1;
|
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()
|
void VNotebookSelector::insertAddNotebookItem()
|
||||||
{
|
{
|
||||||
QListWidgetItem *item = new QListWidgetItem();
|
QListWidgetItem *item = new QListWidgetItem();
|
||||||
@ -230,6 +190,9 @@ bool VNotebookSelector::newNotebook()
|
|||||||
info += "\n";
|
info += "\n";
|
||||||
info += tr("* A previously created notebook could be imported into VNote "
|
info += tr("* A previously created notebook could be imported into VNote "
|
||||||
"by choosing its root folder.");
|
"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
|
// Use empty default name and path to let the dialog to auto generate a name
|
||||||
// under the default VNote notebook folder.
|
// under the default VNote notebook folder.
|
||||||
@ -240,18 +203,51 @@ bool VNotebookSelector::newNotebook()
|
|||||||
m_notebooks,
|
m_notebooks,
|
||||||
this);
|
this);
|
||||||
if (dialog.exec() == QDialog::Accepted) {
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
|
bool isImport = dialog.isImportExistingNotebook();
|
||||||
if(dialog.isImportExternalProject()) {
|
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(),
|
createNotebook(dialog.getNameInput(),
|
||||||
dialog.getPathInput(),
|
dialog.getPathInput(),
|
||||||
dialog.isImportExistingNotebook(),
|
isImport,
|
||||||
dialog.getImageFolder(),
|
dialog.getImageFolder(),
|
||||||
dialog.getAttachmentFolder());
|
dialog.getAttachmentFolder());
|
||||||
|
|
||||||
emit notebookCreated(dialog.getNameInput(), dialog.isImportExistingNotebook());
|
emit notebookCreated(dialog.getNameInput(), isImport);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,9 +71,6 @@ private:
|
|||||||
// Return the item index of @p_notebook.
|
// Return the item index of @p_notebook.
|
||||||
int itemIndexOfNotebook(const VNotebook *p_notebook) const;
|
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_import is true, we will use the existing config file.
|
||||||
// If @p_imageFolder is empty, we will use the global one.
|
// If @p_imageFolder is empty, we will use the global one.
|
||||||
// If @p_attachmentFolder is empty, we will use the global one.
|
// If @p_attachmentFolder is empty, we will use the global one.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user