Marble

RouteSyncManager.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2013 Utku Aydın <utkuaydin34@gmail.com>
4//
5
6#include "RouteSyncManager.h"
7
8#include "GeoDataParser.h"
9#include "MarbleDirs.h"
10#include "MarbleDebug.h"
11#include "GeoDataFolder.h"
12#include "GeoDataDocument.h"
13#include "GeoDataPlacemark.h"
14#include "CloudRouteModel.h"
15#include "CloudRoutesDialog.h"
16#include "CloudSyncManager.h"
17#include "OwncloudSyncBackend.h"
18#include "RouteItem.h"
19#include "RoutingManager.h"
20
21#include <QDir>
22#include <QUrl>
23#include <QFile>
24#include <QIcon>
25#include <QPointer>
26
27namespace Marble
28{
29
30/**
31 * Private class for RouteSyncManager.
32 */
33class Q_DECL_HIDDEN RouteSyncManager::Private {
34public:
35 Private( CloudSyncManager *cloudSyncManager );
36 ~Private();
37
38 bool m_routeSyncEnabled;
39 CloudSyncManager *m_cloudSyncManager;
40 RoutingManager *m_routingManager;
41 CloudRouteModel *m_model;
42
43 QDir m_cacheDir;
44 OwncloudSyncBackend m_owncloudBackend;
45 QVector<RouteItem> m_routeList;
46};
47
48RouteSyncManager::Private::Private( CloudSyncManager *cloudSyncManager ) :
49 m_routeSyncEnabled( false ),
50 m_cloudSyncManager( cloudSyncManager ),
51 m_routingManager( nullptr ),
52 m_model( new CloudRouteModel() ),
53 m_owncloudBackend( cloudSyncManager )
54{
55 m_cacheDir = QDir(MarbleDirs::localPath() + QLatin1String("/cloudsync/cache/routes/"));
56}
57
58RouteSyncManager::Private::~Private()
59{
60 delete m_model;
61}
62
63RouteSyncManager::RouteSyncManager(CloudSyncManager *cloudSyncManager) :
64 d( new Private( cloudSyncManager ) )
65{
66 connect( &d->m_owncloudBackend, SIGNAL(routeUploadProgress(qint64,qint64)), this, SLOT(updateUploadProgressbar(qint64,qint64)) );
67 connect( &d->m_owncloudBackend, SIGNAL(routeListDownloaded(QVector<RouteItem>)), this, SLOT(setRouteModelItems(QVector<RouteItem>)) );
68 connect( &d->m_owncloudBackend, SIGNAL(routeListDownloadProgress(qint64,qint64)), this, SIGNAL(routeListDownloadProgress(qint64,qint64)) );
69 connect( &d->m_owncloudBackend, SIGNAL(routeDownloadProgress(qint64,qint64)), d->m_model, SLOT(updateProgress(qint64,qint64)) );
70 connect( &d->m_owncloudBackend, SIGNAL(routeDownloaded()), this, SLOT(prepareRouteList()) );
71 connect( &d->m_owncloudBackend, SIGNAL(routeDeleted()), this, SLOT(prepareRouteList()) );
72 connect( &d->m_owncloudBackend, SIGNAL(removedFromCache(QString)), this, SLOT(prepareRouteList()) );
73}
74
75RouteSyncManager::~RouteSyncManager()
76{
77 delete d;
78}
79
80void RouteSyncManager::setRoutingManager(RoutingManager *routingManager)
81{
82 d->m_routingManager = routingManager;
83}
84
85bool RouteSyncManager::isRouteSyncEnabled() const
86{
87 return d->m_routeSyncEnabled && d->m_cloudSyncManager && d->m_cloudSyncManager->isSyncEnabled();
88}
89
90void RouteSyncManager::setRouteSyncEnabled( bool enabled )
91{
92 if ( d->m_routeSyncEnabled != enabled ) {
93 d->m_routeSyncEnabled = enabled;
94 emit routeSyncEnabledChanged( d->m_routeSyncEnabled );
95 }
96}
97
98CloudRouteModel* RouteSyncManager::model()
99{
100 return d->m_model;
101}
102
103QString RouteSyncManager::generateTimestamp() const
104{
105 qint64 timestamp = QDateTime::currentMSecsSinceEpoch();
106 return QString::number( timestamp );
107}
108
109QString RouteSyncManager::saveDisplayedToCache() const
110{
111 if ( !d->m_routingManager ) {
112 qWarning() << "RoutingManager instance not set in RouteSyncManager. Cannot save current route.";
113 return QString();
114 }
115
116 d->m_cacheDir.mkpath( d->m_cacheDir.absolutePath() );
117
118 const QString timestamp = generateTimestamp();
119 const QString filename = d->m_cacheDir.absolutePath() + QLatin1Char('/') + timestamp + QLatin1String(".kml");
120 d->m_routingManager->saveRoute( filename );
121 return timestamp;
122}
123
124void RouteSyncManager::uploadRoute()
125{
126 if( !d->m_cloudSyncManager->workOffline() ) {
127 d->m_owncloudBackend.uploadRoute( saveDisplayedToCache() );
128 }
129}
130
131QVector<RouteItem> RouteSyncManager::cachedRouteList() const
132{
133 QVector<RouteItem> routeList;
134 QStringList cachedRoutes = d->m_cacheDir.entryList( QStringList() << "*.kml", QDir::Files );
135 for ( const QString &routeFilename: cachedRoutes ) {
136 QFile file(d->m_cacheDir.absolutePath() + QLatin1Char('/') + routeFilename);
137 file.open( QFile::ReadOnly );
138
139 GeoDataParser parser( GeoData_KML );
140 if( !parser.read( &file ) ) {
141 mDebug() << QLatin1String("Could not read ") + routeFilename;
142 }
143
144 file.close();
145
146 QString routeName;
147 GeoDocument *geoDoc = parser.releaseDocument();
148 GeoDataDocument *container = dynamic_cast<GeoDataDocument*>( geoDoc );
149 if ( container && container->size() > 0 ) {
150 GeoDataFolder *folder = container->folderList().at( 0 );
151 for ( GeoDataPlacemark *placemark: folder->placemarkList() ) {
152 routeName += placemark->name() + QLatin1String(" - ");
153 }
154 }
155
156 routeName = routeName.left( routeName.length() - 3 );
157 QString timestamp = routeFilename.left( routeFilename.length() - 4 );
159 QString duration(QLatin1Char('0'));
160
161 QString previewPath = QString( "%0/preview/%1.jpg" ).arg( d->m_cacheDir.absolutePath(), timestamp );
162 QIcon preview;
163
164 if( QFile( previewPath ).exists() ) {
165 preview = QIcon( previewPath );
166 }
167
168 // Would that work on Windows?
169 QUrl previewUrl( QString( "file://%0" ).arg( previewPath ) );
170
171 RouteItem item;
172 item.setIdentifier( timestamp );
173 item.setName( routeName );
174 item.setDistance( distance );
175 item.setDistance( duration );
176 item.setPreview( preview );
177 item.setPreviewUrl( previewUrl );
178 item.setOnCloud( false );
179 routeList.append( item );
180 }
181
182 return routeList;
183}
184
185void RouteSyncManager::uploadRoute( const QString &timestamp )
186{
187 if( !d->m_cloudSyncManager->workOffline() ) {
188 d->m_owncloudBackend.uploadRoute( timestamp );
189 }
190}
191
192void RouteSyncManager::prepareRouteList()
193{
194 d->m_routeList.clear();
195
196 QVector<RouteItem> cachedRoutes = cachedRouteList();
197 for( const RouteItem &item: cachedRoutes ) {
198 d->m_routeList.append( item );
199 }
200
201 if( !d->m_cloudSyncManager->workOffline() ) {
202 d->m_owncloudBackend.downloadRouteList();
203 } else {
204 // If not offline, setRouteModelItems() does this after
205 // appending downloaded items to the list.
206 d->m_model->setItems( d->m_routeList );
207 }
208}
209
210void RouteSyncManager::downloadRoute( const QString &timestamp )
211{
212 d->m_owncloudBackend.downloadRoute( timestamp );
213}
214
215void RouteSyncManager::openRoute(const QString &timestamp )
216{
217 if ( !d->m_routingManager ) {
218 qWarning() << "RoutingManager instance not set in RouteSyncManager. Cannot open route " << timestamp;
219 return;
220 }
221
222 d->m_routingManager->loadRoute( QString( "%0/%1.kml" )
223 .arg( d->m_cacheDir.absolutePath() )
224 .arg( timestamp ) );
225}
226
227void RouteSyncManager::deleteRoute(const QString &timestamp )
228{
229 d->m_owncloudBackend.deleteRoute( timestamp );
230}
231
232void RouteSyncManager::removeRouteFromCache( const QString &timestamp )
233{
234 d->m_owncloudBackend.removeFromCache( d->m_cacheDir, timestamp );
235}
236
237void RouteSyncManager::updateUploadProgressbar( qint64 sent, qint64 total )
238{
239 emit routeUploadProgress( sent, total );
240 if( sent == total ) {
241 prepareRouteList();
242 }
243}
244
245void RouteSyncManager::setRouteModelItems( const QVector<RouteItem> &routeList )
246{
247 if( d->m_routeList.count() > 0 ) {
248 QStringList cloudRoutes;
249 for( const RouteItem &item: routeList ) {
250 cloudRoutes.append( item.identifier() );
251 }
252
253 for( int position = 0; position < d->m_routeList.count(); position++ ) {
254 if( cloudRoutes.contains( d->m_routeList.at( position ).identifier() ) ) {
255 d->m_routeList[ position ].setOnCloud( true );
256 }
257 }
258
259 QStringList cachedRoutes;
260 for( const RouteItem &item: d->m_routeList ) {
261 cachedRoutes.append( item.identifier() );
262 }
263
264 for( const RouteItem &item: routeList ) {
265 if( !cachedRoutes.contains( item.identifier() ) ) {
266 d->m_routeList.append( item );
267 }
268 }
269 } else {
270 for( const RouteItem &item: routeList ) {
271 d->m_routeList.append( item );
272 }
273 }
274
275 d->m_model->setItems( d->m_routeList );
276}
277
278}
279
280#include "moc_RouteSyncManager.cpp"
Binds a QML item to a specific geodetic location in screen coordinates.
KOSM_EXPORT double distance(const std::vector< const OSM::Node * > &path, Coordinate coord)
qint64 currentMSecsSinceEpoch()
void append(QList< T > &&value)
void clear()
QString arg(Args &&... args) const const
const QChar at(qsizetype position) const const
QString left(qsizetype n) const const
qsizetype length() const const
QString number(double n, char format, int precision)
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
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.