From ff29dfae051e370fa8f5fc8667cc01bfaf764963 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Thu, 10 Feb 2022 23:03:33 +0100 Subject: [PATCH] Add paragraph formatting and update edit controls (#28) * Add block formatting buttons to toolbar * Add block format doc actions * Split up doc actions and add sub/sup script * Connect remaining editor toolbar actions * Optimise and extend SVG icon classes * Add a tab width setting * Add tracking of document changes --- i18n/collett_en_US.ts | 76 +++++-- i18n/collett_nb_NO.ts | 76 +++++-- .../7e5a1a98-d1a3-44a1-ab4e-2b5d21d92201.json | 13 +- .../e709ba3f-3141-4b4b-95df-4a8d3e91a8ba.json | 9 +- sample/project/project.json | 5 +- src/collett.h | 14 -- src/core/icons.cpp | 80 ++++--- src/core/icons.h | 8 +- src/core/svgiconengine.cpp | 4 +- src/core/svgiconengine.h | 2 +- src/editor/doceditor.cpp | 98 ++++++++- src/editor/edittoolbar.cpp | 117 +++++++--- src/editor/edittoolbar.h | 27 ++- src/editor/textedit.cpp | 201 ++++++++++++------ src/editor/textedit.h | 17 +- src/project/document.cpp | 23 +- src/project/document.h | 3 + src/project/project.cpp | 2 + src/settings.cpp | 17 +- src/settings.h | 4 +- 20 files changed, 588 insertions(+), 208 deletions(-) diff --git a/i18n/collett_en_US.ts b/i18n/collett_en_US.ts index 7ed60e4..b19b27d 100644 --- a/i18n/collett_en_US.ts +++ b/i18n/collett_en_US.ts @@ -4,57 +4,107 @@ Collett::GuiEditToolBar - + + Header 1 + + + + + Header 2 + + + + + Header 3 + + + + + Header 4 + + + + + Paragraph + + + + + Block Quote + + + + + Format + + + + Bold - + Italic - + Underline - - Strikethrough + + Strike Out + + + + + Superscript - + + Subscript + + + + Align Left - + Align Right - + Align Centre - + Align Justify - + + Text Segment + + + + First Line Indent - + Indent Paragraph - + Outdent Paragraph @@ -191,7 +241,7 @@ Collett::Project - + Unnamed Project diff --git a/i18n/collett_nb_NO.ts b/i18n/collett_nb_NO.ts index e162ee2..1bbd671 100644 --- a/i18n/collett_nb_NO.ts +++ b/i18n/collett_nb_NO.ts @@ -4,57 +4,107 @@ Collett::GuiEditToolBar - + + Header 1 + + + + + Header 2 + + + + + Header 3 + + + + + Header 4 + + + + + Paragraph + + + + + Block Quote + + + + + Format + + + + Bold - + Italic - + Underline - - Strikethrough + + Strike Out + + + + + Superscript - + + Subscript + + + + Align Left - + Align Right - + Align Centre - + Align Justify - + + Text Segment + + + + First Line Indent - + Indent Paragraph - + Outdent Paragraph @@ -191,7 +241,7 @@ Collett::Project - + Unnamed Project diff --git a/sample/content/7e5a1a98-d1a3-44a1-ab4e-2b5d21d92201.json b/sample/content/7e5a1a98-d1a3-44a1-ab4e-2b5d21d92201.json index 79e8c2e..1270697 100644 --- a/sample/content/7e5a1a98-d1a3-44a1-ab4e-2b5d21d92201.json +++ b/sample/content/7e5a1a98-d1a3-44a1-ab4e-2b5d21d92201.json @@ -1,6 +1,7 @@ { + "c:format": "document", "m:created": "2022-01-29T18:22:54", - "m:updated": "2022-01-29T18:23:42", + "m:updated": "2022-02-10T22:57:01", "x:content": [ { "u:fmt": "h3:al", @@ -23,7 +24,9 @@ { "u:fmt": "p:al:ti", "x:txt": [ - "t|Here is a paragraph with no formatting whatsoever.\nThis is a second line in the same ", + "t|Here is a paragraph", + "t:sup|23", + "t| with no formatting whatsoever.\nThis is a second line in the same ", "t:s|silly", "t| paragraph." ] @@ -45,11 +48,7 @@ "u:txt": "t|This text belongs to a second section of the text document." }, { - "u:fmt": "p:al", - "u:txt": "t|" - }, - { - "u:fmt": "p:al", + "u:fmt": "h4:al", "u:txt": "t:b|Song time!" }, { diff --git a/sample/content/e709ba3f-3141-4b4b-95df-4a8d3e91a8ba.json b/sample/content/e709ba3f-3141-4b4b-95df-4a8d3e91a8ba.json index 7536394..bdca7da 100644 --- a/sample/content/e709ba3f-3141-4b4b-95df-4a8d3e91a8ba.json +++ b/sample/content/e709ba3f-3141-4b4b-95df-4a8d3e91a8ba.json @@ -1,14 +1,15 @@ { + "c:format": "document", "m:created": "2022-01-30T18:54:49", - "m:updated": "2022-01-30T21:17:06", + "m:updated": "2022-02-10T22:39:18", "x:content": [ { - "u:fmt": "p:ac", - "u:txt": "t|My Novel" + "u:fmt": "h1:ac", + "u:txt": "t:b|My Novel" }, { "u:fmt": "p:ac", - "u:txt": "t|" + "u:txt": "t|By Jane Doe" } ] } diff --git a/sample/project/project.json b/sample/project/project.json index 561f649..aeccaf0 100644 --- a/sample/project/project.json +++ b/sample/project/project.json @@ -1,10 +1,11 @@ { + "c:format": "project", "c:meta": { "m:created": "2021-12-14T22:24:25", - "m:updated": "2022-01-30T21:17:06" + "m:updated": "2022-02-10T22:59:27" }, "c:project": { - "s:last-doc-main": "e709ba3f-3141-4b4b-95df-4a8d3e91a8ba", + "s:last-doc-main": "7e5a1a98-d1a3-44a1-ab4e-2b5d21d92201", "u:project-name": "Sample Project" }, "c:settings": { diff --git a/src/collett.h b/src/collett.h index 88afc0d..6a25a6c 100644 --- a/src/collett.h +++ b/src/collett.h @@ -28,20 +28,6 @@ namespace Collett { -enum DocAction { - FormatBold, - FormatItalic, - FormatUnderline, - FormatStrikethrough, - TextAlignLeft, - TextAlignCentre, - TextAlignRight, - TextAlignJustify, - TextIndent, - BlockIndent, - BlockOutdent, -}; - enum Severity { Information, Warning, diff --git a/src/core/icons.cpp b/src/core/icons.cpp index 3410913..8fac5d8 100644 --- a/src/core/icons.cpp +++ b/src/core/icons.cpp @@ -28,7 +28,6 @@ #include #include #include -#include namespace Collett { @@ -56,41 +55,44 @@ void CollettIcons::destroy() { */ CollettIcons::CollettIcons() { + // Default Style + this->setIconStyle(qApp->palette().buttonText().color(), 0.7); + // format_align_center_black_24dp.svg - m_svgPath["alignCentre"] = QLatin1String( + m_svgPath["alignCentre"] = QByteArray( "M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z" ); // format_align_justify_black_24dp.svg - m_svgPath["alignJustify"] = QLatin1String( + m_svgPath["alignJustify"] = QByteArray( "M3 21h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18V7H3v2zm0-6v2h18V3H3z" ); // format_align_left_black_24dp.svg - m_svgPath["alignLeft"] = QLatin1String( + m_svgPath["alignLeft"] = QByteArray( "M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z" ); // format_align_right_black_24dp.svg - m_svgPath["alignRight"] = QLatin1String( + m_svgPath["alignRight"] = QByteArray( "M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z" ); // inventory_2_black_24dp.svg - m_svgPath["archive"] = QLatin1String( + m_svgPath["archive"] = QByteArray( "M20,2H4C3,2,2,2.9,2,4v3.01C2,7.73,2.43,8.35,3,8.7V20c0,1.1,1.1,2,2,2h14c0.9,0,2-0.9,2-2V8" ".7c0.57-0.35,1-0.97,1-1.69V4 C22,2.9,21,2,20,2z M15,14H9v-2h6V14z M20,7H4V4h16V7z" ); // format_bold_black_24dp.svg - m_svgPath["bold"] = QLatin1String( + m_svgPath["bold"] = QByteArray( "M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-" "3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5" " 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z" ); // auto_stories_black_24dp.svg - m_svgPath["book"] = QLatin1String( + m_svgPath["book"] = QByteArray( "M19 1l-5 5v11l5-4.5V1zM1 6v14.65c0 .25.25.5.5.5.1 0 .15-.05.25-.05C3.1 20.45 5.05 20 6.5 " "20c1.95 0 4.05.4 5.5 1.5V6c-1.45-1.1-3.55-1.5-5.5-1.5S2.45 4.9 1 6zm22 13.5V6c-.6-.45-1.2" "5-.75-2-1v13.5c-1.1-.35-2.3-.5-3.5-.5-1.7 0-4.15.65-5.5 1.5v2c1.35-.85 3.8-1.5 5.5-1.5 1." @@ -98,30 +100,40 @@ CollettIcons::CollettIcons() { ); // format_indent_increase_black_24dp.svg - m_svgPath["blockIndent"] = QLatin1String( + m_svgPath["blockIndent"] = QByteArray( "M3 21h18v-2H3v2zM3 8v8l4-4-4-4zm8 9h10v-2H11v2zM3 3v2h18V3H3zm8 6h10V7H11v2zm0 4h10v-2H11" "v2z" ); // format_indent_decrease_black_24dp.svg - m_svgPath["blockOutdent"] = QLatin1String( + m_svgPath["blockOutdent"] = QByteArray( "M11 17h10v-2H11v2zm-8-5l4 4V8l-4 4zm0 9h18v-2H3v2zM3 3v2h18V3H3zm8 6h10V7H11v2zm0 4h10v-2" "H11v2z" ); + // format_size_black_24dp.svg + m_svgPath["formatText"] = QByteArray( + "M9 4v3h5v12h3V7h5V4H9zm-6 8h3v7h3v-7h3V9H3v3z" + ); + // format_italic_black_24dp.svg - m_svgPath["italic"] = QLatin1String( + m_svgPath["italic"] = QByteArray( "M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4z" ); // more_vert_black_24dp.svg - m_svgPath["more"] = QLatin1String( + m_svgPath["more"] = QByteArray( "M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-." "9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" ); + // format_quote_black_24dp.svg + m_svgPath["quote"] = QByteArray( + "M6 17h3l2-4V7H5v6h3zm8 0h3l2-4V7h-6v6h3z" + ); + // settings_black_24dp.svg - m_svgPath["settings"] = QLatin1String( + m_svgPath["settings"] = QByteArray( "M19.5,12c0-0.23-0.01-0.45-0.03-0.68l1.86-1.41c0.4-0.3,0.51-0.86,0.26-1.3l-1.87-3.23c-0.25" "-0.44-0.79-0.62-1.25-0.42 l-2.15,0.91c-0.37-0.26-0.76-0.49-1.17-0.68l-0.29-2.31C14.8,2.38" ",14.37,2,13.87,2h-3.73C9.63,2,9.2,2.38,9.14,2.88L8.85,5.19 c-0.41,0.19-0.8,0.42-1.17,0.68" @@ -135,33 +147,38 @@ CollettIcons::CollettIcons() { ); // format_strikethrough_black_24dp.svg - m_svgPath["strikethrough"] = QLatin1String( + m_svgPath["strikeOut"] = QByteArray( "M10 19h4v-3h-4v3zM5 4v3h5v3h4V7h5V4H5zM3 14h18v-2H3v2z" ); // subscript_black_24dp.svg - m_svgPath["subscript"] = QLatin1String( + m_svgPath["subscript"] = QByteArray( "M22,18h-2v1h3v1h-4v-2c0-0.55,0.45-1,1-1h2v-1h-3v-1h3c0.55,0,1,0.45,1,1v1C23,17.55,22.55,1" "8,22,18z M5.88,18h2.66 l3.4-5.42h0.12l3.4,5.42h2.66l-4.65-7.27L17.81,4h-2.68l-3.07,4.99h-" "0.12L8.85,4H6.19l4.32,6.73L5.88,18z" ); // superscript_black_24dp.svg - m_svgPath["superscript"] = QLatin1String( + m_svgPath["superscript"] = QByteArray( "M22,7h-2v1h3v1h-4V7c0-0.55,0.45-1,1-1h2V5h-3V4h3c0.55,0,1,0.45,1,1v1C23,6.55,22.55,7,22,7" "z M5.88,20h2.66l3.4-5.42h0.12 l3.4,5.42h2.66l-4.65-7.27L17.81,6h-2.68l-3.07,4.99h-0.12L8." "85,6H6.19l4.32,6.73L5.88,20z" ); // subject_black_24dp.svg (rotated 180 degrees) - m_svgPath["textIndent"] = QLatin1String( + m_svgPath["textIndent"] = QByteArray( "m10 7h10v-2h-10zm-6 8h16v-2h-16zm16-6h-16v2h16zm0 10v-2h-16v2z" ); + // subject_black_24dp.svg (rotated 180 degrees, short bar replaces middle bars) + m_svgPath["textSegment"] = QByteArray( + "m20 9h-10v2h10zm0 4h-10v2h10zm0 4h-10v2h10zm-16-12v2h16v-2z" + ); + // format_underlined_black_24dp.svg - m_svgPath["underline"] = QLatin1String( + m_svgPath["underline"] = QByteArray( "M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2" - ".69 6 6 6zm-7 2v2h14" + ".69 6 6 6zm-7 2v2h14v-2H5z" ); } @@ -169,13 +186,26 @@ CollettIcons::~CollettIcons() { qDebug() << "Destructor: CollettIcons"; } +void CollettIcons::setIconStyle(const QColor &foreground, qreal opacity) { + m_svgTemplateA = QByteArray( + "" - ).arg(col.name(QColor::HexRgb)).arg("0.7").arg(m_svgPath[name]); - return QIcon(new SVGIconEngine(svg)); + return QIcon( + new SVGIconEngine( + QByteArray().append(m_svgTemplateA).append(m_svgPath[name]).append(m_svgTemplateB) + ) + ); } } // namespace Collett diff --git a/src/core/icons.h b/src/core/icons.h index f389141..a899824 100644 --- a/src/core/icons.h +++ b/src/core/icons.h @@ -27,7 +27,6 @@ #include #include #include -#include namespace Collett { @@ -42,11 +41,16 @@ class CollettIcons : public QObject explicit CollettIcons(); ~CollettIcons(); + void setIconStyle(const QColor &foreground, qreal opacity); + QIcon icon(const QString &name); private: static CollettIcons *staticInstance; - QHash m_svgPath; + + QByteArray m_svgTemplateA = ""; + QHash m_svgPath; }; } // namespace Collett diff --git a/src/core/svgiconengine.cpp b/src/core/svgiconengine.cpp index 1dd8ff8..4a8fda0 100644 --- a/src/core/svgiconengine.cpp +++ b/src/core/svgiconengine.cpp @@ -38,9 +38,7 @@ namespace Collett { * Based on: https://stackoverflow.com/a/44757951 */ -SVGIconEngine::SVGIconEngine(const QString &iconBuffer) { - m_iconData = iconBuffer.toLatin1(); -} +SVGIconEngine::SVGIconEngine(const QByteArray &iconBuffer) : m_iconData(iconBuffer) {} void SVGIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) { QSvgRenderer renderer(m_iconData); diff --git a/src/core/svgiconengine.h b/src/core/svgiconengine.h index e1ddf82..a61ceef 100644 --- a/src/core/svgiconengine.h +++ b/src/core/svgiconengine.h @@ -36,7 +36,7 @@ class SVGIconEngine : public QIconEngine { public: - explicit SVGIconEngine(const QString &iconBuffer); + explicit SVGIconEngine(const QByteArray &iconBuffer); void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override; QIconEngine *clone() const override; diff --git a/src/editor/doceditor.cpp b/src/editor/doceditor.cpp index 2770ddf..c45251c 100644 --- a/src/editor/doceditor.cpp +++ b/src/editor/doceditor.cpp @@ -65,15 +65,57 @@ GuiDocEditor::GuiDocEditor(QWidget *parent) m_autoSave->setInterval(settings->editorAutoSave() * 1000); // Connections - - connect(m_editToolBar, SIGNAL(documentAction(DocAction)), - m_textArea, SLOT(applyDocAction(DocAction))); connect(m_textArea, SIGNAL(currentCharFormatChanged(const QTextCharFormat&)), this, SLOT(editorCharFormatChanged(const QTextCharFormat&))); connect(m_textArea, SIGNAL(currentBlockChanged(const QTextBlock&)), this, SLOT(editorBlockChanged(const QTextBlock&))); connect(m_autoSave, SIGNAL(timeout()), this, SLOT(flushEditorData())); + + // Editor Tool Bar Signals + connect(m_editToolBar->m_formatBold, SIGNAL(triggered()), + m_textArea, SLOT(toggleBoldFormat())); + connect(m_editToolBar->m_formatItalic, SIGNAL(triggered()), + m_textArea, SLOT(toggleItalicFormat())); + connect(m_editToolBar->m_formatUnderline, SIGNAL(triggered()), + m_textArea, SLOT(toggleUnderlineFormat())); + connect(m_editToolBar->m_formatStrikeOut, SIGNAL(triggered()), + m_textArea, SLOT(toggleStrikeOutFormat())); + connect(m_editToolBar->m_formatSuperScript, SIGNAL(triggered()), + m_textArea, SLOT(toggleSuperScriptFormat())); + connect(m_editToolBar->m_formatSubScript, SIGNAL(triggered()), + m_textArea, SLOT(toggleSubScriptFormat())); + + connect(m_editToolBar->m_textSegment, SIGNAL(triggered()), + m_textArea, SLOT(toggleSegmentFormat())); + connect(m_editToolBar->m_textIndent, SIGNAL(triggered()), + m_textArea, SLOT(toggleFirstLineIndent())); + connect(m_editToolBar->m_blockIndent, SIGNAL(triggered()), + m_textArea, SLOT(increaseBlockIndent())); + connect(m_editToolBar->m_blockOutdent, SIGNAL(triggered()), + m_textArea, SLOT(decreaseBlockIndent())); + + connect(m_editToolBar->m_formatHeader1, &QAction::triggered, + [this]{m_textArea->applyBlockFormat(GuiTextEdit::Header, 1);}); + connect(m_editToolBar->m_formatHeader2, &QAction::triggered, + [this]{m_textArea->applyBlockFormat(GuiTextEdit::Header, 2);}); + connect(m_editToolBar->m_formatHeader3, &QAction::triggered, + [this]{m_textArea->applyBlockFormat(GuiTextEdit::Header, 3);}); + connect(m_editToolBar->m_formatHeader4, &QAction::triggered, + [this]{m_textArea->applyBlockFormat(GuiTextEdit::Header, 4);}); + connect(m_editToolBar->m_formatParagraph, &QAction::triggered, + [this]{m_textArea->applyBlockFormat(GuiTextEdit::Paragraph, 0);}); + connect(m_editToolBar->m_formatBlockQuote, &QAction::triggered, + [this]{m_textArea->applyBlockFormat(GuiTextEdit::BlockQuote, 0);}); + + connect(m_editToolBar->m_alignLeft, &QAction::triggered, + [this]{m_textArea->applyBlockAlignment(Qt::AlignLeft);}); + connect(m_editToolBar->m_alignCentre, &QAction::triggered, + [this]{m_textArea->applyBlockAlignment(Qt::AlignHCenter);}); + connect(m_editToolBar->m_alignRight, &QAction::triggered, + [this]{m_textArea->applyBlockAlignment(Qt::AlignRight);}); + connect(m_editToolBar->m_alignJustify, &QAction::triggered, + [this]{m_textArea->applyBlockAlignment(Qt::AlignJustify);}); } /** @@ -108,6 +150,10 @@ bool GuiDocEditor::saveDocument() { qWarning() << "No document to save"; return false; } + if (!m_textArea->isModified()) { + qDebug() << "Document has not been changed"; + return true; + } m_document->setLocked(true); m_document->setContent(m_textArea->toJsonContent()); @@ -146,22 +192,54 @@ void GuiDocEditor::editorCharFormatChanged(const QTextCharFormat &fmt) { m_editToolBar->m_formatBold->setChecked(fmt.fontWeight() > QFont::Medium); m_editToolBar->m_formatItalic->setChecked(fmt.fontItalic()); m_editToolBar->m_formatUnderline->setChecked(fmt.fontUnderline()); - m_editToolBar->m_formatStrikethrough->setChecked(fmt.fontStrikeOut()); + m_editToolBar->m_formatStrikeOut->setChecked(fmt.fontStrikeOut()); + m_editToolBar->m_formatSuperScript->setChecked(fmt.verticalAlignment() == QTextCharFormat::AlignSuperScript); + m_editToolBar->m_formatSubScript->setChecked(fmt.verticalAlignment() == QTextCharFormat::AlignSubScript); } void GuiDocEditor::editorBlockChanged(const QTextBlock &block) { + QTextBlockFormat blockFormat = block.blockFormat(); - m_editToolBar->m_alignLeft->setChecked(blockFormat.alignment() == Qt::AlignLeft); - m_editToolBar->m_alignCentre->setChecked(blockFormat.alignment() == Qt::AlignHCenter); - m_editToolBar->m_alignRight->setChecked(blockFormat.alignment() == Qt::AlignRight); - m_editToolBar->m_alignJustify->setChecked(blockFormat.alignment() == Qt::AlignJustify); + + switch (blockFormat.headingLevel()) { + case 1: + m_editToolBar->m_formatHeader1->setChecked(true); + break; + case 2: + m_editToolBar->m_formatHeader2->setChecked(true); + break; + case 3: + m_editToolBar->m_formatHeader3->setChecked(true); + break; + case 4: + m_editToolBar->m_formatHeader4->setChecked(true); + break; + default: + m_editToolBar->m_formatParagraph->setChecked(true); + break; + } + + switch (blockFormat.alignment()) { + case Qt::AlignLeft: + m_editToolBar->m_alignLeft->setChecked(true); + break; + case Qt::AlignHCenter: + m_editToolBar->m_alignCentre->setChecked(true); + break; + case Qt::AlignRight: + m_editToolBar->m_alignRight->setChecked(true); + break; + case Qt::AlignJustify: + m_editToolBar->m_alignJustify->setChecked(true); + break; + } + + m_editToolBar->m_textSegment->setChecked(blockFormat.textIndent() < 0.0); m_editToolBar->m_textIndent->setChecked(blockFormat.textIndent() > 0.0); } void GuiDocEditor::flushEditorData() { - qDebug() << "Ding!"; - if (!m_data->hasProject() || !hasDocument()) { return; } diff --git a/src/editor/edittoolbar.cpp b/src/editor/edittoolbar.cpp index 2127844..b5b3160 100644 --- a/src/editor/edittoolbar.cpp +++ b/src/editor/edittoolbar.cpp @@ -23,11 +23,13 @@ #include "edittoolbar.h" #include "icons.h" +#include #include #include #include #include #include +#include namespace Collett { @@ -38,58 +40,107 @@ GuiEditToolBar::GuiEditToolBar(QWidget *parent) this->setIconSize(QSize(20, 20)); - m_formatBold = this->addAction(icons->icon("bold"), tr("Bold")); - m_formatItalic = this->addAction(icons->icon("italic"), tr("Italic")); - m_formatUnderline = this->addAction(icons->icon("underline"), tr("Underline")); - m_formatStrikethrough = this->addAction(icons->icon("strikethrough"), tr("Strikethrough")); + // Text Block Format Menu + // ====================== + + m_formatTextMenu = new QMenu(); + + m_formatTextGroup = new QActionGroup(this); + m_formatTextGroup->setExclusionPolicy(QActionGroup::ExclusionPolicy::Exclusive); + + m_formatHeader1 = m_formatTextMenu->addAction(tr("Header 1")); + m_formatHeader1->setCheckable(true); + m_formatHeader1->setActionGroup(m_formatTextGroup); + + m_formatHeader2 = m_formatTextMenu->addAction(tr("Header 2")); + m_formatHeader2->setCheckable(true); + m_formatHeader2->setActionGroup(m_formatTextGroup); + + m_formatHeader3 = m_formatTextMenu->addAction(tr("Header 3")); + m_formatHeader3->setCheckable(true); + m_formatHeader3->setActionGroup(m_formatTextGroup); + + m_formatHeader4 = m_formatTextMenu->addAction(tr("Header 4")); + m_formatHeader4->setCheckable(true); + m_formatHeader4->setActionGroup(m_formatTextGroup); + + m_formatParagraph = m_formatTextMenu->addAction(tr("Paragraph")); + m_formatParagraph->setCheckable(true); + m_formatParagraph->setActionGroup(m_formatTextGroup); + + m_formatBlockQuote = m_formatTextMenu->addAction(tr("Block Quote")); + m_formatBlockQuote->setCheckable(true); + m_formatBlockQuote->setActionGroup(m_formatTextGroup); + + m_formatText = new QToolButton(this); + m_formatText->setIcon(icons->icon("formatText")); + m_formatText->setText(tr("Format")); + m_formatText->setMenu(m_formatTextMenu); + m_formatText->setPopupMode(QToolButton::InstantPopup); + this->addWidget(m_formatText); + this->addSeparator(); + + // Character Format Buttons + // ======================== + + m_formatBold = this->addAction(icons->icon("bold"), tr("Bold")); m_formatBold->setCheckable(true); + + m_formatItalic = this->addAction(icons->icon("italic"), tr("Italic")); m_formatItalic->setCheckable(true); + + m_formatUnderline = this->addAction(icons->icon("underline"), tr("Underline")); m_formatUnderline->setCheckable(true); - m_formatStrikethrough->setCheckable(true); - connect(m_formatBold, &QAction::triggered, [this]{emitDocumentAction(DocAction::FormatBold);}); - connect(m_formatItalic, &QAction::triggered, [this]{emitDocumentAction(DocAction::FormatItalic);}); - connect(m_formatUnderline, &QAction::triggered, [this]{emitDocumentAction(DocAction::FormatUnderline);}); - connect(m_formatStrikethrough, &QAction::triggered, [this]{emitDocumentAction(DocAction::FormatStrikethrough);}); + m_formatStrikeOut = this->addAction(icons->icon("strikeOut"), tr("Strike Out")); + m_formatStrikeOut->setCheckable(true); this->addSeparator(); - m_alignLeft = this->addAction(icons->icon("alignLeft"), tr("Align Left")); - m_alignCentre = this->addAction(icons->icon("alignCentre"), tr("Align Right")); - m_alignRight = this->addAction(icons->icon("alignRight"), tr("Align Centre")); - m_alignJustify = this->addAction(icons->icon("alignJustify"), tr("Align Justify")); + m_formatSuperScript = this->addAction(icons->icon("superscript"), tr("Superscript")); + m_formatSuperScript->setCheckable(true); + m_formatSubScript = this->addAction(icons->icon("subscript"), tr("Subscript")); + m_formatSubScript->setCheckable(true); + + this->addSeparator(); + + // Text Block Alignment Options + // ============================ + + m_alignTextGroup = new QActionGroup(this); + m_alignTextGroup->setExclusionPolicy(QActionGroup::ExclusionPolicy::Exclusive); + + m_alignLeft = this->addAction(icons->icon("alignLeft"), tr("Align Left")); m_alignLeft->setCheckable(true); + m_alignLeft->setActionGroup(m_alignTextGroup); + + m_alignCentre = this->addAction(icons->icon("alignCentre"), tr("Align Right")); m_alignCentre->setCheckable(true); + m_alignCentre->setActionGroup(m_alignTextGroup); + + m_alignRight = this->addAction(icons->icon("alignRight"), tr("Align Centre")); m_alignRight->setCheckable(true); - m_alignJustify->setCheckable(true); + m_alignRight->setActionGroup(m_alignTextGroup); - connect(m_alignLeft, &QAction::triggered, [this]{emitDocumentAction(DocAction::TextAlignLeft);}); - connect(m_alignCentre, &QAction::triggered, [this]{emitDocumentAction(DocAction::TextAlignCentre);}); - connect(m_alignRight, &QAction::triggered, [this]{emitDocumentAction(DocAction::TextAlignRight);}); - connect(m_alignJustify, &QAction::triggered, [this]{emitDocumentAction(DocAction::TextAlignJustify);}); + m_alignJustify = this->addAction(icons->icon("alignJustify"), tr("Align Justify")); + m_alignJustify->setCheckable(true); + m_alignJustify->setActionGroup(m_alignTextGroup); this->addSeparator(); - m_textIndent = this->addAction(icons->icon("textIndent"), tr("First Line Indent")); - m_blockIndent = this->addAction(icons->icon("blockIndent"), tr("Indent Paragraph")); - m_blockOutdent = this->addAction(icons->icon("blockOutdent"), tr("Outdent Paragraph")); + // Text Block Indentation and Style + // ================================ - m_textIndent->setCheckable(true); + m_textSegment = this->addAction(icons->icon("textSegment"), tr("Text Segment")); + m_textSegment->setCheckable(true); - connect(m_textIndent, &QAction::triggered, [this]{emitDocumentAction(DocAction::TextIndent);}); - connect(m_blockIndent, &QAction::triggered, [this]{emitDocumentAction(DocAction::BlockIndent);}); - connect(m_blockOutdent, &QAction::triggered, [this]{emitDocumentAction(DocAction::BlockOutdent);}); -} - -/** - * Private Slots - * ============= - */ + m_textIndent = this->addAction(icons->icon("textIndent"), tr("First Line Indent")); + m_textIndent->setCheckable(true); -void GuiEditToolBar::emitDocumentAction(DocAction action) { - emit documentAction(action); + m_blockIndent = this->addAction(icons->icon("blockIndent"), tr("Indent Paragraph")); + m_blockOutdent = this->addAction(icons->icon("blockOutdent"), tr("Outdent Paragraph")); } } // namespace Collett diff --git a/src/editor/edittoolbar.h b/src/editor/edittoolbar.h index 2d2cf2f..e4b3b63 100644 --- a/src/editor/edittoolbar.h +++ b/src/editor/edittoolbar.h @@ -24,9 +24,12 @@ #include "collett.h" +#include #include #include #include +#include +#include namespace Collett { @@ -40,27 +43,37 @@ class GuiEditToolBar : public QToolBar GuiEditToolBar(QWidget *parent=nullptr); ~GuiEditToolBar() {}; -signals: - void documentAction(DocAction action); - private: + QActionGroup *m_formatTextGroup; + QActionGroup *m_alignTextGroup; + + QToolButton *m_formatText; + QMenu *m_formatTextMenu; + QAction *m_formatHeader1; + QAction *m_formatHeader2; + QAction *m_formatHeader3; + QAction *m_formatHeader4; + QAction *m_formatParagraph; + QAction *m_formatBlockQuote; + QAction *m_formatBold; QAction *m_formatItalic; QAction *m_formatUnderline; - QAction *m_formatStrikethrough; + QAction *m_formatStrikeOut; + + QAction *m_formatSuperScript; + QAction *m_formatSubScript; QAction *m_alignLeft; QAction *m_alignCentre; QAction *m_alignRight; QAction *m_alignJustify; + QAction *m_textSegment; QAction *m_textIndent; QAction *m_blockIndent; QAction *m_blockOutdent; -private slots: - void emitDocumentAction(DocAction action); - friend class GuiDocEditor; }; diff --git a/src/editor/textedit.cpp b/src/editor/textedit.cpp index ff3f64f..8ebb94e 100644 --- a/src/editor/textedit.cpp +++ b/src/editor/textedit.cpp @@ -115,6 +115,8 @@ QJsonArray GuiTextEdit::toJsonContent() { // Text Indent if (blockFormat.textIndent() > 0.0) { jsonBlockFmt << "ti"; + } else if (blockFormat.textIndent() < 0.0) { + jsonBlockFmt << "sg"; } // Block Indent @@ -140,6 +142,8 @@ QJsonArray GuiTextEdit::toJsonContent() { if (fragFmt.fontItalic()) jsonFragFmt << "i"; if (fragFmt.fontUnderline()) jsonFragFmt << "u"; if (fragFmt.fontStrikeOut()) jsonFragFmt << "s"; + if (fragFmt.verticalAlignment() == QTextCharFormat::AlignSuperScript) jsonFragFmt << "sup"; + if (fragFmt.verticalAlignment() == QTextCharFormat::AlignSubScript) jsonFragFmt << "sub"; jsonFrags.append(jsonFragFmt.join(":") + "|" + blockFrag.text().replace(QChar::LineSeparator, '\n')); } @@ -226,7 +230,10 @@ void GuiTextEdit::setJsonContent(const QJsonArray &json) { } else if (blockFmtTag == "aj") { blockFormat.setAlignment(Qt::AlignJustify); } else if (blockFmtTag == "ti") { - blockFormat.setTextIndent(m_format.textIndent); + blockFormat.setTextIndent(m_format.tabWidth); + } else if (blockFmtTag == "sg") { + blockFormat.setTextIndent(-m_format.tabWidth); + blockFormat.setLeftMargin(m_format.tabWidth); } else if (blockFmtTag.startsWith("in")) { blockFormat.setIndent(blockFmtTag.last(1).toInt()); } @@ -272,6 +279,10 @@ void GuiTextEdit::setJsonContent(const QJsonArray &json) { fragFormat.setFontUnderline(true); } else if (fragFmtTag == "s") { fragFormat.setFontStrikeOut(true); + } else if (fragFmtTag == "sup") { + fragFormat.setVerticalAlignment(QTextCharFormat::AlignSuperScript); + } else if (fragFmtTag == "sub") { + fragFormat.setVerticalAlignment(QTextCharFormat::AlignSubScript); } } @@ -301,6 +312,8 @@ void GuiTextEdit::initDocument(QTextDocument *doc) { doc->setDefaultTextOption(opts); doc->setDocumentMargin(40); + // Editor Options + this->setTabStopDistance(m_format.tabWidth); } /** @@ -308,82 +321,140 @@ void GuiTextEdit::initDocument(QTextDocument *doc) { * ============ */ -void GuiTextEdit::applyDocAction(DocAction action) { +void GuiTextEdit::toggleBoldFormat() { + if (this->fontWeight() > QFont::Medium) { + this->setFontWeight(QFont::Normal); + } else { + this->setFontWeight(QFont::Bold); + } +} + +void GuiTextEdit::toggleItalicFormat() { + this->setFontItalic(!this->fontItalic()); +} + +void GuiTextEdit::toggleUnderlineFormat() { + this->setFontUnderline(!this->fontUnderline()); +} + +void GuiTextEdit::toggleStrikeOutFormat() { + QFont font = this->currentFont(); + font.setStrikeOut(!font.strikeOut()); + this->setCurrentFont(font); +} - bool blockChanged = false; +void GuiTextEdit::toggleSuperScriptFormat() { + QTextCharFormat fmt = this->currentCharFormat(); + if (fmt.verticalAlignment() == QTextCharFormat::AlignSuperScript) { + fmt.setVerticalAlignment(QTextCharFormat::AlignNormal); + } else { + fmt.setVerticalAlignment(QTextCharFormat::AlignSuperScript); + } + this->setCurrentCharFormat(fmt); +} - if (action == Collett::FormatBold) { - if (fontWeight() > QFont::Medium) { - setFontWeight(QFont::Normal); +void GuiTextEdit::toggleSubScriptFormat() { + QTextCharFormat fmt = this->currentCharFormat(); + if (fmt.verticalAlignment() == QTextCharFormat::AlignSubScript) { + fmt.setVerticalAlignment(QTextCharFormat::AlignNormal); + } else { + fmt.setVerticalAlignment(QTextCharFormat::AlignSubScript); + } + this->setCurrentCharFormat(fmt); +} + +void GuiTextEdit::toggleSegmentFormat() { + QTextCursor cursor = textCursor(); + QTextBlockFormat format = cursor.blockFormat(); + if (format.headingLevel() == 0 && format.alignment() == Qt::AlignLeading) { + if (format.textIndent() < 0.0) { + format.setTextIndent(0.0); + format.setLeftMargin(0.0); } else { - setFontWeight(QFont::Bold); + format.setTextIndent(-m_format.tabWidth); + format.setLeftMargin(m_format.tabWidth); } + cursor.setBlockFormat(format); + emit currentBlockChanged(cursor.block()); + } +} - } else if (action == Collett::FormatItalic) { - setFontItalic(!fontItalic()); - - } else if (action == Collett::FormatUnderline) { - setFontUnderline(!fontUnderline()); - - } else if (action == Collett::FormatStrikethrough) { - QFont font = currentFont(); - font.setStrikeOut(!font.strikeOut()); - setCurrentFont(font); - - } else if (action == Collett::TextAlignLeft) { - setAlignment(Qt::AlignLeft); - blockChanged = true; - - } else if (action == Collett::TextAlignCentre) { - setAlignment(Qt::AlignHCenter); - blockChanged = true; - - } else if (action == Collett::TextAlignRight) { - setAlignment(Qt::AlignRight); - blockChanged = true; - - } else if (action == Collett::TextAlignJustify) { - setAlignment(Qt::AlignJustify); - blockChanged = true; - - } else if (action == Collett::TextIndent) { - QTextCursor cursor = textCursor(); - QTextBlockFormat format = cursor.blockFormat(); - if (format.headingLevel() == 0 && format.alignment() == Qt::AlignLeading) { - if (format.textIndent() > 0.0) { - format.setTextIndent(0.0); - } else { - format.setTextIndent(m_format.textIndent); - } - cursor.setBlockFormat(format); - } - blockChanged = true; - - } else if (action == Collett::BlockIndent) { - QTextCursor cursor = textCursor(); - QTextBlockFormat format = cursor.blockFormat(); - if (format.headingLevel() == 0 && format.alignment() == Qt::AlignLeading) { - format.setIndent(std::min(format.indent() + 1, 9)); - cursor.setBlockFormat(format); - } - blockChanged = true; - - } else if (action == Collett::BlockOutdent) { - QTextCursor cursor = textCursor(); - QTextBlockFormat format = cursor.blockFormat(); - if (format.headingLevel() == 0 && format.alignment() == Qt::AlignLeading) { - format.setIndent(std::max(format.indent() - 1, 0)); - cursor.setBlockFormat(format); +void GuiTextEdit::toggleFirstLineIndent() { + QTextCursor cursor = textCursor(); + QTextBlockFormat format = cursor.blockFormat(); + if (format.headingLevel() == 0 && format.alignment() == Qt::AlignLeading) { + if (format.textIndent() > 0.0) { + format.setTextIndent(0.0); + format.setLeftMargin(0.0); + } else { + format.setTextIndent(m_format.tabWidth); + format.setLeftMargin(0.0); } - blockChanged = true; + cursor.setBlockFormat(format); + emit currentBlockChanged(cursor.block()); } +} - if (blockChanged) { - QTextCursor cursor = textCursor(); +void GuiTextEdit::increaseBlockIndent() { + QTextCursor cursor = textCursor(); + QTextBlockFormat format = cursor.blockFormat(); + if (format.headingLevel() == 0 && format.alignment() == Qt::AlignLeading) { + format.setIndent(std::min(format.indent() + 1, 9)); + cursor.setBlockFormat(format); emit currentBlockChanged(cursor.block()); } } +void GuiTextEdit::decreaseBlockIndent() { + QTextCursor cursor = textCursor(); + QTextBlockFormat format = cursor.blockFormat(); + if (format.headingLevel() == 0 && format.alignment() == Qt::AlignLeading) { + format.setIndent(std::max(format.indent() - 1, 0)); + cursor.setBlockFormat(format); + emit currentBlockChanged(cursor.block()); + } +} + +void GuiTextEdit::applyBlockAlignment(const Qt::Alignment align) { + this->setAlignment(align); + QTextCursor cursor = this->textCursor(); + emit currentBlockChanged(cursor.block()); +} + +void GuiTextEdit::applyBlockFormat(BlockFormat format, int hLevel) { + + QTextCursor cursor = textCursor(); + int bPos = cursor.block().position(); + int bLen = cursor.block().length(); + int hLevelNow = cursor.blockFormat().headingLevel(); + + if (bLen < 2) return; + if (hLevel > 0 && hLevelNow == hLevel) return; + + cursor.beginEditBlock(); + cursor.setPosition(bPos, QTextCursor::MoveAnchor); + cursor.setPosition(bPos + bLen - 1, QTextCursor::KeepAnchor); + if (format == BlockFormat::Paragraph && hLevelNow != 0) { + cursor.setBlockFormat(m_format.blockParagraph); + cursor.setCharFormat(m_format.charParagraph); + } else if (format == BlockFormat::Header && hLevel == 1) { + cursor.setBlockFormat(m_format.blockHeader1); + cursor.setCharFormat(m_format.charHeader1); + } else if (format == BlockFormat::Header && hLevel == 2) { + cursor.setBlockFormat(m_format.blockHeader2); + cursor.setCharFormat(m_format.charHeader2); + } else if (format == BlockFormat::Header && hLevel == 3) { + cursor.setBlockFormat(m_format.blockHeader3); + cursor.setCharFormat(m_format.charHeader3); + } else if (format == BlockFormat::Header && hLevel == 4) { + cursor.setBlockFormat(m_format.blockHeader4); + cursor.setCharFormat(m_format.charHeader4); + } + cursor.endEditBlock(); + + emit currentBlockChanged(cursor.block()); +} + /** * Private Slots * ============= diff --git a/src/editor/textedit.h b/src/editor/textedit.h index fda7d70..f844552 100644 --- a/src/editor/textedit.h +++ b/src/editor/textedit.h @@ -41,6 +41,10 @@ class GuiTextEdit : public QTextEdit Q_OBJECT public: + enum BlockFormat { + Paragraph, Header, BlockQuote + }; + GuiTextEdit(QWidget *parent=nullptr); ~GuiTextEdit() {}; @@ -68,7 +72,18 @@ class GuiTextEdit : public QTextEdit void currentBlockChanged(const QTextBlock &block); public slots: - void applyDocAction(DocAction action); + void toggleBoldFormat(); + void toggleItalicFormat(); + void toggleUnderlineFormat(); + void toggleStrikeOutFormat(); + void toggleSuperScriptFormat(); + void toggleSubScriptFormat(); + void toggleSegmentFormat(); + void toggleFirstLineIndent(); + void increaseBlockIndent(); + void decreaseBlockIndent(); + void applyBlockAlignment(Qt::Alignment align); + void applyBlockFormat(BlockFormat format, int hLevel); private slots: void processCursorPositionChanged(); diff --git a/src/project/document.cpp b/src/project/document.cpp index 2cba8ae..111124c 100644 --- a/src/project/document.cpp +++ b/src/project/document.cpp @@ -35,6 +35,7 @@ Document::Document(Storage *store, const QUuid uuid) m_locked = false; m_unsaved = true; m_created = QDateTime::currentDateTime().toString(Qt::ISODate); + m_updated = QDateTime::currentDateTime().toString(Qt::ISODate); } /** @@ -44,7 +45,7 @@ Document::Document(Storage *store, const QUuid uuid) void Document::setContent(const QJsonArray &content) { m_content = content; - m_unsaved = true; + this->docChanged(); } void Document::setLocked(bool locked) { @@ -101,12 +102,19 @@ bool Document::read() { } else { m_created = "unknown"; } + if (json.contains(QLatin1String("m:created"))) { + m_updated = json.value(QLatin1String("m:updated")).toString(); + } else { + m_updated = "unknown"; + } if (json.contains(QLatin1String("x:content"))) { m_content = json.value(QLatin1String("x:content")).toArray(); } else { m_content = QJsonArray(); } + m_unsaved = false; + return true; } @@ -129,8 +137,9 @@ bool Document::write() { } QJsonObject json; + json.insert(QLatin1String("c:format"), "document"); json.insert(QLatin1String("m:created"), m_created); - json.insert(QLatin1String("m:updated"), QDateTime::currentDateTime().toString(Qt::ISODate)); + json.insert(QLatin1String("m:updated"), m_updated); json.insert(QLatin1String("x:content"), m_content); if (!m_store->saveFile(m_handle, json)) { @@ -142,4 +151,14 @@ bool Document::write() { return true; } +/** + * Internal Functions + * ================== + */ + +void Document::docChanged() { + m_updated = QDateTime::currentDateTime().toString(Qt::ISODate); + m_unsaved = true; +} + } // namespace Collett diff --git a/src/project/document.h b/src/project/document.h index 0ac645e..3f412bf 100644 --- a/src/project/document.h +++ b/src/project/document.h @@ -69,8 +69,11 @@ class Document : public QObject // Data Variables QString m_created; + QString m_updated; QJsonArray m_content; + void docChanged(); + }; } // namespace Collett diff --git a/src/project/project.cpp b/src/project/project.cpp index 8f1433d..e027149 100644 --- a/src/project/project.cpp +++ b/src/project/project.cpp @@ -205,6 +205,8 @@ bool Project::saveSettingsFile() { // Project Settings jProject[QLatin1String("u:project-name")] = m_projectName; + // Root Object + jData[QLatin1String("c:format")] = "project"; jData[QLatin1String("c:meta")] = jMeta; jData[QLatin1String("c:project")] = jProject; jData[QLatin1String("c:settings")] = jSettings; diff --git a/src/settings.cpp b/src/settings.cpp index e357ba3..4b42e48 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -28,9 +28,11 @@ #define CNF_EDITOR_AUTO_SAVE "Editor/autoSave" #define CNF_TEXT_FONT_SIZE "TextFormat/fontSize" +#define CNF_TEXT_TAB_WIDTH "TextFormat/tabWidth" #include +#include #include #include #include @@ -112,6 +114,7 @@ CollettSettings::CollettSettings() { // ----------- m_textFontSize = std::max(settings.value(CNF_TEXT_FONT_SIZE, (qreal)13.0).toReal(), 5.0); + m_textTabWidth = std::max(settings.value(CNF_TEXT_TAB_WIDTH, (qreal)40.0).toReal(), 0.0); recalculateTextFormats(); } @@ -202,17 +205,17 @@ void CollettSettings::recalculateTextFormats() { qreal defaultTopMargin = 0.5 * m_textFontSize; qreal defaultBottomMargin = 0.5 * m_textFontSize; - qreal header1FontSize = 2.2*m_textFontSize; - qreal header2FontSize = 1.9*m_textFontSize; - qreal header3FontSize = 1.6*m_textFontSize; - qreal header4FontSize = 1.3*m_textFontSize; + qreal header1FontSize = 2.0*m_textFontSize; + qreal header2FontSize = 1.7*m_textFontSize; + qreal header3FontSize = 1.4*m_textFontSize; + qreal header4FontSize = 1.2*m_textFontSize; qreal headerBottomMargin = 0.7 * m_textFontSize; // Text Format Values m_textFormat.fontSize = m_textFontSize; - m_textFormat.textIndent = 2.0 * m_textFontSize; + m_textFormat.tabWidth = m_textTabWidth; m_textFormat.lineHeight = 1.15; // Default Text Formats @@ -241,6 +244,7 @@ void CollettSettings::recalculateTextFormats() { m_textFormat.charHeader1 = defaultCharFmt; m_textFormat.charHeader1.setFontPointSize(header1FontSize); + m_textFormat.charHeader1.setFontWeight(QFont::Bold); // Header 2 Formats @@ -251,6 +255,7 @@ void CollettSettings::recalculateTextFormats() { m_textFormat.charHeader2 = defaultCharFmt; m_textFormat.charHeader2.setFontPointSize(header2FontSize); + m_textFormat.charHeader2.setFontWeight(QFont::Bold); // Header 3 Formats @@ -261,6 +266,7 @@ void CollettSettings::recalculateTextFormats() { m_textFormat.charHeader3 = defaultCharFmt; m_textFormat.charHeader3.setFontPointSize(header3FontSize); + m_textFormat.charHeader3.setFontWeight(QFont::Bold); // Header 4 Formats @@ -271,6 +277,7 @@ void CollettSettings::recalculateTextFormats() { m_textFormat.charHeader4 = defaultCharFmt; m_textFormat.charHeader4.setFontPointSize(header4FontSize); + m_textFormat.charHeader4.setFontWeight(QFont::Bold); } diff --git a/src/settings.h b/src/settings.h index fae5262..296ee8c 100644 --- a/src/settings.h +++ b/src/settings.h @@ -52,7 +52,7 @@ class CollettSettings : public QObject QTextBlockFormat blockHeader4; QTextCharFormat charHeader4; qreal fontSize; - qreal textIndent; + qreal tabWidth; qreal lineHeight; }; @@ -70,6 +70,7 @@ class CollettSettings : public QObject void setMainSplitSizes(const QList &sizes); void setEditorAutoSave(const int interval); void setTextFontSize(const qreal size); + void setTextTabWidth(const qreal width); // Getters @@ -93,6 +94,7 @@ class CollettSettings : public QObject // Text Format qreal m_textFontSize; + qreal m_textTabWidth; TextFormat m_textFormat; // Internal Functions