]> git.lyx.org Git - lyx.git/commitdiff
* even setModel can trigger focus events. So move also those into
authorStefan Schimanski <sts@lyx.org>
Tue, 4 Mar 2008 12:44:48 +0000 (12:44 +0000)
committerStefan Schimanski <sts@lyx.org>
Tue, 4 Mar 2008 12:44:48 +0000 (12:44 +0000)
  asynchronous handlers.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23438 a592a061-630c-0410-9148-cb99ea01b6c8

src/frontends/qt4/GuiCompleter.cpp
src/frontends/qt4/GuiCompleter.h

index f5a51fd24dd4b688d3807ba1950cb6302d39e505..67f6222d8d12b8c3f07bda515391fb118edb60a0 100644 (file)
@@ -173,7 +173,8 @@ private:
 
 GuiCompleter::GuiCompleter(GuiWorkArea * gui, QObject * parent)
        : QCompleter(parent), gui_(gui), updateLock_(0),
 
 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));
 {
        // Setup the completion popup
        setModel(new GuiCompletionModel(this, 0));
@@ -250,6 +251,9 @@ bool GuiCompleter::inlinePossible(Cursor const & cur) const
 
 bool GuiCompleter::completionAvailable() 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 
        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
                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);
        if (possiblePopupState || possibleInlineState) {
                if (modelActive)
                        updatePrefix(cur);
@@ -402,14 +406,11 @@ void GuiCompleter::updatePopup(Cursor & cur)
                return;
        }
 
                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)) {
 {
        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));
        // 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
        if (list->sorted())
                setModelSorting(QCompleter::CaseSensitivelySortedModel);
        else
@@ -527,17 +529,26 @@ void GuiCompleter::showPopup(Cursor & cur)
 void GuiCompleter::hidePopup(Cursor & cur)
 {
        popupVisible_ = false;
 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.
        // 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));
 }
        if (!inlineVisible())
                setModel(new GuiCompletionModel(this, 0));
 }
@@ -560,6 +571,19 @@ void GuiCompleter::hideInline(Cursor & cur)
        if (inline_timer_.isActive())
                inline_timer_.stop();
        
        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));
 }
        if (!popupVisible())
                setModel(new GuiCompletionModel(this, 0));
 }
index 7cb87535a09187043bee5e6b3681480d181d519f..1ab2376bfad97c0669fa8efb3d854d0c963eb941 100644 (file)
@@ -88,8 +88,12 @@ private Q_SLOTS:
        void popupHighlighted(const QString & completion);
        ///
        void updateAvailability();
        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:
        ///
        
 private:
        ///
@@ -131,6 +135,9 @@ private:
        bool inlineVisible_;
        ///
        bool popupVisible_;
        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
        ///
        RtlItemDelegate * rtlItemDelegate_;
 }; // GuiCompleter