1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2010 Dennis Nienhüser <nienhueser@kde.org>
4 //
5
6 #include "MonavConfigWidget.h"
7
8 #include "MonavMapsModel.h"
9 #include "MonavPlugin.h"
10 #include "MarbleDirs.h"
11 #include "MarbleDebug.h"
12
13 #include <QFile>
14 #include <QProcess>
15 #include <QSignalMapper>
16 #include <QPushButton>
17 #include <QShowEvent>
18 #include <QSortFilterProxyModel>
19 #include <QMessageBox>
20 #include <QNetworkAccessManager>
21 #include <QNetworkReply>
22 #include <QDomDocument>
23
24 namespace Marble
25 {
26
27 class MonavStuffEntry
28 {
29 public:
30 void setPayload( const QString &payload );
31
32 QString payload() const;
33
34 void setName( const QString &name );
35
36 QString name() const;
37
38 bool isValid() const;
39
40 QString continent() const;
41
42 QString state() const;
43
44 QString region() const;
45
46 QString transport() const;
47
48 private:
49 QString m_payload;
50
51 QString m_name;
52
53 QString m_continent;
54
55 QString m_state;
56
57 QString m_region;
58
59 QString m_transport;
60 };
61
62 class MonavConfigWidgetPrivate
63 {
64 public:
65 MonavConfigWidget* m_parent;
66
67 MonavPlugin* m_plugin;
68
69 QNetworkAccessManager m_networkAccessManager;
70
71 QNetworkReply* m_currentReply;
72
73 QProcess* m_unpackProcess;
74
75 QSortFilterProxyModel* m_filteredModel;
76
77 MonavMapsModel* m_mapsModel;
78
79 bool m_initialized;
80
81 QSignalMapper m_removeMapSignalMapper;
82
83 QSignalMapper m_upgradeMapSignalMapper;
84
85 QVector<MonavStuffEntry> m_remoteMaps;
86
87 QMap<QString, QString> m_remoteVersions;
88
89 QString m_currentDownload;
90
91 QFile m_currentFile;
92
93 QString m_transport;
94
95 MonavConfigWidgetPrivate( MonavConfigWidget* parent, MonavPlugin* plugin );
96
97 void parseNewStuff( const QByteArray &data );
98
99 bool updateContinents( QComboBox* comboBox );
100
101 bool updateStates( const QString &continent, QComboBox* comboBox );
102
103 bool updateRegions( const QString &continent, const QString &state, QComboBox* comboBox );
104
105 MonavStuffEntry map( const QString &continent, const QString &state, const QString ®ion ) const;
106
107 void install();
108
109 void installMap();
110
111 void updateInstalledMapsView();
112
113 void updateInstalledMapsViewButtons();
114
115 void updateTransportPreference();
116
117 static bool canExecute( const QString &executable );
118
119 void setBusy( bool busy, const QString &message = QString() ) const;
120
121 private:
122 static bool fillComboBox( QStringList items, QComboBox* comboBox );
123 };
124
setPayload(const QString & payload)125 void MonavStuffEntry::setPayload( const QString &payload )
126 {
127 m_payload = payload;
128 }
129
payload() const130 QString MonavStuffEntry::payload() const
131 {
132 return m_payload;
133 }
134
setName(const QString & name)135 void MonavStuffEntry::setName( const QString &name )
136 {
137 m_name = name;
138 QStringList parsed = name.split( QLatin1Char( '/' ) );
139 int size = parsed.size();
140 m_continent = size > 0 ? parsed.at( 0 ).trimmed() : QString();
141 m_state = size > 1 ? parsed.at( 1 ).trimmed() : QString();
142 m_region = size > 2 ? parsed.at( 2 ).trimmed() : QString();
143 m_transport = "Motorcar"; // No i18n
144
145 if ( size > 1 ) {
146 QString last = parsed.last().trimmed();
147 QRegExp regexp("([^(]+)\\(([^)]+)\\)");
148 if ( regexp.indexIn( last ) >= 0 ) {
149 QStringList matches = regexp.capturedTexts();
150 if ( matches.size() == 3 ) {
151 m_transport = matches.at( 2 ).trimmed();
152 if ( size > 2 ) {
153 m_region = matches.at( 1 ).trimmed();
154 } else {
155 m_state = matches.at( 1 ).trimmed();
156 }
157 }
158 }
159 }
160 }
161
name() const162 QString MonavStuffEntry::name() const
163 {
164 return m_name;
165 }
166
continent() const167 QString MonavStuffEntry::continent() const
168 {
169 return m_continent;
170 }
171
state() const172 QString MonavStuffEntry::state() const
173 {
174 return m_state;
175 }
176
region() const177 QString MonavStuffEntry::region() const
178 {
179 return m_region;
180 }
181
transport() const182 QString MonavStuffEntry::transport() const
183 {
184 return m_transport;
185 }
186
isValid() const187 bool MonavStuffEntry::isValid() const
188 {
189 return !m_continent.isEmpty() && !m_state.isEmpty() && m_payload.startsWith( QLatin1String( "http://" ) );
190 }
191
MonavConfigWidgetPrivate(MonavConfigWidget * parent,MonavPlugin * plugin)192 MonavConfigWidgetPrivate::MonavConfigWidgetPrivate( MonavConfigWidget* parent, MonavPlugin* plugin ) :
193 m_parent( parent ), m_plugin( plugin ), m_networkAccessManager( nullptr ),
194 m_currentReply( nullptr ), m_unpackProcess( nullptr ), m_filteredModel( new QSortFilterProxyModel( parent) ),
195 m_mapsModel( nullptr ), m_initialized( false )
196 {
197 m_filteredModel->setFilterKeyColumn( 1 );
198 }
199
parseNewStuff(const QByteArray & data)200 void MonavConfigWidgetPrivate::parseNewStuff( const QByteArray &data )
201 {
202 QDomDocument xml;
203 if ( !xml.setContent( data ) ) {
204 mDebug() << "Cannot parse xml file " << data;
205 return;
206 }
207
208 QDomElement root = xml.documentElement();
209 QDomNodeList items = root.elementsByTagName(QStringLiteral("stuff"));
210 for (int i=0 ; i < items.length(); ++i ) {
211 MonavStuffEntry item;
212 QDomNode node = items.item( i );
213
214 QDomNodeList names = node.toElement().elementsByTagName(QStringLiteral("name"));
215 if ( names.size() == 1 ) {
216 item.setName( names.at( 0 ).toElement().text() );
217 }
218
219 QString releaseDate;
220 QDomNodeList dates = node.toElement().elementsByTagName(QStringLiteral("releasedate"));
221 if ( dates.size() == 1 ) {
222 releaseDate = dates.at( 0 ).toElement().text();
223 }
224
225 QString filename;
226 QDomNodeList payloads = node.toElement().elementsByTagName(QStringLiteral("payload"));
227 if ( payloads.size() == 1 ) {
228 QString payload = payloads.at( 0 ).toElement().text();
229 filename = payload.mid(1 + payload.lastIndexOf(QLatin1Char('/')));
230 item.setPayload( payload );
231 }
232
233 if ( item.isValid() ) {
234 m_remoteMaps.push_back( item );
235 if ( !filename.isEmpty() && !releaseDate.isEmpty() ) {
236 m_remoteVersions[filename] = releaseDate;
237 }
238 }
239 }
240
241 m_mapsModel->setInstallableVersions( m_remoteVersions );
242 updateInstalledMapsViewButtons();
243 }
244
fillComboBox(QStringList items,QComboBox * comboBox)245 bool MonavConfigWidgetPrivate::fillComboBox( QStringList items, QComboBox* comboBox )
246 {
247 comboBox->clear();
248 std::sort( items.begin(), items.end() );
249 comboBox->addItems( items );
250 return !items.isEmpty();
251 }
252
updateContinents(QComboBox * comboBox)253 bool MonavConfigWidgetPrivate::updateContinents( QComboBox* comboBox )
254 {
255 QSet<QString> continents;
256 for( const MonavStuffEntry &map: m_remoteMaps ) {
257 Q_ASSERT( map.isValid() );
258 continents << map.continent();
259 }
260
261 return fillComboBox( continents.toList(), comboBox );
262 }
263
updateStates(const QString & continent,QComboBox * comboBox)264 bool MonavConfigWidgetPrivate::updateStates( const QString &continent, QComboBox* comboBox )
265 {
266 QSet<QString> states;
267 for( const MonavStuffEntry &map: m_remoteMaps ) {
268 Q_ASSERT( map.isValid() );
269 if ( map.continent() == continent ) {
270 states << map.state();
271 }
272 }
273
274 return fillComboBox( states.toList(), comboBox );
275 }
276
updateRegions(const QString & continent,const QString & state,QComboBox * comboBox)277 bool MonavConfigWidgetPrivate::updateRegions( const QString &continent, const QString &state, QComboBox* comboBox )
278 {
279 comboBox->clear();
280 QMap<QString,QString> regions;
281 for( const MonavStuffEntry &map: m_remoteMaps ) {
282 Q_ASSERT( map.isValid() );
283 if ( map.continent() == continent && map.state() == state ) {
284 QString item = "%1 - %2";
285 if ( map.region().isEmpty() ) {
286 item = item.arg( map.state() );
287 comboBox->addItem( item.arg( map.transport() ), map.payload() );
288 } else {
289 item = item.arg( map.region(), map.transport() );
290 regions.insert( item, map.payload() );
291 }
292 }
293 }
294
295 QMapIterator<QString, QString> iter( regions );
296 while ( iter.hasNext() ) {
297 iter.next();
298 comboBox->addItem( iter.key(), iter.value() );
299 }
300
301 return true;
302 }
303
map(const QString & continent,const QString & state,const QString & region) const304 MonavStuffEntry MonavConfigWidgetPrivate::map( const QString &continent, const QString &state, const QString ®ion ) const
305 {
306 for( const MonavStuffEntry &entry: m_remoteMaps ) {
307 if ( continent == entry.continent() && state == entry.state() && region == entry.region() ) {
308 return entry;
309 }
310 }
311
312 return MonavStuffEntry();
313 }
314
MonavConfigWidget(MonavPlugin * plugin)315 MonavConfigWidget::MonavConfigWidget( MonavPlugin* plugin ) :
316 d( new MonavConfigWidgetPrivate( this, plugin ) )
317 {
318 setupUi( this );
319 m_statusLabel->setText( plugin->statusMessage() );
320 m_statusLabel->setHidden( m_statusLabel->text().isEmpty() );
321 d->setBusy( false );
322 m_installedMapsListView->setModel( d->m_mapsModel );
323 m_configureMapsListView->setModel( d->m_filteredModel );
324 m_configureMapsListView->resizeColumnsToContents();
325
326 updateComboBoxes();
327
328 connect( m_continentComboBox, SIGNAL(currentIndexChanged(int)),
329 this, SLOT(updateStates()) );
330 connect( m_transportTypeComboBox, SIGNAL(currentIndexChanged(QString)),
331 this, SLOT(updateTransportTypeFilter(QString)) );
332 connect( m_stateComboBox, SIGNAL(currentIndexChanged(int)),
333 this, SLOT(updateRegions()) );
334 connect( m_installButton, SIGNAL(clicked()), this, SLOT(downloadMap()) );
335 connect( m_cancelButton, SIGNAL(clicked()), this, SLOT(cancelOperation()) );
336 connect( &d->m_removeMapSignalMapper, SIGNAL(mapped(int)),
337 this, SLOT(removeMap(int)) );
338 connect( &d->m_upgradeMapSignalMapper, SIGNAL(mapped(int)),
339 this, SLOT(upgradeMap(int)) );
340 connect( &d->m_networkAccessManager, SIGNAL(finished(QNetworkReply*)),
341 this, SLOT(retrieveMapList(QNetworkReply*)) );
342 }
343
~MonavConfigWidget()344 MonavConfigWidget::~MonavConfigWidget()
345 {
346 delete d;
347 }
348
loadSettings(const QHash<QString,QVariant> & settings)349 void MonavConfigWidget::loadSettings( const QHash<QString, QVariant> &settings )
350 {
351 d->m_transport = settings[QStringLiteral("transport")].toString();
352 d->updateTransportPreference();
353 }
354
updateTransportPreference()355 void MonavConfigWidgetPrivate::updateTransportPreference()
356 {
357 if ( m_parent->m_transportTypeComboBox && m_mapsModel ) {
358 m_parent->m_transportTypeComboBox->blockSignals( true );
359 m_parent->m_transportTypeComboBox->clear();
360 QSet<QString> transportTypes;
361 for( int i=0; i<m_mapsModel->rowCount(); ++i ) {
362 QModelIndex index = m_mapsModel->index( i, 1 );
363 transportTypes << m_mapsModel->data( index ).toString();
364 }
365 m_parent->m_transportTypeComboBox->addItems( transportTypes.toList() );
366 m_parent->m_transportTypeComboBox->blockSignals( false );
367
368 if ( !m_transport.isEmpty() && m_parent->m_transportTypeComboBox ) {
369 for ( int i=1; i<m_parent->m_transportTypeComboBox->count(); ++i ) {
370 if ( m_parent->m_transportTypeComboBox->itemText( i ) == m_transport ) {
371 m_parent->m_transportTypeComboBox->setCurrentIndex( i );
372 return;
373 }
374 }
375 }
376 }
377 }
378
settings() const379 QHash<QString, QVariant> MonavConfigWidget::settings() const
380 {
381 QHash<QString, QVariant> settings;
382 settings.insert(QStringLiteral("transport"), d->m_transport);
383 return settings;
384 }
385
retrieveMapList(QNetworkReply * reply)386 void MonavConfigWidget::retrieveMapList( QNetworkReply *reply )
387 {
388 if ( reply->isReadable() && d->m_currentDownload.isEmpty() ) {
389 // check if we are redirected
390 QVariant const redirectionAttribute = reply->attribute( QNetworkRequest::RedirectionTargetAttribute );
391 if ( !redirectionAttribute.isNull() ) {
392 d->m_networkAccessManager.get( QNetworkRequest( redirectionAttribute.toUrl() ) );
393 } else {
394 disconnect( &d->m_networkAccessManager, SIGNAL(finished(QNetworkReply*)),
395 this, SLOT(retrieveMapList(QNetworkReply*)) );
396 d->parseNewStuff( reply->readAll() );
397 updateComboBoxes();
398 }
399 }
400 }
401
retrieveData()402 void MonavConfigWidget::retrieveData()
403 {
404 if ( d->m_currentReply && d->m_currentReply->isReadable() && !d->m_currentDownload.isEmpty() ) {
405 // check if we are redirected
406 QVariant const redirectionAttribute = d->m_currentReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
407 if ( !redirectionAttribute.isNull() ) {
408 d->m_currentReply = d->m_networkAccessManager.get( QNetworkRequest( redirectionAttribute.toUrl() ) );
409 connect( d->m_currentReply, SIGNAL(readyRead()),
410 this, SLOT(retrieveData()) );
411 connect( d->m_currentReply, SIGNAL(readChannelFinished()),
412 this, SLOT(retrieveData()) );
413 connect( d->m_currentReply, SIGNAL(downloadProgress(qint64,qint64)),
414 this, SLOT(updateProgressBar(qint64,qint64)) );
415 } else {
416 d->m_currentFile.write( d->m_currentReply->readAll() );
417 if ( d->m_currentReply->isFinished() ) {
418 d->m_currentReply->deleteLater();
419 d->m_currentReply = nullptr;
420 d->m_currentFile.close();
421 d->installMap();
422 d->m_currentDownload.clear();
423 }
424 }
425 }
426 }
427
updateComboBoxes()428 void MonavConfigWidget::updateComboBoxes()
429 {
430 d->updateContinents( m_continentComboBox );
431 updateStates();
432 updateRegions();
433 }
434
updateStates()435 void MonavConfigWidget::updateStates()
436 {
437 bool const haveContinents = m_continentComboBox->currentIndex() >= 0;
438 if ( haveContinents ) {
439 QString const continent = m_continentComboBox->currentText();
440 if ( d->updateStates( continent, m_stateComboBox ) ) {
441 updateRegions();
442 }
443 }
444 }
445
updateRegions()446 void MonavConfigWidget::updateRegions()
447 {
448 bool haveRegions = false;
449 if ( m_continentComboBox->currentIndex() >= 0 ) {
450 if ( m_stateComboBox->currentIndex() >= 0 ) {
451 QString const continent = m_continentComboBox->currentText();
452 QString const state = m_stateComboBox->currentText();
453 haveRegions = d->updateRegions( continent, state, m_regionComboBox );
454 }
455 }
456
457 m_regionLabel->setVisible( haveRegions );
458 m_regionComboBox->setVisible( haveRegions );
459 }
460
downloadMap()461 void MonavConfigWidget::downloadMap()
462 {
463 if ( d->m_currentDownload.isEmpty() && !d->m_currentFile.isOpen() ) {
464 d->m_currentDownload = m_regionComboBox->itemData( m_regionComboBox->currentIndex() ).toString();
465 d->install();
466 }
467 }
468
cancelOperation()469 void MonavConfigWidget::cancelOperation()
470 {
471 if ( !d->m_currentDownload.isEmpty() || d->m_currentFile.isOpen() ) {
472 d->m_currentReply->abort();
473 d->m_currentReply->deleteLater();
474 d->m_currentReply = nullptr;
475 d->m_currentDownload.clear();
476 d->setBusy( false );
477 d->m_currentFile.close();
478 }
479 }
480
install()481 void MonavConfigWidgetPrivate::install()
482 {
483 if ( !m_currentDownload.isEmpty() ) {
484 int const index = m_currentDownload.lastIndexOf(QLatin1Char('/'));
485 const QString localFile = MarbleDirs::localPath() + QLatin1String("/maps") + m_currentDownload.mid(index);
486 m_currentFile.setFileName( localFile );
487 if ( m_currentFile.open( QFile::WriteOnly ) ) {
488 QFileInfo file( m_currentFile );
489 QString message = QObject::tr( "Downloading %1" ).arg( file.fileName() );
490 setBusy( true, message );
491 m_currentReply = m_networkAccessManager.get( QNetworkRequest( QUrl ( m_currentDownload ) ) );
492 QObject::connect( m_currentReply, SIGNAL(readyRead()),
493 m_parent, SLOT(retrieveData()) );
494 QObject::connect( m_currentReply, SIGNAL(readChannelFinished()),
495 m_parent, SLOT(retrieveData()) );
496 QObject::connect( m_currentReply, SIGNAL(downloadProgress(qint64,qint64)),
497 m_parent, SLOT(updateProgressBar(qint64,qint64)) );
498 } else {
499 mDebug() << "Failed to write to " << localFile;
500 }
501 }
502 }
503
installMap()504 void MonavConfigWidgetPrivate::installMap()
505 {
506 if ( m_unpackProcess ) {
507 m_unpackProcess->close();
508 delete m_unpackProcess;
509 m_unpackProcess = nullptr;
510 m_parent->m_installButton->setEnabled( true );
511 } else if ( m_currentFile.fileName().endsWith( QLatin1String( "tar.gz" ) ) && canExecute( "tar" ) ) {
512 QFileInfo file( m_currentFile );
513 QString message = QObject::tr( "Installing %1" ).arg( file.fileName() );
514 setBusy( true, message );
515 m_parent->m_progressBar->setMaximum( 0 );
516 if ( file.exists() && file.isReadable() ) {
517 m_unpackProcess = new QProcess;
518 QObject::connect( m_unpackProcess, SIGNAL(finished(int)),
519 m_parent, SLOT(mapInstalled(int)) );
520 QStringList arguments = QStringList() << "-x" << "-z" << "-f" << file.fileName();
521 m_unpackProcess->setWorkingDirectory( file.dir().absolutePath() );
522 m_unpackProcess->start( "tar", arguments );
523 }
524 } else {
525 if ( !m_currentFile.fileName().endsWith( QLatin1String( "tar.gz" ) ) ) {
526 mDebug() << "Can only handle tar.gz files";
527 } else {
528 mDebug() << "Cannot extract archive: tar executable not found in PATH.";
529 }
530 }
531 }
532
updateProgressBar(qint64 bytesReceived,qint64 bytesTotal)533 void MonavConfigWidget::updateProgressBar( qint64 bytesReceived, qint64 bytesTotal )
534 {
535 // Coarse MB resolution for the text to get it short,
536 // finer Kb resolution for the progress values to see changes easily
537 m_progressBar->setMaximum( bytesTotal / 1024 );
538 m_progressBar->setValue( bytesReceived / 1024 );
539 QString progress = "%1/%2 MB";
540 m_progressBar->setFormat( progress.arg( bytesReceived / 1024 / 1024 ).arg( bytesTotal / 1024 / 1024 ) );
541 }
542
canExecute(const QString & executable)543 bool MonavConfigWidgetPrivate::canExecute( const QString &executable )
544 {
545 QString path = QProcessEnvironment::systemEnvironment().value(QStringLiteral("PATH"), QStringLiteral("/usr/local/bin:/usr/bin:/bin"));
546 for( const QString &dir: path.split( QLatin1Char( ':' ) ) ) {
547 QFileInfo application( QDir( dir ), executable );
548 if ( application.exists() ) {
549 return true;
550 }
551 }
552
553 return false;
554 }
555
mapInstalled(int exitStatus)556 void MonavConfigWidget::mapInstalled( int exitStatus )
557 {
558 d->m_unpackProcess = nullptr;
559 d->m_currentFile.remove();
560 d->setBusy( false );
561
562 if ( exitStatus == 0 ) {
563 d->m_plugin->reloadMaps();
564 d->updateInstalledMapsView();
565 monavTabWidget->setCurrentIndex( 0 );
566 } else {
567 mDebug() << "Error when unpacking archive, process exited with status code " << exitStatus;
568 }
569 }
570
showEvent(QShowEvent * event)571 void MonavConfigWidget::showEvent ( QShowEvent * event )
572 {
573 // Lazy initialization
574 RoutingRunnerPlugin::ConfigWidget::showEvent( event );
575 if ( !event->spontaneous() && !d->m_initialized ) {
576 d->m_initialized = true;
577 d->updateInstalledMapsView();
578 QUrl url = QUrl( "http://files.kde.org/marble/newstuff/maps-monav.xml" );
579 d->m_networkAccessManager.get( QNetworkRequest( url ) );
580 }
581 }
582
updateInstalledMapsView()583 void MonavConfigWidgetPrivate::updateInstalledMapsView()
584 {
585 m_mapsModel = m_plugin->installedMapsModel();
586 m_mapsModel->setInstallableVersions( m_remoteVersions );
587 m_filteredModel->setSourceModel( m_mapsModel );
588 m_parent->m_installedMapsListView->setModel( m_mapsModel );
589
590 m_parent->m_configureMapsListView->setColumnHidden( 1, true );
591 m_parent->m_installedMapsListView->setColumnHidden( 2, true );
592 m_parent->m_configureMapsListView->setColumnHidden( 3, true );
593 m_parent->m_configureMapsListView->setColumnHidden( 4, true );
594 m_parent->m_installedMapsListView->setColumnHidden( 5, true );
595
596 m_parent->m_configureMapsListView->horizontalHeader()->setVisible( true );
597 m_parent->m_installedMapsListView->horizontalHeader()->setVisible( true );
598 m_parent->m_configureMapsListView->resizeColumnsToContents();
599 m_parent->m_installedMapsListView->resizeColumnsToContents();
600
601 updateTransportPreference();
602 updateInstalledMapsViewButtons();
603 }
604
updateInstalledMapsViewButtons()605 void MonavConfigWidgetPrivate::updateInstalledMapsViewButtons()
606 {
607 m_removeMapSignalMapper.removeMappings( m_parent );
608 m_upgradeMapSignalMapper.removeMappings( m_parent );
609 for( int i=0; i<m_mapsModel->rowCount(); ++i ) {
610 {
611 QPushButton* button = new QPushButton(QIcon(QStringLiteral(":/system-software-update.png")), QString());
612 button->setAutoFillBackground( true );
613 QModelIndex index = m_mapsModel->index( i, 3 );
614 m_parent->m_installedMapsListView->setIndexWidget( index, button );
615 m_upgradeMapSignalMapper.setMapping( button, index.row() );
616 QObject::connect( button, SIGNAL(clicked()), &m_upgradeMapSignalMapper, SLOT(map()) );
617 bool upgradable = m_mapsModel->data( index ).toBool();
618 QString canUpgradeText = QObject::tr( "An update is available. Click to install it." );
619 QString isLatestText = QObject::tr( "No update available. You are running the latest version." );
620 button->setToolTip( upgradable ? canUpgradeText : isLatestText );
621 button->setEnabled( upgradable );
622 }
623 {
624 QPushButton* button = new QPushButton(QIcon(QStringLiteral(":/edit-delete.png")), QString());
625 button->setAutoFillBackground( true );
626 QModelIndex index = m_mapsModel->index( i, 4 );
627 m_parent->m_installedMapsListView->setIndexWidget( index, button );
628 m_removeMapSignalMapper.setMapping( button, index.row() );
629 QObject::connect( button, SIGNAL(clicked()), &m_removeMapSignalMapper, SLOT(map()) );
630 bool const writable = m_mapsModel->data( index ).toBool();
631 button->setEnabled( writable );
632 }
633 }
634 m_parent->m_installedMapsListView->resizeColumnsToContents();
635 }
636
updateTransportTypeFilter(const QString & filter)637 void MonavConfigWidget::updateTransportTypeFilter( const QString &filter )
638 {
639 d->m_filteredModel->setFilterFixedString( filter );
640 d->m_transport = filter;
641 m_configureMapsListView->resizeColumnsToContents();
642 }
643
removeMap(int index)644 void MonavConfigWidget::removeMap( int index )
645 {
646 QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel;
647 QString text = tr( "Are you sure you want to delete this map from the system?" );
648 if ( QMessageBox::question( this, tr( "Remove Map" ), text, buttons, QMessageBox::No ) == QMessageBox::Yes ) {
649 d->m_mapsModel->deleteMapFiles( index );
650 d->m_plugin->reloadMaps();
651 d->updateInstalledMapsView();
652 }
653 }
654
upgradeMap(int index)655 void MonavConfigWidget::upgradeMap( int index )
656 {
657 QString payload = d->m_mapsModel->payload( index );
658 if ( !payload.isEmpty() ) {
659 for( const MonavStuffEntry &entry: d->m_remoteMaps ) {
660 if (entry.payload().endsWith(QLatin1Char('/') + payload)) {
661 d->m_currentDownload = entry.payload();
662 d->install();
663 return;
664 }
665 }
666 }
667 }
668
setBusy(bool busy,const QString & message) const669 void MonavConfigWidgetPrivate::setBusy( bool busy, const QString &message ) const
670 {
671 if ( busy ) {
672 m_parent->m_stackedWidget->removeWidget( m_parent->m_settingsPage );
673 m_parent->m_stackedWidget->addWidget( m_parent->m_progressPage );
674 } else {
675 m_parent->m_stackedWidget->removeWidget( m_parent->m_progressPage );
676 m_parent->m_stackedWidget->addWidget( m_parent->m_settingsPage );
677 }
678
679 QString const defaultMessage = QObject::tr( "Nothing to do." );
680 m_parent->m_progressLabel->setText( message.isEmpty() ? defaultMessage : message );
681 }
682
683 }
684
685 #include "moc_MonavConfigWidget.cpp"
686