File indexing completed on 2024-04-21 03:49:31

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2010 Jens-Michael Hoffmann <jmho@c-xx.com>
0004 //
0005 
0006 #include "DownloadRegionDialog.h"
0007 
0008 #include <cmath>
0009 
0010 #include <QDialogButtonBox>
0011 #include <QGroupBox>
0012 #include <QHBoxLayout>
0013 #include <QHideEvent>
0014 #include <QLabel>
0015 #include <QComboBox>
0016 #include <QPushButton>
0017 #include <QButtonGroup>
0018 #include <QRadioButton>
0019 #include <QShowEvent>
0020 #include <QVBoxLayout>
0021 #include <QSpinBox>
0022 #include <QScrollArea>
0023 #include <QSet>
0024 #include <QStandardItemModel>
0025 #include <QTimer>
0026 
0027 #include "GeoDataLatLonAltBox.h"
0028 #include "MarbleDebug.h"
0029 #include "MarbleModel.h"
0030 #include "MarbleWidget.h"
0031 #include "LatLonBoxWidget.h"
0032 #include "TileLayer.h"
0033 #include "TextureLayer.h"
0034 #include "VectorTileLayer.h"
0035 #include "TileId.h"
0036 #include "TileCoordsPyramid.h"
0037 #include "TileLevelRangeWidget.h"
0038 #include "TileLoaderHelper.h"
0039 #include "routing/RoutingManager.h"
0040 #include "routing/RoutingModel.h"
0041 #include "GeoDataCoordinates.h"
0042 #include "GeoDataLineString.h"
0043 #include "DownloadRegion.h"
0044 #include "GeoSceneDocument.h"
0045 #include "GeoSceneMap.h"
0046 #include "Route.h"
0047 
0048 namespace Marble
0049 {
0050 
0051 int const maxTilesCount = 100000;
0052 int const minimumRouteOffset = 0;
0053 int const maximumRouteOffset = 10000;
0054 int averageTextureTileSize = 13; //The average size of a tile in kilobytes
0055 int averageVectorTileSize = 30; // The average size of a vector tile in kilobytes
0056 
0057 class Q_DECL_HIDDEN DownloadRegionDialog::Private
0058 {
0059 public:
0060     Private( MarbleWidget *const widget, QDialog * const dialog );
0061     QWidget * createSelectionMethodBox();
0062     QLayout * createTilesCounter();
0063     QWidget * createOkCancelButtonBox();
0064 
0065     bool hasRoute() const;
0066     bool hasTextureLayers() const;
0067     bool hasVectorLayers() const;
0068     QDialog * m_dialog;
0069     QLabel * m_layerLabel;
0070     QComboBox * m_layerComboBox;
0071     QButtonGroup * m_buttonGroup;
0072     QRadioButton * m_visibleRegionMethodButton;
0073     QRadioButton * m_specifiedRegionMethodButton;
0074     LatLonBoxWidget * m_latLonBoxWidget;
0075     TileLevelRangeWidget * m_tileLevelRangeWidget;
0076     QRadioButton *m_routeDownloadMethodButton;
0077     QLabel* m_routeOffsetLabel;
0078     QDoubleSpinBox *m_routeOffsetSpinBox;
0079     QLabel * m_tilesCountLabel;
0080     QLabel * m_tileSizeInfo;
0081     QPushButton * m_okButton;
0082     QPushButton * m_applyButton;
0083     TextureLayer const * m_textureLayer;
0084     VectorTileLayer const * m_vectorTileLayer;
0085     int m_visibleTileLevel;
0086     MarbleModel const*const m_model;
0087     MarbleWidget *const m_widget;
0088     SelectionMethod m_selectionMethod;
0089     GeoDataLatLonAltBox m_visibleRegion;
0090     RoutingModel *m_routingModel;
0091     DownloadRegion m_downloadRegion;
0092     TileType m_tileType;
0093 };
0094 
0095 DownloadRegionDialog::Private::Private( MarbleWidget * const widget,
0096                                         QDialog * const dialog )
0097     : m_dialog( dialog ),
0098       m_layerLabel( nullptr ),
0099       m_layerComboBox( nullptr ),
0100       m_buttonGroup(nullptr),
0101       m_visibleRegionMethodButton( nullptr ),
0102       m_specifiedRegionMethodButton( nullptr ),
0103       m_latLonBoxWidget( new LatLonBoxWidget ),
0104       m_tileLevelRangeWidget( new TileLevelRangeWidget ),
0105       m_routeDownloadMethodButton( nullptr ),
0106       m_routeOffsetLabel( nullptr ),
0107       m_routeOffsetSpinBox( nullptr ),
0108       m_tilesCountLabel( nullptr ),
0109       m_tileSizeInfo( nullptr ),
0110       m_okButton( nullptr ),
0111       m_applyButton( nullptr ),
0112       m_textureLayer( widget->textureLayer() ),
0113       m_vectorTileLayer( widget->vectorTileLayer() ),
0114       m_visibleTileLevel( 0 ),
0115       m_model( widget->model() ),
0116       m_widget( widget ),
0117       m_selectionMethod( VisibleRegionMethod ),
0118       m_visibleRegion(),
0119       m_routingModel( widget->model()->routingManager()->routingModel() )
0120 {
0121     m_latLonBoxWidget->setEnabled( false );
0122     m_latLonBoxWidget->setLatLonBox( m_visibleRegion );
0123     m_tileLevelRangeWidget->setDefaultLevel( m_visibleTileLevel );
0124     m_downloadRegion.setMarbleModel( widget->model() );
0125 }
0126 
0127 
0128 
0129 QWidget * DownloadRegionDialog::Private::createSelectionMethodBox()
0130 {
0131     m_buttonGroup = new QButtonGroup(m_dialog);
0132     m_buttonGroup->setExclusive(true);
0133     m_visibleRegionMethodButton = new QRadioButton( tr( "Visible region" ) );
0134     m_buttonGroup->addButton(m_visibleRegionMethodButton);
0135     m_specifiedRegionMethodButton = new QRadioButton( tr( "Specify region" ) );
0136     m_buttonGroup->addButton(m_specifiedRegionMethodButton);
0137     m_routeDownloadMethodButton = new QRadioButton( tr( "Download Route" ) );
0138     m_buttonGroup->addButton(m_routeDownloadMethodButton);
0139     m_routeDownloadMethodButton->setToolTip( tr( "Enabled when a route exists" ) );
0140     m_routeDownloadMethodButton->setEnabled( hasRoute() );
0141     m_routeDownloadMethodButton->setChecked( hasRoute() );
0142     m_routeOffsetSpinBox = new QDoubleSpinBox();
0143     m_routeOffsetSpinBox->setEnabled( hasRoute() );
0144     m_routeOffsetSpinBox->setRange( minimumRouteOffset, maximumRouteOffset );
0145     int defaultOffset = 500;
0146     m_routeOffsetSpinBox->setValue( defaultOffset );
0147     m_routeOffsetSpinBox->setSingleStep( 100 );
0148     m_routeOffsetSpinBox->setSuffix( " m" );
0149     m_routeOffsetSpinBox->setDecimals( 0 );
0150     m_routeOffsetSpinBox->setAlignment( Qt::AlignRight );
0151 
0152     m_routeOffsetLabel = new QLabel( tr( "Offset from route:" ) );
0153     m_routeOffsetLabel->setAlignment( Qt::AlignHCenter );
0154 
0155     connect( m_buttonGroup, SIGNAL(buttonToggled(QAbstractButton*,bool)),
0156              m_dialog, SLOT(toggleSelectionMethod()) );
0157     connect( m_routingModel, SIGNAL(modelReset()), m_dialog, SLOT(updateRouteDialog()) );
0158     connect( m_routingModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
0159              m_dialog, SLOT(updateRouteDialog()) );
0160     connect( m_routingModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
0161              m_dialog, SLOT(updateRouteDialog()) );
0162 
0163     QHBoxLayout *routeOffsetLayout = new QHBoxLayout;
0164     routeOffsetLayout->addWidget( m_routeOffsetLabel );
0165     routeOffsetLayout->insertSpacing( 0, 25 );
0166     routeOffsetLayout->addWidget( m_routeOffsetSpinBox );
0167 
0168     QVBoxLayout * const routeLayout = new QVBoxLayout;
0169     routeLayout->addWidget( m_routeDownloadMethodButton );
0170     routeLayout->addLayout( routeOffsetLayout );
0171 
0172     QVBoxLayout * const layout = new QVBoxLayout;
0173     layout->addWidget( m_visibleRegionMethodButton );
0174     layout->addLayout( routeLayout );
0175     layout->addWidget( m_specifiedRegionMethodButton );
0176     layout->addWidget( m_latLonBoxWidget );
0177 
0178     bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
0179     m_specifiedRegionMethodButton->setVisible( !smallScreen );
0180     m_latLonBoxWidget->setVisible( !smallScreen );
0181 
0182     if ( smallScreen ) {
0183         QWidget * const selectionMethodWidget = new QWidget;
0184         selectionMethodWidget->setLayout( layout );
0185         return selectionMethodWidget;
0186     } else {
0187         QGroupBox * const selectionMethodBox = new QGroupBox( tr( "Selection Method" ) );
0188         selectionMethodBox->setLayout( layout );
0189         return selectionMethodBox;
0190     }
0191 }
0192 
0193 QLayout * DownloadRegionDialog::Private::createTilesCounter()
0194 {
0195     QLabel * const description = new QLabel( tr( "Number of tiles to download:" ) );
0196     m_tilesCountLabel = new QLabel;
0197     m_tileSizeInfo = new QLabel;
0198 
0199     QHBoxLayout * const tilesCountLayout = new QHBoxLayout;
0200     tilesCountLayout->addWidget( description );
0201     tilesCountLayout->addWidget( m_tilesCountLabel );
0202     //tilesCountLayout->insertSpacing( 0, 5 );
0203     QVBoxLayout * const layout = new QVBoxLayout;
0204     layout->addLayout( tilesCountLayout );
0205     layout->addWidget( m_tileSizeInfo );
0206     return layout;
0207 }
0208 
0209 QWidget * DownloadRegionDialog::Private::createOkCancelButtonBox()
0210 {
0211     QDialogButtonBox * const buttonBox = new QDialogButtonBox;
0212     m_okButton = buttonBox->addButton( QDialogButtonBox::Ok );
0213     m_applyButton = buttonBox->addButton( QDialogButtonBox::Apply );
0214     if ( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) {
0215         buttonBox->removeButton( m_applyButton );
0216         m_applyButton->setVisible( false );
0217     }
0218     buttonBox->addButton( QDialogButtonBox::Cancel );
0219     connect( buttonBox, SIGNAL(accepted()), m_dialog, SLOT(accept()) );
0220     connect( buttonBox, SIGNAL(rejected()), m_dialog, SLOT(reject()) );
0221     connect( m_applyButton, SIGNAL(clicked()), m_dialog, SIGNAL(applied()) );
0222     return buttonBox;
0223 }
0224 
0225 bool DownloadRegionDialog::Private::hasRoute() const
0226 {
0227     return !m_routingModel->route().path().isEmpty();
0228 }
0229 
0230 bool DownloadRegionDialog::Private::hasTextureLayers() const
0231 {
0232     return m_model->mapTheme()->map()->hasTextureLayers();
0233 }
0234 
0235 bool DownloadRegionDialog::Private::hasVectorLayers() const
0236 {
0237     return m_model->mapTheme()->map()->hasVectorLayers();
0238 }
0239 
0240 DownloadRegionDialog::DownloadRegionDialog( MarbleWidget *const widget, QWidget * const parent,
0241                                             Qt::WindowFlags const f )
0242     : QDialog( parent, f ),
0243       d( new Private( widget, this ))
0244 {
0245     setWindowTitle( tr( "Download Region" ));
0246     QVBoxLayout * const layout = new QVBoxLayout;
0247     d->m_layerLabel = new QLabel( tr( "Tile type to be downloaded:" ));
0248     d->m_layerComboBox = new QComboBox();
0249     d->m_layerComboBox->addItem(tr("Texture tiles"));
0250     d->m_layerComboBox->addItem(tr("Vector tiles"));
0251     d->m_layerComboBox->setToolTip(tr("Allows selection between layer types that are visibly being rendered."));
0252     updateTileLayer();
0253 
0254     layout->addWidget( d->m_layerLabel );
0255     layout->addWidget( d->m_layerComboBox );
0256     layout->addWidget( d->createSelectionMethodBox() );
0257     layout->addWidget( d->m_tileLevelRangeWidget );
0258     layout->addStretch();
0259     layout->addLayout( d->createTilesCounter() );
0260 
0261     if ( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) {
0262         QWidget* widget = new QWidget( this );
0263         widget->setLayout( layout );
0264         QScrollArea* scrollArea = new QScrollArea( this );
0265         scrollArea->setFrameShape( QFrame::NoFrame );
0266         scrollArea->setWidget( widget );
0267         QVBoxLayout * const mainLayout = new QVBoxLayout;
0268         mainLayout->addWidget( scrollArea );
0269         mainLayout->addWidget( d->createOkCancelButtonBox() );
0270         setLayout( mainLayout );
0271     } else {
0272         layout->addWidget( d->createOkCancelButtonBox() );
0273         setLayout( layout );
0274     }
0275 
0276     connect( d->m_layerComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
0277              this, &DownloadRegionDialog::updateTileCount );
0278     connect( d->m_latLonBoxWidget, &Marble::LatLonBoxWidget::valueChanged,
0279              this, &DownloadRegionDialog::updateTileCount );
0280     connect( d->m_tileLevelRangeWidget, &TileLevelRangeWidget::topLevelChanged,
0281              this, &DownloadRegionDialog::updateTileCount );
0282     connect( d->m_tileLevelRangeWidget, &TileLevelRangeWidget::bottomLevelChanged,
0283              this, &DownloadRegionDialog::updateTileCount );
0284     connect( d->m_routeOffsetSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
0285              this, &DownloadRegionDialog::updateTileCount );
0286     connect( d->m_routeOffsetSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
0287              this, &DownloadRegionDialog::setOffsetUnit );
0288     connect( d->m_model, &MarbleModel::themeChanged,
0289              this, &DownloadRegionDialog::delayUpdateTileLayer);
0290 }
0291 
0292 DownloadRegionDialog::~DownloadRegionDialog()
0293 {
0294     delete d;
0295 }
0296 
0297 void DownloadRegionDialog::setAllowedTileLevelRange( int const minimumTileLevel,
0298                                                      int const maximumTileLevel )
0299 {
0300     d->m_tileLevelRangeWidget->setAllowedLevelRange( minimumTileLevel, maximumTileLevel );
0301 }
0302 
0303 void DownloadRegionDialog::setVisibleTileLevel( int const tileLevel )
0304 {
0305     d->m_visibleTileLevel = tileLevel;
0306     d->m_tileLevelRangeWidget->setDefaultLevel( tileLevel );
0307     d->m_downloadRegion.setVisibleTileLevel( tileLevel );
0308 }
0309 
0310 void DownloadRegionDialog::setSelectionMethod( SelectionMethod const selectionMethod )
0311 {
0312     d->m_selectionMethod = selectionMethod;
0313     switch ( selectionMethod ) {
0314     case VisibleRegionMethod:
0315         d->m_visibleRegionMethodButton->setChecked( true );
0316         d->m_routeOffsetLabel->setEnabled( false );
0317         d->m_routeOffsetSpinBox->setEnabled( false );
0318         d->m_latLonBoxWidget->setEnabled( false );
0319         setSpecifiedLatLonAltBox( d->m_visibleRegion );
0320         break;
0321     case SpecifiedRegionMethod:
0322         d->m_specifiedRegionMethodButton->setChecked( true );
0323         d->m_routeOffsetLabel->setEnabled( false );
0324         d->m_routeOffsetSpinBox->setEnabled( false );
0325         d->m_latLonBoxWidget->setEnabled( true );
0326         break;
0327     case RouteDownloadMethod:
0328         d->m_routeDownloadMethodButton->setChecked( true );
0329         d->m_routeOffsetLabel->setEnabled( true );
0330         d->m_routeOffsetSpinBox->setEnabled( true );
0331         d->m_latLonBoxWidget->setEnabled( false );
0332     }
0333 
0334     updateTileCount();
0335 }
0336 
0337 QVector<TileCoordsPyramid> DownloadRegionDialog::region() const
0338 {
0339     if ( !d->hasTextureLayers() && !d->hasVectorLayers() ) {
0340         return QVector<TileCoordsPyramid>();
0341     }
0342 
0343     d->m_visibleTileLevel = (tileType() == TextureTileType && d->m_textureLayer->tileZoomLevel() != -1)
0344             ? d->m_textureLayer->tileZoomLevel() : d->m_vectorTileLayer->tileZoomLevel();
0345 
0346     const TileLayer * tileLayer = (tileType() == TextureTileType && d->m_textureLayer->layerCount() > 0)
0347             ? dynamic_cast<const TileLayer *>(d->m_textureLayer)
0348             : dynamic_cast<const TileLayer *>(d->m_vectorTileLayer);
0349 
0350     d->m_downloadRegion.setTileLevelRange( d->m_tileLevelRangeWidget->topLevel(),
0351                                            d->m_tileLevelRangeWidget->bottomLevel() );
0352     d->m_downloadRegion.setVisibleTileLevel( d->m_visibleTileLevel );
0353 
0354     // check whether "visible region" or "lat/lon region" is selection method
0355     GeoDataLatLonAltBox downloadRegion;
0356     switch ( d->m_selectionMethod ) {
0357     case VisibleRegionMethod:
0358         downloadRegion = d->m_visibleRegion;
0359         break;
0360     case SpecifiedRegionMethod:
0361         downloadRegion = GeoDataLatLonAltBox( d->m_latLonBoxWidget->latLonBox(), 0, 0 );
0362         break;
0363     case RouteDownloadMethod:
0364         qreal offset = d->m_routeOffsetSpinBox->value();
0365         if (d->m_routeOffsetSpinBox->suffix() == QLatin1String(" km")) {
0366             offset *= KM2METER;
0367         }
0368         const GeoDataLineString waypoints = d->m_model->routingManager()->routingModel()->route().path();
0369         return d->m_downloadRegion.fromPath( tileLayer, offset, waypoints );
0370     }
0371 
0372     // For Mercator tiles limit the LatLonBox to the valid tile range.
0373     if (tileLayer->tileProjection()->type() == GeoSceneAbstractTileProjection::Mercator) {
0374         downloadRegion.setNorth(qMin(downloadRegion.north(), +1.4835));
0375         downloadRegion.setSouth(qMax(downloadRegion.south(), -1.4835));
0376     }
0377 
0378     return d->m_downloadRegion.region( tileLayer, downloadRegion );
0379 }
0380 
0381 TileType DownloadRegionDialog::tileType() const
0382 {
0383     return d->m_layerComboBox->currentIndex() == 0 ? TextureTileType : VectorTileType;
0384 }
0385 
0386 void DownloadRegionDialog::setSpecifiedLatLonAltBox( GeoDataLatLonAltBox const & region )
0387 {
0388     d->m_latLonBoxWidget->setLatLonBox( region );
0389 }
0390 
0391 void DownloadRegionDialog::setVisibleLatLonAltBox( GeoDataLatLonAltBox const & region )
0392 {
0393     d->m_visibleRegion = region;
0394 
0395     // update lat/lon widget only if not active to prevent that users unintentionally loose
0396     // entered values
0397     if ( d->m_selectionMethod == VisibleRegionMethod ) {
0398         setSpecifiedLatLonAltBox( region );
0399     }
0400     updateTileCount();
0401 }
0402 
0403 void DownloadRegionDialog::updateTileLayer()
0404 {
0405     updateTileType();
0406     updateTileCount();
0407 }
0408 
0409 void DownloadRegionDialog::delayUpdateTileLayer()
0410 {
0411     QTimer::singleShot(500, this, &DownloadRegionDialog::updateTileLayer);
0412 }
0413 
0414 void DownloadRegionDialog::hideEvent( QHideEvent * event )
0415 {
0416     disconnect( d->m_widget, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)),
0417                 this, SLOT(setVisibleLatLonAltBox(GeoDataLatLonAltBox)) );
0418     disconnect( d->m_widget, SIGNAL(themeChanged(QString)),
0419                 this, SLOT(delayUpdateTileLayer()) );
0420     disconnect( d->m_widget, SIGNAL(propertyValueChanged(QString,bool)),
0421                 this, SLOT(delayUpdateTileLayer()) );
0422 
0423     emit hidden();
0424     event->accept();
0425 }
0426 
0427 void DownloadRegionDialog::showEvent( QShowEvent * event )
0428 {
0429     connect( d->m_widget, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)),
0430              this, SLOT(setVisibleLatLonAltBox(GeoDataLatLonAltBox)) );
0431     connect( d->m_widget, SIGNAL(themeChanged(QString)),
0432              this, SLOT(delayUpdateTileLayer()) );
0433     connect( d->m_widget, SIGNAL(propertyValueChanged(QString,bool)),
0434              this, SLOT(delayUpdateTileLayer()) );
0435 
0436     setVisibleTileLevel(d->m_widget->tileZoomLevel());
0437 
0438     updateTileCount();
0439 
0440     emit shown();
0441     event->accept();
0442 }
0443 
0444 void DownloadRegionDialog::toggleSelectionMethod()
0445 {
0446     if( d->m_specifiedRegionMethodButton->isChecked() ) {
0447         setSelectionMethod( SpecifiedRegionMethod );
0448     }
0449     else if( d->m_routeDownloadMethodButton->isChecked() ) {
0450         setSelectionMethod( RouteDownloadMethod );
0451     }
0452     else if( d->m_specifiedRegionMethodButton->isChecked() ) {
0453         setSelectionMethod( SpecifiedRegionMethod );
0454     }
0455 }
0456 
0457 void DownloadRegionDialog::updateTileType()
0458 {
0459     bool hasVisibleTextureLayers = d->hasTextureLayers() && d->m_textureLayer->layerCount() > 0;
0460     bool hasVisibleVectorLayers = d->hasVectorLayers() && d->m_vectorTileLayer->layerCount() > 0;
0461 
0462     QStandardItemModel *model = qobject_cast<QStandardItemModel *>(d->m_layerComboBox->model());
0463     Q_ASSERT(model != nullptr);
0464     QStandardItem *item = nullptr;
0465     item = model->item(0);
0466     item->setFlags(hasVisibleTextureLayers ? item->flags() | Qt::ItemIsEnabled
0467                                            : item->flags() & ~Qt::ItemIsEnabled);
0468     item = model->item(1);
0469     item->setFlags(hasVisibleVectorLayers ? item->flags() | Qt::ItemIsEnabled
0470                                           : item->flags() & ~Qt::ItemIsEnabled);
0471 
0472     bool allTileTypesAvailable = hasVisibleTextureLayers && hasVisibleVectorLayers;
0473 
0474     d->m_layerComboBox->setEnabled(allTileTypesAvailable);
0475     if (hasVisibleVectorLayers) {
0476         d->m_layerComboBox->setCurrentIndex(1);
0477     }
0478     else if (hasVisibleTextureLayers && !hasVisibleVectorLayers) {
0479         d->m_layerComboBox->setCurrentIndex(0);
0480     }
0481 }
0482 
0483 void DownloadRegionDialog::updateTileCount()
0484 {
0485     if ( !isVisible() ) {
0486         return;
0487     }
0488 
0489     qint64 tilesCount = 0;
0490     QString themeId( d->m_model->mapThemeId() );
0491     QVector<TileCoordsPyramid> const pyramid = region();
0492     Q_ASSERT( !pyramid.isEmpty() );
0493     if( pyramid.size() == 1 ) {
0494         tilesCount = pyramid[0].tilesCount();
0495     }
0496     else {
0497         for( int level = pyramid[0].bottomLevel(); level>= pyramid[0].topLevel(); --level ) {
0498             QSet<TileId> tileIdSet;
0499             for( int i = 0; i < pyramid.size(); ++i ) {
0500                 QRect const coords = pyramid[i].coords( level );
0501                 int x1, y1, x2, y2;
0502                 coords.getCoords( &x1, &y1, &x2, &y2 );
0503                 for ( int x = x1; x <= x2; ++x ) {
0504                     for ( int y = y1; y <= y2; ++y ) {
0505                         TileId const tileId( 0, level, x, y );
0506                         tileIdSet.insert( tileId );
0507                     }
0508                 }
0509             }
0510             tilesCount += tileIdSet.count();
0511         }
0512     }
0513 
0514     qreal tileDownloadSize = 0;
0515 
0516     if ( tilesCount > maxTilesCount ) {
0517         d->m_tileSizeInfo->setToolTip( QString() );
0518         //~ singular There is a limit of %n tile to download.
0519         //~ plural There is a limit of %n tiles to download.
0520         d->m_tileSizeInfo->setText( tr( "There is a limit of %n tile(s) to download.", "",
0521                                                maxTilesCount ) );
0522     } else {
0523         if (themeId == QLatin1String("earth/openstreetmap/openstreetmap.dgml") ||
0524             themeId == QLatin1String("earth/openstreetmap/openseamap.dgml") ||
0525             themeId == QLatin1String("earth/vectorosm/vectorosm.dgml") ) {
0526 
0527             tileDownloadSize = tileType() == TextureTileType
0528                     ? tilesCount * averageTextureTileSize
0529                     : tilesCount * averageVectorTileSize;
0530 
0531             d->m_tileSizeInfo->setToolTip( tr( "Approximate size of the tiles to be downloaded" ) );
0532 
0533             if( tileDownloadSize > 1024 ) {
0534                 tileDownloadSize = tileDownloadSize / 1024;
0535                 d->m_tileSizeInfo->setText( tr( "Estimated download size: %1 MB" ).arg( ceil( tileDownloadSize ) ) );
0536             }
0537             else {
0538                 d->m_tileSizeInfo->setText( tr( "Estimated download size: %1 kB" ).arg( tileDownloadSize ) );
0539             }
0540         }
0541         else {
0542             d->m_tileSizeInfo->setToolTip( QString() );
0543             d->m_tileSizeInfo->clear();
0544         }
0545     }
0546 
0547     d->m_tilesCountLabel->setText( QString::number( tilesCount ) );
0548     bool const tilesCountWithinLimits = tilesCount > 0 && tilesCount <= maxTilesCount;
0549     d->m_okButton->setEnabled( tilesCountWithinLimits );
0550     d->m_applyButton->setEnabled( tilesCountWithinLimits );
0551 }
0552 
0553 void DownloadRegionDialog::updateRouteDialog()
0554 {
0555     d->m_routeDownloadMethodButton->setEnabled( d->hasRoute() );
0556     d->m_routeDownloadMethodButton->setChecked( d->hasRoute() );
0557     if( !d->hasRoute() ) {
0558         setSelectionMethod( VisibleRegionMethod );
0559     }
0560 }
0561 
0562 void DownloadRegionDialog::setOffsetUnit()
0563 {
0564     qreal offset = d->m_routeOffsetSpinBox->value();
0565 
0566     if( offset >= 1100 ) {
0567         d->m_routeOffsetSpinBox->setSuffix( " km" );
0568         d->m_routeOffsetSpinBox->setRange( minimumRouteOffset * METER2KM, maximumRouteOffset * METER2KM );
0569         d->m_routeOffsetSpinBox->setDecimals( 1 );
0570         d->m_routeOffsetSpinBox->setValue( offset * METER2KM );
0571         d->m_routeOffsetSpinBox->setSingleStep( 0.1 );
0572     }
0573     else if (offset <= 1 && d->m_routeOffsetSpinBox->suffix() == QLatin1String(" km")) {
0574         d->m_routeOffsetSpinBox->setSuffix( " m" );
0575         d->m_routeOffsetSpinBox->setRange( minimumRouteOffset, maximumRouteOffset );
0576         d->m_routeOffsetSpinBox->setDecimals( 0 );
0577         d->m_routeOffsetSpinBox->setValue( offset * KM2METER );
0578         d->m_routeOffsetSpinBox->setSingleStep( 100 );
0579     }
0580 }
0581 
0582 }
0583 
0584 #include "moc_DownloadRegionDialog.cpp"