14 #include "ui_RoutingPlugin.h"
15 #include "ui_RoutingConfigDialog.h"
38 #include <QToolButton>
40 #include <QActionGroup>
43 #include <QPushButton>
44 #include <QSpacerItem>
45 #if QT_VERSION < 0x050000
46 #include <QPlastiqueStyle>
54 int const thresholdDistance = 1000;
57 class RoutingPluginPrivate
61 WidgetGraphicsItem* m_widgetItem;
62 RoutingModel* m_routingModel;
63 Ui::RoutingPlugin m_widget;
64 bool m_nearNextInstruction;
65 bool m_guidanceModeEnabled;
68 Ui::RoutingConfigDialog m_configUi;
69 bool m_routeCompleted;
70 SpeakersModel* m_speakersModel;
72 RoutingPluginPrivate( RoutingPlugin* parent );
74 void updateZoomButtons(
int zoomValue );
76 void updateZoomButtons();
78 void updateGuidanceModeButton();
82 void updateButtonVisibility();
86 void toggleGuidanceMode(
bool enabled );
88 void updateDestinationInformation();
90 void updateGpsButton( PositionProviderPlugin *activePlugin );
92 void togglePositionTracking(
bool enabled );
96 static QString fuzzyDistance( qreal distanceMeter );
100 qreal nextInstructionDistance()
const;
102 qreal remainingDistance()
const;
105 RoutingPlugin* m_parent;
108 RoutingPluginPrivate::RoutingPluginPrivate( RoutingPlugin *parent ) :
112 m_nearNextInstruction( false ),
113 m_guidanceModeEnabled( false ),
114 m_audio( new AudioOutput( parent ) ),
116 m_routeCompleted( false ),
117 m_speakersModel( 0 ),
120 m_audio->setMuted(
false );
121 m_audio->setSoundEnabled(
true );
126 return QString(
"<font size=\"+1\" color=\"black\">%1</font>" ).
arg( source );
129 QString RoutingPluginPrivate::fuzzyDistance( qreal length )
141 if ( length >= 1000 ) {
145 }
else if ( length >= 200 ) {
146 length = 50 * qRound( length / 50 );
147 }
else if ( length >= 100 ) {
148 length = 25 * qRound( length / 25 );
150 length = 10 * qRound( length / 10 );
160 return QString(
"%1 %2" ).
arg( length, 0,
'f', precision ).
arg( distanceUnit );
163 void RoutingPluginPrivate::updateZoomButtons(
int zoomValue )
165 int const minZoom = m_marbleWidget ? m_marbleWidget->minimumZoom() : 900;
166 int const maxZoom = m_marbleWidget ? m_marbleWidget->maximumZoom() : 2400;
168 bool const zoomInEnabled = zoomValue < maxZoom;
169 bool const zoomOutEnabled = zoomValue > minZoom;
171 if ( ( zoomInEnabled != m_widget.zoomInButton->isEnabled() ) ||
172 ( zoomOutEnabled != m_widget.zoomOutButton->isEnabled() ) ) {
173 m_widget.zoomInButton->setEnabled( zoomInEnabled );
174 m_widget.zoomOutButton->setEnabled( zoomOutEnabled );
179 void RoutingPluginPrivate::updateGuidanceModeButton()
181 bool const hasRoute = m_routingModel->rowCount() > 0;
182 m_widget.routingButton->setEnabled( hasRoute );
186 void RoutingPluginPrivate::forceRepaint()
189 emit m_parent->repaintNeeded();
192 void RoutingPluginPrivate::updateButtonVisibility()
194 bool const show = m_guidanceModeEnabled;
195 bool const near = show && m_nearNextInstruction;
196 m_widget.progressBar->setVisible( near );
197 m_widget.instructionIconLabel->setVisible( show );
198 m_widget.spacer->changeSize( show ? 10 : 0, 20 );
199 m_widget.instructionLabel->setVisible( show );
203 m_widget.followingInstructionIconLabel->setVisible(
false );
205 m_widget.destinationDistanceLabel->setVisible( show );
207 m_widget.gpsButton->setVisible( !show );
208 m_widget.zoomOutButton->setVisible( !show );
209 m_widget.zoomInButton->setVisible( !show );
211 m_widgetItem->widget()->updateGeometry();
212 QSize const size = m_widgetItem->widget()->sizeHint();
213 m_widgetItem->widget()->resize( size );
214 m_widgetItem->setContentSize( size );
218 qreal
const pluginWidth = size.
width();
220 if ( m_guidanceModeEnabled ) {
221 int const parentWidth = m_marbleWidget->width();
222 x = qRound( ( parentWidth - pluginWidth ) / 2.0 );
224 m_parent->setPosition(
QPointF( x, m_parent->position().y() ) );
228 void RoutingPluginPrivate::updateZoomButtons()
230 if ( m_marbleWidget ) {
231 updateZoomButtons( m_marbleWidget->zoom() );
235 void RoutingPluginPrivate::toggleGuidanceMode(
bool enabled )
237 if( !m_marbleWidget || m_guidanceModeEnabled == enabled ) {
241 m_guidanceModeEnabled = enabled;
242 updateButtonVisibility();
246 m_parent, SLOT(updateDestinationInformation()) );
249 m_parent, SLOT(updateDestinationInformation()) );
254 m_widget.instructionLabel->setText( richText(
"%1" ).arg( text ) );
258 RouteRequest* request = m_marbleWidget->model()->routingManager()->routeRequest();
259 if ( request && request->size() > 0 ) {
260 GeoDataCoordinates source = request->source();
261 if ( source.longitude() != 0.0 || source.latitude() != 0.0 ) {
263 view.setCoordinates( source );
265 view.setRange( 851.807 );
266 m_marbleWidget->flyTo( view );
271 m_marbleWidget->model()->routingManager()->setGuidanceModeEnabled( enabled );
274 m_routeCompleted =
false;
280 void RoutingPluginPrivate::updateDestinationInformation()
282 if ( m_routingModel->route().currentSegment().isValid() ) {
283 qreal remaining = remainingDistance();
284 qreal distanceLeft = nextInstructionDistance();
285 m_audio->update( m_routingModel->route(), distanceLeft, remaining, m_routingModel->deviatedFromRoute() );
287 m_nearNextInstruction = distanceLeft < thresholdDistance;
289 QString pixmapHtml =
"<img src=\":/flag.png\" /><br />";
290 m_widget.destinationDistanceLabel->setText( pixmapHtml + richText( fuzzyDistance( remaining ) ) );
292 m_widget.instructionIconLabel->setEnabled( m_nearNextInstruction );
293 m_widget.progressBar->setMaximum( thresholdDistance );
294 m_widget.progressBar->setValue( qRound( distanceLeft ) );
296 updateButtonVisibility();
299 pixmapHtml =
QString(
"<img src=\"%1\" />" ).
arg( pixmap );
301 GeoDataCoordinates
const onRoute = m_routingModel->route().positionOnRoute();
302 GeoDataCoordinates
const ego = m_routingModel->route().position();
305 if ( !m_routingModel->route().currentSegment().isValid() ) {
306 m_widget.instructionLabel->setText( richText(
QObject::tr(
"Calculate a route to get directions." ) ) );
307 m_widget.instructionIconLabel->setText( pixmapHtml );
308 }
else if ( distanceToRoute > 300.0 ) {
309 m_widget.instructionLabel->setText( richText(
QObject::tr(
"Route left." ) ) );
310 m_widget.instructionIconLabel->setText( pixmapHtml );
311 }
else if ( !m_routingModel->route().currentSegment().nextRouteSegment().isValid() ) {
312 m_widget.instructionLabel->setText( richText(
QObject::tr(
"Destination ahead." ) ) );
313 m_widget.instructionIconLabel->setText( pixmapHtml );
315 pixmap = m_routingModel->route().currentSegment().nextRouteSegment().maneuver().directionPixmap();
316 QString const instructionText = m_routingModel->route().currentSegment().nextRouteSegment().maneuver().instructionText();
317 m_widget.instructionLabel->setText( richText(
"%1" ).arg( instructionText ) );
318 pixmapHtml =
QString(
"<p align=\"center\"><img src=\"%1\" /><br />%2</p>" ).
arg( pixmap );
319 m_widget.instructionIconLabel->setText( pixmapHtml.
arg( richText( fuzzyDistance( distanceLeft ) ) ) );
321 if( remaining > 50 ) {
322 m_routeCompleted =
false;
324 if ( !m_routeCompleted ) {
325 QString content =
QObject::tr(
"Arrived at destination. <a href=\"#reverse\">Calculate the way back.</a>" );
326 m_widget.instructionLabel->setText( richText(
"%1" ).arg( content ) );
328 m_routeCompleted =
true;
336 void RoutingPluginPrivate::updateGpsButton( PositionProviderPlugin *activePlugin )
338 m_widget.gpsButton->setChecked( activePlugin != 0 );
342 void RoutingPluginPrivate::togglePositionTracking(
bool enabled )
344 PositionProviderPlugin* plugin = 0;
346 const PluginManager* pluginManager = m_marbleWidget->model()->pluginManager();
348 if ( plugins.
size() > 0 ) {
349 plugin = plugins.
first()->newInstance();
352 m_parent->marbleModel()->positionTracking()->setPositionProviderPlugin( plugin );
355 void RoutingPluginPrivate::reverseRoute()
357 if ( m_marbleWidget ) {
358 m_marbleWidget->model()->routingManager()->reverseRoute();
362 void RoutingPluginPrivate::readSettings()
364 if ( m_configDialog ) {
365 if ( !m_speakersModel ) {
366 m_speakersModel =
new SpeakersModel( m_parent );
368 int const index = m_speakersModel->indexOf( m_audio->speaker() );
369 m_configUi.speakerComboBox->setModel( m_speakersModel );
370 m_configUi.speakerComboBox->setCurrentIndex( index );
371 m_configUi.voiceNavigationCheckBox->setChecked( !m_audio->isMuted() );
372 m_configUi.soundRadioButton->setChecked( m_audio->isSoundEnabled() );
373 m_configUi.speakerRadioButton->setChecked( !m_audio->isSoundEnabled() );
377 qreal RoutingPluginPrivate::nextInstructionDistance()
const
379 GeoDataCoordinates position = m_routingModel->route().position();
380 GeoDataCoordinates interpolated = m_routingModel->route().positionOnRoute();
381 GeoDataCoordinates onRoute = m_routingModel->route().currentWaypoint();
383 const RouteSegment &segment = m_routingModel->route().currentSegment();
384 for (
int i=0; i<segment.path().size(); ++i) {
385 if (segment.path()[i] == onRoute) {
386 return distance + segment.path().length(
EARTH_RADIUS, i );
393 qreal RoutingPluginPrivate::remainingDistance()
const
395 GeoDataCoordinates position = m_routingModel->route().currentSegment().maneuver().position();
396 bool foundSegment =
false;
397 qreal distance = nextInstructionDistance();
398 for (
int i=0; i<m_routingModel->route().size(); ++i ) {
399 if ( foundSegment ) {
400 distance += m_routingModel->route().at( i ).distance();
402 foundSegment = m_routingModel->route().at( i ).maneuver().position() == position;
409 void RoutingPlugin::writeSettings()
411 Q_ASSERT( d->m_configDialog );
412 int const index = d->m_configUi.speakerComboBox->currentIndex();
414 QModelIndex const idx = d->m_speakersModel->index( index );
417 d->m_speakersModel->install( index );
420 d->m_audio->setMuted( !d->m_configUi.voiceNavigationCheckBox->isChecked() );
421 d->m_audio->setSoundEnabled( d->m_configUi.soundRadioButton->isChecked() );
435 d( new RoutingPluginPrivate( this ) )
457 return tr(
"Routing" );
462 return tr(
"&Routing" );
477 return tr(
"Routing information and navigation controls" );
488 <<
PluginAuthor(
"Siddharth Srivastava",
"akssps011@gmail.com" )
494 return QIcon(
":/icons/routeplanning.png");
500 d->m_widget.setupUi( widget );
502 d->m_widgetItem->setWidget( widget );
505 d->updateGpsButton( activePlugin );
510 d->m_widget.routingButton->setEnabled(
false );
511 connect( d->m_widget.instructionLabel, SIGNAL(linkActivated(
QString)),
512 this, SLOT(reverseRoute()) );
514 #if QT_VERSION < 0x050000
527 layout->
addItem( d->m_widgetItem, 0, 0 );
529 d->updateButtonVisibility();
534 return d->m_widgetItem;
539 if ( d->m_marbleWidget || !enabled() || !
visible() ) {
545 if ( widget && !d->m_marbleWidget ) {
546 d->m_marbleWidget = widget;
547 d->m_routingModel = d->m_marbleWidget->model()->routingManager()->routingModel();
549 connect( d->m_widget.routingButton, SIGNAL(clicked(
bool)),
550 this, SLOT(toggleGuidanceMode(
bool)) );
551 connect( d->m_widget.gpsButton, SIGNAL(clicked(
bool)),
552 this, SLOT(togglePositionTracking(
bool)) );
553 connect( d->m_widget.zoomInButton, SIGNAL(clicked()),
554 d->m_marbleWidget, SLOT(zoomIn()) );
555 connect( d->m_widget.zoomOutButton, SIGNAL(clicked()),
556 d->m_marbleWidget, SLOT(zoomOut()) );
558 this, SLOT(updateZoomButtons()) );
559 connect( d->m_marbleWidget, SIGNAL(zoomChanged(
int)),
560 this, SLOT(updateZoomButtons(
int)) );
561 connect( d->m_routingModel, SIGNAL(currentRouteChanged()),
562 this, SLOT(updateGuidanceModeButton()) );
563 d->updateGuidanceModeButton();
572 result.
insert(
"muted", d->m_audio->isMuted() );
573 result.
insert(
"sound", d->m_audio->isSoundEnabled() );
574 result.
insert(
"speaker", d->m_audio->speaker() );
583 d->m_audio->setMuted( settings.
value(
"muted",
false ).toBool() );
584 d->m_audio->setSoundEnabled( settings.
value(
"sound",
true ).toBool() );
585 d->m_audio->setSpeaker( settings.
value(
"speaker" ).toString() );
592 if ( !d->m_configDialog ) {
593 d->m_configDialog =
new QDialog;
594 d->m_configUi.setupUi( d->m_configDialog );
597 connect( d->m_configDialog, SIGNAL(accepted()),
this, SLOT(writeSettings()) );
598 connect( d->m_configDialog, SIGNAL(rejected()),
this, SLOT(readSettings()) );
599 connect( d->m_configUi.buttonBox->button( QDialogButtonBox::Reset ), SIGNAL(clicked()),
603 return d->m_configDialog;
610 #include "RoutingPlugin.moc"
QString copyrightYears() const
PositionProviderPlugin positionProviderPlugin
virtual QHash< QString, QVariant > settings() const
Settings of the plugin.
bool visible() const
Check visibility of the float item.
QString nameId() const
Returns the unique name of the plugin.
iterator insert(const Key &key, const T &value)
static QString path(const QString &relativePath)
QIcon icon() const
Returns an icon for the plugin.
virtual void setSettings(const QHash< QString, QVariant > &settings)
Set the settings of the plugin.
This file contains the headers for MarbleModel.
virtual bool eventFilter(QObject *object, QEvent *e)
bool eventFilter(QObject *object, QEvent *event)
void setBackground(const QBrush &background)
Changes the background brush of the item.
virtual void setSettings(const QHash< QString, QVariant > &settings)
Set the settings of the plugin.
void restoreDefaultSettings()
Passes an empty set of settings to the plugin.
qreal distanceSphere(qreal lon1, qreal lat1, qreal lon2, qreal lat2)
This method calculates the shortest distance between two points on a sphere.
void setLayout(AbstractMarbleGraphicsLayout *layout)
Set the layout of the graphics item.
void addItem(ScreenGraphicsItem *item, int row, int column)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QString tr(const char *sourceText, const char *disambiguation, int n)
The abstract class that provides position information.
bool isInitialized() const
QString fromUtf8(const char *str, int size)
QStringList backendTypes() const
Returns the name(s) of the backend that the plugin can render This method should return the name of t...
void settingsChanged(QString nameId)
This signal is emitted if the settings of the RenderPlugin changed.
The abstract class for float item plugins.
PositionTracking * positionTracking() const
QList< PluginAuthor > pluginAuthors() const
QString name() const
Returns the user-visible name of the plugin.
#define Q_EXPORT_PLUGIN2(a, b)
const T value(const Key &key) const
This file contains the headers for ViewportParams.
static MarbleGlobal * getInstance()
virtual QHash< QString, QVariant > settings() const
Settings of the plugin.
The data model (not based on QAbstractModel) for a MarbleWidget.
void setEnabled(bool enabled)
settting enabled
Profiles profiles() const
QString guiString() const
String that should be displayed in GUI.
QDialog * configDialog()
Returns a pointer to the configuration dialog of the plugin.
AbstractMarbleGraphicsLayout * layout() const
Returns the layout of the MarbleGraphicsItem.
void setBorderWidth(qreal width)
Set the border width of the item.
QString description() const
Returns a user description of the plugin.
const MarbleModel * marbleModel() const
Access to the MarbleModel.
void setPadding(qreal width)
Set the padding of the item.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
void setVisible(bool visible)
Set visibility of the float item.