Marble

RouteSyncManager.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2013 Utku Aydın <[email protected]>
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 
27 namespace Marble
28 {
29 
30 /**
31  * Private class for RouteSyncManager.
32  */
33 class Q_DECL_HIDDEN RouteSyncManager::Private {
34 public:
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 
48 RouteSyncManager::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 
58 RouteSyncManager::Private::~Private()
59 {
60  delete m_model;
61 }
62 
63 RouteSyncManager::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 
75 RouteSyncManager::~RouteSyncManager()
76 {
77  delete d;
78 }
79 
80 void RouteSyncManager::setRoutingManager(RoutingManager *routingManager)
81 {
82  d->m_routingManager = routingManager;
83 }
84 
85 bool RouteSyncManager::isRouteSyncEnabled() const
86 {
87  return d->m_routeSyncEnabled && d->m_cloudSyncManager && d->m_cloudSyncManager->isSyncEnabled();
88 }
89 
90 void 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 
98 CloudRouteModel* RouteSyncManager::model()
99 {
100  return d->m_model;
101 }
102 
103 QString RouteSyncManager::generateTimestamp() const
104 {
105  qint64 timestamp = QDateTime::currentMSecsSinceEpoch();
106  return QString::number( timestamp );
107 }
108 
109 QString 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 
124 void RouteSyncManager::uploadRoute()
125 {
126  if( !d->m_cloudSyncManager->workOffline() ) {
127  d->m_owncloudBackend.uploadRoute( saveDisplayedToCache() );
128  }
129 }
130 
131 QVector<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 
185 void RouteSyncManager::uploadRoute( const QString &timestamp )
186 {
187  if( !d->m_cloudSyncManager->workOffline() ) {
188  d->m_owncloudBackend.uploadRoute( timestamp );
189  }
190 }
191 
192 void 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 
210 void RouteSyncManager::downloadRoute( const QString &timestamp )
211 {
212  d->m_owncloudBackend.downloadRoute( timestamp );
213 }
214 
215 void 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 
227 void RouteSyncManager::deleteRoute(const QString &timestamp )
228 {
229  d->m_owncloudBackend.deleteRoute( timestamp );
230 }
231 
232 void RouteSyncManager::removeRouteFromCache( const QString &timestamp )
233 {
234  d->m_owncloudBackend.removeFromCache( d->m_cacheDir, timestamp );
235 }
236 
237 void RouteSyncManager::updateUploadProgressbar( qint64 sent, qint64 total )
238 {
239  emit routeUploadProgress( sent, total );
240  if( sent == total ) {
241  prepareRouteList();
242  }
243 }
244 
245 void 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"
void append(const T &value)
QString number(int n, int base)
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
void append(const T &value)
qint64 currentMSecsSinceEpoch()
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void clear()
KOSM_EXPORT double distance(const std::vector< const OSM::Node * > &path, Coordinate coord)
int length() const const
Binds a QML item to a specific geodetic location in screen coordinates.
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString left(int n) const const
const QChar at(int position) const const
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:31
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.