From 1264d0ea5ea817e89d0ffead3cbeae024008462a Mon Sep 17 00:00:00 2001 From: Lukas Holecek <hluk@email.cz> Date: Mon, 10 Sep 2012 22:10:23 +0200 Subject: [PATCH] fakevim: Appearance of command line widget. Widget for Ex and search mode is QLineEdit. Messages are displayed using QLabel widget with different style for error, warnings etc. Change-Id: I4d4f799bbe261febaf6c2c21c01f6b66e1beec6e Reviewed-by: hjk <qthjk@ovi.com> --- src/plugins/fakevim/fakevimhandler.cpp | 226 ++++++++++++++----------- src/plugins/fakevim/fakevimhandler.h | 17 +- src/plugins/fakevim/fakevimplugin.cpp | 139 ++++++++++----- 3 files changed, 240 insertions(+), 142 deletions(-) diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index db333bddc6..95f23d4732 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -880,6 +880,8 @@ public: void setPrompt(const QChar &prompt) { m_prompt = prompt; } void setContents(const QString &s) { m_buffer = s; m_pos = s.size(); } + void setContents(const QString &s, int pos) { m_buffer = s; m_pos = m_userPos = pos; } + QStringRef userContents() const { return m_buffer.leftRef(m_userPos); } const QChar &prompt() const { return m_prompt; } const QString &contents() const { return m_buffer; } @@ -1143,11 +1145,12 @@ public: void finishMovement(const QString &dotCommand = QString()); void finishMovement(const QString &dotCommand, int count); void resetCommandMode(); - void search(const SearchData &sd); + void search(const SearchData &sd, bool showMessages = true); void searchNext(bool forward = true); void searchBalanced(bool forward, QChar needle, QChar other); void highlightMatches(const QString &needle); void stopIncrementalFind(); + void updateFind(bool isComplete); int mvCount() const { return m_mvcount.isEmpty() ? 1 : m_mvcount.toInt(); } int opCount() const { return m_opcount.isEmpty() ? 1 : m_opcount.toInt(); } @@ -1286,8 +1289,8 @@ public: void enterReplaceMode(); void enterCommandMode(); void enterExMode(); - void showRedMessage(const QString &msg); - void showBlackMessage(const QString &msg); + void showMessage(MessageLevel level, const QString &msg); + void clearMessage() { showMessage(MessageInfo, QString()); } void notImplementedYet(); void updateMiniBuffer(); void updateSelection(); @@ -1514,9 +1517,12 @@ public: signed char m_charClass[256]; bool m_ctrlVActive; + void miniBufferTextEdited(const QString &text, int cursorPos); + static struct GlobalData { - GlobalData() : mappings(), currentMap(&mappings), inputTimer(-1) + GlobalData() + : mappings(), currentMap(&mappings), inputTimer(-1), currentMessageLevel(MessageInfo) { // default mapping state - shouldn't be removed mapStates << MappingState(); @@ -1544,6 +1550,7 @@ public: // Current mini buffer message. QString currentMessage; + MessageLevel currentMessageLevel; } g; }; @@ -1847,7 +1854,7 @@ void FakeVimHandler::Private::updateEditor() void FakeVimHandler::Private::restoreWidget(int tabSize) { - //showBlackMessage(QString()); + //clearMessage(); //updateMiniBuffer(); //EDITOR(removeEventFilter(q)); //EDITOR(setReadOnly(m_wasReadOnly)); @@ -1968,7 +1975,7 @@ void FakeVimHandler::Private::handleMappedKeys() } if (maxMapDepth <= 0) { - showRedMessage("recursive mapping"); + showMessage(MessageError, "recursive mapping"); g.pendingInput.remove(0, g.currentMap.mapLength() + invalidCount); } else { const Inputs &inputs = g.currentMap.inputs(); @@ -2002,6 +2009,22 @@ void FakeVimHandler::Private::stopIncrementalFind() } } +void FakeVimHandler::Private::updateFind(bool isComplete) +{ + if (!isComplete && !hasConfig(ConfigIncSearch)) + return; + + g.currentMessage.clear(); + + const QString &needle = g.searchBuffer.contents(); + SearchData sd; + sd.needle = needle; + sd.forward = m_lastSearchForward; + sd.highlightCursor = !isComplete; + sd.highlightMatches = isComplete; + search(sd, isComplete); +} + bool FakeVimHandler::Private::atEmptyLine(const QTextCursor &tc) const { if (tc.isNull()) @@ -2245,7 +2268,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand) setPosition(anchor()); } if (la != lp) - showBlackMessage(QString("%1 lines yanked").arg(qAbs(la - lp) + 1)); + showMessage(MessageInfo, QString("%1 lines yanked").arg(qAbs(la - lp) + 1)); } else if (m_submode == TransformSubMode) { if (m_subsubmode == InvertCaseSubSubMode) { invertCase(currentRange()); @@ -2334,12 +2357,13 @@ void FakeVimHandler::Private::updateMiniBuffer() QString msg; int cursorPos = -1; + MessageLevel messageLevel = MessageMode; - if (g.mapStates.last().silent) + if (g.mapStates.last().silent && g.currentMessageLevel < MessageInfo) g.currentMessage.clear(); if (m_passing) { - msg = "-- PASSING -- "; + msg = "PASSING"; } else if (m_subsubmode == SearchSubSubMode) { msg = g.searchBuffer.display(); if (g.mapStates.size() == 1) @@ -2351,27 +2375,28 @@ void FakeVimHandler::Private::updateMiniBuffer() } else if (!g.currentMessage.isEmpty()) { msg = g.currentMessage; g.currentMessage.clear(); + messageLevel = g.currentMessageLevel; } else if (g.mapStates.size() > 1 && !g.mapStates.last().silent) { // Do not reset previous message when after running a mapped command. return; } else if (m_mode == CommandMode && isVisualMode()) { if (isVisualCharMode()) { - msg = "-- VISUAL --"; + msg = "VISUAL"; } else if (isVisualLineMode()) { - msg = "-- VISUAL LINE --"; + msg = "VISUAL LINE"; } else if (isVisualBlockMode()) { - msg = "-- VISUAL BLOCK --"; + msg = "VISUAL BLOCK"; } } else if (m_mode == InsertMode) { - msg = "-- INSERT --"; + msg = "INSERT"; } else if (m_mode == ReplaceMode) { - msg = "-- REPLACE --"; + msg = "REPLACE"; } else { QTC_CHECK(m_mode == CommandMode && m_subsubmode != SearchSubSubMode); - msg = "-- COMMAND --"; + msg = "COMMAND"; } - emit q->commandBufferChanged(msg, cursorPos); + emit q->commandBufferChanged(msg, cursorPos, messageLevel, q); int linesInDoc = linesInDocument(); int l = cursorLine(); @@ -2387,24 +2412,18 @@ void FakeVimHandler::Private::updateMiniBuffer() emit q->statusDataChanged(status); } -void FakeVimHandler::Private::showRedMessage(const QString &msg) -{ - //qDebug() << "MSG: " << msg; - g.currentMessage = msg; - updateMiniBuffer(); -} - -void FakeVimHandler::Private::showBlackMessage(const QString &msg) +void FakeVimHandler::Private::showMessage(MessageLevel level, const QString &msg) { //qDebug() << "MSG: " << msg; g.currentMessage = msg; + g.currentMessageLevel = level; updateMiniBuffer(); } void FakeVimHandler::Private::notImplementedYet() { qDebug() << "Not implemented in FakeVim"; - showRedMessage(FakeVimHandler::tr("Not implemented in FakeVim")); + showMessage(MessageError, FakeVimHandler::tr("Not implemented in FakeVim")); updateMiniBuffer(); } @@ -2486,7 +2505,7 @@ EventResult FakeVimHandler::Private::handleCommandSubSubMode(const Input &input) moveToFirstNonBlankOnLine(); finishMovement(); } else { - showRedMessage(msgMarkNotSet(input.text())); + showMessage(MessageError, msgMarkNotSet(input.text())); } m_subsubmode = NoSubSubMode; } else { @@ -2896,7 +2915,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input) finishMovement(); } else if (input.isControl('c')) { if (isNoVisualMode()) - showBlackMessage("Type Alt-v,Alt-v to quit FakeVim mode"); + showMessage(MessageInfo, "Type Alt-v,Alt-v to quit FakeVim mode"); else leaveVisualMode(); } else if (input.is('d') && isNoVisualMode()) { @@ -3460,6 +3479,7 @@ EventResult FakeVimHandler::Private::handleReplaceMode(const Input &input) m_submode = NoSubMode; m_mode = CommandMode; finishMovement(); + updateMiniBuffer(); } else if (input.isKey(Key_Left)) { breakEditBlock(); moveLeft(1); @@ -3735,15 +3755,11 @@ EventResult FakeVimHandler::Private::handleExMode(const Input &input) } else if (input.isKey(Key_Left)) { g.commandBuffer.moveLeft(); } else if (input.isReturn()) { - if (!g.commandBuffer.isEmpty()) { - //g.commandHistory.takeLast(); - handleExCommand(g.commandBuffer.contents()); - if (g.currentMessage.isEmpty()) - g.currentMessage = g.commandBuffer.display(); - g.commandBuffer.clear(); - if (m_textedit || m_plaintextedit) - leaveVisualMode(); - } + showMessage(MessageCommand, g.commandBuffer.display()); + handleExCommand(g.commandBuffer.contents()); + g.commandBuffer.clear(); + if (m_textedit || m_plaintextedit) + leaveVisualMode(); } else if (input.isKey(Key_Up) || input.isKey(Key_PageUp)) { g.commandBuffer.historyUp(); } else if (input.isKey(Key_Down) || input.isKey(Key_PageDown)) { @@ -3781,20 +3797,13 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input) m_searchCursor = QTextCursor(); const QString &needle = g.searchBuffer.contents(); if (!needle.isEmpty()) { - if (!hasConfig(ConfigIncSearch)) { - SearchData sd; - sd.needle = needle; - sd.forward = m_lastSearchForward; - sd.highlightCursor = false; - sd.highlightMatches = true; - search(sd); - } + updateFind(true); finishMovement(g.searchBuffer.prompt() + needle + '\n'); } else { finishMovement(); } if (g.currentMessage.isEmpty()) - g.currentMessage = g.searchBuffer.display(); + showMessage(MessageCommand, g.searchBuffer.display()); enterCommandMode(); highlightMatches(needle); g.searchBuffer.clear(); @@ -3805,23 +3814,15 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input) } else if (input.isKey(Key_Tab)) { g.searchBuffer.insertChar(QChar(9)); } else if (!g.searchBuffer.handleInput(input)) { + //qDebug() << "IGNORED IN SEARCH MODE: " << input.key() << input.text(); return EventUnhandled; } + updateMiniBuffer(); - if (hasConfig(ConfigIncSearch) && !input.isReturn() && !input.isEscape()) { - SearchData sd; - sd.needle = g.searchBuffer.contents(); - sd.forward = m_lastSearchForward; - sd.highlightCursor = true; - sd.highlightMatches = false; - search(sd); - } + if (!input.isReturn() && !input.isEscape()) + updateFind(false); - //else { - // qDebug() << "IGNORED IN SEARCH MODE: " << input.key() << input.text(); - // return EventUnhandled; - //} return EventHandled; } @@ -3848,12 +3849,12 @@ int FakeVimHandler::Private::readLineCode(QString &cmd) return linesInDocument(); if (c == '\'' && !cmd.isEmpty()) { if (cmd.isEmpty()) { - showRedMessage(msgMarkNotSet(QString())); + showMessage(MessageError, msgMarkNotSet(QString())); return -1; } int m = mark(cmd.at(0).unicode()); if (m == -1) { - showRedMessage(msgMarkNotSet(cmd.at(0))); + showMessage(MessageError, msgMarkNotSet(cmd.at(0))); cmd = cmd.mid(1); return -1; } @@ -3871,7 +3872,7 @@ int FakeVimHandler::Private::readLineCode(QString &cmd) if (c == '\'' && !cmd.isEmpty()) { int pos = mark(cmd.at(0).unicode()); if (pos == -1) { - showRedMessage(msgMarkNotSet(cmd.at(0))); + showMessage(MessageError, msgMarkNotSet(cmd.at(0))); cmd = cmd.mid(1); return -1; } @@ -4189,7 +4190,7 @@ bool FakeVimHandler::Private::handleExSetCommand(const ExCommand &cmd) if (!cmd.matches("se", "set")) return false; - showBlackMessage(QString()); + clearMessage(); SavedAction *act = theFakeVimSettings()->item(cmd.args); QTC_CHECK(!cmd.args.isEmpty()); // Handled by plugin. if (act && act->value().canConvert(QVariant::Bool)) { @@ -4201,7 +4202,7 @@ bool FakeVimHandler::Private::handleExSetCommand(const ExCommand &cmd) {} // nothing to do } else if (act) { // Non-boolean to show. - showBlackMessage(cmd.args + '=' + act->value().toString()); + showMessage(MessageInfo, cmd.args + '=' + act->value().toString()); } else if (cmd.args.startsWith(_("no")) && (act = theFakeVimSettings()->item(cmd.args.mid(2)))) { // Boolean config to be switched off. @@ -4216,9 +4217,9 @@ bool FakeVimHandler::Private::handleExSetCommand(const ExCommand &cmd) QString error = theFakeVimSettings() ->trySetValue(cmd.args.left(p), cmd.args.mid(p + 1)); if (!error.isEmpty()) - showRedMessage(error); + showMessage(MessageError, error); } else { - showRedMessage(FakeVimHandler::tr("Unknown option: ") + cmd.args); + showMessage(MessageError, FakeVimHandler::tr("Unknown option: ") + cmd.args); } updateMiniBuffer(); updateEditor(); @@ -4278,7 +4279,7 @@ bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd) QFile file1(fileName); const bool exists = file1.exists(); if (exists && !forced && !noArgs) { - showRedMessage(FakeVimHandler::tr + showMessage(MessageError, FakeVimHandler::tr ("File \"%1\" exists (add ! to override)").arg(fileName)); } else if (file1.open(QIODevice::ReadWrite)) { // Nobody cared, so act ourselves. @@ -4292,14 +4293,14 @@ bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd) QTextStream ts(&file2); ts << contents; } else { - showRedMessage(FakeVimHandler::tr + showMessage(MessageError, FakeVimHandler::tr ("Cannot open file \"%1\" for writing").arg(fileName)); } // Check result by reading back. QFile file3(fileName); file3.open(QIODevice::ReadOnly); QByteArray ba = file3.readAll(); - showBlackMessage(FakeVimHandler::tr("\"%1\" %2 %3L, %4C written") + showMessage(MessageInfo, FakeVimHandler::tr("\"%1\" %2 %3L, %4C written") .arg(fileName).arg(exists ? " " : tr(" [New] ")) .arg(ba.count('\n')).arg(ba.size())); //if (quitAll) @@ -4307,7 +4308,7 @@ bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd) //else if (quit) // passUnknownExCommand(forced ? "q!" : "q"); } else { - showRedMessage(FakeVimHandler::tr + showMessage(MessageError, FakeVimHandler::tr ("Cannot open file \"%1\" for reading").arg(fileName)); } return true; @@ -4330,7 +4331,7 @@ bool FakeVimHandler::Private::handleExReadCommand(const ExCommand &cmd) QString data = ts.readAll(); insertText(data); endEditBlock(); - showBlackMessage(FakeVimHandler::tr("\"%1\" %2L, %3C") + showMessage(MessageInfo, FakeVimHandler::tr("\"%1\" %2L, %3C") .arg(m_currentFileName).arg(data.count('\n')).arg(data.size())); return true; } @@ -4363,7 +4364,7 @@ bool FakeVimHandler::Private::handleExBangCommand(const ExCommand &cmd) // :! endEditBlock(); leaveVisualMode(); //qDebug() << "FILTER: " << command; - showBlackMessage(FakeVimHandler::tr("%n lines filtered", 0, + showMessage(MessageInfo, FakeVimHandler::tr("%n lines filtered", 0, text.count('\n'))); } return true; @@ -4386,7 +4387,7 @@ bool FakeVimHandler::Private::handleExShiftCommand(const ExCommand &cmd) leaveVisualMode(); const int beginLine = lineForPosition(range.beginPos); const int endLine = lineForPosition(range.endPos); - showBlackMessage(FakeVimHandler::tr("%n lines %1ed %2 time", 0, + showMessage(MessageInfo, FakeVimHandler::tr("%n lines %1ed %2 time", 0, (endLine - beginLine + 1)).arg(cmd.cmd).arg(count)); return true; } @@ -4432,7 +4433,7 @@ bool FakeVimHandler::Private::handleExGotoCommand(const ExCommand &cmd) const int beginLine = lineForPosition(cmd.range.beginPos); setPosition(firstPositionInLine(beginLine)); - showBlackMessage(QString()); + clearMessage(); return true; } @@ -4445,7 +4446,7 @@ bool FakeVimHandler::Private::handleExSourceCommand(const ExCommand &cmd) QString fileName = cmd.args; QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) { - showRedMessage(FakeVimHandler::tr("Cannot open file %1").arg(fileName)); + showMessage(MessageError, FakeVimHandler::tr("Cannot open file %1").arg(fileName)); return true; } @@ -4479,7 +4480,7 @@ bool FakeVimHandler::Private::handleExEchoCommand(const ExCommand &cmd) // :echo if (cmd.cmd != "echo") return false; - g.currentMessage = cmd.args; + showMessage(MessageInfo, cmd.args); return true; } @@ -4491,7 +4492,7 @@ void FakeVimHandler::Private::handleExCommand(const QString &line0) line.chop(1); int percent = line.toInt(); setPosition(firstPositionInLine(percent * linesInDocument() / 100)); - showBlackMessage(QString()); + clearMessage(); return; } @@ -4517,9 +4518,8 @@ void FakeVimHandler::Private::handleExCommand(const QString &line0) } //qDebug() << "CMD: " << cmd; - showBlackMessage(QString()); if (!handleExCommandHelper(cmd)) - showRedMessage(tr("Not an editor command: %1").arg(cmd.cmd)); + showMessage(MessageError, tr("Not an editor command: %1").arg(cmd.cmd)); enterCommandMode(); } @@ -4584,7 +4584,7 @@ void FakeVimHandler::Private::searchBalanced(bool forward, QChar needle, QChar o } } -void FakeVimHandler::Private::search(const SearchData &sd) +void FakeVimHandler::Private::search(const SearchData &sd, bool showMessages) { QTextDocument::FindFlags flags = QTextDocument::FindCaseSensitively; if (!sd.forward) @@ -4610,19 +4610,22 @@ void FakeVimHandler::Private::search(const SearchData &sd) tc = document()->find(needleExp, tc, flags); if (tc.isNull()) { highlightMatches(QString()); - showRedMessage(FakeVimHandler::tr("Pattern not found: %1").arg(sd.needle)); + if (showMessages) { + showMessage(MessageError, + FakeVimHandler::tr("Pattern not found: %1").arg(sd.needle)); + } updateSelection(); - } else { + } else if (showMessages) { QString msg = sd.forward ? FakeVimHandler::tr("search hit BOTTOM, continuing at TOP") : FakeVimHandler::tr("search hit TOP, continuing at BOTTOM"); - showRedMessage(msg); + showMessage(MessageWarning, msg); } - } else { + } else if (showMessages) { QString msg = sd.forward ? FakeVimHandler::tr("search hit BOTTOM without match for: %1") : FakeVimHandler::tr("search hit TOP without match for: %1"); - showRedMessage(msg.arg(sd.needle)); + showMessage(MessageError, msg.arg(sd.needle)); } } @@ -4663,8 +4666,7 @@ void FakeVimHandler::Private::searchNext(bool forward) sd.highlightCursor = false; sd.highlightMatches = true; m_searchStartPosition = position(); - g.currentMessage = (m_lastSearchForward ? '/' : '?') + sd.needle; - updateMiniBuffer(); + showMessage(MessageCommand, (m_lastSearchForward ? '/' : '?') + sd.needle); search(sd); } @@ -4683,7 +4685,7 @@ void FakeVimHandler::Private::highlightMatches(const QString &needle) QRegExp needleExp = vimPatternToQtPattern(needle, hasConfig(ConfigSmartCase)); if (!needleExp.isValid()) { QString error = needleExp.errorString(); - showRedMessage( + showMessage(MessageError, FakeVimHandler::tr("Invalid regular expression: %1").arg(error)); return; } @@ -4753,7 +4755,7 @@ void FakeVimHandler::Private::indentText(const Range &range, QChar typedChar) // LineForPosition has returned 1-based line numbers. emit q->indentRegion(beginLine - 1, endLine - 1, typedChar); if (beginLine != endLine) - showBlackMessage("MARKS ARE OFF NOW"); + showMessage(MessageError, "MARKS ARE OFF NOW"); } bool FakeVimHandler::Private::isElectricCharacter(QChar c) const @@ -4877,6 +4879,32 @@ int FakeVimHandler::Private::charClass(QChar c, bool simple) const return c.isSpace() ? 0 : 1; } +void FakeVimHandler::Private::miniBufferTextEdited(const QString &text, int cursorPos) +{ + if (m_subsubmode != SearchSubSubMode && m_mode != ExMode) { + editor()->setFocus(); + } else if (text.isEmpty()) { + // editing cancelled + handleDefaultKey(Input(Qt::Key_Escape, Qt::NoModifier, QString())); + editor()->setFocus(); + updateCursorShape(); + } else { + CommandBuffer &cmdBuf = (m_mode == ExMode) ? g.commandBuffer : g.searchBuffer; + // prepend prompt character if missing + if (!text.startsWith(cmdBuf.prompt())) { + emit q->commandBufferChanged(cmdBuf.prompt() + text, cmdBuf.cursorPos() + 1, 0, q); + cmdBuf.setContents(text, cursorPos - 1); + } else { + cmdBuf.setContents(text.mid(1), cursorPos - 1); + } + // update search expression + if (m_subsubmode == SearchSubSubMode) { + updateFind(false); + exportSelection(); + } + } +} + // Helper to parse a-z,A-Z,48-57,_ static int someInt(const QString &str) { @@ -5657,10 +5685,10 @@ void FakeVimHandler::Private::undo() m_undo.pop(); if (current == rev) { - showBlackMessage(FakeVimHandler::tr("Already at oldest change")); + showMessage(MessageInfo, FakeVimHandler::tr("Already at oldest change")); return; } - showBlackMessage(QString()); + clearMessage(); if (!m_undo.empty()) { State &state = m_undo.top(); @@ -5689,10 +5717,10 @@ void FakeVimHandler::Private::redo() m_redo.pop(); if (rev == current) { - showBlackMessage(FakeVimHandler::tr("Already at newest change")); + showMessage(MessageInfo, FakeVimHandler::tr("Already at newest change")); return; } - showBlackMessage(QString()); + clearMessage(); if (!m_redo.empty()) { State &state = m_redo.top(); @@ -6224,7 +6252,7 @@ bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev) return res == EventHandled; } - if (active && ev->type() == QEvent::KeyPress && ob == d->editor()) { + if (active && ev->type() == QEvent::KeyPress) { QKeyEvent *kev = static_cast<QKeyEvent *>(ev); KEY_DEBUG("KEYPRESS" << kev->key() << kev->text() << QChar(kev->key())); EventResult res = d->handleEvent(kev); @@ -6300,14 +6328,9 @@ QString FakeVimHandler::currentFileName() const return d->m_currentFileName; } -void FakeVimHandler::showBlackMessage(const QString &msg) -{ - d->showBlackMessage(msg); -} - -void FakeVimHandler::showRedMessage(const QString &msg) +void FakeVimHandler::showMessage(MessageLevel level, const QString &msg) { - d->showRedMessage(msg); + d->showMessage(level, msg); } QWidget *FakeVimHandler::widget() @@ -6333,6 +6356,11 @@ QString FakeVimHandler::tabExpand(int n) const return d->tabExpand(n); } +void FakeVimHandler::miniBufferTextEdited(const QString &text, int cursorPos) +{ + d->miniBufferTextEdited(text, cursorPos); +} + } // namespace Internal } // namespace FakeVim diff --git a/src/plugins/fakevim/fakevimhandler.h b/src/plugins/fakevim/fakevimhandler.h index 7ef0d1afbf..63c1123fbb 100644 --- a/src/plugins/fakevim/fakevimhandler.h +++ b/src/plugins/fakevim/fakevimhandler.h @@ -77,6 +77,16 @@ struct ExCommand int count; }; +// message levels sorted by severity +enum MessageLevel +{ + MessageMode, // show current mode (format "-- %1 --") + MessageCommand, // show last Ex command or search + MessageInfo, // result of a command + MessageWarning, // warning + MessageError // error +}; + class FakeVimHandler : public QObject { Q_OBJECT @@ -94,8 +104,7 @@ public slots: void setCurrentFileName(const QString &fileName); QString currentFileName() const; - void showBlackMessage(const QString &msg); - void showRedMessage(const QString &msg); + void showMessage(MessageLevel level, const QString &msg); // This executes an "ex" style command taking context // information from the current widget. @@ -114,8 +123,10 @@ public slots: int logicalIndentation(const QString &line) const; QString tabExpand(int n) const; + void miniBufferTextEdited(const QString &text, int cursorPos); + signals: - void commandBufferChanged(const QString &msg, int pos); + void commandBufferChanged(const QString &msg, int pos, int messageLevel, QObject *eventFilter); void statusDataChanged(const QString &msg); void extraInformationChanged(const QString &msg); void selectionChanged(const QList<QTextEdit::ExtraSelection> &selection); diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index e24ca6f724..03da387b7f 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -86,6 +86,7 @@ #include <QtPlugin> #include <QObject> #include <QSettings> +#include <QStackedWidget> #include <QTextStream> #include <QDesktopServices> @@ -111,49 +112,99 @@ const char SETTINGS_ID[] = "A.General"; const char SETTINGS_EX_CMDS_ID[] = "B.ExCommands"; const char SETTINGS_USER_CMDS_ID[] = "C.UserCommands"; -class MiniBuffer : public QLabel +class MiniBuffer : public QStackedWidget { Q_OBJECT public: - void setContents(const QString &contents, int cursorPos) + MiniBuffer() : m_label(new QLabel(this)), m_edit(new QLineEdit(this)), m_eventFilter(0) { - QString msg = contents; - if (cursorPos != -1) - msg = contents.left(cursorPos) + QChar(10073) + contents.mid(cursorPos); - setText(" " + msg); + m_edit->installEventFilter(this); + connect(m_edit, SIGNAL(textEdited(QString)), SLOT(changed())); + connect(m_edit, SIGNAL(cursorPositionChanged(int,int)), SLOT(changed())); + m_label->setTextInteractionFlags(Qt::TextSelectableByMouse); + + addWidget(m_label); + addWidget(m_edit); } -}; -class MiniBuffer1 : public QLineEdit -{ - Q_OBJECT + void setContents(const QString &contents, int cursorPos, int messageLevel, QObject *eventFilter) + { + if (cursorPos != -1) { + m_edit->blockSignals(true); + m_label->clear(); + m_edit->setText(contents); + m_edit->setCursorPosition(cursorPos); + m_edit->blockSignals(false); + + setCurrentWidget(m_edit); + m_edit->setFocus(); + } else { + m_label->setText(messageLevel == MessageMode ? "-- " + contents + " --" : contents); + + QString css; + if (messageLevel == MessageError) { + css = QString("border:1px solid rgba(255,255,255,150);" + "background-color:rgba(255,0,0,100);"); + } else if (messageLevel == MessageWarning) { + css = QString("border:1px solid rgba(255,255,255,120);" + "background-color:rgba(255,255,0,20);"); + } + m_label->setStyleSheet(QString( + "*{border-radius:2px;padding-left:4px;padding-right:4px;%1}").arg(css)); -public: - MiniBuffer1() + if (m_edit->hasFocus()) + emit edited(QString(), -1); + + setCurrentWidget(m_label); + } + + if (m_eventFilter != eventFilter) { + if (m_eventFilter != 0) { + m_edit->removeEventFilter(m_eventFilter); + disconnect(SIGNAL(edited(QString,int))); + } + if (eventFilter != 0) { + m_edit->installEventFilter(eventFilter); + connect(this, SIGNAL(edited(QString,int)), + eventFilter, SLOT(miniBufferTextEdited(QString,int))); + } + m_eventFilter = eventFilter; + } + } + + QSize sizeHint() const { - setFrame(false); + QSize size = QWidget::sizeHint(); + // reserve maximal width for line edit widget + return currentWidget() == m_edit ? QSize(maximumWidth(), size.height()) : size; } - void showEvent(QShowEvent *ev) + +signals: + void edited(const QString &text, int cursorPos); + +private slots: + void changed() { - QLineEdit::showEvent(ev); - QColor color = Qt::black; - QPalette pal = parentWidget()->palette(); - pal.setBrush(QPalette::All, QPalette::WindowText, color); - pal.setBrush(QPalette::All, QPalette::ButtonText, color); - pal.setBrush(QPalette::All, QPalette::Foreground, color); - pal.setBrush(QPalette::All, QPalette::Background, color); - //color.setAlpha(100); - //pal.setBrush(QPalette::Disabled, QPalette::WindowText, color); - //pal.setBrush(QPalette::Disabled, QPalette::ButtonText, color); - //pal.setBrush(QPalette::Disabled, QPalette::Foreground, color); - setPalette(pal); + emit edited(m_edit->text(), m_edit->cursorPosition()); } - void setContents(const QString &contents, int cursorPos) + + bool eventFilter(QObject *ob, QEvent *ev) { - setText(contents); - setCursorPosition(cursorPos); + // cancel editing on escape + if (m_eventFilter != 0 && ob == m_edit && ev->type() == QEvent::ShortcutOverride + && static_cast<QKeyEvent*>(ev)->key() == Qt::Key_Escape) { + emit edited(QString(), -1); + ev->accept(); + return true; + } + return false; } + +private: + QLabel *m_label; + QLineEdit *m_edit; + QObject *m_eventFilter; }; /////////////////////////////////////////////////////////////////////// @@ -797,7 +848,9 @@ private slots: void setBlockSelection(bool); void hasBlockSelection(bool*); - void showCommandBuffer(const QString &contents, int cursorPos); + void resetCommandBuffer(); + void showCommandBuffer(const QString &contents, int cursorPos, int messageLevel, + QObject *eventFilter); void showExtraInformation(const QString &msg); void changeSelection(const QList<QTextEdit::ExtraSelection> &selections); void moveToMatchingParenthesis(bool *moved, bool *forward, QTextCursor *cursor); @@ -1340,8 +1393,8 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) connect(handler, SIGNAL(extraInformationChanged(QString)), SLOT(showExtraInformation(QString))); - connect(handler, SIGNAL(commandBufferChanged(QString,int)), - SLOT(showCommandBuffer(QString,int))); + connect(handler, SIGNAL(commandBufferChanged(QString,int,int,QObject*)), + SLOT(showCommandBuffer(QString,int,int,QObject*))); connect(handler, SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)), SLOT(changeSelection(QList<QTextEdit::ExtraSelection>))); connect(handler, SIGNAL(moveToMatchingParenthesis(bool*,bool*,QTextCursor*)), @@ -1376,7 +1429,7 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) // pop up the bar if (theFakeVimSetting(ConfigUseFakeVim)->value().toBool()) { - showCommandBuffer(QString(), -1); + resetCommandBuffer(); handler->setupWidget(); } } @@ -1408,7 +1461,7 @@ void FakeVimPluginPrivate::setUseFakeVimInternal(bool on) //ICore *core = ICore::instance(); //core->updateAdditionalContexts(Context(), // Context(FAKEVIM_CONTEXT)); - showCommandBuffer(QString(), -1); + resetCommandBuffer(); foreach (IEditor *editor, m_editorToHandler.keys()) { if (BaseTextEditorWidget *textEditor = qobject_cast<BaseTextEditorWidget *>(editor->widget())) { @@ -1485,22 +1538,22 @@ void FakeVimPluginPrivate::handleExCommand(bool *handled, const ExCommand &cmd) QFile file3(fileName); file3.open(QIODevice::ReadOnly); QByteArray ba = file3.readAll(); - handler->showBlackMessage(FakeVimHandler::tr("\"%1\" %2 %3L, %4C written") + handler->showMessage(MessageInfo, FakeVimHandler::tr("\"%1\" %2 %3L, %4C written") .arg(fileName).arg(" ") .arg(ba.count('\n')).arg(ba.size())); if (cmd.cmd == "wq") delayedQuitRequested(cmd.hasBang, m_editorToHandler.key(handler)); } else { - handler->showRedMessage(tr("File not saved")); + handler->showMessage(MessageError, tr("File not saved")); } } else if (cmd.matches("wa", "wall")) { // :w[all] QList<IDocument *> toSave = DocumentManager::modifiedDocuments(); QList<IDocument *> failed = DocumentManager::saveModifiedDocumentsSilently(toSave); if (failed.isEmpty()) - handler->showBlackMessage(tr("Saving succeeded")); + handler->showMessage(MessageInfo, tr("Saving succeeded")); else - handler->showRedMessage(tr("%n files not saved", 0, failed.size())); + handler->showMessage(MessageError, tr("%n files not saved", 0, failed.size())); } else if (cmd.matches("q", "quit")) { // :q[uit] emit delayedQuitRequested(cmd.hasBang, m_editorToHandler.key(handler)); @@ -1666,11 +1719,17 @@ void FakeVimPluginPrivate::quitFakeVim() theFakeVimSetting(ConfigUseFakeVim)->setValue(false); } -void FakeVimPluginPrivate::showCommandBuffer(const QString &contents, int cursorPos) +void FakeVimPluginPrivate::resetCommandBuffer() +{ + showCommandBuffer(QString(), -1, 0, 0); +} + +void FakeVimPluginPrivate::showCommandBuffer(const QString &contents, int cursorPos, + int messageLevel, QObject *eventFilter) { //qDebug() << "SHOW COMMAND BUFFER" << contents; if (MiniBuffer *w = qobject_cast<MiniBuffer *>(m_statusBar->widget())) - w->setContents(contents, cursorPos); + w->setContents(contents, cursorPos, messageLevel, eventFilter); } void FakeVimPluginPrivate::showExtraInformation(const QString &text) -- GitLab