1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "fakevimplugin.h"
36 #include "fakevimhandler.h"
37 #include "ui_fakevimoptions.h"
39 #include <coreplugin/actionmanager/actioncontainer.h>
40 #include <coreplugin/actionmanager/actionmanager.h>
41 #include <coreplugin/actionmanager/command.h>
42 #include <coreplugin/actionmanager/command.h>
43 #include <coreplugin/actionmanager/commandmappings.h>
44 #include <coreplugin/coreconstants.h>
45 #include <coreplugin/dialogs/ioptionspage.h>
46 #include <coreplugin/editormanager/editormanager.h>
47 #include <coreplugin/editormanager/openeditorsmodel.h>
48 #include <coreplugin/filemanager.h>
49 #include <coreplugin/icore.h>
50 #include <coreplugin/ifile.h>
51 #include <coreplugin/messagemanager.h>
52 #include <coreplugin/uniqueidmanager.h>
53 #include <coreplugin/statusbarwidget.h>
54 #include <coreplugin/statusbarmanager.h>
56 #include <projectexplorer/projectexplorerconstants.h>
58 #include <texteditor/basetextdocumentlayout.h>
59 #include <texteditor/basetexteditor.h>
60 #include <texteditor/basetextmark.h>
61 #include <texteditor/completionsupport.h>
62 #include <texteditor/texteditorconstants.h>
63 #include <texteditor/tabsettings.h>
64 #include <texteditor/texteditorsettings.h>
65 #include <texteditor/indenter.h>
66 #include <texteditor/icompletioncollector.h>
68 #include <find/findplugin.h>
69 #include <find/textfindconstants.h>
71 #include <utils/qtcassert.h>
72 #include <utils/savedaction.h>
73 #include <utils/treewidgetcolumnstretcher.h>
75 #include <cppeditor/cppeditorconstants.h>
77 #include <cpptools/cpptoolsconstants.h>
79 #include <QtCore/QDebug>
80 #include <QtCore/QFile>
81 #include <QtCore/QtPlugin>
82 #include <QtCore/QObject>
83 #include <QtCore/QSettings>
84 #include <QtCore/QTextStream>
86 #include <QtGui/QDesktopServices>
87 #include <QtGui/QMessageBox>
88 #include <QtGui/QPlainTextEdit>
89 #include <QtGui/QShortcut>
90 #include <QtGui/QTextBlock>
91 #include <QtGui/QTextCursor>
92 #include <QtGui/QTextEdit>
93 #include <QtGui/QTreeWidgetItem>
95 using namespace FakeVim::Internal;
96 using namespace TextEditor;
100 namespace Constants {
102 const char * const INSTALL_HANDLER = "TextEditor.FakeVimHandler";
103 const char * const MINI_BUFFER = "TextEditor.FakeVimMiniBuffer";
104 const char * const INSTALL_KEY = "Alt+V,Alt+V";
105 const char * const SETTINGS_CATEGORY = "D.FakeVim";
106 const char * const SETTINGS_CATEGORY_FAKEVIM_ICON = ":/core/images/category_fakevim.png";
107 const char * const SETTINGS_ID = "A.General";
108 const char * const SETTINGS_EX_CMDS_ID = "B.ExCommands";
110 } // namespace Constants
111 } // namespace FakeVim
117 ///////////////////////////////////////////////////////////////////////
121 ///////////////////////////////////////////////////////////////////////
123 typedef QMap<QString, QRegExp> CommandMap;
124 typedef QLatin1String _;
126 class FakeVimOptionPage : public Core::IOptionsPage
131 FakeVimOptionPage() {}
134 QString id() const { return _(Constants::SETTINGS_ID); }
135 QString displayName() const { return tr("General"); }
136 QString category() const { return _(Constants::SETTINGS_CATEGORY); }
137 QString displayCategory() const { return tr("FakeVim"); }
138 QIcon categoryIcon() const
139 { return QIcon(_(Constants::SETTINGS_CATEGORY_FAKEVIM_ICON)); }
141 QWidget *createPage(QWidget *parent);
142 void apply() { m_group.apply(ICore::instance()->settings()); }
143 void finish() { m_group.finish(); }
144 virtual bool matches(const QString &) const;
147 void copyTextEditorSettings();
149 void setPlainStyle();
152 friend class DebuggerPlugin;
153 Ui::FakeVimOptionPage m_ui;
154 QString m_searchKeywords;
155 Utils::SavedActionSet m_group;
158 QWidget *FakeVimOptionPage::createPage(QWidget *parent)
160 QWidget *w = new QWidget(parent);
164 m_group.insert(theFakeVimSetting(ConfigUseFakeVim),
165 m_ui.checkBoxUseFakeVim);
166 m_group.insert(theFakeVimSetting(ConfigReadVimRc),
167 m_ui.checkBoxReadVimRc);
169 m_group.insert(theFakeVimSetting(ConfigExpandTab),
170 m_ui.checkBoxExpandTab);
171 m_group.insert(theFakeVimSetting(ConfigHlSearch),
172 m_ui.checkBoxHlSearch);
173 m_group.insert(theFakeVimSetting(ConfigShiftWidth),
174 m_ui.spinBoxShiftWidth);
175 m_group.insert(theFakeVimSetting(ConfigShowMarks),
176 m_ui.checkBoxShowMarks);
178 m_group.insert(theFakeVimSetting(ConfigSmartTab),
179 m_ui.checkBoxSmartTab);
180 m_group.insert(theFakeVimSetting(ConfigStartOfLine),
181 m_ui.checkBoxStartOfLine);
182 m_group.insert(theFakeVimSetting(ConfigTabStop),
183 m_ui.spinBoxTabStop);
184 m_group.insert(theFakeVimSetting(ConfigBackspace),
185 m_ui.lineEditBackspace);
186 m_group.insert(theFakeVimSetting(ConfigIsKeyword),
187 m_ui.lineEditIsKeyword);
189 m_group.insert(theFakeVimSetting(ConfigPassControlKey),
190 m_ui.checkBoxPassControlKey);
191 m_group.insert(theFakeVimSetting(ConfigAutoIndent),
192 m_ui.checkBoxAutoIndent);
193 m_group.insert(theFakeVimSetting(ConfigSmartIndent),
194 m_ui.checkBoxSmartIndent);
195 m_group.insert(theFakeVimSetting(ConfigIncSearch),
196 m_ui.checkBoxIncSearch);
197 m_group.insert(theFakeVimSetting(ConfigUseCoreSearch),
198 m_ui.checkBoxUseCoreSearch);
200 connect(m_ui.pushButtonCopyTextEditorSettings, SIGNAL(clicked()),
201 SLOT(copyTextEditorSettings()));
202 connect(m_ui.pushButtonSetQtStyle, SIGNAL(clicked()),
204 connect(m_ui.pushButtonSetPlainStyle, SIGNAL(clicked()),
205 SLOT(setPlainStyle()));
207 if (m_searchKeywords.isEmpty()) {
208 QLatin1Char sep(' ');
209 QTextStream(&m_searchKeywords)
210 << sep << m_ui.checkBoxUseFakeVim->text()
211 << sep << m_ui.checkBoxReadVimRc->text()
212 << sep << m_ui.checkBoxAutoIndent->text()
213 << sep << m_ui.checkBoxSmartIndent->text()
214 << sep << m_ui.checkBoxExpandTab->text()
215 << sep << m_ui.checkBoxSmartTab->text()
216 << sep << m_ui.checkBoxHlSearch->text()
217 << sep << m_ui.checkBoxIncSearch->text()
218 << sep << m_ui.checkBoxStartOfLine->text()
219 << sep << m_ui.checkBoxUseCoreSearch->text()
220 << sep << m_ui.checkBoxShowMarks->text()
221 << sep << m_ui.checkBoxPassControlKey->text()
222 << sep << m_ui.labelShiftWidth->text()
223 << sep << m_ui.labelTabulator->text()
224 << sep << m_ui.labelBackspace->text()
225 << sep << m_ui.labelIsKeyword->text();
226 m_searchKeywords.remove(QLatin1Char('&'));
231 void FakeVimOptionPage::copyTextEditorSettings()
233 TabSettings ts = TextEditorSettings::instance()->tabSettings();
234 m_ui.checkBoxExpandTab->setChecked(ts.m_spacesForTabs);
235 m_ui.spinBoxTabStop->setValue(ts.m_tabSize);
236 m_ui.spinBoxShiftWidth->setValue(ts.m_indentSize);
237 m_ui.checkBoxSmartTab->setChecked(ts.m_smartBackspace);
238 m_ui.checkBoxAutoIndent->setChecked(true);
239 m_ui.checkBoxSmartIndent->setChecked(ts.m_autoIndent);
240 m_ui.checkBoxIncSearch->setChecked(true);
243 void FakeVimOptionPage::setQtStyle()
245 m_ui.checkBoxExpandTab->setChecked(true);
246 m_ui.spinBoxTabStop->setValue(4);
247 m_ui.spinBoxShiftWidth->setValue(4);
248 m_ui.checkBoxSmartTab->setChecked(true);
249 m_ui.checkBoxAutoIndent->setChecked(true);
250 m_ui.checkBoxSmartIndent->setChecked(true);
251 m_ui.checkBoxIncSearch->setChecked(true);
252 m_ui.lineEditBackspace->setText(_("indent,eol,start"));
255 void FakeVimOptionPage::setPlainStyle()
257 m_ui.checkBoxExpandTab->setChecked(false);
258 m_ui.spinBoxTabStop->setValue(8);
259 m_ui.spinBoxShiftWidth->setValue(8);
260 m_ui.checkBoxSmartTab->setChecked(false);
261 m_ui.checkBoxAutoIndent->setChecked(false);
262 m_ui.checkBoxSmartIndent->setChecked(false);
263 m_ui.checkBoxIncSearch->setChecked(false);
264 m_ui.lineEditBackspace->setText(QString());
267 bool FakeVimOptionPage::matches(const QString &s) const
269 return m_searchKeywords.contains(s, Qt::CaseInsensitive);
272 //const char *FAKEVIM_CONTEXT = "FakeVim";
274 ///////////////////////////////////////////////////////////////////////
276 // FakeVimExCommandsPage
278 ///////////////////////////////////////////////////////////////////////
280 enum { CommandRole = Qt::UserRole };
282 class FakeVimExCommandsPage : public Core::CommandMappings
287 FakeVimExCommandsPage(FakeVimPluginPrivate *q) : m_q(q) {}
288 ~FakeVimExCommandsPage() {}
291 QString id() const { return _(Constants::SETTINGS_EX_CMDS_ID); }
292 QString displayName() const { return tr("Ex Command Mapping"); }
293 QString category() const { return _(Constants::SETTINGS_CATEGORY); }
294 QString displayCategory() const { return tr("FakeVim"); }
295 QIcon categoryIcon() const { return QIcon(); } // TODO: Icon for FakeVim
297 QWidget *createPage(QWidget *parent);
299 CommandMap &exCommandMap();
300 CommandMap &defaultExCommandMap();
303 void commandChanged(QTreeWidgetItem *current);
304 void targetIdentifierChanged();
305 void resetTargetIdentifier();
306 void removeTargetIdentifier();
307 void defaultAction();
310 //QList<QTreeWidgetItem *> m_citems;
311 FakeVimPluginPrivate *m_q;
314 QWidget *FakeVimExCommandsPage::createPage(QWidget *parent)
316 QWidget *w = CommandMappings::createPage(parent);
317 setPageTitle(tr("Ex Command Mapping"));
318 setTargetHeader(tr("Ex Trigger Expression"));
319 setTargetLabelText(tr("Regular expression:"));
320 setTargetEditTitle(tr("Ex Command"));
321 setImportExportEnabled(false);
325 void FakeVimExCommandsPage::initialize()
327 ActionManager *am = ICore::instance()->actionManager();
328 QTC_ASSERT(am, return);
329 UniqueIDManager *uidm = UniqueIDManager::instance();
330 QTC_ASSERT(uidm, return);
332 QMap<QString, QTreeWidgetItem *> sections;
334 foreach (Command *c, am->commands()) {
335 if (c->action() && c->action()->isSeparator())
338 QTreeWidgetItem *item = new QTreeWidgetItem;
339 item->setData(0, CommandRole, int(c->id()));
340 //m_citems.append(item);
342 const QString name = uidm->stringForUniqueIdentifier(c->id());
343 const int pos = name.indexOf(QLatin1Char('.'));
344 const QString section = name.left(pos);
345 const QString subId = name.mid(pos + 1);
347 if (!sections.contains(section)) {
348 QTreeWidgetItem *categoryItem =
349 new QTreeWidgetItem(commandList(), QStringList() << section);
350 QFont f = categoryItem->font(0);
352 categoryItem->setFont(0, f);
353 sections.insert(section, categoryItem);
354 commandList()->expandItem(categoryItem);
356 sections[section]->addChild(item);
358 item->setText(0, subId);
361 QString text = c->hasAttribute(Command::CA_UpdateText)
362 && !c->defaultText().isNull()
363 ? c->defaultText() : c->action()->text();
364 text.remove(QRegExp("&(?!&)"));
365 item->setText(1, text);
367 item->setText(1, c->shortcut()->whatsThis());
371 if (exCommandMap().contains(name))
372 regex = exCommandMap()[name].pattern();
373 item->setText(2, regex);
375 if (regex != defaultExCommandMap()[name].pattern())
376 setModified(item, true);
382 void FakeVimExCommandsPage::commandChanged(QTreeWidgetItem *current)
384 CommandMappings::commandChanged(current);
386 targetEdit()->setText(current->text(2));
389 void FakeVimExCommandsPage::targetIdentifierChanged()
391 QTreeWidgetItem *current = commandList()->currentItem();
395 UniqueIDManager *uidm = UniqueIDManager::instance();
396 int id = current->data(0, CommandRole).toInt();
397 const QString name = uidm->stringForUniqueIdentifier(id);
398 const QString regex = targetEdit()->text();
400 if (current->data(0, Qt::UserRole).isValid()) {
401 current->setText(2, regex);
402 exCommandMap()[name] = QRegExp(regex);
405 if (regex != defaultExCommandMap()[name].pattern())
406 setModified(current, true);
408 setModified(current, false);
412 void FakeVimExCommandsPage::resetTargetIdentifier()
414 QTreeWidgetItem *current = commandList()->currentItem();
417 UniqueIDManager *uidm = UniqueIDManager::instance();
418 int id = current->data(0, CommandRole).toInt();
419 const QString name = uidm->stringForUniqueIdentifier(id);
421 if (defaultExCommandMap().contains(name))
422 regex = defaultExCommandMap()[name].pattern();
423 targetEdit()->setText(regex);
426 void FakeVimExCommandsPage::removeTargetIdentifier()
428 targetEdit()->clear();
431 void FakeVimExCommandsPage::defaultAction()
433 UniqueIDManager *uidm = UniqueIDManager::instance();
434 int n = commandList()->topLevelItemCount();
435 for (int i = 0; i != n; ++i) {
436 QTreeWidgetItem *section = commandList()->topLevelItem(i);
437 int m = section->childCount();
438 for (int j = 0; j != m; ++j) {
439 QTreeWidgetItem *item = section->child(j);
440 const int id = item->data(0, CommandRole).toInt();
441 const QString name = uidm->stringForUniqueIdentifier(id);
443 if (defaultExCommandMap().contains(name))
444 regex = defaultExCommandMap()[name].pattern();
445 setModified(item, false);
446 item->setText(2, regex);
447 if (item == commandList()->currentItem())
448 commandChanged(item);
454 ///////////////////////////////////////////////////////////////////////
458 ///////////////////////////////////////////////////////////////////////
460 class WordCompletion : public ICompletionCollector
471 virtual bool shouldRestartCompletion()
473 //qDebug() << "SHOULD RESTART COMPLETION?";
477 virtual ITextEditor *editor() const
479 //qDebug() << "NO EDITOR?";
483 virtual int startPosition() const
485 return m_startPosition;
488 virtual bool supportsEditor(ITextEditor *) const
493 virtual bool supportsPolicy(CompletionPolicy policy) const
495 return policy == TextCompletion;
498 virtual bool triggersCompletion(ITextEditor *editable)
500 //qDebug() << "TRIGGERS?";
501 QTC_ASSERT(m_editable == editable, /**/);
505 virtual int startCompletion(ITextEditor *editable)
507 //qDebug() << "START COMPLETION";
508 QTC_ASSERT(m_editor, return -1);
509 QTC_ASSERT(m_editable == editable, return -1);
510 return m_editor->textCursor().position();
513 void setActive(const QString &needle, bool forward, FakeVimHandler *handler)
519 m_editor = qobject_cast<BaseTextEditorWidget *>(handler->widget());
522 //qDebug() << "ACTIVATE: " << needle << forward;
524 m_editable = m_editor->editor();
525 m_startPosition = m_editor->textCursor().position() - needle.size();
527 CompletionSupport::instance()->complete(m_editable, TextCompletion, false);
536 m_startPosition = -1;
539 virtual void completions(QList<CompletionItem> *completions)
541 QTC_ASSERT(m_editor, return);
542 QTC_ASSERT(completions, return);
543 QTextCursor tc = m_editor->textCursor();
544 tc.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
548 QTextDocument::FindFlags flags = QTextDocument::FindCaseSensitively;
550 tc = tc.document()->find(m_needle, tc.position(), flags);
553 QTextCursor sel = tc;
554 sel.select(QTextCursor::WordUnderCursor);
555 QString found = sel.selectedText();
556 // Only add "real" completions.
557 if (found.startsWith(m_needle)
558 && !seen.contains(found)
559 && sel.anchor() != m_startPosition) {
562 item.collector = this;
564 completions->append(item);
566 tc.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor);
568 //qDebug() << "COMPLETIONS" << completions->size();
571 virtual bool typedCharCompletes(const CompletionItem &item, QChar typedChar)
573 m_needle += typedChar;
574 //qDebug() << "COMPLETE? " << typedChar << item.text << m_needle;
575 return item.text == m_needle;
578 virtual void complete(const CompletionItem &item, QChar typedChar)
581 //qDebug() << "COMPLETE: " << item.text;
582 QTC_ASSERT(m_handler, return);
583 m_handler->handleReplay(item.text.mid(m_needle.size()));
587 virtual bool partiallyComplete(const QList<CompletionItem> &completionItems)
589 //qDebug() << "PARTIALLY";
590 Q_UNUSED(completionItems);
594 virtual void cleanup() {}
597 int findStartOfName(int pos = -1) const;
598 bool isInComment() const;
600 FakeVimHandler *m_handler;
601 BaseTextEditorWidget *m_editor;
602 ITextEditor *m_editable;
604 QString m_currentPrefix;
605 QList<CompletionItem> m_items;
610 ///////////////////////////////////////////////////////////////////////
612 // FakeVimPluginPrivate
614 ///////////////////////////////////////////////////////////////////////
616 class FakeVimPluginPrivate : public QObject
621 FakeVimPluginPrivate(FakeVimPlugin *);
622 ~FakeVimPluginPrivate();
623 friend class FakeVimPlugin;
624 friend class FakeVimExCommandsPage;
627 void aboutToShutdown();
630 void onCoreAboutToClose();
631 void editorOpened(Core::IEditor *);
632 void editorAboutToClose(Core::IEditor *);
634 void setUseFakeVim(const QVariant &value);
636 void triggerCompletions();
637 void triggerSimpleCompletions(const QString &needle, bool forward);
638 void windowCommand(int key);
639 void find(bool reverse);
640 void findNext(bool reverse);
641 void showSettingsDialog();
642 void maybeReadVimRc();
643 void setBlockSelection(bool);
644 void hasBlockSelection(bool*);
646 void showCommandBuffer(const QString &contents);
647 void showExtraInformation(const QString &msg);
648 void changeSelection(const QList<QTextEdit::ExtraSelection> &selections);
649 void moveToMatchingParenthesis(bool *moved, bool *forward, QTextCursor *cursor);
650 void checkForElectricCharacter(bool *result, QChar c);
651 void indentRegion(int beginLine, int endLine, QChar typedChar);
652 void handleExCommand(bool *handled, const ExCommand &cmd);
654 void writeSettings();
657 void handleDelayedQuitAll(bool forced);
658 void handleDelayedQuit(bool forced, Core::IEditor *editor);
660 void switchToFile(int n);
661 int currentFile() const;
664 void delayedQuitRequested(bool forced, Core::IEditor *editor);
665 void delayedQuitAllRequested(bool forced);
669 FakeVimOptionPage *m_fakeVimOptionsPage;
670 FakeVimExCommandsPage *m_fakeVimExCommandsPage;
671 QHash<Core::IEditor *, FakeVimHandler *> m_editorToHandler;
672 QPointer<Core::ICore> m_core;
673 QPointer<Core::EditorManager> m_editorManager;
674 QPointer<Core::ActionManager> m_actionManager;
675 ICore *core() const { return m_core; }
676 EditorManager *editorManager() const { return m_editorManager; }
677 ActionManager *actionManager() const { return m_actionManager; }
679 void triggerAction(const QString &code);
680 void setActionChecked(const QString &code, bool check);
682 typedef int (*DistFunction)(const QRect &cursor, const QRect &other);
683 void moveSomewhere(DistFunction f);
685 CommandMap &exCommandMap() { return m_exCommandMap; }
686 CommandMap &defaultExCommandMap() { return m_defaultExCommandMap; }
687 CommandMap m_exCommandMap;
688 CommandMap m_defaultExCommandMap;
689 Core::StatusBarWidget *m_statusBar;
690 WordCompletion *m_wordCompletion;
693 FakeVimPluginPrivate::FakeVimPluginPrivate(FakeVimPlugin *plugin)
696 m_fakeVimOptionsPage = 0;
697 m_fakeVimExCommandsPage = 0;
698 defaultExCommandMap()[CppTools::Constants::SWITCH_HEADER_SOURCE] =
700 defaultExCommandMap()["Coreplugin.OutputPane.previtem"] =
701 QRegExp("^(cN(ext)?|cp(revious)?)!?( (.*))?$");
702 defaultExCommandMap()["Coreplugin.OutputPane.nextitem"] =
703 QRegExp("^cn(ext)?!?( (.*))?$");
704 defaultExCommandMap()[CppEditor::Constants::JUMP_TO_DEFINITION] =
706 defaultExCommandMap()[Core::Constants::GO_BACK] =
708 defaultExCommandMap()[_("QtCreator.Locate")] =
713 FakeVimPluginPrivate::~FakeVimPluginPrivate()
715 q->removeObject(m_fakeVimOptionsPage);
716 delete m_fakeVimOptionsPage;
717 m_fakeVimOptionsPage = 0;
718 delete theFakeVimSettings();
720 q->removeObject(m_fakeVimExCommandsPage);
721 delete m_fakeVimExCommandsPage;
722 m_fakeVimExCommandsPage = 0;
725 void FakeVimPluginPrivate::onCoreAboutToClose()
727 // don't attach to editors any more
728 disconnect(editorManager(), SIGNAL(editorOpened(Core::IEditor*)),
729 this, SLOT(editorOpened(Core::IEditor*)));
732 void FakeVimPluginPrivate::aboutToShutdown()
736 bool FakeVimPluginPrivate::initialize()
738 m_core = Core::ICore::instance();
739 m_editorManager = core()->editorManager();
740 m_actionManager = core()->actionManager();
741 QTC_ASSERT(actionManager(), return false);
743 m_wordCompletion = new WordCompletion;
744 q->addAutoReleasedObject(m_wordCompletion);
746 // Set completion settings and keep them up to date.
747 TextEditorSettings *textEditorSettings = TextEditorSettings::instance();
748 completion->setCompletionSettings(textEditorSettings->completionSettings());
749 connect(textEditorSettings,
750 SIGNAL(completionSettingsChanged(TextEditor::CompletionSettings)),
752 SLOT(setCompletionSettings(TextEditor::CompletionSettings)));
755 Context globalcontext(Core::Constants::C_GLOBAL);
757 m_fakeVimOptionsPage = new FakeVimOptionPage;
758 q->addObject(m_fakeVimOptionsPage);
760 m_fakeVimExCommandsPage = new FakeVimExCommandsPage(this);
761 q->addObject(m_fakeVimExCommandsPage);
764 Core::Command *cmd = 0;
765 cmd = actionManager()->registerAction(theFakeVimSetting(ConfigUseFakeVim),
766 Constants::INSTALL_HANDLER, globalcontext);
767 cmd->setDefaultKeySequence(QKeySequence(Constants::INSTALL_KEY));
769 ActionContainer *advancedMenu =
770 actionManager()->actionContainer(Core::Constants::M_EDIT_ADVANCED);
771 advancedMenu->addAction(cmd, Core::Constants::G_EDIT_EDITOR);
773 connect(m_core, SIGNAL(coreAboutToClose()), this, SLOT(onCoreAboutToClose()));
776 connect(editorManager(), SIGNAL(editorAboutToClose(Core::IEditor*)),
777 this, SLOT(editorAboutToClose(Core::IEditor*)));
778 connect(editorManager(), SIGNAL(editorOpened(Core::IEditor*)),
779 this, SLOT(editorOpened(Core::IEditor*)));
781 connect(theFakeVimSetting(ConfigUseFakeVim), SIGNAL(valueChanged(QVariant)),
782 this, SLOT(setUseFakeVim(QVariant)));
783 connect(theFakeVimSetting(ConfigReadVimRc), SIGNAL(valueChanged(QVariant)),
784 this, SLOT(maybeReadVimRc()));
786 // Delayed operations.
787 connect(this, SIGNAL(delayedQuitRequested(bool,Core::IEditor*)),
788 this, SLOT(handleDelayedQuit(bool,Core::IEditor*)), Qt::QueuedConnection);
789 connect(this, SIGNAL(delayedQuitAllRequested(bool)),
790 this, SLOT(handleDelayedQuitAll(bool)), Qt::QueuedConnection);
792 // << "MODE: " << theFakeVimSetting(ConfigUseFakeVim)->value();
797 static const char *exCommandMapGroup = "FakeVimExCommand";
798 static const char *reKey = "RegEx";
799 static const char *idKey = "Command";
801 void FakeVimPluginPrivate::writeSettings()
803 QSettings *settings = ICore::instance()->settings();
805 theFakeVimSettings()->writeSettings(settings);
807 settings->beginWriteArray(_(exCommandMapGroup));
809 typedef CommandMap::const_iterator Iterator;
810 const Iterator end = exCommandMap().constEnd();
811 for (Iterator it = exCommandMap().constBegin(); it != end; ++it) {
812 const QString id = it.key();
813 const QRegExp re = it.value();
815 if ((defaultExCommandMap().contains(id) && defaultExCommandMap()[id] != re)
816 || (!defaultExCommandMap().contains(id) && !re.pattern().isEmpty())) {
817 settings->setArrayIndex(count);
818 settings->setValue(_(idKey), id);
819 settings->setValue(_(reKey), re.pattern());
824 settings->endArray();
827 void FakeVimPluginPrivate::readSettings()
829 QSettings *settings = ICore::instance()->settings();
831 theFakeVimSettings()->readSettings(settings);
833 exCommandMap() = defaultExCommandMap();
834 int size = settings->beginReadArray(_(exCommandMapGroup));
835 for (int i = 0; i < size; ++i) {
836 settings->setArrayIndex(i);
837 const QString id = settings->value(_(idKey)).toString();
838 const QString re = settings->value(_(reKey)).toString();
839 exCommandMap()[id] = QRegExp(re);
841 settings->endArray();
844 void FakeVimPluginPrivate::maybeReadVimRc()
846 //qDebug() << theFakeVimSetting(ConfigReadVimRc)
847 // << theFakeVimSetting(ConfigReadVimRc)->value();
848 //qDebug() << theFakeVimSetting(ConfigShiftWidth)->value();
849 if (!theFakeVimSetting(ConfigReadVimRc)->value().toBool())
852 QDesktopServices::storageLocation(QDesktopServices::HomeLocation)
854 //qDebug() << "READING VIMRC: " << fileName;
855 // Read it into a temporary handler for effects modifying global state.
856 QPlainTextEdit editor;
857 FakeVimHandler handler(&editor);
858 handler.handleCommand("source " + fileName);
860 //qDebug() << theFakeVimSetting(ConfigShiftWidth)->value();
863 void FakeVimPluginPrivate::showSettingsDialog()
865 core()->showOptionsDialog(
866 _(Constants::SETTINGS_CATEGORY),
867 _(Constants::SETTINGS_ID));
870 void FakeVimPluginPrivate::triggerAction(const QString &code)
872 Core::ActionManager *am = actionManager();
873 QTC_ASSERT(am, return);
874 Core::Command *cmd = am->command(code);
875 QTC_ASSERT(cmd, qDebug() << "UNKNOWN CODE: " << code; return);
876 QAction *action = cmd->action();
877 QTC_ASSERT(action, return);
881 void FakeVimPluginPrivate::setActionChecked(const QString &code, bool check)
883 Core::ActionManager *am = actionManager();
884 QTC_ASSERT(am, return);
885 Core::Command *cmd = am->command(code);
886 QTC_ASSERT(cmd, return);
887 QAction *action = cmd->action();
888 QTC_ASSERT(action, return);
889 QTC_ASSERT(action->isCheckable(), return);
890 action->setChecked(!check); // trigger negates the action's state
894 static int moveRightWeight(const QRect &cursor, const QRect &other)
896 int dx = other.left() - cursor.right();
900 int dy1 = cursor.top() - other.bottom();
901 int dy2 = cursor.bottom() - other.top();
902 w += dy1 * (dy1 > 0);
903 w += dy2 * (dy2 > 0);
904 qDebug() << " DX: " << dx << dy1 << dy2 << w;
908 static int moveLeftWeight(const QRect &cursor, const QRect &other)
910 int dx = other.right() - cursor.left();
914 int dy1 = cursor.top() - other.bottom();
915 int dy2 = cursor.bottom() - other.top();
916 w += dy1 * (dy1 > 0);
917 w += dy2 * (dy2 > 0);
921 static int moveUpWeight(const QRect &cursor, const QRect &other)
923 int dy = other.bottom() - cursor.top();
927 int dx1 = cursor.left() - other.right();
928 int dx2 = cursor.right() - other.left();
929 w += dx1 * (dx1 > 0);
930 w += dx2 * (dx2 > 0);
934 static int moveDownWeight(const QRect &cursor, const QRect &other)
936 int dy = other.top() - cursor.bottom();
940 int dx1 = cursor.left() - other.right();
941 int dx2 = cursor.right() - other.left();
942 w += dx1 * (dx1 > 0);
943 w += dx2 * (dx2 > 0);
947 void FakeVimPluginPrivate::windowCommand(int key)
949 # define control(n) (256 + n)
951 case 'c': case 'C': case control('c'):
952 triggerAction(Core::Constants::CLOSE);
954 case 'n': case 'N': case control('n'):
955 triggerAction(Core::Constants::GOTONEXT);
957 case 'o': case 'O': case control('o'):
958 //triggerAction(Core::Constants::REMOVE_ALL_SPLITS);
959 triggerAction(Core::Constants::REMOVE_CURRENT_SPLIT);
961 case 'p': case 'P': case control('p'):
962 triggerAction(Core::Constants::GOTOPREV);
964 case 's': case 'S': case control('s'):
965 triggerAction(Core::Constants::SPLIT);
967 case 'w': case 'W': case control('w'):
968 triggerAction(Core::Constants::GOTO_OTHER_SPLIT);
971 moveSomewhere(&moveRightWeight);
974 moveSomewhere(&moveLeftWeight);
977 moveSomewhere(&moveUpWeight);
980 moveSomewhere(&moveDownWeight);
983 qDebug() << "UNKNOWN WINDOWS COMMAND: " << key;
989 void FakeVimPluginPrivate::moveSomewhere(DistFunction f)
991 IEditor *editor = editorManager()->currentEditor();
992 QWidget *w = editor->widget();
994 qobject_cast<QPlainTextEdit *>(editor->widget());
995 QTC_ASSERT(pe, return);
996 QRect rc = pe->cursorRect();
997 QRect cursorRect(w->mapToGlobal(rc.topLeft()),
998 w->mapToGlobal(rc.bottomRight()));
999 //qDebug() << "\nCURSOR: " << cursorRect;
1001 IEditor *bestEditor = 0;
1002 int bestValue = 1 << 30;
1004 QList<IEditor*> editors = editorManager()->visibleEditors();
1005 foreach (IEditor *editor, editors) {
1006 QWidget *w = editor->widget();
1007 QRect editorRect(w->mapToGlobal(w->geometry().topLeft()),
1008 w->mapToGlobal(w->geometry().bottomRight()));
1009 //qDebug() << " EDITOR: " << editorRect << editor;
1011 int value = f(cursorRect, editorRect);
1012 if (value != -1 && value < bestValue) {
1014 bestEditor = editor;
1015 //qDebug() << " BEST SO FAR: " << bestValue << bestEditor;
1018 //qDebug() << " BEST: " << bestValue << bestEditor;
1020 // FIME: This is know to fail as the EditorManager will fall back to
1021 // the current editor's view. Needs additional public API there.
1023 editorManager()->activateEditor(bestEditor);
1026 void FakeVimPluginPrivate::find(bool reverse)
1028 if (Find::FindPlugin *plugin = Find::FindPlugin::instance()) {
1029 plugin->setUseFakeVim(true);
1030 plugin->openFindToolBar(reverse
1031 ? Find::FindPlugin::FindBackward
1032 : Find::FindPlugin::FindForward);
1036 void FakeVimPluginPrivate::findNext(bool reverse)
1039 triggerAction(Find::Constants::FIND_PREVIOUS);
1041 triggerAction(Find::Constants::FIND_NEXT);
1044 // This class defers deletion of a child FakeVimHandler using deleteLater().
1045 class DeferredDeleter : public QObject
1049 FakeVimHandler *m_handler;
1052 DeferredDeleter(QObject *parent, FakeVimHandler *handler)
1053 : QObject(parent), m_handler(handler)
1056 virtual ~DeferredDeleter()
1059 m_handler->disconnectFromEditor();
1060 m_handler->deleteLater();
1066 void FakeVimPluginPrivate::editorOpened(Core::IEditor *editor)
1071 QWidget *widget = editor->widget();
1075 // we can only handle QTextEdit and QPlainTextEdit
1076 if (!qobject_cast<QTextEdit *>(widget) && !qobject_cast<QPlainTextEdit *>(widget))
1079 //qDebug() << "OPENING: " << editor << editor->widget()
1080 // << "MODE: " << theFakeVimSetting(ConfigUseFakeVim)->value();
1082 FakeVimHandler *handler = new FakeVimHandler(widget, 0);
1083 // the handler might have triggered the deletion of the editor:
1084 // make sure that it can return before being deleted itself
1085 new DeferredDeleter(widget, handler);
1086 m_editorToHandler[editor] = handler;
1088 connect(handler, SIGNAL(extraInformationChanged(QString)),
1089 SLOT(showExtraInformation(QString)));
1090 connect(handler, SIGNAL(commandBufferChanged(QString)),
1091 SLOT(showCommandBuffer(QString)));
1092 connect(handler, SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)),
1093 SLOT(changeSelection(QList<QTextEdit::ExtraSelection>)));
1094 connect(handler, SIGNAL(moveToMatchingParenthesis(bool*,bool*,QTextCursor*)),
1095 SLOT(moveToMatchingParenthesis(bool*,bool*,QTextCursor*)));
1096 connect(handler, SIGNAL(indentRegion(int,int,QChar)),
1097 SLOT(indentRegion(int,int,QChar)));
1098 connect(handler, SIGNAL(checkForElectricCharacter(bool*,QChar)),
1099 SLOT(checkForElectricCharacter(bool*,QChar)));
1100 connect(handler, SIGNAL(requestSetBlockSelection(bool)),
1101 SLOT(setBlockSelection(bool)));
1102 connect(handler, SIGNAL(requestHasBlockSelection(bool*)),
1103 SLOT(hasBlockSelection(bool*)));
1104 connect(handler, SIGNAL(completionRequested()),
1105 SLOT(triggerCompletions()));
1106 connect(handler, SIGNAL(simpleCompletionRequested(QString,bool)),
1107 SLOT(triggerSimpleCompletions(QString,bool)));
1108 connect(handler, SIGNAL(windowCommandRequested(int)),
1109 SLOT(windowCommand(int)));
1110 connect(handler, SIGNAL(findRequested(bool)),
1112 connect(handler, SIGNAL(findNextRequested(bool)),
1113 SLOT(findNext(bool)));
1115 connect(handler, SIGNAL(handleExCommandRequested(bool*,ExCommand)),
1116 SLOT(handleExCommand(bool*,ExCommand)));
1118 connect(core(), SIGNAL(saveSettingsRequested()),
1119 SLOT(writeSettings()));
1121 handler->setCurrentFileName(editor->file()->fileName());
1122 handler->installEventFilter();
1125 if (theFakeVimSetting(ConfigUseFakeVim)->value().toBool()) {
1126 showCommandBuffer(QString());
1127 handler->setupWidget();
1131 void FakeVimPluginPrivate::editorAboutToClose(Core::IEditor *editor)
1133 //qDebug() << "CLOSING: " << editor << editor->widget();
1134 m_editorToHandler.remove(editor);
1137 void FakeVimPluginPrivate::setUseFakeVim(const QVariant &value)
1139 //qDebug() << "SET USE FAKEVIM" << value;
1140 bool on = value.toBool();
1141 if (Find::FindPlugin::instance())
1142 Find::FindPlugin::instance()->setUseFakeVim(on);
1144 //ICore *core = ICore::instance();
1145 //core->updateAdditionalContexts(Core::Context(FAKEVIM_CONTEXT),
1146 // Core::Context());
1147 foreach (Core::IEditor *editor, m_editorToHandler.keys())
1148 m_editorToHandler[editor]->setupWidget();
1150 //ICore *core = ICore::instance();
1151 //core->updateAdditionalContexts(Core::Context(),
1152 // Core::Context(FAKEVIM_CONTEXT));
1153 showCommandBuffer(QString());
1154 foreach (Core::IEditor *editor, m_editorToHandler.keys()) {
1155 if (TextEditor::BaseTextEditorWidget *textEditor =
1156 qobject_cast<TextEditor::BaseTextEditorWidget *>(editor->widget())) {
1157 m_editorToHandler[editor]->restoreWidget(textEditor->tabSettings().m_tabSize);
1163 void FakeVimPluginPrivate::triggerCompletions()
1165 FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
1168 if (BaseTextEditorWidget *editor = qobject_cast<BaseTextEditorWidget *>(handler->widget()))
1169 CompletionSupport::instance()->
1170 complete(editor->editor(), TextCompletion, false);
1171 // editor->triggerCompletions();
1174 void FakeVimPluginPrivate::triggerSimpleCompletions(const QString &needle,
1177 m_wordCompletion->setActive(needle, forward,
1178 qobject_cast<FakeVimHandler *>(sender()));
1181 void FakeVimPluginPrivate::setBlockSelection(bool on)
1183 FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
1186 if (BaseTextEditorWidget *bt = qobject_cast<BaseTextEditorWidget *>(handler->widget()))
1187 bt->setBlockSelection(on);
1190 void FakeVimPluginPrivate::hasBlockSelection(bool *on)
1192 FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
1195 if (BaseTextEditorWidget *bt = qobject_cast<BaseTextEditorWidget *>(handler->widget()))
1196 *on = bt->hasBlockSelection();
1199 void FakeVimPluginPrivate::checkForElectricCharacter(bool *result, QChar c)
1201 FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
1204 if (BaseTextEditorWidget *bt = qobject_cast<BaseTextEditorWidget *>(handler->widget()))
1205 *result = bt->indenter()->isElectricCharacter(c);
1208 void FakeVimPluginPrivate::handleExCommand(bool *handled, const ExCommand &cmd)
1210 using namespace Core;
1211 //qDebug() << "PLUGIN HANDLE: " << cmd.cmd << cmd.count;
1215 FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
1219 QTC_ASSERT(editorManager(), return);
1222 if (cmd.matches("w", "write") || cmd.cmd == "wq") {
1224 Core::IEditor *editor = m_editorToHandler.key(handler);
1225 const QString fileName = handler->currentFileName();
1226 if (editor && editor->file()->fileName() == fileName) {
1227 // Handle that as a special case for nicer interaction with core
1228 Core::IFile *file = editor->file();
1229 Core::ICore::instance()->fileManager()->blockFileChange(file);
1230 file->save(fileName);
1231 Core::ICore::instance()->fileManager()->unblockFileChange(file);
1232 // Check result by reading back.
1233 QFile file3(fileName);
1234 file3.open(QIODevice::ReadOnly);
1235 QByteArray ba = file3.readAll();
1236 handler->showBlackMessage(FakeVimHandler::tr("\"%1\" %2 %3L, %4C written")
1237 .arg(fileName).arg(" ")
1238 .arg(ba.count('\n')).arg(ba.size()));
1239 if (cmd.cmd == "wq")
1240 delayedQuitRequested(cmd.hasBang, m_editorToHandler.key(handler));
1242 handler->showRedMessage(tr("File not saved"));
1244 } else if (cmd.matches("wa", "wall")) {
1246 FileManager *fm = ICore::instance()->fileManager();
1247 QList<IFile *> toSave = fm->modifiedFiles();
1248 QList<IFile *> failed = fm->saveModifiedFilesSilently(toSave);
1249 if (failed.isEmpty())
1250 handler->showBlackMessage(tr("Saving succeeded"));
1252 handler->showRedMessage(tr("%n files not saved", 0, failed.size()));
1253 } else if (cmd.matches("q", "quit")) {
1255 emit delayedQuitRequested(cmd.hasBang, m_editorToHandler.key(handler));
1256 } else if (cmd.matches("qa", "qall")) {
1258 emit delayedQuitAllRequested(cmd.hasBang);
1259 } else if (cmd.matches("sp", "split")) {
1261 triggerAction(Core::Constants::SPLIT);
1262 } else if (cmd.matches("vs", "vsplit")) {
1264 triggerAction(Core::Constants::SPLIT_SIDE_BY_SIDE);
1265 } else if (cmd.matches("mak", "make")) {
1266 // :mak[e][!] [arguments]
1267 triggerAction(ProjectExplorer::Constants::BUILD);
1268 } else if (cmd.matches("se", "set")) {
1269 if (cmd.args.isEmpty()) {
1271 showSettingsDialog();
1272 } else if (cmd.args == "ic" || cmd.args == "ignorecase") {
1274 setActionChecked(Find::Constants::CASE_SENSITIVE, false);
1275 } else if (cmd.args == "noic" || cmd.args == "noignorecase") {
1277 setActionChecked(Find::Constants::CASE_SENSITIVE, true);
1279 *handled = false; // Let the handler see it as well.
1281 } else if (cmd.matches("n", "next")) {
1283 switchToFile(currentFile() + cmd.count);
1284 } else if (cmd.matches("prev", "previous") || cmd.matches("N", "Next")) {
1285 // :prev[ious], :N[ext]
1286 switchToFile(currentFile() - cmd.count);
1287 } else if (cmd.matches("bn", "bnext")) {
1289 switchToFile(currentFile() + cmd.count);
1290 } else if (cmd.matches("bp", "bprevious") || cmd.matches("bN", "bNext")) {
1291 // :bp[revious], :bN[ext]
1292 switchToFile(currentFile() - cmd.count);
1293 } else if (cmd.matches("on", "only")) {
1295 //triggerAction(Core::Constants::REMOVE_ALL_SPLITS);
1296 triggerAction(Core::Constants::REMOVE_CURRENT_SPLIT);
1298 // Check whether one of the configure commands matches.
1299 typedef CommandMap::const_iterator Iterator;
1300 const Iterator end = exCommandMap().constEnd();
1301 for (Iterator it = exCommandMap().constBegin(); it != end; ++it) {
1302 const QString &id = it.key();
1303 const QRegExp &re = it.value();
1304 if (!re.pattern().isEmpty() && re.indexIn(cmd.cmd) != -1) {
1313 void FakeVimPluginPrivate::handleDelayedQuit(bool forced, Core::IEditor *editor)
1315 // This tries to simulate vim behaviour. But the models of vim and
1316 // Qt Creator core do not match well...
1317 if (editorManager()->hasSplitter()) {
1318 triggerAction(Core::Constants::REMOVE_CURRENT_SPLIT);
1320 QList<Core::IEditor *> editors;
1321 editors.append(editor);
1322 editorManager()->closeEditors(editors, !forced);
1326 void FakeVimPluginPrivate::handleDelayedQuitAll(bool forced)
1328 triggerAction(Core::Constants::REMOVE_ALL_SPLITS);
1329 editorManager()->closeAllEditors(!forced);
1332 void FakeVimPluginPrivate::moveToMatchingParenthesis(bool *moved, bool *forward,
1333 QTextCursor *cursor)
1337 bool undoFakeEOL = false;
1338 if (cursor->atBlockEnd() && cursor->block().length() > 1) {
1339 cursor->movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, 1);
1342 TextBlockUserData::MatchType match
1343 = TextBlockUserData::matchCursorForward(cursor);
1344 if (match == TextBlockUserData::Match) {
1349 cursor->movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 1);
1350 if (match == TextBlockUserData::NoMatch) {
1351 // Backward matching is according to the character before the cursor.
1352 bool undoMove = false;
1353 if (!cursor->atBlockEnd()) {
1354 cursor->movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 1);
1357 match = TextBlockUserData::matchCursorBackward(cursor);
1358 if (match == TextBlockUserData::Match) {
1361 } else if (undoMove) {
1362 cursor->movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, 1);
1368 void FakeVimPluginPrivate::indentRegion(int beginLine, int endLine,
1371 FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
1375 BaseTextEditorWidget *bt = qobject_cast<BaseTextEditorWidget *>(handler->widget());
1379 const TabSettings oldTabSettings = bt->tabSettings();
1380 TabSettings tabSettings;
1381 tabSettings.m_indentSize = theFakeVimSetting(ConfigShiftWidth)->value().toInt();
1382 tabSettings.m_tabSize = theFakeVimSetting(ConfigTabStop)->value().toInt();
1383 tabSettings.m_spacesForTabs = theFakeVimSetting(ConfigExpandTab)->value().toBool();
1384 bt->setTabSettings(tabSettings);
1386 QTextDocument *doc = bt->document();
1387 QTextBlock startBlock = doc->findBlockByNumber(beginLine);
1389 // Record line lenghts for mark adjustments
1390 QVector<int> lineLengths(endLine - beginLine + 1);
1391 QTextBlock block = startBlock;
1393 for (int i = beginLine; i <= endLine; ++i) {
1394 lineLengths[i - beginLine] = block.text().length();
1395 if (typedChar == 0 && block.text().simplified().isEmpty()) {
1396 // clear empty lines
1397 QTextCursor cursor(block);
1398 while (!cursor.atBlockEnd())
1399 cursor.deleteChar();
1401 bt->indenter()->indentBlock(doc, block, typedChar, bt);
1403 block = block.next();
1406 bt->setTabSettings(oldTabSettings);
1409 void FakeVimPluginPrivate::quitFakeVim()
1411 theFakeVimSetting(ConfigUseFakeVim)->setValue(false);
1414 void FakeVimPluginPrivate::showCommandBuffer(const QString &contents)
1416 //qDebug() << "SHOW COMMAND BUFFER" << contents;
1417 if (QLabel *label = qobject_cast<QLabel *>(m_statusBar->widget()))
1418 label->setText(" " + contents);
1421 void FakeVimPluginPrivate::showExtraInformation(const QString &text)
1423 FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
1425 QMessageBox::information(handler->widget(), tr("FakeVim Information"), text);
1428 void FakeVimPluginPrivate::changeSelection
1429 (const QList<QTextEdit::ExtraSelection> &selection)
1431 if (FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender()))
1432 if (BaseTextEditorWidget *bt = qobject_cast<BaseTextEditorWidget *>(handler->widget()))
1433 bt->setExtraSelections(BaseTextEditorWidget::FakeVimSelection, selection);
1436 int FakeVimPluginPrivate::currentFile() const
1438 Core::OpenEditorsModel *model = editorManager()->openedEditorsModel();
1439 IEditor *editor = editorManager()->currentEditor();
1440 return model->indexOf(editor).row();
1443 void FakeVimPluginPrivate::switchToFile(int n)
1445 Core::OpenEditorsModel *model = editorManager()->openedEditorsModel();
1446 int size = model->rowCount();
1447 QTC_ASSERT(size, return);
1451 editorManager()->activateEditorForIndex(model->index(n, 0));
1454 CommandMap &FakeVimExCommandsPage::exCommandMap()
1456 return m_q->exCommandMap();
1459 CommandMap &FakeVimExCommandsPage::defaultExCommandMap()
1461 return m_q->defaultExCommandMap();
1464 ///////////////////////////////////////////////////////////////////////
1468 ///////////////////////////////////////////////////////////////////////
1470 FakeVimPlugin::FakeVimPlugin()
1471 : d(new FakeVimPluginPrivate(this))
1474 FakeVimPlugin::~FakeVimPlugin()
1479 bool FakeVimPlugin::initialize(const QStringList &arguments, QString *errorMessage)
1482 Q_UNUSED(errorMessage)
1483 return d->initialize();
1486 ExtensionSystem::IPlugin::ShutdownFlag FakeVimPlugin::aboutToShutdown()
1488 d->aboutToShutdown();
1489 return SynchronousShutdown;
1492 void FakeVimPlugin::extensionsInitialized()
1494 d->m_statusBar = new Core::StatusBarWidget;
1495 d->m_statusBar->setWidget(new QLabel);
1496 //d->m_statusBar->setContext(Context(FAKEVIM_CONTEXT));
1497 d->m_statusBar->setPosition(StatusBarWidget::Last);
1498 addAutoReleasedObject(d->m_statusBar);
1501 } // namespace Internal
1502 } // namespace FakeVim
1504 #include "fakevimplugin.moc"
1506 Q_EXPORT_PLUGIN(FakeVimPlugin)