]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiCompleter.cpp
do what the FIXME suggested
[lyx.git] / src / frontends / qt4 / GuiCompleter.cpp
index 11348e5dcb95fc2c0d27b0637cbd39471080d6f6..0a67bae0beb6a68c319374a3eae0b6953d7b4a86 100644 (file)
@@ -26,7 +26,6 @@
 #include "support/debug.h"
 
 #include <QApplication>
-#include <QAbstractListModel>
 #include <QHeaderView>
 #include <QPainter>
 #include <QPixmapCache>
@@ -44,7 +43,7 @@ namespace frontend {
 class RtlItemDelegate : public QItemDelegate {
 public:
        explicit RtlItemDelegate(QObject * parent = 0)
-               : QItemDelegate(parent) {}
+               : QItemDelegate(parent), enabled_(false) {}
 
        void setEnabled(bool enabled = true)
        {
@@ -56,8 +55,10 @@ protected:
                QStyleOptionViewItem const & option,
                QRect const & rect, QString const & text) const
        {
-               if (!enabled_)
-                       return QItemDelegate::drawDisplay(painter, option, rect, text);
+               if (!enabled_) {
+                       QItemDelegate::drawDisplay(painter, option, rect, text);
+                       return;
+               }
 
                // FIXME: do this more elegantly
                docstring stltext = qstring_to_ucs4(text);
@@ -73,7 +74,7 @@ private:
 class PixmapItemDelegate : public QItemDelegate {
 public:
        explicit PixmapItemDelegate(QObject *parent = 0)
-       : QItemDelegate(parent) {}
+               : QItemDelegate(parent) {}
 
 protected:
        void paint(QPainter *painter, const QStyleOptionViewItem &option,
@@ -101,8 +102,7 @@ protected:
 class GuiCompletionModel : public QAbstractListModel {
 public:
        ///
-       GuiCompletionModel(QObject * parent,
-               Inset::CompletionList const * l)
+       GuiCompletionModel(QObject * parent, Inset::CompletionList const * l)
                : QAbstractListModel(parent), list_(l) {}
        ///
        ~GuiCompletionModel()
@@ -171,7 +171,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));
@@ -188,10 +189,11 @@ GuiCompleter::GuiCompleter(GuiWorkArea * gui, QObject * parent)
        listView->setIndentation(0);
        listView->setUniformRowHeights(true);
        setPopup(listView);
-       popup()->setItemDelegateForColumn(1, new PixmapItemDelegate(this));
+       
        rtlItemDelegate_ = new RtlItemDelegate(this);
        popup()->setItemDelegateForColumn(0, rtlItemDelegate_);
-
+       popup()->setItemDelegateForColumn(1, new PixmapItemDelegate(this));
+       
        // create timeout timers
        popup_timer_.setSingleShot(true);
        inline_timer_.setSingleShot(true);
@@ -247,6 +249,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 
@@ -305,7 +310,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);
@@ -399,14 +404,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)) {
@@ -479,6 +481,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
@@ -524,17 +527,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));
 }
@@ -557,6 +569,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));
 }