1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
#include "ProjectItem.h"
#include "Common.h"
#include <QIcon>
#include <QPainter>
ProjectItemDelegate::ProjectItemDelegate(QWidget* parent) : QStyledItemDelegate(parent) {}
void ProjectItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
painter->save();
QStyleOptionViewItem opt(option);
initStyleOption(&opt, index);
auto rect = opt.rect;
if (opt.state & QStyle::State_Selected) {
painter->fillRect(rect, opt.palette.highlight());
painter->setPen(opt.palette.highlightedText().color());
} else if (opt.state & QStyle::State_MouseOver) {
painter->fillRect(rect, opt.palette.window());
}
// The default icon size will be a square (and height is usually the lower value).
auto icon_width = rect.height(), icon_height = rect.height();
int icon_x_margin = (rect.height() - icon_width) / 2;
int icon_y_margin = (rect.height() - icon_height) / 2;
if (!opt.icon.isNull()) { // Icon painting
{
auto icon_size = opt.decorationSize;
icon_width = icon_size.width();
icon_height = icon_size.height();
icon_x_margin = (rect.height() - icon_width) / 2;
icon_y_margin = (rect.height() - icon_height) / 2;
}
// Centralize icon with a margin to separate from the other elements
int x = rect.x() + icon_x_margin;
int y = rect.y() + icon_y_margin;
// Prevent 'scaling null pixmap' warnings
if (icon_width > 0 && icon_height > 0)
opt.icon.paint(painter, x, y, icon_width, icon_height);
}
// Change the rect so that funther painting is easier
auto remaining_width = rect.width() - icon_width - 2 * icon_x_margin;
rect.setRect(rect.x() + icon_width + 2 * icon_x_margin, rect.y(), remaining_width, rect.height());
int title_height = 0;
{ // Title painting
auto title = index.data(UserDataTypes::TITLE).toString();
painter->save();
auto font = opt.font;
if (index.data(UserDataTypes::SELECTED).toBool()) {
// Set nice font
font.setBold(true);
font.setUnderline(true);
}
if (index.data(UserDataTypes::INSTALLED).toBool()) {
auto hRect = opt.rect;
hRect.setX(hRect.x() + 1);
hRect.setY(hRect.y() + 1);
hRect.setHeight(hRect.height() - 2);
hRect.setWidth(hRect.width() - 2);
// Set nice font
font.setItalic(true);
font.setOverline(true);
painter->drawRect(hRect);
}
font.setPointSize(font.pointSize() + 2);
painter->setFont(font);
title_height = QFontMetrics(font).height();
// On the top, aligned to the left after the icon
painter->drawText(rect.x(), rect.y() + title_height, title);
painter->restore();
}
{ // Description painting
auto description = index.data(UserDataTypes::DESCRIPTION).toString();
QTextLayout text_layout(description, opt.font);
qreal height = 0;
auto cut_text = viewItemTextLayout(text_layout, remaining_width, height);
// Get first line unconditionally
description = cut_text.first().second;
auto num_lines = 1;
// Get second line, elided if needed
if (cut_text.size() > 1) {
// 2.5x so because there should be some margin left from the 2x so things don't get too squishy.
if (rect.height() - title_height <= 2.5 * opt.fontMetrics.height()) {
// If there's not enough space, show only a single line, elided.
description = opt.fontMetrics.elidedText(description, opt.textElideMode, cut_text.at(0).first);
} else {
if (cut_text.size() > 2) {
description += opt.fontMetrics.elidedText(cut_text.at(1).second, opt.textElideMode, cut_text.at(1).first);
} else {
description += cut_text.at(1).second;
}
num_lines += 1;
}
}
int description_x = rect.x();
// Have the y-value be set based on the number of lines in the description, to centralize the
// description text with the space between the base and the title.
int description_y = rect.y() + title_height + (rect.height() - title_height) / 2;
if (num_lines == 1)
description_y -= opt.fontMetrics.height() / 2;
else
description_y -= opt.fontMetrics.height();
// On the bottom, aligned to the left after the icon, and featuring at most two lines of text (with some margin space to spare)
painter->drawText(description_x, description_y, remaining_width, cut_text.size() * opt.fontMetrics.height(), Qt::TextWordWrap,
description);
}
painter->restore();
}
|