From a4e34a804af1aef8983a70784efddbfa3bfa9e02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Aum=C3=BCller?= <aumuell@reserv.at> Date: Fri, 22 Jan 2010 13:56:50 +0100 Subject: [PATCH] fakevim: make sure that FakeVimHandler has returned before being deleted some actions might cause the parent editor to be deleted, don't crash in that case Merge-request: 101 Reviewed-by: hjk <qtc-committer@nokia.com> --- src/plugins/fakevim/fakevimhandler.cpp | 35 ++++++++++++++++++-------- src/plugins/fakevim/fakevimhandler.h | 3 +++ src/plugins/fakevim/fakevimplugin.cpp | 29 ++++++++++++++++++++- 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index f4626e0a922..941718d3eeb 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -662,17 +662,20 @@ EventResult FakeVimHandler::Private::handleEvent(QKeyEvent *ev) EventResult result = handleKey(key, um, ev->text()); //endEditBlock(); - // We fake vi-style end-of-line behaviour - m_fakeEnd = atEndOfLine() && m_mode == CommandMode && !isVisualBlockMode(); + // the command might have destroyed the editor + if (m_textedit || m_plaintextedit) { + // We fake vi-style end-of-line behaviour + m_fakeEnd = atEndOfLine() && m_mode == CommandMode && !isVisualBlockMode(); - QTC_ASSERT(!(m_mode != InsertMode && m_tc.atBlockEnd() && m_tc.block().length() > 1), - qDebug() << "Cursor at EOL after key handler"); + QTC_ASSERT(!(m_mode != InsertMode && m_tc.atBlockEnd() && m_tc.block().length() > 1), + qDebug() << "Cursor at EOL after key handler"); - if (m_fakeEnd) - moveLeft(); + if (m_fakeEnd) + moveLeft(); - EDITOR(setTextCursor(m_tc)); - m_oldPosition = m_tc.position(); + EDITOR(setTextCursor(m_tc)); + m_oldPosition = m_tc.position(); + } return result; } @@ -1033,6 +1036,9 @@ void FakeVimHandler::Private::updateSelection() void FakeVimHandler::Private::updateMiniBuffer() { + if (!m_textedit && !m_plaintextedit) + return; + QString msg; if (m_passing) { msg = "-- PASSING -- "; @@ -2060,8 +2066,10 @@ EventResult FakeVimHandler::Private::handleMiniBufferModes(int key, int unmodifi m_commandHistory.append(m_commandBuffer); EDITOR(setTextCursor(m_tc)); handleExCommand(m_commandBuffer); - m_tc = EDITOR(textCursor()); - leaveVisualMode(); + if (m_textedit || m_plaintextedit) { + m_tc = EDITOR(textCursor()); + leaveVisualMode(); + } } } else if (unmodified == Key_Return && isSearchMode()) { if (!m_commandBuffer.isEmpty()) { @@ -3428,6 +3436,13 @@ FakeVimHandler::~FakeVimHandler() delete d; } +// gracefully handle that the parent editor is deleted +void FakeVimHandler::disconnectFromEditor() +{ + d->m_textedit = 0; + d->m_plaintextedit = 0; +} + bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev) { bool active = theFakeVimSetting(ConfigUseFakeVim)->value().toBool(); diff --git a/src/plugins/fakevim/fakevimhandler.h b/src/plugins/fakevim/fakevimhandler.h index 8620aadb16f..59e5c85b1d0 100644 --- a/src/plugins/fakevim/fakevimhandler.h +++ b/src/plugins/fakevim/fakevimhandler.h @@ -48,6 +48,9 @@ public: QWidget *widget(); + // call before widget is deleted + void disconnectFromEditor(); + public slots: void setCurrentFileName(const QString &fileName); void showBlackMessage(const QString &msg); diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 97e9d5db4c5..178440b1363 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -744,6 +744,30 @@ void FakeVimPluginPrivate::findNext(bool reverse) triggerAction(Find::Constants::FIND_NEXT); } +// this class defers deletion of a child FakeVimHandler using 'deleteLater' +// - direct children QObject's would be 'delete'ed immediately before their parents +class DeferredDeleter : public QObject +{ + Q_OBJECT + + FakeVimHandler *m_handler; + +public: + DeferredDeleter(QObject *parent, FakeVimHandler *handler) + : QObject(parent) + , m_handler(handler) + {} + + virtual ~DeferredDeleter() + { + if (m_handler) { + m_handler->disconnectFromEditor(); + m_handler->deleteLater(); + m_handler = 0; + } + } +}; + void FakeVimPluginPrivate::editorOpened(Core::IEditor *editor) { if (!editor) @@ -760,7 +784,10 @@ void FakeVimPluginPrivate::editorOpened(Core::IEditor *editor) //qDebug() << "OPENING: " << editor << editor->widget() // << "MODE: " << theFakeVimSetting(ConfigUseFakeVim)->value(); - FakeVimHandler *handler = new FakeVimHandler(widget, widget); + FakeVimHandler *handler = new FakeVimHandler(widget, 0); + // the handler might have triggered the deletion of the editor: + // make sure that it can return before being deleted itself + new DeferredDeleter(widget, handler); m_editorToHandler[editor] = handler; connect(handler, SIGNAL(extraInformationChanged(QString)), -- GitLab