File indexing completed on 2024-05-05 03:49:14

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2013 Utku Aydın <utkuaydin34@gmail.com>
0004 //
0005 
0006 #include "CloudRouteModel.h"
0007 
0008 #include "RouteItem.h"
0009 
0010 #include "MarbleDebug.h"
0011 #include "MarbleDirs.h"
0012 
0013 #include <QIcon>
0014 #include <QUrl>
0015 #include <QSet>
0016 #include <QVector>
0017 #include <QNetworkRequest>
0018 #include <QNetworkReply>
0019 #include <QNetworkAccessManager>
0020 
0021 namespace Marble {
0022 
0023 class Q_DECL_HIDDEN CloudRouteModel::Private {
0024 
0025 public:
0026     Private();
0027 
0028     QVector<RouteItem> m_items;
0029     QString m_cacheDir;
0030     QPersistentModelIndex m_downloading;
0031     qint64 m_totalSize;
0032     qint64 m_downloadedSize;
0033 
0034     QNetworkAccessManager m_network;
0035     QMap<QNetworkReply*, int> m_previewQueue;
0036     QSet<QString> m_requestedPreviews;
0037 
0038     QHash<int, QByteArray> m_roleNames;
0039 };
0040 
0041 CloudRouteModel::Private::Private() :
0042     m_totalSize( -1 ),
0043     m_downloadedSize( 0 )
0044 {
0045     m_cacheDir = MarbleDirs::localPath() + QLatin1String("/cloudsync/cache/routes/");
0046 }
0047 
0048 CloudRouteModel::CloudRouteModel( QObject* parent ) :
0049     QAbstractListModel( parent ), d( new Private() )
0050 {
0051     connect( &(d->m_network), SIGNAL(finished(QNetworkReply*)),
0052              this, SLOT(setPreview(QNetworkReply*)) );
0053 
0054     QHash<int, QByteArray> roles = roleNames();
0055     roles[ Name ] = "name";
0056     roles[ Timestamp ] = "identifier";
0057     roles[ PreviewUrl ] = "previewUrl";
0058     roles[ Distance ] = "distance";
0059     roles[ Duration ] = "duration";
0060     roles[ IsCached ] = "isCached";
0061     roles[ IsDownloading ] = "isDownloading";
0062     roles[ IsOnCloud ] = "isOnCloud";
0063     d->m_roleNames = roles;
0064 }
0065 
0066 CloudRouteModel::~CloudRouteModel()
0067 {
0068     delete d;
0069 }
0070 
0071 QVariant CloudRouteModel::data( const QModelIndex& index, int role ) const
0072 {
0073     if ( index.isValid() && index.row() >= 0 && index.row() < d->m_items.size() ) {
0074         switch( role ) {
0075         case Qt::DecorationRole: return preview( index );
0076         case Timestamp: return d->m_items.at( index.row() ).identifier();
0077         case Name: return d->m_items.at( index.row() ).name();
0078         case PreviewUrl: return d->m_items.at( index.row() ).previewUrl();
0079         case Distance: return d->m_items.at( index.row() ).distance();
0080         case Duration: return d->m_items.at( index.row() ).duration();
0081         case IsCached: return isCached( index );
0082         case IsDownloading: return isDownloading( index );
0083         case IsOnCloud: return d->m_items.at( index.row() ).onCloud();
0084         }
0085     }
0086     
0087     return QVariant();
0088 }
0089 
0090 int CloudRouteModel::rowCount( const QModelIndex &parent ) const
0091 {
0092     return parent.isValid() ? 0 : d->m_items.count();
0093 }
0094 
0095 QHash<int, QByteArray> CloudRouteModel::roleNames() const
0096 {
0097     return d->m_roleNames;
0098 }
0099 
0100 void CloudRouteModel::setItems( const QVector<RouteItem> &items )
0101 {
0102     beginResetModel();
0103     d->m_items = items;
0104     d->m_previewQueue.clear();
0105     d->m_requestedPreviews.clear();
0106     endResetModel();
0107 }
0108 
0109 bool CloudRouteModel::isCached( const QModelIndex &index ) const
0110 {
0111     QFileInfo cacheDir(d->m_cacheDir + index.data(Timestamp).toString() + QLatin1String(".kml"));
0112     return cacheDir.exists();
0113 }
0114 
0115 QPersistentModelIndex CloudRouteModel::downloadingItem() const
0116 {
0117     return d->m_downloading;
0118 }
0119 
0120 void CloudRouteModel::setDownloadingItem(const QPersistentModelIndex &index )
0121 {
0122     d->m_downloading = index;
0123 }
0124 
0125 bool CloudRouteModel::isDownloading( const QModelIndex &index ) const
0126 {
0127     return d->m_downloading == index;
0128 }
0129 
0130 qint64 CloudRouteModel::totalSize() const
0131 {
0132     return d->m_totalSize;
0133 }
0134 
0135 qint64 CloudRouteModel::downloadedSize() const
0136 {
0137     return d->m_downloadedSize;
0138 }
0139 
0140 QIcon CloudRouteModel::preview( const QModelIndex &index ) const
0141 {
0142     QString timestamp = d->m_items.at( index.row() ).identifier();
0143     if( d->m_items.at( index.row() ).preview().isNull() && !d->m_requestedPreviews.contains( timestamp ) ) {
0144         QUrl url( d->m_items.at( index.row() ).previewUrl() );
0145         QNetworkRequest request( url );
0146         QNetworkReply *reply = d->m_network.get( request );
0147         d->m_previewQueue.insert( reply, index.row() );
0148         d->m_requestedPreviews.insert( timestamp );
0149     }
0150 
0151     return d->m_items.at( index.row() ).preview();
0152 }
0153 
0154 void CloudRouteModel::setPreview( QNetworkReply *reply )
0155 {
0156     int position = d->m_previewQueue.take( reply );
0157 
0158     if( position >= d->m_items.count() ) {
0159         return;
0160     }
0161 
0162     RouteItem &route = d->m_items[ position ];
0163     QIcon icon( QPixmap::fromImage( QImage::fromData( reply->readAll() ) ) );
0164     route.setPreview( icon );
0165     d->m_requestedPreviews.remove( route.identifier() );
0166 }
0167 
0168 void CloudRouteModel::updateProgress( qint64 currentSize, qint64 totalSize )
0169 {
0170     d->m_totalSize = totalSize;
0171     d->m_downloadedSize = currentSize;
0172     dataChanged( d->m_downloading, d->m_downloading );
0173     if( currentSize == totalSize ) {
0174         d->m_downloading = QPersistentModelIndex();
0175         d->m_totalSize = -1;
0176         d->m_downloadedSize = 0;
0177     }
0178 }
0179 
0180 }
0181 
0182 #include "moc_CloudRouteModel.cpp"