Browse Source

decouple VVimIndicator and VVimCmdLineEdit

Le Tan 7 years ago
parent
commit
b927a525e2

+ 4 - 2
src/src.pro

@@ -107,7 +107,8 @@ SOURCES += main.cpp\
     vwaitingwidget.cpp \
     utils/vwebutils.cpp \
     vlineedit.cpp \
-    vcart.cpp
+    vcart.cpp \
+    vvimcmdlineedit.cpp
 
 HEADERS  += vmainwindow.h \
     vdirectorytree.h \
@@ -201,7 +202,8 @@ HEADERS  += vmainwindow.h \
     vwaitingwidget.h \
     utils/vwebutils.h \
     vlineedit.h \
-    vcart.h
+    vcart.h \
+    vvimcmdlineedit.h
 
 RESOURCES += \
     vnote.qrc \

+ 5 - 0
src/veditoperations.cpp

@@ -100,3 +100,8 @@ void VEditOperations::setVimMode(VimMode p_mode)
         m_vim->setMode(p_mode);
     }
 }
+
+VVim *VEditOperations::getVim() const
+{
+    return m_vim;
+}

+ 2 - 0
src/veditoperations.h

@@ -47,6 +47,8 @@ public:
     // Set Vim mode if not NULL.
     void setVimMode(VimMode p_mode);
 
+    VVim *getVim() const;
+
 signals:
     // Want to display a template message in status bar.
     void statusMessage(const QString &p_msg);

+ 9 - 0
src/veditor.cpp

@@ -970,3 +970,12 @@ void VEditor::setVimMode(VimMode p_mode)
         m_editOps->setVimMode(p_mode);
     }
 }
+
+VVim *VEditor::getVim() const
+{
+    if (m_editOps) {
+        return m_editOps->getVim();
+    }
+
+    return NULL;
+}

+ 2 - 0
src/veditor.h

@@ -142,6 +142,8 @@ public:
 
     void setVimMode(VimMode p_mode);
 
+    VVim *getVim() const;
+
     virtual QString getContent() const = 0;
 
     // @p_modified: if true, delete the whole content and insert the new content.

+ 41 - 0
src/vedittab.cpp

@@ -195,3 +195,44 @@ void VEditTab::handleFileOrDirectoryChange(bool p_isFile, UpdateAction p_act)
     Q_UNUSED(p_isFile);
     Q_UNUSED(p_act);
 }
+
+void VEditTab::handleVimCmdCommandCancelled()
+{
+
+}
+
+void VEditTab::handleVimCmdCommandFinished(VVim::CommandLineType p_type, const QString &p_cmd)
+{
+    Q_UNUSED(p_type);
+    Q_UNUSED(p_cmd);
+}
+
+void VEditTab::handleVimCmdCommandChanged(VVim::CommandLineType p_type, const QString &p_cmd)
+{
+    Q_UNUSED(p_type);
+    Q_UNUSED(p_cmd);
+}
+
+QString VEditTab::handleVimCmdRequestNextCommand(VVim::CommandLineType p_type, const QString &p_cmd)
+{
+    Q_UNUSED(p_type);
+    Q_UNUSED(p_cmd);
+
+    return QString();
+}
+
+QString VEditTab::handleVimCmdRequestPreviousCommand(VVim::CommandLineType p_type, const QString &p_cmd)
+{
+    Q_UNUSED(p_type);
+    Q_UNUSED(p_cmd);
+
+    return QString();
+}
+
+QString VEditTab::handleVimCmdRequestRegister(int p_key, int p_modifiers)
+{
+    Q_UNUSED(p_key);
+    Q_UNUSED(p_modifiers);
+
+    return QString();
+}

+ 15 - 0
src/vedittab.h

@@ -118,6 +118,18 @@ public slots:
     // Enter edit mode
     virtual void editFile() = 0;
 
+    virtual void handleVimCmdCommandCancelled();
+
+    virtual void handleVimCmdCommandFinished(VVim::CommandLineType p_type, const QString &p_cmd);
+
+    virtual void handleVimCmdCommandChanged(VVim::CommandLineType p_type, const QString &p_cmd);
+
+    virtual QString handleVimCmdRequestNextCommand(VVim::CommandLineType p_type, const QString &p_cmd);
+
+    virtual QString handleVimCmdRequestPreviousCommand(VVim::CommandLineType p_type, const QString &p_cmd);
+
+    virtual QString handleVimCmdRequestRegister(int p_key, int p_modifiers);
+
 protected:
     void wheelEvent(QWheelEvent *p_event) Q_DECL_OVERRIDE;
 
@@ -180,6 +192,9 @@ signals:
     // Request to close itself.
     void closeRequested(VEditTab *p_tab);
 
+    // Request main window to show Vim cmd line.
+    void triggerVimCmd(VVim::CommandLineType p_type);
+
 private slots:
     // Called when app focus changed.
     void handleFocusChanged(QWidget *p_old, QWidget *p_now);

+ 101 - 2
src/vmainwindow.cpp

@@ -20,6 +20,7 @@
 #include "vexporter.h"
 #include "vmdtab.h"
 #include "vvimindicator.h"
+#include "vvimcmdlineedit.h"
 #include "vtabindicator.h"
 #include "dialog/vupdater.h"
 #include "vorphanfile.h"
@@ -240,6 +241,8 @@ void VMainWindow::setupUI()
 
     setCentralWidget(m_mainSplitter);
 
+    initVimCmd();
+
     m_vimIndicator = new VVimIndicator(this);
     m_vimIndicator->hide();
 
@@ -247,6 +250,7 @@ void VMainWindow::setupUI()
     m_tabIndicator->hide();
 
     // Create and show the status bar
+    statusBar()->addPermanentWidget(m_vimCmd);
     statusBar()->addPermanentWidget(m_vimIndicator);
     statusBar()->addPermanentWidget(m_tabIndicator);
 
@@ -1835,7 +1839,25 @@ void VMainWindow::updateActionsStateFromTab(const VEditTab *p_tab)
 
 void VMainWindow::handleAreaTabStatusUpdated(const VEditTabInfo &p_info)
 {
-    m_curTab = p_info.m_editTab;
+    if (m_curTab != p_info.m_editTab) {
+        if (m_curTab) {
+            if (m_vimCmd->isVisible()) {
+                m_curTab->handleVimCmdCommandCancelled();
+            }
+
+            // Disconnect the trigger signal from edit tab.
+            disconnect(m_curTab, 0, m_vimCmd, 0);
+        }
+
+        m_curTab = p_info.m_editTab;
+        if (m_curTab) {
+            connect(m_curTab, &VEditTab::triggerVimCmd,
+                    m_vimCmd, &VVimCmdLineEdit::reset);
+        }
+
+        m_vimCmd->hide();
+    }
+
     if (m_curTab) {
         m_curFile = m_curTab->getFile();
     } else {
@@ -2376,7 +2398,7 @@ void VMainWindow::updateStatusInfo(const VEditTabInfo &p_info)
 
 void VMainWindow::handleVimStatusUpdated(const VVim *p_vim)
 {
-    m_vimIndicator->update(p_vim, m_curTab);
+    m_vimIndicator->update(p_vim);
     if (!p_vim || !m_curTab || !m_curTab->isEditMode()) {
         m_vimIndicator->hide();
     } else {
@@ -2826,3 +2848,80 @@ void VMainWindow::customShortcut()
                        this);
     dialog.exec();
 }
+
+void VMainWindow::initVimCmd()
+{
+    m_vimCmd = new VVimCmdLineEdit(this);
+    m_vimCmd->setProperty("VimCommandLine", true);
+
+    connect(m_vimCmd, &VVimCmdLineEdit::commandCancelled,
+            this, [this]() {
+                if (m_curTab) {
+                    m_curTab->focusTab();
+                }
+
+                // NOTICE: should not hide before setting focus to edit tab.
+                m_vimCmd->hide();
+
+                if (m_curTab) {
+                    m_curTab->handleVimCmdCommandCancelled();
+                }
+            });
+
+    connect(m_vimCmd, &VVimCmdLineEdit::commandFinished,
+            this, [this](VVim::CommandLineType p_type, const QString &p_cmd) {
+                if (m_curTab) {
+                    m_curTab->focusTab();
+                }
+
+                m_vimCmd->hide();
+
+                // Hide the cmd line edit before execute the command.
+                // If we execute the command first, we will get Chinese input
+                // method enabled after returning to read mode.
+                if (m_curTab) {
+                    m_curTab->handleVimCmdCommandFinished(p_type, p_cmd);
+                }
+            });
+
+    connect(m_vimCmd, &VVimCmdLineEdit::commandChanged,
+            this, [this](VVim::CommandLineType p_type, const QString &p_cmd) {
+                if (m_curTab) {
+                    m_curTab->handleVimCmdCommandChanged(p_type, p_cmd);
+                }
+            });
+
+    connect(m_vimCmd, &VVimCmdLineEdit::requestNextCommand,
+            this, [this](VVim::CommandLineType p_type, const QString &p_cmd) {
+                if (m_curTab) {
+                    QString cmd = m_curTab->handleVimCmdRequestNextCommand(p_type, p_cmd);
+                    if (!cmd.isNull()) {
+                        m_vimCmd->setCommand(cmd);
+                    } else {
+                        m_vimCmd->restoreUserLastInput();
+                    }
+                }
+            });
+
+    connect(m_vimCmd, &VVimCmdLineEdit::requestPreviousCommand,
+            this, [this](VVim::CommandLineType p_type, const QString &p_cmd) {
+                if (m_curTab) {
+                    QString cmd = m_curTab->handleVimCmdRequestPreviousCommand(p_type, p_cmd);
+                    if (!cmd.isNull()) {
+                        m_vimCmd->setCommand(cmd);
+                    }
+                }
+            });
+
+    connect(m_vimCmd, &VVimCmdLineEdit::requestRegister,
+            this, [this](int p_key, int p_modifiers){
+                if (m_curTab) {
+                    QString val = m_curTab->handleVimCmdRequestRegister(p_key, p_modifiers);
+                    if (!val.isEmpty()) {
+                        m_vimCmd->setText(m_vimCmd->text() + val);
+                    }
+                }
+            });
+
+    m_vimCmd->hide();
+}

+ 7 - 0
src/vmainwindow.h

@@ -30,6 +30,7 @@ class VNotebookSelector;
 class VFindReplaceDialog;
 class VCaptain;
 class VVimIndicator;
+class VVimCmdLineEdit;
 class VTabIndicator;
 class VSingleInstanceGuard;
 class QTimer;
@@ -213,6 +214,8 @@ private:
     void initEditorStyleMenu(QMenu *p_emnu);
     void updateWindowTitle(const QString &str);
 
+    void initVimCmd();
+
     // Update state of actions according to @p_tab.
     void updateActionsStateFromTab(const VEditTab *p_tab);
 
@@ -311,7 +314,11 @@ private:
     VCart *m_cart;
 
     VFindReplaceDialog *m_findReplaceDialog;
+
+    VVimCmdLineEdit *m_vimCmd;
+
     VVimIndicator *m_vimIndicator;
+
     VTabIndicator *m_tabIndicator;
 
     // SinglePanel, TwoPanels, CompactMode.

+ 83 - 0
src/vmdtab.cpp

@@ -472,6 +472,15 @@ void VMdTab::setupMarkdownEditor()
     connect(m_editor, &VMdEditor::requestTextToHtml,
             this, &VMdTab::textToHtmlViaWebView);
 
+    if (m_editor->getVim()) {
+        connect(m_editor->getVim(), &VVim::commandLineTriggered,
+                this, [this](VVim::CommandLineType p_type) {
+                    if (m_isEditMode) {
+                        emit triggerVimCmd(p_type);
+                    }
+                });
+    }
+
     enableHeadingSequence(m_enableHeadingSequence);
     m_editor->reloadFile();
     m_stacks->addWidget(m_editor);
@@ -1030,3 +1039,77 @@ void VMdTab::textToHtmlViaWebView(const QString &p_text)
 
     m_document->textToHtmlAsync(p_text);
 }
+
+void VMdTab::handleVimCmdCommandCancelled()
+{
+    if (m_isEditMode) {
+        VVim *vim = getEditor()->getVim();
+        if (vim) {
+            vim->processCommandLineCancelled();
+        }
+    }
+}
+
+void VMdTab::handleVimCmdCommandFinished(VVim::CommandLineType p_type, const QString &p_cmd)
+{
+    if (m_isEditMode) {
+        VVim *vim = getEditor()->getVim();
+        if (vim) {
+            vim->processCommandLine(p_type, p_cmd);
+        }
+    }
+}
+
+void VMdTab::handleVimCmdCommandChanged(VVim::CommandLineType p_type, const QString &p_cmd)
+{
+    Q_UNUSED(p_type);
+    Q_UNUSED(p_cmd);
+    if (m_isEditMode) {
+        VVim *vim = getEditor()->getVim();
+        if (vim) {
+            vim->processCommandLineChanged(p_type, p_cmd);
+        }
+    }
+}
+
+QString VMdTab::handleVimCmdRequestNextCommand(VVim::CommandLineType p_type, const QString &p_cmd)
+{
+    Q_UNUSED(p_type);
+    Q_UNUSED(p_cmd);
+    if (m_isEditMode) {
+        VVim *vim = getEditor()->getVim();
+        if (vim) {
+            return vim->getNextCommandHistory(p_type, p_cmd);
+        }
+    }
+
+    return QString();
+}
+
+QString VMdTab::handleVimCmdRequestPreviousCommand(VVim::CommandLineType p_type, const QString &p_cmd)
+{
+    Q_UNUSED(p_type);
+    Q_UNUSED(p_cmd);
+    if (m_isEditMode) {
+        VVim *vim = getEditor()->getVim();
+        if (vim) {
+            return vim->getPreviousCommandHistory(p_type, p_cmd);
+        }
+    }
+
+    return QString();
+}
+
+QString VMdTab::handleVimCmdRequestRegister(int p_key, int p_modifiers)
+{
+    Q_UNUSED(p_key);
+    Q_UNUSED(p_modifiers);
+    if (m_isEditMode) {
+        VVim *vim = getEditor()->getVim();
+        if (vim) {
+            return vim->readRegister(p_key, p_modifiers);
+        }
+    }
+
+    return QString();
+}

+ 12 - 0
src/vmdtab.h

@@ -91,6 +91,18 @@ public slots:
     // Enter edit mode.
     void editFile() Q_DECL_OVERRIDE;
 
+    void handleVimCmdCommandCancelled();
+
+    void handleVimCmdCommandFinished(VVim::CommandLineType p_type, const QString &p_cmd);
+
+    void handleVimCmdCommandChanged(VVim::CommandLineType p_type, const QString &p_cmd);
+
+    QString handleVimCmdRequestNextCommand(VVim::CommandLineType p_type, const QString &p_cmd);
+
+    QString handleVimCmdRequestPreviousCommand(VVim::CommandLineType p_type, const QString &p_cmd);
+
+    QString handleVimCmdRequestRegister(int p_key, int p_modifiers);
+
 protected:
     void writeBackupFile() Q_DECL_OVERRIDE;
 

+ 232 - 0
src/vvimcmdlineedit.cpp

@@ -0,0 +1,232 @@
+#include "vvimcmdlineedit.h"
+
+#include <QInputMethod>
+#include <QGuiApplication>
+
+#include "vpalette.h"
+
+extern VPalette *g_palette;
+
+VVimCmdLineEdit::VVimCmdLineEdit(QWidget *p_parent)
+    : VLineEdit(p_parent), m_type(VVim::CommandLineType::Invalid),
+      m_registerPending(false), m_enableInputMethod(true)
+{
+    // When user delete all the text, cancel command input.
+    connect(this, &VVimCmdLineEdit::textChanged,
+            this, [this](const QString &p_text){
+                if (p_text.isEmpty()) {
+                    emit commandCancelled();
+                } else {
+                    emit commandChanged(m_type, p_text.right(p_text.size() - 1));
+                }
+            });
+
+    connect(this, &VVimCmdLineEdit::textEdited,
+            this, [this](const QString &p_text){
+                if (p_text.size() < 2) {
+                    m_userLastInput.clear();
+                } else {
+                    m_userLastInput = p_text.right(p_text.size() - 1);
+                }
+            });
+
+    m_originStyleSheet = styleSheet();
+}
+
+QString VVimCmdLineEdit::getCommand() const
+{
+    QString tx = text();
+    if (tx.size() < 2) {
+        return "";
+    } else {
+        return tx.right(tx.size() - 1);
+    }
+}
+
+QString VVimCmdLineEdit::commandLineTypeLeader(VVim::CommandLineType p_type)
+{
+    QString leader;
+    switch (p_type) {
+    case VVim::CommandLineType::Command:
+        leader = ":";
+        break;
+
+    case VVim::CommandLineType::SearchForward:
+        leader = "/";
+        break;
+
+    case VVim::CommandLineType::SearchBackward:
+        leader = "?";
+        break;
+
+    case VVim::CommandLineType::Invalid:
+        leader.clear();
+        break;
+
+    default:
+        Q_ASSERT(false);
+        break;
+    }
+
+    return leader;
+}
+
+void VVimCmdLineEdit::reset(VVim::CommandLineType p_type)
+{
+    m_type = p_type;
+    m_userLastInput.clear();
+    setCommand("");
+    show();
+    setFocus();
+    setInputMethodEnabled(p_type != VVim::CommandLineType::Command);
+}
+
+void VVimCmdLineEdit::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);
+    }
+}
+
+QVariant VVimCmdLineEdit::inputMethodQuery(Qt::InputMethodQuery p_query) const
+{
+    if (p_query == Qt::ImEnabled) {
+        return m_enableInputMethod;
+    }
+
+    return VLineEdit::inputMethodQuery(p_query);
+}
+
+// See if @p_modifiers is Control which is different on macOs and Windows.
+static bool isControlModifier(int p_modifiers)
+{
+#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
+    return p_modifiers == Qt::MetaModifier;
+#else
+    return p_modifiers == Qt::ControlModifier;
+#endif
+}
+
+void VVimCmdLineEdit::keyPressEvent(QKeyEvent *p_event)
+{
+    int key = p_event->key();
+    int modifiers = p_event->modifiers();
+
+    if (m_registerPending) {
+        // Ctrl and Shift may be sent out first.
+        if (key == Qt::Key_Control || key == Qt::Key_Shift || key == Qt::Key_Meta) {
+            goto exit;
+        }
+
+        // Expecting a register name.
+        emit requestRegister(key, modifiers);
+
+        p_event->accept();
+        setRegisterPending(false);
+        return;
+    }
+
+    if ((key == Qt::Key_Return && modifiers == Qt::NoModifier)
+        || (key == Qt::Key_Enter && modifiers == Qt::KeypadModifier)) {
+        // Enter, complete the command line input.
+        p_event->accept();
+        emit commandFinished(m_type, getCommand());
+        return;
+    } else if (key == Qt::Key_Escape
+               || (key == Qt::Key_BracketLeft && isControlModifier(modifiers))) {
+        // Exit command line input.
+        setText(commandLineTypeLeader(m_type));
+        p_event->accept();
+        emit commandCancelled();
+        return;
+    }
+
+    switch (key) {
+    case Qt::Key_U:
+        if (isControlModifier(modifiers)) {
+            // Ctrl+U, delete all user input.
+            setText(commandLineTypeLeader(m_type));
+            p_event->accept();
+            return;
+        }
+
+        break;
+
+    case Qt::Key_N:
+        if (!isControlModifier(modifiers)) {
+            break;
+        }
+        // Ctrl+N, request next command.
+        // Fall through.
+    case Qt::Key_Down:
+    {
+        emit requestNextCommand(m_type, getCommand());
+        p_event->accept();
+        return;
+    }
+
+    case Qt::Key_P:
+        if (!isControlModifier(modifiers)) {
+            break;
+        }
+        // Ctrl+P, request previous command.
+        // Fall through.
+    case Qt::Key_Up:
+    {
+        emit requestPreviousCommand(m_type, getCommand());
+        p_event->accept();
+        return;
+    }
+
+    case Qt::Key_R:
+    {
+        if (isControlModifier(modifiers)) {
+            // Ctrl+R, insert the content of a register.
+            setRegisterPending(true);
+            p_event->accept();
+            return;
+        }
+    }
+
+    default:
+        break;
+    }
+
+exit:
+    VLineEdit::keyPressEvent(p_event);
+}
+
+void VVimCmdLineEdit::focusOutEvent(QFocusEvent *p_event)
+{
+    if (p_event->reason() != Qt::ActiveWindowFocusReason) {
+        emit commandCancelled();
+    }
+}
+
+void VVimCmdLineEdit::setCommand(const QString &p_cmd)
+{
+    setText(commandLineTypeLeader(m_type) + p_cmd);
+}
+
+void VVimCmdLineEdit::restoreUserLastInput()
+{
+    setCommand(m_userLastInput);
+}
+
+void VVimCmdLineEdit::setRegisterPending(bool p_pending)
+{
+    if (p_pending && !m_registerPending) {
+        // Going to pending.
+        setStyleSheet(QString("background: %1;").arg(g_palette->color("vim_indicator_cmd_edit_pending_bg")));
+    } else if (!p_pending && m_registerPending) {
+        // Leaving pending.
+        setStyleSheet(m_originStyleSheet);
+    }
+
+    m_registerPending = p_pending;
+}

+ 74 - 0
src/vvimcmdlineedit.h

@@ -0,0 +1,74 @@
+#ifndef VVIMCMDLINEEDIT_H
+#define VVIMCMDLINEEDIT_H
+
+#include "vlineedit.h"
+#include "utils/vvim.h"
+
+class QKeyEvent;
+class QFocusEvent;
+
+class VVimCmdLineEdit : public VLineEdit
+{
+    Q_OBJECT
+
+public:
+    explicit VVimCmdLineEdit(QWidget *p_parent = 0);
+
+    void reset(VVim::CommandLineType p_type);
+
+    // Set the command to @p_cmd with leader unchanged.
+    void setCommand(const QString &p_cmd);
+
+    // Get the command.
+    QString getCommand() const;
+
+    void restoreUserLastInput();
+
+    QVariant inputMethodQuery(Qt::InputMethodQuery p_query) const Q_DECL_OVERRIDE;
+
+signals:
+    // User has finished the input and the command is ready to execute.
+    void commandFinished(VVim::CommandLineType p_type, const QString &p_cmd);
+
+    // User cancelled the input.
+    void commandCancelled();
+
+    // User request the next command in the history.
+    void requestNextCommand(VVim::CommandLineType p_type, const QString &p_cmd);
+
+    // User request the previous command in the history.
+    void requestPreviousCommand(VVim::CommandLineType p_type, const QString &p_cmd);
+
+    // Emit when the input text changed.
+    void commandChanged(VVim::CommandLineType p_type, const QString &p_cmd);
+
+    // Emit when expecting to read a register.
+    void requestRegister(int p_key, int p_modifiers);
+
+protected:
+    void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
+
+    void focusOutEvent(QFocusEvent *p_event) Q_DECL_OVERRIDE;
+
+private:
+    // Return the leader of @p_type.
+    QString commandLineTypeLeader(VVim::CommandLineType p_type);
+
+    void setRegisterPending(bool p_pending);
+
+    void setInputMethodEnabled(bool p_enabled);
+
+    VVim::CommandLineType m_type;
+
+    // The latest command user input.
+    QString m_userLastInput;
+
+    // Whether we are expecting a register name to read.
+    bool m_registerPending;
+
+    QString m_originStyleSheet;
+
+    // Whether enable input method.
+    bool m_enableInputMethod;
+};
+#endif // VVIMCMDLINEEDIT_H

+ 2 - 325
src/vvimindicator.cpp

@@ -12,7 +12,6 @@
 
 #include "vconfigmanager.h"
 #include "vbuttonwithwidget.h"
-#include "vedittab.h"
 #include "vpalette.h"
 
 extern VConfigManager *g_config;
@@ -27,80 +26,6 @@ VVimIndicator::VVimIndicator(QWidget *p_parent)
 
 void VVimIndicator::setupUI()
 {
-    m_cmdLineEdit = new VVimCmdLineEdit(this);
-    m_cmdLineEdit->setProperty("VimCommandLine", true);
-    connect(m_cmdLineEdit, &VVimCmdLineEdit::commandCancelled,
-            this, [this](){
-                if (m_editTab) {
-                    m_editTab->focusTab();
-                }
-
-                // NOTICE: m_cmdLineEdit should not hide itself before setting
-                // focus to edit tab.
-                m_cmdLineEdit->hide();
-
-                if (m_vim) {
-                    m_vim->processCommandLineCancelled();
-                }
-            });
-
-    connect(m_cmdLineEdit, &VVimCmdLineEdit::commandFinished,
-            this, [this](VVim::CommandLineType p_type, const QString &p_cmd){
-                if (m_editTab) {
-                    m_editTab->focusTab();
-                }
-
-                m_cmdLineEdit->hide();
-
-                // Hide the cmd line edit before execute the command.
-                // If we execute the command first, we will get Chinese input
-                // method enabled after returning to read mode.
-                if (m_vim) {
-                    m_vim->processCommandLine(p_type, p_cmd);
-                }
-            });
-
-    connect(m_cmdLineEdit, &VVimCmdLineEdit::commandChanged,
-            this, [this](VVim::CommandLineType p_type, const QString &p_cmd){
-                if (m_vim) {
-                    m_vim->processCommandLineChanged(p_type, p_cmd);
-                }
-            });
-
-    connect(m_cmdLineEdit, &VVimCmdLineEdit::requestNextCommand,
-            this, [this](VVim::CommandLineType p_type, const QString &p_cmd){
-                if (m_vim) {
-                    QString cmd = m_vim->getNextCommandHistory(p_type, p_cmd);
-                    if (!cmd.isNull()) {
-                        m_cmdLineEdit->setCommand(cmd);
-                    } else {
-                        m_cmdLineEdit->restoreUserLastInput();
-                    }
-                }
-            });
-
-    connect(m_cmdLineEdit, &VVimCmdLineEdit::requestPreviousCommand,
-            this, [this](VVim::CommandLineType p_type, const QString &p_cmd){
-                if (m_vim) {
-                    QString cmd = m_vim->getPreviousCommandHistory(p_type, p_cmd);
-                    if (!cmd.isNull()) {
-                        m_cmdLineEdit->setCommand(cmd);
-                    }
-                }
-            });
-
-    connect(m_cmdLineEdit, &VVimCmdLineEdit::requestRegister,
-            this, [this](int p_key, int p_modifiers){
-                if (m_vim) {
-                    QString val = m_vim->readRegister(p_key, p_modifiers);
-                    if (!val.isEmpty()) {
-                        m_cmdLineEdit->setText(m_cmdLineEdit->text() + val);
-                    }
-                }
-            });
-
-    m_cmdLineEdit->hide();
-
     m_modeLabel = new QLabel(this);
     m_modeLabel->setProperty("VimIndicatorModeLabel", true);
 
@@ -146,8 +71,6 @@ void VVimIndicator::setupUI()
     m_keyLabel->setMinimumWidth(metric.width('A') * 5);
 
     QHBoxLayout *mainLayout = new QHBoxLayout(this);
-    mainLayout->addStretch();
-    mainLayout->addWidget(m_cmdLineEdit);
     mainLayout->addWidget(m_modeLabel);
     mainLayout->addWidget(m_regBtn);
     mainLayout->addWidget(m_markBtn);
@@ -242,27 +165,10 @@ static void fillTreeItemsWithRegisters(QTreeWidget *p_tree,
     p_tree->resizeColumnToContents(1);
 }
 
-void VVimIndicator::update(const VVim *p_vim, const VEditTab *p_editTab)
+void VVimIndicator::update(const VVim *p_vim)
 {
-    m_editTab = const_cast<VEditTab *>(p_editTab);
-    if (m_vim != p_vim) {
-        // Disconnect from previous Vim.
-        if (m_vim) {
-            disconnect(m_vim.data(), 0, this, 0);
-        }
-
-        m_vim = const_cast<VVim *>(p_vim);
-        if (m_vim) {
-            // Connect signal.
-            connect(m_vim.data(), &VVim::commandLineTriggered,
-                    this, &VVimIndicator::triggerCommandLine);
-
-            m_cmdLineEdit->hide();
-        }
-    }
-
+    m_vim = const_cast<VVim *>(p_vim);
     if (!m_vim) {
-        m_cmdLineEdit->hide();
         return;
     }
 
@@ -334,232 +240,3 @@ void VVimIndicator::updateMarksTree(QWidget *p_widget)
     const QMap<QChar, VVim::Mark> &marks = m_vim->getMarks().getMarks();
     fillTreeItemsWithMarks(markTree, marks);
 }
-
-void VVimIndicator::triggerCommandLine(VVim::CommandLineType p_type)
-{
-    m_cmdLineEdit->reset(p_type);
-}
-
-VVimCmdLineEdit::VVimCmdLineEdit(QWidget *p_parent)
-    : VLineEdit(p_parent), m_type(VVim::CommandLineType::Invalid),
-      m_registerPending(false), m_enableInputMethod(true)
-{
-    // When user delete all the text, cancel command input.
-    connect(this, &VVimCmdLineEdit::textChanged,
-            this, [this](const QString &p_text){
-                if (p_text.isEmpty()) {
-                    emit commandCancelled();
-                } else {
-                    emit commandChanged(m_type, p_text.right(p_text.size() - 1));
-                }
-            });
-
-    connect(this, &VVimCmdLineEdit::textEdited,
-            this, [this](const QString &p_text){
-                if (p_text.size() < 2) {
-                    m_userLastInput.clear();
-                } else {
-                    m_userLastInput = p_text.right(p_text.size() - 1);
-                }
-            });
-
-    m_originStyleSheet = styleSheet();
-}
-
-QString VVimCmdLineEdit::getCommand() const
-{
-    QString tx = text();
-    if (tx.size() < 2) {
-        return "";
-    } else {
-        return tx.right(tx.size() - 1);
-    }
-}
-
-QString VVimCmdLineEdit::commandLineTypeLeader(VVim::CommandLineType p_type)
-{
-    QString leader;
-    switch (p_type) {
-    case VVim::CommandLineType::Command:
-        leader = ":";
-        break;
-
-    case VVim::CommandLineType::SearchForward:
-        leader = "/";
-        break;
-
-    case VVim::CommandLineType::SearchBackward:
-        leader = "?";
-        break;
-
-    case VVim::CommandLineType::Invalid:
-        leader.clear();
-        break;
-
-    default:
-        Q_ASSERT(false);
-        break;
-    }
-
-    return leader;
-}
-
-void VVimCmdLineEdit::reset(VVim::CommandLineType p_type)
-{
-    m_type = p_type;
-    m_userLastInput.clear();
-    setCommand("");
-    show();
-    setFocus();
-    setInputMethodEnabled(p_type != VVim::CommandLineType::Command);
-}
-
-void VVimCmdLineEdit::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);
-    }
-}
-
-QVariant VVimCmdLineEdit::inputMethodQuery(Qt::InputMethodQuery p_query) const
-{
-    if (p_query == Qt::ImEnabled) {
-        return m_enableInputMethod;
-    }
-
-    return VLineEdit::inputMethodQuery(p_query);
-}
-
-// See if @p_modifiers is Control which is different on macOs and Windows.
-static bool isControlModifier(int p_modifiers)
-{
-#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
-    return p_modifiers == Qt::MetaModifier;
-#else
-    return p_modifiers == Qt::ControlModifier;
-#endif
-}
-
-void VVimCmdLineEdit::keyPressEvent(QKeyEvent *p_event)
-{
-    int key = p_event->key();
-    int modifiers = p_event->modifiers();
-
-    if (m_registerPending) {
-        // Ctrl and Shift may be sent out first.
-        if (key == Qt::Key_Control || key == Qt::Key_Shift || key == Qt::Key_Meta) {
-            goto exit;
-        }
-
-        // Expecting a register name.
-        emit requestRegister(key, modifiers);
-
-        p_event->accept();
-        setRegisterPending(false);
-        return;
-    }
-
-    if ((key == Qt::Key_Return && modifiers == Qt::NoModifier)
-        || (key == Qt::Key_Enter && modifiers == Qt::KeypadModifier)) {
-        // Enter, complete the command line input.
-        p_event->accept();
-        emit commandFinished(m_type, getCommand());
-        return;
-    } else if (key == Qt::Key_Escape
-               || (key == Qt::Key_BracketLeft && isControlModifier(modifiers))) {
-        // Exit command line input.
-        setText(commandLineTypeLeader(m_type));
-        p_event->accept();
-        emit commandCancelled();
-        return;
-    }
-
-    switch (key) {
-    case Qt::Key_U:
-        if (isControlModifier(modifiers)) {
-            // Ctrl+U, delete all user input.
-            setText(commandLineTypeLeader(m_type));
-            p_event->accept();
-            return;
-        }
-
-        break;
-
-    case Qt::Key_N:
-        if (!isControlModifier(modifiers)) {
-            break;
-        }
-        // Ctrl+N, request next command.
-        // Fall through.
-    case Qt::Key_Down:
-    {
-        emit requestNextCommand(m_type, getCommand());
-        p_event->accept();
-        return;
-    }
-
-    case Qt::Key_P:
-        if (!isControlModifier(modifiers)) {
-            break;
-        }
-        // Ctrl+P, request previous command.
-        // Fall through.
-    case Qt::Key_Up:
-    {
-        emit requestPreviousCommand(m_type, getCommand());
-        p_event->accept();
-        return;
-    }
-
-    case Qt::Key_R:
-    {
-        if (isControlModifier(modifiers)) {
-            // Ctrl+R, insert the content of a register.
-            setRegisterPending(true);
-            p_event->accept();
-            return;
-        }
-    }
-
-    default:
-        break;
-    }
-
-exit:
-    VLineEdit::keyPressEvent(p_event);
-}
-
-void VVimCmdLineEdit::focusOutEvent(QFocusEvent *p_event)
-{
-    if (p_event->reason() != Qt::ActiveWindowFocusReason) {
-        emit commandCancelled();
-    }
-}
-
-void VVimCmdLineEdit::setCommand(const QString &p_cmd)
-{
-    setText(commandLineTypeLeader(m_type) + p_cmd);
-}
-
-void VVimCmdLineEdit::restoreUserLastInput()
-{
-    setCommand(m_userLastInput);
-}
-
-void VVimCmdLineEdit::setRegisterPending(bool p_pending)
-{
-    if (p_pending && !m_registerPending) {
-        // Going to pending.
-        setStyleSheet(QString("background: %1;").arg(g_palette->color("vim_indicator_cmd_edit_pending_bg")));
-    } else if (!p_pending && m_registerPending) {
-        // Leaving pending.
-        setStyleSheet(m_originStyleSheet);
-    }
-
-    m_registerPending = p_pending;
-}

+ 1 - 75
src/vvimindicator.h

@@ -4,78 +4,11 @@
 #include <QWidget>
 #include <QPointer>
 #include "utils/vvim.h"
-#include "vlineedit.h"
 
 class QLabel;
 class VButtonWithWidget;
 class QKeyEvent;
 class QFocusEvent;
-class VEditTab;
-
-class VVimCmdLineEdit : public VLineEdit
-{
-    Q_OBJECT
-
-public:
-    explicit VVimCmdLineEdit(QWidget *p_parent = 0);
-
-    void reset(VVim::CommandLineType p_type);
-
-    // Set the command to @p_cmd with leader unchanged.
-    void setCommand(const QString &p_cmd);
-
-    // Get the command.
-    QString getCommand() const;
-
-    void restoreUserLastInput();
-
-    QVariant inputMethodQuery(Qt::InputMethodQuery p_query) const Q_DECL_OVERRIDE;
-
-signals:
-    // User has finished the input and the command is ready to execute.
-    void commandFinished(VVim::CommandLineType p_type, const QString &p_cmd);
-
-    // User cancelled the input.
-    void commandCancelled();
-
-    // User request the next command in the history.
-    void requestNextCommand(VVim::CommandLineType p_type, const QString &p_cmd);
-
-    // User request the previous command in the history.
-    void requestPreviousCommand(VVim::CommandLineType p_type, const QString &p_cmd);
-
-    // Emit when the input text changed.
-    void commandChanged(VVim::CommandLineType p_type, const QString &p_cmd);
-
-    // Emit when expecting to read a register.
-    void requestRegister(int p_key, int p_modifiers);
-
-protected:
-    void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
-
-    void focusOutEvent(QFocusEvent *p_event) Q_DECL_OVERRIDE;
-
-private:
-    // Return the leader of @p_type.
-    QString commandLineTypeLeader(VVim::CommandLineType p_type);
-
-    void setRegisterPending(bool p_pending);
-
-    void setInputMethodEnabled(bool p_enabled);
-
-    VVim::CommandLineType m_type;
-
-    // The latest command user input.
-    QString m_userLastInput;
-
-    // Whether we are expecting a register name to read.
-    bool m_registerPending;
-
-    QString m_originStyleSheet;
-
-    // Whether enable input method.
-    bool m_enableInputMethod;
-};
 
 class VVimIndicator : public QWidget
 {
@@ -85,24 +18,18 @@ public:
     explicit VVimIndicator(QWidget *p_parent = 0);
 
     // Update indicator according to @p_vim.
-    void update(const VVim *p_vim, const VEditTab *p_editTab);
+    void update(const VVim *p_vim);
 
 private slots:
     void updateRegistersTree(QWidget *p_widget);
 
     void updateMarksTree(QWidget *p_widget);
 
-    // Vim request to trigger command line.
-    void triggerCommandLine(VVim::CommandLineType p_type);
-
 private:
     void setupUI();
 
     QString modeToString(VimMode p_mode) const;
 
-    // Command line input.
-    VVimCmdLineEdit *m_cmdLineEdit;
-
     // Indicate the mode.
     QLabel *m_modeLabel;
 
@@ -116,7 +43,6 @@ private:
     QLabel *m_keyLabel;
 
     QPointer<VVim> m_vim;
-    QPointer<VEditTab> m_editTab;
 };
 
 #endif // VVIMINDICATOR_H