diff --git a/src/resources/icons/heading.svg b/src/resources/icons/heading.svg new file mode 100644 index 00000000..b4273b87 --- /dev/null +++ b/src/resources/icons/heading.svg @@ -0,0 +1,7 @@ + + + + Layer 1 + H + + diff --git a/src/vconstants.h b/src/vconstants.h index 7ab37955..11827c0f 100644 --- a/src/vconstants.h +++ b/src/vconstants.h @@ -72,7 +72,8 @@ enum class TextDecoration Underline, Strikethrough, InlineCode, - CodeBlock + CodeBlock, + Heading }; enum FindOption diff --git a/src/veditoperations.cpp b/src/veditoperations.cpp index e11887aa..e36a236a 100644 --- a/src/veditoperations.cpp +++ b/src/veditoperations.cpp @@ -100,8 +100,3 @@ void VEditOperations::setVimMode(VimMode p_mode) m_vim->setMode(p_mode); } } - -void VEditOperations::decorateText(TextDecoration p_decoration) -{ - Q_UNUSED(p_decoration); -} diff --git a/src/veditoperations.h b/src/veditoperations.h index 3af62c13..32f92e9e 100644 --- a/src/veditoperations.h +++ b/src/veditoperations.h @@ -38,7 +38,11 @@ public: void requestUpdateVimStatus(); // Insert decoration markers or decorate selected text. - virtual void decorateText(TextDecoration p_decoration); + virtual void decorateText(TextDecoration p_decoration, int p_level = -1) + { + Q_UNUSED(p_decoration); + Q_UNUSED(p_level); + } // Set Vim mode if not NULL. void setVimMode(VimMode p_mode); diff --git a/src/veditor.cpp b/src/veditor.cpp index 509b9289..c21047b0 100644 --- a/src/veditor.cpp +++ b/src/veditor.cpp @@ -893,10 +893,10 @@ void VEditor::setInputMethodEnabled(bool p_enabled) } } -void VEditor::decorateText(TextDecoration p_decoration) +void VEditor::decorateText(TextDecoration p_decoration, int p_level) { if (m_editOps) { - m_editOps->decorateText(p_decoration); + m_editOps->decorateText(p_decoration, p_level); } } diff --git a/src/veditor.h b/src/veditor.h index 733b7bcc..a6a1ac35 100644 --- a/src/veditor.h +++ b/src/veditor.h @@ -120,7 +120,7 @@ public: void setInputMethodEnabled(bool p_enabled); // Insert decoration markers or decorate selected text. - void decorateText(TextDecoration p_decoration); + void decorateText(TextDecoration p_decoration, int p_level); virtual bool isBlockVisible(const QTextBlock &p_block) = 0; diff --git a/src/vedittab.h b/src/vedittab.h index 445b5e42..e0bd1253 100644 --- a/src/vedittab.h +++ b/src/vedittab.h @@ -73,7 +73,11 @@ public: virtual void requestUpdateVimStatus() = 0; // Insert decoration markers or decorate selected text. - virtual void decorateText(TextDecoration p_decoration) {Q_UNUSED(p_decoration);} + virtual void decorateText(TextDecoration p_decoration, int p_level = -1) + { + Q_UNUSED(p_decoration); + Q_UNUSED(p_level); + } // Create a filled VEditTabInfo. virtual VEditTabInfo fetchTabInfo() const; diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp index be75c7f9..7b87496d 100644 --- a/src/vmainwindow.cpp +++ b/src/vmainwindow.cpp @@ -424,6 +424,8 @@ void VMainWindow::initEditToolBar(QSize p_iconSize) m_editToolBar->addAction(m_headingSequenceAct); + initHeadingButton(m_editToolBar); + QAction *boldAct = new QAction(QIcon(":/resources/icons/bold.svg"), tr("Bold\t%1").arg(VUtils::getShortcutText("Ctrl+B")), this); @@ -1829,6 +1831,8 @@ void VMainWindow::updateActionsStateFromTab(const VEditTab *p_tab) m_attachmentBtn->setEnabled(file && file->getType() == FileType::Note); + m_headingBtn->setEnabled(file && editMode); + setActionsEnabled(m_editToolBar, file && editMode); // Handle heading sequence act independently. @@ -2712,3 +2716,62 @@ void VMainWindow::openFlashPage() OpenFileMode::Edit, true); } + +void VMainWindow::initHeadingButton(QToolBar *p_tb) +{ + m_headingBtn = new QPushButton(QIcon(":/resources/icons/heading.svg"), + "", + this); + m_headingBtn->setToolTip(tr("Headings")); + m_headingBtn->setProperty("CornerBtn", true); + m_headingBtn->setFocusPolicy(Qt::NoFocus); + m_headingBtn->setEnabled(false); + + QMenu *menu = new QMenu(this); + QAction *act = menu->addAction(tr("Heading 1\t%1").arg(VUtils::getShortcutText("Ctrl+1"))); + QFont font = act->font(); + int ps = font.pointSize(); + font.setBold(true); + font.setPointSize(ps + 8); + act->setFont(font); + act->setData(1); + + act = menu->addAction(tr("Heading 2\t%1").arg(VUtils::getShortcutText("Ctrl+2"))); + font.setPointSize(ps + 6); + act->setFont(font); + act->setData(2); + + act = menu->addAction(tr("Heading 3\t%1").arg(VUtils::getShortcutText("Ctrl+3"))); + font.setPointSize(ps + 4); + act->setFont(font); + act->setData(3); + + act = menu->addAction(tr("Heading 4\t%1").arg(VUtils::getShortcutText("Ctrl+4"))); + font.setPointSize(ps + 2); + act->setFont(font); + act->setData(4); + + act = menu->addAction(tr("Heading 5\t%1").arg(VUtils::getShortcutText("Ctrl+5"))); + font.setPointSize(ps + 2); + act->setFont(font); + act->setData(5); + + act = menu->addAction(tr("Heading 6\t%1").arg(VUtils::getShortcutText("Ctrl+6"))); + font.setPointSize(ps + 2); + act->setFont(font); + act->setData(6); + + act = menu->addAction(tr("Clear\t%1").arg(VUtils::getShortcutText("Ctrl+7"))); + act->setData(0); + + connect(menu, &QMenu::triggered, + this, [this](QAction *p_action) { + if (m_curTab) { + int level = p_action->data().toInt(); + m_curTab->decorateText(TextDecoration::Heading, level); + } + }); + + m_headingBtn->setMenu(menu); + p_tb->addWidget(m_headingBtn); +} diff --git a/src/vmainwindow.h b/src/vmainwindow.h index fc61d580..df5d2f5c 100644 --- a/src/vmainwindow.h +++ b/src/vmainwindow.h @@ -261,6 +261,8 @@ private: void initShortcuts(); + void initHeadingButton(QToolBar *p_tb); + // Captain mode functions. // Popup the attachment list if it is enabled. @@ -372,6 +374,8 @@ private: // Attachment list. VAttachmentList *m_attachmentList; + QPushButton *m_headingBtn; + QVector predefinedColorPixmaps; // Single instance guard. diff --git a/src/vmdeditoperations.cpp b/src/vmdeditoperations.cpp index 4018a596..06edd0ea 100644 --- a/src/vmdeditoperations.cpp +++ b/src/vmdeditoperations.cpp @@ -223,7 +223,7 @@ bool VMdEditOperations::handleKeyPressEvent(QKeyEvent *p_event) { if (modifiers == Qt::ControlModifier) { // Ctrl + : insert title at level . - if (insertTitle(key == Qt::Key_7 ? 0 : key - Qt::Key_0)) { + if (decorateHeading(key == Qt::Key_7 ? 0 : key - Qt::Key_0)) { p_event->accept(); ret = true; goto exit; @@ -649,7 +649,7 @@ void VMdEditOperations::changeListBlockSeqNumber(QTextBlock &p_block, int p_seq) cursor.insertText(QString::number(p_seq)); } -bool VMdEditOperations::insertTitle(int p_level) +bool VMdEditOperations::decorateHeading(int p_level) { QTextDocument *doc = m_editor->documentW(); QTextCursor cursor = m_editor->textCursorW(); @@ -674,7 +674,7 @@ bool VMdEditOperations::insertTitle(int p_level) return true; } -void VMdEditOperations::decorateText(TextDecoration p_decoration) +void VMdEditOperations::decorateText(TextDecoration p_decoration, int p_level) { if (p_decoration == TextDecoration::None) { return; @@ -702,6 +702,10 @@ void VMdEditOperations::decorateText(TextDecoration p_decoration) decorateCodeBlock(); break; + case TextDecoration::Heading: + decorateHeading(p_level); + break; + default: validDecoration = false; qDebug() << "decoration" << (int)p_decoration << "is not implemented yet"; diff --git a/src/vmdeditoperations.h b/src/vmdeditoperations.h index b9f9a515..dc53e03d 100644 --- a/src/vmdeditoperations.h +++ b/src/vmdeditoperations.h @@ -30,7 +30,7 @@ public: // Insert decoration markers or decorate selected text. // If it is Vim Normal mode, change to Insert mode first. - void decorateText(TextDecoration p_decoration) Q_DECL_OVERRIDE; + void decorateText(TextDecoration p_decoration, int p_level = -1) Q_DECL_OVERRIDE; private: // Insert image from @oriImagePath as @path. @@ -55,12 +55,6 @@ private: bool handleKeyReturn(QKeyEvent *p_event); bool handleKeyBracketLeft(QKeyEvent *p_event); - // Insert title of level @p_level. - // Will detect if current block already has some leading #s. If yes, - // will delete it and insert the correct #s. - // @p_level: 0 to cancel title. - bool insertTitle(int p_level); - // Change the sequence number of a list block. void changeListBlockSeqNumber(QTextBlock &p_block, int p_seq); @@ -79,6 +73,12 @@ private: // Insert strikethrough marker or set selected text strikethrough. void decorateStrikethrough(); + // Insert title of level @p_level. + // Will detect if current block already has some leading #s. If yes, + // will delete it and insert the correct #s. + // @p_level: 0 to cancel title. + bool decorateHeading(int p_level); + // The cursor position after auto indent or auto list. // It will be -1 if last key press do not trigger the auto indent or auto list. int m_autoIndentPos; diff --git a/src/vmdtab.cpp b/src/vmdtab.cpp index ed9e3f24..47628c65 100644 --- a/src/vmdtab.cpp +++ b/src/vmdtab.cpp @@ -717,10 +717,10 @@ VEditTabInfo VMdTab::fetchTabInfo() const return info; } -void VMdTab::decorateText(TextDecoration p_decoration) +void VMdTab::decorateText(TextDecoration p_decoration, int p_level) { if (m_editor) { - m_editor->decorateText(p_decoration); + m_editor->decorateText(p_decoration, p_level); } } diff --git a/src/vmdtab.h b/src/vmdtab.h index 481fc49b..7b547fa7 100644 --- a/src/vmdtab.h +++ b/src/vmdtab.h @@ -66,7 +66,7 @@ public: void requestUpdateVimStatus() Q_DECL_OVERRIDE; // Insert decoration markers or decorate selected text. - void decorateText(TextDecoration p_decoration) Q_DECL_OVERRIDE; + void decorateText(TextDecoration p_decoration, int p_level = -1) Q_DECL_OVERRIDE; // Create a filled VEditTabInfo. VEditTabInfo fetchTabInfo() const Q_DECL_OVERRIDE; diff --git a/src/vnote.qrc b/src/vnote.qrc index d90e3520..0264e946 100644 --- a/src/vnote.qrc +++ b/src/vnote.qrc @@ -143,5 +143,6 @@ resources/icons/apply_snippet.svg resources/icons/reading_modified.svg resources/icons/flash_page.svg + resources/icons/heading.svg