mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
support note template
This commit is contained in:
parent
88a3ee183f
commit
af85dc5aed
@ -1 +1 @@
|
||||
Subproject commit 893a88cdd7fdc3957005d109b46c9972a83d6772
|
||||
Subproject commit b9c3758d1d34a2281748352902cf1d3452f24bd4
|
@ -381,6 +381,13 @@ QString ConfigMgr::getUserDictsFolder() const
|
||||
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
|
||||
{
|
||||
QFileInfo fi(p_filePath);
|
||||
|
@ -91,6 +91,8 @@ namespace vnotex
|
||||
QString getAppDictsFolder() const;
|
||||
QString getUserDictsFolder() const;
|
||||
|
||||
QString getUserTemplateFolder() const;
|
||||
|
||||
// If @p_filePath is absolute, just return it.
|
||||
// Otherwise, first try to find it in user folder, then in app folder.
|
||||
QString getUserOrAppFile(const QString &p_filePath) const;
|
||||
|
@ -23,6 +23,7 @@ SOURCES += \
|
||||
$$PWD/markdowneditorconfig.cpp \
|
||||
$$PWD/quickaccesshelper.cpp \
|
||||
$$PWD/singleinstanceguard.cpp \
|
||||
$$PWD/templatemgr.cpp \
|
||||
$$PWD/texteditorconfig.cpp \
|
||||
$$PWD/vnotex.cpp \
|
||||
$$PWD/thememgr.cpp \
|
||||
@ -51,6 +52,7 @@ HEADERS += \
|
||||
$$PWD/quickaccesshelper.h \
|
||||
$$PWD/singleinstanceguard.h \
|
||||
$$PWD/iconfig.h \
|
||||
$$PWD/templatemgr.h \
|
||||
$$PWD/texteditorconfig.h \
|
||||
$$PWD/vnotex.h \
|
||||
$$PWD/thememgr.h \
|
||||
|
@ -117,6 +117,4 @@ QString MainConfig::getVersion(const QJsonObject &p_jobj)
|
||||
void MainConfig::doVersionSpecificOverride()
|
||||
{
|
||||
// In a new version, we may want to change one value by force.
|
||||
m_editorConfig->m_toolBarIconSize = 16;
|
||||
m_editorConfig->writeToSettings();
|
||||
}
|
||||
|
@ -175,9 +175,12 @@ QSharedPointer<Node> Notebook::getRecycleBinNode() const
|
||||
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
|
||||
|
@ -67,7 +67,8 @@ namespace vnotex
|
||||
|
||||
QSharedPointer<Node> newNode(Node *p_parent,
|
||||
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.
|
||||
QSharedPointer<Node> addAsNode(Node *p_parent,
|
||||
|
@ -45,7 +45,8 @@ namespace vnotex
|
||||
|
||||
virtual QSharedPointer<Node> newNode(Node *p_parent,
|
||||
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,
|
||||
Node::Flags p_flags,
|
||||
|
@ -273,7 +273,7 @@ void VXNotebookConfigMgr::createRecycleBinNode(const QSharedPointer<Node> &p_roo
|
||||
{
|
||||
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);
|
||||
markNodeReadOnly(node.data());
|
||||
}
|
||||
@ -376,7 +376,8 @@ void VXNotebookConfigMgr::loadFolderNode(Node *p_node, const NodeConfig &p_confi
|
||||
|
||||
QSharedPointer<Node> VXNotebookConfigMgr::newNode(Node *p_parent,
|
||||
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());
|
||||
|
||||
@ -384,7 +385,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::newNode(Node *p_parent,
|
||||
|
||||
if (p_flags & Node::Flag::Content) {
|
||||
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 {
|
||||
node = newFolderNode(p_parent, p_name, true, NodeParameters());
|
||||
}
|
||||
@ -403,7 +404,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::addAsNode(Node *p_parent,
|
||||
QSharedPointer<Node> node;
|
||||
if (p_flags & Node::Flag::Content) {
|
||||
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 {
|
||||
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,
|
||||
const QString &p_name,
|
||||
const QString &p_content,
|
||||
bool p_create,
|
||||
const NodeParameters &p_paras)
|
||||
{
|
||||
@ -447,7 +449,7 @@ QSharedPointer<Node> VXNotebookConfigMgr::newFileNode(Node *p_parent,
|
||||
|
||||
// Write empty file.
|
||||
if (p_create) {
|
||||
getBackend()->writeFile(node->fetchPath(), QString());
|
||||
getBackend()->writeFile(node->fetchPath(), p_content);
|
||||
node->setExists(true);
|
||||
} else {
|
||||
node->setExists(getBackend()->existsFile(node->fetchPath()));
|
||||
|
@ -41,7 +41,8 @@ namespace vnotex
|
||||
|
||||
QSharedPointer<Node> newNode(Node *p_parent,
|
||||
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,
|
||||
Node::Flags p_flags,
|
||||
@ -154,6 +155,7 @@ namespace vnotex
|
||||
|
||||
QSharedPointer<Node> newFileNode(Node *p_parent,
|
||||
const QString &p_name,
|
||||
const QString &p_content,
|
||||
bool p_create,
|
||||
const NodeParameters &p_paras);
|
||||
|
||||
|
24
src/core/templatemgr.cpp
Normal file
24
src/core/templatemgr.cpp
Normal 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
32
src/core/templatemgr.h
Normal 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
|
@ -1,6 +1,11 @@
|
||||
#include "newnotedialog.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QComboBox>
|
||||
#include <QFormLayout>
|
||||
#include <QPushButton>
|
||||
#include <QPlainTextEdit>
|
||||
|
||||
#include "notebook/notebook.h"
|
||||
#include "notebook/node.h"
|
||||
@ -10,9 +15,12 @@
|
||||
#include "exception.h"
|
||||
#include "nodeinfowidget.h"
|
||||
#include <utils/widgetutils.h>
|
||||
#include <core/templatemgr.h>
|
||||
|
||||
using namespace vnotex;
|
||||
|
||||
QString NewNoteDialog::s_lastTemplate;
|
||||
|
||||
NewNoteDialog::NewNoteDialog(Node *p_node, QWidget *p_parent)
|
||||
: ScrollDialog(p_parent)
|
||||
{
|
||||
@ -29,6 +37,30 @@ void NewNoteDialog::setupUI(const Node *p_node)
|
||||
setupNodeInfoWidget(p_node, this);
|
||||
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);
|
||||
setButtonEnabled(QDialogButtonBox::Ok, false);
|
||||
|
||||
@ -73,6 +105,8 @@ bool NewNoteDialog::validateNameInput(QString &p_msg)
|
||||
|
||||
void NewNoteDialog::acceptedButtonClicked()
|
||||
{
|
||||
s_lastTemplate = m_templateComboBox->currentData().toString();
|
||||
|
||||
if (newNote()) {
|
||||
accept();
|
||||
}
|
||||
@ -85,7 +119,10 @@ bool NewNoteDialog::newNote()
|
||||
Notebook *notebook = const_cast<Notebook *>(m_infoWidget->getNotebook());
|
||||
Node *parentNode = const_cast<Node *>(m_infoWidget->getParentNode());
|
||||
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) {
|
||||
QString msg = tr("Failed to create note under (%1) in (%2) (%3).").arg(parentNode->getName(),
|
||||
notebook->getName(),
|
||||
@ -118,3 +155,60 @@ void NewNoteDialog::initDefaultValues(const Node *p_node)
|
||||
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;
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
#include "scrolldialog.h"
|
||||
|
||||
class QComboBox;
|
||||
class QPlainTextEdit;
|
||||
|
||||
namespace vnotex
|
||||
{
|
||||
class Notebook;
|
||||
@ -29,15 +32,27 @@ namespace vnotex
|
||||
|
||||
void setupNodeInfoWidget(const Node *p_node, QWidget *p_parent);
|
||||
|
||||
void setupTemplateComboBox(QWidget *p_parent);
|
||||
|
||||
bool validateNameInput(QString &p_msg);
|
||||
|
||||
bool newNote();
|
||||
|
||||
void initDefaultValues(const Node *p_node);
|
||||
|
||||
QString getTemplateContent() const;
|
||||
|
||||
NodeInfoWidget *m_infoWidget = nullptr;
|
||||
|
||||
QComboBox *m_templateComboBox = nullptr;
|
||||
|
||||
QPlainTextEdit *m_templateTextEdit = nullptr;
|
||||
|
||||
QString m_templateContent;
|
||||
|
||||
QSharedPointer<Node> m_newNode;
|
||||
|
||||
static QString s_lastTemplate;
|
||||
};
|
||||
} // ns vnotex
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include "nodeinfowidget.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
#include <QComboBox>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QFormLayout>
|
||||
|
||||
#include "notebook/notebook.h"
|
||||
#include "../widgetsfactory.h"
|
||||
@ -174,3 +177,8 @@ void NodeInfoWidget::setupFileTypeComboBox(QWidget *p_parent)
|
||||
m_nameLineEdit->setFocus();
|
||||
});
|
||||
}
|
||||
|
||||
QFormLayout *NodeInfoWidget::getMainLayout() const
|
||||
{
|
||||
return m_mainLayout;
|
||||
}
|
||||
|
@ -35,6 +35,9 @@ namespace vnotex
|
||||
|
||||
const Node *getParentNode() const;
|
||||
|
||||
// Allow upper level to add more widgets to the layout.
|
||||
QFormLayout *getMainLayout() const;
|
||||
|
||||
signals:
|
||||
void inputEdited();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user