diff --git a/src/dialog/vfixnotebookdialog.cpp b/src/dialog/vfixnotebookdialog.cpp
index 1a84d099..9e75bc41 100644
--- a/src/dialog/vfixnotebookdialog.cpp
+++ b/src/dialog/vfixnotebookdialog.cpp
@@ -39,6 +39,12 @@ void VFixNotebookDialog::setupUI()
connect(m_browseBtn, &QPushButton::clicked,
this, &VFixNotebookDialog::handleBrowseBtnClicked);
+ m_relativePathCB = new QCheckBox(tr("Use relative path"), this);
+ m_relativePathCB->setToolTip(tr("Use relative path (to VNote's executable) in configuration file"));
+ m_relativePathCB->setChecked(!QDir::isAbsolutePath(m_notebook->getPathInConfig()));
+ connect(m_relativePathCB, &QCheckBox::stateChanged,
+ this, &VFixNotebookDialog::handleInputChanged);
+
QHBoxLayout *pathLayout = new QHBoxLayout();
pathLayout->addWidget(m_pathEdit);
pathLayout->addWidget(m_browseBtn);
@@ -46,6 +52,7 @@ void VFixNotebookDialog::setupUI()
QFormLayout *topLayout = new QFormLayout();
topLayout->addRow(tr("Notebook name:"), nameLabel);
topLayout->addRow(tr("Notebook root folder:"), pathLayout);
+ topLayout->addRow(m_relativePathCB);
// Warning label.
m_warnLabel = new QLabel(this);
@@ -89,7 +96,12 @@ void VFixNotebookDialog::handleBrowseBtnClicked()
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (!dirPath.isEmpty()) {
- m_pathEdit->setText(dirPath);
+ if (m_pathEdit->text() == dirPath) {
+ handleInputChanged();
+ } else {
+ m_pathEdit->setText(dirPath);
+ }
+
defaultPath = VUtils::basePathFromPath(dirPath);
}
}
@@ -103,7 +115,11 @@ void VFixNotebookDialog::handleInputChanged()
QString path = m_pathEdit->text();
if (!path.isEmpty()) {
- if (VConfigManager::directoryConfigExist(path)) {
+ if (!QDir::isAbsolutePath(path)) {
+ QString tmp = tr("WARNING: Please specify absolute path.")
+ .arg(g_config->c_warningTextStyle);
+ m_warnLabel->setText(tmp);
+ } else if (VConfigManager::directoryConfigExist(path)) {
pathOk = true;
}
}
@@ -131,6 +147,18 @@ void VFixNotebookDialog::handleInputChanged()
m_warnLabel->setText(warnText);
}
+ if (pathOk && isUseRelativePath()) {
+ if (!VUtils::inSameDrive(QCoreApplication::applicationDirPath(), path)) {
+ pathOk = false;
+ QString existText = tr("WARNING: Please choose a folder in the same drive as "
+ "%3 when relative path is enabled.")
+ .arg(g_config->c_warningTextStyle)
+ .arg(g_config->c_dataTextStyle)
+ .arg(QCoreApplication::applicationDirPath());
+ m_warnLabel->setText(existText);
+ }
+ }
+
m_warnLabel->setVisible(!pathOk);
QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok);
okBtn->setEnabled(pathOk);
@@ -140,5 +168,19 @@ QString VFixNotebookDialog::getPathInput() const
{
// absoluteFilePath() to convert the drive to upper case.
// cleanPath() to remove duplicate separator, '.', and '..'.
- return QDir::cleanPath(QFileInfo(m_pathEdit->text()).absoluteFilePath());
+ QString ret;
+ if (isUseRelativePath()) {
+ // Use relative path in config file.
+ QDir appDir(QCoreApplication::applicationDirPath());
+ ret = QDir::cleanPath(appDir.relativeFilePath(m_pathEdit->text()));
+ } else {
+ ret = QDir::cleanPath(QFileInfo(m_pathEdit->text()).absoluteFilePath());
+ }
+
+ return ret;
+}
+
+bool VFixNotebookDialog::isUseRelativePath() const
+{
+ return m_relativePathCB->isChecked();
}
diff --git a/src/dialog/vfixnotebookdialog.h b/src/dialog/vfixnotebookdialog.h
index 40418032..6d348afe 100644
--- a/src/dialog/vfixnotebookdialog.h
+++ b/src/dialog/vfixnotebookdialog.h
@@ -8,6 +8,7 @@ class VLineEdit;
class QLabel;
class QPushButton;
class QDialogButtonBox;
+class QCheckBox;
class VFixNotebookDialog : public QDialog
{
@@ -27,6 +28,9 @@ private slots:
private:
void setupUI();
+ // Whether relative path will be used in config file.
+ bool isUseRelativePath() const;
+
const VNotebook *m_notebook;
const QVector &m_notebooks;
@@ -35,6 +39,8 @@ private:
QPushButton *m_browseBtn;
+ QCheckBox *m_relativePathCB;
+
QLabel *m_warnLabel;
QDialogButtonBox *m_btnBox;
diff --git a/src/dialog/vnewnotebookdialog.cpp b/src/dialog/vnewnotebookdialog.cpp
index 6ff575c7..0f17ad99 100644
--- a/src/dialog/vnewnotebookdialog.cpp
+++ b/src/dialog/vnewnotebookdialog.cpp
@@ -20,7 +20,7 @@ VNewNotebookDialog::VNewNotebookDialog(const QString &title, const QString &info
setupUI(title, info);
connect(m_nameEdit, &VMetaWordLineEdit::textChanged, this, &VNewNotebookDialog::handleInputChanged);
- connect(pathEdit, &VLineEdit::textChanged, this, &VNewNotebookDialog::handleInputChanged);
+ connect(m_pathEdit, &VLineEdit::textChanged, this, &VNewNotebookDialog::handleInputChanged);
connect(browseBtn, &QPushButton::clicked, this, &VNewNotebookDialog::handleBrowseBtnClicked);
handleInputChanged();
@@ -42,10 +42,15 @@ void VNewNotebookDialog::setupUI(const QString &p_title, const QString &p_info)
nameLabel->setBuddy(m_nameEdit);
QLabel *pathLabel = new QLabel(tr("Notebook &root folder:"));
- pathEdit = new VLineEdit(defaultPath);
- pathLabel->setBuddy(pathEdit);
+ m_pathEdit = new VLineEdit(defaultPath);
+ pathLabel->setBuddy(m_pathEdit);
browseBtn = new QPushButton(tr("&Browse"));
+ m_relativePathCB = new QCheckBox(tr("Use relative path"));
+ m_relativePathCB->setToolTip(tr("Use relative path (to VNote's executable) in configuration file"));
+ connect(m_relativePathCB, &QCheckBox::stateChanged,
+ this, &VNewNotebookDialog::handleInputChanged);
+
QLabel *imageFolderLabel = new QLabel(tr("&Image folder:"));
m_imageFolderEdit = new VLineEdit();
imageFolderLabel->setBuddy(m_imageFolderEdit);
@@ -72,12 +77,13 @@ void VNewNotebookDialog::setupUI(const QString &p_title, const QString &p_info)
topLayout->addWidget(nameLabel, 0, 0);
topLayout->addWidget(m_nameEdit, 0, 1, 1, 2);
topLayout->addWidget(pathLabel, 1, 0);
- topLayout->addWidget(pathEdit, 1, 1);
+ topLayout->addWidget(m_pathEdit, 1, 1);
topLayout->addWidget(browseBtn, 1, 2);
- topLayout->addWidget(imageFolderLabel, 2, 0);
- topLayout->addWidget(m_imageFolderEdit, 2, 1);
- topLayout->addWidget(attachmentFolderLabel, 3, 0);
- topLayout->addWidget(m_attachmentFolderEdit, 3, 1);
+ topLayout->addWidget(m_relativePathCB, 2, 1);
+ topLayout->addWidget(imageFolderLabel, 3, 0);
+ topLayout->addWidget(m_imageFolderEdit, 3, 1);
+ topLayout->addWidget(attachmentFolderLabel, 4, 0);
+ topLayout->addWidget(m_attachmentFolderEdit, 4, 1);
// Warning label.
m_warnLabel = new QLabel();
@@ -91,7 +97,7 @@ void VNewNotebookDialog::setupUI(const QString &p_title, const QString &p_info)
QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok);
okBtn->setProperty("SpecialBtn", true);
- pathEdit->setMinimumWidth(okBtn->sizeHint().width() * 3);
+ m_pathEdit->setMinimumWidth(okBtn->sizeHint().width() * 3);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
if (infoLabel) {
@@ -116,7 +122,16 @@ QString VNewNotebookDialog::getPathInput() const
{
// absoluteFilePath() to convert the drive to upper case.
// cleanPath() to remove duplicate separator, '.', and '..'.
- return QDir::cleanPath(QFileInfo(pathEdit->text()).absoluteFilePath());
+ QString ret;
+ if (isUseRelativePath()) {
+ // Use relative path in config file.
+ QDir appDir(QCoreApplication::applicationDirPath());
+ ret = QDir::cleanPath(appDir.relativeFilePath(m_pathEdit->text()));
+ } else {
+ ret = QDir::cleanPath(QFileInfo(m_pathEdit->text()).absoluteFilePath());
+ }
+
+ return ret;
}
QString VNewNotebookDialog::getImageFolder() const
@@ -140,6 +155,7 @@ QString VNewNotebookDialog::getAttachmentFolder() const
void VNewNotebookDialog::handleBrowseBtnClicked()
{
static QString defaultPath;
+
if (defaultPath.isEmpty()) {
defaultPath = g_config->getVnoteNotebookFolderPath();
if (!QFileInfo::exists(defaultPath)) {
@@ -154,7 +170,12 @@ void VNewNotebookDialog::handleBrowseBtnClicked()
if (!dirPath.isEmpty()) {
m_manualPath = true;
- pathEdit->setText(dirPath);
+ if (m_pathEdit->text() == dirPath) {
+ handleInputChanged();
+ } else {
+ m_pathEdit->setText(dirPath);
+ }
+
defaultPath = VUtils::basePathFromPath(dirPath);
}
}
@@ -184,7 +205,7 @@ void VNewNotebookDialog::handleInputChanged()
bool showWarnLabel = false;
// User has input some texts.
- if (pathEdit->isModified()) {
+ if (m_pathEdit->isModified()) {
m_manualPath = true;
}
@@ -196,9 +217,14 @@ void VNewNotebookDialog::handleInputChanged()
return;
}
- QString path = pathEdit->text();
+ QString path = m_pathEdit->text();
if (!path.isEmpty()) {
- if (QFileInfo::exists(path)) {
+ if (!QDir::isAbsolutePath(path)) {
+ showWarnLabel = true;
+ QString tmp = tr("WARNING: Please specify absolute path.")
+ .arg(g_config->c_warningTextStyle);
+ m_warnLabel->setText(tmp);
+ } else if (QFileInfo::exists(path)) {
QDir dir(path);
QStringList files = dir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden);
if (files.isEmpty()) {
@@ -206,6 +232,13 @@ void VNewNotebookDialog::handleInputChanged()
} else {
// Folder is not empty.
configExist = VConfigManager::directoryConfigExist(path);
+ if (configExist) {
+ pathOk = true;
+ m_warnLabel->setText(infoText);
+ } else {
+ m_warnLabel->setText(warnText);
+ }
+
showWarnLabel = true;
}
} else {
@@ -213,13 +246,6 @@ void VNewNotebookDialog::handleInputChanged()
}
}
- 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);
@@ -253,6 +279,19 @@ void VNewNotebookDialog::handleInputChanged()
}
}
+ if (pathOk && isUseRelativePath()) {
+ if (!VUtils::inSameDrive(QCoreApplication::applicationDirPath(), path)) {
+ pathOk = false;
+ showWarnLabel = true;
+ QString existText = tr("WARNING: Please choose a folder in the same drive as "
+ "%3 when relative path is enabled.")
+ .arg(g_config->c_warningTextStyle)
+ .arg(g_config->c_dataTextStyle)
+ .arg(QCoreApplication::applicationDirPath());
+ m_warnLabel->setText(existText);
+ }
+ }
+
QString name = m_nameEdit->getEvaluatedText();
bool nameOk = !name.isEmpty();
if (pathOk && nameOk) {
@@ -310,7 +349,7 @@ bool VNewNotebookDialog::autoComplete()
}
// Set the name according to user-chosen path.
- QString pathText = pathEdit->text();
+ QString pathText = m_pathEdit->text();
if (!pathText.isEmpty()) {
QString autoName = VUtils::directoryNameFromPath(pathText);
if (autoName != nameText) {
@@ -323,7 +362,7 @@ bool VNewNotebookDialog::autoComplete()
}
QString vnoteFolder = g_config->getVnoteNotebookFolderPath();
- QString pathText = pathEdit->text();
+ QString pathText = m_pathEdit->text();
if (!pathText.isEmpty()
&& !VUtils::equalPath(vnoteFolder, VUtils::basePathFromPath(pathText))) {
return false;
@@ -344,10 +383,15 @@ bool VNewNotebookDialog::autoComplete()
// Use the name as the folder name under vnoteFolder.
QString autoPath = QDir::cleanPath(QDir(vnoteFolder).filePath(nameText));
if (autoPath != pathText) {
- pathEdit->setText(autoPath);
+ m_pathEdit->setText(autoPath);
ret = true;
}
}
return ret;
}
+
+bool VNewNotebookDialog::isUseRelativePath() const
+{
+ return m_relativePathCB->isChecked();
+}
diff --git a/src/dialog/vnewnotebookdialog.h b/src/dialog/vnewnotebookdialog.h
index 79143f89..a31e49c6 100644
--- a/src/dialog/vnewnotebookdialog.h
+++ b/src/dialog/vnewnotebookdialog.h
@@ -10,6 +10,7 @@ class VMetaWordLineEdit;
class QPushButton;
class QDialogButtonBox;
class VNotebook;
+class QCheckBox;
class VNewNotebookDialog : public QDialog
{
@@ -53,9 +54,13 @@ private:
// Returns true if name or path is modified.
bool autoComplete();
+ // Whether relative path will be used in config file.
+ bool isUseRelativePath() const;
+
VMetaWordLineEdit *m_nameEdit;
- VLineEdit *pathEdit;
+ VLineEdit *m_pathEdit;
QPushButton *browseBtn;
+ QCheckBox *m_relativePathCB;
QLabel *m_warnLabel;
VLineEdit *m_imageFolderEdit;
VLineEdit *m_attachmentFolderEdit;
diff --git a/src/utils/vutils.cpp b/src/utils/vutils.cpp
index 80f585f7..fa1ee986 100644
--- a/src/utils/vutils.cpp
+++ b/src/utils/vutils.cpp
@@ -1525,3 +1525,20 @@ QFormLayout *VUtils::getFormLayout()
return layout;
}
+
+bool VUtils::inSameDrive(const QString &p_a, const QString &p_b)
+{
+#if defined(Q_OS_WIN)
+ QChar sep(':');
+ int ai = p_a.indexOf(sep);
+ int bi = p_b.indexOf(sep);
+
+ if (ai == -1 || bi == -1) {
+ return false;
+ }
+
+ return p_a.left(ai).toLower() == p_b.left(bi).toLower();
+#else
+ return true;
+#endif
+}
diff --git a/src/utils/vutils.h b/src/utils/vutils.h
index 70ef6764..31fbbbd5 100644
--- a/src/utils/vutils.h
+++ b/src/utils/vutils.h
@@ -331,6 +331,8 @@ public:
// Return QFormLayout.
static QFormLayout *getFormLayout();
+ static bool inSameDrive(const QString &p_a, const QString &p_b);
+
// Regular expression for image link.
// 
// Captured texts (need to be trimmed):
diff --git a/src/vconfigmanager.cpp b/src/vconfigmanager.cpp
index ab5709ea..7a5f12b5 100644
--- a/src/vconfigmanager.cpp
+++ b/src/vconfigmanager.cpp
@@ -396,7 +396,7 @@ void VConfigManager::writeNotebookToSettings(QSettings *p_settings,
p_settings->setArrayIndex(i);
const VNotebook ¬ebook = *p_notebooks[i];
p_settings->setValue("name", notebook.getName());
- p_settings->setValue("path", notebook.getPath());
+ p_settings->setValue("path", notebook.getPathInConfig());
}
p_settings->endArray();
diff --git a/src/vnotebook.cpp b/src/vnotebook.cpp
index c7b4a1be..6cceddca 100644
--- a/src/vnotebook.cpp
+++ b/src/vnotebook.cpp
@@ -1,6 +1,8 @@
#include "vnotebook.h"
#include
#include
+#include
+
#include "vdirectory.h"
#include "utils/vutils.h"
#include "vconfigmanager.h"
@@ -11,7 +13,7 @@ extern VConfigManager *g_config;
VNotebook::VNotebook(const QString &name, const QString &path, QObject *parent)
: QObject(parent), m_name(name), m_valid(false)
{
- m_path = QDir::cleanPath(path);
+ setPath(path);
m_recycleBinFolder = g_config->getRecycleBinFolder();
m_rootDir = new VDirectory(this,
NULL,
@@ -24,6 +26,16 @@ VNotebook::~VNotebook()
delete m_rootDir;
}
+void VNotebook::setPath(const QString &p_path)
+{
+ m_pathInConfig = QDir::cleanPath(p_path);
+ if (QDir::isAbsolutePath(m_pathInConfig)) {
+ m_path = m_pathInConfig;
+ } else {
+ m_path = QDir::cleanPath(QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(m_pathInConfig));
+ }
+}
+
bool VNotebook::readConfigNotebook()
{
QJsonObject configJson = VConfigManager::readDirectoryConfig(m_path);
@@ -115,16 +127,6 @@ bool VNotebook::writeConfigNotebook() const
return VConfigManager::writeDirectoryConfig(m_path, configJson);
}
-const QString &VNotebook::getName() const
-{
- return m_name;
-}
-
-const QString &VNotebook::getPath() const
-{
- return m_path;
-}
-
void VNotebook::close()
{
m_rootDir->close();
@@ -171,13 +173,13 @@ VNotebook *VNotebook::createNotebook(const QString &p_name,
nb->setAttachmentFolder(attachmentFolder);
// Check if there alread exists a config file.
- if (p_import && VConfigManager::directoryConfigExist(p_path)) {
+ if (p_import && VConfigManager::directoryConfigExist(nb->getPath())) {
qDebug() << "import existing notebook";
nb->readConfigNotebook();
return nb;
}
- VUtils::makePath(p_path);
+ VUtils::makePath(nb->getPath());
if (!nb->writeToConfig()) {
delete nb;
@@ -397,7 +399,7 @@ void VNotebook::updatePath(const QString &p_path)
{
Q_ASSERT(!isOpened());
m_valid = false;
- m_path = QDir::cleanPath(p_path);
+ setPath(p_path);
delete m_rootDir;
m_rootDir = new VDirectory(this,
NULL,
diff --git a/src/vnotebook.h b/src/vnotebook.h
index 9fd5359c..55e8991c 100644
--- a/src/vnotebook.h
+++ b/src/vnotebook.h
@@ -47,6 +47,8 @@ public:
const QString &getPath() const;
+ const QString &getPathInConfig() const;
+
void updatePath(const QString &p_path);
VDirectory *getRootDir() const;
@@ -107,9 +109,16 @@ private:
// Write current instance to config file.
bool writeToConfig() const;
+ void setPath(const QString &p_path);
+
QString m_name;
+
QString m_path;
+ // Path in vnote.ini.
+ // May be relative path to VNote's executable.
+ QString m_pathInConfig;
+
// Folder name to store images.
// If not empty, VNote will store images in this folder within the same directory of the note.
// Otherwise, VNote will use the global configured folder.
@@ -146,4 +155,19 @@ inline bool VNotebook::isValid() const
return m_valid;
}
+inline const QString &VNotebook::getPath() const
+{
+ return m_path;
+}
+
+inline const QString &VNotebook::getPathInConfig() const
+{
+ return m_pathInConfig;
+}
+
+inline const QString &VNotebook::getName() const
+{
+ return m_name;
+}
+
#endif // VNOTEBOOK_H
diff --git a/src/vnotebookselector.cpp b/src/vnotebookselector.cpp
index db15a885..129013a0 100644
--- a/src/vnotebookselector.cpp
+++ b/src/vnotebookselector.cpp
@@ -320,8 +320,11 @@ void VNotebookSelector::createNotebook(const QString &p_name,
const QString &p_imageFolder,
const QString &p_attachmentFolder)
{
- VNotebook *nb = VNotebook::createNotebook(p_name, p_path, p_import,
- p_imageFolder, p_attachmentFolder,
+ VNotebook *nb = VNotebook::createNotebook(p_name,
+ p_path,
+ p_import,
+ p_imageFolder,
+ p_attachmentFolder,
g_vnote);
if (!nb) {
VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
diff --git a/src/vnotebookselector.h b/src/vnotebookselector.h
index cabc7403..6f3cf889 100644
--- a/src/vnotebookselector.h
+++ b/src/vnotebookselector.h
@@ -77,8 +77,10 @@ private:
// 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.
- void createNotebook(const QString &p_name, const QString &p_path,
- bool p_import, const QString &p_imageFolder,
+ void createNotebook(const QString &p_name,
+ const QString &p_path,
+ bool p_import,
+ const QString &p_imageFolder,
const QString &p_attachmentFolder);
void deleteNotebook(VNotebook *p_notebook, bool p_deleteFiles);