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
|
#include "library/stareditor.h"
#include <QStylePainter>
#include "library/starrating.h"
#include "moc_stareditor.cpp"
#include "util/painterscope.h"
// We enable mouse tracking on the widget so we can follow the cursor even
// when the user doesn't hold down any mouse button. We also turn on
// QWidget's auto-fill background feature to obtain an opaque background.
// (Without the call, the view's background would shine through the editor.)
/// StarEditor inherits QWidget and is used by StarDelegate to let the user
/// edit a star rating in the library using the mouse.
///
/// The class has been adapted from the official "Star Delegate Example",
/// see http://doc.trolltech.com/4.5/itemviews-stardelegate.html
StarEditor::StarEditor(QWidget *parent, QTableView* pTableView,
const QModelIndex& index,
const QStyleOptionViewItem& option)
: QWidget(parent),
m_pTableView(pTableView),
m_index(index),
m_styleOption(option) {
setMouseTracking(true);
}
QSize StarEditor::sizeHint() const {
return m_starRating.sizeHint();
}
// static
void StarEditor::renderHelper(QPainter* painter,
QTableView* pTableView,
const QStyleOptionViewItem& option,
StarRating* pStarRating) {
PainterScope painterScope(painter);
painter->setClipRect(option.rect);
if (pTableView != nullptr) {
QStyle* style = pTableView->style();
if (style != nullptr) {
style->drawControl(QStyle::CE_ItemViewItem, &option, painter,
pTableView);
}
}
// Set the palette appropriately based on whether the row is selected or
// not. We also have to check if it is inactive or not and use the
// appropriate ColorGroup.
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
? QPalette::Normal : QPalette::Disabled;
if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)) {
cg = QPalette::Inactive;
}
if (option.state & QStyle::State_Selected) {
painter->setBrush(option.palette.color(cg, QPalette::HighlightedText));
} else {
painter->setBrush(option.palette.color(cg, QPalette::Text));
}
pStarRating->paint(painter, option.rect);
}
void StarEditor::paintEvent(QPaintEvent*) {
// If a StarEditor is open, by definition the mouse is hovering over us.
m_styleOption.state |= QStyle::State_MouseOver;
m_styleOption.rect = rect();
if (m_pTableView) {
QItemSelectionModel* selectionModel = m_pTableView->selectionModel();
if (selectionModel && selectionModel->isSelected(m_index)) {
m_styleOption.state |= QStyle::State_Selected;
}
}
QPainter painter(this);
renderHelper(&painter, m_pTableView, m_styleOption, &m_starRating);
}
void StarEditor::mouseMoveEvent(QMouseEvent *event) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
const int eventPosition = static_cast<int>(event->position().x());
#else
const int eventPosition = event->x();
#endif
int star = starAtPosition(eventPosition);
if (star != m_starRating.starCount() && star != -1) {
m_starRating.setStarCount(star);
update();
}
}
void StarEditor::leaveEvent(QEvent*) {
m_starRating.setStarCount(0);
update();
}
void StarEditor::mouseReleaseEvent(QMouseEvent* /* event */) {
emit editingFinished();
}
int StarEditor::starAtPosition(int x) {
// If the mouse is very close to the left edge, set 0 stars.
if (x < m_starRating.sizeHint().width() * 0.05) {
return 0;
}
int star = (x / (m_starRating.sizeHint().width() / m_starRating.maxStarCount())) + 1;
if (star <= 0 || star > m_starRating.maxStarCount()) {
return 0;
}
return star;
}
|