• 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
  • routing
RoutingWidget.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 2010 Dennis Nienhüser <earthwings@gentoo.org>
9 //
10 
11 #include "RoutingWidget.h"
12 
13 #include "GeoDataLineString.h"
14 #include "MarbleModel.h"
15 #include "MarblePlacemarkModel.h"
16 #include "MarbleWidget.h"
17 #include "MarbleWidgetInputHandler.h"
18 #include "RouteRequest.h"
19 #include "RoutingInputWidget.h"
20 #include "RoutingLayer.h"
21 #include "RoutingManager.h"
22 #include "RoutingModel.h"
23 #include "RoutingProfilesModel.h"
24 #include "RoutingProfileSettingsDialog.h"
25 #include "GeoDataDocument.h"
26 #include "AlternativeRoutesModel.h"
27 #include "RouteSyncManager.h"
28 #include "CloudRoutesDialog.h"
29 #include "CloudSyncManager.h"
30 
31 #include <QTime>
32 #include <QTimer>
33 #include <QSortFilterProxyModel>
34 #include <QComboBox>
35 #include <QPainter>
36 #include <QFileDialog>
37 #include <QKeyEvent>
38 #include <QMouseEvent>
39 #include <QToolBar>
40 #include <QToolButton>
41 #include <QProgressDialog>
42 
43 #include "ui_RoutingWidget.h"
44 
45 namespace Marble
46 {
47 
48 class RoutingWidgetPrivate
49 {
50 public:
51  Ui::RoutingWidget m_ui;
52 
53  MarbleWidget *const m_widget;
54 
55  RoutingManager *const m_routingManager;
56 
57  RoutingLayer *const m_routingLayer;
58 
59  RoutingInputWidget *m_activeInput;
60 
61  QVector<RoutingInputWidget*> m_inputWidgets;
62 
63  RoutingInputWidget *m_inputRequest;
64 
65  QAbstractItemModel *const m_routingModel;
66 
67  RouteRequest *const m_routeRequest;
68 
69  RouteSyncManager *m_routeSyncManager;
70 
71  bool m_zoomRouteAfterDownload;
72 
73  QTimer m_progressTimer;
74 
75  QVector<QIcon> m_progressAnimation;
76 
77  int m_currentFrame;
78 
79  int m_iconSize;
80 
81  int m_collapse_width;
82 
83  QToolBar *m_toolBar;
84 
85  QToolButton *m_openRouteButton;
86  QToolButton *m_saveRouteButton;
87  QAction *m_cloudSyncSeparator;
88  QAction *m_uploadToCloudAction;
89  QAction *m_openCloudRoutesAction;
90  QToolButton *m_addViaButton;
91  QToolButton *m_reverseRouteButton;
92  QToolButton *m_clearRouteButton;
93  QToolButton *m_configureButton;
94 
95  QProgressDialog* m_routeUploadDialog;
96 
98  RoutingWidgetPrivate(RoutingWidget *parent, MarbleWidget *marbleWidget );
99 
104  void adjustInputWidgets();
105 
106  void adjustSearchButton();
107 
114  void setActiveInput( RoutingInputWidget* widget );
115 
116  void setupToolBar();
117 
118 private:
119  void createProgressAnimation();
120  RoutingWidget *m_parent;
121 };
122 
123 RoutingWidgetPrivate::RoutingWidgetPrivate( RoutingWidget *parent, MarbleWidget *marbleWidget ) :
124  m_widget( marbleWidget ),
125  m_routingManager( marbleWidget->model()->routingManager() ),
126  m_routingLayer( marbleWidget->routingLayer() ),
127  m_activeInput( 0 ),
128  m_inputRequest( 0 ),
129  m_routingModel( m_routingManager->routingModel() ),
130  m_routeRequest( marbleWidget->model()->routingManager()->routeRequest() ),
131  m_routeSyncManager( 0 ),
132  m_zoomRouteAfterDownload( false ),
133  m_currentFrame( 0 ),
134  m_iconSize( 16 ),
135  m_collapse_width( 0 ),
136  m_routeUploadDialog( 0 ),
137  m_parent( parent )
138 {
139  createProgressAnimation();
140  m_progressTimer.setInterval( 100 );
141  if ( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) {
142  m_iconSize = 32;
143  }
144 }
145 
146 void RoutingWidgetPrivate::adjustInputWidgets()
147 {
148  for ( int i = 0; i < m_inputWidgets.size(); ++i ) {
149  m_inputWidgets[i]->setIndex( i );
150  }
151 
152  adjustSearchButton();
153 }
154 
155 void RoutingWidgetPrivate::adjustSearchButton()
156 {
157  QString text = QObject::tr( "Get Directions" );
158  QString tooltip = QObject::tr( "Retrieve routing instructions for the selected destinations." );
159 
160  int validInputs = 0;
161  for ( int i = 0; i < m_inputWidgets.size(); ++i ) {
162  if ( m_inputWidgets[i]->hasTargetPosition() ) {
163  ++validInputs;
164  }
165  }
166 
167  if ( validInputs < 2 ) {
168  text = QObject::tr( "Search" );
169  tooltip = QObject::tr( "Find places matching the search term" );
170  }
171 
172  m_ui.searchButton->setText( text );
173  m_ui.searchButton->setToolTip( tooltip );
174 }
175 
176 void RoutingWidgetPrivate::setActiveInput( RoutingInputWidget *widget )
177 {
178  Q_ASSERT( widget && "Must not pass null" );
179  MarblePlacemarkModel *model = widget->searchResultModel();
180 
181  m_activeInput = widget;
182  m_ui.directionsListView->setModel( model );
183  m_routingLayer->setPlacemarkModel( model );
184  m_routingLayer->synchronizeWith( m_ui.directionsListView->selectionModel() );
185 }
186 
187 void RoutingWidgetPrivate::setupToolBar()
188 {
189  m_toolBar = new QToolBar;
190 
191  m_openRouteButton = new QToolButton;
192  m_openRouteButton->setToolTip( QObject::tr("Open Route") );
193  m_openRouteButton->setIcon( QIcon(":/icons/16x16/document-open.png") );
194  m_toolBar->addWidget(m_openRouteButton);
195 
196  m_saveRouteButton = new QToolButton;
197  m_saveRouteButton->setToolTip( QObject::tr("Save Route") );
198  m_saveRouteButton->setIcon( QIcon(":/icons/16x16/document-save.png") );
199  m_toolBar->addWidget(m_saveRouteButton);
200 
201  m_cloudSyncSeparator = m_toolBar->addSeparator();
202  m_uploadToCloudAction = m_toolBar->addAction( QObject::tr("Upload to Cloud") );
203  m_uploadToCloudAction->setToolTip( QObject::tr("Upload to Cloud") );
204  m_uploadToCloudAction->setIcon( QIcon(":/icons/cloud-upload.png") );
205 
206  m_openCloudRoutesAction = m_toolBar->addAction( QObject::tr("Manage Cloud Routes") );
207  m_openCloudRoutesAction->setToolTip( QObject::tr("Manage Cloud Routes") );
208  m_openCloudRoutesAction->setIcon( QIcon(":/icons/cloud-download.png") );
209 
210  m_toolBar->addSeparator();
211  m_addViaButton = new QToolButton;
212  m_addViaButton->setToolTip( QObject::tr("Add Via") );
213  m_addViaButton->setIcon( QIcon(":/marble/list-add.png") );
214  m_toolBar->addWidget(m_addViaButton);
215 
216  m_reverseRouteButton = new QToolButton;
217  m_reverseRouteButton->setToolTip( QObject::tr("Reverse Route") );
218  m_reverseRouteButton->setIcon( QIcon(":/marble/reverse.png") );
219  m_toolBar->addWidget(m_reverseRouteButton);
220 
221  m_clearRouteButton = new QToolButton;
222  m_clearRouteButton->setToolTip( QObject::tr("Clear Route") );
223  m_clearRouteButton->setIcon( QIcon(":/marble/edit-clear.png") );
224  m_toolBar->addWidget(m_clearRouteButton);
225 
226  m_toolBar->addSeparator();
227 
228  m_configureButton = new QToolButton;
229  m_configureButton->setToolTip( QObject::tr("Settings") );
230  m_configureButton->setIcon( QIcon(":/icons/16x16/configure.png") );
231  m_toolBar->addWidget(m_configureButton);
232 
233  QObject::connect( m_openRouteButton, SIGNAL(clicked()),
234  m_parent, SLOT(openRoute()) );
235  QObject::connect( m_saveRouteButton, SIGNAL(clicked()),
236  m_parent, SLOT(saveRoute()) );
237  QObject::connect( m_uploadToCloudAction, SIGNAL(triggered()),
238  m_parent, SLOT(uploadToCloud()) );
239  QObject::connect( m_openCloudRoutesAction, SIGNAL(triggered()),
240  m_parent, SLOT(openCloudRoutesDialog()));
241  QObject::connect( m_addViaButton, SIGNAL(clicked()),
242  m_parent, SLOT(addInputWidget()) );
243  QObject::connect( m_reverseRouteButton, SIGNAL(clicked()),
244  m_routingManager, SLOT(reverseRoute()) );
245  QObject::connect( m_clearRouteButton, SIGNAL(clicked()),
246  m_routingManager, SLOT(clearRoute()) );
247  QObject::connect( m_configureButton, SIGNAL(clicked()),
248  m_parent, SLOT(configureProfile()) );
249 
250  m_toolBar->setIconSize(QSize(16, 16));
251  m_ui.toolBarLayout->addWidget(m_toolBar, 0, Qt::AlignLeft);
252 }
253 
254 void RoutingWidgetPrivate::createProgressAnimation()
255 {
256  // Size parameters
257  qreal const h = m_iconSize / 2.0; // Half of the icon size
258  qreal const q = h / 2.0; // Quarter of the icon size
259  qreal const d = 7.5; // Circle diameter
260  qreal const r = d / 2.0; // Circle radius
261 
262  // Canvas parameters
263  QImage canvas( m_iconSize, m_iconSize, QImage::Format_ARGB32 );
264  QPainter painter( &canvas );
265  painter.setRenderHint( QPainter::Antialiasing, true );
266  painter.setPen( QColor ( Qt::gray ) );
267  painter.setBrush( QColor( Qt::white ) );
268 
269  // Create all frames
270  for( double t = 0.0; t < 2 * M_PI; t += M_PI / 8.0 ) {
271  canvas.fill( Qt::transparent );
272  QRectF firstCircle( h - r + q * cos( t ), h - r + q * sin( t ), d, d );
273  QRectF secondCircle( h - r + q * cos( t + M_PI ), h - r + q * sin( t + M_PI ), d, d );
274  painter.drawEllipse( firstCircle );
275  painter.drawEllipse( secondCircle );
276  m_progressAnimation.push_back( QIcon( QPixmap::fromImage( canvas ) ) );
277  }
278 }
279 
280 RoutingWidget::RoutingWidget( MarbleWidget *marbleWidget, QWidget *parent ) :
281  QWidget( parent ), d( new RoutingWidgetPrivate( this, marbleWidget ) )
282 {
283  d->m_ui.setupUi( this );
284  d->setupToolBar();
285  d->m_ui.routeComboBox->setVisible( false );
286  d->m_ui.routeComboBox->setModel( d->m_routingManager->alternativeRoutesModel() );
287  layout()->setMargin( 0 );
288 
289  d->m_ui.routingProfileComboBox->setModel( d->m_routingManager->profilesModel() );
290 
291  connect( d->m_routingManager->profilesModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
292  this, SLOT(selectFirstProfile()) );
293  connect( d->m_routingManager->profilesModel(), SIGNAL(modelReset()),
294  this, SLOT(selectFirstProfile()) );
295  connect( d->m_routingLayer, SIGNAL(placemarkSelected(QModelIndex)),
296  this, SLOT(activatePlacemark(QModelIndex)) );
297  connect( d->m_routingManager, SIGNAL(stateChanged(RoutingManager::State)),
298  this, SLOT(updateRouteState(RoutingManager::State)) );
299  connect( d->m_routingManager, SIGNAL(routeRetrieved(GeoDataDocument*)),
300  this, SLOT(indicateRoutingFailure(GeoDataDocument*)) );
301  connect( d->m_routeRequest, SIGNAL(positionAdded(int)),
302  this, SLOT(insertInputWidget(int)) );
303  connect( d->m_routeRequest, SIGNAL(positionRemoved(int)),
304  this, SLOT(removeInputWidget(int)) );
305  connect( d->m_routeRequest, SIGNAL(routingProfileChanged()),
306  this, SLOT(updateActiveRoutingProfile()) );
307  connect( &d->m_progressTimer, SIGNAL(timeout()),
308  this, SLOT(updateProgress()) );
309  connect( d->m_ui.routeComboBox, SIGNAL(currentIndexChanged(int)),
310  d->m_routingManager->alternativeRoutesModel(), SLOT(setCurrentRoute(int)) );
311  connect( d->m_routingManager->alternativeRoutesModel(), SIGNAL(currentRouteChanged(int)),
312  d->m_ui.routeComboBox, SLOT(setCurrentIndex(int)) );
313  connect( d->m_ui.routingProfileComboBox, SIGNAL(currentIndexChanged(int)),
314  this, SLOT(setRoutingProfile(int)) );
315  connect( d->m_ui.routingProfileComboBox, SIGNAL(activated(int)),
316  this, SLOT(retrieveRoute()) );
317  connect( d->m_routingManager->alternativeRoutesModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
318  this, SLOT(updateAlternativeRoutes()) );
319 
320  d->m_ui.directionsListView->setModel( d->m_routingModel );
321 
322  QItemSelectionModel *selectionModel = d->m_ui.directionsListView->selectionModel();
323  d->m_routingLayer->synchronizeWith( selectionModel );
324  connect( d->m_ui.directionsListView, SIGNAL(activated(QModelIndex)),
325  this, SLOT(activateItem(QModelIndex)) );
326 
327  // FIXME: apply for this sector
328  connect( d->m_ui.searchButton, SIGNAL(clicked()),
329  this, SLOT(retrieveRoute()) );
330  connect( d->m_ui.showInstructionsButton, SIGNAL(clicked(bool)),
331  this, SLOT(showDirections()) );
332 
333  for( int i=0; i<d->m_routeRequest->size(); ++i ) {
334  insertInputWidget( i );
335  }
336 
337  for ( int i=0; i<2 && d->m_inputWidgets.size()<2; ++i ) {
338  // Start with source and destination if the route is empty yet
339  addInputWidget();
340  }
341  //d->m_ui.descriptionLabel->setVisible( false );
342  d->m_ui.resultLabel->setVisible( false );
343  setShowDirectionsButtonVisible( false );
344  updateActiveRoutingProfile();
345  updateCloudSyncButtons();
346 
347  if ( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) {
348  d->m_ui.directionsListView->setVisible( false );
349  d->m_openRouteButton->setVisible( false );
350  d->m_saveRouteButton->setVisible( false );
351 #ifdef Q_WS_MAEMO_5
352  d->m_ui.directionsListView->setAttribute( Qt::WA_Maemo5StackedWindow );
353  d->m_ui.directionsListView->setWindowFlags( Qt::Window );
354  d->m_ui.directionsListView->setWindowTitle( tr( "Directions - Marble" ) );
355 #endif // Q_WS_MAEMO_5
356  }
357 }
358 
359 RoutingWidget::~RoutingWidget()
360 {
361  delete d;
362 }
363 
364 void RoutingWidget::retrieveRoute()
365 {
366  if ( d->m_inputWidgets.size() == 1 ) {
367  // Search mode
368  d->m_inputWidgets.first()->findPlacemarks();
369  return;
370  }
371 
372  int index = d->m_ui.routingProfileComboBox->currentIndex();
373  if ( index == -1 ) {
374  return;
375  }
376  d->m_routeRequest->setRoutingProfile( d->m_routingManager->profilesModel()->profiles().at( index ) );
377 
378  Q_ASSERT( d->m_routeRequest->size() == d->m_inputWidgets.size() );
379  for ( int i = 0; i < d->m_inputWidgets.size(); ++i ) {
380  RoutingInputWidget *widget = d->m_inputWidgets.at( i );
381  if ( !widget->hasTargetPosition() && widget->hasInput() ) {
382  widget->findPlacemarks();
383  return;
384  }
385  }
386 
387  d->m_activeInput = 0;
388  if ( d->m_routeRequest->size() > 1 ) {
389  d->m_zoomRouteAfterDownload = true;
390  d->m_routingLayer->setPlacemarkModel( 0 );
391  d->m_routingManager->retrieveRoute();
392  d->m_ui.directionsListView->setModel( d->m_routingModel );
393  d->m_routingLayer->synchronizeWith( d->m_ui.directionsListView->selectionModel() );
394  }
395 }
396 
397 void RoutingWidget::activateItem ( const QModelIndex &index )
398 {
399  QVariant data = index.data( MarblePlacemarkModel::CoordinateRole );
400 
401  if ( !data.isNull() ) {
402  GeoDataCoordinates position = qvariant_cast<GeoDataCoordinates>( data );
403  d->m_widget->centerOn( position, true );
404  }
405 
406  if ( d->m_activeInput && index.isValid() ) {
407  QVariant data = index.data( MarblePlacemarkModel::CoordinateRole );
408  if ( !data.isNull() ) {
409  d->m_activeInput->setTargetPosition( data.value<GeoDataCoordinates>(), index.data().toString() );
410  }
411  }
412 }
413 
414 void RoutingWidget::handleSearchResult( RoutingInputWidget *widget )
415 {
416  d->setActiveInput( widget );
417  MarblePlacemarkModel *model = widget->searchResultModel();
418 
419  if ( model->rowCount() ) {
420  QString const results = tr( "placemarks found: %1" ).arg( model->rowCount() );
421  d->m_ui.resultLabel->setText( results );
422  d->m_ui.resultLabel->setVisible( true );
423  // Make sure we have a selection
424  activatePlacemark( model->index( 0, 0 ) );
425  } else {
426  QString const results = tr( "No placemark found" );
427  d->m_ui.resultLabel->setText( "<font color=\"red\">" + results + "</font>" );
428  d->m_ui.resultLabel->setVisible( true );
429  }
430 
431  GeoDataLineString placemarks;
432  for ( int i = 0; i < model->rowCount(); ++i ) {
433  QVariant data = model->index( i, 0 ).data( MarblePlacemarkModel::CoordinateRole );
434  if ( !data.isNull() ) {
435  placemarks << data.value<GeoDataCoordinates>();
436  }
437  }
438 
439  if ( placemarks.size() > 1 ) {
440  d->m_widget->centerOn( GeoDataLatLonBox::fromLineString( placemarks ) );
441  //d->m_ui.descriptionLabel->setVisible( false );
442 
443  if ( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) {
444  d->m_ui.directionsListView->setVisible( true );
445  }
446  }
447 }
448 
449 void RoutingWidget::centerOnInputWidget( RoutingInputWidget *widget )
450 {
451  if ( widget->hasTargetPosition() ) {
452  d->m_widget->centerOn( widget->targetPosition() );
453  }
454 }
455 
456 void RoutingWidget::activatePlacemark( const QModelIndex &index )
457 {
458  if ( d->m_activeInput && index.isValid() ) {
459  QVariant data = index.data( MarblePlacemarkModel::CoordinateRole );
460  if ( !data.isNull() ) {
461  d->m_activeInput->setTargetPosition( data.value<GeoDataCoordinates>() );
462  }
463  }
464 
465  d->m_ui.directionsListView->setCurrentIndex( index );
466 }
467 
468 void RoutingWidget::addInputWidget()
469 {
470  d->m_routeRequest->append( GeoDataCoordinates() );
471 }
472 
473 void RoutingWidget::insertInputWidget( int index )
474 {
475  if ( index >= 0 && index <= d->m_inputWidgets.size() ) {
476  RoutingInputWidget *input = new RoutingInputWidget( d->m_widget, index, this );
477  input->setProgressAnimation( d->m_progressAnimation );
478  d->m_inputWidgets.insert( index, input );
479  connect( input, SIGNAL(searchFinished(RoutingInputWidget*)),
480  this, SLOT(handleSearchResult(RoutingInputWidget*)) );
481  connect( input, SIGNAL(removalRequest(RoutingInputWidget*)),
482  this, SLOT(removeInputWidget(RoutingInputWidget*)) );
483  connect( input, SIGNAL(activityRequest(RoutingInputWidget*)),
484  this, SLOT(centerOnInputWidget(RoutingInputWidget*)) );
485  connect( input, SIGNAL(mapInputModeEnabled(RoutingInputWidget*,bool)),
486  this, SLOT(requestMapPosition(RoutingInputWidget*,bool)) );
487  connect( input, SIGNAL(targetValidityChanged(bool)),
488  this, SLOT(adjustSearchButton()) );
489 
490  d->m_ui.routingLayout->insertWidget( index, input );
491  d->adjustInputWidgets();
492  }
493 }
494 
495 void RoutingWidget::removeInputWidget( RoutingInputWidget *widget )
496 {
497  int index = d->m_inputWidgets.indexOf( widget );
498  if ( index >= 0 ) {
499  if ( d->m_inputWidgets.size() < 3 ) {
500  widget->clear();
501  } else {
502  d->m_routeRequest->remove( index );
503  }
504  d->m_routingManager->retrieveRoute();
505  }
506 }
507 
508 void RoutingWidget::removeInputWidget( int index )
509 {
510  if ( index >= 0 && index < d->m_inputWidgets.size() ) {
511  RoutingInputWidget *widget = d->m_inputWidgets.at( index );
512  d->m_inputWidgets.remove( index );
513  d->m_ui.routingLayout->removeWidget( widget );
514  widget->deleteLater();
515  if ( widget == d->m_activeInput ) {
516  d->m_activeInput = 0;
517  d->m_routingLayer->setPlacemarkModel( 0 );
518  d->m_ui.directionsListView->setModel( d->m_routingModel );
519  d->m_routingLayer->synchronizeWith( d->m_ui.directionsListView->selectionModel() );
520  }
521  d->adjustInputWidgets();
522  }
523 
524  if ( d->m_inputWidgets.size() < 2 ) {
525  addInputWidget();
526  }
527 }
528 
529 void RoutingWidget::updateRouteState( RoutingManager::State state )
530 {
531  if ( state != RoutingManager::Retrieved ) {
532  d->m_ui.routeComboBox->setVisible( false );
533  d->m_ui.routeComboBox->clear();
534  }
535 
536  if ( state == RoutingManager::Downloading ) {
537  d->m_progressTimer.start();
538  }
539 
540  d->m_saveRouteButton->setEnabled( d->m_routingManager->routingModel()->rowCount() > 0 );
541 }
542 
543 void RoutingWidget::requestMapPosition( RoutingInputWidget *widget, bool enabled )
544 {
545  pointSelectionCanceled();
546 
547  if ( enabled ) {
548  d->m_inputRequest = widget;
549  d->m_widget->installEventFilter( this );
550  d->m_widget->setFocus( Qt::OtherFocusReason );
551  }
552 }
553 
554 void RoutingWidget::retrieveSelectedPoint( const GeoDataCoordinates &coordinates )
555 {
556  if ( d->m_inputRequest && d->m_inputWidgets.contains( d->m_inputRequest ) ) {
557  d->m_inputRequest->setTargetPosition( coordinates );
558  d->m_widget->update();
559  }
560 
561  d->m_inputRequest = 0;
562  d->m_widget->removeEventFilter( this );
563 }
564 
565 void RoutingWidget::adjustSearchButton()
566 {
567  d->adjustSearchButton();
568 }
569 
570 void RoutingWidget::pointSelectionCanceled()
571 {
572  if ( d->m_inputRequest && d->m_inputWidgets.contains( d->m_inputRequest ) ) {
573  d->m_inputRequest->abortMapInputRequest();
574  }
575 
576  d->m_inputRequest = 0;
577  d->m_widget->removeEventFilter( this );
578 }
579 
580 void RoutingWidget::configureProfile()
581 {
582  int index = d->m_ui.routingProfileComboBox->currentIndex();
583  if ( index != -1 ) {
584  RoutingProfileSettingsDialog dialog( d->m_widget->model()->pluginManager(), d->m_routingManager->profilesModel(), this );
585  dialog.editProfile( d->m_ui.routingProfileComboBox->currentIndex() );
586  d->m_routeRequest->setRoutingProfile( d->m_routingManager->profilesModel()->profiles().at( index ) );
587  }
588 }
589 
590 void RoutingWidget::updateProgress()
591 {
592  if ( !d->m_progressAnimation.isEmpty() ) {
593  d->m_currentFrame = ( d->m_currentFrame + 1 ) % d->m_progressAnimation.size();
594  QIcon frame = d->m_progressAnimation[d->m_currentFrame];
595  d->m_ui.searchButton->setIcon( frame );
596  d->m_ui.resultLabel->setVisible( false );
597  }
598 }
599 
600 void RoutingWidget::updateAlternativeRoutes()
601 {
602  if ( d->m_ui.routeComboBox->count() == 1) {
603  // Parts of the route may lie outside the route trip points
604  GeoDataLatLonBox const bbox = d->m_routingManager->routingModel()->route().bounds();
605  if ( d->m_zoomRouteAfterDownload ) {
606  d->m_zoomRouteAfterDownload = false;
607  d->m_widget->centerOn( bbox );
608  }
609  }
610 
611  d->m_ui.routeComboBox->setVisible( d->m_ui.routeComboBox->count() > 0 );
612  if ( d->m_ui.routeComboBox->currentIndex() < 0 && d->m_ui.routeComboBox->count() > 0 ) {
613  d->m_ui.routeComboBox->setCurrentIndex( 0 );
614  }
615 
616  d->m_progressTimer.stop();
617  d->m_ui.searchButton->setIcon( QIcon() );
618 
619  QString const results = tr( "routes found: %1" ).arg( d->m_ui.routeComboBox->count() );
620  d->m_ui.resultLabel->setText( results );
621  d->m_ui.resultLabel->setVisible( true );
622  d->m_saveRouteButton->setEnabled( d->m_routingManager->routingModel()->rowCount() > 0 );
623 }
624 
625 void RoutingWidget::setShowDirectionsButtonVisible( bool visible )
626 {
627  d->m_ui.showInstructionsButton->setVisible( visible );
628 }
629 
630 void RoutingWidget::setRouteSyncManager(RouteSyncManager *manager)
631 {
632  d->m_routeSyncManager = manager;
633  connect( d->m_routeSyncManager, SIGNAL(routeSyncEnabledChanged(bool)),
634  this, SLOT(updateCloudSyncButtons()) );
635  updateCloudSyncButtons();
636 }
637 
638 void RoutingWidget::openRoute()
639 {
640  QString const file = QFileDialog::getOpenFileName( this, tr( "Open Route" ),
641  d->m_routingManager->lastOpenPath(), tr("KML Files (*.kml)") );
642  if ( !file.isEmpty() ) {
643  d->m_routingManager->setLastOpenPath( QFileInfo( file ).absolutePath() );
644  d->m_zoomRouteAfterDownload = true;
645  d->m_routingManager->loadRoute( file );
646  updateAlternativeRoutes();
647  }
648 }
649 
650 void RoutingWidget::selectFirstProfile()
651 {
652  int count = d->m_routingManager->profilesModel()->rowCount();
653  if ( count && d->m_ui.routingProfileComboBox->currentIndex() < 0 ) {
654  d->m_ui.routingProfileComboBox->setCurrentIndex( 0 );
655  }
656 }
657 
658 void RoutingWidget::setRoutingProfile( int index )
659 {
660  if ( index >= 0 && index < d->m_routingManager->profilesModel()->rowCount() ) {
661  d->m_routeRequest->setRoutingProfile( d->m_routingManager->profilesModel()->profiles().at( index ) );
662  }
663 }
664 
665 void RoutingWidget::showDirections()
666 {
667  d->m_ui.directionsListView->setVisible( true );
668 }
669 
670 void RoutingWidget::saveRoute()
671 {
672  QString fileName = QFileDialog::getSaveFileName( this,
673  tr( "Save Route" ), // krazy:exclude=qclasses
674  d->m_routingManager->lastSavePath(),
675  tr( "KML files (*.kml)" ) );
676 
677  if ( !fileName.isEmpty() ) {
678  // maemo 5 file dialog does not append the file extension
679  if ( !fileName.endsWith(QLatin1String( ".kml" ), Qt::CaseInsensitive) ) {
680  fileName.append( ".kml" );
681  }
682  d->m_routingManager->setLastSavePath( QFileInfo( fileName ).absolutePath() );
683  d->m_routingManager->saveRoute( fileName );
684  }
685 }
686 
687 void RoutingWidget::uploadToCloud()
688 {
689  Q_ASSERT( d->m_routeSyncManager );
690 
691  if (!d->m_routeUploadDialog) {
692  d->m_routeUploadDialog = new QProgressDialog( d->m_widget );
693  d->m_routeUploadDialog->setWindowTitle( tr( "Uploading route..." ) );
694  d->m_routeUploadDialog->setMinimum( 0 );
695  d->m_routeUploadDialog->setMaximum( 100 );
696  d->m_routeUploadDialog->setAutoClose( true );
697  d->m_routeUploadDialog->setAutoReset( true );
698  connect( d->m_routeSyncManager, SIGNAL(routeUploadProgress(qint64,qint64)), this, SLOT(updateUploadProgress(qint64,qint64)) );
699  }
700 
701  d->m_routeUploadDialog->show();
702  d->m_routeSyncManager->uploadRoute();
703 }
704 
705 void RoutingWidget::openCloudRoutesDialog()
706 {
707  Q_ASSERT( d->m_routeSyncManager );
708  d->m_routeSyncManager->prepareRouteList();
709 
710  CloudRoutesDialog *dialog = new CloudRoutesDialog( d->m_routeSyncManager->model(), d->m_widget );
711  connect( d->m_routeSyncManager, SIGNAL(routeListDownloadProgress(qint64,qint64)), dialog, SLOT(updateListDownloadProgressbar(qint64,qint64)) );
712  connect( dialog, SIGNAL(downloadButtonClicked(QString)), d->m_routeSyncManager, SLOT(downloadRoute(QString)) );
713  connect( dialog, SIGNAL(openButtonClicked(QString)), this, SLOT(openCloudRoute(QString)) );
714  connect( dialog, SIGNAL(deleteButtonClicked(QString)), d->m_routeSyncManager, SLOT(deleteRoute(QString)) );
715  connect( dialog, SIGNAL(removeFromCacheButtonClicked(QString)), d->m_routeSyncManager, SLOT(removeRouteFromCache(QString)) );
716  connect( dialog, SIGNAL(uploadToCloudButtonClicked(QString)), d->m_routeSyncManager, SLOT(uploadRoute(QString)) );
717  dialog->exec();
718 }
719 
720 void RoutingWidget::indicateRoutingFailure( GeoDataDocument* route )
721 {
722  if ( !route ) {
723  d->m_progressTimer.stop();
724  d->m_ui.searchButton->setIcon( QIcon() );
725  QString const results = tr( "No route found" );
726  d->m_ui.resultLabel->setText( "<font color=\"red\">" + results + "</font>" );
727  d->m_ui.resultLabel->setVisible( true );
728  }
729 }
730 
731 void RoutingWidget::updateActiveRoutingProfile()
732 {
733  RoutingProfile const profile = d->m_routingManager->routeRequest()->routingProfile();
734  QList<RoutingProfile> const profiles = d->m_routingManager->profilesModel()->profiles();
735  d->m_ui.routingProfileComboBox->setCurrentIndex( profiles.indexOf( profile ) );
736 }
737 
738 void RoutingWidget::updateCloudSyncButtons()
739 {
740  bool const show = d->m_routeSyncManager && d->m_routeSyncManager->isRouteSyncEnabled();
741  d->m_cloudSyncSeparator->setVisible( show );
742  d->m_uploadToCloudAction->setVisible( show );
743  d->m_openCloudRoutesAction->setVisible( show );
744 }
745 
746 void RoutingWidget::openCloudRoute(const QString &identifier)
747 {
748  Q_ASSERT( d->m_routeSyncManager );
749  d->m_routeSyncManager->openRoute( identifier );
750  d->m_widget->centerOn( d->m_routingManager->routingModel()->route().bounds() );
751 }
752 
753 void RoutingWidget::updateUploadProgress(qint64 sent, qint64 total)
754 {
755  Q_ASSERT( d->m_routeUploadDialog );
756  d->m_routeUploadDialog->setValue( 100.0 * sent / total );
757 }
758 
759 bool RoutingWidget::eventFilter( QObject *o, QEvent *event )
760 {
761  if ( o != d->m_widget ) {
762  return QWidget::eventFilter( o, event );
763  }
764 
765  Q_ASSERT( d->m_inputRequest != 0 );
766  Q_ASSERT( d->m_inputWidgets.contains( d->m_inputRequest ) );
767 
768  if ( event->type() == QEvent::MouseButtonPress ) {
769  QMouseEvent *e = static_cast<QMouseEvent*>( event );
770  return e->button() == Qt::LeftButton;
771  }
772 
773  if ( event->type() == QEvent::MouseButtonRelease ) {
774  QMouseEvent *e = static_cast<QMouseEvent*>( event );
775  qreal lon( 0.0 ), lat( 0.0 );
776  if ( e->button() == Qt::LeftButton && d->m_widget->geoCoordinates( e->pos().x(), e->pos().y(),
777  lon, lat, GeoDataCoordinates::Radian ) ) {
778  retrieveSelectedPoint( GeoDataCoordinates( lon, lat ) );
779  return true;
780  } else {
781  return QWidget::eventFilter( o, event );
782  }
783  }
784 
785  if ( event->type() == QEvent::MouseMove ) {
786  d->m_widget->setCursor( Qt::CrossCursor );
787  return true;
788  }
789 
790  if ( event->type() == QEvent::KeyPress ) {
791  QKeyEvent *e = static_cast<QKeyEvent*>( event );
792  if ( e->key() == Qt::Key_Escape ) {
793  pointSelectionCanceled();
794  return true;
795  }
796 
797  return QWidget::eventFilter( o, event );
798  }
799 
800  return QWidget::eventFilter( o, event );
801 }
802 
803 void RoutingWidget::resizeEvent(QResizeEvent *e)
804 {
805  QWidget::resizeEvent(e);
806 }
807 
808 } // namespace Marble
809 
810 #include "RoutingWidget.moc"
QPainter
GeoDataDocument.h
Marble::GeoDataCoordinates
A 3d point representation.
Definition: GeoDataCoordinates.h:52
RoutingModel.h
Marble::GeoDataCoordinates::Radian
Definition: GeoDataCoordinates.h:65
Marble::GeoDataDocument
A container for Features, Styles and in the future Schemas.
Definition: GeoDataDocument.h:64
Marble::RoutingWidget::saveRoute
void saveRoute()
Ask the user for a kml file to save the current route to.
Definition: RoutingWidget.cpp:670
CloudRoutesDialog.h
MarbleModel.h
This file contains the headers for MarbleModel.
Marble::RouteSyncManager
Definition: RouteSyncManager.h:23
QWidget
Marble::CloudRoutesDialog
Definition: CloudRoutesDialog.h:23
QObject
Marble::RoutingWidget::openCloudRoutesDialog
void openCloudRoutesDialog()
Open cloud routes dialog.
Definition: RoutingWidget.cpp:705
Marble::MarbleWidget
A widget class that displays a view of the earth.
Definition: MarbleWidget.h:102
MarbleWidgetInputHandler.h
Marble::RoutingManager::Retrieved
Definition: RoutingManager.h:44
RoutingInputWidget.h
RoutingManager.h
Marble::RoutingWidget::openRoute
void openRoute()
Ask the user for a kml file to open.
Definition: RoutingWidget.cpp:638
Marble::RoutingInputWidget::setProgressAnimation
void setProgressAnimation(const QVector< QIcon > &animation)
Set the progress animation to use.
Definition: RoutingInputWidget.cpp:438
Marble::RoutingWidget::~RoutingWidget
~RoutingWidget()
Destructor.
Definition: RoutingWidget.cpp:359
RoutingLayer.h
GeoDataLineString.h
Marble::RoutingWidget::eventFilter
bool eventFilter(QObject *o, QEvent *e)
Definition: RoutingWidget.cpp:759
Marble::RoutingInputWidget
Combines a line edit for input and a couple of buttons to let the user type in a search term...
Definition: RoutingInputWidget.h:39
RouteSyncManager.h
MarblePlacemarkModel.h
Marble::GeoDataLatLonBox::fromLineString
static GeoDataLatLonBox fromLineString(const GeoDataLineString &lineString)
Create the smallest bounding box from a line string.
Definition: GeoDataLatLonBox.cpp:620
QAbstractItemModel
Marble::MarbleGlobal::SmallScreen
Definition: MarbleGlobal.h:268
Marble::MarbleGlobal::getInstance
static MarbleGlobal * getInstance()
Definition: MarbleGlobal.cpp:37
Marble::RoutingWidget::resizeEvent
void resizeEvent(QResizeEvent *e)
Definition: RoutingWidget.cpp:803
Marble::MarblePlacemarkModel::CoordinateRole
The GeoDataCoordinates coordinate.
Definition: MarblePlacemarkModel.h:53
Marble::RoutingWidget::setRouteSyncManager
void setRouteSyncManager(RouteSyncManager *manager)
Definition: RoutingWidget.cpp:630
Marble::RoutingManager::State
State
Definition: RoutingManager.h:42
Marble::RoutingWidget::addInputWidget
void addInputWidget()
Add another input field at the end.
Definition: RoutingWidget.cpp:468
RoutingWidget.h
Marble::RoutingWidget::setShowDirectionsButtonVisible
void setShowDirectionsButtonVisible(bool visible)
Show or hide the "open file..." button.
Definition: RoutingWidget.cpp:625
M_PI
#define M_PI
Definition: GeoDataCoordinates.h:26
AlternativeRoutesModel.h
MarbleWidget.h
This file contains the headers for MarbleWidget.
RouteRequest.h
Marble::RoutingManager::Downloading
Definition: RoutingManager.h:43
MarbleWidget
Wraps a Marble::MarbleWidget, providing access to important properties and methods.
Definition: MarbleDeclarativeWidget.h:50
RoutingProfileSettingsDialog.h
Marble::RoutingWidget::uploadToCloud
void uploadToCloud()
Upload route to the cloud.
Definition: RoutingWidget.cpp:687
CloudSyncManager.h
RoutingProfilesModel.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:38:52 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