support note template

This commit is contained in:
Le Tan 2021-06-21 21:01:40 +08:00
parent 88a3ee183f
commit af85dc5aed
16 changed files with 210 additions and 16 deletions

@ -1 +1 @@
Subproject commit 893a88cdd7fdc3957005d109b46c9972a83d6772 Subproject commit b9c3758d1d34a2281748352902cf1d3452f24bd4

View File

@ -381,6 +381,13 @@ QString ConfigMgr::getUserDictsFolder() const
return folderPath; return folderPath;
} }
QString ConfigMgr::getUserTemplateFolder() const
{
auto folderPath = PathUtils::concatenateFilePath(m_userConfigFolderPath, QStringLiteral("templates"));
QDir().mkpath(folderPath);
return folderPath;
}
QString ConfigMgr::getUserOrAppFile(const QString &p_filePath) const QString ConfigMgr::getUserOrAppFile(const QString &p_filePath) const
{ {
QFileInfo fi(p_filePath); QFileInfo fi(p_filePath);

View File

@ -91,6 +91,8 @@ namespace vnotex
QString getAppDictsFolder() const; QString getAppDictsFolder() const;
QString getUserDictsFolder() const; QString getUserDictsFolder() const;
QString getUserTemplateFolder() const;
// If @p_filePath is absolute, just return it. // If @p_filePath is absolute, just return it.
// Otherwise, first try to find it in user folder, then in app folder. // Otherwise, first try to find it in user folder, then in app folder.
QString getUserOrAppFile(const QString &p_filePath) const; QString getUserOrAppFile(const QString &p_filePath) const;

View File

@ -23,6 +23,7 @@ SOURCES += \
$$PWD/markdowneditorconfig.cpp \ $$PWD/markdowneditorconfig.cpp \
$$PWD/quickaccesshelper.cpp \ $$PWD/quickaccesshelper.cpp \
$$PWD/singleinstanceguard.cpp \ $$PWD/singleinstanceguard.cpp \
$$PWD/templatemgr.cpp \
$$PWD/texteditorconfig.cpp \ $$PWD/texteditorconfig.cpp \
$$PWD/vnotex.cpp \ $$PWD/vnotex.cpp \
$$PWD/thememgr.cpp \ $$PWD/thememgr.cpp \
@ -51,6 +52,7 @@ HEADERS += \
$$PWD/quickaccesshelper.h \ $$PWD/quickaccesshelper.h \
$$PWD/singleinstanceguard.h \ $$PWD/singleinstanceguard.h \
$$PWD/iconfig.h \ $$PWD/iconfig.h \
$$PWD/templatemgr.h \
$$PWD/texteditorconfig.h \ $$PWD/texteditorconfig.h \
$$PWD/vnotex.h \ $$PWD/vnotex.h \
$$PWD/thememgr.h \ $$PWD/thememgr.h \

View File

@ -117,6 +117,4 @@ QString MainConfig::getVersion(const QJsonObject &p_jobj)
void MainConfig::doVersionSpecificOverride() void MainConfig::doVersionSpecificOverride()
{ {
// In a new version, we may want to change one value by force. // In a new version, we may want to change one value by force.
m_editorConfig->m_toolBarIconSize = 16;
m_editorConfig->writeToSettings();
} }

View File

@ -175,9 +175,12 @@ QSharedPointer<Node> Notebook::getRecycleBinNode() const
return nullptr; return nullptr;
} }
QSharedPointer<Node> Notebook::newNode(Node *p_parent, Node::Flags p_flags, const QString &p_name) QSharedPointer<Node> Notebook::newNode(Node *p_parent,
Node::Flags p_flags,
const QString &p_name,
const QString &p_content)
{ {
return m_configMgr->newNode(p_parent, p_flags, p_name); return m_configMgr->newNode(p_parent, p_flags, p_name, p_content);
} }
const QDateTime &Notebook::getCreatedTimeUtc() const const QDateTime &Notebook::getCreatedTimeUtc() const

View File

@ -67,7 +67,8 @@ namespace vnotex
QSharedPointer<Node> newNode(Node *p_parent, QSharedPointer<Node> newNode(Node *p_parent,
Node::Flags p_flags, Node::Flags p_flags,
const QString &p_name); const QString &p_name,
const QString &p_content = QString());
// Add @p_name under @p_parent to add as a new node @p_type. // Add @p_name under @p_parent to add as a new node @p_type.
QSharedPointer<Node> addAsNode(Node *p_parent, QSharedPointer<Node> addAsNode(Node *p_parent,

View File

@ -45,7 +45,8 @@ namespace vnotex
virtual QSharedPointer<Node> newNode(Node *p_parent, virtual QSharedPointer<Node> newNode(Node *p_parent,
Node::Flags p_flags, Node::Flags p_flags,
const QString &p_name) = 0; const QString &p_name,
const QString &p_content) = 0;
virtual QSharedPointer<Node> addAsNode(Node *p_parent, virtual QSharedPointer<Node> addAsNode(Node *p_parent,
Node::Flags p_flags, Node::Flags p_flags,

View File

@ -273,7 +273,7 @@ void VXNotebookConfigMgr::createRecycleBinNode(const QSharedPointer<Node> &p_roo
{ {
Q_ASSERT(p_root->isRoot()); Q_ASSERT(p_root->isRoot());
auto node = newNode(p_root.data(), Node::Flag::Container, c_recycleBinFolderName); auto node = newNode(p_root.data(), Node::Flag::Container, c_recycleBinFolderName, "");
node->setUse(Node::Use::RecycleBin); node->setUse(Node::Use::RecycleBin);
markNodeReadOnly(node.data()); markNodeReadOnly(node.data());
} }
@ -376,7 +376,8 @@ void VXNotebookConfigMgr::loadFolderNode(Node *p_node, const NodeConfig &p_confi
QSharedPointer<Node> VXNotebookConfigMgr::newNode(Node *p_parent, QSharedPointer<Node> VXNotebookConfigMgr::newNode(Node *p_parent,
Node::Flags p_flags, Node::Flags p_flags,
const QString &p_name) const QString &p_name,
const QString &p_content)
{ {
Q_ASSERT(p_parent && p_parent->isContainer() && !p_name.isEmpty()); Q_ASSERT(p_parent && p_parent->isContainer() && !p_name.isEmpty());
@ -384,7 +385,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::newNode(Node *p_parent,
if (p_flags & Node::Flag::Content) { if (p_flags & Node::Flag::Content) {
Q_ASSERT(!(p_flags & Node::Flag::Container)); Q_ASSERT(!(p_flags & Node::Flag::Container));
node = newFileNode(p_parent, p_name, true, NodeParameters()); node = newFileNode(p_parent, p_name, p_content, true, NodeParameters());
} else { } else {
node = newFolderNode(p_parent, p_name, true, NodeParameters()); node = newFolderNode(p_parent, p_name, true, NodeParameters());
} }
@ -403,7 +404,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::addAsNode(Node *p_parent,
QSharedPointer<Node> node; QSharedPointer<Node> node;
if (p_flags & Node::Flag::Content) { if (p_flags & Node::Flag::Content) {
Q_ASSERT(!(p_flags & Node::Flag::Container)); Q_ASSERT(!(p_flags & Node::Flag::Container));
node = newFileNode(p_parent, p_name, false, p_paras); node = newFileNode(p_parent, p_name, "", false, p_paras);
} else { } else {
node = newFolderNode(p_parent, p_name, false, p_paras); node = newFolderNode(p_parent, p_name, false, p_paras);
} }
@ -430,6 +431,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::copyAsNode(Node *p_parent,
QSharedPointer<Node> VXNotebookConfigMgr::newFileNode(Node *p_parent, QSharedPointer<Node> VXNotebookConfigMgr::newFileNode(Node *p_parent,
const QString &p_name, const QString &p_name,
const QString &p_content,
bool p_create, bool p_create,
const NodeParameters &p_paras) const NodeParameters &p_paras)
{ {
@ -447,7 +449,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::newFileNode(Node *p_parent,
// Write empty file. // Write empty file.
if (p_create) { if (p_create) {
getBackend()->writeFile(node->fetchPath(), QString()); getBackend()->writeFile(node->fetchPath(), p_content);
node->setExists(true); node->setExists(true);
} else { } else {
node->setExists(getBackend()->existsFile(node->fetchPath())); node->setExists(getBackend()->existsFile(node->fetchPath()));

View File

@ -41,7 +41,8 @@ namespace vnotex
QSharedPointer<Node> newNode(Node *p_parent, QSharedPointer<Node> newNode(Node *p_parent,
Node::Flags p_flags, Node::Flags p_flags,
const QString &p_name) Q_DECL_OVERRIDE; const QString &p_name,
const QString &p_content) Q_DECL_OVERRIDE;
QSharedPointer<Node> addAsNode(Node *p_parent, QSharedPointer<Node> addAsNode(Node *p_parent,
Node::Flags p_flags, Node::Flags p_flags,
@ -154,6 +155,7 @@ namespace vnotex
QSharedPointer<Node> newFileNode(Node *p_parent, QSharedPointer<Node> newFileNode(Node *p_parent,
const QString &p_name, const QString &p_name,
const QString &p_content,
bool p_create, bool p_create,
const NodeParameters &p_paras); const NodeParameters &p_paras);

24
src/core/templatemgr.cpp Normal file
View File

@ -0,0 +1,24 @@
#include "templatemgr.h"
#include <QDir>
#include "configmgr.h"
using namespace vnotex;
QString TemplateMgr::getTemplateFolder() const
{
return ConfigMgr::getInst().getUserTemplateFolder();
}
QStringList TemplateMgr::getTemplates() const
{
QDir dir(getTemplateFolder());
dir.setFilter(QDir::Files | QDir::NoSymLinks);
return dir.entryList();
}
QString TemplateMgr::getTemplateFilePath(const QString &p_name) const
{
return QDir(getTemplateFolder()).filePath(p_name);
}

32
src/core/templatemgr.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef TEMPLATEMGR_H
#define TEMPLATEMGR_H
#include <QObject>
#include <QStringList>
#include "noncopyable.h"
namespace vnotex
{
class TemplateMgr : public QObject, private Noncopyable
{
Q_OBJECT
public:
static TemplateMgr &getInst()
{
static TemplateMgr inst;
return inst;
}
QString getTemplateFolder() const;
QStringList getTemplates() const;
QString getTemplateFilePath(const QString &p_name) const;
private:
TemplateMgr() = default;
};
}
#endif // TEMPLATEMGR_H

View File

@ -1,6 +1,11 @@
#include "newnotedialog.h" #include "newnotedialog.h"
#include <QtWidgets> #include <QHBoxLayout>
#include <QLineEdit>
#include <QComboBox>
#include <QFormLayout>
#include <QPushButton>
#include <QPlainTextEdit>
#include "notebook/notebook.h" #include "notebook/notebook.h"
#include "notebook/node.h" #include "notebook/node.h"
@ -10,9 +15,12 @@
#include "exception.h" #include "exception.h"
#include "nodeinfowidget.h" #include "nodeinfowidget.h"
#include <utils/widgetutils.h> #include <utils/widgetutils.h>
#include <core/templatemgr.h>
using namespace vnotex; using namespace vnotex;
QString NewNoteDialog::s_lastTemplate;
NewNoteDialog::NewNoteDialog(Node *p_node, QWidget *p_parent) NewNoteDialog::NewNoteDialog(Node *p_node, QWidget *p_parent)
: ScrollDialog(p_parent) : ScrollDialog(p_parent)
{ {
@ -29,6 +37,30 @@ void NewNoteDialog::setupUI(const Node *p_node)
setupNodeInfoWidget(p_node, this); setupNodeInfoWidget(p_node, this);
setCentralWidget(m_infoWidget); setCentralWidget(m_infoWidget);
auto infoLayout = m_infoWidget->getMainLayout();
{
auto templateLayout = new QHBoxLayout();
templateLayout->setContentsMargins(0, 0, 0, 0);
infoLayout->addRow(tr("Template:"), templateLayout);
setupTemplateComboBox(m_infoWidget);
templateLayout->addWidget(m_templateComboBox);
templateLayout->addStretch();
auto manageBtn = new QPushButton(tr("Manage"), m_infoWidget);
templateLayout->addWidget(manageBtn);
connect(manageBtn, &QPushButton::clicked,
this, []() {
WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(TemplateMgr::getInst().getTemplateFolder()));
});
m_templateTextEdit = WidgetsFactory::createPlainTextConsole(m_infoWidget);
infoLayout->addRow("", m_templateTextEdit);
m_templateTextEdit->hide();
}
setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); setDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
setButtonEnabled(QDialogButtonBox::Ok, false); setButtonEnabled(QDialogButtonBox::Ok, false);
@ -73,6 +105,8 @@ bool NewNoteDialog::validateNameInput(QString &p_msg)
void NewNoteDialog::acceptedButtonClicked() void NewNoteDialog::acceptedButtonClicked()
{ {
s_lastTemplate = m_templateComboBox->currentData().toString();
if (newNote()) { if (newNote()) {
accept(); accept();
} }
@ -85,7 +119,10 @@ bool NewNoteDialog::newNote()
Notebook *notebook = const_cast<Notebook *>(m_infoWidget->getNotebook()); Notebook *notebook = const_cast<Notebook *>(m_infoWidget->getNotebook());
Node *parentNode = const_cast<Node *>(m_infoWidget->getParentNode()); Node *parentNode = const_cast<Node *>(m_infoWidget->getParentNode());
try { try {
m_newNode = notebook->newNode(parentNode, Node::Flag::Content, m_infoWidget->getName()); m_newNode = notebook->newNode(parentNode,
Node::Flag::Content,
m_infoWidget->getName(),
getTemplateContent());
} catch (Exception &p_e) { } catch (Exception &p_e) {
QString msg = tr("Failed to create note under (%1) in (%2) (%3).").arg(parentNode->getName(), QString msg = tr("Failed to create note under (%1) in (%2) (%3).").arg(parentNode->getName(),
notebook->getName(), notebook->getName(),
@ -118,3 +155,60 @@ void NewNoteDialog::initDefaultValues(const Node *p_node)
validateInputs(); validateInputs();
} }
} }
void NewNoteDialog::setupTemplateComboBox(QWidget *p_parent)
{
m_templateComboBox = WidgetsFactory::createComboBox(p_parent);
// None.
m_templateComboBox->addItem(tr("None"), "");
int idx = 1;
auto templates = TemplateMgr::getInst().getTemplates();
for (const auto &temp : templates) {
m_templateComboBox->addItem(temp, temp);
m_templateComboBox->setItemData(idx++, temp, Qt::ToolTipRole);
}
if (!s_lastTemplate.isEmpty()) {
// Restore.
int idx = m_templateComboBox->findData(s_lastTemplate);
if (idx != -1) {
m_templateComboBox->setCurrentIndex(idx);
} else {
s_lastTemplate.clear();
}
}
connect(m_templateComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [this]() {
m_templateContent.clear();
m_templateTextEdit->clear();
auto temp = m_templateComboBox->currentData().toString();
if (temp.isEmpty()) {
m_templateTextEdit->hide();
return;
}
const auto filePath = TemplateMgr::getInst().getTemplateFilePath(temp);
try {
m_templateContent = FileUtils::readTextFile(filePath);
m_templateTextEdit->setPlainText(m_templateContent);
m_templateTextEdit->show();
} catch (Exception &p_e) {
m_templateTextEdit->hide();
QString msg = tr("Failed to load template (%1) (%2).")
.arg(filePath, p_e.what());
qCritical() << msg;
setInformationText(msg, ScrollDialog::InformationLevel::Error);
}
});
}
QString NewNoteDialog::getTemplateContent() const
{
// TODO: parse snippets of the template.
return m_templateContent;
}

View File

@ -3,6 +3,9 @@
#include "scrolldialog.h" #include "scrolldialog.h"
class QComboBox;
class QPlainTextEdit;
namespace vnotex namespace vnotex
{ {
class Notebook; class Notebook;
@ -29,15 +32,27 @@ namespace vnotex
void setupNodeInfoWidget(const Node *p_node, QWidget *p_parent); void setupNodeInfoWidget(const Node *p_node, QWidget *p_parent);
void setupTemplateComboBox(QWidget *p_parent);
bool validateNameInput(QString &p_msg); bool validateNameInput(QString &p_msg);
bool newNote(); bool newNote();
void initDefaultValues(const Node *p_node); void initDefaultValues(const Node *p_node);
QString getTemplateContent() const;
NodeInfoWidget *m_infoWidget = nullptr; NodeInfoWidget *m_infoWidget = nullptr;
QComboBox *m_templateComboBox = nullptr;
QPlainTextEdit *m_templateTextEdit = nullptr;
QString m_templateContent;
QSharedPointer<Node> m_newNode; QSharedPointer<Node> m_newNode;
static QString s_lastTemplate;
}; };
} // ns vnotex } // ns vnotex

View File

@ -1,6 +1,9 @@
#include "nodeinfowidget.h" #include "nodeinfowidget.h"
#include <QtWidgets> #include <QComboBox>
#include <QLabel>
#include <QLineEdit>
#include <QFormLayout>
#include "notebook/notebook.h" #include "notebook/notebook.h"
#include "../widgetsfactory.h" #include "../widgetsfactory.h"
@ -174,3 +177,8 @@ void NodeInfoWidget::setupFileTypeComboBox(QWidget *p_parent)
m_nameLineEdit->setFocus(); m_nameLineEdit->setFocus();
}); });
} }
QFormLayout *NodeInfoWidget::getMainLayout() const
{
return m_mainLayout;
}

View File

@ -35,6 +35,9 @@ namespace vnotex
const Node *getParentNode() const; const Node *getParentNode() const;
// Allow upper level to add more widgets to the layout.
QFormLayout *getMainLayout() const;
signals: signals:
void inputEdited(); void inputEdited();