support inserting note name as title when creating a note

This commit is contained in:
Le Tan 2017-09-07 20:32:29 +08:00
parent 72970cd404
commit 803af89dde
8 changed files with 210 additions and 96 deletions

View File

@ -1,16 +1,22 @@
#include <QtWidgets> #include <QtWidgets>
#include "vfileinfodialog.h" #include "vfileinfodialog.h"
#include "vdirectory.h"
#include "vfile.h"
#include "vconfigmanager.h"
extern VConfigManager *g_config;
VFileInfoDialog::VFileInfoDialog(const QString &title, const QString &info, VFileInfoDialog::VFileInfoDialog(const QString &title, const QString &info,
const QString &defaultName, VDirectory *directory, const VFile *file,
QWidget *parent) QWidget *parent)
: QDialog(parent), infoLabel(NULL), title(title), info(info), defaultName(defaultName) : QDialog(parent), infoLabel(NULL), title(title), info(info),
m_directory(directory), m_file(file)
{ {
setupUI(); setupUI();
connect(nameEdit, &QLineEdit::textChanged, this, &VFileInfoDialog::enableOkButton); connect(nameEdit, &QLineEdit::textChanged, this, &VFileInfoDialog::handleInputChanged);
enableOkButton(); handleInputChanged();
} }
void VFileInfoDialog::setupUI() void VFileInfoDialog::setupUI()
@ -19,10 +25,14 @@ void VFileInfoDialog::setupUI()
infoLabel = new QLabel(info); infoLabel = new QLabel(info);
} }
nameLabel = new QLabel(tr("Note &name:")); nameLabel = new QLabel(tr("Note &name:"));
nameEdit = new QLineEdit(defaultName); nameEdit = new QLineEdit(m_file->getName());
nameEdit->selectAll(); nameEdit->selectAll();
nameLabel->setBuddy(nameEdit); nameLabel->setBuddy(nameEdit);
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);
connect(m_btnBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(m_btnBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
@ -41,6 +51,7 @@ void VFileInfoDialog::setupUI()
} }
mainLayout->addLayout(topLayout); mainLayout->addLayout(topLayout);
mainLayout->addWidget(m_warnLabel);
mainLayout->addWidget(m_btnBox); mainLayout->addWidget(m_btnBox);
mainLayout->setSizeConstraint(QLayout::SetFixedSize); mainLayout->setSizeConstraint(QLayout::SetFixedSize);
setLayout(mainLayout); setLayout(mainLayout);
@ -48,10 +59,28 @@ void VFileInfoDialog::setupUI()
setWindowTitle(title); setWindowTitle(title);
} }
void VFileInfoDialog::enableOkButton() void VFileInfoDialog::handleInputChanged()
{ {
bool showWarnLabel = false;
QString name = nameEdit->text();
bool nameOk = !name.isEmpty();
if (nameOk && name != m_file->getName()) {
// Check if the name conflicts with existing notebook name.
// Case-insensitive when creating note.
if (m_directory->findFile(name, false)) {
nameOk = false;
showWarnLabel = true;
QString nameConflictText = tr("<span style=\"%1\">WARNING</span>: Name (case-insensitive) already exists. "
"Please choose another name.")
.arg(g_config->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(!nameEdit->text().isEmpty()); okBtn->setEnabled(nameOk);
} }
QString VFileInfoDialog::getNameInput() const QString VFileInfoDialog::getNameInput() const

View File

@ -7,17 +7,20 @@ class QLabel;
class QLineEdit; class QLineEdit;
class QDialogButtonBox; class QDialogButtonBox;
class QString; class QString;
class VDirectory;
class VFile;
class VFileInfoDialog : public QDialog class VFileInfoDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
VFileInfoDialog(const QString &title, const QString &info, const QString &defaultName, VFileInfoDialog(const QString &title, const QString &info,
VDirectory *directory, const VFile *file,
QWidget *parent = 0); QWidget *parent = 0);
QString getNameInput() const; QString getNameInput() const;
private slots: private slots:
void enableOkButton(); void handleInputChanged();
private: private:
void setupUI(); void setupUI();
@ -25,11 +28,14 @@ private:
QLabel *infoLabel; QLabel *infoLabel;
QLabel *nameLabel; QLabel *nameLabel;
QLineEdit *nameEdit; QLineEdit *nameEdit;
QLabel *m_warnLabel;
QDialogButtonBox *m_btnBox; QDialogButtonBox *m_btnBox;
QString title; QString title;
QString info; QString info;
QString defaultName;
VDirectory *m_directory;
const VFile *m_file;
}; };
#endif // VFILEINFODIALOG_H #endif // VFILEINFODIALOG_H

View File

@ -1,13 +1,21 @@
#include <QtWidgets> #include <QtWidgets>
#include "vnewfiledialog.h" #include "vnewfiledialog.h"
#include "vconfigmanager.h"
#include "vdirectory.h"
VNewFileDialog::VNewFileDialog(const QString &title, const QString &info, const QString &name, extern VConfigManager *g_config;
const QString &defaultName, QWidget *parent)
: QDialog(parent), title(title), info(info), name(name), defaultName(defaultName) VNewFileDialog::VNewFileDialog(const QString &title, const QString &info,
const QString &defaultName, VDirectory *directory,
QWidget *parent)
: QDialog(parent), title(title), info(info),
defaultName(defaultName), m_directory(directory)
{ {
setupUI(); setupUI();
connect(nameEdit, &QLineEdit::textChanged, this, &VNewFileDialog::enableOkButton); connect(nameEdit, &QLineEdit::textChanged, this, &VNewFileDialog::handleInputChanged);
handleInputChanged();
} }
void VNewFileDialog::setupUI() void VNewFileDialog::setupUI()
@ -17,21 +25,35 @@ void VNewFileDialog::setupUI()
infoLabel = new QLabel(info); infoLabel = new QLabel(info);
} }
nameLabel = new QLabel(name); // Name.
QLabel *nameLabel = new QLabel(tr("Note &name:"));
nameEdit = new QLineEdit(defaultName); nameEdit = new QLineEdit(defaultName);
int dotIndex = defaultName.lastIndexOf('.'); int dotIndex = defaultName.lastIndexOf('.');
nameEdit->setSelection(0, (dotIndex == -1) ? defaultName.size() : dotIndex); nameEdit->setSelection(0, (dotIndex == -1) ? defaultName.size() : dotIndex);
nameLabel->setBuddy(nameEdit); nameLabel->setBuddy(nameEdit);
// InsertTitle.
m_insertTitleCB = new QCheckBox(tr("Insert note name as title (for Markdown only)"));
m_insertTitleCB->setToolTip(tr("Insert note name into the new note as a title"));
m_insertTitleCB->setChecked(g_config->getInsertTitleFromNoteName());
connect(m_insertTitleCB, &QCheckBox::stateChanged,
this, [this](int p_state) {
g_config->setInsertTitleFromNoteName(p_state == Qt::Checked);
});
QFormLayout *topLayout = new QFormLayout();
topLayout->addRow(nameLabel, nameEdit);
topLayout->addRow("", m_insertTitleCB);
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);
connect(m_btnBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(m_btnBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(m_btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject); connect(m_btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
QHBoxLayout *topLayout = new QHBoxLayout();
topLayout->addWidget(nameLabel);
topLayout->addWidget(nameEdit);
QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok); QPushButton *okBtn = m_btnBox->button(QDialogButtonBox::Ok);
nameEdit->setMinimumWidth(okBtn->sizeHint().width() * 3); nameEdit->setMinimumWidth(okBtn->sizeHint().width() * 3);
@ -39,7 +61,9 @@ void VNewFileDialog::setupUI()
if (infoLabel) { if (infoLabel) {
mainLayout->addWidget(infoLabel); mainLayout->addWidget(infoLabel);
} }
mainLayout->addLayout(topLayout); mainLayout->addLayout(topLayout);
mainLayout->addWidget(m_warnLabel);
mainLayout->addWidget(m_btnBox); mainLayout->addWidget(m_btnBox);
mainLayout->setSizeConstraint(QLayout::SetFixedSize); mainLayout->setSizeConstraint(QLayout::SetFixedSize);
setLayout(mainLayout); setLayout(mainLayout);
@ -47,13 +71,36 @@ void VNewFileDialog::setupUI()
setWindowTitle(title); setWindowTitle(title);
} }
void VNewFileDialog::enableOkButton(const QString &editText) void VNewFileDialog::handleInputChanged()
{ {
bool showWarnLabel = false;
QString name = nameEdit->text();
bool nameOk = !name.isEmpty();
if (nameOk) {
// Check if the name conflicts with existing notebook name.
// Case-insensitive when creating note.
if (m_directory->findFile(name, false)) {
nameOk = false;
showWarnLabel = true;
QString nameConflictText = tr("<span style=\"%1\">WARNING</span>: Name (case-insensitive) already exists. "
"Please choose another name.")
.arg(g_config->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(!editText.isEmpty()); okBtn->setEnabled(nameOk);
} }
QString VNewFileDialog::getNameInput() const QString VNewFileDialog::getNameInput() const
{ {
return nameEdit->text(); return nameEdit->text();
} }
bool VNewFileDialog::getInsertTitleInput() const
{
return m_insertTitleCB->isChecked();
}

View File

@ -6,31 +6,40 @@
class QLabel; class QLabel;
class QLineEdit; class QLineEdit;
class QDialogButtonBox; class QDialogButtonBox;
class QString; class QCheckBox;
class VDirectory;
class VNewFileDialog : public QDialog class VNewFileDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
VNewFileDialog(const QString &title, const QString &info, const QString &name, VNewFileDialog(const QString &title, const QString &info,
const QString &defaultName, QWidget *parent = 0); const QString &defaultName, VDirectory *directory,
QWidget *parent = 0);
QString getNameInput() const; QString getNameInput() const;
bool getInsertTitleInput() const;
private slots: private slots:
void enableOkButton(const QString &editText); void handleInputChanged();
private: private:
void setupUI(); void setupUI();
QLabel *nameLabel;
QLineEdit *nameEdit; QLineEdit *nameEdit;
QCheckBox *m_insertTitleCB;
QPushButton *okBtn; QPushButton *okBtn;
QDialogButtonBox *m_btnBox; QDialogButtonBox *m_btnBox;
QLabel *m_warnLabel;
QString title; QString title;
QString info; QString info;
QString name;
QString defaultName; QString defaultName;
VDirectory *m_directory;
}; };
#endif // VNEWFILEDIALOG_H #endif // VNEWFILEDIALOG_H

View File

@ -76,6 +76,9 @@ markdown_highlight_interval=400
; Adds specified height between lines (in pixels) ; Adds specified height between lines (in pixels)
line_distance_height=3 line_distance_height=3
; Whether insert the note name as a title when creating a new note
insert_title_from_note_name=true
[session] [session]
tools_dock_checked=true tools_dock_checked=true

View File

@ -163,6 +163,9 @@ void VConfigManager::initialize()
m_lineDistanceHeight = getConfigFromSettings("global", m_lineDistanceHeight = getConfigFromSettings("global",
"line_distance_height").toInt(); "line_distance_height").toInt();
m_insertTitleFromNoteName = getConfigFromSettings("global",
"insert_title_from_note_name").toBool();
} }
void VConfigManager::readPredefinedColorsFromSettings() void VConfigManager::readPredefinedColorsFromSettings()

View File

@ -225,6 +225,9 @@ public:
int getLineDistanceHeight() const; int getLineDistanceHeight() const;
bool getInsertTitleFromNoteName() const;
void setInsertTitleFromNoteName(bool p_enabled);
// Return the configured key sequence of @p_operation. // Return the configured key sequence of @p_operation.
// Return empty if there is no corresponding config. // Return empty if there is no corresponding config.
QString getShortcutKeySequence(const QString &p_operation) const; QString getShortcutKeySequence(const QString &p_operation) const;
@ -456,6 +459,9 @@ private:
// Line distance height in pixel. // Line distance height in pixel.
int m_lineDistanceHeight; int m_lineDistanceHeight;
// Whether insert the note name as a title when creating a new note.
bool m_insertTitleFromNoteName;
// The name of the config file in each directory, obsolete. // The name of the config file in each directory, obsolete.
// Use c_dirConfigFile instead. // Use c_dirConfigFile instead.
static const QString c_obsoleteDirConfigFile; static const QString c_obsoleteDirConfigFile;
@ -1159,4 +1165,20 @@ inline int VConfigManager::getLineDistanceHeight() const
return m_lineDistanceHeight; return m_lineDistanceHeight;
} }
inline bool VConfigManager::getInsertTitleFromNoteName() const
{
return m_insertTitleFromNoteName;
}
inline void VConfigManager::setInsertTitleFromNoteName(bool p_enabled)
{
if (p_enabled == m_insertTitleFromNoteName) {
return;
}
m_insertTitleFromNoteName = p_enabled;
setConfigToSettings("global", "insert_title_from_note_name",
m_insertTitleFromNoteName);
}
#endif // VCONFIGMANAGER_H #endif // VCONFIGMANAGER_H

View File

@ -178,46 +178,35 @@ void VFileList::fileInfo(VFile *p_file)
if (!p_file) { if (!p_file) {
return; return;
} }
VDirectory *dir = p_file->getDirectory(); VDirectory *dir = p_file->getDirectory();
QString info; QString curName = p_file->getName();
QString defaultName = p_file->getName(); VFileInfoDialog dialog(tr("Note Information"), "", dir, p_file, this);
QString curName = defaultName; if (dialog.exec() == QDialog::Accepted) {
do { QString name = dialog.getNameInput();
VFileInfoDialog dialog(tr("Note Information"), info, defaultName, this); if (name == curName) {
if (dialog.exec() == QDialog::Accepted) { return;
QString name = dialog.getNameInput();
if (name == curName) {
return;
}
// Case-insensitive when creating note.
if (dir->findFile(name, false)) {
info = "Name (case-insensitive) already exists. Please choose another name.";
defaultName = name;
continue;
}
if (!promptForDocTypeChange(p_file, QDir(p_file->retriveBasePath()).filePath(name))) {
return;
}
if (!p_file->rename(name)) {
VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
tr("Fail to rename note <span style=\"%1\">%2</span>.")
.arg(g_config->c_dataTextStyle).arg(curName), "",
QMessageBox::Ok, QMessageBox::Ok, this);
return;
}
QListWidgetItem *item = findItem(p_file);
if (item) {
fillItem(item, p_file);
}
emit fileUpdated(p_file);
} }
break;
} while (true); if (!promptForDocTypeChange(p_file, QDir(p_file->retriveBasePath()).filePath(name))) {
return;
}
if (!p_file->rename(name)) {
VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
tr("Fail to rename note <span style=\"%1\">%2</span>.")
.arg(g_config->c_dataTextStyle).arg(curName), "",
QMessageBox::Ok, QMessageBox::Ok, this);
return;
}
QListWidgetItem *item = findItem(p_file);
if (item) {
fillItem(item, p_file);
}
emit fileUpdated(p_file);
}
} }
void VFileList::fillItem(QListWidgetItem *p_item, const VFile *p_file) void VFileList::fillItem(QListWidgetItem *p_item, const VFile *p_file)
@ -277,38 +266,44 @@ void VFileList::newFile()
.arg(g_config->c_dataTextStyle).arg(m_directory->getName()); .arg(g_config->c_dataTextStyle).arg(m_directory->getName());
info = info + "<br>" + tr("Note with name ending with \"%1\" will be treated as Markdown type.") info = info + "<br>" + tr("Note with name ending with \"%1\" will be treated as Markdown type.")
.arg(suffixStr); .arg(suffixStr);
QString text(tr("Note &name:")); QString defaultName = QString("new_note.%1").arg(defaultSuf);
QString defaultText = QString("new_note.%1").arg(defaultSuf); defaultName = VUtils::getFileNameWithSequence(m_directory->retrivePath(), defaultName);
do { VNewFileDialog dialog(tr("Create Note"), info, defaultName, m_directory, this);
VNewFileDialog dialog(tr("Create Note"), info, text, defaultText, this); if (dialog.exec() == QDialog::Accepted) {
if (dialog.exec() == QDialog::Accepted) { VFile *file = m_directory->createFile(dialog.getNameInput());
QString name = dialog.getNameInput(); if (!file) {
// Case-insensitive when creating note. VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
if (m_directory->findFile(name, false)) { tr("Fail to create note <span style=\"%1\">%2</span>.")
info = tr("Name (case-insensitive) already exists. Please choose another name."); .arg(g_config->c_dataTextStyle).arg(dialog.getNameInput()), "",
defaultText = name; QMessageBox::Ok, QMessageBox::Ok, this);
continue; return;
}
VFile *file = m_directory->createFile(name);
if (!file) {
VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
tr("Fail to create note <span style=\"%1\">%2</span>.")
.arg(g_config->c_dataTextStyle).arg(name), "",
QMessageBox::Ok, QMessageBox::Ok, this);
return;
}
QVector<QListWidgetItem *> items = updateFileListAdded();
Q_ASSERT(items.size() == 1);
fileList->setCurrentItem(items[0], QItemSelectionModel::ClearAndSelect);
// Qt seems not to update the QListWidget correctly. Manually force it to repaint.
fileList->update();
// Open it in edit mode
emit fileCreated(file, OpenFileMode::Edit);
} }
break;
} while (true); // Write title if needed.
if (dialog.getInsertTitleInput()) {
if (!file->open()) {
qWarning() << "fail to open newly-created note" << file->getName();
} else {
Q_ASSERT(file->getContent().isEmpty());
QString content = QString("# %1\n").arg(QFileInfo(file->getName()).baseName());
file->setContent(content);
if (!file->save()) {
qWarning() << "fail to write to newly-created note" << file->getName();
}
file->close();
}
}
QVector<QListWidgetItem *> items = updateFileListAdded();
Q_ASSERT(items.size() == 1);
fileList->setCurrentItem(items[0], QItemSelectionModel::ClearAndSelect);
// Qt seems not to update the QListWidget correctly. Manually force it to repaint.
fileList->update();
// Open it in edit mode
emit fileCreated(file, OpenFileMode::Edit);
}
} }
QVector<QListWidgetItem *> VFileList::updateFileListAdded() QVector<QListWidgetItem *> VFileList::updateFileListAdded()