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

marble

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