mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
decouple VVimIndicator and VVimCmdLineEdit
This commit is contained in:
parent
eb25aec5b5
commit
b927a525e2
@ -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 \
|
||||
|
@ -100,3 +100,8 @@ void VEditOperations::setVimMode(VimMode p_mode)
|
||||
m_vim->setMode(p_mode);
|
||||
}
|
||||
}
|
||||
|
||||
VVim *VEditOperations::getVim() const
|
||||
{
|
||||
return m_vim;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
src/vmdtab.h
12
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
src/vvimcmdlineedit.cpp
Normal file
232
src/vvimcmdlineedit.cpp
Normal file
@ -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
src/vvimcmdlineedit.h
Normal file
74
src/vvimcmdlineedit.h
Normal file
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user