mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
398 lines
14 KiB
C++
398 lines
14 KiB
C++
#include <QtWidgets>
|
|
#include <QDir>
|
|
#include "vnewnotebookdialog.h"
|
|
#include "vconfigmanager.h"
|
|
#include "utils/vutils.h"
|
|
#include "vnotebook.h"
|
|
#include "vmetawordlineedit.h"
|
|
|
|
extern VConfigManager *g_config;
|
|
|
|
VNewNotebookDialog::VNewNotebookDialog(const QString &title, const QString &info,
|
|
const QString &defaultName, const QString &defaultPath,
|
|
const QVector<VNotebook *> &p_notebooks,
|
|
QWidget *parent)
|
|
: QDialog(parent),
|
|
defaultName(defaultName), defaultPath(defaultPath),
|
|
m_importNotebook(false), m_manualPath(false), m_manualName(false),
|
|
m_notebooks(p_notebooks)
|
|
{
|
|
setupUI(title, info);
|
|
|
|
connect(m_nameEdit, &VMetaWordLineEdit::textChanged, this, &VNewNotebookDialog::handleInputChanged);
|
|
connect(m_pathEdit, &VLineEdit::textChanged, this, &VNewNotebookDialog::handleInputChanged);
|
|
connect(browseBtn, &QPushButton::clicked, this, &VNewNotebookDialog::handleBrowseBtnClicked);
|
|
|
|
handleInputChanged();
|
|
}
|
|
|
|
void VNewNotebookDialog::setupUI(const QString &p_title, const QString &p_info)
|
|
{
|
|
QLabel *infoLabel = NULL;
|
|
if (!p_info.isEmpty()) {
|
|
infoLabel = new QLabel(p_info);
|
|
infoLabel->setWordWrap(true);
|
|
}
|
|
|
|
QLabel *nameLabel = new QLabel(tr("Notebook &name:"));
|
|
m_nameEdit = new VMetaWordLineEdit(defaultName);
|
|
QValidator *validator = new QRegExpValidator(QRegExp(VUtils::c_fileNameRegExp),
|
|
m_nameEdit);
|
|
m_nameEdit->setValidator(validator);
|
|
nameLabel->setBuddy(m_nameEdit);
|
|
|
|
QLabel *pathLabel = new QLabel(tr("Notebook &root folder:"));
|
|
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);
|
|
m_imageFolderEdit->setPlaceholderText(tr("Use global configuration (%1)")
|
|
.arg(g_config->getImageFolder()));
|
|
m_imageFolderEdit->setToolTip(tr("Set the name of the folder to hold images of all the notes in this notebook "
|
|
"(empty to use global configuration)"));
|
|
imageFolderLabel->setToolTip(m_imageFolderEdit->toolTip());
|
|
validator = new QRegExpValidator(QRegExp(VUtils::c_fileNameRegExp), m_imageFolderEdit);
|
|
m_imageFolderEdit->setValidator(validator);
|
|
|
|
QLabel *attachmentFolderLabel = new QLabel(tr("&Attachment folder:"));
|
|
m_attachmentFolderEdit = new VLineEdit();
|
|
attachmentFolderLabel->setBuddy(m_attachmentFolderEdit);
|
|
m_attachmentFolderEdit->setPlaceholderText(tr("Use global configuration (%1)")
|
|
.arg(g_config->getAttachmentFolder()));
|
|
m_attachmentFolderEdit->setToolTip(tr("Set the name of the folder to hold attachments of all the notes in this notebook "
|
|
"(empty to use global configuration, read-only once created)"));
|
|
attachmentFolderLabel->setToolTip(m_attachmentFolderEdit->toolTip());
|
|
validator = new QRegExpValidator(QRegExp(VUtils::c_fileNameRegExp), m_attachmentFolderEdit);
|
|
m_attachmentFolderEdit->setValidator(validator);
|
|
|
|
QGridLayout *topLayout = new QGridLayout();
|
|
topLayout->addWidget(nameLabel, 0, 0);
|
|
topLayout->addWidget(m_nameEdit, 0, 1, 1, 2);
|
|
topLayout->addWidget(pathLabel, 1, 0);
|
|
topLayout->addWidget(m_pathEdit, 1, 1);
|
|
topLayout->addWidget(browseBtn, 1, 2);
|
|
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();
|
|
m_warnLabel->setWordWrap(true);
|
|
m_warnLabel->hide();
|
|
|
|
// Ok is the default button.
|
|
m_btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
|
connect(m_btnBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
|
connect(m_btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
|
|
|
QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok);
|
|
okBtn->setProperty("SpecialBtn", true);
|
|
m_pathEdit->setMinimumWidth(okBtn->sizeHint().width() * 3);
|
|
|
|
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
|
if (infoLabel) {
|
|
mainLayout->addWidget(infoLabel);
|
|
}
|
|
mainLayout->addLayout(topLayout);
|
|
mainLayout->addWidget(m_warnLabel);
|
|
mainLayout->addWidget(m_btnBox);
|
|
|
|
// Will set the parent of above widgets properly.
|
|
setLayout(mainLayout);
|
|
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
|
|
setWindowTitle(p_title);
|
|
}
|
|
|
|
QString VNewNotebookDialog::getNameInput() const
|
|
{
|
|
return m_nameEdit->getEvaluatedText();
|
|
}
|
|
|
|
QString VNewNotebookDialog::getPathInput() const
|
|
{
|
|
// absoluteFilePath() to convert the drive to upper case.
|
|
// cleanPath() to remove duplicate separator, '.', and '..'.
|
|
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
|
|
{
|
|
if (m_imageFolderEdit->isEnabled()) {
|
|
return m_imageFolderEdit->text();
|
|
} else {
|
|
return QString();
|
|
}
|
|
}
|
|
|
|
QString VNewNotebookDialog::getAttachmentFolder() const
|
|
{
|
|
if (m_attachmentFolderEdit->isEnabled()) {
|
|
return m_attachmentFolderEdit->text();
|
|
} else {
|
|
return QString();
|
|
}
|
|
}
|
|
|
|
void VNewNotebookDialog::handleBrowseBtnClicked()
|
|
{
|
|
static QString defaultPath;
|
|
|
|
if (defaultPath.isEmpty()) {
|
|
defaultPath = g_config->getVnoteNotebookFolderPath();
|
|
if (!QFileInfo::exists(defaultPath)) {
|
|
defaultPath = g_config->getDocumentPathOrHomePath();
|
|
}
|
|
}
|
|
|
|
QString dirPath = QFileDialog::getExistingDirectory(this,
|
|
tr("Select Root Folder Of The Notebook"),
|
|
defaultPath,
|
|
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
|
|
|
if (!dirPath.isEmpty()) {
|
|
m_manualPath = true;
|
|
if (m_pathEdit->text() == dirPath) {
|
|
handleInputChanged();
|
|
} else {
|
|
m_pathEdit->setText(dirPath);
|
|
}
|
|
|
|
defaultPath = VUtils::basePathFromPath(dirPath);
|
|
}
|
|
}
|
|
|
|
bool VNewNotebookDialog::isImportExistingNotebook() const
|
|
{
|
|
return m_importNotebook;
|
|
}
|
|
|
|
void VNewNotebookDialog::showEvent(QShowEvent *event)
|
|
{
|
|
m_nameEdit->setFocus();
|
|
QDialog::showEvent(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;
|
|
|
|
// User has input some texts.
|
|
if (m_pathEdit->isModified()) {
|
|
m_manualPath = true;
|
|
}
|
|
|
|
if (m_nameEdit->isModified()) {
|
|
m_manualName = true;
|
|
}
|
|
|
|
if (autoComplete()) {
|
|
return;
|
|
}
|
|
|
|
QString path = m_pathEdit->text();
|
|
if (!path.isEmpty()) {
|
|
if (!QDir::isAbsolutePath(path)) {
|
|
showWarnLabel = true;
|
|
QString tmp = tr("<span style=\"%1\">WARNING</span>: 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()) {
|
|
pathOk = true;
|
|
} 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 {
|
|
pathOk = true;
|
|
}
|
|
}
|
|
|
|
// 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(g_config->c_warningTextStyle);
|
|
m_warnLabel->setText(tmp);
|
|
}
|
|
}
|
|
|
|
if (pathOk) {
|
|
// Check if this path has been in VNote.
|
|
int idx = -1;
|
|
for (idx = 0; idx < m_notebooks.size(); ++idx) {
|
|
if (VUtils::equalPath(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(g_config->c_warningTextStyle)
|
|
.arg(g_config->c_dataTextStyle)
|
|
.arg(m_notebooks[idx]->getName());
|
|
m_warnLabel->setText(existText);
|
|
}
|
|
}
|
|
|
|
if (pathOk && isUseRelativePath()) {
|
|
if (!VUtils::inSameDrive(QCoreApplication::applicationDirPath(), path)) {
|
|
pathOk = false;
|
|
showWarnLabel = true;
|
|
QString existText = tr("<span style=\"%1\">WARNING</span>: Please choose a folder in the same drive as "
|
|
"<span style=\"%2\">%3</span> 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) {
|
|
// Check if the name conflicts with existing notebook name.
|
|
// Case-insensitive.
|
|
int idx = -1;
|
|
for (idx = 0; idx < m_notebooks.size(); ++idx) {
|
|
if (m_notebooks[idx]->getName().toLower() == name.toLower()) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
QString warnText;
|
|
if (idx < m_notebooks.size()) {
|
|
nameOk = false;
|
|
warnText = tr("<span style=\"%1\">WARNING</span>: "
|
|
"Name (case-insensitive) <span style=\"%2\">%3</span> already exists. "
|
|
"Please choose another name.")
|
|
.arg(g_config->c_warningTextStyle)
|
|
.arg(g_config->c_dataTextStyle)
|
|
.arg(name);
|
|
} else if (!VUtils::checkFileNameLegal(name)) {
|
|
// Check if evaluated name contains illegal characters.
|
|
nameOk = false;
|
|
warnText = tr("<span style=\"%1\">WARNING</span>: "
|
|
"Name <span style=\"%2\">%3</span> contains illegal characters "
|
|
"(after magic word evaluation).")
|
|
.arg(g_config->c_warningTextStyle)
|
|
.arg(g_config->c_dataTextStyle)
|
|
.arg(name);
|
|
}
|
|
|
|
if (!nameOk) {
|
|
showWarnLabel = true;
|
|
m_warnLabel->setText(warnText);
|
|
}
|
|
}
|
|
|
|
m_warnLabel->setVisible(showWarnLabel);
|
|
m_importNotebook = configExist;
|
|
m_imageFolderEdit->setEnabled(!m_importNotebook);
|
|
m_attachmentFolderEdit->setEnabled(!m_importNotebook);
|
|
|
|
QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok);
|
|
okBtn->setEnabled(nameOk && pathOk);
|
|
}
|
|
|
|
bool VNewNotebookDialog::autoComplete()
|
|
{
|
|
QString nameText = m_nameEdit->getEvaluatedText();
|
|
|
|
if (m_manualPath) {
|
|
if (m_manualName) {
|
|
return false;
|
|
}
|
|
|
|
// Set the name according to user-chosen path.
|
|
QString pathText = m_pathEdit->text();
|
|
if (!pathText.isEmpty()) {
|
|
QString autoName = VUtils::directoryNameFromPath(pathText);
|
|
if (autoName != nameText) {
|
|
m_nameEdit->setText(autoName);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
QString vnoteFolder = g_config->getVnoteNotebookFolderPath();
|
|
QString pathText = m_pathEdit->text();
|
|
if (!pathText.isEmpty()
|
|
&& !VUtils::equalPath(vnoteFolder, VUtils::basePathFromPath(pathText))) {
|
|
return false;
|
|
}
|
|
|
|
bool ret = false;
|
|
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::getDirNameWithSequence(vnoteFolder, name);
|
|
m_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) {
|
|
m_pathEdit->setText(autoPath);
|
|
ret = true;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool VNewNotebookDialog::isUseRelativePath() const
|
|
{
|
|
return m_relativePathCB->isChecked();
|
|
}
|