File indexing completed on 2024-05-05 03:49:15
0001 #include "RouteItemDelegate.h" 0002 0003 #include "CloudRouteModel.h" 0004 0005 #ifdef MARBLE_NO_WEBKITWIDGETS 0006 #include <QWidget> 0007 #else 0008 #include <QWebEngineView> 0009 #endif 0010 0011 #include <QApplication> 0012 #include <QAbstractTextDocumentLayout> 0013 #include <QPainter> 0014 #include <QListView> 0015 0016 namespace Marble { 0017 0018 RouteItemDelegate::RouteItemDelegate( QListView *view, CloudRouteModel *model ) : 0019 m_view( view ), 0020 m_model( model ), 0021 m_buttonWidth( 0 ), 0022 m_iconSize( 16 ), 0023 m_previewSize( 128 ), 0024 m_margin( 8 ) 0025 { 0026 } 0027 0028 void RouteItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const 0029 { 0030 QStyleOptionViewItem styleOption = option; 0031 styleOption.text = QString(); 0032 QApplication::style()->drawControl( QStyle::CE_ItemViewItem, &styleOption, painter ); 0033 0034 QAbstractTextDocumentLayout::PaintContext paintContext; 0035 if ( styleOption.state & QStyle::State_Selected) { 0036 paintContext.palette.setColor( QPalette::Text, styleOption.palette.color( QPalette::Active, QPalette::HighlightedText ) ); 0037 } 0038 0039 QRect const iconRect = position( Preview, option ); 0040 QIcon const icon = index.data( Qt::DecorationRole ).value<QIcon>(); 0041 painter->drawPixmap( iconRect, icon.pixmap( iconRect.size() ) ); 0042 0043 QTextDocument document; 0044 QRect const textRect = position( Text, option ); 0045 document.setTextWidth( textRect.width() ); 0046 document.setDefaultFont( option.font ); 0047 document.setHtml( text( index ) ); 0048 0049 painter->save(); 0050 painter->translate( textRect.topLeft() ); 0051 painter->setClipRect( 0, 0, textRect.width(), textRect.height() ); 0052 document.documentLayout()->draw( painter, paintContext ); 0053 painter->restore(); 0054 0055 bool cached = index.data( CloudRouteModel::IsCached ).toBool(); 0056 bool downloading = index.data( CloudRouteModel::IsDownloading ).toBool(); 0057 bool onCloud = index.data( CloudRouteModel::IsOnCloud ).toBool(); 0058 0059 if ( downloading ) { 0060 qint64 total = m_model->totalSize(); 0061 qint64 progress = m_model->downloadedSize(); 0062 0063 QStyleOptionProgressBar progressBarOption; 0064 progressBarOption.rect = position( Progressbar, option ); 0065 progressBarOption.minimum = 0; 0066 progressBarOption.maximum = 100; 0067 progressBarOption.progress = ( 100.0 * progress / total ); 0068 progressBarOption.text = QString::number(progressBarOption.progress) + QLatin1Char('%'); 0069 progressBarOption.textVisible = true; 0070 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter); 0071 } else if ( !cached && onCloud ) { 0072 QStyleOptionButton downloadButton = button( DownloadButton, option ); 0073 QRect downloadRect = position( DownloadButton, option ); 0074 downloadButton.rect = downloadRect; 0075 QApplication::style()->drawControl( QStyle::CE_PushButton, &downloadButton, painter ); 0076 0077 QStyleOptionButton cloudRemoveButton = button( RemoveFromCloudButton, option ); 0078 QRect cloudRemoveRect = position( RemoveFromCloudButton, option ); 0079 cloudRemoveButton.rect = cloudRemoveRect; 0080 QApplication::style()->drawControl( QStyle::CE_PushButton, &cloudRemoveButton, painter ); 0081 } else if ( cached && !onCloud ) { 0082 QStyleOptionButton openButton = button( OpenButton, option ); 0083 QRect openRect = position( OpenButton, option ); 0084 openButton.rect = openRect; 0085 QApplication::style()->drawControl( QStyle::CE_PushButton, &openButton, painter ); 0086 0087 QStyleOptionButton cacheRemoveButton = button( RemoveFromCacheButton, option ); 0088 QRect cacheRemoveRect = position( RemoveFromCacheButton, option ); 0089 cacheRemoveButton.rect = cacheRemoveRect; 0090 QApplication::style()->drawControl( QStyle::CE_PushButton, &cacheRemoveButton, painter ); 0091 0092 QStyleOptionButton uploadButton = button( UploadToCloudButton, option ); 0093 QRect uploadRect = position( UploadToCloudButton, option ); 0094 uploadButton.rect = uploadRect; 0095 QApplication::style()->drawControl( QStyle::CE_PushButton, &uploadButton, painter ); 0096 } else if ( cached && onCloud ) { 0097 QStyleOptionButton openButton = button( OpenButton, option ); 0098 QRect openRect = position( OpenButton, option ); 0099 openButton.rect = openRect; 0100 QApplication::style()->drawControl( QStyle::CE_PushButton, &openButton, painter ); 0101 0102 QStyleOptionButton cacheRemoveButton = button( RemoveFromCacheButton, option ); 0103 QRect cacheRemoveRect = position( RemoveFromCacheButton, option ); 0104 cacheRemoveButton.rect = cacheRemoveRect; 0105 QApplication::style()->drawControl( QStyle::CE_PushButton, &cacheRemoveButton, painter ); 0106 } 0107 } 0108 0109 QSize RouteItemDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const 0110 { 0111 if ( index.column() == 0 ) { 0112 QTextDocument doc; 0113 doc.setDefaultFont( option.font ); 0114 doc.setTextWidth( qMax( 128, m_view->contentsRect().width() - m_previewSize - buttonWidth( option ) ) ); 0115 doc.setHtml( text( index ) ); 0116 return QSize( qMax( 256, qRound( m_previewSize + buttonWidth( option ) + doc.size().width() + m_margin * 2 ) ), 0117 qMax( m_previewSize + m_margin * 2, qRound( doc.size().height() ) ) ); 0118 } 0119 0120 return QSize(); 0121 } 0122 0123 bool RouteItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index ) 0124 { 0125 Q_UNUSED( model ); 0126 0127 if ( ( event->type() == QEvent::MouseButtonRelease ) ) { 0128 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>( event ); 0129 QPoint pos = mouseEvent->pos(); 0130 0131 bool cached = index.data( CloudRouteModel::IsCached ).toBool(); 0132 bool onCloud = index.data( CloudRouteModel::IsOnCloud ).toBool(); 0133 0134 if( cached && !onCloud ) { 0135 QRect uploadRect = position( UploadToCloudButton, option ); 0136 0137 if ( uploadRect.contains( pos ) ) { 0138 QString timestamp = index.data( CloudRouteModel::Timestamp ).toString(); 0139 emit uploadToCloudButtonClicked( timestamp ); 0140 return true; 0141 } 0142 } 0143 0144 if ( cached ) { 0145 QRect openRect = position( OpenButton, option ); 0146 QRect cacheRemoveRect = position( RemoveFromCacheButton, option ); 0147 0148 if ( openRect.contains( pos ) ) { 0149 QString timestamp = index.data( CloudRouteModel::Timestamp ).toString(); 0150 emit openButtonClicked( timestamp ); 0151 return true; 0152 } else if ( cacheRemoveRect.contains( pos ) ) { 0153 QString timestamp = index.data( CloudRouteModel::Timestamp ).toString(); 0154 emit removeFromCacheButtonClicked( timestamp ); 0155 return true; 0156 } 0157 } else { 0158 QRect downloadRect = position( DownloadButton, option ); 0159 QRect cloudRemoveRect = position( RemoveFromCloudButton, option ); 0160 0161 if ( downloadRect.contains( pos ) ) { 0162 QString timestamp = index.data( CloudRouteModel::Timestamp ).toString(); 0163 m_model->setDownloadingItem( index ); 0164 emit downloadButtonClicked( timestamp ); 0165 return true; 0166 } 0167 0168 if ( cloudRemoveRect.contains( pos ) ) { 0169 QString timestamp = index.data( CloudRouteModel::Timestamp ).toString(); 0170 emit deleteButtonClicked( timestamp ); 0171 return true; 0172 } 0173 } 0174 } 0175 0176 return false; 0177 } 0178 0179 int RouteItemDelegate::buttonWidth( const QStyleOptionViewItem &option ) const 0180 { 0181 if ( m_buttonWidth <= 0 ) { 0182 int const openWidth = option.fontMetrics.size( 0, tr( "Open" ) ).width(); 0183 int const downloadWidth = option.fontMetrics.size( 0, tr( "Load" ) ).width(); 0184 int const cacheWidth = option.fontMetrics.size( 0, tr( "Remove from device" ) ).width(); 0185 int const cloudWidth = option.fontMetrics.size( 0, tr( "Delete from cloud" ) ).width(); 0186 m_buttonWidth = 2 * m_iconSize + qMax( qMax( openWidth, downloadWidth ), qMax( cacheWidth, cloudWidth ) ); 0187 } 0188 0189 return m_buttonWidth; 0190 } 0191 0192 QStyleOptionButton RouteItemDelegate::button( Element element, const QStyleOptionViewItem &option ) const 0193 { 0194 QStyleOptionButton result; 0195 result.state = option.state; 0196 result.state &= ~QStyle::State_HasFocus; 0197 0198 result.palette = option.palette; 0199 result.features = QStyleOptionButton::None; 0200 0201 switch ( element ) { 0202 case OpenButton: 0203 result.text = tr( "Open" ); 0204 result.icon = QIcon(QStringLiteral(":/marble/document-open.png")); 0205 result.iconSize = QSize( m_iconSize, m_iconSize ); 0206 break; 0207 case DownloadButton: 0208 result.text = tr( "Load" ); 0209 result.icon = QIcon(QStringLiteral(":/marble/dialog-ok.png")); 0210 result.iconSize = QSize( m_iconSize, m_iconSize ); 0211 break; 0212 case RemoveFromCacheButton: 0213 result.text = tr( "Remove from device" ); 0214 result.icon = QIcon(QStringLiteral(":/marble/edit-clear.png")); 0215 result.iconSize = QSize( m_iconSize, m_iconSize ); 0216 break; 0217 case RemoveFromCloudButton: 0218 result.text = tr( "Delete from cloud" ); 0219 result.icon = QIcon(QStringLiteral(":/marble/edit-delete.png")); 0220 result.iconSize = QSize( m_iconSize, m_iconSize ); 0221 break; 0222 case UploadToCloudButton: 0223 result.text = tr( "Upload to cloud" ); 0224 result.icon = QIcon(QStringLiteral(":/icons/cloud-upload.png")); 0225 result.iconSize = QSize( m_iconSize, m_iconSize ); 0226 break; 0227 default: 0228 // Ignored. 0229 break; 0230 } 0231 0232 return result; 0233 } 0234 0235 QString RouteItemDelegate::text( const QModelIndex& index ) 0236 { 0237 return QString( "%0" ).arg( index.data( CloudRouteModel::Name ).toString() ); 0238 // TODO: Show distance and duration 0239 //return QString( "%0<br /><b>Duration:</b> %1<br/><b>Distance:</b> %2" ) 0240 //.arg( index.data( CloudRouteModel::Name ).toString() ) 0241 //.arg( index.data( CloudRouteModel::Duration ).toString() ) 0242 //.arg( index.data( CloudRouteModel::Distance ).toString() ); 0243 } 0244 0245 QRect RouteItemDelegate::position( Element element, const QStyleOptionViewItem& option ) const 0246 { 0247 int const width = buttonWidth( option ); 0248 QPoint const firstColumn = option.rect.topLeft() + QPoint( m_margin, m_margin ); 0249 QPoint const secondColumn = firstColumn + QPoint( m_previewSize + m_margin, 0 ); 0250 QPoint const thirdColumn = QPoint( option.rect.width() - width - option.decorationSize.width(), firstColumn.y() ); 0251 0252 switch (element) { 0253 case Text: 0254 return QRect( secondColumn, QSize( thirdColumn.x() - secondColumn.x(), option.rect.height() ) ); 0255 case OpenButton: 0256 case DownloadButton: 0257 { 0258 QStyleOptionButton optionButton = button( element, option ); 0259 QSize size = option.fontMetrics.size( 0, optionButton.text ) + QSize( 4, 4 ); 0260 QSize buttonSize = QApplication::style()->sizeFromContents( QStyle::CT_PushButton, &optionButton, size ); 0261 buttonSize.setWidth( width ); 0262 return QRect( thirdColumn, buttonSize ); 0263 } 0264 case RemoveFromCacheButton: 0265 case RemoveFromCloudButton: 0266 { 0267 QStyleOptionButton optionButton = button( element, option ); 0268 QSize size = option.fontMetrics.size( 0, optionButton.text ) + QSize( 4, 4 ); 0269 QSize buttonSize = QApplication::style()->sizeFromContents( QStyle::CT_PushButton, &optionButton, size ); 0270 buttonSize.setWidth( width ); 0271 return QRect( thirdColumn + QPoint( 0, buttonSize.height() ), buttonSize ); 0272 } 0273 case Progressbar: 0274 { 0275 QSize const progressSize = QSize( width, option.fontMetrics.height() + 4 ); 0276 return QRect( thirdColumn + QPoint( 0, 10 ), progressSize ); 0277 } 0278 case Preview: 0279 { 0280 return QRect( firstColumn, QSize( m_previewSize, m_previewSize) ); 0281 } 0282 case UploadToCloudButton: 0283 { 0284 QStyleOptionButton optionButton = button( element, option ); 0285 QSize size = option.fontMetrics.size( 0, optionButton.text ) + QSize( 4, 4 ); 0286 QSize buttonSize = QApplication::style()->sizeFromContents( QStyle::CT_PushButton, &optionButton, size ); 0287 buttonSize.setWidth( width ); 0288 return QRect( thirdColumn + QPoint( 0, buttonSize.height() * 2 ), buttonSize ); 0289 } 0290 } 0291 0292 return QRect(); 0293 } 0294 0295 } 0296 0297 #include "moc_RouteItemDelegate.cpp"