* add file type combobox in NewNoteDialog

* add SectionNumberStyle
This commit is contained in:
Le Tan 2021-01-07 04:41:45 -08:00 committed by GitHub
parent 9dd83a6f2f
commit 6503b433e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 433 additions and 126 deletions

@ -1 +1 @@
Subproject commit 5fe5d4be7191de58fd1c2411b1ff97bcbecfaa3d Subproject commit 69bd57656ccac8cf75502506be0c87d80d86e577

View File

@ -1,54 +1,123 @@
#include "filetypehelper.h" #include "filetypehelper.h"
#include <QFileInfo> #include <QFileInfo>
#include <QDebug>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include "buffer.h"
using namespace vnotex; using namespace vnotex;
const FileType FileTypeHelper::s_markdownFileType = "markdown"; FileTypeHelper::FileTypeHelper()
{
setupBuiltInTypes();
const FileType FileTypeHelper::s_textFileType = "text"; // TODO: read configuration file.
const FileType FileTypeHelper::s_unknownFileType = "unknown"; setupSuffixTypeMap();
}
QSharedPointer<QMap<QString, FileType>> FileTypeHelper::s_fileTypeMap; void FileTypeHelper::setupBuiltInTypes()
{
{
FileType type;
type.m_type = Type::Markdown;
type.m_displayName = Buffer::tr("Markdown");
type.m_typeName = QStringLiteral("Markdown");
type.m_suffixes << QStringLiteral("md") << QStringLiteral("mkd") << QStringLiteral("markdown");
m_fileTypes.push_back(type);
}
FileType FileTypeHelper::fileType(const QString &p_filePath) {
FileType type;
type.m_type = Type::Text;
type.m_typeName = QStringLiteral("Text");
type.m_displayName = Buffer::tr("Text");
type.m_suffixes << QStringLiteral("txt") << QStringLiteral("text") << QStringLiteral("log");
m_fileTypes.push_back(type);
}
{
FileType type;
type.m_type = Type::Others;
type.m_typeName = QStringLiteral("Others");
type.m_displayName = Buffer::tr("Others");
m_fileTypes.push_back(type);
}
}
const FileType &FileTypeHelper::getFileType(const QString &p_filePath) const
{ {
Q_ASSERT(!p_filePath.isEmpty()); Q_ASSERT(!p_filePath.isEmpty());
if (!s_fileTypeMap) {
init();
}
QFileInfo fi(p_filePath); QFileInfo fi(p_filePath);
auto suffix = fi.suffix().toLower(); auto suffix = fi.suffix().toLower();
auto it = s_fileTypeMap->find(suffix); auto it = m_suffixTypeMap.find(suffix);
if (it != s_fileTypeMap->end()) { if (it != m_suffixTypeMap.end()) {
return it.value(); return m_fileTypes.at(it.value());
} }
// Treat all unknown text files as plain text files. // Treat all unknown text files as plain text files.
if (FileUtils::isText(p_filePath)) { if (FileUtils::isText(p_filePath)) {
return s_fileTypeMap->value(QStringLiteral("txt")); return m_fileTypes[Type::Text];
} }
return s_unknownFileType; return m_fileTypes[Type::Others];
} }
#define ADD(x, y) s_fileTypeMap->insert((x), (y)) const FileType &FileTypeHelper::getFileTypeBySuffix(const QString &p_suffix) const
void FileTypeHelper::init()
{ {
// TODO: load mapping from configuration file. auto it = m_suffixTypeMap.find(p_suffix.toLower());
s_fileTypeMap.reset(new QMap<QString, FileType>()); if (it != m_suffixTypeMap.end()) {
return m_fileTypes.at(it.value());
ADD(QStringLiteral("md"), s_markdownFileType); } else {
ADD(QStringLiteral("markdown"), s_markdownFileType); return m_fileTypes[Type::Others];
ADD(QStringLiteral("mkd"), s_markdownFileType); }
}
ADD(QStringLiteral("txt"), s_textFileType);
ADD(QStringLiteral("text"), s_textFileType); #define ADD(x, y) m_suffixTypeMap.insert((x), (y))
ADD(QStringLiteral("log"), s_textFileType);
void FileTypeHelper::setupSuffixTypeMap()
{
for (int i = 0; i < m_fileTypes.size(); ++i) {
for (const auto &suffix : m_fileTypes[i].m_suffixes) {
if (m_suffixTypeMap.contains(suffix)) {
qWarning() << "suffix conflicts detected" << suffix << m_fileTypes[i].m_type;
}
m_suffixTypeMap.insert(suffix, i);
}
}
}
const QVector<FileType> &FileTypeHelper::getAllFileTypes() const
{
return m_fileTypes;
}
const FileType &FileTypeHelper::getFileType(Type p_type) const
{
return m_fileTypes[p_type];
}
const FileTypeHelper &FileTypeHelper::getInst()
{
static FileTypeHelper helper;
return helper;
}
bool FileTypeHelper::checkFileType(const QString &p_filePath, Type p_type) const
{
return getFileType(p_filePath).m_type == static_cast<int>(p_type);
}
const FileType &FileTypeHelper::getFileTypeByName(const QString &p_typeName) const
{
for (const auto &ft : m_fileTypes) {
if (ft.m_typeName == p_typeName) {
return ft;
}
}
Q_ASSERT(false);
return m_fileTypes[Type::Others];
} }

View File

@ -3,30 +3,65 @@
#include <QString> #include <QString>
#include <QMap> #include <QMap>
#include <QSharedPointer> #include <QVector>
namespace vnotex namespace vnotex
{ {
typedef QString FileType; class FileType
{
public:
// FileTypeHelper::Type.
int m_type = -1;
QString m_typeName;
QString m_displayName;
QStringList m_suffixes;
QString preferredSuffix() const
{
return m_suffixes.isEmpty() ? QString() : m_suffixes.first();
}
};
// Map file suffix to file type.
class FileTypeHelper class FileTypeHelper
{ {
public: public:
FileTypeHelper() = delete; enum Type
{
Markdown = 0,
Text,
Others
};
static FileType fileType(const QString &p_filePath); const FileType &getFileType(const QString &p_filePath) const;
static const FileType s_markdownFileType; const FileType &getFileType(Type p_type) const;
static const FileType s_textFileType; const FileType &getFileTypeByName(const QString &p_typeName) const;
static const FileType s_unknownFileType; const FileType &getFileTypeBySuffix(const QString &p_suffix) const;
const QVector<FileType> &getAllFileTypes() const;
bool checkFileType(const QString &p_filePath, Type p_type) const;
static const FileTypeHelper &getInst();
private: private:
static void init(); FileTypeHelper();
static QSharedPointer<QMap<QString, FileType>> s_fileTypeMap; void setupBuiltInTypes();
void setupSuffixTypeMap();
// Built-in Type could be accessed via enum Type.
QVector<FileType> m_fileTypes;
// suffix -> index of m_fileTypes.
// TODO: handle suffix conflicts.
QMap<QString, int> m_suffixTypeMap;
}; };
} // ns vnotex } // ns vnotex

View File

@ -37,13 +37,15 @@ void BufferMgr::initBufferServer()
{ {
m_bufferServer.reset(new NameBasedServer<IBufferFactory>); m_bufferServer.reset(new NameBasedServer<IBufferFactory>);
const auto &helper = FileTypeHelper::getInst();
// Markdown. // Markdown.
auto markdownFactory = QSharedPointer<MarkdownBufferFactory>::create(); auto markdownFactory = QSharedPointer<MarkdownBufferFactory>::create();
m_bufferServer->registerItem(FileTypeHelper::s_markdownFileType, markdownFactory); m_bufferServer->registerItem(helper.getFileType(FileTypeHelper::Markdown).m_typeName, markdownFactory);
// Text. // Text.
auto textFactory = QSharedPointer<TextBufferFactory>::create(); auto textFactory = QSharedPointer<TextBufferFactory>::create();
m_bufferServer->registerItem(FileTypeHelper::s_textFileType, textFactory); m_bufferServer->registerItem(helper.getFileType(FileTypeHelper::Text).m_typeName, textFactory);
} }
void BufferMgr::open(Node *p_node, const QSharedPointer<FileOpenParameters> &p_paras) void BufferMgr::open(Node *p_node, const QSharedPointer<FileOpenParameters> &p_paras)
@ -59,11 +61,11 @@ void BufferMgr::open(Node *p_node, const QSharedPointer<FileOpenParameters> &p_p
auto buffer = findBuffer(p_node); auto buffer = findBuffer(p_node);
if (!buffer) { if (!buffer) {
auto nodePath = p_node->fetchAbsolutePath(); auto nodePath = p_node->fetchAbsolutePath();
auto fileType = FileTypeHelper::fileType(nodePath); auto fileType = FileTypeHelper::getInst().getFileType(nodePath).m_typeName;
auto factory = m_bufferServer->getItem(fileType); auto factory = m_bufferServer->getItem(fileType);
if (!factory) { if (!factory) {
// No factory to open this file type. // No factory to open this file type.
qInfo() << "File will be opened by system:" << nodePath; qInfo() << "file will be opened by default program" << nodePath;
WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(nodePath)); WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(nodePath));
return; return;
} }
@ -102,11 +104,11 @@ void BufferMgr::open(const QString &p_filePath, const QSharedPointer<FileOpenPar
auto buffer = findBuffer(p_filePath); auto buffer = findBuffer(p_filePath);
if (!buffer) { if (!buffer) {
// Open it as external file. // Open it as external file.
auto fileType = FileTypeHelper::fileType(p_filePath); auto fileType = FileTypeHelper::getInst().getFileType(p_filePath).m_typeName;
auto factory = m_bufferServer->getItem(fileType); auto factory = m_bufferServer->getItem(fileType);
if (!factory) { if (!factory) {
// No factory to open this file type. // No factory to open this file type.
qInfo() << "File will be opened by system:" << p_filePath; qInfo() << "file will be opened by default program" << p_filePath;
WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(p_filePath)); WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(p_filePath));
return; return;
} }

View File

@ -37,6 +37,7 @@ void MarkdownEditorConfig::init(const QJsonObject &p_app, const QJsonObject &p_u
m_sectionNumberMode = stringToSectionNumberMode(READSTR(QStringLiteral("section_number"))); m_sectionNumberMode = stringToSectionNumberMode(READSTR(QStringLiteral("section_number")));
m_sectionNumberBaseLevel = READINT(QStringLiteral("section_number_base_level")); m_sectionNumberBaseLevel = READINT(QStringLiteral("section_number_base_level"));
m_sectionNumberStyle = stringToSectionNumberStyle(READSTR(QStringLiteral("section_number_style")));
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"));
@ -61,6 +62,7 @@ QJsonObject MarkdownEditorConfig::toJson() const
obj[QStringLiteral("section_number")] = sectionNumberModeToString(m_sectionNumberMode); obj[QStringLiteral("section_number")] = sectionNumberModeToString(m_sectionNumberMode);
obj[QStringLiteral("section_number_base_level")] = m_sectionNumberBaseLevel; obj[QStringLiteral("section_number_base_level")] = m_sectionNumberBaseLevel;
obj[QStringLiteral("section_number_style")] = sectionNumberStyleToString(m_sectionNumberStyle);
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;
@ -267,6 +269,27 @@ MarkdownEditorConfig::SectionNumberMode MarkdownEditorConfig::stringToSectionNum
} }
} }
QString MarkdownEditorConfig::sectionNumberStyleToString(SectionNumberStyle p_style) const
{
switch (p_style) {
case SectionNumberStyle::DigDotDig:
return QStringLiteral("digdotdig");
default:
return QStringLiteral("digdotdigdot");
}
}
MarkdownEditorConfig::SectionNumberStyle MarkdownEditorConfig::stringToSectionNumberStyle(const QString &p_str) const
{
auto style = p_str.toLower();
if (style == QStringLiteral("digdotdig")) {
return SectionNumberStyle::DigDotDig;
} else {
return SectionNumberStyle::DigDotDigDot;
}
}
MarkdownEditorConfig::SectionNumberMode MarkdownEditorConfig::getSectionNumberMode() const MarkdownEditorConfig::SectionNumberMode MarkdownEditorConfig::getSectionNumberMode() const
{ {
return m_sectionNumberMode; return m_sectionNumberMode;
@ -286,3 +309,13 @@ void MarkdownEditorConfig::setSectionNumberBaseLevel(int p_level)
{ {
updateConfig(m_sectionNumberBaseLevel, p_level, this); updateConfig(m_sectionNumberBaseLevel, p_level, this);
} }
MarkdownEditorConfig::SectionNumberStyle MarkdownEditorConfig::getSectionNumberStyle() const
{
return m_sectionNumberStyle;
}
void MarkdownEditorConfig::setSectionNumberStyle(SectionNumberStyle p_style)
{
updateConfig(m_sectionNumberStyle, p_style, this);
}

View File

@ -22,6 +22,14 @@ namespace vnotex
Edit Edit
}; };
enum SectionNumberStyle
{
// 1.1.
DigDotDigDot,
// 1.1
DigDotDig
};
MarkdownEditorConfig(ConfigMgr *p_mgr, MarkdownEditorConfig(ConfigMgr *p_mgr,
IConfig *p_topConfig, IConfig *p_topConfig,
const QSharedPointer<TextEditorConfig> &p_textEditorConfig); const QSharedPointer<TextEditorConfig> &p_textEditorConfig);
@ -58,6 +66,9 @@ namespace vnotex
int getSectionNumberBaseLevel() const; int getSectionNumberBaseLevel() const;
void setSectionNumberBaseLevel(int p_level); void setSectionNumberBaseLevel(int p_level);
SectionNumberStyle getSectionNumberStyle() const;
void setSectionNumberStyle(SectionNumberStyle p_style);
bool getConstrainImageWidthEnabled() const; bool getConstrainImageWidthEnabled() const;
void setConstrainImageWidthEnabled(bool p_enabled); void setConstrainImageWidthEnabled(bool p_enabled);
@ -88,6 +99,9 @@ namespace vnotex
QString sectionNumberModeToString(SectionNumberMode p_mode) const; QString sectionNumberModeToString(SectionNumberMode p_mode) const;
SectionNumberMode stringToSectionNumberMode(const QString &p_str) const; SectionNumberMode stringToSectionNumberMode(const QString &p_str) const;
QString sectionNumberStyleToString(SectionNumberStyle p_style) const;
SectionNumberStyle stringToSectionNumberStyle(const QString &p_str) const;
QSharedPointer<TextEditorConfig> m_textEditorConfig; QSharedPointer<TextEditorConfig> m_textEditorConfig;
ViewerResource m_viewerResource; ViewerResource m_viewerResource;
@ -112,6 +126,9 @@ namespace vnotex
// 1 based. // 1 based.
int m_sectionNumberBaseLevel = 2; int m_sectionNumberBaseLevel = 2;
// Section number style.
SectionNumberStyle m_sectionNumberStyle = SectionNumberStyle::DigDotDigDot;
// Whether enable image width constraint. // Whether enable image width constraint.
bool m_constrainImageWidthEnabled = true; bool m_constrainImageWidthEnabled = true;

View File

@ -23,8 +23,8 @@ void NodeContentMediaUtils::copyMediaFiles(const Node *p_node,
const QString &p_destFilePath) const QString &p_destFilePath)
{ {
Q_ASSERT(p_node->getType() == Node::Type::File); Q_ASSERT(p_node->getType() == Node::Type::File);
auto fileType = FileTypeHelper::fileType(p_node->fetchAbsolutePath()); const auto &fileType = FileTypeHelper::getInst().getFileType(p_node->fetchAbsolutePath());
if (fileType == QStringLiteral("markdown")) { if (fileType.m_type == FileTypeHelper::Markdown) {
copyMarkdownMediaFiles(p_node->read(), copyMarkdownMediaFiles(p_node->read(),
PathUtils::parentDirPath(p_node->fetchContentPath()), PathUtils::parentDirPath(p_node->fetchContentPath()),
p_backend, p_backend,
@ -36,8 +36,8 @@ void NodeContentMediaUtils::copyMediaFiles(const QString &p_filePath,
INotebookBackend *p_backend, INotebookBackend *p_backend,
const QString &p_destFilePath) const QString &p_destFilePath)
{ {
auto fileType = FileTypeHelper::fileType(p_filePath); const auto &fileType = FileTypeHelper::getInst().getFileType(p_filePath);
if (fileType == QStringLiteral("markdown")) { if (fileType.m_type == FileTypeHelper::Markdown) {
copyMarkdownMediaFiles(FileUtils::readTextFile(p_filePath), copyMarkdownMediaFiles(FileUtils::readTextFile(p_filePath),
PathUtils::parentDirPath(p_filePath), PathUtils::parentDirPath(p_filePath),
p_backend, p_backend,
@ -112,8 +112,8 @@ void NodeContentMediaUtils::copyMarkdownMediaFiles(const QString &p_content,
void NodeContentMediaUtils::removeMediaFiles(const Node *p_node) void NodeContentMediaUtils::removeMediaFiles(const Node *p_node)
{ {
Q_ASSERT(p_node->getType() == Node::Type::File); Q_ASSERT(p_node->getType() == Node::Type::File);
auto fileType = FileTypeHelper::fileType(p_node->fetchAbsolutePath()); const auto &fileType = FileTypeHelper::getInst().getFileType(p_node->fetchAbsolutePath());
if (fileType == QStringLiteral("markdown")) { if (fileType.m_type == FileTypeHelper::Markdown) {
removeMarkdownMediaFiles(p_node); removeMarkdownMediaFiles(p_node);
} }
} }
@ -162,8 +162,8 @@ void NodeContentMediaUtils::copyAttachment(Node *p_node,
return; return;
} }
auto fileType = FileTypeHelper::fileType(p_node->fetchAbsolutePath()); const auto &fileType = FileTypeHelper::getInst().getFileType(p_node->fetchAbsolutePath());
if (fileType == QStringLiteral("markdown")) { if (fileType.m_type == FileTypeHelper::Markdown) {
fixMarkdownLinks(srcAttachmentFolderPath, p_backend, p_destFilePath, p_destAttachmentFolderPath); fixMarkdownLinks(srcAttachmentFolderPath, p_backend, p_destFilePath, p_destAttachmentFolderPath);
} }
} }

View File

@ -1 +1 @@
<svg t="1600000206395" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9662" width="512" height="512"><path d="M0 616.192l321.344 206.624 0-149.152L130.016 555.52l191.328-118.144L321.344 287.2 0 494.88 0 616.192zM389.312 896l110.592 0 162.048-768-111.328 0L389.312 896zM702.688 287.2l0 150.176 191.264 118.144-191.264 118.112 0 149.152L1024 616.192l0-121.312L702.688 287.2z" p-id="9663" fill="#000000"></path></svg> <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1609914714422" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7578" width="512" height="512" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M516.551 695.182c0 5.006 3.869 9.102 8.533 9.102h210.49c4.664 0 8.533-4.096 8.533-9.102V640.57c0-5.006-3.869-9.102-8.534-9.102H525.084c-4.664 0-8.533 4.096-8.533 9.102v54.613z m-221.753 6.94L513.252 518.94c4.323-3.64 4.323-10.353 0-13.994L294.798 321.877c-5.916-5.006-14.905-0.796-14.905 6.94v71.34c0 2.73 1.138 5.233 3.3 6.94L408.12 512 283.193 616.903c-2.048 1.707-3.3 4.324-3.3 6.94v71.34c0 7.736 8.989 11.946 14.905 6.94z" p-id="7579" fill="#000000"></path><path d="M930.702 56.889H93.298c-20.139 0-36.41 16.27-36.41 36.409v837.404c0 20.139 16.271 36.41 36.41 36.41h837.404c20.139 0 36.41-16.271 36.41-36.41V93.298c0-20.139-16.271-36.41-36.41-36.41z m-45.51 828.302H138.808V138.81H885.19V885.19z" p-id="7580" fill="#000000"></path></svg>

Before

Width:  |  Height:  |  Size: 460 B

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -228,8 +228,11 @@
"insert_file_name_as_title" : true, "insert_file_name_as_title" : true,
"//comment" : "none/read/edit", "//comment" : "none/read/edit",
"section_number" : "read", "section_number" : "read",
"//comment" : "base level to start section numbering, valid only in edit mode", "//comment" : "Base level to start section numbering, valid only in edit mode",
"section_number_base_level" : 2, "section_number_base_level" : 2,
"//comment" : "Style of the section number in edit mode",
"//comment" : "digdotdigdot/digdotdig",
"section_number_style" : "digdotdigdot",
"//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",

View File

@ -1079,3 +1079,18 @@ QSizeGrip {
width: 16px; width: 16px;
height: 16px; height: 16px;
} }
/* ViewWindow */
vnotex--ViewWindow QToolBar[ViewWindowToolBar="true"] {
background-color: @widgets#viewwindow#toolbar#bg;
}
/* ViewSplit */
vnotex--ViewSplit QTabBar::tab:selected {
color: @widgets#viewsplit#tabbar#tab#selected#fg;
background-color: @widgets#viewsplit#tabbar#tab#selected#bg;
}
vte--VTextEdit {
border: none;
}

View File

@ -233,6 +233,14 @@
"active" : { "active" : {
"fg" : "@base#icon#fg" "fg" : "@base#icon#fg"
} }
},
"tabbar" : {
"tab" : {
"selected" : {
"fg" : "@base#content#fg",
"bg" : "@base#content#bg"
}
}
} }
}, },
"qmainwindow" : { "qmainwindow" : {
@ -403,8 +411,8 @@
"bg" : "@base#hover#bg" "bg" : "@base#hover#bg"
}, },
"selected" : { "selected" : {
"fg" : "@base#selected#fg", "fg" : "@base#content#fg",
"bg" : "@base#selected#bg", "bg" : "@base#content#bg",
"border" : "@base#master#bg" "border" : "@base#master#bg"
} }
} }
@ -584,6 +592,11 @@
"border" : "@widgets#qslider#handle#border", "border" : "@widgets#qslider#handle#border",
"bg" : "@base#master#alt" "bg" : "@base#master#alt"
} }
},
"viewwindow" : {
"toolbar" : {
"bg" : "@base#content#bg"
}
} }
} }
} }

View File

@ -108,7 +108,7 @@
}, },
"HRULE" : { "HRULE" : {
"text-color" : "#abb2bf", "text-color" : "#abb2bf",
"background-color" : "#493134" "background-color" : "#864046"
}, },
"LIST_BULLET" : { "LIST_BULLET" : {
"text-color" : "#e06c75", "text-color" : "#e06c75",

View File

@ -22,27 +22,27 @@
#vx-content.vx-section-number h2::before { #vx-content.vx-section-number h2::before {
counter-increment: section1; counter-increment: section1;
content: counter(section1) " "; content: counter(section1) ". ";
} }
#vx-content.vx-section-number h3::before { #vx-content.vx-section-number h3::before {
counter-increment: section2; counter-increment: section2;
content: counter(section1) "." counter(section2) " "; content: counter(section1) "." counter(section2) ". ";
} }
#vx-content.vx-section-number h4::before { #vx-content.vx-section-number h4::before {
counter-increment: section3; counter-increment: section3;
content: counter(section1) "." counter(section2) "." counter(section3) " "; content: counter(section1) "." counter(section2) "." counter(section3) ". ";
} }
#vx-content.vx-section-number h5::before { #vx-content.vx-section-number h5::before {
counter-increment: section4; counter-increment: section4;
content: counter(section1) "." counter(section2) "." counter(section3) "." counter(section4) " "; content: counter(section1) "." counter(section2) "." counter(section3) "." counter(section4) ". ";
} }
#vx-content.vx-section-number h6::before { #vx-content.vx-section-number h6::before {
counter-increment: section5; counter-increment: section5;
content: counter(section1) "." counter(section2) "." counter(section3) "." counter(section4) "." counter(section5) " "; content: counter(section1) "." counter(section2) "." counter(section3) "." counter(section4) "." counter(section5) ". ";
} }
#vx-content.vx-constrain-image-width img { #vx-content.vx-constrain-image-width img {

View File

@ -61,7 +61,9 @@ class MarkJs {
'className': this.className, 'className': this.className,
'caseSensitive': p_options.caseSensitive, 'caseSensitive': p_options.caseSensitive,
'accuracy': p_options.wholeWordOnly ? 'exactly' : 'partially', 'accuracy': p_options.wholeWordOnly ? 'exactly' : 'partially',
'done': callbackFunc(this, p_text, p_options) 'done': callbackFunc(this, p_text, p_options),
// Ignore SVG, or SVG will be corrupted.
'exclude': ['svg *']
} }
if (p_options.regularExpression) { if (p_options.regularExpression) {

View File

@ -111,6 +111,6 @@ class Utils {
} }
static headingSequenceRegExp() { static headingSequenceRegExp() {
return /^\d{1,3}(?:\.\d+)*\.? /; return /^\d{1,3}(?:\.\d+)*\. /;
} }
} }

View File

@ -22,6 +22,7 @@
#include <QMenu> #include <QMenu>
#include <QDebug> #include <QDebug>
#include <QFormLayout> #include <QFormLayout>
#include <QLineEdit>
using namespace vnotex; using namespace vnotex;
@ -366,3 +367,10 @@ QFormLayout *WidgetUtils::createFormLayout(QWidget *p_parent)
return layout; return layout;
} }
void WidgetUtils::selectBaseName(QLineEdit *p_lineEdit)
{
auto text = p_lineEdit->text();
int dotIndex = text.lastIndexOf(QLatin1Char('.'));
p_lineEdit->setSelection(0, (dotIndex == -1) ? text.size() : dotIndex);
}

View File

@ -18,6 +18,7 @@ class QListView;
class QMenu; class QMenu;
class QShortcut; class QShortcut;
class QFormLayout; class QFormLayout;
class QLineEdit;
namespace vnotex namespace vnotex
{ {
@ -80,6 +81,9 @@ namespace vnotex
static QFormLayout *createFormLayout(QWidget *p_parent = nullptr); static QFormLayout *createFormLayout(QWidget *p_parent = nullptr);
// Select the base name part of the line edit content.
static void selectBaseName(QLineEdit *p_lineEdit);
private: private:
static void resizeToHideScrollBar(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal); static void resizeToHideScrollBar(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal);
}; };

View File

@ -8,6 +8,7 @@
#include <utils/pathutils.h> #include <utils/pathutils.h>
#include "exception.h" #include "exception.h"
#include "nodeinfowidget.h" #include "nodeinfowidget.h"
#include <utils/widgetutils.h>
using namespace vnotex; using namespace vnotex;
@ -110,8 +111,7 @@ void NewNoteDialog::initDefaultValues()
{ {
auto lineEdit = m_infoWidget->getNameLineEdit(); auto lineEdit = m_infoWidget->getNameLineEdit();
lineEdit->setText(c_defaultNoteName); lineEdit->setText(c_defaultNoteName);
int dotIndex = c_defaultNoteName.lastIndexOf('.'); WidgetUtils::selectBaseName(lineEdit);
lineEdit->setSelection(0, (dotIndex == -1) ? c_defaultNoteName.size() : dotIndex);
validateInputs(); validateInputs();
} }

View File

@ -9,6 +9,7 @@
#include "exception.h" #include "exception.h"
#include "nodelabelwithupbutton.h" #include "nodelabelwithupbutton.h"
#include <utils/widgetutils.h> #include <utils/widgetutils.h>
#include <buffer/filetypehelper.h>
using namespace vnotex; using namespace vnotex;
@ -16,11 +17,9 @@ NodeInfoWidget::NodeInfoWidget(const Node *p_node, QWidget *p_parent)
: QWidget(p_parent), : QWidget(p_parent),
m_mode(Mode::Edit) m_mode(Mode::Edit)
{ {
setupUI(p_node->getParent()); setupUI(p_node->getParent(), p_node->getType());
setNode(p_node); setNode(p_node);
setStateAccordingToModeAndNodeType(p_node->getType());
} }
NodeInfoWidget::NodeInfoWidget(const Node *p_parentNode, NodeInfoWidget::NodeInfoWidget(const Node *p_parentNode,
@ -29,32 +28,43 @@ NodeInfoWidget::NodeInfoWidget(const Node *p_parentNode,
: QWidget(p_parent), : QWidget(p_parent),
m_mode(Mode::Create) m_mode(Mode::Create)
{ {
setupUI(p_parentNode); setupUI(p_parentNode, p_typeToCreate);
setStateAccordingToModeAndNodeType(p_typeToCreate);
} }
void NodeInfoWidget::setupUI(const Node *p_parentNode) void NodeInfoWidget::setupUI(const Node *p_parentNode, Node::Type p_newNodeType)
{ {
const bool createMode = m_mode == Mode::Create;
const bool isNote = p_newNodeType == Node::Type::File;
m_mainLayout = WidgetUtils::createFormLayout(this); m_mainLayout = WidgetUtils::createFormLayout(this);
m_mainLayout->addRow(tr("Notebook:"), m_mainLayout->addRow(tr("Notebook:"),
new QLabel(p_parentNode->getNotebook()->getName(), this)); new QLabel(p_parentNode->getNotebook()->getName(), this));
m_parentNodeLabel = new NodeLabelWithUpButton(p_parentNode, this); m_parentNodeLabel = new NodeLabelWithUpButton(p_parentNode, this);
m_parentNodeLabel->setReadOnly(!createMode);
connect(m_parentNodeLabel, &NodeLabelWithUpButton::nodeChanged, connect(m_parentNodeLabel, &NodeLabelWithUpButton::nodeChanged,
this, &NodeInfoWidget::inputEdited); this, &NodeInfoWidget::inputEdited);
m_mainLayout->addRow(tr("Location:"), m_parentNodeLabel); m_mainLayout->addRow(tr("Location:"), m_parentNodeLabel);
if (createMode && isNote) {
setupFileTypeComboBox(this);
m_mainLayout->addRow(tr("File type:"), m_fileTypeComboBox);
}
setupNameLineEdit(this); setupNameLineEdit(this);
m_mainLayout->addRow(tr("Name:"), m_nameLineEdit); m_mainLayout->addRow(tr("Name:"), m_nameLineEdit);
if (!createMode) {
m_createdDateTimeLabel = new QLabel(this); m_createdDateTimeLabel = new QLabel(this);
m_mainLayout->addRow(tr("Created time:"), m_createdDateTimeLabel); m_mainLayout->addRow(tr("Created time:"), m_createdDateTimeLabel);
}
if (!createMode && isNote) {
m_modifiedDateTimeLabel = new QLabel(this); m_modifiedDateTimeLabel = new QLabel(this);
m_mainLayout->addRow(tr("Modified time:"), m_modifiedDateTimeLabel); m_mainLayout->addRow(tr("Modified time:"), m_modifiedDateTimeLabel);
} }
}
void NodeInfoWidget::setupNameLineEdit(QWidget *p_parent) void NodeInfoWidget::setupNameLineEdit(QWidget *p_parent)
{ {
@ -63,23 +73,30 @@ void NodeInfoWidget::setupNameLineEdit(QWidget *p_parent)
m_nameLineEdit); m_nameLineEdit);
m_nameLineEdit->setValidator(validator); m_nameLineEdit->setValidator(validator);
connect(m_nameLineEdit, &QLineEdit::textEdited, connect(m_nameLineEdit, &QLineEdit::textEdited,
this, &NodeInfoWidget::inputEdited); this, [this]() {
// Choose the correct file type.
if (m_fileTypeComboBox) {
auto inputName = m_nameLineEdit->text();
QString typeName;
int dotIdx = inputName.lastIndexOf(QLatin1Char('.'));
if (dotIdx != -1) {
auto suffix = inputName.mid(dotIdx + 1);
const auto &fileType = FileTypeHelper::getInst().getFileTypeBySuffix(suffix);
typeName = fileType.m_typeName;
} else {
typeName = FileTypeHelper::getInst().getFileType(FileTypeHelper::Others).m_typeName;
} }
void NodeInfoWidget::setStateAccordingToModeAndNodeType(Node::Type p_type) int idx = m_fileTypeComboBox->findData(typeName);
{ if (idx != -1) {
bool createMode = m_mode == Mode::Create; m_fileTypeComboBoxMuted = true;
bool isNote = p_type == Node::Type::File; m_fileTypeComboBox->setCurrentIndex(idx);
m_fileTypeComboBoxMuted = false;
}
}
m_parentNodeLabel->setReadOnly(!createMode); emit inputEdited();
});
bool visible = !createMode;
m_createdDateTimeLabel->setVisible(visible);
m_mainLayout->labelForField(m_createdDateTimeLabel)->setVisible(visible);
visible = !createMode && isNote;
m_modifiedDateTimeLabel->setVisible(visible);
m_mainLayout->labelForField(m_modifiedDateTimeLabel)->setVisible(visible);
} }
QLineEdit *NodeInfoWidget::getNameLineEdit() const QLineEdit *NodeInfoWidget::getNameLineEdit() const
@ -108,6 +125,7 @@ void NodeInfoWidget::setNode(const Node *p_node)
return; return;
} }
Q_ASSERT(m_mode != Mode::Create);
m_node = p_node; m_node = p_node;
if (m_node) { if (m_node) {
Q_ASSERT(getNotebook() == m_node->getNotebook()); Q_ASSERT(getNotebook() == m_node->getNotebook());
@ -120,3 +138,39 @@ void NodeInfoWidget::setNode(const Node *p_node)
m_modifiedDateTimeLabel->setText(modifiedTime); m_modifiedDateTimeLabel->setText(modifiedTime);
} }
} }
void NodeInfoWidget::setupFileTypeComboBox(QWidget *p_parent)
{
m_fileTypeComboBox = WidgetsFactory::createComboBox(p_parent);
const auto &fileTypes = FileTypeHelper::getInst().getAllFileTypes();
for (const auto &ft : fileTypes) {
m_fileTypeComboBox->addItem(ft.m_displayName, ft.m_typeName);
}
connect(m_fileTypeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [this]() {
if (m_fileTypeComboBoxMuted) {
return;
}
auto name = m_fileTypeComboBox->currentData().toString();
const auto &fileType = FileTypeHelper::getInst().getFileTypeByName(name);
const auto suffix = fileType.preferredSuffix();
if (!suffix.isEmpty()) {
// Change the suffix.
auto inputName = m_nameLineEdit->text();
QString newName;
int dotIdx = inputName.lastIndexOf(QLatin1Char('.'));
if (dotIdx == -1) {
newName = inputName + QLatin1Char('.') + suffix;
} else if (inputName.mid(dotIdx + 1) != suffix) {
newName = inputName.left(dotIdx + 1) + suffix;
}
if (!newName.isEmpty()) {
m_nameLineEdit->setText(newName);
}
}
WidgetUtils::selectBaseName(m_nameLineEdit);
m_nameLineEdit->setFocus();
});
}

View File

@ -8,6 +8,7 @@
class QLineEdit; class QLineEdit;
class QLabel; class QLabel;
class QFormLayout; class QFormLayout;
class QComboBox;
namespace vnotex namespace vnotex
{ {
@ -38,18 +39,20 @@ namespace vnotex
void inputEdited(); void inputEdited();
private: private:
void setupUI(const Node *p_parentNode); void setupUI(const Node *p_parentNode, Node::Type p_newNodeType);
void setupFileTypeComboBox(QWidget *p_parent);
void setupNameLineEdit(QWidget *p_parent); void setupNameLineEdit(QWidget *p_parent);
void setStateAccordingToModeAndNodeType(Node::Type p_type);
void setNode(const Node *p_node); void setNode(const Node *p_node);
Mode m_mode; Mode m_mode;
QFormLayout *m_mainLayout = nullptr; QFormLayout *m_mainLayout = nullptr;
QComboBox *m_fileTypeComboBox = nullptr;
QLineEdit *m_nameLineEdit = nullptr; QLineEdit *m_nameLineEdit = nullptr;
NodeLabelWithUpButton *m_parentNodeLabel = nullptr; NodeLabelWithUpButton *m_parentNodeLabel = nullptr;
@ -59,6 +62,8 @@ namespace vnotex
QLabel *m_modifiedDateTimeLabel = nullptr; QLabel *m_modifiedDateTimeLabel = nullptr;
const Node *m_node = nullptr; const Node *m_node = nullptr;
bool m_fileTypeComboBoxMuted = false;
}; };
} // ns vnotex } // ns vnotex

View File

@ -27,9 +27,9 @@ void NodeLabelWithUpButton::setupUI()
auto iconFile = VNoteX::getInst().getThemeMgr().getIconFile("up_parent_node.svg"); auto iconFile = VNoteX::getInst().getThemeMgr().getIconFile("up_parent_node.svg");
m_upButton = new QPushButton(IconUtils::fetchIconWithDisabledState(iconFile), m_upButton = new QPushButton(IconUtils::fetchIconWithDisabledState(iconFile),
"", tr("Up"),
this); this);
m_upButton->setToolTip(tr("Up")); m_upButton->setToolTip(tr("Create note under an upper level node"));
connect(m_upButton, &QPushButton::clicked, connect(m_upButton, &QPushButton::clicked,
this, [this]() { this, [this]() {
if (!m_node->isRoot()) { if (!m_node->isRoot()) {

View File

@ -51,6 +51,10 @@ void MarkdownEditorPage::loadInternal()
m_sectionNumberComboBox->setCurrentIndex(idx); m_sectionNumberComboBox->setCurrentIndex(idx);
m_sectionNumberBaseLevelSpinBox->setValue(markdownConfig.getSectionNumberBaseLevel()); m_sectionNumberBaseLevelSpinBox->setValue(markdownConfig.getSectionNumberBaseLevel());
idx = m_sectionNumberStyleComboBox->findData(static_cast<int>(markdownConfig.getSectionNumberStyle()));
Q_ASSERT(idx != -1);
m_sectionNumberStyleComboBox->setCurrentIndex(idx);
} }
m_constrainImageWidthCheckBox->setChecked(markdownConfig.getConstrainImageWidthEnabled()); m_constrainImageWidthCheckBox->setChecked(markdownConfig.getConstrainImageWidthEnabled());
@ -83,6 +87,11 @@ void MarkdownEditorPage::saveInternal()
if (m_sectionNumberBaseLevelSpinBox->isEnabled()) { if (m_sectionNumberBaseLevelSpinBox->isEnabled()) {
markdownConfig.setSectionNumberBaseLevel(m_sectionNumberBaseLevelSpinBox->value()); markdownConfig.setSectionNumberBaseLevel(m_sectionNumberBaseLevelSpinBox->value());
} }
if (m_sectionNumberStyleComboBox->isEnabled()) {
auto style = m_sectionNumberStyleComboBox->currentData().toInt();
markdownConfig.setSectionNumberStyle(static_cast<MarkdownEditorConfig::SectionNumberStyle>(style));
}
} }
markdownConfig.setConstrainImageWidthEnabled(m_constrainImageWidthCheckBox->isChecked()); markdownConfig.setConstrainImageWidthEnabled(m_constrainImageWidthCheckBox->isChecked());
@ -229,11 +238,9 @@ QGroupBox *MarkdownEditorPage::setupGeneralGroup()
m_sectionNumberComboBox = WidgetsFactory::createComboBox(this); m_sectionNumberComboBox = WidgetsFactory::createComboBox(this);
m_sectionNumberComboBox->setToolTip(tr("Section number mode")); m_sectionNumberComboBox->setToolTip(tr("Section number mode"));
m_sectionNumberComboBox->addItem(tr("None"), (int)MarkdownEditorConfig::SectionNumberMode::None); m_sectionNumberComboBox->addItem(tr("None"), (int)MarkdownEditorConfig::SectionNumberMode::None);
m_sectionNumberComboBox->addItem(tr("Read"), (int)MarkdownEditorConfig::SectionNumberMode::Read); m_sectionNumberComboBox->addItem(tr("Read"), (int)MarkdownEditorConfig::SectionNumberMode::Read);
m_sectionNumberComboBox->addItem(tr("Edit"), (int)MarkdownEditorConfig::SectionNumberMode::Edit); m_sectionNumberComboBox->addItem(tr("Edit"), (int)MarkdownEditorConfig::SectionNumberMode::Edit);
sectionLayout->addWidget(m_sectionNumberComboBox); sectionLayout->addWidget(m_sectionNumberComboBox);
connect(m_sectionNumberComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), connect(m_sectionNumberComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &MarkdownEditorPage::pageIsChanged); this, &MarkdownEditorPage::pageIsChanged);
@ -242,13 +249,22 @@ QGroupBox *MarkdownEditorPage::setupGeneralGroup()
m_sectionNumberBaseLevelSpinBox->setToolTip(tr("Base level to start section numbering in edit mode")); m_sectionNumberBaseLevelSpinBox->setToolTip(tr("Base level to start section numbering in edit mode"));
m_sectionNumberBaseLevelSpinBox->setRange(1, 6); m_sectionNumberBaseLevelSpinBox->setRange(1, 6);
m_sectionNumberBaseLevelSpinBox->setSingleStep(1); m_sectionNumberBaseLevelSpinBox->setSingleStep(1);
sectionLayout->addWidget(m_sectionNumberBaseLevelSpinBox); sectionLayout->addWidget(m_sectionNumberBaseLevelSpinBox);
connect(m_sectionNumberBaseLevelSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), connect(m_sectionNumberBaseLevelSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
this, &MarkdownEditorPage::pageIsChanged); this, &MarkdownEditorPage::pageIsChanged);
m_sectionNumberStyleComboBox = WidgetsFactory::createComboBox(this);
m_sectionNumberStyleComboBox->setToolTip(tr("Section number style"));
m_sectionNumberStyleComboBox->addItem(tr("1.1."), (int)MarkdownEditorConfig::SectionNumberStyle::DigDotDigDot);
m_sectionNumberStyleComboBox->addItem(tr("1.1"), (int)MarkdownEditorConfig::SectionNumberStyle::DigDotDig);
sectionLayout->addWidget(m_sectionNumberStyleComboBox);
connect(m_sectionNumberStyleComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &MarkdownEditorPage::pageIsChanged);
connect(m_sectionNumberComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), connect(m_sectionNumberComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [this](int p_index) { this, [this](int p_index) {
m_sectionNumberBaseLevelSpinBox->setEnabled(p_index == MarkdownEditorConfig::SectionNumberMode::Edit); m_sectionNumberBaseLevelSpinBox->setEnabled(p_index == MarkdownEditorConfig::SectionNumberMode::Edit);
m_sectionNumberStyleComboBox->setEnabled(p_index == MarkdownEditorConfig::SectionNumberMode::Edit);
}); });
const QString label(tr("Section number:")); const QString label(tr("Section number:"));

View File

@ -54,6 +54,8 @@ namespace vnotex
QComboBox *m_sectionNumberComboBox = nullptr; QComboBox *m_sectionNumberComboBox = nullptr;
QSpinBox *m_sectionNumberBaseLevelSpinBox = nullptr; QSpinBox *m_sectionNumberBaseLevelSpinBox = nullptr;
QComboBox *m_sectionNumberStyleComboBox = nullptr;
}; };
} }

View File

@ -755,7 +755,6 @@ void MarkdownEditor::updateHeadings(const QVector<vte::peg::ElementRegion> &p_he
// 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(); auto doc = document();
QRegExp headerReg(vte::MarkdownUtils::c_headerRegExp);
for (auto const &reg : p_headerRegions) { for (auto const &reg : p_headerRegions) {
auto block = doc->findBlock(reg.m_startPos); auto block = doc->findBlock(reg.m_startPos);
if (!block.isValid()) { if (!block.isValid()) {
@ -766,11 +765,11 @@ void MarkdownEditor::updateHeadings(const QVector<vte::peg::ElementRegion> &p_he
qWarning() << "header accross multiple blocks, starting from block" << block.blockNumber() << block.text(); qWarning() << "header accross multiple blocks, starting from block" << block.blockNumber() << block.text();
} }
if (headerReg.exactMatch(block.text())) { auto match = vte::MarkdownUtils::matchHeader(block.text());
const int level = headerReg.cap(1).length(); if (match.m_matched) {
Heading heading(headerReg.cap(2).trimmed(), Heading heading(match.m_header,
level, match.m_level,
headerReg.cap(3), match.m_sequence,
block.blockNumber()); block.blockNumber());
headings.append(heading); headings.append(heading);
} }
@ -1097,10 +1096,9 @@ static void increaseSectionNumber(QVector<int> &p_sectionNumber, int p_level, in
} }
} }
static QString joinSectionNumberStr(const QVector<int> &p_sectionNumber) static QString joinSectionNumberStr(const QVector<int> &p_sectionNumber, bool p_endingDot)
{ {
QString res; QString res;
// TODO: make it configurable? 1.1 or 1.1.?
for (auto sec : p_sectionNumber) { for (auto sec : p_sectionNumber) {
if (sec != 0) { if (sec != 0) {
if (res.isEmpty()) { if (res.isEmpty()) {
@ -1115,28 +1113,41 @@ static QString joinSectionNumberStr(const QVector<int> &p_sectionNumber)
} }
} }
if (p_endingDot && !res.isEmpty()) {
return res + '.';
} else {
return res; return res;
} }
}
static bool updateHeadingSectionNumber(QTextCursor &p_cursor, static bool updateHeadingSectionNumber(QTextCursor &p_cursor,
const QTextBlock &p_block, const QTextBlock &p_block,
QRegExp &p_headingReg, const QString &p_sectionNumber,
QRegExp &p_prefixReg, bool p_endingDot)
const QString &p_sectionNumber)
{ {
if (!p_block.isValid()) { if (!p_block.isValid()) {
return false; return false;
} }
QString text = p_block.text(); QString text = p_block.text();
bool matched = p_headingReg.exactMatch(text); auto match = vte::MarkdownUtils::matchHeader(text);
Q_ASSERT(matched); Q_ASSERT(match.m_matched);
matched = p_prefixReg.exactMatch(text); bool isSequence = false;
Q_ASSERT(matched); if (!match.m_sequence.isEmpty()) {
// Check if this sequence is the real sequence matching current style.
if (match.m_sequence.endsWith('.')) {
isSequence = p_endingDot;
} else {
isSequence = !p_endingDot;
}
}
int start = p_headingReg.cap(1).length() + 1; int start = match.m_level + 1;
int end = p_prefixReg.cap(1).length(); int end = match.m_level + match.m_spacesAfterMarker;
if (isSequence) {
end += match.m_sequence.size() + match.m_spacesAfterSequence;
}
Q_ASSERT(start <= end); Q_ASSERT(start <= end);
@ -1162,20 +1173,18 @@ bool MarkdownEditor::updateSectionNumber(const QVector<Heading> &p_headings)
} }
bool changed = false; bool changed = false;
bool endingDot = m_config.getSectionNumberStyle() == MarkdownEditorConfig::SectionNumberStyle::DigDotDigDot;
auto doc = document(); auto doc = document();
QRegExp headerReg(vte::MarkdownUtils::c_headerRegExp);
QRegExp prefixReg(vte::MarkdownUtils::c_headerPrefixRegExp);
QTextCursor cursor(doc); QTextCursor cursor(doc);
cursor.beginEditBlock(); cursor.beginEditBlock();
for (const auto &heading : p_headings) { for (const auto &heading : p_headings) {
increaseSectionNumber(sectionNumber, heading.m_level, baseLevel); increaseSectionNumber(sectionNumber, heading.m_level, baseLevel);
auto sectionStr = m_sectionNumberEnabled ? joinSectionNumberStr(sectionNumber) : QString(); auto sectionStr = m_sectionNumberEnabled ? joinSectionNumberStr(sectionNumber, endingDot) : QString();
if (heading.m_blockNumber > -1 && sectionStr != heading.m_sectionNumber) { if (heading.m_blockNumber > -1 && sectionStr != heading.m_sectionNumber) {
if (updateHeadingSectionNumber(cursor, if (updateHeadingSectionNumber(cursor,
doc->findBlockByNumber(heading.m_blockNumber), doc->findBlockByNumber(heading.m_blockNumber),
headerReg, sectionStr,
prefixReg, endingDot)) {
sectionStr)) {
changed = true; changed = true;
} }
} }

View File

@ -251,7 +251,8 @@ void MarkdownViewWindow::handleBufferChangedInternal()
void MarkdownViewWindow::setupToolBar() void MarkdownViewWindow::setupToolBar()
{ {
auto toolBar = new QToolBar(this); auto toolBar = createToolBar(this);
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
const int iconSize = editorConfig.getToolBarIconSize(); const int iconSize = editorConfig.getToolBarIconSize();
toolBar->setIconSize(QSize(iconSize, iconSize)); toolBar->setIconSize(QSize(iconSize, iconSize));

View File

@ -51,6 +51,7 @@ void OutlineViewer::setupUI(const QString &p_title)
{ {
auto mainLayout = new QVBoxLayout(this); auto mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0);
{ {
auto titleBar = setupTitleBar(p_title, this); auto titleBar = setupTitleBar(p_title, this);

View File

@ -13,3 +13,5 @@ const char *PropertyDefs::s_dialogCentralWidget = "DialogCentralWidget";
const char *PropertyDefs::s_viewSplitCornerWidget = "ViewSplitCornerWidget"; const char *PropertyDefs::s_viewSplitCornerWidget = "ViewSplitCornerWidget";
const char *PropertyDefs::s_state = "State"; const char *PropertyDefs::s_state = "State";
const char *PropertyDefs::s_viewWindowToolBar = "ViewWindowToolBar";

View File

@ -19,6 +19,8 @@ namespace vnotex
static const char *s_viewSplitCornerWidget; static const char *s_viewSplitCornerWidget;
static const char *s_viewWindowToolBar;
// Values: info/warning/error. // Values: info/warning/error.
static const char *s_state; static const char *s_state;
}; };

View File

@ -55,7 +55,7 @@ void TextViewWindow::setupUI()
void TextViewWindow::setupToolBar() void TextViewWindow::setupToolBar()
{ {
auto toolBar = new QToolBar(this); auto toolBar = createToolBar(this);
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig(); const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
const int iconSize = editorConfig.getToolBarIconSize(); const int iconSize = editorConfig.getToolBarIconSize();
toolBar->setIconSize(QSize(iconSize, iconSize)); toolBar->setIconSize(QSize(iconSize, iconSize));

View File

@ -32,6 +32,7 @@
#include "exception.h" #include "exception.h"
#include "findandreplacewidget.h" #include "findandreplacewidget.h"
#include "editors/statuswidget.h" #include "editors/statuswidget.h"
#include "propertydefs.h"
using namespace vnotex; using namespace vnotex;
@ -106,14 +107,17 @@ ViewWindow::~ViewWindow()
void ViewWindow::setupUI() void ViewWindow::setupUI()
{ {
m_mainLayout = new QVBoxLayout(this); m_mainLayout = new QVBoxLayout(this);
m_mainLayout->setSpacing(0);
m_mainLayout->setContentsMargins(0, 0, 0, 0); m_mainLayout->setContentsMargins(0, 0, 0, 0);
m_topLayout = new QVBoxLayout(); m_topLayout = new QVBoxLayout();
m_topLayout->setContentsMargins(0, 0, 0, 0); m_topLayout->setContentsMargins(0, 0, 0, 0);
m_topLayout->setSpacing(0);
m_mainLayout->addLayout(m_topLayout, 0); m_mainLayout->addLayout(m_topLayout, 0);
m_bottomLayout = new QVBoxLayout(); m_bottomLayout = new QVBoxLayout();
m_bottomLayout->setContentsMargins(0, 0, 0, 0); m_bottomLayout->setContentsMargins(0, 0, 0, 0);
m_bottomLayout->setSpacing(0);
m_mainLayout->addLayout(m_bottomLayout, 0); m_mainLayout->addLayout(m_bottomLayout, 0);
} }
@ -1073,3 +1077,10 @@ void ViewWindow::read(bool p_save)
} }
setFocus(); setFocus();
} }
QToolBar *ViewWindow::createToolBar(QWidget *p_parent)
{
auto toolBar = new QToolBar(p_parent);
toolBar->setProperty(PropertyDefs::s_viewWindowToolBar, true);
return toolBar;
}

View File

@ -11,6 +11,7 @@
class QVBoxLayout; class QVBoxLayout;
class QTimer; class QTimer;
class QToolBar;
namespace vnotex namespace vnotex
{ {
@ -218,6 +219,8 @@ namespace vnotex
static ViewWindow::Mode modeFromOpenParameters(const FileOpenParameters &p_paras); static ViewWindow::Mode modeFromOpenParameters(const FileOpenParameters &p_paras);
static QToolBar *createToolBar(QWidget *p_parent = nullptr);
// The revision of the buffer of the last sync content. // The revision of the buffer of the last sync content.
int m_bufferRevision = 0; int m_bufferRevision = 0;