From 9c055938768c7ef939940254a7f166083d198882 Mon Sep 17 00:00:00 2001 From: Stefan Schimanski Date: Wed, 5 Mar 2008 12:00:56 +0000 Subject: [PATCH] * rich text item delegate to draw the layout filter as underline git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23472 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/frontends/qt4/GuiCompleter.cpp | 1 - src/frontends/qt4/GuiToolbar.cpp | 140 ++++++++++++++++++++++------- src/frontends/qt4/GuiToolbar.h | 3 + 3 files changed, 113 insertions(+), 31 deletions(-) diff --git a/src/frontends/qt4/GuiCompleter.cpp b/src/frontends/qt4/GuiCompleter.cpp index 67f6222d8d..928c27bc93 100644 --- a/src/frontends/qt4/GuiCompleter.cpp +++ b/src/frontends/qt4/GuiCompleter.cpp @@ -26,7 +26,6 @@ #include "support/debug.h" #include -#include #include #include #include diff --git a/src/frontends/qt4/GuiToolbar.cpp b/src/frontends/qt4/GuiToolbar.cpp index b1f7c877df..642773edb8 100644 --- a/src/frontends/qt4/GuiToolbar.cpp +++ b/src/frontends/qt4/GuiToolbar.cpp @@ -42,14 +42,19 @@ #include "support/lstrings.h" #include "support/lyxalgo.h" // sorted +#include +#include +#include #include #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -236,45 +241,119 @@ static QIcon getIcon(FuncRequest const & f, bool unknown) // ///////////////////////////////////////////////////////////////////// -class GuiFilterProxyModel : public QSortFilterProxyModel -{ +class FilterItemDelegate : public QAbstractItemDelegate { public: /// - GuiFilterProxyModel(QObject * parent) - : QSortFilterProxyModel(parent) {} + explicit FilterItemDelegate(QObject * parent = 0) + : QAbstractItemDelegate(parent) {} /// - QVariant data(const QModelIndex & index, int role) const + void paint(QPainter * painter, const QStyleOptionViewItem & option, + const QModelIndex &index) const { + QComboBox * combo = static_cast(parent()); + + // Draw using the menu item style (this is how QComboBox does it). + // But for the rich text drawing below we will call it with an + // empty string, and later then draw over it the real string. + QStyleOptionMenuItem opt = getStyleOption(option, index); + QString text = underlineFilter(opt.text); + opt.text = QString(); + painter->eraseRect(option.rect); + combo->style()->drawControl(QStyle::CE_MenuItem, &opt, painter, combo); + + // Draw the rich text. + painter->save(); + + QColor col = opt.palette.text().color(); + if (opt.state & QStyle::State_Selected) + col = opt.palette.highlightedText().color(); + QAbstractTextDocumentLayout::PaintContext context; + context.palette.setColor(QPalette::Text, col); + + QTextDocument doc; + doc.setDefaultFont(opt.font); + doc.setHtml(text); + doc.setPageSize(QSize(opt.rect.width() - 20, opt.rect.height())); + painter->translate(opt.rect.x() + 20, opt.rect.y() - opt.rect.height()); + doc.documentLayout()->draw(painter, context); + painter->restore(); + } + + /// + QSize sizeHint(const QStyleOptionViewItem &option, + const QModelIndex &index) const { + QComboBox * combo = static_cast(parent()); + + QStyleOptionMenuItem opt = getStyleOption(option, index); + return combo->style()->sizeFromContents( + QStyle::CT_MenuItem, &opt, option.rect.size(), combo); + } + +private: + /// + QString underlineFilter(QString const & s) const { + // get filter GuiLayoutBox * p = static_cast(parent()); QString const & f = p->filter(); - - if (!f.isEmpty() && index.isValid() && role == Qt::DisplayRole) { - // step through data item and put "(x)" for every matching character - QString s = QSortFilterProxyModel::data(index, role).toString(); - QString r; - int lastp = -1; - p->filter(); - for (int i = 0; i < f.length(); ++i) { - int p = s.indexOf(f[i], lastp + 1, Qt::CaseInsensitive); - BOOST_ASSERT(p != -1); - if (lastp == p - 1 && lastp != -1) { - // remove ")" and append "x)" - r = r.left(r.length() - 1) + s[p] + ")"; - } else { - // append "(x)" - r += s.mid(lastp + 1, p - lastp - 1); - r += "(" + s[p] + ")"; - } - lastp = p; + if (f.isEmpty()) + return s; + + // step through data item and put "(x)" for every matching character + QString r; + int lastp = -1; + p->filter(); + for (int i = 0; i < f.length(); ++i) { + int p = s.indexOf(f[i], lastp + 1, Qt::CaseInsensitive); + BOOST_ASSERT(p != -1); + if (lastp == p - 1 && lastp != -1) { + // remove ")" and append "x)" + r = r.left(r.length() - 4) + s[p] + ""; + } else { + // append "(x)" + r += s.mid(lastp + 1, p - lastp - 1); + r += QString("") + s[p] + ""; } - r += s.mid(lastp + 1); - return r; + lastp = p; } - - return QSortFilterProxyModel::data(index, role); + r += s.mid(lastp + 1); + return r; } - + + /// + QStyleOptionMenuItem getStyleOption(const QStyleOptionViewItem &option, + const QModelIndex &index) const + { + QComboBox * combo = static_cast(parent()); + + // create the options for a menu item + QStyleOptionMenuItem menuOption; + menuOption.palette = QApplication::palette("QMenu"); + menuOption.state = QStyle::State_Active | QStyle::State_Enabled; + if (option.state & QStyle::State_Selected) + menuOption.state |= QStyle::State_Selected; + menuOption.checkType = QStyleOptionMenuItem::NonExclusive; + menuOption.checked = combo->currentIndex() == index.row(); + menuOption.menuItemType = QStyleOptionMenuItem::Normal; + menuOption.text = index.model()->data(index, Qt::DisplayRole).toString() + .replace(QLatin1Char('&'), QLatin1String("&&")); + menuOption.tabWidth = 0; + menuOption.menuRect = option.rect; + menuOption.rect = option.rect; + menuOption.font = combo->font(); + menuOption.fontMetrics = QFontMetrics(menuOption.font); + return menuOption; + } +}; + + +class GuiFilterProxyModel : public QSortFilterProxyModel +{ +public: + /// + GuiFilterProxyModel(QObject * parent) + : QSortFilterProxyModel(parent) {} + /// void setCharFilter(QString const & f) { @@ -295,7 +374,7 @@ private: GuiLayoutBox::GuiLayoutBox(GuiView & owner) - : owner_(owner) + : owner_(owner), filterItemDelegate_(new FilterItemDelegate(this)) { setSizeAdjustPolicy(QComboBox::AdjustToContents); setFocusPolicy(Qt::ClickFocus); @@ -314,6 +393,7 @@ GuiLayoutBox::GuiLayoutBox(GuiView & owner) // for the filtering we have to intercept characters view()->installEventFilter(this); + view()->setItemDelegateForColumn(0, filterItemDelegate_); QObject::connect(this, SIGNAL(activated(int)), this, SLOT(selected(int))); diff --git a/src/frontends/qt4/GuiToolbar.h b/src/frontends/qt4/GuiToolbar.h index d972f13bd1..c480cb7438 100644 --- a/src/frontends/qt4/GuiToolbar.h +++ b/src/frontends/qt4/GuiToolbar.h @@ -32,6 +32,7 @@ class ToolbarItem; namespace frontend { +class FilterItemDelegate; class GuiCommandBuffer; class GuiFilterProxyModel; class GuiView; @@ -81,6 +82,8 @@ private: int lastSel_; /// the character filter QString filter_; + /// + FilterItemDelegate * filterItemDelegate_; }; -- 2.39.2