diff --git a/src/resources/vnote.ini b/src/resources/vnote.ini index 66e215b1..0ecd53f4 100644 --- a/src/resources/vnote.ini +++ b/src/resources/vnote.ini @@ -50,6 +50,9 @@ enable_trailing_space_highlight=true ; Enable Vim mode in edit mode enable_vim_mode=false +; Enable smart input method in Vim mode (disable IM in non-Insert modes) +enable_smart_im_in_vim_mode=true + [session] tools_dock_checked=true diff --git a/src/utils/vvim.cpp b/src/utils/vvim.cpp index b8e72d52..b6465790 100644 --- a/src/utils/vvim.cpp +++ b/src/utils/vvim.cpp @@ -84,10 +84,14 @@ static QChar keyToChar(int p_key, int p_modifiers) VVim::VVim(VEdit *p_editor) : QObject(p_editor), m_editor(p_editor), - m_editConfig(&p_editor->getConfig()), m_mode(VimMode::Normal), + m_editConfig(&p_editor->getConfig()), m_mode(VimMode::Invalid), m_resetPositionInBlock(true), m_regName(c_unnamedRegister), m_cmdMode(false), m_leaderKey(Key(Qt::Key_Space)), m_replayLeaderSequence(false) { + Q_ASSERT(m_editConfig->m_enableVimMode); + + setMode(VimMode::Normal); + initRegisters(); connect(m_editor, &VEdit::copyAvailable, @@ -1969,6 +1973,12 @@ void VVim::setMode(VimMode p_mode, bool p_clearSelection) clearSelection(); } + if (p_mode == VimMode::Insert) { + m_editor->setInputMethodEnabled(true); + } else if (vconfig.getEnableSmartImInVimMode()) { + m_editor->setInputMethodEnabled(false); + } + m_mode = p_mode; resetState(); diff --git a/src/vconfigmanager.cpp b/src/vconfigmanager.cpp index 5b9547d7..0c0ccd3d 100644 --- a/src/vconfigmanager.cpp +++ b/src/vconfigmanager.cpp @@ -147,6 +147,9 @@ void VConfigManager::initialize() m_enableVimMode = getConfigFromSettings("global", "enable_vim_mode").toBool(); + + m_enableSmartImInVimMode = getConfigFromSettings("global", + "enable_smart_im_in_vim_mode").toBool(); } void VConfigManager::readPredefinedColorsFromSettings() diff --git a/src/vconfigmanager.h b/src/vconfigmanager.h index 9e82856e..a85868d3 100644 --- a/src/vconfigmanager.h +++ b/src/vconfigmanager.h @@ -196,6 +196,9 @@ public: inline bool getEnableVimMode() const; inline void setEnableVimMode(bool p_enabled); + inline bool getEnableSmartImInVimMode() const; + inline void setEnableSmartImInVimMode(bool p_enabled); + // Get the folder the ini file exists. QString getConfigFolder() const; @@ -358,6 +361,9 @@ private: // Enable Vim mode. bool m_enableVimMode; + // Enable smart input method in Vim mode. + bool m_enableSmartImInVimMode; + // The name of the config file in each directory, obsolete. // Use c_dirConfigFile instead. static const QString c_obsoleteDirConfigFile; @@ -942,4 +948,20 @@ inline void VConfigManager::setEnableVimMode(bool p_enabled) m_enableVimMode); } +inline bool VConfigManager::getEnableSmartImInVimMode() const +{ + return m_enableSmartImInVimMode; +} + +inline void VConfigManager::setEnableSmartImInVimMode(bool p_enabled) +{ + if (m_enableSmartImInVimMode == p_enabled) { + return; + } + + m_enableSmartImInVimMode = p_enabled; + setConfigToSettings("global", "enable_smart_im_in_vim_mode", + m_enableSmartImInVimMode); +} + #endif // VCONFIGMANAGER_H diff --git a/src/vedit.cpp b/src/vedit.cpp index 5fa887de..f5e90227 100644 --- a/src/vedit.cpp +++ b/src/vedit.cpp @@ -14,6 +14,15 @@ extern VConfigManager vconfig; extern VNote *g_vnote; void VEditConfig::init(const QFontMetrics &p_metric) +{ + update(p_metric); + + m_enableVimMode = vconfig.getEnableVimMode(); + + m_highlightWholeBlock = m_enableVimMode; +} + +void VEditConfig::update(const QFontMetrics &p_metric) { if (vconfig.getTabStopWidth() > 0) { m_tabStopWidth = vconfig.getTabStopWidth() * p_metric.width(' '); @@ -29,15 +38,12 @@ void VEditConfig::init(const QFontMetrics &p_metric) m_tabSpaces = "\t"; } - m_enableVimMode = vconfig.getEnableVimMode(); - m_cursorLineBg = QColor(vconfig.getEditorCurrentLineBg()); - - m_highlightWholeBlock = m_enableVimMode; } VEdit::VEdit(VFile *p_file, QWidget *p_parent) - : QTextEdit(p_parent), m_file(p_file), m_editOps(NULL) + : QTextEdit(p_parent), m_file(p_file), + m_editOps(NULL), m_enableInputMethod(true) { const int labelTimerInterval = 500; const int extraSelectionHighlightTimer = 500; @@ -70,6 +76,7 @@ VEdit::VEdit(VFile *p_file, QWidget *p_parent) updateFontAndPalette(); + m_config.init(QFontMetrics(font())); updateConfig(); connect(this, &VEdit::cursorPositionChanged, @@ -89,7 +96,7 @@ VEdit::~VEdit() void VEdit::updateConfig() { - m_config.init(QFontMetrics(font())); + m_config.update(QFontMetrics(font())); if (m_config.m_tabStopWidth > 0) { setTabStopWidth(m_config.m_tabStopWidth); @@ -798,3 +805,24 @@ bool VEdit::jumpTitle(bool p_forward, int p_relativeLevel, int p_repeat) Q_UNUSED(p_repeat); return false; } + +QVariant VEdit::inputMethodQuery(Qt::InputMethodQuery p_query) const +{ + if (p_query == Qt::ImEnabled) { + return m_enableInputMethod; + } + + return QTextEdit::inputMethodQuery(p_query); +} + +void VEdit::setInputMethodEnabled(bool p_enabled) +{ + if (m_enableInputMethod != p_enabled) { + m_enableInputMethod = p_enabled; + + QInputMethod *im = QGuiApplication::inputMethod(); + im->reset(); + // Ask input method to query current state, which will call inputMethodQuery(). + im->update(Qt::ImEnabled); + } +} diff --git a/src/vedit.h b/src/vedit.h index 48a477b4..d21f2cee 100644 --- a/src/vedit.h +++ b/src/vedit.h @@ -35,6 +35,9 @@ public: void init(const QFontMetrics &p_metric); + // Only update those configs which could be updated online. + void update(const QFontMetrics &p_metric); + // Width in pixels. int m_tabStopWidth; @@ -85,6 +88,10 @@ public: // Request to update Vim status. void requestUpdateVimStatus(); + QVariant inputMethodQuery(Qt::InputMethodQuery p_query) const Q_DECL_OVERRIDE; + + void setInputMethodEnabled(bool p_enabled); + signals: // Request VEditTab to save and exit edit mode. void saveAndRead(); @@ -164,6 +171,9 @@ private: int m_oriMouseX; int m_oriMouseY; + // Whether enable input method. + bool m_enableInputMethod; + void showWrapLabel(); // Trigger the timer to request highlight. diff --git a/src/veditoperations.cpp b/src/veditoperations.cpp index c5aa40b7..00a52ec0 100644 --- a/src/veditoperations.cpp +++ b/src/veditoperations.cpp @@ -10,18 +10,21 @@ extern VConfigManager vconfig; VEditOperations::VEditOperations(VEdit *p_editor, VFile *p_file) : QObject(p_editor), m_editor(p_editor), m_file(p_file), - m_editConfig(&p_editor->getConfig()) + m_editConfig(&p_editor->getConfig()), m_vim(NULL) { - m_vim = new VVim(m_editor); - connect(m_editor, &VEdit::configUpdated, this, &VEditOperations::handleEditConfigUpdated); - connect(m_vim, &VVim::modeChanged, - this, &VEditOperations::handleVimModeChanged); - connect(m_vim, &VVim::vimMessage, - this, &VEditOperations::statusMessage); - connect(m_vim, &VVim::vimStatusUpdated, - this, &VEditOperations::vimStatusUpdated); + + if (m_editConfig->m_enableVimMode) { + m_vim = new VVim(m_editor); + + connect(m_vim, &VVim::modeChanged, + this, &VEditOperations::handleVimModeChanged); + connect(m_vim, &VVim::vimMessage, + this, &VEditOperations::statusMessage); + connect(m_vim, &VVim::vimStatusUpdated, + this, &VEditOperations::vimStatusUpdated); + } } void VEditOperations::insertTextAtCurPos(const QString &p_text) @@ -70,7 +73,9 @@ void VEditOperations::updateCursorLineBg() void VEditOperations::handleEditConfigUpdated() { // Reset to Normal mode. - m_vim->setMode(VimMode::Normal); + if (m_vim) { + m_vim->setMode(VimMode::Normal); + } updateCursorLineBg(); } @@ -85,9 +90,5 @@ void VEditOperations::handleVimModeChanged(VimMode p_mode) void VEditOperations::requestUpdateVimStatus() { - if (m_editConfig->m_enableVimMode) { - emit vimStatusUpdated(m_vim); - } else { - emit vimStatusUpdated(NULL); - } + emit vimStatusUpdated(m_vim); } diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp index 6e5dfb84..7f5863e2 100644 --- a/src/vmainwindow.cpp +++ b/src/vmainwindow.cpp @@ -661,11 +661,20 @@ void VMainWindow::initEditMenu() // Vim Mode. QAction *vimAct = new QAction(tr("Vim Mode"), this); - vimAct->setToolTip(tr("Enable Vim mode for editing (re-enter edit mode to make it work)")); + vimAct->setToolTip(tr("Enable Vim mode for editing (re-open current tabs to make it work)")); vimAct->setCheckable(true); connect(vimAct, &QAction::triggered, this, &VMainWindow::changeVimMode); + // Smart input method in Vim mode. + QAction *smartImAct = new QAction(tr("Smart Input Method In Vim Mode"), this); + smartImAct->setToolTip(tr("Disable input method when leaving Insert mode in Vim mode")); + smartImAct->setCheckable(true); + connect(smartImAct, &QAction::triggered, + this, [this](bool p_checked){ + vconfig.setEnableSmartImInVimMode(p_checked); + }); + // Highlight current cursor line. QAction *cursorLineAct = new QAction(tr("Highlight Cursor Line"), this); cursorLineAct->setToolTip(tr("Highlight current cursor line")); @@ -751,6 +760,9 @@ void VMainWindow::initEditMenu() editMenu->addAction(vimAct); vimAct->setChecked(vconfig.getEnableVimMode()); + editMenu->addAction(smartImAct); + smartImAct->setChecked(vconfig.getEnableSmartImInVimMode()); + editMenu->addSeparator(); initEditorStyleMenu(editMenu);