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

KDE's Doxygen guidelines are available online.