refactor logics about adding notebook

This commit is contained in:
Le Tan 2017-06-21 23:18:39 +08:00
parent 2734b8407c
commit 707814909a
11 changed files with 399 additions and 141 deletions

View File

@ -3,23 +3,26 @@
#include "vnewnotebookdialog.h" #include "vnewnotebookdialog.h"
#include "vconfigmanager.h" #include "vconfigmanager.h"
#include "utils/vutils.h" #include "utils/vutils.h"
#include "vnotebook.h"
extern VConfigManager vconfig; extern VConfigManager vconfig;
VNewNotebookDialog::VNewNotebookDialog(const QString &title, const QString &info, VNewNotebookDialog::VNewNotebookDialog(const QString &title, const QString &info,
const QString &defaultName, const QString &defaultPath, const QString &defaultName, const QString &defaultPath,
const QVector<VNotebook *> &p_notebooks,
QWidget *parent) QWidget *parent)
: QDialog(parent), infoLabel(NULL), : QDialog(parent), infoLabel(NULL),
title(title), info(info), defaultName(defaultName), defaultPath(defaultPath) title(title), info(info), defaultName(defaultName), defaultPath(defaultPath),
m_importNotebook(false), m_manualPath(false), m_manualName(false),
m_notebooks(p_notebooks)
{ {
setupUI(); setupUI();
connect(nameEdit, &QLineEdit::textChanged, this, &VNewNotebookDialog::enableOkButton); connect(nameEdit, &QLineEdit::textChanged, this, &VNewNotebookDialog::handleInputChanged);
connect(pathEdit, &QLineEdit::textChanged, this, &VNewNotebookDialog::handlePathChanged); connect(pathEdit, &QLineEdit::textChanged, this, &VNewNotebookDialog::handleInputChanged);
connect(browseBtn, &QPushButton::clicked, this, &VNewNotebookDialog::handleBrowseBtnClicked); connect(browseBtn, &QPushButton::clicked, this, &VNewNotebookDialog::handleBrowseBtnClicked);
enableOkButton(); handleInputChanged();
checkRootFolder(pathEdit->text());
} }
void VNewNotebookDialog::setupUI() void VNewNotebookDialog::setupUI()
@ -38,11 +41,6 @@ void VNewNotebookDialog::setupUI()
pathLabel->setBuddy(pathEdit); pathLabel->setBuddy(pathEdit);
browseBtn = new QPushButton(tr("&Browse")); browseBtn = new QPushButton(tr("&Browse"));
importCheck = new QCheckBox(tr("Import existing notebook"));
importCheck->setToolTip(tr("When checked, VNote will read the configuration file to import an existing notebook"));
connect(importCheck, &QCheckBox::stateChanged,
this, &VNewNotebookDialog::importCheckChanged);
QLabel *imageFolderLabel = new QLabel(tr("&Image folder:")); QLabel *imageFolderLabel = new QLabel(tr("&Image folder:"));
m_imageFolderEdit = new QLineEdit(); m_imageFolderEdit = new QLineEdit();
m_imageFolderEdit->setPlaceholderText(tr("Use global configuration (%1)") m_imageFolderEdit->setPlaceholderText(tr("Use global configuration (%1)")
@ -61,9 +59,13 @@ void VNewNotebookDialog::setupUI()
topLayout->addWidget(pathLabel, 1, 0); topLayout->addWidget(pathLabel, 1, 0);
topLayout->addWidget(pathEdit, 1, 1); topLayout->addWidget(pathEdit, 1, 1);
topLayout->addWidget(browseBtn, 1, 2); topLayout->addWidget(browseBtn, 1, 2);
topLayout->addWidget(importCheck, 2, 1); topLayout->addWidget(imageFolderLabel, 2, 0);
topLayout->addWidget(imageFolderLabel, 3, 0); topLayout->addWidget(m_imageFolderEdit, 2, 1);
topLayout->addWidget(m_imageFolderEdit, 3, 1);
// Warning label.
m_warnLabel = new QLabel();
m_warnLabel->setWordWrap(true);
m_warnLabel->hide();
// Ok is the default button. // Ok is the default button.
m_btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); m_btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
@ -73,14 +75,6 @@ void VNewNotebookDialog::setupUI()
QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok); QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok);
pathEdit->setMinimumWidth(okBtn->sizeHint().width() * 3); pathEdit->setMinimumWidth(okBtn->sizeHint().width() * 3);
// Warning label.
m_warnLabel = new QLabel(tr("<span style=\"%1\">WARNING</span>: The folder you choose is NOT empty! "
"It is highly recommended to use an EMPTY and EXCLUSIVE folder for a notebook. "
"Ignore this warning if you do want to import an existing VNote notebook folder.")
.arg(vconfig.c_warningTextStyle));
m_warnLabel->setWordWrap(true);
m_warnLabel->hide();
QVBoxLayout *mainLayout = new QVBoxLayout(this); QVBoxLayout *mainLayout = new QVBoxLayout(this);
if (infoLabel) { if (infoLabel) {
mainLayout->addWidget(infoLabel); mainLayout->addWidget(infoLabel);
@ -88,20 +82,13 @@ void VNewNotebookDialog::setupUI()
mainLayout->addLayout(topLayout); mainLayout->addLayout(topLayout);
mainLayout->addWidget(m_warnLabel); mainLayout->addWidget(m_warnLabel);
mainLayout->addWidget(m_btnBox); mainLayout->addWidget(m_btnBox);
// Will set the parent of above widgets properly. // Will set the parent of above widgets properly.
setLayout(mainLayout); setLayout(mainLayout);
mainLayout->setSizeConstraint(QLayout::SetFixedSize); mainLayout->setSizeConstraint(QLayout::SetFixedSize);
setWindowTitle(title); setWindowTitle(title);
} }
void VNewNotebookDialog::enableOkButton()
{
QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok);
okBtn->setEnabled(!pathEdit->text().isEmpty()
&& !nameEdit->text().isEmpty()
&& QDir(pathEdit->text()).exists());
}
QString VNewNotebookDialog::getNameInput() const QString VNewNotebookDialog::getNameInput() const
{ {
return nameEdit->text(); return nameEdit->text();
@ -109,27 +96,42 @@ QString VNewNotebookDialog::getNameInput() const
QString VNewNotebookDialog::getPathInput() const QString VNewNotebookDialog::getPathInput() const
{ {
return pathEdit->text(); return QDir::cleanPath(pathEdit->text());
} }
QString VNewNotebookDialog::getImageFolder() const QString VNewNotebookDialog::getImageFolder() const
{ {
return m_imageFolderEdit->text(); if (m_imageFolderEdit->isEnabled()) {
return m_imageFolderEdit->text();
} else {
return QString();
}
} }
void VNewNotebookDialog::handleBrowseBtnClicked() void VNewNotebookDialog::handleBrowseBtnClicked()
{ {
static QString defaultPath;
if (defaultPath.isEmpty()) {
defaultPath = vconfig.getVnoteNotebookFolderPath();
if (!QFileInfo::exists(defaultPath)) {
defaultPath = QDir::homePath();
}
}
QString dirPath = QFileDialog::getExistingDirectory(this, tr("Select Root Folder Of The Notebook"), QString dirPath = QFileDialog::getExistingDirectory(this, tr("Select Root Folder Of The Notebook"),
QDir::homePath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); defaultPath,
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (!dirPath.isEmpty()) { if (!dirPath.isEmpty()) {
m_manualPath = true;
pathEdit->setText(dirPath); pathEdit->setText(dirPath);
defaultPath = VUtils::basePathFromPath(dirPath);
} }
} }
bool VNewNotebookDialog::getImportCheck() const bool VNewNotebookDialog::isImportExistingNotebook() const
{ {
return importCheck->isChecked(); return m_importNotebook;
} }
void VNewNotebookDialog::showEvent(QShowEvent *event) void VNewNotebookDialog::showEvent(QShowEvent *event)
@ -138,38 +140,149 @@ void VNewNotebookDialog::showEvent(QShowEvent *event)
QDialog::showEvent(event); QDialog::showEvent(event);
} }
void VNewNotebookDialog::handlePathChanged(const QString &p_text) void VNewNotebookDialog::handleInputChanged()
{ {
enableOkButton(); QString warnText = tr("<span style=\"%1\">WARNING</span>: The folder chosen is NOT empty! "
checkRootFolder(p_text); "It is highly recommended to use an EMPTY and EXCLUSIVE folder for a new notebook.")
} .arg(vconfig.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;
void VNewNotebookDialog::importCheckChanged(int p_state) // User has input some texts.
{ if (pathEdit->isModified()) {
// If import existing notebook, disable setting new configs. m_manualPath = true;
bool checked = p_state == Qt::Checked;
m_imageFolderEdit->setEnabled(!checked);
}
void VNewNotebookDialog::checkRootFolder(const QString &p_path)
{
bool existConfig = false;
if (!p_path.isEmpty()) {
QDir dir(p_path);
QStringList files = dir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden);
if (!files.isEmpty()) {
m_warnLabel->show();
} else {
m_warnLabel->hide();
}
existConfig = VConfigManager::directoryConfigExist(p_path);
} else {
m_warnLabel->hide();
} }
importCheck->setChecked(existConfig); if (nameEdit->isModified()) {
importCheck->setEnabled(existConfig); m_manualName = true;
}
if (autoComplete()) {
return;
}
QString path = pathEdit->text();
if (!path.isEmpty()) {
if (QFileInfo::exists(path)) {
QDir dir(path);
QStringList files = dir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden);
if (!files.isEmpty()) {
// Folder is not empty.
configExist = VConfigManager::directoryConfigExist(path);
showWarnLabel = true;
}
} else {
pathOk = true;
}
}
if (configExist) {
pathOk = true;
m_warnLabel->setText(infoText);
} else {
m_warnLabel->setText(warnText);
}
// Try to validate if this is a legal path on the OS.
if (pathOk) {
pathOk = VUtils::checkPathLegal(path);
if (!pathOk) {
showWarnLabel = true;
QString tmp = tr("<span style=\"%1\">WARNING</span>: The path seems to be illegal. "
"Please choose another one.")
.arg(vconfig.c_warningTextStyle);
m_warnLabel->setText(tmp);
}
}
if (pathOk) {
// Check if this path has been in VNote.
int idx = -1;
path = QDir::cleanPath(path);
for (idx = 0; idx < m_notebooks.size(); ++idx) {
if (QDir::cleanPath(m_notebooks[idx]->getPath()) == path) {
break;
}
}
if (idx < m_notebooks.size()) {
pathOk = false;
showWarnLabel = true;
QString existText = tr("<span style=\"%1\">WARNING</span>: The folder chosen has already been a root folder "
"of existing notebook <span style=\"%2\">%3</span> in VNote.")
.arg(vconfig.c_warningTextStyle)
.arg(vconfig.c_dataTextStyle)
.arg(m_notebooks[idx]->getName());
m_warnLabel->setText(existText);
}
}
QString name = nameEdit->text();
bool nameOk = !name.isEmpty();
if (pathOk && nameOk) {
// Check if the name conflicts with existing notebook name.
int idx = -1;
for (idx = 0; idx < m_notebooks.size(); ++idx) {
if (m_notebooks[idx]->getName() == name) {
break;
}
}
if (idx < m_notebooks.size()) {
nameOk = false;
showWarnLabel = true;
QString nameConflictText = tr("<span style=\"%1\">WARNING</span>: Name already exists. "
"Please choose another name.")
.arg(vconfig.c_warningTextStyle);
m_warnLabel->setText(nameConflictText);
}
}
m_warnLabel->setVisible(showWarnLabel);
m_importNotebook = configExist;
m_imageFolderEdit->setEnabled(!m_importNotebook);
QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok);
okBtn->setEnabled(nameOk && pathOk);
}
bool VNewNotebookDialog::autoComplete()
{
if (m_manualPath) {
return false;
}
QString vnoteFolder = vconfig.getVnoteNotebookFolderPath();
QString pathText = pathEdit->text();
if (!pathText.isEmpty() && vnoteFolder != VUtils::basePathFromPath(pathText)) {
return false;
}
bool ret = false;
QString nameText = nameEdit->text();
if (nameText.isEmpty()) {
if (m_manualName) {
return false;
}
// Get a folder name under vnoteFolder and set it as the name of the notebook.
QString name = "vnotebook";
name = VUtils::getFileNameWithSequence(vnoteFolder, name);
nameEdit->setText(name);
ret = true;
} else {
// Use the name as the folder name under vnoteFolder.
QString autoPath = QDir::cleanPath(QDir(vnoteFolder).filePath(nameText));
if (autoPath != pathText) {
pathEdit->setText(autoPath);
ret = true;
}
}
return ret;
} }

View File

@ -2,43 +2,57 @@
#define VNEWNOTEBOOKDIALOG_H #define VNEWNOTEBOOKDIALOG_H
#include <QDialog> #include <QDialog>
#include <QVector>
class QLabel; class QLabel;
class QLineEdit; class QLineEdit;
class QPushButton; class QPushButton;
class QString; class QString;
class QCheckBox;
class QDialogButtonBox; class QDialogButtonBox;
class VNotebook;
class VNewNotebookDialog : public QDialog class VNewNotebookDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
VNewNotebookDialog(const QString &title, const QString &info, const QString &defaultName, VNewNotebookDialog(const QString &title, const QString &info, const QString &defaultName,
const QString &defaultPath, QWidget *parent = 0); const QString &defaultPath, const QVector<VNotebook *> &p_notebooks,
QWidget *parent = 0);
QString getNameInput() const; QString getNameInput() const;
QString getPathInput() const; QString getPathInput() const;
bool getImportCheck() const;
// Whether import existing notebook by reading the config file.
bool isImportExistingNotebook() const;
// Get the custom image folder for this notebook.
// Empty string indicates using global config.
QString getImageFolder() const; QString getImageFolder() const;
private slots: private slots:
void enableOkButton();
void handleBrowseBtnClicked(); void handleBrowseBtnClicked();
void handlePathChanged(const QString &p_text);
void importCheckChanged(int p_state); // Handle the change of the name and path input.
void handleInputChanged();
protected: protected:
void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; void showEvent(QShowEvent *event) Q_DECL_OVERRIDE;
private: private:
void setupUI(); void setupUI();
// Should be called before enableOkButton() when path changed.
void checkRootFolder(const QString &p_path); void checkRootFolder(const QString &p_path);
// Try to figure out name and path.
// Returns true if name or path is modified.
bool autoComplete();
QLabel *infoLabel; QLabel *infoLabel;
QLabel *nameLabel; QLabel *nameLabel;
QLineEdit *nameEdit; QLineEdit *nameEdit;
QLineEdit *pathEdit; QLineEdit *pathEdit;
QCheckBox *importCheck;
QPushButton *browseBtn; QPushButton *browseBtn;
QLabel *m_warnLabel; QLabel *m_warnLabel;
QLineEdit *m_imageFolderEdit; QLineEdit *m_imageFolderEdit;
@ -48,6 +62,18 @@ private:
QString info; QString info;
QString defaultName; QString defaultName;
QString defaultPath; QString defaultPath;
// Whether import existing notebook config file.
bool m_importNotebook;
// True if user has change the content of the path edit.
bool m_manualPath;
// True if user has change the content of the name edit.
bool m_manualName;
// All existing notebooks in VNote.
const QVector<VNotebook *> &m_notebooks;
}; };
#endif // VNEWNOTEBOOKDIALOG_H #endif // VNEWNOTEBOOKDIALOG_H

View File

@ -6,16 +6,20 @@
extern VConfigManager vconfig; extern VConfigManager vconfig;
VNotebookInfoDialog::VNotebookInfoDialog(const QString &p_title, const QString &p_info, VNotebookInfoDialog::VNotebookInfoDialog(const QString &p_title,
const VNotebook *p_notebook, QWidget *p_parent) const QString &p_info,
: QDialog(p_parent), m_notebook(p_notebook), m_infoLabel(NULL) const VNotebook *p_notebook,
const QVector<VNotebook *> &p_notebooks,
QWidget *p_parent)
: QDialog(p_parent), m_notebook(p_notebook), m_infoLabel(NULL),
m_notebooks(p_notebooks)
{ {
setupUI(p_title, p_info); setupUI(p_title, p_info);
connect(m_nameEdit, &QLineEdit::textChanged, connect(m_nameEdit, &QLineEdit::textChanged,
this, &VNotebookInfoDialog::enableOkButton); this, &VNotebookInfoDialog::handleInputChanged);
enableOkButton(); handleInputChanged();
} }
void VNotebookInfoDialog::setupUI(const QString &p_title, const QString &p_info) void VNotebookInfoDialog::setupUI(const QString &p_title, const QString &p_info)
@ -46,10 +50,16 @@ void VNotebookInfoDialog::setupUI(const QString &p_title, const QString &p_info)
QValidator *validator = new QRegExpValidator(QRegExp(VUtils::c_fileNameRegExp), m_imageFolderEdit); QValidator *validator = new QRegExpValidator(QRegExp(VUtils::c_fileNameRegExp), m_imageFolderEdit);
m_imageFolderEdit->setValidator(validator); m_imageFolderEdit->setValidator(validator);
// Warning label.
m_warnLabel = new QLabel();
m_warnLabel->setWordWrap(true);
m_warnLabel->hide();
QFormLayout *topLayout = new QFormLayout(); QFormLayout *topLayout = new QFormLayout();
topLayout->addRow(nameLabel, m_nameEdit); topLayout->addRow(nameLabel, m_nameEdit);
topLayout->addRow(pathLabel, m_pathEdit); topLayout->addRow(pathLabel, m_pathEdit);
topLayout->addRow(imageFolderLabel, m_imageFolderEdit); topLayout->addRow(imageFolderLabel, m_imageFolderEdit);
topLayout->addRow(m_warnLabel);
// Ok is the default button. // Ok is the default button.
m_btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); m_btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
@ -63,17 +73,44 @@ void VNotebookInfoDialog::setupUI(const QString &p_title, const QString &p_info)
if (m_infoLabel) { if (m_infoLabel) {
mainLayout->addWidget(m_infoLabel); mainLayout->addWidget(m_infoLabel);
} }
mainLayout->addLayout(topLayout); mainLayout->addLayout(topLayout);
mainLayout->addWidget(m_btnBox); mainLayout->addWidget(m_btnBox);
setLayout(mainLayout); setLayout(mainLayout);
mainLayout->setSizeConstraint(QLayout::SetFixedSize); mainLayout->setSizeConstraint(QLayout::SetFixedSize);
setWindowTitle(p_title); setWindowTitle(p_title);
} }
void VNotebookInfoDialog::enableOkButton() void VNotebookInfoDialog::handleInputChanged()
{ {
QString name = m_nameEdit->text();
bool nameOk = !name.isEmpty();
bool showWarnLabel = false;
if (nameOk && name != m_notebook->getName()) {
// Check if the name conflicts with existing notebook name.
int idx = -1;
for (idx = 0; idx < m_notebooks.size(); ++idx) {
if (m_notebooks[idx]->getName() == name) {
break;
}
}
if (idx < m_notebooks.size()) {
nameOk = false;
showWarnLabel = true;
QString nameConflictText = tr("<span style=\"%1\">WARNING</span>: Name already exists. "
"Please choose another name.")
.arg(vconfig.c_warningTextStyle);
m_warnLabel->setText(nameConflictText);
}
}
m_warnLabel->setVisible(showWarnLabel);
QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok); QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok);
okBtn->setEnabled(!m_nameEdit->text().isEmpty()); okBtn->setEnabled(nameOk);
} }
QString VNotebookInfoDialog::getName() const QString VNotebookInfoDialog::getName() const

View File

@ -2,6 +2,7 @@
#define VNOTEBOOKINFODIALOG_H #define VNOTEBOOKINFODIALOG_H
#include <QDialog> #include <QDialog>
#include <QVector>
class QLabel; class QLabel;
class QLineEdit; class QLineEdit;
@ -13,14 +14,21 @@ class VNotebookInfoDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
VNotebookInfoDialog(const QString &p_title, const QString &p_info, VNotebookInfoDialog(const QString &p_title,
const VNotebook *p_notebook, QWidget *p_parent = 0); const QString &p_info,
const VNotebook *p_notebook,
const QVector<VNotebook *> &p_notebooks,
QWidget *p_parent = 0);
QString getName() const; QString getName() const;
// Get the custom image folder for this notebook.
// Empty string indicates using global config.
QString getImageFolder() const; QString getImageFolder() const;
private slots: private slots:
void enableOkButton(); // Handle the change of the name and path input.
void handleInputChanged();
protected: protected:
void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE;
@ -34,7 +42,9 @@ private:
QLineEdit *m_nameEdit; QLineEdit *m_nameEdit;
QLineEdit *m_pathEdit; QLineEdit *m_pathEdit;
QLineEdit *m_imageFolderEdit; QLineEdit *m_imageFolderEdit;
QLabel *m_warnLabel;
QDialogButtonBox *m_btnBox; QDialogButtonBox *m_btnBox;
const QVector<VNotebook *> &m_notebooks;
}; };
#endif // VNOTEBOOKINFODIALOG_H #endif // VNOTEBOOKINFODIALOG_H

View File

@ -17,6 +17,9 @@
#include <QLocale> #include <QLocale>
#include <QPushButton> #include <QPushButton>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QValidator>
#include <QRegExpValidator>
#include <QRegExp>
#include "vfile.h" #include "vfile.h"
#include "vnote.h" #include "vnote.h"
@ -552,3 +555,63 @@ QString VUtils::generateHtmlTemplate(MarkdownConverterType p_conType, bool p_exp
return htmlTemplate; return htmlTemplate;
} }
QString VUtils::getFileNameWithSequence(const QString &p_directory,
const QString &p_baseFileName)
{
QDir dir(p_directory);
if (!dir.exists() || !dir.exists(p_baseFileName)) {
return p_baseFileName;
}
// Append a sequence.
QFileInfo fi(p_baseFileName);
QString baseName = fi.baseName();
QString suffix = fi.completeSuffix();
int seq = 1;
QString fileName;
do {
fileName = QString("%1_%2").arg(baseName).arg(QString::number(seq++), 3, '0');
if (!suffix.isEmpty()) {
fileName = fileName + "." + suffix;
}
} while (dir.exists(fileName));
return fileName;
}
bool VUtils::checkPathLegal(const QString &p_path)
{
// Ensure every part of the p_path is a valid file name until we come to
// an existing parent directory.
if (p_path.isEmpty()) {
return false;
}
if (QFileInfo::exists(p_path)) {
return true;
}
bool ret = false;
int pos;
QString basePath = basePathFromPath(p_path);
QString fileName = fileNameFromPath(p_path);
QValidator *validator = new QRegExpValidator(QRegExp(c_fileNameRegExp));
while (!fileName.isEmpty()) {
QValidator::State validFile = validator->validate(fileName, pos);
if (validFile != QValidator::Acceptable) {
break;
}
if (QFileInfo::exists(basePath)) {
ret = true;
break;
}
fileName = fileNameFromPath(basePath);
basePath = basePathFromPath(basePath);
}
delete validator;
return ret;
}

View File

@ -97,6 +97,15 @@ public:
// Generate HTML template. // Generate HTML template.
static QString generateHtmlTemplate(MarkdownConverterType p_conType, bool p_exportPdf); static QString generateHtmlTemplate(MarkdownConverterType p_conType, bool p_exportPdf);
// Get an available file name in @p_directory with base @p_baseFileName.
// If there already exists a file named @p_baseFileName, try to add sequence
// suffix to the name, such as _001.
static QString getFileNameWithSequence(const QString &p_directory,
const QString &p_baseFileName);
// Try to check if @p_path is legal.
static bool checkPathLegal(const QString &p_path);
// 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

@ -26,6 +26,7 @@ const QString VConfigManager::c_warningTextStyle = QString("color: red; font: bo
const QString VConfigManager::c_dataTextStyle = QString("font: bold"); const QString VConfigManager::c_dataTextStyle = QString("font: bold");
const QString VConfigManager::c_dangerBtnStyle = QString("QPushButton {color: #fff; border-color: #d43f3a; background-color: #d9534f;}" const QString VConfigManager::c_dangerBtnStyle = QString("QPushButton {color: #fff; border-color: #d43f3a; background-color: #d9534f;}"
"QPushButton::hover {color: #fff; border-color: #ac2925; background-color: #c9302c;}"); "QPushButton::hover {color: #fff; border-color: #ac2925; background-color: #c9302c;}");
const QString VConfigManager::c_vnoteNotebookFolderName = QString("vnote_notebooks");
VConfigManager::VConfigManager() VConfigManager::VConfigManager()
: userSettings(NULL), defaultSettings(NULL) : userSettings(NULL), defaultSettings(NULL)
@ -654,3 +655,8 @@ void VConfigManager::setEditorStyle(const QString &p_style)
setConfigToSettings("global", "editor_style", m_editorStyle); setConfigToSettings("global", "editor_style", m_editorStyle);
updateEditStyle(); updateEditStyle();
} }
QString VConfigManager::getVnoteNotebookFolderPath()
{
return QDir::home().filePath(c_vnoteNotebookFolderName);
}

View File

@ -44,6 +44,9 @@ public:
static QString getLogFilePath(); static QString getLogFilePath();
// Get the path of the folder used to store default notebook.
static QString getVnoteNotebookFolderPath();
// Constants // Constants
static const QString orgName; static const QString orgName;
static const QString appName; static const QString appName;
@ -362,6 +365,9 @@ private:
static const QString c_defaultMdhlFile; static const QString c_defaultMdhlFile;
static const QString c_solarizedDarkMdhlFile; static const QString c_solarizedDarkMdhlFile;
static const QString c_solarizedLightMdhlFile; static const QString c_solarizedLightMdhlFile;
// The folder name to store all notebooks if user does not specify one.
static const QString c_vnoteNotebookFolderName;
}; };

View File

@ -107,6 +107,9 @@ VNotebook *VNotebook::createNotebook(const QString &p_name, const QString &p_pat
QObject *p_parent) QObject *p_parent)
{ {
VNotebook *nb = new VNotebook(p_name, p_path, p_parent); VNotebook *nb = new VNotebook(p_name, p_path, p_parent);
// If @p_imageFolder is empty, it will report global configured folder as
// its image folder.
nb->setImageFolder(p_imageFolder); nb->setImageFolder(p_imageFolder);
// Check if there alread exists a config file. // Check if there alread exists a config file.
@ -116,6 +119,8 @@ VNotebook *VNotebook::createNotebook(const QString &p_name, const QString &p_pat
return nb; return nb;
} }
VUtils::makePath(p_path);
if (!nb->writeToConfig()) { if (!nb->writeToConfig()) {
delete nb; delete nb;
return NULL; return NULL;

View File

@ -168,41 +168,24 @@ bool VNotebookSelector::newNotebook()
info += tr("The root folder should be used EXCLUSIVELY by VNote and " info += tr("The root folder should be used EXCLUSIVELY by VNote and "
"it is recommended to be EMPTY."); "it is recommended to be EMPTY.");
QString defaultName("new_notebook"); QString defaultName;
QString defaultPath; QString defaultPath;
// Use empty default name and path to let the dialog to auto generate a name
// under the default VNote notebook folder.
VNewNotebookDialog dialog(tr("Add Notebook"), info, defaultName, VNewNotebookDialog dialog(tr("Add Notebook"), info, defaultName,
defaultPath, this); defaultPath, m_notebooks, this);
do { if (dialog.exec() == QDialog::Accepted) {
if (dialog.exec() == QDialog::Accepted) { createNotebook(dialog.getNameInput(),
QString name = dialog.getNameInput(); dialog.getPathInput(),
QString path = dialog.getPathInput(); dialog.isImportExistingNotebook(),
if (findNotebook(name)) { dialog.getImageFolder());
VUtils::showMessage(QMessageBox::Warning, tr("Warning"), return true;
tr("Name already exists. Please choose another name."), "", }
QMessageBox::Ok, QMessageBox::Ok, this);
continue;
}
createNotebook(name, path, dialog.getImportCheck(), dialog.getImageFolder());
return true;
}
break;
} while (true);
return false; return false;
} }
VNotebook *VNotebookSelector::findNotebook(const QString &p_name)
{
for (int i = 0; i < m_notebooks.size(); ++i) {
if (m_notebooks[i]->getName() == p_name) {
return m_notebooks[i];
}
}
return NULL;
}
void VNotebookSelector::createNotebook(const QString &p_name, void VNotebookSelector::createNotebook(const QString &p_name,
const QString &p_path, const QString &p_path,
bool p_import, bool p_import,
@ -210,6 +193,15 @@ void VNotebookSelector::createNotebook(const QString &p_name,
{ {
VNotebook *nb = VNotebook::createNotebook(p_name, p_path, p_import, VNotebook *nb = VNotebook::createNotebook(p_name, p_path, p_import,
p_imageFolder, m_vnote); p_imageFolder, m_vnote);
if (!nb) {
VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
tr("Fail to create notebook "
"<span style=\"%1\">%2</span> in <span style=\"%1\">%3</span>.")
.arg(vconfig.c_dataTextStyle).arg(p_name).arg(p_path), "",
QMessageBox::Ok, QMessageBox::Ok, this);
return;
}
m_notebooks.append(nb); m_notebooks.append(nb);
vconfig.setNotebooks(m_notebooks); vconfig.setNotebooks(m_notebooks);
@ -293,38 +285,29 @@ void VNotebookSelector::editNotebookInfo()
VNotebook *notebook = getNotebookFromComboIndex(index); VNotebook *notebook = getNotebookFromComboIndex(index);
QString curName = notebook->getName(); QString curName = notebook->getName();
VNotebookInfoDialog dialog(tr("Notebook Information"), "", notebook, this); VNotebookInfoDialog dialog(tr("Notebook Information"), "", notebook,
do { m_notebooks, this);
if (dialog.exec() == QDialog::Accepted) { if (dialog.exec() == QDialog::Accepted) {
bool updated = false; bool updated = false;
QString name = dialog.getName(); QString name = dialog.getName();
if (name != curName) { if (name != curName) {
if (findNotebook(name)) { updated = true;
VUtils::showMessage(QMessageBox::Warning, tr("Warning"), notebook->rename(name);
tr("Name already exists. Please choose another name."), "", updateComboBoxItem(index, name);
QMessageBox::Ok, QMessageBox::Ok, this); vconfig.setNotebooks(m_notebooks);
continue;
}
updated = true;
notebook->rename(name);
updateComboBoxItem(index, name);
vconfig.setNotebooks(m_notebooks);
}
QString imageFolder = dialog.getImageFolder();
if (imageFolder != notebook->getImageFolderConfig()) {
updated = true;
notebook->setImageFolder(imageFolder);
notebook->writeConfig();
}
if (updated) {
emit notebookUpdated(notebook);
}
} }
break;
} while (true); QString imageFolder = dialog.getImageFolder();
if (imageFolder != notebook->getImageFolderConfig()) {
updated = true;
notebook->setImageFolder(imageFolder);
notebook->writeConfig();
}
if (updated) {
emit notebookUpdated(notebook);
}
}
} }
void VNotebookSelector::addNotebookItem(const QString &p_name) void VNotebookSelector::addNotebookItem(const QString &p_name)

View File

@ -52,7 +52,7 @@ private slots:
private: private:
void initActions(); void initActions();
void updateComboBox(); void updateComboBox();
VNotebook *findNotebook(const QString &p_name);
// Return the index of @p_notebook in m_noteboks. // Return the index of @p_notebook in m_noteboks.
int indexOfNotebook(const VNotebook *p_notebook); int indexOfNotebook(const VNotebook *p_notebook);