From de518abff53ad5216f471272b4b3e01dbf442aeb Mon Sep 17 00:00:00 2001 From: Stefan Schimanski Date: Tue, 4 Mar 2008 12:44:48 +0000 Subject: [PATCH] * even setModel can trigger focus events. So move also those into asynchronous handlers. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23438 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/frontends/qt4/GuiCompleter.cpp | 48 ++++++++++++++++++++++-------- src/frontends/qt4/GuiCompleter.h | 11 +++++-- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/frontends/qt4/GuiCompleter.cpp b/src/frontends/qt4/GuiCompleter.cpp index f5a51fd24d..67f6222d8d 100644 --- a/src/frontends/qt4/GuiCompleter.cpp +++ b/src/frontends/qt4/GuiCompleter.cpp @@ -173,7 +173,8 @@ private: GuiCompleter::GuiCompleter(GuiWorkArea * gui, QObject * parent) : QCompleter(parent), gui_(gui), updateLock_(0), - inlineVisible_(false), popupVisible_(false) + inlineVisible_(false), popupVisible_(false), + modelActive_(false) { // Setup the completion popup setModel(new GuiCompletionModel(this, 0)); @@ -250,6 +251,9 @@ bool GuiCompleter::inlinePossible(Cursor const & cur) const bool GuiCompleter::completionAvailable() const { + if (!modelActive_) + return false; + size_t n = popup()->model()->rowCount(); // if there is exactly one, we have to check whether it is a @@ -308,7 +312,7 @@ void GuiCompleter::updateVisibility(Cursor & cur, bool start, bool keep, bool cu inline_timer_.start(int(lyxrc.completion_inline_delay * 1000)); // update prefix if any completion is possible - bool modelActive = model()->rowCount() > 0; + bool modelActive = modelActive_ && model()->rowCount() > 0; if (possiblePopupState || possibleInlineState) { if (modelActive) updatePrefix(cur); @@ -402,14 +406,11 @@ void GuiCompleter::updatePopup(Cursor & cur) return; } - // show asynchronously to avoid lookups before the metrics - // have been computed. This can happen because we might be in - // the middle of a dispatch. - QTimer::singleShot(0, this, SLOT(asyncCompletePopup())); + QTimer::singleShot(0, this, SLOT(asyncUpdatePopup())); } -void GuiCompleter::asyncCompletePopup() +void GuiCompleter::asyncUpdatePopup() { Cursor cur = gui_->bufferView().cursor(); if (!cur.inset().completionSupported(cur)) { @@ -482,6 +483,7 @@ void GuiCompleter::updateModel(Cursor & cur, bool popupUpdate, bool inlineUpdate // set new model Inset::CompletionList const * list = cur.inset().createCompletionList(cur); setModel(new GuiCompletionModel(this, list)); + modelActive_ = true; if (list->sorted()) setModelSorting(QCompleter::CaseSensitivelySortedModel); else @@ -527,17 +529,26 @@ void GuiCompleter::showPopup(Cursor & cur) void GuiCompleter::hidePopup(Cursor & cur) { popupVisible_ = false; - + + if (popup_timer_.isActive()) + popup_timer_.stop(); + // hide popup asynchronously because we might be here inside of // LFUN dispatchers. Hiding a popup can trigger a focus event on the // workarea which then redisplays the cursor. But the metrics are not // yet up to date such that the coord cache has not all insets yet. The // cursorPos methods would triggers asserts in the coord cache then. - QTimer::singleShot(0, popup(), SLOT(hide())); - - if (popup_timer_.isActive()) - popup_timer_.stop(); + QTimer::singleShot(0, this, SLOT(asyncHidePopup())); + // mark that the asynchronous part will reset the model + if (!inlineVisible()) + modelActive_ = false; +} + + +void GuiCompleter::asyncHidePopup() +{ + popup()->hide(); if (!inlineVisible()) setModel(new GuiCompletionModel(this, 0)); } @@ -560,6 +571,19 @@ void GuiCompleter::hideInline(Cursor & cur) if (inline_timer_.isActive()) inline_timer_.stop(); + // Trigger asynchronous part of hideInline. We might be + // in a dispatcher here and the setModel call might + // trigger focus events which is are not healthy here. + QTimer::singleShot(0, this, SLOT(asyncHideModel())); + + // mark that the asynchronous part will reset the model + if (!popupVisible()) + modelActive_ = false; +} + + +void GuiCompleter::asyncHideInline() +{ if (!popupVisible()) setModel(new GuiCompletionModel(this, 0)); } diff --git a/src/frontends/qt4/GuiCompleter.h b/src/frontends/qt4/GuiCompleter.h index 7cb87535a0..1ab2376bfa 100644 --- a/src/frontends/qt4/GuiCompleter.h +++ b/src/frontends/qt4/GuiCompleter.h @@ -88,8 +88,12 @@ private Q_SLOTS: void popupHighlighted(const QString & completion); /// void updateAvailability(); - /// - void asyncCompletePopup(); + /// the asynchronous part of updatePopup(cur) + void asyncUpdatePopup(); + /// the asynchronous part of hidePopup(cur) + void asyncHidePopup(); + /// the asynchronous part of hideInline(cur) + void asyncHideInline(); private: /// @@ -131,6 +135,9 @@ private: bool inlineVisible_; /// bool popupVisible_; + /// the model reset is asynchronous in hidePopup/Inline. So let's mark + /// a coming reset here by setting it to false. + bool modelActive_; /// RtlItemDelegate * rtlItemDelegate_; }; // GuiCompleter -- 2.39.2