Fixes: fakevim: use one handler per editor

This commit is contained in:
hjk
2009-01-23 15:12:04 +01:00
parent 5d0e277bc3
commit 02ea86b5c2
4 changed files with 205 additions and 153 deletions

View File

@@ -45,6 +45,7 @@
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QObject>
#include <QtCore/QPointer>
#include <QtCore/QProcess>
#include <QtCore/QRegExp>
#include <QtCore/QTextStream>
@@ -166,11 +167,14 @@ int lineCount(const QString &text)
class FakeVimHandler::Private
{
public:
Private(FakeVimHandler *parent);
Private(FakeVimHandler *parent, QWidget *widget);
bool handleEvent(QKeyEvent *ev);
void handleExCommand(const QString &cmd);
void setupWidget();
void restoreWidget();
private:
friend class FakeVimHandler;
static int shift(int key) { return key + 32; }
@@ -238,7 +242,6 @@ private:
int readLineCode(QString &cmd);
void selectRange(int beginLine, int endLine);
void setWidget(QWidget *ob);
void enterInsertMode();
void enterCommandMode();
void showRedMessage(const QString &msg);
@@ -328,12 +331,17 @@ public:
// for restoring cursor position
int m_savedYankPosition;
int m_desiredColumn;
QPointer<QObject> m_extraData;
};
FakeVimHandler::Private::Private(FakeVimHandler *parent)
FakeVimHandler::Private::Private(FakeVimHandler *parent, QWidget *widget)
{
q = parent;
m_textedit = qobject_cast<QTextEdit *>(widget);
m_plaintextedit = qobject_cast<QPlainTextEdit *>(widget);
m_mode = CommandMode;
m_submode = NoSubMode;
m_subsubmode = NoSubSubMode;
@@ -341,8 +349,6 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent)
m_lastSearchForward = true;
m_register = '"';
m_gflag = false;
m_textedit = 0;
m_plaintextedit = 0;
m_visualMode = NoVisualMode;
m_desiredColumn = 0;
m_moveType = MoveInclusive;
@@ -403,6 +409,37 @@ bool FakeVimHandler::Private::handleEvent(QKeyEvent *ev)
return handled;
}
void FakeVimHandler::Private::setupWidget()
{
enterCommandMode();
if (m_textedit) {
m_textedit->installEventFilter(q);
//m_textedit->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x')));
m_textedit->setLineWrapMode(QTextEdit::NoWrap);
m_wasReadOnly = m_textedit->isReadOnly();
} else if (m_plaintextedit) {
m_plaintextedit->installEventFilter(q);
//plaintextedit->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x')));
m_plaintextedit->setLineWrapMode(QPlainTextEdit::NoWrap);
m_wasReadOnly = m_plaintextedit->isReadOnly();
}
showBlackMessage("vi emulation mode.");
updateMiniBuffer();
}
void FakeVimHandler::Private::restoreWidget()
{
//showBlackMessage(QString());
//updateMiniBuffer();
if (m_textedit) {
m_textedit->removeEventFilter(q);
m_textedit->setReadOnly(m_wasReadOnly);
} else if (m_plaintextedit) {
m_plaintextedit->removeEventFilter(q);
m_plaintextedit->setReadOnly(m_wasReadOnly);
}
}
bool FakeVimHandler::Private::handleKey(int key, int unmodified, const QString &text)
{
//qDebug() << "KEY: " << key << text << "POS: " << m_tc.position();
@@ -529,7 +566,7 @@ void FakeVimHandler::Private::updateSelection()
}
}
}
emit q->selectionChanged(editor(), selections);
emit q->selectionChanged(selections);
}
void FakeVimHandler::Private::updateMiniBuffer()
@@ -1329,7 +1366,7 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
beginLine = 0;
if (endLine == -1)
endLine = linesInDocument();
//qDebug() << "LINES: " << beginLine << endLine;
qDebug() << "LINES: " << beginLine << endLine;
bool forced = cmd.startsWith("w!");
QString fileName = reWrite.cap(2);
if (fileName.isEmpty())
@@ -1339,9 +1376,20 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
if (exists && !forced && !noArgs) {
showRedMessage(tr("File '%1' exists (add ! to override)").arg(fileName));
} else if (file.open(QIODevice::ReadWrite)) {
file.close();
selectRange(beginLine, endLine);
emit q->writeFile(fileName, selectedText());
// check by reading back
QString contents = selectedText();
bool handled = false;
emit q->writeFileRequested(&handled, fileName, contents);
// nobody cared, so act ourselves
if (!handled) {
qDebug() << "HANDLING MANUAL SAVE";
QFile file(fileName);
file.open(QIODevice::ReadWrite);
{ QTextStream ts(&file); ts << contents; }
file.close();
}
// check result by reading back
file.open(QIODevice::ReadOnly);
QByteArray ba = file.readAll();
showBlackMessage(tr("\"%1\" %2 %3L, %4C written")
@@ -1401,7 +1449,7 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
QString info;
foreach (const QString &key, m_config.keys())
info += key + ": " + m_config.value(key) + "\n";
emit q->extraInformationChanged(editor(), info);
emit q->extraInformationChanged(info);
} else {
notImplementedYet();
}
@@ -1417,7 +1465,7 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
++i;
info += QString("%1 %2\n").arg(i, -8).arg(item);
}
emit q->extraInformationChanged(editor(), info);
emit q->extraInformationChanged(info);
} else {
notImplementedYet();
}
@@ -1735,7 +1783,9 @@ QString FakeVimHandler::Private::selectedText() const
{
QTextCursor tc = m_tc;
tc.setPosition(m_anchor, KeepAnchor);
return tc.selection().toPlainText();
QString text = tc.selection().toPlainText();
tc.clearSelection();
return text;
}
int FakeVimHandler::Private::positionForLine(int line) const
@@ -1942,16 +1992,10 @@ void FakeVimHandler::Private::enterCommandMode()
void FakeVimHandler::Private::quit()
{
showBlackMessage(QString());
EDITOR(setOverwriteMode(false));
q->quitRequested(editor());
q->quitRequested();
}
void FakeVimHandler::Private::setWidget(QWidget *ob)
{
m_textedit = qobject_cast<QTextEdit *>(ob);
m_plaintextedit = qobject_cast<QPlainTextEdit *>(ob);
}
///////////////////////////////////////////////////////////////////////
//
@@ -1959,12 +2003,13 @@ void FakeVimHandler::Private::setWidget(QWidget *ob)
//
///////////////////////////////////////////////////////////////////////
FakeVimHandler::FakeVimHandler(QObject *parent)
: QObject(parent), d(new Private(this))
FakeVimHandler::FakeVimHandler(QWidget *widget, QObject *parent)
: QObject(parent), d(new Private(this, widget))
{}
FakeVimHandler::~FakeVimHandler()
{
qDebug() << "DELETING HANDLER" << this;
delete d;
}
@@ -1993,40 +2038,18 @@ bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev)
return QObject::eventFilter(ob, ev);
}
void FakeVimHandler::addWidget(QWidget *widget)
void FakeVimHandler::setupWidget()
{
widget->installEventFilter(this);
d->setWidget(widget);
d->enterCommandMode();
if (QTextEdit *ed = qobject_cast<QTextEdit *>(widget)) {
//ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x')));
ed->setLineWrapMode(QTextEdit::NoWrap);
d->m_wasReadOnly = ed->isReadOnly();
} else if (QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(widget)) {
//ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x')));
ed->setLineWrapMode(QPlainTextEdit::NoWrap);
d->m_wasReadOnly = ed->isReadOnly();
}
d->showBlackMessage("vi emulation mode.");
d->updateMiniBuffer();
d->setupWidget();
}
void FakeVimHandler::removeWidget(QWidget *widget)
void FakeVimHandler::restoreWidget()
{
d->setWidget(widget);
d->showBlackMessage(QString());
d->updateMiniBuffer();
widget->removeEventFilter(this);
if (QTextEdit *ed = qobject_cast<QTextEdit *>(widget)) {
ed->setReadOnly(d->m_wasReadOnly);
} else if (QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(widget)) {
ed->setReadOnly(d->m_wasReadOnly);
}
d->restoreWidget();
}
void FakeVimHandler::handleCommand(QWidget *widget, const QString &cmd)
void FakeVimHandler::handleCommand(const QString &cmd)
{
d->setWidget(widget);
d->handleExCommand(cmd);
}
@@ -2044,3 +2067,19 @@ void FakeVimHandler::setCurrentFileName(const QString &fileName)
{
d->m_currentFileName = fileName;
}
QWidget *FakeVimHandler::widget()
{
return d->editor();
}
void FakeVimHandler::setExtraData(QObject *data)
{
d->m_extraData = data;
}
QObject *FakeVimHandler::extraData() const
{
return d->m_extraData;
}

View File

@@ -50,30 +50,35 @@ class FakeVimHandler : public QObject
Q_OBJECT
public:
FakeVimHandler(QObject *parent = 0);
FakeVimHandler(QWidget *widget, QObject *parent = 0);
~FakeVimHandler();
QWidget *widget();
void setExtraData(QObject *data);
QObject *extraData() const;
public slots:
// The same handler can be installed on several widgets
// FIXME: good idea?
void addWidget(QWidget *widget);
void removeWidget(QWidget *widget);
void setCurrentFileName(const QString &fileName);
// This executes an "ex" style command taking context
// information from \p widget;
void handleCommand(QWidget *widget, const QString &cmd);
void quit();
// information from widget;
void handleCommand(const QString &cmd);
void setConfigValue(const QString &key, const QString &value);
void quit();
// Convenience
void setupWidget();
void restoreWidget();
signals:
void commandBufferChanged(const QString &msg);
void statusDataChanged(const QString &msg);
void extraInformationChanged(QWidget *widget, const QString &msg);
void quitRequested(QWidget *widget);
void selectionChanged(QWidget *widget,
const QList<QTextEdit::ExtraSelection> &selection);
void writeFile(const QString &fileName, const QString &contents);
void extraInformationChanged(const QString &msg);
void quitRequested();
void selectionChanged(const QList<QTextEdit::ExtraSelection> &selection);
void writeFileRequested(bool *handled,
const QString &fileName, const QString &contents);
private:
bool eventFilter(QObject *ob, QEvent *ev);

View File

@@ -106,27 +106,26 @@ public:
~FakeVimPluginPrivate();
friend class FakeVimPlugin;
bool initialize(const QStringList &arguments, QString *error_message);
bool initialize();
void shutdown();
private slots:
void installHandler();
void installHandler(QWidget *widget);
void removeHandler(QWidget *widget);
void showCommandBuffer(const QString &contents);
void showExtraInformation(QWidget *, const QString &msg);
void editorOpened(Core::IEditor *);
void editorAboutToClose(Core::IEditor *);
void changeSelection(QWidget *widget,
const QList<QTextEdit::ExtraSelection> &selections);
void writeFile(const QString &fileName, const QString &contents);
void installHandler();
void installHandler(Core::IEditor *editor);
void removeHandler();
void showCommandBuffer(const QString &contents);
void showExtraInformation(const QString &msg);
void changeSelection(const QList<QTextEdit::ExtraSelection> &selections);
void writeFile(bool *handled, const QString &fileName, const QString &contents);
private:
FakeVimPlugin *q;
FakeVimHandler *m_handler;
QAction *m_installHandlerAction;
Core::ICore *m_core;
Core::IFile *m_currentFile;
};
} // namespace Internal
@@ -135,10 +134,8 @@ private:
FakeVimPluginPrivate::FakeVimPluginPrivate(FakeVimPlugin *plugin)
{
q = plugin;
m_handler = 0;
m_installHandlerAction = 0;
m_core = 0;
m_currentFile = 0;
}
FakeVimPluginPrivate::~FakeVimPluginPrivate()
@@ -147,17 +144,10 @@ FakeVimPluginPrivate::~FakeVimPluginPrivate()
void FakeVimPluginPrivate::shutdown()
{
delete m_handler;
m_handler = 0;
}
bool FakeVimPluginPrivate::initialize(const QStringList &arguments, QString *error_message)
bool FakeVimPluginPrivate::initialize()
{
Q_UNUSED(arguments);
Q_UNUSED(error_message);
m_handler = new FakeVimHandler;
m_core = Core::ICore::instance();
QTC_ASSERT(m_core, return false);
@@ -195,102 +185,113 @@ bool FakeVimPluginPrivate::initialize(const QStringList &arguments, QString *err
void FakeVimPluginPrivate::installHandler()
{
if (Core::IEditor *editor = m_core->editorManager()->currentEditor())
installHandler(editor->widget());
installHandler(editor);
}
void FakeVimPluginPrivate::installHandler(QWidget *widget)
void FakeVimPluginPrivate::installHandler(Core::IEditor *editor)
{
connect(m_handler, SIGNAL(extraInformationChanged(QWidget *, QString)),
this, SLOT(showExtraInformation(QWidget *, QString)));
connect(m_handler, SIGNAL(commandBufferChanged(QString)),
QWidget *widget = editor->widget();
FakeVimHandler *handler = new FakeVimHandler(widget, this);
connect(handler, SIGNAL(extraInformationChanged(QString)),
this, SLOT(showExtraInformation(QString)));
connect(handler, SIGNAL(commandBufferChanged(QString)),
this, SLOT(showCommandBuffer(QString)));
connect(m_handler, SIGNAL(quitRequested(QWidget *)),
this, SLOT(removeHandler(QWidget *)));
connect(m_handler,
SIGNAL(selectionChanged(QWidget*,QList<QTextEdit::ExtraSelection>)),
this, SLOT(changeSelection(QWidget*,QList<QTextEdit::ExtraSelection>)));
connect(handler, SIGNAL(quitRequested()),
this, SLOT(removeHandler()), Qt::QueuedConnection);
connect(handler, SIGNAL(writeFileRequested(bool*,QString,QString)),
this, SLOT(writeFile(bool*,QString,QString)));
connect(handler, SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)),
this, SLOT(changeSelection(QList<QTextEdit::ExtraSelection>)));
m_handler->addWidget(widget);
TextEditor::BaseTextEditor* editor =
qobject_cast<TextEditor::BaseTextEditor*>(widget);
if (editor) {
m_currentFile = editor->file();
m_handler->setCurrentFileName(editor->file()->fileName());
}
handler->setupWidget();
handler->setExtraData(editor);
BaseTextEditor *bt = qobject_cast<BaseTextEditor *>(widget);
if (bt) {
if (BaseTextEditor *bt = qobject_cast<BaseTextEditor *>(widget)) {
using namespace TextEditor;
using namespace FakeVim::Constants;
handler->setCurrentFileName(editor->file()->fileName());
TabSettings settings = bt->tabSettings();
m_handler->setConfigValue(ConfigTabStop,
handler->setConfigValue(ConfigTabStop,
QString::number(settings.m_tabSize));
m_handler->setConfigValue(ConfigShiftWidth,
handler->setConfigValue(ConfigShiftWidth,
QString::number(settings.m_indentSize));
m_handler->setConfigValue(ConfigExpandTab,
handler->setConfigValue(ConfigExpandTab,
settings.m_spacesForTabs ? ConfigOn : ConfigOff);
m_handler->setConfigValue(ConfigSmartTab,
handler->setConfigValue(ConfigSmartTab,
settings.m_smartBackspace ? ConfigOn : ConfigOff);
m_handler->setConfigValue(ConfigAutoIndent,
handler->setConfigValue(ConfigAutoIndent,
settings.m_autoIndent ? ConfigOn : ConfigOff);
}
}
void FakeVimPluginPrivate::writeFile(const QString &fileName,
const QString &contents)
void FakeVimPluginPrivate::writeFile(bool *handled,
const QString &fileName, const QString &contents)
{
if (m_currentFile && fileName == m_currentFile->fileName()) {
//qDebug() << "HANDLING WRITE FILE" << fileName << sender();
FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
if (!handler)
return;
Core::IEditor *editor = qobject_cast<Core::IEditor *>(handler->extraData());
if (editor && editor->file()->fileName() == fileName) {
//qDebug() << "HANDLING CORE SAVE";
// Handle that as a special case for nicer interaction with core
m_core->fileManager()->blockFileChange(m_currentFile);
m_currentFile->save(fileName);
m_core->fileManager()->unblockFileChange(m_currentFile);
} else {
QFile file(fileName);
file.open(QIODevice::ReadWrite);
{ QTextStream ts(&file); ts << contents; }
file.close();
Core::IFile *file = editor->file();
m_core->fileManager()->blockFileChange(file);
file->save(fileName);
m_core->fileManager()->unblockFileChange(file);
*handled = true;
}
}
void FakeVimPluginPrivate::removeHandler(QWidget *widget)
void FakeVimPluginPrivate::removeHandler()
{
Q_UNUSED(widget);
m_handler->removeWidget(widget);
if (FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender())) {
handler->restoreWidget();
handler->deleteLater();
}
Core::EditorManager::instance()->hideEditorInfoBar(
QLatin1String(Constants::MINI_BUFFER));
m_currentFile = 0;
}
void FakeVimPluginPrivate::editorOpened(Core::IEditor *editor)
{
Q_UNUSED(editor);
//qDebug() << "OPENING: " << editor << editor->widget();
//installHandler(editor->widget());
installHandler(editor);
}
void FakeVimPluginPrivate::editorAboutToClose(Core::IEditor *editor)
{
//qDebug() << "CLOSING: " << editor << editor->widget();
removeHandler(editor->widget());
Q_UNUSED(editor);
//qDebug() << "CLOSING: " << editor;
}
void FakeVimPluginPrivate::showCommandBuffer(const QString &contents)
{
Core::EditorManager::instance()->showEditorInfoBar(
QLatin1String(Constants::MINI_BUFFER), contents,
tr("Quit FakeVim"), m_handler, SLOT(quit()));
//qDebug() << "SHOW COMMAND BUFFER" << contents;
FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
if (handler) {
Core::EditorManager::instance()->showEditorInfoBar(
QLatin1String(Constants::MINI_BUFFER), contents,
tr("Quit FakeVim"), handler, SLOT(quit()));
}
}
void FakeVimPluginPrivate::showExtraInformation(QWidget *widget, const QString &text)
void FakeVimPluginPrivate::showExtraInformation(const QString &text)
{
QMessageBox::information(widget, tr("FakeVim Information"), text);
FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
if (handler)
QMessageBox::information(handler->widget(), tr("FakeVim Information"), text);
}
void FakeVimPluginPrivate::changeSelection(QWidget *widget,
const QList<QTextEdit::ExtraSelection> &selection)
void FakeVimPluginPrivate::changeSelection
(const QList<QTextEdit::ExtraSelection> &selection)
{
if (BaseTextEditor *bt = qobject_cast<BaseTextEditor *>(widget))
bt->setExtraSelections(BaseTextEditor::FakeVimSelection, selection);
if (FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender()))
if (BaseTextEditor *bt = qobject_cast<BaseTextEditor *>(handler->widget()))
bt->setExtraSelections(BaseTextEditor::FakeVimSelection, selection);
}
@@ -309,9 +310,11 @@ FakeVimPlugin::~FakeVimPlugin()
delete d;
}
bool FakeVimPlugin::initialize(const QStringList &arguments, QString *error_message)
bool FakeVimPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
return d->initialize(arguments, error_message);
Q_UNUSED(arguments);
Q_UNUSED(errorMessage);
return d->initialize();
}
void FakeVimPlugin::shutdown()

View File

@@ -17,21 +17,26 @@ class Proxy : public QObject
Q_OBJECT
public:
Proxy() : QObject(0) {}
Proxy(QWidget *widget, QObject *parent = 0)
: QObject(parent), m_widget(widget)
{}
public slots:
void changeSelection(QWidget *w, const QList<QTextEdit::ExtraSelection> &s)
void changeSelection(const QList<QTextEdit::ExtraSelection> &s)
{
if (QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(w))
if (QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(sender()))
ed->setExtraSelections(s);
else if (QTextEdit *ed = qobject_cast<QTextEdit *>(w))
else if (QTextEdit *ed = qobject_cast<QTextEdit *>(sender()))
ed->setExtraSelections(s);
}
void changeExtraInformation(QWidget *w, const QString &info)
void changeExtraInformation(const QString &info)
{
QMessageBox::information(w, "Information", info);
QMessageBox::information(m_widget, "Information", info);
}
private:
QWidget *m_widget;
};
int main(int argc, char *argv[])
@@ -51,13 +56,13 @@ int main(int argc, char *argv[])
widget = new QTextEdit;
title = "TextEdit";
}
widget->setObjectName("Editor");
widget->resize(450, 350);
widget->setFocus();
Proxy proxy;
Proxy proxy(widget);
FakeVimHandler handler;
FakeVimHandler handler(widget, 0);
QMainWindow mw;
mw.setWindowTitle("Fakevim (" + title + ")");
@@ -77,18 +82,18 @@ int main(int argc, char *argv[])
QObject::connect(&handler, SIGNAL(commandBufferChanged(QString)),
mw.statusBar(), SLOT(showMessage(QString)));
QObject::connect(&handler, SIGNAL(quitRequested(QWidget *)),
QObject::connect(&handler, SIGNAL(quitRequested()),
&app, SLOT(quit()));
QObject::connect(&handler,
SIGNAL(selectionChanged(QWidget*,QList<QTextEdit::ExtraSelection>)),
&proxy, SLOT(changeSelection(QWidget*,QList<QTextEdit::ExtraSelection>)));
SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)),
&proxy, SLOT(changeSelection(QList<QTextEdit::ExtraSelection>)));
QObject::connect(&handler,
SIGNAL(extraInformationChanged(QWidget*,QString)),
&proxy, SLOT(changeExtraInformation(QWidget*,QString)));
SIGNAL(extraInformationChanged(QString)),
&proxy, SLOT(changeExtraInformation(QString)));
handler.addWidget(widget);
handler.setupWidget();
if (args.size() >= 1)
handler.handleCommand(widget, "r " + args.at(0));
handler.handleCommand("r " + args.at(0));
return app.exec();
}