From 1d2183d44e22bdda8bc9a4015449d1d28597e27e Mon Sep 17 00:00:00 2001 From: Le Tan Date: Fri, 5 Jan 2018 19:36:54 +0800 Subject: [PATCH] VMdEditor: support zoom in/out --- src/hgmarkdownhighlighter.h | 18 +++++ src/resources/markdown_template.js | 2 +- src/veditor.cpp | 41 ++++++++++++ src/veditor.h | 6 ++ src/vedittab.cpp | 13 ++-- src/vmdeditor.cpp | 102 ++++++++++++++++++++++++++++- src/vmdeditor.h | 18 +++++ src/vmdtab.cpp | 6 +- 8 files changed, 195 insertions(+), 11 deletions(-) diff --git a/src/hgmarkdownhighlighter.h b/src/hgmarkdownhighlighter.h index 6f639a37..e0f17741 100644 --- a/src/hgmarkdownhighlighter.h +++ b/src/hgmarkdownhighlighter.h @@ -133,6 +133,10 @@ public: // Parse and only update the highlight results for rehighlight(). void updateHighlightFast(); + QHash &getCodeBlockStyles(); + + QVector &getHighlightingStyles(); + signals: void highlightCompleted(); @@ -167,8 +171,11 @@ private: QTextCharFormat m_colorColumnFormat; QTextDocument *document; + QVector highlightingStyles; + QHash m_codeBlockStyles; + QVector > blockHighlights; // Use another member to store the codeblocks highlights, because the highlight @@ -294,4 +301,15 @@ inline VTextBlockData *HGMarkdownHighlighter::previousBlockData() const return static_cast(block.userData()); } + +inline QHash &HGMarkdownHighlighter::getCodeBlockStyles() +{ + return m_codeBlockStyles; +} + +inline QVector &HGMarkdownHighlighter::getHighlightingStyles() +{ + return highlightingStyles; +} + #endif diff --git a/src/resources/markdown_template.js b/src/resources/markdown_template.js index 40903393..a3e030a1 100644 --- a/src/resources/markdown_template.js +++ b/src/resources/markdown_template.js @@ -199,7 +199,7 @@ document.onkeydown = function(e) { case 104: case 105: { - if (pendingKeys.length != 0) { + if (pendingKeys.length != 0 || ctrl || shift) { accept = false; break; } diff --git a/src/veditor.cpp b/src/veditor.cpp index d4b0874a..dfceaf90 100644 --- a/src/veditor.cpp +++ b/src/veditor.cpp @@ -878,6 +878,47 @@ bool VEditor::handleMouseMoveEvent(QMouseEvent *p_event) return false; } +bool VEditor::handleWheelEvent(QWheelEvent *p_event) +{ + Qt::KeyboardModifiers modifiers = p_event->modifiers(); + if (modifiers == Qt::ShiftModifier) { + // Scroll horizontally. + QPoint numPixels = p_event->pixelDelta(); + QPoint numDegrees = p_event->angleDelta() / 8; + + QScrollBar *horBar = horizontalScrollBarW(); + int steps = 0; + if (!numPixels.isNull()) { + steps = numPixels.y(); + } else if (!numDegrees.isNull()) { + QPoint numSteps = numDegrees / 15; + steps = numSteps.y() * horBar->singleStep(); + } + + if (horBar->minimum() != horBar->maximum()) { + horBar->setValue(horBar->value() - steps); + } + + p_event->accept(); + return true; + } else if (modifiers == Qt::ControlModifier) { + // Zoom in/out. + QPoint angle = p_event->angleDelta(); + if (!angle.isNull() && (angle.y() != 0)) { + if (angle.y() > 0) { + zoomInW(); + } else { + zoomOutW(); + } + } + + p_event->accept(); + return true; + } + + return false; +} + void VEditor::requestUpdateVimStatus() { if (m_editOps) { diff --git a/src/veditor.h b/src/veditor.h index 557c368c..740dd734 100644 --- a/src/veditor.h +++ b/src/veditor.h @@ -186,6 +186,10 @@ public: // Whether display cursor as block. virtual void setCursorBlockModeW(CursorBlock p_mode) = 0; + virtual void zoomInW(int p_range = 1) = 0; + + virtual void zoomOutW(int p_range = 1) = 0; + protected: void init(); @@ -216,6 +220,8 @@ protected: bool handleInputMethodQuery(Qt::InputMethodQuery p_query, QVariant &p_var) const; + bool handleWheelEvent(QWheelEvent *p_event); + QWidget *m_editor; VEditorObject *m_object; diff --git a/src/vedittab.cpp b/src/vedittab.cpp index 0832b3ca..b0b6af37 100644 --- a/src/vedittab.cpp +++ b/src/vedittab.cpp @@ -68,17 +68,18 @@ void VEditTab::handleFocusChanged(QWidget * /* p_old */, QWidget *p_now) void VEditTab::wheelEvent(QWheelEvent *p_event) { - QPoint angle = p_event->angleDelta(); - Qt::KeyboardModifiers modifiers = p_event->modifiers(); - if (!angle.isNull() && (angle.y() != 0) && (modifiers & Qt::ControlModifier)) { - // Zoom in/out current tab. - zoom(angle.y() > 0); + if (p_event->modifiers() & Qt::ControlModifier) { + QPoint angle = p_event->angleDelta(); + if (!angle.isNull() && (angle.y() != 0)) { + // Zoom in/out current tab. + zoom(angle.y() > 0); + } p_event->accept(); return; } - p_event->ignore(); + QWidget::wheelEvent(p_event); } VEditTabInfo VEditTab::fetchTabInfo(VEditTabInfo::InfoType p_type) const diff --git a/src/vmdeditor.cpp b/src/vmdeditor.cpp index 8973a3c5..338e6e51 100644 --- a/src/vmdeditor.cpp +++ b/src/vmdeditor.cpp @@ -31,7 +31,8 @@ VMdEditor::VMdEditor(VFile *p_file, VEditor(p_file, this), m_mdHighlighter(NULL), m_freshEdit(true), - m_textToHtmlDialog(NULL) + m_textToHtmlDialog(NULL), + m_zoomDelta(0) { Q_ASSERT(p_file->getDocType() == DocType::Markdown); @@ -666,6 +667,46 @@ void VMdEditor::clearUnusedImages() void VMdEditor::keyPressEvent(QKeyEvent *p_event) { + int modifiers = p_event->modifiers(); + switch (p_event->key()) { + case Qt::Key_Minus: + case Qt::Key_Underscore: + // Zoom out. + if (modifiers & Qt::ControlModifier) { + zoomPage(false); + return; + } + + break; + + case Qt::Key_Plus: + case Qt::Key_Equal: + // Zoom in. + if (modifiers & Qt::ControlModifier) { + zoomPage(true); + return; + } + + break; + + case Qt::Key_0: + // Restore zoom. + if (modifiers & Qt::ControlModifier) { + if (m_zoomDelta > 0) { + zoomPage(false, m_zoomDelta); + } else if (m_zoomDelta < 0) { + zoomPage(true, -m_zoomDelta); + } + + return; + } + + break; + + default: + break; + } + if (m_editOps && m_editOps->handleKeyPressEvent(p_event)) { return; } @@ -1029,3 +1070,62 @@ void VMdEditor::textToHtmlFinished(const QString &p_text, m_textToHtmlDialog->setConvertedHtml(p_baseUrl, p_html); } } + +void VMdEditor::wheelEvent(QWheelEvent *p_event) +{ + if (handleWheelEvent(p_event)) { + return; + } + + VTextEdit::wheelEvent(p_event); +} + +void VMdEditor::zoomPage(bool p_zoomIn, int p_range) +{ + int delta; + const int minSize = 2; + + if (p_zoomIn) { + delta = p_range; + zoomIn(p_range); + } else { + delta = -p_range; + zoomOut(p_range); + } + + m_zoomDelta += delta; + + QVector &styles = m_mdHighlighter->getHighlightingStyles(); + for (auto & it : styles) { + int size = it.format.fontPointSize(); + if (size == 0) { + // It contains no font size format. + continue; + } + + size += delta; + if (size < minSize) { + size = minSize; + } + + it.format.setFontPointSize(size); + } + + QHash &cbStyles = m_mdHighlighter->getCodeBlockStyles(); + for (auto it = cbStyles.begin(); it != cbStyles.end(); ++it) { + int size = it.value().fontPointSize(); + if (size == 0) { + // It contains no font size format. + continue; + } + + size += delta; + if (size < minSize) { + size = minSize; + } + + it.value().setFontPointSize(size); + } + + m_mdHighlighter->rehighlight(); +} diff --git a/src/vmdeditor.h b/src/vmdeditor.h index 0ec120e4..76428bc1 100644 --- a/src/vmdeditor.h +++ b/src/vmdeditor.h @@ -158,6 +158,16 @@ public: setCursorBlockMode(p_mode); } + void zoomInW(int p_range = 1) Q_DECL_OVERRIDE + { + zoomPage(true, p_range); + } + + void zoomOutW(int p_range = 1) Q_DECL_OVERRIDE + { + zoomPage(false, p_range); + } + signals: // Signal when headers change. void headersChanged(const QVector &p_headers); @@ -190,6 +200,8 @@ protected: void insertFromMimeData(const QMimeData *p_source) Q_DECL_OVERRIDE; + void wheelEvent(QWheelEvent *p_event) Q_DECL_OVERRIDE; + private slots: // Update m_headers according to elements. void updateHeaders(const QVector &p_headerRegions); @@ -216,6 +228,10 @@ private: // Index in m_headers of current header which contains the cursor. int indexOfCurrentHeader() const; + // Zoom in/out. + // We need to maintain the styles font size. + void zoomPage(bool p_zoomIn, int p_range = 1); + HGMarkdownHighlighter *m_mdHighlighter; VCodeBlockHighlightHelper *m_cbHighlighter; @@ -234,5 +250,7 @@ private: bool m_freshEdit; VCopyTextAsHtmlDialog *m_textToHtmlDialog; + + int m_zoomDelta; }; #endif // VMDEDITOR_H diff --git a/src/vmdtab.cpp b/src/vmdtab.cpp index 63ba2199..679246f5 100644 --- a/src/vmdtab.cpp +++ b/src/vmdtab.cpp @@ -677,9 +677,9 @@ void VMdTab::handleWebKeyPressed(int p_key, bool p_ctrl, bool /* p_shift */) void VMdTab::zoom(bool p_zoomIn, qreal p_step) { - if (m_isEditMode) { - // TODO - } else { + // Editor will handle it itself. + Q_ASSERT(!m_isEditMode); + if (!m_isEditMode) { zoomWebPage(p_zoomIn, p_step); } }