Eventviews

tododelegates.cpp
1/*
2 This file is part of KOrganizer.
3
4 SPDX-FileCopyrightText: 2008 Thomas Thrainer <tom_t@gmx.at>
5
6 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
7*/
8
9#include "tododelegates.h"
10#include "todoviewview.h"
11
12#include <Akonadi/TagSelectionComboBox>
13#include <Akonadi/TodoModel>
14#include <CalendarSupport/CategoryHierarchyReader>
15
16#include <KCalendarCore/CalFilter>
17
18#include <KDateComboBox>
19
20#include <QApplication>
21#include <QPainter>
22#include <QTextDocument>
23#include <QToolTip>
24
25// ---------------- COMPLETION DELEGATE --------------------------
26// ---------------------------------------------------------------
27
28TodoCompleteDelegate::TodoCompleteDelegate(QObject *parent)
29 : QStyledItemDelegate(parent)
30{
31}
32
33void TodoCompleteDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
34{
35 QStyleOptionViewItem opt = option;
36 initStyleOption(&opt, index);
37
38 QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
39 style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter);
40
41 if (index.data(Qt::EditRole).toInt() > 0) {
42 bool isEditing = false;
43 auto view = qobject_cast<TodoViewView *>(parent());
44 if (view) {
45 isEditing = view->isEditing(index);
46 }
47
48 // TODO QTreeView does not set State_Editing. Qt task id 205051
49 // should be fixed with Qt 4.5, but wasn't. According to the
50 // task tracker the fix arrives in "Some future release".
51 if (!(opt.state & QStyle::State_Editing) && !isEditing) {
53 pbOption.QStyleOption::operator=(option);
54 initStyleOptionProgressBar(&pbOption, index);
55
56 style->drawControl(QStyle::CE_ProgressBar, &pbOption, painter);
57 }
58 }
59}
60
61QSize TodoCompleteDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
62{
63 QStyleOptionViewItem opt = option;
64 initStyleOption(&opt, index);
65
66 QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
67
69 pbOption.QStyleOption::operator=(option);
70 initStyleOptionProgressBar(&pbOption, index);
71
72 return style->sizeFromContents(QStyle::CT_ProgressBar, &pbOption, QSize(), opt.widget);
73}
74
75void TodoCompleteDelegate::initStyleOptionProgressBar(QStyleOptionProgressBar *option, const QModelIndex &index) const
76{
77 option->rect.adjust(0, 1, 0, -1);
78 option->maximum = 100;
79 option->minimum = 0;
80 option->progress = index.data().toInt();
81 option->text = index.data().toString() + QChar::fromLatin1('%');
82 option->textAlignment = Qt::AlignCenter;
83 option->textVisible = true;
84 option->state |= QStyle::State_Horizontal;
85}
86
87QWidget *TodoCompleteDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
88{
89 Q_UNUSED(option)
90 Q_UNUSED(index)
91
92 auto slider = new TodoCompleteSlider(parent);
93
94 slider->setRange(0, 100);
95 slider->setOrientation(Qt::Horizontal);
96
97 return slider;
98}
99
100void TodoCompleteDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
101{
102 auto slider = static_cast<QSlider *>(editor);
103
104 slider->setValue(index.data(Qt::EditRole).toInt());
105}
106
107void TodoCompleteDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
108{
109 auto slider = static_cast<QSlider *>(editor);
110
111 model->setData(index, slider->value());
112}
113
114void TodoCompleteDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
115{
116 Q_UNUSED(index)
117
118 editor->setGeometry(option.rect);
119}
120
121TodoCompleteSlider::TodoCompleteSlider(QWidget *parent)
122 : QSlider(parent)
123{
124 connect(this, &TodoCompleteSlider::valueChanged, this, &TodoCompleteSlider::updateTip);
125}
126
127void TodoCompleteSlider::updateTip(int value)
128{
129 QPoint p;
130 p.setY(height() / 2);
131 p.setX(style()->sliderPositionFromValue(minimum(), maximum(), value, width()));
132
133 const QString text = QStringLiteral("%1%").arg(value);
134 QToolTip::showText(mapToGlobal(p), text, this);
135}
136
137// ---------------- PRIORITY DELEGATE ----------------------------
138// ---------------------------------------------------------------
139
140TodoPriorityDelegate::TodoPriorityDelegate(QObject *parent)
141 : QStyledItemDelegate(parent)
142{
143}
144
145QWidget *TodoPriorityDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
146{
147 Q_UNUSED(option)
148 Q_UNUSED(index)
149
150 auto combo = new QComboBox(parent);
151
152 combo->addItem(i18nc("@action:inmenu Unspecified priority", "unspecified"));
153 combo->addItem(i18nc("@action:inmenu highest priority", "1 (highest)"));
154 combo->addItem(i18nc("@action:inmenu", "2"));
155 combo->addItem(i18nc("@action:inmenu", "3"));
156 combo->addItem(i18nc("@action:inmenu", "4"));
157 combo->addItem(i18nc("@action:inmenu medium priority", "5 (medium)"));
158 combo->addItem(i18nc("@action:inmenu", "6"));
159 combo->addItem(i18nc("@action:inmenu", "7"));
160 combo->addItem(i18nc("@action:inmenu", "8"));
161 combo->addItem(i18nc("@action:inmenu lowest priority", "9 (lowest)"));
162
163 return combo;
164}
165
166void TodoPriorityDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
167{
168 auto combo = static_cast<QComboBox *>(editor);
169
170 combo->setCurrentIndex(index.data(Qt::EditRole).toInt());
171}
172
173void TodoPriorityDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
174{
175 auto combo = static_cast<QComboBox *>(editor);
176
177 model->setData(index, combo->currentIndex());
178}
179
180void TodoPriorityDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
181{
182 Q_UNUSED(index)
183
184 editor->setGeometry(option.rect);
185}
186
187// ---------------- DUE DATE DELEGATE ----------------------------
188// ---------------------------------------------------------------
189
190TodoDueDateDelegate::TodoDueDateDelegate(QObject *parent)
191 : QStyledItemDelegate(parent)
192{
193}
194
195QWidget *TodoDueDateDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
196{
197 Q_UNUSED(option)
198 Q_UNUSED(index)
199
200 auto dateEdit = new KDateComboBox(parent);
201
202 return dateEdit;
203}
204
205void TodoDueDateDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
206{
207 auto dateEdit = static_cast<KDateComboBox *>(editor);
208
209 dateEdit->setDate(index.data(Qt::EditRole).toDate());
210}
211
212void TodoDueDateDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
213{
214 auto dateEdit = static_cast<KDateComboBox *>(editor);
215
216 model->setData(index, dateEdit->date());
217}
218
219void TodoDueDateDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
220{
221 Q_UNUSED(index)
223}
224
225// ---------------- CATEGORIES DELEGATE --------------------------
226// ---------------------------------------------------------------
227
228TodoCategoriesDelegate::TodoCategoriesDelegate(QObject *parent)
229 : QStyledItemDelegate(parent)
230{
231}
232
233QWidget *TodoCategoriesDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
234{
235 Q_UNUSED(option)
236 Q_UNUSED(index)
237
239}
240
241void TodoCategoriesDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
242{
243 auto combo = static_cast<Akonadi::TagSelectionComboBox *>(editor);
244 combo->setSelection(index.data(Qt::EditRole).toStringList());
245}
246
247void TodoCategoriesDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
248{
249 auto combo = static_cast<Akonadi::TagSelectionComboBox *>(editor);
250 model->setData(index, combo->selectionNames());
251}
252
253void TodoCategoriesDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
254{
255 Q_UNUSED(index)
256
257 editor->setGeometry(option.rect);
258}
259
260// ---------------- RICH TEXT DELEGATE ---------------------------
261// ---------------------------------------------------------------
262
263TodoRichTextDelegate::TodoRichTextDelegate(QObject *parent)
264 : QStyledItemDelegate(parent)
265{
266 m_textDoc = new QTextDocument(this);
267}
268
269void TodoRichTextDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
270{
271 if (index.data(Akonadi::TodoModel::IsRichTextRole).toBool()) {
272 QStyleOptionViewItem opt = option;
273 initStyleOption(&opt, index);
274
275 const QWidget *widget = opt.widget;
276 QStyle *style = widget ? widget->style() : QApplication::style();
277
278 QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &opt, widget);
279
280 // draw the item without text
281 opt.text.clear();
282 style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
283
284 // draw the text (rich text)
286 if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active)) {
288 }
289
290 if (opt.state & QStyle::State_Selected) {
291 painter->setPen(QPen(opt.palette.brush(cg, QPalette::HighlightedText), 0));
292 } else {
293 painter->setPen(QPen(opt.palette.brush(cg, QPalette::Text), 0));
294 }
295 if (opt.state & QStyle::State_Editing) {
296 painter->setPen(QPen(opt.palette.brush(cg, QPalette::Text), 0));
297 painter->drawRect(textRect.adjusted(0, 0, -1, -1));
298 }
299
300 m_textDoc->setHtml(index.data().toString());
301
302 painter->save();
303 painter->translate(textRect.topLeft());
304
305 QRect tmpRect = textRect;
306 tmpRect.moveTo(0, 0);
307 m_textDoc->setTextWidth(tmpRect.width());
308 m_textDoc->drawContents(painter, tmpRect);
309
310 painter->restore();
311 } else {
312 // align the text at top so that when it has more than two lines
313 // it will just cut the extra lines out instead of aligning centered vertically
314 QStyleOptionViewItem copy = option;
315 copy.displayAlignment = Qt::AlignLeft | Qt::AlignTop;
316 QStyledItemDelegate::paint(painter, copy, index);
317 }
318}
319
320QSize TodoRichTextDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
321{
322 QSize ret = QStyledItemDelegate::sizeHint(option, index);
323 if (index.data(Akonadi::TodoModel::IsRichTextRole).toBool()) {
324 m_textDoc->setHtml(index.data().toString());
325 ret = ret.expandedTo(m_textDoc->size().toSize());
326 }
327 // limit height to max. 2 lines
328 // TODO add graphical hint when truncating! make configurable height?
329 if (ret.height() > option.fontMetrics.height() * 2) {
330 ret.setHeight(option.fontMetrics.height() * 2);
331 }
332
333 // This row might not have a checkbox, so give it more height so it appears the same size as other rows.
334 const int checkboxHeight = QApplication::style()->sizeFromContents(QStyle::CT_CheckBox, &option, QSize()).height();
335 return {ret.width(), qMax(ret.height(), checkboxHeight)};
336}
337
338#include "moc_tododelegates.cpp"
void setDate(const QDate &date)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
const QList< QKeySequence > & copy()
virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
void setValue(int)
void valueChanged(int value)
QStyle * style()
QChar fromLatin1(char c)
void setCurrentIndex(int index)
QVariant data(int role) const const
QObject * parent() const const
void drawRect(const QRect &rectangle)
void restore()
void save()
void setPen(Qt::PenStyle style)
void translate(const QPoint &offset)
void setX(int x)
void setY(int y)
QRect adjusted(int dx1, int dy1, int dx2, int dy2) const const
void moveTo(const QPoint &position)
QPoint topLeft() const const
int width() const const
QSize expandedTo(const QSize &otherSize) const const
int height() const const
void setHeight(int height)
int width() const const
QString arg(Args &&... args) const const
PE_PanelItemViewItem
SE_ItemViewItemText
QRect alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment, const QSize &size, const QRect &rectangle)
virtual void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const const=0
virtual void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const const=0
virtual QSize sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const const=0
virtual QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const const=0
virtual void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const const
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const const override
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const const override
AlignCenter
EditRole
Horizontal
void drawContents(QPainter *p, const QRectF &rect)
void setHtml(const QString &html)
void setTextWidth(qreal width)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect, int msecDisplayTime)
bool toBool() const const
QDate toDate() const const
int toInt(bool *ok) const const
QString toString() const const
QStringList toStringList() const const
void setGeometry(const QRect &)
QPoint mapToGlobal(const QPoint &pos) const const
QStyle * style() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:12:29 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.