• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.12
  • kdeedu
  • marble
  • src
  • lib
  • marble
  • cloudsync
BookmarkSyncManager.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2013 Utku Aydın <utkuaydin34@gmail.com>
9 //
10 
11 #include "BookmarkSyncManager.h"
12 
13 #include "GeoWriter.h"
14 #include "MarbleMath.h"
15 #include "MarbleDirs.h"
16 #include "MarbleDebug.h"
17 #include "GeoDataParser.h"
18 #include "GeoDataFolder.h"
19 #include "GeoDataDocument.h"
20 #include "CloudSyncManager.h"
21 #include "GeoDataCoordinates.h"
22 #include "OwncloudSyncBackend.h"
23 #include "MarbleModel.h"
24 #include "BookmarkManager.h"
25 
26 #include <QFile>
27 #include <QBuffer>
28 #include <QScriptValue>
29 #include <QScriptEngine>
30 #include <QTemporaryFile>
31 #include <QNetworkAccessManager>
32 #include <QTimer>
33 
34 namespace Marble {
35 
36 class DiffItem
37 {
38 public:
39  enum Action {
40  NoAction,
41  Created,
42  Changed,
43  Deleted
44  };
45 
46  enum Status {
47  Source,
48  Destination
49  };
50 
51  QString m_path;
52  Action m_action;
53  Status m_origin;
54  GeoDataPlacemark m_placemarkA;
55  GeoDataPlacemark m_placemarkB;
56 };
57 
58 class BookmarkSyncManager::Private
59 {
60 public:
61  Private( BookmarkSyncManager* parent, CloudSyncManager *cloudSyncManager );
62 
63  BookmarkSyncManager* m_q;
64  CloudSyncManager *m_cloudSyncManager;
65 
66  QNetworkAccessManager m_network;
67  QString m_uploadEndpoint;
68  QString m_downloadEndpoint;
69  QString m_timestampEndpoint;
70 
71  QNetworkReply* m_uploadReply;
72  QNetworkReply* m_downloadReply;
73  QNetworkReply* m_timestampReply;
74 
75  QString m_cloudTimestamp;
76 
77  QString m_cachePath;
78  QString m_localBookmarksPath;
79  QString m_bookmarksTimestamp;
80 
81  QList<DiffItem> m_diffA;
82  QList<DiffItem> m_diffB;
83  QList<DiffItem> m_merged;
84  DiffItem m_conflictItem;
85 
86  BookmarkManager* m_bookmarkManager;
87  QTimer m_syncTimer;
88  bool m_bookmarkSyncEnabled;
89 
95  QUrl endpointUrl( const QString &endpoint );
96 
100  void uploadBookmarks();
101 
105  void downloadBookmarks();
106 
110  void downloadTimestamp();
111 
116  bool cloudBookmarksModified( const QString &cloudTimestamp );
117 
122  void clearCache();
123 
128  QString lastSyncedKmlPath();
129 
137  QList<DiffItem> getPlacemarks(GeoDataDocument *document, GeoDataDocument *other, DiffItem::Status diffDirection );
138 
147  QList<DiffItem> getPlacemarks( GeoDataFolder *folder, QString &path, GeoDataDocument *other, DiffItem::Status diffDirection );
148 
155  GeoDataPlacemark* findPlacemark( GeoDataContainer* container, const GeoDataPlacemark &bookmark ) const;
156 
163  void determineDiffStatus( DiffItem &item, GeoDataDocument* document );
164 
171  QList<DiffItem> diff( QString &sourcePath, QString &destinationPath );
172  QList<DiffItem> diff( QString &sourcePath, QIODevice* destination );
173  QList<DiffItem> diff( QIODevice* source, QString &destinationPath );
174  QList<DiffItem> diff( QIODevice *source, QIODevice* destination );
175 
182  void merge();
183 
190  GeoDataFolder* createFolders( GeoDataContainer *container, QStringList &pathList );
191 
197  GeoDataDocument* constructDocument( const QList<DiffItem> &mergedList );
198 
199  void saveDownloadedToCache( const QByteArray &kml );
200 
201  void parseTimestamp();
202  void copyLocalToCache();
203 
204  void continueSynchronization();
205  void completeSynchronization();
206  void completeMerge();
207  void completeUpload();
208 };
209 
210 BookmarkSyncManager::Private::Private(BookmarkSyncManager *parent, CloudSyncManager *cloudSyncManager ) :
211  m_q( parent ),
212  m_cloudSyncManager( cloudSyncManager ),
213  m_bookmarkManager( 0 ),
214  m_bookmarkSyncEnabled( false )
215 {
216  m_cachePath = QString( "%0/cloudsync/cache/bookmarks" ).arg( MarbleDirs::localPath() );
217  m_localBookmarksPath = QString( "%0/bookmarks/bookmarks.kml" ).arg( MarbleDirs::localPath() );
218  m_downloadEndpoint = "bookmarks/kml";
219  m_uploadEndpoint = "bookmarks/update";
220  m_timestampEndpoint = "bookmarks/timestamp";
221 }
222 
223 BookmarkSyncManager::BookmarkSyncManager( CloudSyncManager *cloudSyncManager ) :
224  QObject(),
225  d( new Private( this, cloudSyncManager ) )
226 {
227  d->m_syncTimer.setInterval( 60 * 60 * 1000 ); // 1 hour. TODO: Make this configurable.
228  connect( &d->m_syncTimer, SIGNAL(timeout()), this, SLOT(startBookmarkSync()) );
229 }
230 
231 BookmarkSyncManager::~BookmarkSyncManager()
232 {
233  delete d;
234 }
235 
236 
237 bool BookmarkSyncManager::isBookmarkSyncEnabled() const
238 {
239  return d->m_bookmarkSyncEnabled;
240 }
241 
242 void BookmarkSyncManager::setBookmarkSyncEnabled( bool enabled )
243 {
244  bool const old_state = isBookmarkSyncEnabled();
245  d->m_bookmarkSyncEnabled = enabled;
246  if ( old_state != isBookmarkSyncEnabled() ) {
247  emit bookmarkSyncEnabledChanged( d->m_bookmarkSyncEnabled );
248  if ( isBookmarkSyncEnabled() ) {
249  startBookmarkSync();
250  }
251  }
252 }
253 
254 void BookmarkSyncManager::setBookmarkManager(BookmarkManager *manager)
255 {
256  d->m_bookmarkManager = manager;
257  connect( manager, SIGNAL(bookmarksChanged()), this, SLOT(startBookmarkSync()) );
258  startBookmarkSync();
259 }
260 
261 void BookmarkSyncManager::startBookmarkSync()
262 {
263  if ( !isBookmarkSyncEnabled() )
264  {
265  return;
266  }
267 
268  d->m_syncTimer.start();
269  d->downloadTimestamp();
270 }
271 
272 QUrl BookmarkSyncManager::Private::endpointUrl( const QString &endpoint )
273 {
274  return QUrl( QString( "%0/%1" ).arg( m_cloudSyncManager->apiUrl().toString() ).arg( endpoint ) );
275 }
276 
277 void BookmarkSyncManager::Private::uploadBookmarks()
278 {
279  QByteArray data;
280  QByteArray lineBreak = "\r\n";
281  QString word = "----MarbleCloudBoundary";
282  QString boundary = QString( "--%0" ).arg( word );
283  QNetworkRequest request( endpointUrl( m_uploadEndpoint ) );
284  request.setHeader( QNetworkRequest::ContentTypeHeader, QString( "multipart/form-data; boundary=%0" ).arg( word ) );
285 
286  data.append( QString( boundary + lineBreak ).toUtf8() );
287  data.append( "Content-Disposition: form-data; name=\"bookmarks\"; filename=\"bookmarks.kml\"" + lineBreak );
288  data.append( "Content-Type: application/vnd.google-earth.kml+xml" + lineBreak + lineBreak );
289 
290  QFile bookmarksFile( m_localBookmarksPath );
291  if( !bookmarksFile.open( QFile::ReadOnly ) ) {
292  mDebug() << "Failed to open file" << bookmarksFile.fileName()
293  << ". It is either missing or not readable.";
294  return;
295  }
296 
297  QByteArray kmlContent = bookmarksFile.readAll();
298  data.append( kmlContent + lineBreak + lineBreak );
299  data.append( QString( boundary ).toUtf8() );
300  bookmarksFile.close();
301 
302  m_uploadReply = m_network.post( request, data );
303  connect( m_uploadReply, SIGNAL(uploadProgress(qint64,qint64)),
304  m_q, SIGNAL(uploadProgress(qint64,qint64)) );
305  connect( m_uploadReply, SIGNAL(finished()),
306  m_q, SLOT(completeUpload()) );
307 }
308 
309 void BookmarkSyncManager::Private::downloadBookmarks()
310 {
311  QNetworkRequest request( endpointUrl( m_downloadEndpoint ) );
312  m_downloadReply = m_network.get( request );
313  connect( m_downloadReply, SIGNAL(finished()),
314  m_q, SLOT(completeSynchronization()) );
315  connect( m_downloadReply, SIGNAL(downloadProgress(qint64,qint64)),
316  m_q, SIGNAL(downloadProgress(qint64,qint64)) );
317 }
318 
319 void BookmarkSyncManager::Private::downloadTimestamp()
320 {
321  mDebug() << "Determining remote bookmark state.";
322  m_timestampReply = m_network.get( QNetworkRequest( endpointUrl( m_timestampEndpoint ) ) );
323  connect( m_timestampReply, SIGNAL(finished()),
324  m_q, SLOT(parseTimestamp()) );
325 }
326 
327 bool BookmarkSyncManager::Private::cloudBookmarksModified( const QString &cloudTimestamp )
328 {
329  QStringList entryList = QDir( m_cachePath ).entryList(
330  // TODO: replace with regex filter that only
331  // allows timestamp filenames
332  QStringList() << "*.kml",
333  QDir::NoFilter, QDir::Name );
334  if( !entryList.isEmpty() ) {
335  QString lastSynced = entryList.last();
336  lastSynced.chop( 4 );
337  return cloudTimestamp != lastSynced;
338  } else {
339  return true; // That will let cloud one get downloaded.
340  }
341 }
342 
343 void BookmarkSyncManager::Private::clearCache()
344 {
345  QDir cacheDir( m_cachePath );
346  QFileInfoList fileInfoList = cacheDir.entryInfoList(
347  QStringList() << "*.kml",
348  QDir::NoFilter, QDir::Name );
349  if( !fileInfoList.isEmpty() ) {
350  foreach ( QFileInfo fileInfo, fileInfoList ) {
351  QFile file( fileInfo.absoluteFilePath() );
352  bool removed = file.remove();
353  if( !removed ) {
354  mDebug() << "Could not delete" << file.fileName() <<
355  "Make sure you have sufficient permissions.";
356  }
357  }
358  }
359 }
360 
361 QString BookmarkSyncManager::Private::lastSyncedKmlPath()
362 {
363  QDir cacheDir( m_cachePath );
364  QFileInfoList fileInfoList = cacheDir.entryInfoList(
365  QStringList() << "*.kml",
366  QDir::NoFilter, QDir::Name );
367  if( !fileInfoList.isEmpty() ) {
368  return fileInfoList.last().absoluteFilePath();
369  } else {
370  return QString();
371  }
372 }
373 
374 QList<DiffItem> BookmarkSyncManager::Private::getPlacemarks( GeoDataDocument *document, GeoDataDocument *other, DiffItem::Status diffDirection )
375 {
376  QList<DiffItem> diffItems;
377  foreach ( GeoDataFolder *folder, document->folderList() ) {
378  QString path = QString( "/%0" ).arg( folder->name() );
379  diffItems.append( getPlacemarks( folder, path, other, diffDirection ) );
380  }
381 
382  return diffItems;
383 }
384 
385 QList<DiffItem> BookmarkSyncManager::Private::getPlacemarks( GeoDataFolder *folder, QString &path, GeoDataDocument *other, DiffItem::Status diffDirection )
386 {
387  QList<DiffItem> diffItems;
388  foreach ( GeoDataFolder *folder, folder->folderList() ) {
389  QString newPath = QString( "%0/%1" ).arg( path, folder->name() );
390  diffItems.append( getPlacemarks( folder, newPath, other, diffDirection ) );
391  }
392 
393  foreach( GeoDataPlacemark *placemark, folder->placemarkList() ) {
394  DiffItem diffItem;
395  diffItem.m_path = path;
396  diffItem.m_placemarkA = *placemark;
397  switch ( diffDirection ) {
398  case DiffItem::Source:
399  diffItem.m_origin = DiffItem::Destination;
400  break;
401  case DiffItem::Destination:
402  diffItem.m_origin = DiffItem::Source;
403  break;
404  default:
405  break;
406  }
407 
408  determineDiffStatus( diffItem, other );
409 
410  if( !( diffItem.m_action == DiffItem::NoAction && diffItem.m_origin == DiffItem::Destination )
411  && !( diffItem.m_action == DiffItem::Changed && diffItem.m_origin == DiffItem::Source ) ) {
412  diffItems.append( diffItem );
413  }
414  }
415 
416  return diffItems;
417 }
418 
419 GeoDataPlacemark* BookmarkSyncManager::Private::findPlacemark( GeoDataContainer* container, const GeoDataPlacemark &bookmark ) const
420 {
421  foreach( GeoDataPlacemark* placemark, container->placemarkList() ) {
422  if ( EARTH_RADIUS * distanceSphere( placemark->coordinate(), bookmark.coordinate() ) <= 1 ) {
423  return placemark;
424  }
425  }
426 
427  foreach( GeoDataFolder* folder, container->folderList() ) {
428  GeoDataPlacemark* placemark = findPlacemark( folder, bookmark );
429  if ( placemark ) {
430  return placemark;
431  }
432  }
433 
434  return 0;
435 }
436 
437 void BookmarkSyncManager::Private::determineDiffStatus( DiffItem &item, GeoDataDocument *document )
438 {
439  GeoDataPlacemark *match = findPlacemark( document, item.m_placemarkA );
440 
441  if( match != 0 ) {
442  item.m_placemarkB = *match;
443  bool nameChanged = item.m_placemarkA.name() != item.m_placemarkB.name();
444  bool descChanged = item.m_placemarkA.description() != item.m_placemarkB.description();
445  bool lookAtChanged = item.m_placemarkA.lookAt()->latitude() != item.m_placemarkB.lookAt()->latitude() ||
446  item.m_placemarkA.lookAt()->longitude() != item.m_placemarkB.lookAt()->longitude() ||
447  item.m_placemarkA.lookAt()->altitude() != item.m_placemarkB.lookAt()->altitude() ||
448  item.m_placemarkA.lookAt()->range() != item.m_placemarkB.lookAt()->range();
449  if( nameChanged || descChanged || lookAtChanged ) {
450  item.m_action = DiffItem::Changed;
451  } else {
452  item.m_action = DiffItem::NoAction;
453  }
454  } else {
455  switch( item.m_origin ) {
456  case DiffItem::Source:
457  item.m_action = DiffItem::Deleted;
458  item.m_placemarkB = item.m_placemarkA; // for conflict purposes
459  break;
460  case DiffItem::Destination:
461  item.m_action = DiffItem::Created;
462  break;
463  }
464 
465  }
466 }
467 
468 QList<DiffItem> BookmarkSyncManager::Private::diff( QString &sourcePath, QString &destinationPath )
469 {
470  QFile fileB( destinationPath );
471  if( !fileB.open( QFile::ReadOnly ) ) {
472  mDebug() << "Could not open file " << fileB.fileName();
473  }
474  return diff( sourcePath, &fileB );
475 }
476 
477 QList<DiffItem> BookmarkSyncManager::Private::diff( QString &sourcePath, QIODevice *fileB )
478 {
479  QFile fileA( sourcePath );
480  if( !fileA.open( QFile::ReadOnly ) ) {
481  mDebug() << "Could not open file " << fileA.fileName();
482  }
483 
484  return diff( &fileA, fileB );
485 }
486 
487 QList<DiffItem> BookmarkSyncManager::Private::diff( QIODevice *source, QString &destinationPath )
488 {
489  QFile fileB( destinationPath );
490  if( !fileB.open( QFile::ReadOnly ) ) {
491  mDebug() << "Could not open file " << fileB.fileName();
492  }
493 
494  return diff( source, &fileB );
495 }
496 
497 QList<DiffItem> BookmarkSyncManager::Private::diff( QIODevice *fileA, QIODevice *fileB )
498 {
499  GeoDataParser parserA( GeoData_KML );
500  parserA.read( fileA );
501  GeoDataDocument *documentA = dynamic_cast<GeoDataDocument*>( parserA.releaseDocument() );
502 
503  GeoDataParser parserB( GeoData_KML );
504  parserB.read( fileB );
505  GeoDataDocument *documentB = dynamic_cast<GeoDataDocument*>( parserB.releaseDocument() );
506 
507  QList<DiffItem> diffItems = getPlacemarks( documentA, documentB, DiffItem::Destination ); // Compare old to new
508  diffItems.append( getPlacemarks( documentB, documentA, DiffItem::Source ) ); // Compare new to old
509 
510  // Compare paths
511  for( int i = 0; i < diffItems.count(); i++ ) {
512  for( int p = i + 1; p < diffItems.count(); p++ ) {
513  if( ( diffItems[i].m_origin == DiffItem::Source )
514  && ( diffItems[i].m_action == DiffItem::NoAction )
515  && ( EARTH_RADIUS * distanceSphere( diffItems[i].m_placemarkA.coordinate(), diffItems[p].m_placemarkB.coordinate() ) <= 1 )
516  && ( EARTH_RADIUS * distanceSphere( diffItems[i].m_placemarkB.coordinate(), diffItems[p].m_placemarkA.coordinate() ) <= 1 )
517  && ( diffItems[i].m_path != diffItems[p].m_path ) ) {
518  diffItems[p].m_action = DiffItem::Changed;
519  }
520  }
521  }
522 
523  return diffItems;
524 }
525 
526 void BookmarkSyncManager::Private::merge()
527 {
528  foreach( DiffItem itemA, m_diffA ) {
529  if( itemA.m_action == DiffItem::NoAction ) {
530  bool deleted = false;
531  bool changed = false;
532  DiffItem other;
533 
534  foreach( DiffItem itemB, m_diffB ) {
535  if( EARTH_RADIUS * distanceSphere( itemA.m_placemarkA.coordinate(), itemB.m_placemarkA.coordinate() ) <= 1 ) {
536  if( itemB.m_action == DiffItem::Deleted ) {
537  deleted = true;
538  } else if( itemB.m_action == DiffItem::Changed ) {
539  changed = true;
540  other = itemB;
541  }
542  }
543  }
544  if( changed ) {
545  m_merged.append( other );
546  } else if( !deleted ) {
547  m_merged.append( itemA );
548  }
549  } else if( itemA.m_action == DiffItem::Created ) {
550  m_merged.append( itemA );
551  } else if( itemA.m_action == DiffItem::Changed || itemA.m_action == DiffItem::Deleted ) {
552  bool conflict = false;
553  DiffItem other;
554 
555  foreach( DiffItem itemB, m_diffB ) {
556  if( EARTH_RADIUS * distanceSphere( itemA.m_placemarkB.coordinate(), itemB.m_placemarkB.coordinate() ) <= 1 ) {
557  if( ( itemA.m_action == DiffItem::Changed && ( itemB.m_action == DiffItem::Changed || itemB.m_action == DiffItem::Deleted ) )
558  || ( itemA.m_action == DiffItem::Deleted && itemB.m_action == DiffItem::Changed ) ) {
559  conflict = true;
560  other = itemB;
561  }
562  }
563  }
564 
565  if( !conflict && itemA.m_action == DiffItem::Changed ) {
566  m_merged.append( itemA );
567  } else if ( conflict ) {
568  m_conflictItem = other;
569  MergeItem *mergeItem = new MergeItem();
570  mergeItem->setPathA( itemA.m_path );
571  mergeItem->setPathB( other.m_path );
572  mergeItem->setPlacemarkA( itemA.m_placemarkA );
573  mergeItem->setPlacemarkB( other.m_placemarkA );
574 
575  switch( itemA.m_action ) {
576  case DiffItem::Changed:
577  mergeItem->setActionA( MergeItem::Changed );
578  break;
579  case DiffItem::Deleted:
580  mergeItem->setActionA( MergeItem::Deleted );
581  break;
582  default:
583  break;
584  }
585 
586  switch( other.m_action ) {
587  case DiffItem::Changed:
588  mergeItem->setActionB( MergeItem::Changed );
589  break;
590  case DiffItem::Deleted:
591  mergeItem->setActionB( MergeItem::Deleted );
592  break;
593  default:
594  break;
595  }
596 
597  emit m_q->mergeConflict( mergeItem );
598  return;
599  }
600  }
601 
602  if( !m_diffA.isEmpty() ) {
603  m_diffA.removeFirst();
604  }
605  }
606 
607  foreach( DiffItem itemB, m_diffB ) {
608  if( itemB.m_action == DiffItem::Created ) {
609  m_merged.append( itemB );
610  }
611  }
612 
613  completeMerge();
614 }
615 
616 GeoDataFolder* BookmarkSyncManager::Private::createFolders( GeoDataContainer *container, QStringList &pathList )
617 {
618  GeoDataFolder *folder = 0;
619  if( pathList.count() > 0 ) {
620  QString name = pathList.takeFirst();
621 
622  foreach( GeoDataFolder *otherFolder, container->folderList() ) {
623  if( otherFolder->name() == name ) {
624  folder = otherFolder;
625  }
626  }
627 
628  if( folder == 0 ) {
629  folder = new GeoDataFolder();
630  folder->setName( name );
631  container->append( folder );
632  }
633 
634  if( pathList.count() == 0 ) {
635  return folder;
636  }
637  }
638 
639  return createFolders( folder, pathList );
640 }
641 
642 GeoDataDocument* BookmarkSyncManager::Private::constructDocument( const QList<DiffItem> &mergedList )
643 {
644  GeoDataDocument *document = new GeoDataDocument();
645  document->setName( tr( "Bookmarks" ) );
646 
647  foreach( DiffItem item, mergedList ) {
648  GeoDataPlacemark *placemark = new GeoDataPlacemark( item.m_placemarkA );
649  QStringList splitted = item.m_path.split( "/", QString::SkipEmptyParts );
650  GeoDataFolder *folder = createFolders( document, splitted );
651  folder->append( placemark );
652  }
653 
654  return document;
655 }
656 
657 void BookmarkSyncManager::resolveConflict( MergeItem *item )
658 {
659  DiffItem diffItem;
660 
661  switch( item->resolution() ) {
662  case MergeItem::A:
663  if( !d->m_diffA.isEmpty() ) {
664  diffItem = d->m_diffA.first();
665  break;
666  }
667  case MergeItem::B:
668  diffItem = d->m_conflictItem;
669  break;
670  default:
671  return; // It shouldn't happen.
672  }
673 
674  if( diffItem.m_action != DiffItem::Deleted ) {
675  d->m_merged.append( diffItem );
676  }
677 
678  if( !d->m_diffA.isEmpty() ) {
679  d->m_diffA.removeFirst();
680  }
681 
682  d->merge();
683 }
684 
685 void BookmarkSyncManager::Private::saveDownloadedToCache( const QByteArray &kml )
686 {
687  QString localBookmarksDir = m_localBookmarksPath;
688  QDir().mkdir( localBookmarksDir.remove( "bookmarks.kml" ) );
689  QFile bookmarksFile( m_localBookmarksPath );
690  if( !bookmarksFile.open( QFile::ReadWrite ) ) {
691  mDebug() << "Failed to open file" << bookmarksFile.fileName()
692  << ". It is either missing or not readable.";
693  return;
694  }
695 
696  bookmarksFile.write( kml );
697  bookmarksFile.close();
698  copyLocalToCache();
699 }
700 
701 void BookmarkSyncManager::Private::parseTimestamp()
702 {
703  QString response = m_timestampReply->readAll();
704  QScriptEngine engine;
705  QScriptValue parsedResponse = engine.evaluate( QString( "(%0)" ).arg( response ) );
706  QString timestamp = parsedResponse.property( "data" ).toString();
707  m_cloudTimestamp = timestamp;
708  mDebug() << "Remote bookmark timestamp is " << m_cloudTimestamp;
709  continueSynchronization();
710 }
711 void BookmarkSyncManager::Private::copyLocalToCache()
712 {
713  QDir().mkpath( m_cachePath );
714  clearCache();
715 
716  QFile bookmarksFile( m_localBookmarksPath );
717  bookmarksFile.copy( QString( "%0/%1.kml" ).arg( m_cachePath, m_cloudTimestamp ) );
719  disconnect( m_bookmarkManager, SIGNAL(bookmarksChanged()), m_q, SLOT(startBookmarkSync()) );
720  m_bookmarkManager->loadFile( "bookmarks/bookmarks.kml" );
721  connect( m_bookmarkManager, SIGNAL(bookmarksChanged()), m_q, SLOT(startBookmarkSync()) );
722  emit m_q->syncComplete();
723 }
724 
725 // Bookmark synchronization steps
726 void BookmarkSyncManager::Private::continueSynchronization()
727 {
728  bool cloudModified = cloudBookmarksModified( m_cloudTimestamp );
729  if( cloudModified ) {
730  downloadBookmarks();
731  } else {
732  QString lastSyncedPath = lastSyncedKmlPath();
733  if( lastSyncedPath == QString() ) {
734  mDebug() << "Never synced. Uploading bookmarks.";
735  uploadBookmarks();
736  } else {
737  QList<DiffItem> diffList = diff( lastSyncedPath, m_localBookmarksPath );
738  bool localModified = false;
739  foreach( DiffItem item, diffList ) {
740  if( item.m_action != DiffItem::NoAction ) {
741  localModified = true;
742  }
743  }
744 
745  if( localModified ) {
746  mDebug() << "Local modifications, uploading.";
747  uploadBookmarks();
748  }
749  }
750  }
751 }
752 
753 void BookmarkSyncManager::Private::completeSynchronization()
754 {
755  mDebug() << "Merging remote and local bookmark file";
756  QString lastSyncedPath = lastSyncedKmlPath();
757  QFile localBookmarksFile( m_localBookmarksPath );
758  QByteArray result = m_downloadReply->readAll();
759  QBuffer buffer( &result );
760  buffer.open( QIODevice::ReadOnly );
761 
762  if( lastSyncedPath == QString() ) {
763  if( localBookmarksFile.exists() ) {
764  mDebug() << "Conflict between remote bookmarks and local ones";
765  m_diffA = diff( &buffer, m_localBookmarksPath );
766  m_diffB = diff( m_localBookmarksPath, &buffer );
767  } else {
768  saveDownloadedToCache( result );
769  return;
770  }
771  }
772  else
773  {
774  m_diffA = diff( lastSyncedPath, m_localBookmarksPath );
775  m_diffB = diff( lastSyncedPath, &buffer );
776  }
777 
778  m_merged.clear();
779  merge();
780 }
781 
782 void BookmarkSyncManager::Private::completeMerge()
783 {
784  QFile localBookmarksFile( m_localBookmarksPath );
785  GeoDataDocument *doc = constructDocument( m_merged );
786  GeoWriter writer;
787  localBookmarksFile.remove();
788  localBookmarksFile.open( QFile::ReadWrite );
789  writer.write( &localBookmarksFile, doc );
790  localBookmarksFile.close();
791  uploadBookmarks();
792 }
793 
794 void BookmarkSyncManager::Private::completeUpload()
795 {
796  QString response = m_uploadReply->readAll();
797  QScriptEngine engine;
798  QScriptValue parsedResponse = engine.evaluate( QString( "(%0)" ).arg( response ) );
799  QString timestamp = parsedResponse.property( "data" ).toString();
800  m_cloudTimestamp = timestamp;
801  mDebug() << "Uploaded bookmarks to remote server. Timestamp is " << m_cloudTimestamp;
802  copyLocalToCache();
803 }
804 
805 }
806 
807 #include "BookmarkSyncManager.moc"
GeoDataDocument.h
Marble::BookmarkSyncManager::setBookmarkManager
void setBookmarkManager(BookmarkManager *manager)
Definition: BookmarkSyncManager.cpp:254
GeoDataCoordinates.h
Marble::MergeItem::resolution
MergeItem::Resolution resolution
Definition: MergeItem.h:41
MarbleMath.h
Marble::BookmarkSyncManager::isBookmarkSyncEnabled
bool isBookmarkSyncEnabled() const
Checks if the user enabled bookmark synchronization.
Definition: BookmarkSyncManager.cpp:237
MarbleModel.h
This file contains the headers for MarbleModel.
Marble::BookmarkSyncManager::~BookmarkSyncManager
~BookmarkSyncManager()
Definition: BookmarkSyncManager.cpp:231
Marble::BookmarkSyncManager::setBookmarkSyncEnabled
void setBookmarkSyncEnabled(bool enabled)
Setter for enabling/disabling bookmark synchronization.
Definition: BookmarkSyncManager.cpp:242
GeoDataParser.h
Marble::distanceSphere
qreal distanceSphere(qreal lon1, qreal lat1, qreal lon2, qreal lat2)
This method calculates the shortest distance between two points on a sphere.
Definition: MarbleMath.h:52
QObject
MarbleDebug.h
BookmarkManager.h
GeoWriter.h
Marble::GeoData_KML
Definition: GeoDataParser.h:36
Marble::MergeItem::B
Definition: MergeItem.h:46
Marble::BookmarkSyncManager::startBookmarkSync
void startBookmarkSync()
Initiates running of synchronization "method chain".
Definition: BookmarkSyncManager.cpp:261
Marble::BookmarkManager
This class is responsible for loading the book mark objects from the files and various book mark oper...
Definition: BookmarkManager.h:35
GeoCute::Status
Status
Definition: Status.h:19
Marble::EARTH_RADIUS
const qreal EARTH_RADIUS
Definition: MarbleGlobal.h:238
MarbleDirs.h
Marble::BookmarkSyncManager::BookmarkSyncManager
BookmarkSyncManager(CloudSyncManager *cloudSyncManager)
Definition: BookmarkSyncManager.cpp:223
Marble::MergeItem::Deleted
Definition: MergeItem.h:51
Marble::MergeItem
Definition: MergeItem.h:23
Marble::MergeItem::Changed
Definition: MergeItem.h:50
OwncloudSyncBackend.h
GeoDataFolder.h
Marble::BookmarkSyncManager::bookmarkSyncEnabledChanged
void bookmarkSyncEnabledChanged(bool enabled)
Marble::BookmarkSyncManager::resolveConflict
void resolveConflict(MergeItem *item)
Definition: BookmarkSyncManager.cpp:657
Marble::MergeItem::A
Definition: MergeItem.h:45
Marble::CloudSyncManager
Definition: CloudSyncManager.h:25
CloudSyncManager.h
Marble::mDebug
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:31
BookmarkSyncManager.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:38:49 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal