6 #include "DownloadRegionDialog.h"
10 #include <QDialogButtonBox>
12 #include <QHBoxLayout>
15 #include <QPushButton>
16 #include <QRadioButton>
18 #include <QVBoxLayout>
20 #include <QScrollArea>
23 #include "GeoDataLatLonAltBox.h"
24 #include "MarbleDebug.h"
27 #include "LatLonBoxWidget.h"
28 #include "TileLayer.h"
29 #include "TextureLayer.h"
30 #include "VectorTileLayer.h"
32 #include "TileCoordsPyramid.h"
33 #include "TileLevelRangeWidget.h"
34 #include "TileLoaderHelper.h"
35 #include "routing/RoutingManager.h"
36 #include "routing/RoutingModel.h"
37 #include "GeoDataCoordinates.h"
38 #include "GeoDataLineString.h"
39 #include "DownloadRegion.h"
40 #include "GeoSceneDocument.h"
41 #include "GeoSceneMap.h"
47 int const maxTilesCount = 100000;
48 int const minimumRouteOffset = 0;
49 int const maximumRouteOffset = 10000;
50 int averageTileSize = 13;
52 class Q_DECL_HIDDEN DownloadRegionDialog::Private
55 Private( MarbleWidget *
const widget,
QDialog *
const dialog );
56 QWidget * createSelectionMethodBox();
58 QWidget * createOkCancelButtonBox();
60 bool hasRoute()
const;
61 bool hasTextureLayer()
const;
65 LatLonBoxWidget * m_latLonBoxWidget;
66 TileLevelRangeWidget * m_tileLevelRangeWidget;
68 QLabel* m_routeOffsetLabel;
70 QLabel * m_tilesCountLabel;
74 TextureLayer
const * m_textureLayer;
75 VectorTileLayer
const * m_vectorTileLayer;
76 int m_visibleTileLevel;
77 MarbleModel
const*
const m_model;
78 MarbleWidget *
const m_widget;
79 SelectionMethod m_selectionMethod;
80 GeoDataLatLonAltBox m_visibleRegion;
81 RoutingModel *m_routingModel;
82 DownloadRegion m_downloadRegion;
85 DownloadRegionDialog::Private::Private( MarbleWidget *
const widget,
88 m_visibleRegionMethodButton( nullptr ),
89 m_specifiedRegionMethodButton( nullptr ),
90 m_latLonBoxWidget( new LatLonBoxWidget ),
91 m_tileLevelRangeWidget( new TileLevelRangeWidget ),
92 m_routeDownloadMethodButton( nullptr ),
93 m_routeOffsetLabel( nullptr ),
94 m_routeOffsetSpinBox( nullptr ),
95 m_tilesCountLabel( nullptr ),
96 m_tileSizeInfo( nullptr ),
97 m_okButton( nullptr ),
98 m_applyButton( nullptr ),
99 m_textureLayer( widget->textureLayer() ),
100 m_vectorTileLayer( widget->vectorTileLayer() ),
101 m_visibleTileLevel( m_textureLayer->tileZoomLevel() ),
102 m_model( widget->model() ),
104 m_selectionMethod( VisibleRegionMethod ),
106 m_routingModel( widget->model()->routingManager()->routingModel() )
108 m_latLonBoxWidget->setEnabled(
false );
109 m_latLonBoxWidget->setLatLonBox( m_visibleRegion );
110 m_tileLevelRangeWidget->setDefaultLevel( m_visibleTileLevel );
111 m_downloadRegion.setMarbleModel( widget->model() );
114 QWidget * DownloadRegionDialog::Private::createSelectionMethodBox()
116 m_visibleRegionMethodButton =
new QRadioButton( tr(
"Visible region" ) );
117 m_specifiedRegionMethodButton =
new QRadioButton( tr(
"Specify region" ) );
119 m_routeDownloadMethodButton =
new QRadioButton( tr(
"Download Route" ) );
120 m_routeDownloadMethodButton->setToolTip( tr(
"Enabled when a route exists" ) );
121 m_routeDownloadMethodButton->setEnabled( hasRoute() );
122 m_routeDownloadMethodButton->setChecked( hasRoute() );
124 m_routeOffsetSpinBox->setEnabled( hasRoute() );
125 m_routeOffsetSpinBox->setRange( minimumRouteOffset, maximumRouteOffset );
126 int defaultOffset = 500;
127 m_routeOffsetSpinBox->setValue( defaultOffset );
128 m_routeOffsetSpinBox->setSingleStep( 100 );
129 m_routeOffsetSpinBox->setSuffix(
" m" );
130 m_routeOffsetSpinBox->setDecimals( 0 );
133 m_routeOffsetLabel =
new QLabel( tr(
"Offset from route:" ) );
136 connect( m_visibleRegionMethodButton, SIGNAL(toggled(
bool)),
137 m_dialog, SLOT(toggleSelectionMethod()) );
138 connect( m_specifiedRegionMethodButton, SIGNAL(toggled(
bool)),
139 m_dialog, SLOT(toggleSelectionMethod()));
140 connect( m_routeDownloadMethodButton, SIGNAL(toggled(
bool)),
141 m_dialog, SLOT(toggleSelectionMethod()) );
142 connect( m_routingModel, SIGNAL(modelReset()), m_dialog, SLOT(updateRouteDialog()) );
143 connect( m_routingModel, SIGNAL(rowsInserted(
QModelIndex,
int,
int)),
144 m_dialog, SLOT(updateRouteDialog()) );
145 connect( m_routingModel, SIGNAL(rowsRemoved(
QModelIndex,
int,
int)),
146 m_dialog, SLOT(updateRouteDialog()) );
149 routeOffsetLayout->
addWidget( m_routeOffsetLabel );
151 routeOffsetLayout->
addWidget( m_routeOffsetSpinBox );
154 routeLayout->
addWidget( m_routeDownloadMethodButton );
155 routeLayout->
addLayout( routeOffsetLayout );
158 layout->
addWidget( m_visibleRegionMethodButton );
160 layout->
addWidget( m_specifiedRegionMethodButton );
163 bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
164 m_specifiedRegionMethodButton->setVisible( !smallScreen );
165 m_latLonBoxWidget->setVisible( !smallScreen );
169 selectionMethodWidget->
setLayout( layout );
170 return selectionMethodWidget;
174 return selectionMethodBox;
178 QLayout * DownloadRegionDialog::Private::createTilesCounter()
180 QLabel *
const description =
new QLabel( tr(
"Number of tiles to download:" ) );
181 m_tilesCountLabel =
new QLabel;
182 m_tileSizeInfo =
new QLabel;
185 tilesCountLayout->
addWidget( description );
186 tilesCountLayout->
addWidget( m_tilesCountLabel );
194 QWidget * DownloadRegionDialog::Private::createOkCancelButtonBox()
199 if ( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) {
201 m_applyButton->setVisible(
false );
204 connect( buttonBox, SIGNAL(accepted()), m_dialog, SLOT(accept()) );
205 connect( buttonBox, SIGNAL(rejected()), m_dialog, SLOT(reject()) );
206 connect( m_applyButton, SIGNAL(clicked()), m_dialog, SIGNAL(applied()) );
210 bool DownloadRegionDialog::Private::hasRoute()
const
212 return !m_routingModel->route().path().isEmpty();
215 bool DownloadRegionDialog::Private::hasTextureLayer()
const
217 return m_model->mapTheme()->map()->hasTextureLayers();
220 DownloadRegionDialog::DownloadRegionDialog( MarbleWidget *
const widget,
QWidget *
const parent,
223 d( new Private( widget, this ))
225 setWindowTitle(
tr(
"Download Region" ));
227 layout->
addWidget( d->createSelectionMethodBox() );
228 layout->
addWidget( d->m_tileLevelRangeWidget );
229 layout->
addLayout( d->createTilesCounter() );
231 if ( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) {
239 mainLayout->
addWidget( d->createOkCancelButtonBox() );
240 setLayout( mainLayout );
242 layout->
addWidget( d->createOkCancelButtonBox() );
246 connect( d->m_latLonBoxWidget, SIGNAL(valueChanged()), SLOT(updateTilesCount()) );
247 connect( d->m_tileLevelRangeWidget, SIGNAL(topLevelChanged(
int)),
248 SLOT(updateTilesCount()) );
249 connect( d->m_tileLevelRangeWidget, SIGNAL(bottomLevelChanged(
int)),
250 SLOT(updateTilesCount()) );
251 connect( d->m_routeOffsetSpinBox, SIGNAL(valueChanged(
double)), SLOT(updateTilesCount()) );
252 connect( d->m_routeOffsetSpinBox, SIGNAL(valueChanged(
double)), SLOT(setOffsetUnit()) );
253 connect( d->m_model, SIGNAL(themeChanged(
QString)), SLOT(updateTilesCount()) );
256 DownloadRegionDialog::~DownloadRegionDialog()
261 void DownloadRegionDialog::setAllowedTileLevelRange(
int const minimumTileLevel,
262 int const maximumTileLevel )
264 d->m_tileLevelRangeWidget->setAllowedLevelRange( minimumTileLevel, maximumTileLevel );
267 void DownloadRegionDialog::setVisibleTileLevel(
int const tileLevel )
269 d->m_visibleTileLevel = tileLevel;
270 d->m_tileLevelRangeWidget->setDefaultLevel( tileLevel );
271 d->m_downloadRegion.setVisibleTileLevel( tileLevel );
274 void DownloadRegionDialog::setSelectionMethod( SelectionMethod
const selectionMethod )
279 d->m_visibleRegionMethodButton->blockSignals(
true );
280 d->m_specifiedRegionMethodButton->blockSignals(
true );
281 d->m_routeDownloadMethodButton->blockSignals(
true );
283 d->m_selectionMethod = selectionMethod;
284 switch ( selectionMethod ) {
285 case VisibleRegionMethod:
286 d->m_visibleRegionMethodButton->setChecked(
true );
287 d->m_routeOffsetLabel->setEnabled(
false );
288 d->m_routeOffsetSpinBox->setEnabled(
false );
289 d->m_latLonBoxWidget->setEnabled(
false );
290 setSpecifiedLatLonAltBox( d->m_visibleRegion );
292 case SpecifiedRegionMethod:
293 d->m_specifiedRegionMethodButton->setChecked(
true );
294 d->m_routeOffsetLabel->setEnabled(
false );
295 d->m_routeOffsetSpinBox->setEnabled(
false );
296 d->m_latLonBoxWidget->setEnabled(
true );
298 case RouteDownloadMethod:
299 d->m_routeDownloadMethodButton->setChecked(
true );
300 d->m_routeOffsetLabel->setEnabled(
true );
301 d->m_routeOffsetSpinBox->setEnabled(
true );
302 d->m_latLonBoxWidget->setEnabled(
false );
306 d->m_visibleRegionMethodButton->blockSignals(
false );
307 d->m_specifiedRegionMethodButton->blockSignals(
false );
308 d->m_routeDownloadMethodButton->blockSignals(
false );
313 if ( !d->hasTextureLayer() ) {
317 const TileLayer * tileLayer = d->m_textureLayer->textureLayerCount() > 0 ?
dynamic_cast<const TileLayer *
>(d->m_textureLayer) :
dynamic_cast<const TileLayer *
>(d->m_vectorTileLayer);
320 d->m_downloadRegion.setTileLevelRange( d->m_tileLevelRangeWidget->topLevel(),
321 d->m_tileLevelRangeWidget->bottomLevel() );
322 d->m_downloadRegion.setVisibleTileLevel( d->m_visibleTileLevel );
324 GeoDataLatLonAltBox downloadRegion;
325 switch ( d->m_selectionMethod ) {
326 case VisibleRegionMethod:
327 downloadRegion = d->m_visibleRegion;
329 case SpecifiedRegionMethod:
330 downloadRegion = GeoDataLatLonAltBox( d->m_latLonBoxWidget->latLonBox(), 0, 0 );
332 case RouteDownloadMethod:
333 qreal offset = d->m_routeOffsetSpinBox->value();
334 if (d->m_routeOffsetSpinBox->suffix() ==
QLatin1String(
" km")) {
337 const GeoDataLineString waypoints = d->m_model->routingManager()->routingModel()->route().path();
338 return d->m_downloadRegion.fromPath( tileLayer, offset, waypoints );
341 return d->m_downloadRegion.region( tileLayer, downloadRegion );
344 void DownloadRegionDialog::setSpecifiedLatLonAltBox( GeoDataLatLonAltBox
const & region )
346 d->m_latLonBoxWidget->setLatLonBox( region );
349 void DownloadRegionDialog::setVisibleLatLonAltBox( GeoDataLatLonAltBox
const & region )
351 d->m_visibleRegion = region;
355 if ( d->m_selectionMethod == VisibleRegionMethod ) {
356 setSpecifiedLatLonAltBox( region );
361 void DownloadRegionDialog::updateTextureLayer()
363 mDebug() <<
"DownloadRegionDialog::updateTextureLayer";
367 void DownloadRegionDialog::hideEvent(
QHideEvent * event )
369 disconnect( d->m_widget, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)),
370 this, SLOT(setVisibleLatLonAltBox(GeoDataLatLonAltBox)) );
371 disconnect( d->m_widget, SIGNAL(themeChanged(
QString)),
372 this, SLOT(updateTextureLayer()) );
378 void DownloadRegionDialog::showEvent(
QShowEvent * event )
380 connect( d->m_widget, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)),
381 this, SLOT(setVisibleLatLonAltBox(GeoDataLatLonAltBox)) );
382 connect( d->m_widget, SIGNAL(themeChanged(
QString)),
383 this, SLOT(updateTextureLayer()) );
389 void DownloadRegionDialog::toggleSelectionMethod()
392 switch ( d->m_selectionMethod ) {
393 case VisibleRegionMethod:
394 if( d->m_specifiedRegionMethodButton->isChecked() ) {
395 setSelectionMethod( SpecifiedRegionMethod );
397 else if( d->m_routeDownloadMethodButton->isChecked() ) {
398 setSelectionMethod( RouteDownloadMethod );
402 case SpecifiedRegionMethod:
403 if( d->m_visibleRegionMethodButton->isChecked() ) {
404 setSelectionMethod( VisibleRegionMethod );
406 else if ( d->m_routeDownloadMethodButton->isChecked() ) {
407 setSelectionMethod( RouteDownloadMethod );
410 case RouteDownloadMethod:
411 if( d->m_specifiedRegionMethodButton->isChecked() ) {
412 setSelectionMethod( SpecifiedRegionMethod );
414 else if ( d->m_visibleRegionMethodButton->isChecked() ) {
415 setSelectionMethod( VisibleRegionMethod );
422 void DownloadRegionDialog::updateTilesCount()
424 if ( !isVisible() || !d->hasTextureLayer() ) {
428 qint64 tilesCount = 0;
429 QString themeId( d->m_model->mapThemeId() );
431 Q_ASSERT( !pyramid.
isEmpty() );
432 if( pyramid.
size() == 1 ) {
433 tilesCount = pyramid[0].tilesCount();
436 for(
int level = pyramid[0].bottomLevel();
level>= pyramid[0].topLevel(); --
level ) {
438 for(
int i = 0; i < pyramid.
size(); ++i ) {
439 QRect const coords = pyramid[i].coords( level );
442 for (
int x = x1; x <= x2; ++x ) {
443 for (
int y = y1; y <= y2; ++y ) {
444 TileId
const tileId( 0, level, x, y );
445 tileIdSet.
insert( tileId );
449 tilesCount += tileIdSet.
count();
453 if ( tilesCount > maxTilesCount ) {
454 d->m_tileSizeInfo->setToolTip(
QString() );
457 d->m_tileSizeInfo->setText( tr(
"There is a limit of %n tile(s) to download.",
"",
459 }
else if (themeId ==
QLatin1String(
"earth/openstreetmap/openstreetmap.dgml")) {
460 qreal tileDownloadSize = tilesCount * averageTileSize;
462 d->m_tileSizeInfo->setToolTip( tr(
"Approximate size of the tiles to be downloaded" ) );
464 if( tileDownloadSize > 1024 ) {
465 tileDownloadSize = tileDownloadSize / 1024;
466 d->m_tileSizeInfo->setText( tr(
"Estimated download size: %1 MB" ).arg( ceil( tileDownloadSize ) ) );
469 d->m_tileSizeInfo->setText( tr(
"Estimated download size: %1 kB" ).arg( tileDownloadSize ) );
474 d->m_tileSizeInfo->setToolTip(
QString() );
475 d->m_tileSizeInfo->clear();
479 bool const tilesCountWithinLimits = tilesCount > 0 && tilesCount <= maxTilesCount;
480 d->m_okButton->setEnabled( tilesCountWithinLimits );
481 d->m_applyButton->setEnabled( tilesCountWithinLimits );
484 void DownloadRegionDialog::updateRouteDialog()
486 d->m_routeDownloadMethodButton->setEnabled( d->hasRoute() );
487 d->m_routeDownloadMethodButton->setChecked( d->hasRoute() );
488 if( !d->hasRoute() ) {
489 setSelectionMethod( VisibleRegionMethod );
493 void DownloadRegionDialog::setOffsetUnit()
495 qreal offset = d->m_routeOffsetSpinBox->value();
497 if( offset >= 1100 ) {
498 d->m_routeOffsetSpinBox->setSuffix(
" km" );
499 d->m_routeOffsetSpinBox->setRange( minimumRouteOffset * METER2KM, maximumRouteOffset * METER2KM );
500 d->m_routeOffsetSpinBox->setDecimals( 1 );
501 d->m_routeOffsetSpinBox->setValue( offset * METER2KM );
502 d->m_routeOffsetSpinBox->setSingleStep( 0.1 );
504 else if (offset <= 1 && d->m_routeOffsetSpinBox->suffix() ==
QLatin1String(
" km")) {
505 d->m_routeOffsetSpinBox->setSuffix(
" m" );
506 d->m_routeOffsetSpinBox->setRange( minimumRouteOffset, maximumRouteOffset );
507 d->m_routeOffsetSpinBox->setDecimals( 0 );
508 d->m_routeOffsetSpinBox->setValue( offset * KM2METER );
509 d->m_routeOffsetSpinBox->setSingleStep( 100 );
515 #include "moc_DownloadRegionDialog.cpp"