* simplified layout list a lot by subclassing QItemDelegate instead of

trying to simulate a menu with a QListView (that's what QComboBox does
on some platforms, but not on all).


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23654 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Stefan Schimanski 2008-03-10 23:00:53 +00:00
parent 46c83df1cd
commit 361d4d9a16

View File

@ -49,6 +49,7 @@
#include <QComboBox> #include <QComboBox>
#include <QFontMetrics> #include <QFontMetrics>
#include <QHeaderView> #include <QHeaderView>
#include <QItemDelegate>
#include <QKeyEvent> #include <QKeyEvent>
#include <QList> #include <QList>
#include <QListView> #include <QListView>
@ -249,52 +250,60 @@ static QIcon getIcon(FuncRequest const & f, bool unknown)
// //
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
class LayoutItemDelegate : public QAbstractItemDelegate { class LayoutItemDelegate : public QItemDelegate {
public: public:
/// ///
explicit LayoutItemDelegate(QObject * parent = 0) explicit LayoutItemDelegate(QObject * parent = 0)
: QAbstractItemDelegate(parent) : QItemDelegate(parent)
{} {}
/// ///
void paint(QPainter * painter, QStyleOptionViewItem const & option, void paint(QPainter * painter, QStyleOptionViewItem const & option,
QModelIndex const & index) const QModelIndex const & index) const
{ {
QComboBox * combo = static_cast<QComboBox *>(parent()); QStyleOptionViewItem opt = option;
QSortFilterProxyModel const * model
= static_cast<QSortFilterProxyModel const *>(index.model());
QStyleOptionMenuItem opt = getStyleOption(option, index);
painter->eraseRect(opt.rect); // default background
painter->fillRect(opt.rect, opt.palette.background().color());
QString text = underlineFilter(opt.text);
opt.text = QString();
// category header? // category header?
if (lyxrc.group_layouts) { if (lyxrc.group_layouts) {
QSortFilterProxyModel const * model
= static_cast<QSortFilterProxyModel const *>(index.model());
QString stdCat = category(*model->sourceModel(), 0); QString stdCat = category(*model->sourceModel(), 0);
QString cat = category(*index.model(), index.row()); QString cat = category(*index.model(), index.row());
// not the standard layout and not the same as in the previous line? // not the standard layout and not the same as in the previous line?
if (stdCat != cat if (stdCat != cat
&& (index.row() == 0 || cat != category(*index.model(), index.row() - 1))) { && (index.row() == 0 || cat != category(*index.model(), index.row() - 1))) {
painter->save();
// draw unselected background
QStyle::State state = opt.state;
opt.state = opt.state & ~QStyle::State_Selected;
drawBackground(painter, opt, index);
opt.state = state;
// draw category header // draw category header
paintBackground(painter, opt); drawCategoryHeader(painter, opt,
paintCategoryHeader(painter, opt,
category(*index.model(), index.row())); category(*index.model(), index.row()));
// move rect down below header // move rect down below header
opt.rect.moveTop(opt.rect.top() + headerHeight(opt)); opt.rect.setTop(opt.rect.top() + headerHeight(opt));
opt.menuRect = opt.rect;
painter->restore();
} }
} }
// Draw using the menu item style (this is how QComboBox does it). QItemDelegate::paint(painter, opt, index);
// But for the rich text drawing below we will call it with an }
// empty string, and later then draw over it the real string.
painter->save(); ///
combo->style()->drawControl(QStyle::CE_MenuItem, &opt, painter, combo->view()); void drawDisplay(QPainter * painter, QStyleOptionViewItem const & opt,
painter->restore(); const QRect & rect, const QString & text ) const
{
QString utext = underlineFilter(text);
// Draw the rich text. // Draw the rich text.
painter->save(); painter->save();
@ -306,7 +315,7 @@ public:
QTextDocument doc; QTextDocument doc;
doc.setDefaultFont(opt.font); doc.setDefaultFont(opt.font);
doc.setHtml(text); doc.setHtml(utext);
QTextFrameFormat fmt = doc.rootFrame()->frameFormat(); QTextFrameFormat fmt = doc.rootFrame()->frameFormat();
fmt.setMargin(0); fmt.setMargin(0);
@ -319,18 +328,13 @@ public:
} }
/// ///
QSize sizeHint(QStyleOptionViewItem const & option, QSize sizeHint(QStyleOptionViewItem const & opt,
QModelIndex const & index) const QModelIndex const & index) const
{ {
GuiLayoutBox * combo = static_cast<GuiLayoutBox *>(parent()); GuiLayoutBox * combo = static_cast<GuiLayoutBox *>(parent());
QSortFilterProxyModel const * model QSortFilterProxyModel const * model
= static_cast<QSortFilterProxyModel const *>(index.model()); = static_cast<QSortFilterProxyModel const *>(index.model());
QSize size = QItemDelegate::sizeHint(opt, index);
// we use a compressed menu style here
QStyleOptionMenuItem opt = getStyleOption(option, index);
QSize size = combo->style()->sizeFromContents(
QStyle::CT_MenuItem, &opt, opt.rect.size(), combo);
size.setHeight(opt.rect.height());
/// QComboBox uses the first row height to estimate the /// QComboBox uses the first row height to estimate the
/// complete popup height during QComboBox::showPopup(). /// complete popup height during QComboBox::showPopup().
@ -371,35 +375,14 @@ private:
} }
/// ///
void paintBackground(QPainter * painter, QStyleOptionMenuItem const & opt) const int headerHeight(QStyleOptionViewItem const & opt) const
{
QComboBox * combo = static_cast<QComboBox *>(parent());
// we only want to paint a background using the style, so
// disable every thing else
QStyleOptionMenuItem sopt = opt;
sopt.menuRect = sopt.rect;
sopt.state = QStyle::State_Active | QStyle::State_Enabled;
sopt.checked = false;
sopt.text = QString();
painter->save();
combo->style()->drawControl(QStyle::CE_MenuItem, &sopt,
painter, combo->view());
painter->restore();
}
///
int headerHeight(QStyleOptionMenuItem const & opt) const
{ {
return opt.fontMetrics.height() * 8 / 10; return opt.fontMetrics.height() * 8 / 10;
} }
/// ///
void paintCategoryHeader(QPainter * painter, QStyleOptionMenuItem const & opt, void drawCategoryHeader(QPainter * painter, QStyleOptionViewItem const & opt,
QString const & category) const QString const & category) const
{ {
painter->save();
// slightly blended color // slightly blended color
QColor lcol = opt.palette.text().color(); QColor lcol = opt.palette.text().color();
lcol.setAlpha(127); lcol.setAlpha(127);
@ -430,8 +413,6 @@ private:
painter->drawLine(right + 1, ymid, opt.rect.right(), ymid); painter->drawLine(right + 1, ymid, opt.rect.right(), ymid);
} else } else
painter->drawLine(opt.rect.x(), ymid, opt.rect.right(), ymid); painter->drawLine(opt.rect.x(), ymid, opt.rect.right(), ymid);
painter->restore();
} }
@ -464,32 +445,6 @@ private:
r += s.mid(lastp + 1); r += s.mid(lastp + 1);
return r; return r;
} }
///
QStyleOptionMenuItem getStyleOption(QStyleOptionViewItem const & option,
QModelIndex const & index) const
{
QComboBox * combo = static_cast<QComboBox *>(parent());
// create the options for a menu item
QStyleOptionMenuItem menuOption;
menuOption.palette = QApplication::palette("QMenu");
menuOption.state = QStyle::State_Active | QStyle::State_Enabled;
menuOption.font = combo->font();
menuOption.fontMetrics = QFontMetrics(menuOption.font);
menuOption.rect = option.rect;
menuOption.rect.setHeight(menuOption.fontMetrics.height());
menuOption.menuRect = menuOption.rect;
menuOption.tabWidth = 0;
menuOption.text = index.model()->data(index, Qt::DisplayRole).toString()
.replace(QLatin1Char('&'), QLatin1String("&&"));
menuOption.menuItemType = QStyleOptionMenuItem::Normal;
if (option.state & QStyle::State_Selected)
menuOption.state |= QStyle::State_Selected;
menuOption.checkType = QStyleOptionMenuItem::NotCheckable;
menuOption.checked = false;
return menuOption;
}
}; };