mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
support section number in edit mode
This commit is contained in:
parent
1f7acf2bc5
commit
4636771081
@ -1 +1 @@
|
|||||||
Subproject commit 12a74cb32438b28f002dea51c484133d3058a882
|
Subproject commit 47347580cbcd460ebbbc8358e37b409530edaa2f
|
@ -72,6 +72,13 @@ namespace vnotex
|
|||||||
IncrementalSearch = 0x10U
|
IncrementalSearch = 0x10U
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(FindOptions, FindOption);
|
Q_DECLARE_FLAGS(FindOptions, FindOption);
|
||||||
|
|
||||||
|
enum OverrideState
|
||||||
|
{
|
||||||
|
NoOverride = 0,
|
||||||
|
ForceEnable = 1,
|
||||||
|
ForceDisable = 2
|
||||||
|
};
|
||||||
} // ns vnotex
|
} // ns vnotex
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::FindOptions);
|
Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::FindOptions);
|
||||||
|
@ -155,7 +155,7 @@ void HtmlTemplateHelper::updateMarkdownViewerTemplate(const MarkdownEditorConfig
|
|||||||
WebGlobalOptions opts;
|
WebGlobalOptions opts;
|
||||||
opts.m_webPlantUml = p_config.getWebPlantUml();
|
opts.m_webPlantUml = p_config.getWebPlantUml();
|
||||||
opts.m_webGraphviz = p_config.getWebGraphviz();
|
opts.m_webGraphviz = p_config.getWebGraphviz();
|
||||||
opts.m_sectionNumberEnabled = p_config.getSectionNumberEnabled();
|
opts.m_sectionNumberEnabled = p_config.getSectionNumberMode() == MarkdownEditorConfig::SectionNumberMode::Read;
|
||||||
opts.m_constrainImageWidthEnabled = p_config.getConstrainImageWidthEnabled();
|
opts.m_constrainImageWidthEnabled = p_config.getConstrainImageWidthEnabled();
|
||||||
opts.m_protectFromXss = p_config.getProtectFromXss();
|
opts.m_protectFromXss = p_config.getProtectFromXss();
|
||||||
opts.m_htmlTagEnabled = p_config.getHtmlTagEnabled();
|
opts.m_htmlTagEnabled = p_config.getHtmlTagEnabled();
|
||||||
|
@ -10,6 +10,7 @@ using namespace vnotex;
|
|||||||
#define READSTR(key) readString(appObj, userObj, (key))
|
#define READSTR(key) readString(appObj, userObj, (key))
|
||||||
#define READBOOL(key) readBool(appObj, userObj, (key))
|
#define READBOOL(key) readBool(appObj, userObj, (key))
|
||||||
#define READREAL(key) readReal(appObj, userObj, (key))
|
#define READREAL(key) readReal(appObj, userObj, (key))
|
||||||
|
#define READINT(key) readInt(appObj, userObj, (key))
|
||||||
|
|
||||||
MarkdownEditorConfig::MarkdownEditorConfig(ConfigMgr *p_mgr,
|
MarkdownEditorConfig::MarkdownEditorConfig(ConfigMgr *p_mgr,
|
||||||
IConfig *p_topConfig,
|
IConfig *p_topConfig,
|
||||||
@ -33,7 +34,10 @@ void MarkdownEditorConfig::init(const QJsonObject &p_app, const QJsonObject &p_u
|
|||||||
m_prependDotInRelativeLink = READBOOL(QStringLiteral("prepend_dot_in_relative_link"));
|
m_prependDotInRelativeLink = READBOOL(QStringLiteral("prepend_dot_in_relative_link"));
|
||||||
m_confirmBeforeClearObsoleteImages = READBOOL(QStringLiteral("confirm_before_clear_obsolete_images"));
|
m_confirmBeforeClearObsoleteImages = READBOOL(QStringLiteral("confirm_before_clear_obsolete_images"));
|
||||||
m_insertFileNameAsTitle = READBOOL(QStringLiteral("insert_file_name_as_title"));
|
m_insertFileNameAsTitle = READBOOL(QStringLiteral("insert_file_name_as_title"));
|
||||||
m_sectionNumberEnabled = READBOOL(QStringLiteral("section_number"));
|
|
||||||
|
m_sectionNumberMode = stringToSectionNumberMode(READSTR(QStringLiteral("section_number")));
|
||||||
|
m_sectionNumberBaseLevel = READINT(QStringLiteral("section_number_base_level"));
|
||||||
|
|
||||||
m_constrainImageWidthEnabled = READBOOL(QStringLiteral("constrain_image_width"));
|
m_constrainImageWidthEnabled = READBOOL(QStringLiteral("constrain_image_width"));
|
||||||
m_constrainInPlacePreviewWidthEnabled = READBOOL(QStringLiteral("constrain_inplace_preview_width"));
|
m_constrainInPlacePreviewWidthEnabled = READBOOL(QStringLiteral("constrain_inplace_preview_width"));
|
||||||
m_zoomFactorInReadMode = READREAL(QStringLiteral("zoom_factor_in_read_mode"));
|
m_zoomFactorInReadMode = READREAL(QStringLiteral("zoom_factor_in_read_mode"));
|
||||||
@ -53,7 +57,10 @@ QJsonObject MarkdownEditorConfig::toJson() const
|
|||||||
obj[QStringLiteral("prepend_dot_in_relative_link")] = m_prependDotInRelativeLink;
|
obj[QStringLiteral("prepend_dot_in_relative_link")] = m_prependDotInRelativeLink;
|
||||||
obj[QStringLiteral("confirm_before_clear_obsolete_images")] = m_confirmBeforeClearObsoleteImages;
|
obj[QStringLiteral("confirm_before_clear_obsolete_images")] = m_confirmBeforeClearObsoleteImages;
|
||||||
obj[QStringLiteral("insert_file_name_as_title")] = m_insertFileNameAsTitle;
|
obj[QStringLiteral("insert_file_name_as_title")] = m_insertFileNameAsTitle;
|
||||||
obj[QStringLiteral("section_number")] = m_sectionNumberEnabled;
|
|
||||||
|
obj[QStringLiteral("section_number")] = sectionNumberModeToString(m_sectionNumberMode);
|
||||||
|
obj[QStringLiteral("section_number_base_level")] = m_sectionNumberBaseLevel;
|
||||||
|
|
||||||
obj[QStringLiteral("constrain_image_width")] = m_constrainImageWidthEnabled;
|
obj[QStringLiteral("constrain_image_width")] = m_constrainImageWidthEnabled;
|
||||||
obj[QStringLiteral("constrain_inplace_preview_width")] = m_constrainInPlacePreviewWidthEnabled;
|
obj[QStringLiteral("constrain_inplace_preview_width")] = m_constrainInPlacePreviewWidthEnabled;
|
||||||
obj[QStringLiteral("zoom_factor_in_read_mode")] = m_zoomFactorInReadMode;
|
obj[QStringLiteral("zoom_factor_in_read_mode")] = m_zoomFactorInReadMode;
|
||||||
@ -147,16 +154,6 @@ void MarkdownEditorConfig::setInsertFileNameAsTitle(bool p_enabled)
|
|||||||
updateConfig(m_insertFileNameAsTitle, p_enabled, this);
|
updateConfig(m_insertFileNameAsTitle, p_enabled, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MarkdownEditorConfig::getSectionNumberEnabled() const
|
|
||||||
{
|
|
||||||
return m_sectionNumberEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MarkdownEditorConfig::setSectionNumberEnabled(bool p_enabled)
|
|
||||||
{
|
|
||||||
updateConfig(m_sectionNumberEnabled, p_enabled, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MarkdownEditorConfig::getConstrainImageWidthEnabled() const
|
bool MarkdownEditorConfig::getConstrainImageWidthEnabled() const
|
||||||
{
|
{
|
||||||
return m_constrainImageWidthEnabled;
|
return m_constrainImageWidthEnabled;
|
||||||
@ -231,3 +228,49 @@ void MarkdownEditorConfig::setLinkifyEnabled(bool p_enabled)
|
|||||||
{
|
{
|
||||||
updateConfig(m_linkifyEnabled, p_enabled, this);
|
updateConfig(m_linkifyEnabled, p_enabled, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString MarkdownEditorConfig::sectionNumberModeToString(SectionNumberMode p_mode) const
|
||||||
|
{
|
||||||
|
switch (p_mode) {
|
||||||
|
case SectionNumberMode::None:
|
||||||
|
return QStringLiteral("none");
|
||||||
|
|
||||||
|
case SectionNumberMode::Edit:
|
||||||
|
return QStringLiteral("edit");
|
||||||
|
|
||||||
|
default:
|
||||||
|
return QStringLiteral("read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkdownEditorConfig::SectionNumberMode MarkdownEditorConfig::stringToSectionNumberMode(const QString &p_str) const
|
||||||
|
{
|
||||||
|
auto mode = p_str.toLower();
|
||||||
|
if (mode == QStringLiteral("none")) {
|
||||||
|
return SectionNumberMode::None;
|
||||||
|
} else if (mode == QStringLiteral("edit")) {
|
||||||
|
return SectionNumberMode::Edit;
|
||||||
|
} else {
|
||||||
|
return SectionNumberMode::Read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkdownEditorConfig::SectionNumberMode MarkdownEditorConfig::getSectionNumberMode() const
|
||||||
|
{
|
||||||
|
return m_sectionNumberMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarkdownEditorConfig::setSectionNumberMode(SectionNumberMode p_mode)
|
||||||
|
{
|
||||||
|
updateConfig(m_sectionNumberMode, p_mode, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int MarkdownEditorConfig::getSectionNumberBaseLevel() const
|
||||||
|
{
|
||||||
|
return m_sectionNumberBaseLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarkdownEditorConfig::setSectionNumberBaseLevel(int p_level)
|
||||||
|
{
|
||||||
|
updateConfig(m_sectionNumberBaseLevel, p_level, this);
|
||||||
|
}
|
||||||
|
@ -15,6 +15,13 @@ namespace vnotex
|
|||||||
class MarkdownEditorConfig : public IConfig
|
class MarkdownEditorConfig : public IConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum SectionNumberMode
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Read,
|
||||||
|
Edit
|
||||||
|
};
|
||||||
|
|
||||||
MarkdownEditorConfig(ConfigMgr *p_mgr,
|
MarkdownEditorConfig(ConfigMgr *p_mgr,
|
||||||
IConfig *p_topConfig,
|
IConfig *p_topConfig,
|
||||||
const QSharedPointer<TextEditorConfig> &p_textEditorConfig);
|
const QSharedPointer<TextEditorConfig> &p_textEditorConfig);
|
||||||
@ -45,8 +52,11 @@ namespace vnotex
|
|||||||
bool getInsertFileNameAsTitle() const;
|
bool getInsertFileNameAsTitle() const;
|
||||||
void setInsertFileNameAsTitle(bool p_enabled);
|
void setInsertFileNameAsTitle(bool p_enabled);
|
||||||
|
|
||||||
bool getSectionNumberEnabled() const;
|
SectionNumberMode getSectionNumberMode() const;
|
||||||
void setSectionNumberEnabled(bool p_enabled);
|
void setSectionNumberMode(SectionNumberMode p_mode);
|
||||||
|
|
||||||
|
int getSectionNumberBaseLevel() const;
|
||||||
|
void setSectionNumberBaseLevel(int p_level);
|
||||||
|
|
||||||
bool getConstrainImageWidthEnabled() const;
|
bool getConstrainImageWidthEnabled() const;
|
||||||
void setConstrainImageWidthEnabled(bool p_enabled);
|
void setConstrainImageWidthEnabled(bool p_enabled);
|
||||||
@ -72,6 +82,9 @@ namespace vnotex
|
|||||||
void setLinkifyEnabled(bool p_enabled);
|
void setLinkifyEnabled(bool p_enabled);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QString sectionNumberModeToString(SectionNumberMode p_mode) const;
|
||||||
|
SectionNumberMode stringToSectionNumberMode(const QString &p_str) const;
|
||||||
|
|
||||||
QSharedPointer<TextEditorConfig> m_textEditorConfig;
|
QSharedPointer<TextEditorConfig> m_textEditorConfig;
|
||||||
|
|
||||||
ViewerResource m_viewerResource;
|
ViewerResource m_viewerResource;
|
||||||
@ -91,7 +104,10 @@ namespace vnotex
|
|||||||
bool m_insertFileNameAsTitle = true;
|
bool m_insertFileNameAsTitle = true;
|
||||||
|
|
||||||
// Whether enable section numbering.
|
// Whether enable section numbering.
|
||||||
bool m_sectionNumberEnabled = true;
|
SectionNumberMode m_sectionNumberMode = SectionNumberMode::Read;
|
||||||
|
|
||||||
|
// 1 based.
|
||||||
|
int m_sectionNumberBaseLevel = 2;
|
||||||
|
|
||||||
// Whether enable image width constraint.
|
// Whether enable image width constraint.
|
||||||
bool m_constrainImageWidthEnabled = true;
|
bool m_constrainImageWidthEnabled = true;
|
||||||
|
@ -72,6 +72,7 @@
|
|||||||
<file>icons/stay_on_top.svg</file>
|
<file>icons/stay_on_top.svg</file>
|
||||||
<file>icons/outline_editor.svg</file>
|
<file>icons/outline_editor.svg</file>
|
||||||
<file>icons/find_replace_editor.svg</file>
|
<file>icons/find_replace_editor.svg</file>
|
||||||
|
<file>icons/section_number_editor.svg</file>
|
||||||
<file>logo/vnote.svg</file>
|
<file>logo/vnote.svg</file>
|
||||||
<file>logo/vnote.png</file>
|
<file>logo/vnote.png</file>
|
||||||
<file>logo/256x256/vnote.png</file>
|
<file>logo/256x256/vnote.png</file>
|
||||||
|
7
src/data/core/icons/section_number_editor.svg
Normal file
7
src/data/core/icons/section_number_editor.svg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<svg width="512" height="512" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
|
||||||
|
<g>
|
||||||
|
<title>Layer 2</title>
|
||||||
|
<text stroke="#000000" transform="matrix(11.892995768998892,0,0,12.532065948318316,-399.2455647895517,-874.5950374851516) " xml:space="preserve" text-anchor="middle" font-family="Sans-serif" font-size="24" id="svg_1" y="98.48198" x="55.1146" stroke-width="0" fill="#000000">1.2.</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 502 B |
@ -226,8 +226,10 @@
|
|||||||
"confirm_before_clear_obsolete_images" : true,
|
"confirm_before_clear_obsolete_images" : true,
|
||||||
"//comment" : "Whether insert the file name as title on new file",
|
"//comment" : "Whether insert the file name as title on new file",
|
||||||
"insert_file_name_as_title" : true,
|
"insert_file_name_as_title" : true,
|
||||||
"//comment" : "Whether enable auto section numbering",
|
"//comment" : "none/read/edit",
|
||||||
"section_number" : true,
|
"section_number" : "read",
|
||||||
|
"//comment" : "base level to start section numbering, valid only in edit mode",
|
||||||
|
"section_number_base_level" : 2,
|
||||||
"//comment" : "Whether enable image width constraint",
|
"//comment" : "Whether enable image width constraint",
|
||||||
"constrain_image_width" : true,
|
"constrain_image_width" : true,
|
||||||
"//comment" : "Whether enable in-place preview width constraint",
|
"//comment" : "Whether enable in-place preview width constraint",
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QDoubleSpinBox>
|
#include <QDoubleSpinBox>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
#include <widgets/widgetsfactory.h>
|
#include <widgets/widgetsfactory.h>
|
||||||
#include <core/editorconfig.h>
|
#include <core/editorconfig.h>
|
||||||
@ -25,6 +28,9 @@ void MarkdownEditorPage::setupUI()
|
|||||||
{
|
{
|
||||||
auto mainLayout = new QVBoxLayout(this);
|
auto mainLayout = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
auto generalBox = setupGeneralGroup();
|
||||||
|
mainLayout->addWidget(generalBox);
|
||||||
|
|
||||||
auto readBox = setupReadGroup();
|
auto readBox = setupReadGroup();
|
||||||
mainLayout->addWidget(readBox);
|
mainLayout->addWidget(readBox);
|
||||||
|
|
||||||
@ -38,7 +44,13 @@ void MarkdownEditorPage::loadInternal()
|
|||||||
|
|
||||||
m_insertFileNameAsTitleCheckBox->setChecked(markdownConfig.getInsertFileNameAsTitle());
|
m_insertFileNameAsTitleCheckBox->setChecked(markdownConfig.getInsertFileNameAsTitle());
|
||||||
|
|
||||||
m_sectionNumberCheckBox->setChecked(markdownConfig.getSectionNumberEnabled());
|
{
|
||||||
|
int idx = m_sectionNumberComboBox->findData(static_cast<int>(markdownConfig.getSectionNumberMode()));
|
||||||
|
Q_ASSERT(idx != -1);
|
||||||
|
m_sectionNumberComboBox->setCurrentIndex(idx);
|
||||||
|
|
||||||
|
m_sectionNumberBaseLevelSpinBox->setValue(markdownConfig.getSectionNumberBaseLevel());
|
||||||
|
}
|
||||||
|
|
||||||
m_constrainImageWidthCheckBox->setChecked(markdownConfig.getConstrainImageWidthEnabled());
|
m_constrainImageWidthCheckBox->setChecked(markdownConfig.getConstrainImageWidthEnabled());
|
||||||
|
|
||||||
@ -61,7 +73,14 @@ void MarkdownEditorPage::saveInternal()
|
|||||||
|
|
||||||
markdownConfig.setInsertFileNameAsTitle(m_insertFileNameAsTitleCheckBox->isChecked());
|
markdownConfig.setInsertFileNameAsTitle(m_insertFileNameAsTitleCheckBox->isChecked());
|
||||||
|
|
||||||
markdownConfig.setSectionNumberEnabled(m_sectionNumberCheckBox->isChecked());
|
{
|
||||||
|
auto mode = m_sectionNumberComboBox->currentData().toInt();
|
||||||
|
markdownConfig.setSectionNumberMode(static_cast<MarkdownEditorConfig::SectionNumberMode>(mode));
|
||||||
|
|
||||||
|
if (m_sectionNumberBaseLevelSpinBox->isEnabled()) {
|
||||||
|
markdownConfig.setSectionNumberBaseLevel(m_sectionNumberBaseLevelSpinBox->value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
markdownConfig.setConstrainImageWidthEnabled(m_constrainImageWidthCheckBox->isChecked());
|
markdownConfig.setConstrainImageWidthEnabled(m_constrainImageWidthCheckBox->isChecked());
|
||||||
|
|
||||||
@ -90,16 +109,6 @@ QGroupBox *MarkdownEditorPage::setupReadGroup()
|
|||||||
auto box = new QGroupBox(tr("Read"), this);
|
auto box = new QGroupBox(tr("Read"), this);
|
||||||
auto layout = new QFormLayout(box);
|
auto layout = new QFormLayout(box);
|
||||||
|
|
||||||
{
|
|
||||||
const QString label(tr("Section number"));
|
|
||||||
m_sectionNumberCheckBox = WidgetsFactory::createCheckBox(label, box);
|
|
||||||
m_sectionNumberCheckBox->setToolTip(tr("Display section number of headings in read mode"));
|
|
||||||
layout->addRow(m_sectionNumberCheckBox);
|
|
||||||
addSearchItem(label, m_sectionNumberCheckBox->toolTip(), m_sectionNumberCheckBox);
|
|
||||||
connect(m_sectionNumberCheckBox, &QCheckBox::stateChanged,
|
|
||||||
this, &MarkdownEditorPage::pageIsChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const QString label(tr("Constrain image width"));
|
const QString label(tr("Constrain image width"));
|
||||||
m_constrainImageWidthCheckBox = WidgetsFactory::createCheckBox(label, box);
|
m_constrainImageWidthCheckBox = WidgetsFactory::createCheckBox(label, box);
|
||||||
@ -194,3 +203,43 @@ QGroupBox *MarkdownEditorPage::setupEditGroup()
|
|||||||
|
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QGroupBox *MarkdownEditorPage::setupGeneralGroup()
|
||||||
|
{
|
||||||
|
auto box = new QGroupBox(tr("General"), this);
|
||||||
|
auto layout = new QFormLayout(box);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto sectionLayout = new QHBoxLayout();
|
||||||
|
|
||||||
|
m_sectionNumberComboBox = WidgetsFactory::createComboBox(this);
|
||||||
|
m_sectionNumberComboBox->setToolTip(tr("Section number mode"));
|
||||||
|
|
||||||
|
m_sectionNumberComboBox->addItem(tr("None"), (int)MarkdownEditorConfig::SectionNumberMode::None);
|
||||||
|
m_sectionNumberComboBox->addItem(tr("Read"), (int)MarkdownEditorConfig::SectionNumberMode::Read);
|
||||||
|
m_sectionNumberComboBox->addItem(tr("Edit"), (int)MarkdownEditorConfig::SectionNumberMode::Edit);
|
||||||
|
|
||||||
|
sectionLayout->addWidget(m_sectionNumberComboBox);
|
||||||
|
connect(m_sectionNumberComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||||
|
this, &MarkdownEditorPage::pageIsChanged);
|
||||||
|
|
||||||
|
m_sectionNumberBaseLevelSpinBox = WidgetsFactory::createSpinBox(this);
|
||||||
|
m_sectionNumberBaseLevelSpinBox->setToolTip(tr("Base level to start section numbering in edit mode"));
|
||||||
|
m_sectionNumberBaseLevelSpinBox->setRange(1, 6);
|
||||||
|
m_sectionNumberBaseLevelSpinBox->setSingleStep(1);
|
||||||
|
|
||||||
|
sectionLayout->addWidget(m_sectionNumberBaseLevelSpinBox);
|
||||||
|
connect(m_sectionNumberBaseLevelSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
|
||||||
|
this, &MarkdownEditorPage::pageIsChanged);
|
||||||
|
connect(m_sectionNumberComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||||
|
this, [this](int p_index) {
|
||||||
|
m_sectionNumberBaseLevelSpinBox->setEnabled(p_index == MarkdownEditorConfig::SectionNumberMode::Edit);
|
||||||
|
});
|
||||||
|
|
||||||
|
const QString label(tr("Section number:"));
|
||||||
|
layout->addRow(label, sectionLayout);
|
||||||
|
addSearchItem(label, m_sectionNumberComboBox->toolTip(), m_sectionNumberComboBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
class QCheckBox;
|
class QCheckBox;
|
||||||
class QGroupBox;
|
class QGroupBox;
|
||||||
class QDoubleSpinBox;
|
class QDoubleSpinBox;
|
||||||
|
class QSpinBox;
|
||||||
|
class QComboBox;
|
||||||
|
|
||||||
namespace vnotex
|
namespace vnotex
|
||||||
{
|
{
|
||||||
@ -25,14 +27,14 @@ namespace vnotex
|
|||||||
private:
|
private:
|
||||||
void setupUI();
|
void setupUI();
|
||||||
|
|
||||||
|
QGroupBox *setupGeneralGroup();
|
||||||
|
|
||||||
QGroupBox *setupReadGroup();
|
QGroupBox *setupReadGroup();
|
||||||
|
|
||||||
QGroupBox *setupEditGroup();
|
QGroupBox *setupEditGroup();
|
||||||
|
|
||||||
QCheckBox *m_insertFileNameAsTitleCheckBox = nullptr;
|
QCheckBox *m_insertFileNameAsTitleCheckBox = nullptr;
|
||||||
|
|
||||||
QCheckBox *m_sectionNumberCheckBox = nullptr;
|
|
||||||
|
|
||||||
QCheckBox *m_constrainImageWidthCheckBox = nullptr;
|
QCheckBox *m_constrainImageWidthCheckBox = nullptr;
|
||||||
|
|
||||||
QCheckBox *m_constrainInPlacePreviewWidthCheckBox = nullptr;
|
QCheckBox *m_constrainInPlacePreviewWidthCheckBox = nullptr;
|
||||||
@ -46,6 +48,10 @@ namespace vnotex
|
|||||||
QCheckBox *m_linkifyCheckBox = nullptr;
|
QCheckBox *m_linkifyCheckBox = nullptr;
|
||||||
|
|
||||||
QDoubleSpinBox *m_zoomFactorSpinBox = nullptr;
|
QDoubleSpinBox *m_zoomFactorSpinBox = nullptr;
|
||||||
|
|
||||||
|
QComboBox *m_sectionNumberComboBox = nullptr;
|
||||||
|
|
||||||
|
QSpinBox *m_sectionNumberBaseLevelSpinBox = nullptr;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "texteditorpage.h"
|
#include "texteditorpage.h"
|
||||||
#include "markdowneditorpage.h"
|
#include "markdowneditorpage.h"
|
||||||
#include "appearancepage.h"
|
#include "appearancepage.h"
|
||||||
|
#include "themepage.h"
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
@ -72,45 +73,36 @@ void SettingsDialog::setupPages()
|
|||||||
// General.
|
// General.
|
||||||
{
|
{
|
||||||
auto page = new GeneralPage(this);
|
auto page = new GeneralPage(this);
|
||||||
m_pageLayout->addWidget(page);
|
addPage(page);
|
||||||
|
|
||||||
auto item = new QTreeWidgetItem(m_pageExplorer);
|
|
||||||
setupPage(item, page);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appearance.
|
// Appearance.
|
||||||
{
|
{
|
||||||
auto page = new AppearancePage(this);
|
auto page = new AppearancePage(this);
|
||||||
m_pageLayout->addWidget(page);
|
auto item = addPage(page);
|
||||||
|
|
||||||
auto item = new QTreeWidgetItem(m_pageExplorer);
|
// Theme.
|
||||||
setupPage(item, page);
|
{
|
||||||
|
auto subPage = new ThemePage(this);
|
||||||
|
addSubPage(subPage, item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Editor.
|
// Editor.
|
||||||
{
|
{
|
||||||
auto page = new EditorPage(this);
|
auto page = new EditorPage(this);
|
||||||
m_pageLayout->addWidget(page);
|
auto item = addPage(page);
|
||||||
|
|
||||||
auto item = new QTreeWidgetItem(m_pageExplorer);
|
|
||||||
setupPage(item, page);
|
|
||||||
|
|
||||||
// Text Editor.
|
// Text Editor.
|
||||||
{
|
{
|
||||||
auto subPage = new TextEditorPage(this);
|
auto subPage = new TextEditorPage(this);
|
||||||
m_pageLayout->addWidget(subPage);
|
addSubPage(subPage, item);
|
||||||
|
|
||||||
auto subItem = new QTreeWidgetItem(item);
|
|
||||||
setupPage(subItem, subPage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Markdown Editor.
|
// Markdown Editor.
|
||||||
{
|
{
|
||||||
auto subPage = new MarkdownEditorPage(this);
|
auto subPage = new MarkdownEditorPage(this);
|
||||||
m_pageLayout->addWidget(subPage);
|
addSubPage(subPage, item);
|
||||||
|
|
||||||
auto subItem = new QTreeWidgetItem(item);
|
|
||||||
setupPage(subItem, subPage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,3 +183,21 @@ void SettingsDialog::forEachPage(const std::function<void(SettingsPage *)> &p_fu
|
|||||||
p_func(page);
|
p_func(page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QTreeWidgetItem *SettingsDialog::addPage(SettingsPage *p_page)
|
||||||
|
{
|
||||||
|
m_pageLayout->addWidget(p_page);
|
||||||
|
|
||||||
|
auto item = new QTreeWidgetItem(m_pageExplorer);
|
||||||
|
setupPage(item, p_page);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTreeWidgetItem *SettingsDialog::addSubPage(SettingsPage *p_page, QTreeWidgetItem *p_parentItem)
|
||||||
|
{
|
||||||
|
m_pageLayout->addWidget(p_page);
|
||||||
|
|
||||||
|
auto subItem = new QTreeWidgetItem(p_parentItem);
|
||||||
|
setupPage(subItem, p_page);
|
||||||
|
return subItem;
|
||||||
|
}
|
||||||
|
@ -44,6 +44,10 @@ namespace vnotex
|
|||||||
|
|
||||||
void forEachPage(const std::function<void(SettingsPage *)> &p_func);
|
void forEachPage(const std::function<void(SettingsPage *)> &p_func);
|
||||||
|
|
||||||
|
QTreeWidgetItem *addPage(SettingsPage *p_page);
|
||||||
|
|
||||||
|
QTreeWidgetItem *addSubPage(SettingsPage *p_page, QTreeWidgetItem *p_parentItem);
|
||||||
|
|
||||||
QLineEdit *m_searchEdit = nullptr;
|
QLineEdit *m_searchEdit = nullptr;
|
||||||
|
|
||||||
QTreeWidget *m_pageExplorer = nullptr;
|
QTreeWidget *m_pageExplorer = nullptr;
|
||||||
|
32
src/widgets/dialogs/settings/themepage.cpp
Normal file
32
src/widgets/dialogs/settings/themepage.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "themepage.h"
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include <widgets/widgetsfactory.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
ThemePage::ThemePage(QWidget *p_parent)
|
||||||
|
: SettingsPage(p_parent)
|
||||||
|
{
|
||||||
|
setupUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThemePage::setupUI()
|
||||||
|
{
|
||||||
|
auto mainLayout = new QVBoxLayout(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThemePage::loadInternal()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThemePage::saveInternal()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ThemePage::title() const
|
||||||
|
{
|
||||||
|
return tr("Theme");
|
||||||
|
}
|
26
src/widgets/dialogs/settings/themepage.h
Normal file
26
src/widgets/dialogs/settings/themepage.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef THEMEPAGE_H
|
||||||
|
#define THEMEPAGE_H
|
||||||
|
|
||||||
|
#include "settingspage.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class ThemePage : public SettingsPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ThemePage(QWidget *p_parent = nullptr);
|
||||||
|
|
||||||
|
QString title() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void loadInternal() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void saveInternal() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupUI();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // THEMEPAGE_H
|
@ -37,6 +37,7 @@
|
|||||||
#include <utils/textutils.h>
|
#include <utils/textutils.h>
|
||||||
#include <core/exception.h>
|
#include <core/exception.h>
|
||||||
#include <core/markdowneditorconfig.h>
|
#include <core/markdowneditorconfig.h>
|
||||||
|
#include <core/texteditorconfig.h>
|
||||||
#include <core/configmgr.h>
|
#include <core/configmgr.h>
|
||||||
#include <core/editorconfig.h>
|
#include <core/editorconfig.h>
|
||||||
|
|
||||||
@ -48,9 +49,13 @@ using namespace vnotex;
|
|||||||
// We set the property of the clipboard to mark that we are requesting a rich paste.
|
// We set the property of the clipboard to mark that we are requesting a rich paste.
|
||||||
static const char *c_clipboardPropertyMark = "RichPaste";
|
static const char *c_clipboardPropertyMark = "RichPaste";
|
||||||
|
|
||||||
MarkdownEditor::Heading::Heading(const QString &p_name, int p_level, int p_blockNumber)
|
MarkdownEditor::Heading::Heading(const QString &p_name,
|
||||||
|
int p_level,
|
||||||
|
const QString &p_sectionNumber,
|
||||||
|
int p_blockNumber)
|
||||||
: m_name(p_name),
|
: m_name(p_name),
|
||||||
m_level(p_level),
|
m_level(p_level),
|
||||||
|
m_sectionNumber(p_sectionNumber),
|
||||||
m_blockNumber(p_blockNumber)
|
m_blockNumber(p_blockNumber)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -71,17 +76,25 @@ MarkdownEditor::MarkdownEditor(const MarkdownEditorConfig &p_config,
|
|||||||
this, &MarkdownEditor::handleContextMenuEvent);
|
this, &MarkdownEditor::handleContextMenuEvent);
|
||||||
|
|
||||||
connect(getHighlighter(), &vte::PegMarkdownHighlighter::headersUpdated,
|
connect(getHighlighter(), &vte::PegMarkdownHighlighter::headersUpdated,
|
||||||
this, [this](const QVector<vte::peg::ElementRegion> &p_headerRegions) {
|
this, &MarkdownEditor::updateHeadings);
|
||||||
// TODO: insert heading sequence.
|
|
||||||
updateHeadings(p_headerRegions);
|
|
||||||
});
|
|
||||||
|
|
||||||
m_headingTimer = new QTimer(this);
|
m_headingTimer = new QTimer(this);
|
||||||
m_headingTimer->setInterval(500);
|
m_headingTimer->setInterval(500);
|
||||||
|
m_headingTimer->setSingleShot(true);
|
||||||
connect(m_headingTimer, &QTimer::timeout,
|
connect(m_headingTimer, &QTimer::timeout,
|
||||||
this, &MarkdownEditor::currentHeadingChanged);
|
this, &MarkdownEditor::currentHeadingChanged);
|
||||||
connect(m_textEdit, &vte::VTextEdit::cursorLineChanged,
|
connect(m_textEdit, &vte::VTextEdit::cursorLineChanged,
|
||||||
m_headingTimer, QOverload<>::of(&QTimer::start));
|
m_headingTimer, QOverload<>::of(&QTimer::start));
|
||||||
|
|
||||||
|
m_sectionNumberTimer = new QTimer(this);
|
||||||
|
m_sectionNumberTimer->setInterval(1000);
|
||||||
|
m_sectionNumberTimer->setSingleShot(true);
|
||||||
|
connect(m_sectionNumberTimer, &QTimer::timeout,
|
||||||
|
this, [this]() {
|
||||||
|
updateSectionNumber(m_headings);
|
||||||
|
});
|
||||||
|
|
||||||
|
updateFromConfig(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkdownEditor::~MarkdownEditor()
|
MarkdownEditor::~MarkdownEditor()
|
||||||
@ -719,13 +732,29 @@ int MarkdownEditor::getCurrentHeadingIndex() const
|
|||||||
|
|
||||||
void MarkdownEditor::updateHeadings(const QVector<vte::peg::ElementRegion> &p_headerRegions)
|
void MarkdownEditor::updateHeadings(const QVector<vte::peg::ElementRegion> &p_headerRegions)
|
||||||
{
|
{
|
||||||
auto doc = document();
|
bool needUpdateSectionNumber = false;
|
||||||
|
if (isReadOnly()) {
|
||||||
|
m_sectionNumberEnabled = false;
|
||||||
|
} else {
|
||||||
|
needUpdateSectionNumber = m_config.getSectionNumberMode() == MarkdownEditorConfig::SectionNumberMode::Edit;
|
||||||
|
if (m_overriddenSectionNumber != OverrideState::NoOverride) {
|
||||||
|
needUpdateSectionNumber = m_overriddenSectionNumber == OverrideState::ForceEnable;
|
||||||
|
}
|
||||||
|
if (needUpdateSectionNumber) {
|
||||||
|
m_sectionNumberEnabled = true;
|
||||||
|
} else if (m_sectionNumberEnabled) {
|
||||||
|
// On -> Off. We still need to do the clean up.
|
||||||
|
needUpdateSectionNumber = true;
|
||||||
|
m_sectionNumberEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QVector<Heading> headings;
|
QVector<Heading> headings;
|
||||||
headings.reserve(p_headerRegions.size());
|
headings.reserve(p_headerRegions.size());
|
||||||
|
|
||||||
// Assume that each block contains only one line.
|
// Assume that each block contains only one line.
|
||||||
// Only support # syntax for now.
|
// Only support # syntax for now.
|
||||||
|
auto doc = document();
|
||||||
QRegExp headerReg(vte::MarkdownUtils::c_headerRegExp);
|
QRegExp headerReg(vte::MarkdownUtils::c_headerRegExp);
|
||||||
for (auto const ® : p_headerRegions) {
|
for (auto const ® : p_headerRegions) {
|
||||||
auto block = doc->findBlock(reg.m_startPos);
|
auto block = doc->findBlock(reg.m_startPos);
|
||||||
@ -738,14 +767,22 @@ void MarkdownEditor::updateHeadings(const QVector<vte::peg::ElementRegion> &p_he
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (headerReg.exactMatch(block.text())) {
|
if (headerReg.exactMatch(block.text())) {
|
||||||
int level = headerReg.cap(1).length();
|
const int level = headerReg.cap(1).length();
|
||||||
Heading heading(headerReg.cap(2).trimmed(), level, block.blockNumber());
|
Heading heading(headerReg.cap(2).trimmed(),
|
||||||
|
level,
|
||||||
|
headerReg.cap(3),
|
||||||
|
block.blockNumber());
|
||||||
headings.append(heading);
|
headings.append(heading);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OutlineProvider::makePerfectHeadings(headings, m_headings);
|
OutlineProvider::makePerfectHeadings(headings, m_headings);
|
||||||
|
|
||||||
|
if (needUpdateSectionNumber) {
|
||||||
|
// Use a timer to kick off the update to let user have time to undo.
|
||||||
|
m_sectionNumberTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
emit headingsChanged();
|
emit headingsChanged();
|
||||||
|
|
||||||
emit currentHeadingChanged();
|
emit currentHeadingChanged();
|
||||||
@ -1045,3 +1082,121 @@ void MarkdownEditor::fetchImagesToLocalAndReplace(QString &p_text)
|
|||||||
|
|
||||||
proDlg.setValue(regs.size());
|
proDlg.setValue(regs.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void increaseSectionNumber(QVector<int> &p_sectionNumber, int p_level, int p_baseLevel)
|
||||||
|
{
|
||||||
|
Q_ASSERT(p_level >= 1 && p_level < p_sectionNumber.size());
|
||||||
|
if (p_level < p_baseLevel) {
|
||||||
|
p_sectionNumber.fill(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
++p_sectionNumber[p_level];
|
||||||
|
for (int i = p_level + 1; i < p_sectionNumber.size(); ++i) {
|
||||||
|
p_sectionNumber[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static QString joinSectionNumberStr(const QVector<int> &p_sectionNumber)
|
||||||
|
{
|
||||||
|
QString res;
|
||||||
|
for (auto sec : p_sectionNumber) {
|
||||||
|
if (sec != 0) {
|
||||||
|
res = res + QString::number(sec) + '.';
|
||||||
|
} else if (res.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool updateHeadingSectionNumber(QTextCursor &p_cursor,
|
||||||
|
const QTextBlock &p_block,
|
||||||
|
QRegExp &p_headingReg,
|
||||||
|
QRegExp &p_prefixReg,
|
||||||
|
const QString &p_sectionNumber)
|
||||||
|
{
|
||||||
|
if (!p_block.isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString text = p_block.text();
|
||||||
|
bool matched = p_headingReg.exactMatch(text);
|
||||||
|
Q_ASSERT(matched);
|
||||||
|
|
||||||
|
matched = p_prefixReg.exactMatch(text);
|
||||||
|
Q_ASSERT(matched);
|
||||||
|
|
||||||
|
int start = p_headingReg.cap(1).length() + 1;
|
||||||
|
int end = p_prefixReg.cap(1).length();
|
||||||
|
|
||||||
|
Q_ASSERT(start <= end);
|
||||||
|
|
||||||
|
p_cursor.setPosition(p_block.position() + start);
|
||||||
|
if (start != end) {
|
||||||
|
p_cursor.setPosition(p_block.position() + end, QTextCursor::KeepAnchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_sectionNumber.isEmpty()) {
|
||||||
|
p_cursor.removeSelectedText();
|
||||||
|
} else {
|
||||||
|
p_cursor.insertText(p_sectionNumber + ' ');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MarkdownEditor::updateSectionNumber(const QVector<Heading> &p_headings)
|
||||||
|
{
|
||||||
|
QVector<int> sectionNumber(7, 0);
|
||||||
|
int baseLevel = m_config.getSectionNumberBaseLevel();
|
||||||
|
if (baseLevel < 1 || baseLevel > 6) {
|
||||||
|
baseLevel = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
auto doc = document();
|
||||||
|
QRegExp headerReg(vte::MarkdownUtils::c_headerRegExp);
|
||||||
|
QRegExp prefixReg(vte::MarkdownUtils::c_headerPrefixRegExp);
|
||||||
|
QTextCursor cursor(doc);
|
||||||
|
cursor.beginEditBlock();
|
||||||
|
for (const auto &heading : p_headings) {
|
||||||
|
increaseSectionNumber(sectionNumber, heading.m_level, baseLevel);
|
||||||
|
auto sectionStr = m_sectionNumberEnabled ? joinSectionNumberStr(sectionNumber) : QString();
|
||||||
|
if (heading.m_blockNumber > -1 && sectionStr != heading.m_sectionNumber) {
|
||||||
|
if (updateHeadingSectionNumber(cursor,
|
||||||
|
doc->findBlockByNumber(heading.m_blockNumber),
|
||||||
|
headerReg,
|
||||||
|
prefixReg,
|
||||||
|
sectionStr)) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursor.endEditBlock();
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarkdownEditor::overrideSectionNumber(OverrideState p_state)
|
||||||
|
{
|
||||||
|
if (m_overriddenSectionNumber == p_state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_overriddenSectionNumber = p_state;
|
||||||
|
getHighlighter()->updateHighlight();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarkdownEditor::updateFromConfig(bool p_initialized)
|
||||||
|
{
|
||||||
|
if (m_config.getTextEditorConfig().getZoomDelta() != 0) {
|
||||||
|
zoom(m_config.getTextEditorConfig().getZoomDelta());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_initialized) {
|
||||||
|
getHighlighter()->updateHighlight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -31,12 +31,18 @@ namespace vnotex
|
|||||||
{
|
{
|
||||||
Heading() = default;
|
Heading() = default;
|
||||||
|
|
||||||
Heading(const QString &p_name, int p_level, int p_blockNumber = -1);
|
Heading(const QString &p_name,
|
||||||
|
int p_level,
|
||||||
|
const QString &p_sectionNumber = QString(),
|
||||||
|
int p_blockNumber = -1);
|
||||||
|
|
||||||
QString m_name;
|
QString m_name;
|
||||||
|
|
||||||
int m_level = -1;
|
int m_level = -1;
|
||||||
|
|
||||||
|
// 1.2. .
|
||||||
|
QString m_sectionNumber;
|
||||||
|
|
||||||
int m_blockNumber = -1;
|
int m_blockNumber = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,6 +90,10 @@ namespace vnotex
|
|||||||
|
|
||||||
void scrollToHeading(int p_idx);
|
void scrollToHeading(int p_idx);
|
||||||
|
|
||||||
|
void overrideSectionNumber(OverrideState p_state);
|
||||||
|
|
||||||
|
void updateFromConfig(bool p_initialized = true);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void handleHtmlToMarkdownData(quint64 p_id, TimeStamp p_timeStamp, const QString &p_text);
|
void handleHtmlToMarkdownData(quint64 p_id, TimeStamp p_timeStamp, const QString &p_text);
|
||||||
|
|
||||||
@ -148,6 +158,8 @@ namespace vnotex
|
|||||||
|
|
||||||
QString getRelativeLink(const QString &p_path);
|
QString getRelativeLink(const QString &p_path);
|
||||||
|
|
||||||
|
// Update section number.
|
||||||
|
// Update headings outline.
|
||||||
void updateHeadings(const QVector<vte::peg::ElementRegion> &p_headerRegions);
|
void updateHeadings(const QVector<vte::peg::ElementRegion> &p_headerRegions);
|
||||||
|
|
||||||
int getHeadingIndexByBlockNumber(int p_blockNumber) const;
|
int getHeadingIndexByBlockNumber(int p_blockNumber) const;
|
||||||
@ -156,6 +168,9 @@ namespace vnotex
|
|||||||
|
|
||||||
void fetchImagesToLocalAndReplace(QString &p_text);
|
void fetchImagesToLocalAndReplace(QString &p_text);
|
||||||
|
|
||||||
|
// Return true if there is change.
|
||||||
|
bool updateSectionNumber(const QVector<Heading> &p_headings);
|
||||||
|
|
||||||
static QString generateImageFileNameToInsertAs(const QString &p_title, const QString &p_suffix);
|
static QString generateImageFileNameToInsertAs(const QString &p_title, const QString &p_suffix);
|
||||||
|
|
||||||
const MarkdownEditorConfig &m_config;
|
const MarkdownEditorConfig &m_config;
|
||||||
@ -168,6 +183,13 @@ namespace vnotex
|
|||||||
TimeStamp m_timeStamp = 0;
|
TimeStamp m_timeStamp = 0;
|
||||||
|
|
||||||
QTimer *m_headingTimer = nullptr;
|
QTimer *m_headingTimer = nullptr;
|
||||||
|
|
||||||
|
QTimer *m_sectionNumberTimer = nullptr;
|
||||||
|
|
||||||
|
// Used to detect the config change and do a clean up.
|
||||||
|
bool m_sectionNumberEnabled = true;
|
||||||
|
|
||||||
|
OverrideState m_overriddenSectionNumber = OverrideState::NoOverride;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,6 +292,7 @@ void MainWindow::closeEvent(QCloseEvent *p_event)
|
|||||||
isExit = true;
|
isExit = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool needShowMessage = false;
|
||||||
if(!isExit && toTray == -1){
|
if(!isExit && toTray == -1){
|
||||||
int ret = MessageBoxHelper::questionYesNo(MessageBoxHelper::Question,
|
int ret = MessageBoxHelper::questionYesNo(MessageBoxHelper::Question,
|
||||||
tr("Do you want to minimize %1 to system tray "
|
tr("Do you want to minimize %1 to system tray "
|
||||||
@ -301,6 +302,7 @@ void MainWindow::closeEvent(QCloseEvent *p_event)
|
|||||||
this);
|
this);
|
||||||
if (ret == QMessageBox::Yes) {
|
if (ret == QMessageBox::Yes) {
|
||||||
ConfigMgr::getInst().getSessionConfig().setMinimizeToSystemTray(true);
|
ConfigMgr::getInst().getSessionConfig().setMinimizeToSystemTray(true);
|
||||||
|
needShowMessage = true;
|
||||||
} else if (ret == QMessageBox::No) {
|
} else if (ret == QMessageBox::No) {
|
||||||
ConfigMgr::getInst().getSessionConfig().setMinimizeToSystemTray(false);
|
ConfigMgr::getInst().getSessionConfig().setMinimizeToSystemTray(false);
|
||||||
isExit = true;
|
isExit = true;
|
||||||
@ -330,6 +332,9 @@ void MainWindow::closeEvent(QCloseEvent *p_event)
|
|||||||
} else {
|
} else {
|
||||||
hide();
|
hide();
|
||||||
p_event->ignore();
|
p_event->ignore();
|
||||||
|
if (needShowMessage) {
|
||||||
|
m_trayIcon->showMessage(ConfigMgr::c_appName, tr("%1 is still running here.").arg(ConfigMgr::c_appName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,9 +186,7 @@ void MarkdownViewWindow::handleEditorConfigChange()
|
|||||||
auto config = createMarkdownEditorConfig(markdownEditorConfig);
|
auto config = createMarkdownEditorConfig(markdownEditorConfig);
|
||||||
m_editor->setConfig(config);
|
m_editor->setConfig(config);
|
||||||
|
|
||||||
if (markdownEditorConfig.getTextEditorConfig().getZoomDelta() != 0) {
|
m_editor->updateFromConfig();
|
||||||
m_editor->zoom(markdownEditorConfig.getTextEditorConfig().getZoomDelta());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateWebViewerConfig(markdownEditorConfig);
|
updateWebViewerConfig(markdownEditorConfig);
|
||||||
@ -269,6 +267,8 @@ void MarkdownViewWindow::setupToolBar()
|
|||||||
|
|
||||||
toolBar->addSeparator();
|
toolBar->addSeparator();
|
||||||
|
|
||||||
|
addAction(toolBar, ViewWindowToolBarHelper::SectionNumber);
|
||||||
|
|
||||||
addAction(toolBar, ViewWindowToolBarHelper::TypeHeading);
|
addAction(toolBar, ViewWindowToolBarHelper::TypeHeading);
|
||||||
addAction(toolBar, ViewWindowToolBarHelper::TypeBold);
|
addAction(toolBar, ViewWindowToolBarHelper::TypeBold);
|
||||||
addAction(toolBar, ViewWindowToolBarHelper::TypeItalic);
|
addAction(toolBar, ViewWindowToolBarHelper::TypeItalic);
|
||||||
@ -306,10 +306,6 @@ void MarkdownViewWindow::setupTextEditor()
|
|||||||
this);
|
this);
|
||||||
m_splitter->insertWidget(0, m_editor);
|
m_splitter->insertWidget(0, m_editor);
|
||||||
|
|
||||||
if (markdownEditorConfig.getTextEditorConfig().getZoomDelta() != 0) {
|
|
||||||
m_editor->zoom(markdownEditorConfig.getTextEditorConfig().getZoomDelta());
|
|
||||||
}
|
|
||||||
|
|
||||||
TextViewWindowHelper::connectEditor(this);
|
TextViewWindowHelper::connectEditor(this);
|
||||||
|
|
||||||
// Status widget.
|
// Status widget.
|
||||||
@ -683,6 +679,13 @@ void MarkdownViewWindow::handleTypeAction(TypeAction p_action)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MarkdownViewWindow::handleSectionNumberOverride(OverrideState p_state)
|
||||||
|
{
|
||||||
|
if (m_mode != Mode::Read) {
|
||||||
|
m_editor->overrideSectionNumber(p_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MarkdownViewWindow::detachFromBufferInternal()
|
void MarkdownViewWindow::detachFromBufferInternal()
|
||||||
{
|
{
|
||||||
auto buffer = getBuffer();
|
auto buffer = getBuffer();
|
||||||
|
@ -49,6 +49,8 @@ namespace vnotex
|
|||||||
|
|
||||||
void handleTypeAction(TypeAction p_action) Q_DECL_OVERRIDE;
|
void handleTypeAction(TypeAction p_action) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void handleSectionNumberOverride(OverrideState p_state) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
void handleFindTextChanged(const QString &p_text, FindOptions p_options) Q_DECL_OVERRIDE;
|
void handleFindTextChanged(const QString &p_text, FindOptions p_options) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
void handleFindNext(const QString &p_text, FindOptions p_options) Q_DECL_OVERRIDE;
|
void handleFindNext(const QString &p_text, FindOptions p_options) Q_DECL_OVERRIDE;
|
||||||
|
@ -38,9 +38,7 @@ void TextViewWindow::setupUI()
|
|||||||
m_editor = new TextEditor(config, this);
|
m_editor = new TextEditor(config, this);
|
||||||
setCentralWidget(m_editor);
|
setCentralWidget(m_editor);
|
||||||
|
|
||||||
if (textEditorConfig.getZoomDelta() != 0) {
|
updateEditorFromConfig();
|
||||||
m_editor->zoom(textEditorConfig.getZoomDelta());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextViewWindowHelper::connectEditor(this);
|
TextViewWindowHelper::connectEditor(this);
|
||||||
@ -135,9 +133,7 @@ void TextViewWindow::handleEditorConfigChange()
|
|||||||
auto config = createTextEditorConfig(textEditorConfig);
|
auto config = createTextEditorConfig(textEditorConfig);
|
||||||
m_editor->setConfig(config);
|
m_editor->setConfig(config);
|
||||||
|
|
||||||
if (textEditorConfig.getZoomDelta() != 0) {
|
updateEditorFromConfig();
|
||||||
m_editor->zoom(textEditorConfig.getZoomDelta());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,3 +205,12 @@ void TextViewWindow::handleFindAndReplaceWidgetClosed()
|
|||||||
{
|
{
|
||||||
TextViewWindowHelper::handleFindAndReplaceWidgetClosed(this);
|
TextViewWindowHelper::handleFindAndReplaceWidgetClosed(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextViewWindow::updateEditorFromConfig()
|
||||||
|
{
|
||||||
|
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
|
||||||
|
const auto &textEditorConfig = editorConfig.getTextEditorConfig();
|
||||||
|
if (textEditorConfig.getZoomDelta() != 0) {
|
||||||
|
m_editor->zoom(textEditorConfig.getZoomDelta());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -64,6 +64,8 @@ namespace vnotex
|
|||||||
// call this function to tell us now the latest buffer revision.
|
// call this function to tell us now the latest buffer revision.
|
||||||
void setBufferRevisionAfterInvalidation(int p_bufferRevision);
|
void setBufferRevisionAfterInvalidation(int p_bufferRevision);
|
||||||
|
|
||||||
|
void updateEditorFromConfig();
|
||||||
|
|
||||||
static QSharedPointer<vte::TextEditorConfig> createTextEditorConfig(const TextEditorConfig &p_config);
|
static QSharedPointer<vte::TextEditorConfig> createTextEditorConfig(const TextEditorConfig &p_config);
|
||||||
|
|
||||||
// Managed by QObject.
|
// Managed by QObject.
|
||||||
|
@ -408,6 +408,23 @@ QAction *ViewWindow::addAction(QToolBar *p_toolBar, ViewWindowToolBarHelper::Act
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ViewWindowToolBarHelper::SectionNumber:
|
||||||
|
{
|
||||||
|
act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
|
||||||
|
connect(this, &ViewWindow::modeChanged,
|
||||||
|
this, [this, act]() {
|
||||||
|
act->setEnabled(inModeCanInsert() && getBuffer() && !getBuffer()->isReadOnly());
|
||||||
|
});
|
||||||
|
auto toolBtn = dynamic_cast<QToolButton *>(p_toolBar->widgetForAction(act));
|
||||||
|
Q_ASSERT(toolBtn);
|
||||||
|
connect(toolBtn->menu(), &QMenu::triggered,
|
||||||
|
this, [this](QAction *p_act) {
|
||||||
|
OverrideState state = static_cast<OverrideState>(p_act->data().toInt());
|
||||||
|
handleSectionNumberOverride(state);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return act;
|
return act;
|
||||||
@ -586,6 +603,12 @@ void ViewWindow::handleTypeAction(TypeAction p_action)
|
|||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewWindow::handleSectionNumberOverride(OverrideState p_state)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_state);
|
||||||
|
Q_ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
ViewWindow::TypeAction ViewWindow::toolBarActionToTypeAction(ViewWindowToolBarHelper::Action p_action)
|
ViewWindow::TypeAction ViewWindow::toolBarActionToTypeAction(ViewWindowToolBarHelper::Action p_action)
|
||||||
{
|
{
|
||||||
Q_ASSERT(p_action >= ViewWindowToolBarHelper::Action::TypeBold
|
Q_ASSERT(p_action >= ViewWindowToolBarHelper::Action::TypeBold
|
||||||
|
@ -137,6 +137,8 @@ namespace vnotex
|
|||||||
// Handle all kinds of type action.
|
// Handle all kinds of type action.
|
||||||
virtual void handleTypeAction(TypeAction p_action);
|
virtual void handleTypeAction(TypeAction p_action);
|
||||||
|
|
||||||
|
virtual void handleSectionNumberOverride(OverrideState p_state);
|
||||||
|
|
||||||
virtual void handleFindTextChanged(const QString &p_text, FindOptions p_options);
|
virtual void handleFindTextChanged(const QString &p_text, FindOptions p_options);
|
||||||
|
|
||||||
virtual void handleFindNext(const QString &p_text, FindOptions p_options);
|
virtual void handleFindNext(const QString &p_text, FindOptions p_options);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QActionGroup>
|
||||||
|
|
||||||
#include "toolbarhelper.h"
|
#include "toolbarhelper.h"
|
||||||
#include <utils/iconutils.h>
|
#include <utils/iconutils.h>
|
||||||
@ -20,6 +21,7 @@
|
|||||||
#include "propertydefs.h"
|
#include "propertydefs.h"
|
||||||
#include "outlinepopup.h"
|
#include "outlinepopup.h"
|
||||||
#include "viewwindow.h"
|
#include "viewwindow.h"
|
||||||
|
#include <core/global.h>
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
@ -306,6 +308,39 @@ QAction *ViewWindowToolBarHelper::addAction(QToolBar *p_tb, Action p_action)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Action::SectionNumber:
|
||||||
|
{
|
||||||
|
act = p_tb->addAction(ToolBarHelper::generateIcon("section_number_editor.svg"),
|
||||||
|
ViewWindow::tr("Section Number"));
|
||||||
|
|
||||||
|
auto toolBtn = dynamic_cast<QToolButton *>(p_tb->widgetForAction(act));
|
||||||
|
Q_ASSERT(toolBtn);
|
||||||
|
toolBtn->setPopupMode(QToolButton::InstantPopup);
|
||||||
|
toolBtn->setProperty(PropertyDefs::s_toolButtonWithoutMenuIndicator, true);
|
||||||
|
|
||||||
|
auto menu = WidgetsFactory::createMenu(p_tb);
|
||||||
|
|
||||||
|
auto actGroup = new QActionGroup(menu);
|
||||||
|
auto act1 = actGroup->addAction(ViewWindow::tr("Follow Configuration"));
|
||||||
|
act1->setCheckable(true);
|
||||||
|
act1->setChecked(true);
|
||||||
|
act1->setData(OverrideState::NoOverride);
|
||||||
|
menu->addAction(act1);
|
||||||
|
|
||||||
|
act1 = actGroup->addAction(ViewWindow::tr("Enabled"));
|
||||||
|
act1->setCheckable(true);
|
||||||
|
act1->setData(OverrideState::ForceEnable);
|
||||||
|
menu->addAction(act1);
|
||||||
|
|
||||||
|
act1 = actGroup->addAction(ViewWindow::tr("Disabled"));
|
||||||
|
act1->setCheckable(true);
|
||||||
|
act1->setData(OverrideState::ForceDisable);
|
||||||
|
menu->addAction(act1);
|
||||||
|
|
||||||
|
toolBtn->setMenu(menu);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
break;
|
break;
|
||||||
|
@ -39,7 +39,8 @@ namespace vnotex
|
|||||||
|
|
||||||
Attachment,
|
Attachment,
|
||||||
Outline,
|
Outline,
|
||||||
FindAndReplace
|
FindAndReplace,
|
||||||
|
SectionNumber
|
||||||
};
|
};
|
||||||
|
|
||||||
static QAction *addAction(QToolBar *p_tb, Action p_action);
|
static QAction *addAction(QToolBar *p_tb, Action p_action);
|
||||||
|
@ -20,6 +20,7 @@ SOURCES += \
|
|||||||
$$PWD/dialogs/settings/settingspage.cpp \
|
$$PWD/dialogs/settings/settingspage.cpp \
|
||||||
$$PWD/dialogs/settings/settingsdialog.cpp \
|
$$PWD/dialogs/settings/settingsdialog.cpp \
|
||||||
$$PWD/dialogs/settings/texteditorpage.cpp \
|
$$PWD/dialogs/settings/texteditorpage.cpp \
|
||||||
|
$$PWD/dialogs/settings/themepage.cpp \
|
||||||
$$PWD/dragdropareaindicator.cpp \
|
$$PWD/dragdropareaindicator.cpp \
|
||||||
$$PWD/editors/editormarkdownvieweradapter.cpp \
|
$$PWD/editors/editormarkdownvieweradapter.cpp \
|
||||||
$$PWD/editors/markdowneditor.cpp \
|
$$PWD/editors/markdowneditor.cpp \
|
||||||
@ -100,6 +101,7 @@ HEADERS += \
|
|||||||
$$PWD/dialogs/settings/settingspage.h \
|
$$PWD/dialogs/settings/settingspage.h \
|
||||||
$$PWD/dialogs/settings/settingsdialog.h \
|
$$PWD/dialogs/settings/settingsdialog.h \
|
||||||
$$PWD/dialogs/settings/texteditorpage.h \
|
$$PWD/dialogs/settings/texteditorpage.h \
|
||||||
|
$$PWD/dialogs/settings/themepage.h \
|
||||||
$$PWD/dragdropareaindicator.h \
|
$$PWD/dragdropareaindicator.h \
|
||||||
$$PWD/editors/editormarkdownvieweradapter.h \
|
$$PWD/editors/editormarkdownvieweradapter.h \
|
||||||
$$PWD/editors/markdowneditor.h \
|
$$PWD/editors/markdowneditor.h \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user