diff --git a/src/dialog/veditsnippetdialog.cpp b/src/dialog/veditsnippetdialog.cpp index 9d56a302..6c0cac0d 100644 --- a/src/dialog/veditsnippetdialog.cpp +++ b/src/dialog/veditsnippetdialog.cpp @@ -72,6 +72,11 @@ void VEditSnippetDialog::setupUI(const QString &p_title, const QString &p_info) m_selectionMarkEdit = new QLineEdit(m_snippet.getSelectionMark()); m_selectionMarkEdit->setToolTip(tr("String in the content to be replaced with selected text")); + // Auto Indent. + m_autoIndentCB = new QCheckBox(tr("Auto indent"), this); + m_autoIndentCB->setToolTip(tr("Auto indent the content according to the first line")); + m_autoIndentCB->setChecked(m_snippet.getAutoIndent()); + // Content. m_contentEdit = new QTextEdit(); setContentEditByType(); @@ -82,6 +87,7 @@ void VEditSnippetDialog::setupUI(const QString &p_title, const QString &p_info) topLayout->addRow(tr("Shortc&ut:"), m_shortcutCB); topLayout->addRow(tr("Cursor &mark:"), m_cursorMarkEdit); topLayout->addRow(tr("&Selection mark:"), m_selectionMarkEdit); + topLayout->addWidget(m_autoIndentCB); topLayout->addRow(tr("&Content:"), m_contentEdit); m_warnLabel = new QLabel(); @@ -275,6 +281,11 @@ QChar VEditSnippetDialog::getShortcutInput() const return m_shortcutCB->currentData().toChar(); } +bool VEditSnippetDialog::getAutoIndentInput() const +{ + return m_autoIndentCB->isChecked(); +} + QVector VEditSnippetDialog::getAvailableShortcuts() const { QVector ret = VSnippet::getAllShortcuts(); diff --git a/src/dialog/veditsnippetdialog.h b/src/dialog/veditsnippetdialog.h index cdbc1487..8c4987b4 100644 --- a/src/dialog/veditsnippetdialog.h +++ b/src/dialog/veditsnippetdialog.h @@ -12,6 +12,7 @@ class QLabel; class QDialogButtonBox; class QComboBox; class QTextEdit; +class QCheckBox; class VEditSnippetDialog : public QDialog @@ -36,6 +37,8 @@ public: QChar getShortcutInput() const; + bool getAutoIndentInput() const; + private slots: void handleInputChanged(); @@ -53,6 +56,7 @@ private: QComboBox *m_shortcutCB; QLineEdit *m_cursorMarkEdit; QLineEdit *m_selectionMarkEdit; + QCheckBox *m_autoIndentCB; QTextEdit *m_contentEdit; QLabel *m_warnLabel; diff --git a/src/utils/veditutils.cpp b/src/utils/veditutils.cpp index 5cb04f97..6c24538e 100644 --- a/src/utils/veditutils.cpp +++ b/src/utils/veditutils.cpp @@ -200,10 +200,11 @@ void VEditUtils::indentSelectedBlocks(const QTextDocument *p_doc, } void VEditUtils::indentBlock(QTextCursor &p_cursor, - const QString &p_indentationText) + const QString &p_indentationText, + bool p_skipEmpty) { QTextBlock block = p_cursor.block(); - if (block.length() > 1) { + if (block.length() > 1 || !p_skipEmpty) { p_cursor.movePosition(QTextCursor::StartOfBlock); p_cursor.insertText(p_indentationText); } diff --git a/src/utils/veditutils.h b/src/utils/veditutils.h index 47ae97ac..0db357db 100644 --- a/src/utils/veditutils.h +++ b/src/utils/veditutils.h @@ -63,9 +63,10 @@ public: bool p_isIndent); // Indent current block. - // Skip empty block. + // @p_skipEmpty: skip empty block. static void indentBlock(QTextCursor &p_cursor, - const QString &p_indentationText); + const QString &p_indentationText, + bool p_skipEmpty = true); static void unindentBlock(QTextCursor &p_cursor, const QString &p_indentationText); diff --git a/src/vconstants.h b/src/vconstants.h index 11827c0f..ad37049c 100644 --- a/src/vconstants.h +++ b/src/vconstants.h @@ -60,6 +60,7 @@ namespace SnippetConfig static const QString c_cursorMark = "cursor_mark"; static const QString c_selectionMark = "selection_mark"; static const QString c_shortcut = "shortcut"; + static const QString c_autoIndent = "auto_indent"; } static const QString c_emptyHeaderName = "[EMPTY]"; diff --git a/src/vsnippet.cpp b/src/vsnippet.cpp index 3c700d5d..17e0676f 100644 --- a/src/vsnippet.cpp +++ b/src/vsnippet.cpp @@ -18,7 +18,8 @@ QVector VSnippet::s_allShortcuts; VSnippet::VSnippet() : m_type(Type::PlainText), - m_cursorMark(c_defaultCursorMark) + m_cursorMark(c_defaultCursorMark), + m_autoIndent(false) { } @@ -27,13 +28,15 @@ VSnippet::VSnippet(const QString &p_name, const QString &p_content, const QString &p_cursorMark, const QString &p_selectionMark, - QChar p_shortcut) + QChar p_shortcut, + bool p_autoIndent) : m_name(p_name), m_type(p_type), m_content(p_content), m_cursorMark(p_cursorMark), m_selectionMark(p_selectionMark), - m_shortcut(p_shortcut) + m_shortcut(p_shortcut), + m_autoIndent(p_autoIndent) { Q_ASSERT(m_selectionMark != m_cursorMark); } @@ -43,7 +46,8 @@ bool VSnippet::update(const QString &p_name, const QString &p_content, const QString &p_cursorMark, const QString &p_selectionMark, - QChar p_shortcut) + QChar p_shortcut, + bool p_autoIndent) { bool updated = false; if (m_name != p_name) { @@ -76,6 +80,11 @@ bool VSnippet::update(const QString &p_name, updated = true; } + if (m_autoIndent != p_autoIndent) { + m_autoIndent = p_autoIndent; + updated = true; + } + qDebug() << "snippet" << m_name << "updated" << updated; return updated; @@ -103,6 +112,7 @@ QJsonObject VSnippet::toJson() const snip[SnippetConfig::c_cursorMark] = m_cursorMark; snip[SnippetConfig::c_selectionMark] = m_selectionMark; snip[SnippetConfig::c_shortcut] = m_shortcut.isNull() ? "" : QString(m_shortcut); + snip[SnippetConfig::c_autoIndent] = m_autoIndent; return snip; } @@ -120,7 +130,8 @@ VSnippet VSnippet::fromJson(const QJsonObject &p_json) "", p_json[SnippetConfig::c_cursorMark].toString(), p_json[SnippetConfig::c_selectionMark].toString(), - shortcut); + shortcut, + p_json[SnippetConfig::c_autoIndent].toBool()); return snip; } @@ -193,11 +204,15 @@ bool VSnippet::apply(QTextCursor &p_cursor) const content += secondPart; + // Auto indent. + QTextBlock startBlock = p_cursor.block(); + QTextBlock endBlock; + QString indentation = VEditUtils::fetchIndentSpaces(startBlock); + // Insert it. switch (m_type) { case Type::Html: p_cursor.insertHtml(content); - // TODO: set the position of the cursor. break; case Type::PlainText: @@ -205,10 +220,34 @@ bool VSnippet::apply(QTextCursor &p_cursor) const default: p_cursor.insertText(content); - p_cursor.setPosition(pos); break; } + endBlock = p_cursor.block(); + + if (m_autoIndent + && startBlock != endBlock + && !indentation.isEmpty()) { + // Indent (startBlock, endBlock]. + startBlock = startBlock.next(); + while (startBlock.isValid()) { + int tmpPos = startBlock.position(); + p_cursor.setPosition(tmpPos); + VEditUtils::indentBlock(p_cursor, indentation, false); + if (tmpPos <= pos) { + pos += indentation.size(); + } + + if (startBlock == endBlock) { + break; + } + + startBlock = startBlock.next(); + } + } + + p_cursor.setPosition(pos); + p_cursor.endEditBlock(); return true; } diff --git a/src/vsnippet.h b/src/vsnippet.h index 815ab2be..084389df 100644 --- a/src/vsnippet.h +++ b/src/vsnippet.h @@ -23,7 +23,8 @@ public: const QString &p_content = QString(), const QString &p_cursorMark = c_defaultCursorMark, const QString &p_selectionMark = c_defaultSelectionMark, - QChar p_shortcut = QChar()); + QChar p_shortcut = QChar(), + bool p_autoIndent = false); // Return true if there is any update. bool update(const QString &p_name, @@ -31,7 +32,8 @@ public: const QString &p_content, const QString &p_cursorMark, const QString &p_selectionMark, - QChar p_shortcut); + QChar p_shortcut, + bool p_autoIndent); const QString &getName() const { @@ -63,6 +65,11 @@ public: return m_shortcut; } + bool getAutoIndent() const + { + return m_autoIndent; + } + void setContent(const QString &p_content) { m_content = p_content; @@ -103,6 +110,9 @@ private: // Shortcut to apply this snippet. QChar m_shortcut; + // Auto indent with the first line. + bool m_autoIndent; + static const QString c_defaultCursorMark; static const QString c_defaultSelectionMark; diff --git a/src/vsnippetlist.cpp b/src/vsnippetlist.cpp index 0822f416..33e62652 100644 --- a/src/vsnippetlist.cpp +++ b/src/vsnippetlist.cpp @@ -145,7 +145,8 @@ void VSnippetList::newSnippet() dialog.getContentInput(), dialog.getCursorMarkInput(), dialog.getSelectionMarkInput(), - dialog.getShortcutInput()); + dialog.getShortcutInput(), + dialog.getAutoIndentInput()); QString errMsg; if (!addSnippet(snippet, &errMsg)) { @@ -336,7 +337,8 @@ void VSnippetList::snippetInfo() dialog.getContentInput(), dialog.getCursorMarkInput(), dialog.getSelectionMarkInput(), - dialog.getShortcutInput())) { + dialog.getShortcutInput(), + dialog.getAutoIndentInput())) { if (!writeSnippetFile(*snip, &errMsg)) { ret = false; }