]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiCompleter.cpp
fix completion painting for RTL (inline completion and completion list)
[lyx.git] / src / frontends / qt4 / GuiCompleter.cpp
index 0a67bae0beb6a68c319374a3eae0b6953d7b4a86..4b592dcad72961e8f3ed0c4de1aa19f45298442b 100644 (file)
 
 #include <config.h>
 
-#include "GuiWorkArea.h"
+#include "GuiCompleter.h"
 
 #include "Buffer.h"
 #include "BufferView.h"
+#include "CompletionList.h"
 #include "Cursor.h"
 #include "Dimension.h"
 #include "FuncRequest.h"
+#include "GuiWorkArea.h"
 #include "GuiView.h"
 #include "LyXFunc.h"
 #include "LyXRC.h"
 #include "Paragraph.h"
 #include "version.h"
 
+#include "support/lassert.h"
 #include "support/debug.h"
 
 #include <QApplication>
@@ -40,46 +43,31 @@ using namespace lyx::support;
 namespace lyx {
 namespace frontend {
 
-class RtlItemDelegate : public QItemDelegate {
+class CompleterItemDelegate : public QItemDelegate
+{
 public:
-       explicit RtlItemDelegate(QObject * parent = 0)
-               : QItemDelegate(parent), enabled_(false) {}
+       explicit CompleterItemDelegate(QObject * parent)
+               : QItemDelegate(parent)
+       {}
+
+       ~CompleterItemDelegate()
+       {}
 
-       void setEnabled(bool enabled = true)
-       {
-               enabled_ = enabled;
-       }
-       
 protected:
-       virtual void drawDisplay(QPainter * painter,
+       void drawDisplay(QPainter * painter,
                QStyleOptionViewItem const & option,
                QRect const & rect, QString const & text) const
        {
-               if (!enabled_) {
-                       QItemDelegate::drawDisplay(painter, option, rect, text);
-                       return;
-               }
-
-               // FIXME: do this more elegantly
-               docstring stltext = qstring_to_ucs4(text);
-               reverse(stltext.begin(), stltext.end());
-               QItemDelegate::drawDisplay(painter, option, rect, toqstr(stltext));
+               QItemDelegate::drawDisplay(painter, option, rect, text);
        }
-       
-private:
-       bool enabled_;
-};
-
 
-class PixmapItemDelegate : public QItemDelegate {
-public:
-       explicit PixmapItemDelegate(QObject *parent = 0)
-               : QItemDelegate(parent) {}
-
-protected:
        void paint(QPainter *painter, const QStyleOptionViewItem &option,
                   const QModelIndex &index) const
        {
+               if (index.column() == 0) {
+                       QItemDelegate::paint(painter, option, index);
+                       return;
+               }
                QStyleOptionViewItem opt = setOptions(index, option);
                QVariant value = index.data(Qt::DisplayRole);
                QPixmap pixmap = qvariant_cast<QPixmap>(value);
@@ -98,22 +86,27 @@ protected:
        }
 };
 
-
-class GuiCompletionModel : public QAbstractListModel {
+class GuiCompletionModel : public QAbstractListModel
+{
 public:
        ///
-       GuiCompletionModel(QObject * parent, Inset::CompletionList const * l)
-               : QAbstractListModel(parent), list_(l) {}
+       GuiCompletionModel(QObject * parent, CompletionList const * l)
+               : QAbstractListModel(parent), list_(l)
+       {}
+       ///
+       ~GuiCompletionModel() { delete list_; }
        ///
-       ~GuiCompletionModel()
-               { delete list_; }
+       void setList(CompletionList const * l) {
+               delete list_;
+               list_ = l;
+               reset();
+       }
        ///
        bool sorted() const
        {
                if (list_)
                        return list_->sorted();
-               else
-                       return false;
+               return false;
        }
        ///
        int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const
@@ -143,7 +136,8 @@ public:
                    
                if (index.column() == 0)
                        return toqstr(list_->data(index.row()));
-               else if (index.column() == 1) {
+
+               if (index.column() == 1) {
                        // get icon from cache
                        QPixmap scaled;
                        QString const name = ":" + toqstr(list_->icon(index.row()));
@@ -164,8 +158,8 @@ public:
        }
 
 private:
-       ///
-       Inset::CompletionList const * list_;
+       /// owned by us
+       CompletionList const * list_;
 };
 
 
@@ -175,7 +169,8 @@ GuiCompleter::GuiCompleter(GuiWorkArea * gui, QObject * parent)
          modelActive_(false)
 {
        // Setup the completion popup
-       setModel(new GuiCompletionModel(this, 0));
+       model_ = new GuiCompletionModel(this, 0);
+       setModel(model_);
        setCompletionMode(QCompleter::PopupCompletion);
        setWidget(gui_);
        
@@ -190,9 +185,8 @@ GuiCompleter::GuiCompleter(GuiWorkArea * gui, QObject * parent)
        listView->setUniformRowHeights(true);
        setPopup(listView);
        
-       rtlItemDelegate_ = new RtlItemDelegate(this);
-       popup()->setItemDelegateForColumn(0, rtlItemDelegate_);
-       popup()->setItemDelegateForColumn(1, new PixmapItemDelegate(this));
+       itemDelegate_ = new CompleterItemDelegate(this);
+       popup()->setItemDelegate(itemDelegate_);
        
        // create timeout timers
        popup_timer_.setSingleShot(true);
@@ -378,7 +372,7 @@ void GuiCompleter::updateInline(Cursor & cur, QString const & completion)
        
        // compute postfix
        docstring prefix = cur.inset().completionPrefix(cur);
-       docstring postfix = from_utf8(fromqstr(completion.mid(prefix.length())));
+       docstring postfix = qstring_to_ucs4(completion.mid(prefix.length()));
        
        // shorten it if necessary
        if (lyxrc.completion_inline_dots != -1
@@ -464,23 +458,20 @@ void GuiCompleter::updateModel(Cursor & cur, bool popupUpdate, bool inlineUpdate
        if (old.length() == 0)
                old = last_selection_;
 
+
        // set whether rtl
        bool rtl = false;
        if (cur.inTexted()) {
                Paragraph const & par = cur.paragraph();
                Font const font =
-               par.getFontSettings(cur.bv().buffer().params(), cur.pos());
+                       par.getFontSettings(cur.bv().buffer().params(), cur.pos());
                rtl = font.isVisibleRightToLeft();
        }
        popup()->setLayoutDirection(rtl ? Qt::RightToLeft : Qt::LeftToRight);
 
-       // turn the direction of the strings in the popup.
-       // Qt does not do that itself.
-       rtlItemDelegate_->setEnabled(rtl);
-
        // set new model
-       Inset::CompletionList const * list = cur.inset().createCompletionList(cur);
-       setModel(new GuiCompletionModel(this, list));
+       CompletionList const * list = cur.inset().createCompletionList(cur);
+       model_->setList(list);
        modelActive_ = true;
        if (list->sorted())
                setModelSorting(QCompleter::CaseSensitivelySortedModel);
@@ -524,7 +515,7 @@ void GuiCompleter::showPopup(Cursor & cur)
 }
 
 
-void GuiCompleter::hidePopup(Cursor & cur)
+void GuiCompleter::hidePopup(Cursor &)
 {
        popupVisible_ = false;
 
@@ -548,7 +539,7 @@ void GuiCompleter::asyncHidePopup()
 {
        popup()->hide();
        if (!inlineVisible())
-               setModel(new GuiCompletionModel(this, 0));
+               model_->setList(0);
 }
 
 
@@ -572,7 +563,7 @@ void GuiCompleter::hideInline(Cursor & cur)
        // 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()));
+       QTimer::singleShot(0, this, SLOT(asyncHideInline()));
 
        // mark that the asynchronous part will reset the model
        if (!popupVisible())
@@ -583,7 +574,7 @@ void GuiCompleter::hideInline(Cursor & cur)
 void GuiCompleter::asyncHideInline()
 {
        if (!popupVisible())
-               setModel(new GuiCompletionModel(this, 0));
+               model_->setList(0);
 }
 
 
@@ -679,7 +670,7 @@ void GuiCompleter::tab()
        
        // If completion is active, at least complete by one character
        docstring prefix = cur.inset().completionPrefix(cur);
-       docstring completion = from_utf8(fromqstr(currentCompletion()));
+       docstring completion = qstring_to_ucs4(currentCompletion());
        if (completion.size() <= prefix.size()) {
                // finalize completion
                cur.inset().insertCompletion(cur, docstring(), true);
@@ -785,7 +776,7 @@ void GuiCompleter::setCurrentCompletion(QString const & s)
                        i = n;
                else
                        i = l;
-               BOOST_ASSERT(0 <= i && i <= n);
+               LASSERT(i <= n, /**/);
        }
 
        // select the first if none was found
@@ -859,7 +850,7 @@ docstring GuiCompleter::longestUniqueCompletion() const
                }
        }
 
-       return from_utf8(fromqstr(s));
+       return qstring_to_ucs4(s);
 }
 
 
@@ -869,7 +860,7 @@ void GuiCompleter::popupActivated(const QString & completion)
        cur.updateFlags(Update::None);
        
        docstring prefix = cur.inset().completionPrefix(cur);
-       docstring postfix = from_utf8(fromqstr(completion.mid(prefix.length())));
+       docstring postfix = qstring_to_ucs4(completion.mid(prefix.length()));
        cur.inset().insertCompletion(cur, postfix, true);
        hidePopup(cur);
        hideInline(cur);