Marble

RouteItemDelegate.cpp
1#include "RouteItemDelegate.h"
2
3#include "CloudRouteModel.h"
4
5#ifdef MARBLE_NO_WEBKITWIDGETS
6#include <QWidget>
7#else
8#include <QWebEngineView>
9#endif
10
11#include <QAbstractTextDocumentLayout>
12#include <QApplication>
13#include <QListView>
14#include <QPainter>
15
16namespace Marble
17{
18
19RouteItemDelegate::RouteItemDelegate(QListView *view, CloudRouteModel *model)
20 : m_view(view)
21 , m_model(model)
22 , m_buttonWidth(0)
23 , m_iconSize(16)
24 , m_previewSize(128)
25 , m_margin(8)
26{
27}
28
29void RouteItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
30{
31 QStyleOptionViewItem styleOption = option;
32 styleOption.text = QString();
34
36 if (styleOption.state & QStyle::State_Selected) {
37 paintContext.palette.setColor(QPalette::Text, styleOption.palette.color(QPalette::Active, QPalette::HighlightedText));
38 }
39
40 QRect const iconRect = position(Preview, option);
41 auto const icon = index.data(Qt::DecorationRole).value<QIcon>();
42 painter->drawPixmap(iconRect, icon.pixmap(iconRect.size()));
43
44 QTextDocument document;
45 QRect const textRect = position(Text, option);
46 document.setTextWidth(textRect.width());
47 document.setDefaultFont(option.font);
48 document.setHtml(text(index));
49
50 painter->save();
51 painter->translate(textRect.topLeft());
52 painter->setClipRect(0, 0, textRect.width(), textRect.height());
53 document.documentLayout()->draw(painter, paintContext);
54 painter->restore();
55
56 bool cached = index.data(CloudRouteModel::IsCached).toBool();
57 bool downloading = index.data(CloudRouteModel::IsDownloading).toBool();
58 bool onCloud = index.data(CloudRouteModel::IsOnCloud).toBool();
59
60 if (downloading) {
61 qint64 total = m_model->totalSize();
62 qint64 progress = m_model->downloadedSize();
63
64 QStyleOptionProgressBar progressBarOption;
65 progressBarOption.rect = position(Progressbar, option);
66 progressBarOption.minimum = 0;
67 progressBarOption.maximum = 100;
68 progressBarOption.progress = (100.0 * progress / total);
69 progressBarOption.text = QString::number(progressBarOption.progress) + QLatin1Char('%');
70 progressBarOption.textVisible = true;
71 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
72 } else if (!cached && onCloud) {
73 QStyleOptionButton downloadButton = button(DownloadButton, option);
74 QRect downloadRect = position(DownloadButton, option);
75 downloadButton.rect = downloadRect;
76 QApplication::style()->drawControl(QStyle::CE_PushButton, &downloadButton, painter);
77
78 QStyleOptionButton cloudRemoveButton = button(RemoveFromCloudButton, option);
79 QRect cloudRemoveRect = position(RemoveFromCloudButton, option);
80 cloudRemoveButton.rect = cloudRemoveRect;
81 QApplication::style()->drawControl(QStyle::CE_PushButton, &cloudRemoveButton, painter);
82 } else if (cached && !onCloud) {
83 QStyleOptionButton openButton = button(OpenButton, option);
84 QRect openRect = position(OpenButton, option);
85 openButton.rect = openRect;
87
88 QStyleOptionButton cacheRemoveButton = button(RemoveFromCacheButton, option);
89 QRect cacheRemoveRect = position(RemoveFromCacheButton, option);
90 cacheRemoveButton.rect = cacheRemoveRect;
91 QApplication::style()->drawControl(QStyle::CE_PushButton, &cacheRemoveButton, painter);
92
93 QStyleOptionButton uploadButton = button(UploadToCloudButton, option);
94 QRect uploadRect = position(UploadToCloudButton, option);
95 uploadButton.rect = uploadRect;
96 QApplication::style()->drawControl(QStyle::CE_PushButton, &uploadButton, painter);
97 } else if (cached && onCloud) {
98 QStyleOptionButton openButton = button(OpenButton, option);
99 QRect openRect = position(OpenButton, option);
100 openButton.rect = openRect;
101 QApplication::style()->drawControl(QStyle::CE_PushButton, &openButton, painter);
102
103 QStyleOptionButton cacheRemoveButton = button(RemoveFromCacheButton, option);
104 QRect cacheRemoveRect = position(RemoveFromCacheButton, option);
105 cacheRemoveButton.rect = cacheRemoveRect;
106 QApplication::style()->drawControl(QStyle::CE_PushButton, &cacheRemoveButton, painter);
107 }
108}
109
110QSize RouteItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
111{
112 if (index.column() == 0) {
113 QTextDocument doc;
114 doc.setDefaultFont(option.font);
115 doc.setTextWidth(qMax(128, m_view->contentsRect().width() - m_previewSize - buttonWidth(option)));
116 doc.setHtml(text(index));
117 return {qMax(256, qRound(m_previewSize + buttonWidth(option) + doc.size().width() + m_margin * 2)),
118 qMax(m_previewSize + m_margin * 2, qRound(doc.size().height()))};
119 }
120
121 return {};
122}
123
124bool RouteItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
125{
126 Q_UNUSED(model);
127
128 if ((event->type() == QEvent::MouseButtonRelease)) {
129 auto mouseEvent = static_cast<QMouseEvent *>(event);
130 QPoint pos = mouseEvent->pos();
131
132 bool cached = index.data(CloudRouteModel::IsCached).toBool();
133 bool onCloud = index.data(CloudRouteModel::IsOnCloud).toBool();
134
135 if (cached && !onCloud) {
136 QRect uploadRect = position(UploadToCloudButton, option);
137
138 if (uploadRect.contains(pos)) {
139 QString timestamp = index.data(CloudRouteModel::Timestamp).toString();
140 Q_EMIT uploadToCloudButtonClicked(timestamp);
141 return true;
142 }
143 }
144
145 if (cached) {
146 QRect openRect = position(OpenButton, option);
147 QRect cacheRemoveRect = position(RemoveFromCacheButton, option);
148
149 if (openRect.contains(pos)) {
150 QString timestamp = index.data(CloudRouteModel::Timestamp).toString();
151 Q_EMIT openButtonClicked(timestamp);
152 return true;
153 } else if (cacheRemoveRect.contains(pos)) {
154 QString timestamp = index.data(CloudRouteModel::Timestamp).toString();
155 Q_EMIT removeFromCacheButtonClicked(timestamp);
156 return true;
157 }
158 } else {
159 QRect downloadRect = position(DownloadButton, option);
160 QRect cloudRemoveRect = position(RemoveFromCloudButton, option);
161
162 if (downloadRect.contains(pos)) {
163 QString timestamp = index.data(CloudRouteModel::Timestamp).toString();
164 m_model->setDownloadingItem(index);
165 Q_EMIT downloadButtonClicked(timestamp);
166 return true;
167 }
168
169 if (cloudRemoveRect.contains(pos)) {
170 QString timestamp = index.data(CloudRouteModel::Timestamp).toString();
171 Q_EMIT deleteButtonClicked(timestamp);
172 return true;
173 }
174 }
175 }
176
177 return false;
178}
179
180int RouteItemDelegate::buttonWidth(const QStyleOptionViewItem &option) const
181{
182 if (m_buttonWidth <= 0) {
183 int const openWidth = option.fontMetrics.size(0, tr("Open")).width();
184 int const downloadWidth = option.fontMetrics.size(0, tr("Load")).width();
185 int const cacheWidth = option.fontMetrics.size(0, tr("Remove from device")).width();
186 int const cloudWidth = option.fontMetrics.size(0, tr("Delete from cloud")).width();
187 m_buttonWidth = 2 * m_iconSize + qMax(qMax(openWidth, downloadWidth), qMax(cacheWidth, cloudWidth));
188 }
189
190 return m_buttonWidth;
191}
192
193QStyleOptionButton RouteItemDelegate::button(Element element, const QStyleOptionViewItem &option) const
194{
195 QStyleOptionButton result;
196 result.state = option.state;
197 result.state &= ~QStyle::State_HasFocus;
198
199 result.palette = option.palette;
200 result.features = QStyleOptionButton::None;
201
202 switch (element) {
203 case OpenButton:
204 result.text = tr("Open");
205 result.icon = QIcon(QStringLiteral(":/marble/document-open.png"));
206 result.iconSize = QSize(m_iconSize, m_iconSize);
207 break;
208 case DownloadButton:
209 result.text = tr("Load");
210 result.icon = QIcon(QStringLiteral(":/marble/dialog-ok.png"));
211 result.iconSize = QSize(m_iconSize, m_iconSize);
212 break;
213 case RemoveFromCacheButton:
214 result.text = tr("Remove from device");
215 result.icon = QIcon(QStringLiteral(":/marble/edit-clear.png"));
216 result.iconSize = QSize(m_iconSize, m_iconSize);
217 break;
218 case RemoveFromCloudButton:
219 result.text = tr("Delete from cloud");
220 result.icon = QIcon(QStringLiteral(":/marble/edit-delete.png"));
221 result.iconSize = QSize(m_iconSize, m_iconSize);
222 break;
223 case UploadToCloudButton:
224 result.text = tr("Upload to cloud");
225 result.icon = QIcon(QStringLiteral(":/icons/cloud-upload.png"));
226 result.iconSize = QSize(m_iconSize, m_iconSize);
227 break;
228 default:
229 // Ignored.
230 break;
231 }
232
233 return result;
234}
235
236QString RouteItemDelegate::text(const QModelIndex &index)
237{
238 return QStringLiteral("%0").arg(index.data(CloudRouteModel::Name).toString());
239 // TODO: Show distance and duration
240 // return QStringLiteral( "%0<br /><b>Duration:</b> %1<br/><b>Distance:</b> %2" )
241 //.arg( index.data( CloudRouteModel::Name ).toString() )
242 //.arg( index.data( CloudRouteModel::Duration ).toString() )
243 //.arg( index.data( CloudRouteModel::Distance ).toString() );
244}
245
246QRect RouteItemDelegate::position(Element element, const QStyleOptionViewItem &option) const
247{
248 int const width = buttonWidth(option);
249 QPoint const firstColumn = option.rect.topLeft() + QPoint(m_margin, m_margin);
250 QPoint const secondColumn = firstColumn + QPoint(m_previewSize + m_margin, 0);
251 QPoint const thirdColumn = QPoint(option.rect.width() - width - option.decorationSize.width(), firstColumn.y());
252
253 switch (element) {
254 case Text:
255 return QRect(secondColumn, QSize(thirdColumn.x() - secondColumn.x(), option.rect.height()));
256 case OpenButton:
257 case DownloadButton: {
258 QStyleOptionButton optionButton = button(element, option);
259 QSize size = option.fontMetrics.size(0, optionButton.text) + QSize(4, 4);
260 QSize buttonSize = QApplication::style()->sizeFromContents(QStyle::CT_PushButton, &optionButton, size);
261 buttonSize.setWidth(width);
262 return QRect(thirdColumn, buttonSize);
263 }
264 case RemoveFromCacheButton:
265 case RemoveFromCloudButton: {
266 QStyleOptionButton optionButton = button(element, option);
267 QSize size = option.fontMetrics.size(0, optionButton.text) + QSize(4, 4);
268 QSize buttonSize = QApplication::style()->sizeFromContents(QStyle::CT_PushButton, &optionButton, size);
269 buttonSize.setWidth(width);
270 return QRect(thirdColumn + QPoint(0, buttonSize.height()), buttonSize);
271 }
272 case Progressbar: {
273 QSize const progressSize = QSize(width, option.fontMetrics.height() + 4);
274 return QRect(thirdColumn + QPoint(0, 10), progressSize);
275 }
276 case Preview: {
277 return QRect(firstColumn, QSize(m_previewSize, m_previewSize));
278 }
279 case UploadToCloudButton: {
280 QStyleOptionButton optionButton = button(element, option);
281 QSize size = option.fontMetrics.size(0, optionButton.text) + QSize(4, 4);
282 QSize buttonSize = QApplication::style()->sizeFromContents(QStyle::CT_PushButton, &optionButton, size);
283 buttonSize.setWidth(width);
284 return QRect(thirdColumn + QPoint(0, buttonSize.height() * 2), buttonSize);
285 }
286 }
287
288 return {};
289}
290
291}
292
293#include "moc_RouteItemDelegate.cpp"
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
Binds a QML item to a specific geodetic location in screen coordinates.
virtual void draw(QPainter *painter, const PaintContext &context)=0
QStyle * style()
MouseButtonRelease
int column() const const
QVariant data(int role) const const
void drawPixmap(const QPoint &point, const QPixmap &pixmap)
void restore()
void save()
void setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
void translate(const QPoint &offset)
int x() const const
int y() const const
bool contains(const QPoint &point, bool proper) const const
int height() const const
QSize size() const const
QPoint topLeft() const const
int width() const const
int height() const const
void setWidth(int width)
QString arg(Args &&... args) const const
QString number(double n, char format, int precision)
virtual void drawControl(ControlElement 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
DecorationRole
QAbstractTextDocumentLayout * documentLayout() const const
void setDefaultFont(const QFont &font)
void setHtml(const QString &html)
void setTextWidth(qreal width)
bool toBool() const const
QString toString() const const
T value() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 8 2024 12:02:42 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.