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 
16 namespace Marble {
17 
18 RouteItemDelegate::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 
28 void 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 
109 QSize 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 
123 bool 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 
179 int 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 
192 QStyleOptionButton 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 
235 QString 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 
245 QRect 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"
QPoint pos() const const
virtual void drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const const=0
DecorationRole
MouseButtonRelease
QPoint topLeft() const const
QString number(int n, int base)
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
QSize size() const const
int column() const const
T value() const const
void setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
QAbstractTextDocumentLayout * documentLayout() const const
int width() const const
int x() const const
int y() const const
bool contains(const QRect &rectangle, bool proper) const const
void setWidth(int width)
QVariant data(int role) const const
void setTextWidth(qreal width)
int height() const const
void setDefaultFont(const QFont &font)
Binds a QML item to a specific geodetic location in screen coordinates.
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
bool toBool() const const
virtual QSize sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const const=0
int height() const const
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
void setHtml(const QString &html)
void translate(const QPointF &offset)
void restore()
void save()
virtual void draw(QPainter *painter, const QAbstractTextDocumentLayout::PaintContext &context)=0
QStyle * style()
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Oct 2 2023 03:52:09 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.