6#include "DownloadRegionDialog.h"
10#include <QDialogButtonBox>
17#include <QButtonGroup>
18#include <QRadioButton>
24#include <QStandardItemModel>
27#include "GeoDataLatLonAltBox.h"
28#include "MarbleDebug.h"
31#include "LatLonBoxWidget.h"
33#include "TextureLayer.h"
34#include "VectorTileLayer.h"
36#include "TileCoordsPyramid.h"
37#include "TileLevelRangeWidget.h"
38#include "TileLoaderHelper.h"
39#include "routing/RoutingManager.h"
40#include "routing/RoutingModel.h"
41#include "GeoDataCoordinates.h"
42#include "GeoDataLineString.h"
43#include "DownloadRegion.h"
44#include "GeoSceneDocument.h"
45#include "GeoSceneMap.h"
51int const maxTilesCount = 100000;
52int const minimumRouteOffset = 0;
53int const maximumRouteOffset = 10000;
54int averageTextureTileSize = 13;
55int averageVectorTileSize = 30;
57class Q_DECL_HIDDEN DownloadRegionDialog::Private
60 Private( MarbleWidget *
const widget,
QDialog *
const dialog );
61 QWidget * createSelectionMethodBox();
63 QWidget * createOkCancelButtonBox();
65 bool hasRoute()
const;
66 bool hasTextureLayers()
const;
67 bool hasVectorLayers()
const;
74 LatLonBoxWidget * m_latLonBoxWidget;
75 TileLevelRangeWidget * m_tileLevelRangeWidget;
77 QLabel* m_routeOffsetLabel;
79 QLabel * m_tilesCountLabel;
83 TextureLayer
const * m_textureLayer;
84 VectorTileLayer
const * m_vectorTileLayer;
85 int m_visibleTileLevel;
86 MarbleModel
const*
const m_model;
87 MarbleWidget *
const m_widget;
88 SelectionMethod m_selectionMethod;
89 GeoDataLatLonAltBox m_visibleRegion;
90 RoutingModel *m_routingModel;
91 DownloadRegion m_downloadRegion;
95DownloadRegionDialog::Private::Private( MarbleWidget *
const widget,
98 m_layerLabel( nullptr ),
99 m_layerComboBox( nullptr ),
100 m_buttonGroup(nullptr),
101 m_visibleRegionMethodButton( nullptr ),
102 m_specifiedRegionMethodButton( nullptr ),
103 m_latLonBoxWidget( new LatLonBoxWidget ),
104 m_tileLevelRangeWidget( new TileLevelRangeWidget ),
105 m_routeDownloadMethodButton( nullptr ),
106 m_routeOffsetLabel( nullptr ),
107 m_routeOffsetSpinBox( nullptr ),
108 m_tilesCountLabel( nullptr ),
109 m_tileSizeInfo( nullptr ),
110 m_okButton( nullptr ),
111 m_applyButton( nullptr ),
112 m_textureLayer( widget->textureLayer() ),
113 m_vectorTileLayer( widget->vectorTileLayer() ),
114 m_visibleTileLevel( 0 ),
115 m_model( widget->model() ),
117 m_selectionMethod( VisibleRegionMethod ),
119 m_routingModel( widget->model()->routingManager()->routingModel() )
121 m_latLonBoxWidget->setEnabled(
false );
122 m_latLonBoxWidget->setLatLonBox( m_visibleRegion );
123 m_tileLevelRangeWidget->setDefaultLevel( m_visibleTileLevel );
124 m_downloadRegion.setMarbleModel( widget->model() );
129QWidget * DownloadRegionDialog::Private::createSelectionMethodBox()
132 m_buttonGroup->setExclusive(
true);
133 m_visibleRegionMethodButton =
new QRadioButton( tr(
"Visible region" ) );
134 m_buttonGroup->addButton(m_visibleRegionMethodButton);
135 m_specifiedRegionMethodButton =
new QRadioButton( tr(
"Specify region" ) );
136 m_buttonGroup->addButton(m_specifiedRegionMethodButton);
137 m_routeDownloadMethodButton =
new QRadioButton( tr(
"Download Route" ) );
138 m_buttonGroup->addButton(m_routeDownloadMethodButton);
139 m_routeDownloadMethodButton->setToolTip( tr(
"Enabled when a route exists" ) );
140 m_routeDownloadMethodButton->setEnabled( hasRoute() );
141 m_routeDownloadMethodButton->setChecked( hasRoute() );
143 m_routeOffsetSpinBox->setEnabled( hasRoute() );
144 m_routeOffsetSpinBox->setRange( minimumRouteOffset, maximumRouteOffset );
145 int defaultOffset = 500;
146 m_routeOffsetSpinBox->setValue( defaultOffset );
147 m_routeOffsetSpinBox->setSingleStep( 100 );
148 m_routeOffsetSpinBox->setSuffix(
" m" );
149 m_routeOffsetSpinBox->setDecimals( 0 );
152 m_routeOffsetLabel =
new QLabel( tr(
"Offset from route:" ) );
156 m_dialog, SLOT(toggleSelectionMethod()) );
157 connect( m_routingModel, SIGNAL(modelReset()), m_dialog, SLOT(updateRouteDialog()) );
159 m_dialog, SLOT(updateRouteDialog()) );
161 m_dialog, SLOT(updateRouteDialog()) );
164 routeOffsetLayout->
addWidget( m_routeOffsetLabel );
166 routeOffsetLayout->
addWidget( m_routeOffsetSpinBox );
169 routeLayout->
addWidget( m_routeDownloadMethodButton );
170 routeLayout->
addLayout( routeOffsetLayout );
173 layout->
addWidget( m_visibleRegionMethodButton );
175 layout->
addWidget( m_specifiedRegionMethodButton );
178 bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
179 m_specifiedRegionMethodButton->setVisible( !smallScreen );
180 m_latLonBoxWidget->setVisible( !smallScreen );
184 selectionMethodWidget->
setLayout( layout );
185 return selectionMethodWidget;
189 return selectionMethodBox;
193QLayout * DownloadRegionDialog::Private::createTilesCounter()
195 QLabel *
const description =
new QLabel( tr(
"Number of tiles to download:" ) );
196 m_tilesCountLabel =
new QLabel;
197 m_tileSizeInfo =
new QLabel;
200 tilesCountLayout->
addWidget( description );
201 tilesCountLayout->
addWidget( m_tilesCountLabel );
209QWidget * DownloadRegionDialog::Private::createOkCancelButtonBox()
214 if ( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) {
216 m_applyButton->setVisible(
false );
219 connect( buttonBox, SIGNAL(accepted()), m_dialog, SLOT(accept()) );
220 connect( buttonBox, SIGNAL(rejected()), m_dialog, SLOT(reject()) );
221 connect( m_applyButton, SIGNAL(clicked()), m_dialog, SIGNAL(applied()) );
225bool DownloadRegionDialog::Private::hasRoute()
const
227 return !m_routingModel->route().path().isEmpty();
230bool DownloadRegionDialog::Private::hasTextureLayers()
const
232 return m_model->mapTheme()->map()->hasTextureLayers();
235bool DownloadRegionDialog::Private::hasVectorLayers()
const
237 return m_model->mapTheme()->map()->hasVectorLayers();
240DownloadRegionDialog::DownloadRegionDialog( MarbleWidget *
const widget,
QWidget *
const parent,
243 d( new Private( widget, this ))
245 setWindowTitle( tr(
"Download Region" ));
247 d->m_layerLabel =
new QLabel( tr(
"Tile type to be downloaded:" ));
249 d->m_layerComboBox->addItem(tr(
"Texture tiles"));
250 d->m_layerComboBox->addItem(tr(
"Vector tiles"));
251 d->m_layerComboBox->setToolTip(tr(
"Allows selection between layer types that are visibly being rendered."));
256 layout->
addWidget( d->createSelectionMethodBox() );
257 layout->
addWidget( d->m_tileLevelRangeWidget );
259 layout->
addLayout( d->createTilesCounter() );
261 if ( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) {
269 mainLayout->
addWidget( d->createOkCancelButtonBox() );
270 setLayout( mainLayout );
272 layout->
addWidget( d->createOkCancelButtonBox() );
277 this, &DownloadRegionDialog::updateTileCount );
278 connect( d->m_latLonBoxWidget, &Marble::LatLonBoxWidget::valueChanged,
279 this, &DownloadRegionDialog::updateTileCount );
280 connect( d->m_tileLevelRangeWidget, &TileLevelRangeWidget::topLevelChanged,
281 this, &DownloadRegionDialog::updateTileCount );
282 connect( d->m_tileLevelRangeWidget, &TileLevelRangeWidget::bottomLevelChanged,
283 this, &DownloadRegionDialog::updateTileCount );
285 this, &DownloadRegionDialog::updateTileCount );
287 this, &DownloadRegionDialog::setOffsetUnit );
288 connect( d->m_model, &MarbleModel::themeChanged,
289 this, &DownloadRegionDialog::delayUpdateTileLayer);
292DownloadRegionDialog::~DownloadRegionDialog()
297void DownloadRegionDialog::setAllowedTileLevelRange(
int const minimumTileLevel,
298 int const maximumTileLevel )
300 d->m_tileLevelRangeWidget->setAllowedLevelRange( minimumTileLevel, maximumTileLevel );
303void DownloadRegionDialog::setVisibleTileLevel(
int const tileLevel )
305 d->m_visibleTileLevel = tileLevel;
306 d->m_tileLevelRangeWidget->setDefaultLevel( tileLevel );
307 d->m_downloadRegion.setVisibleTileLevel( tileLevel );
310void DownloadRegionDialog::setSelectionMethod( SelectionMethod
const selectionMethod )
312 d->m_selectionMethod = selectionMethod;
313 switch ( selectionMethod ) {
314 case VisibleRegionMethod:
315 d->m_visibleRegionMethodButton->setChecked(
true );
316 d->m_routeOffsetLabel->setEnabled(
false );
317 d->m_routeOffsetSpinBox->setEnabled(
false );
318 d->m_latLonBoxWidget->setEnabled(
false );
319 setSpecifiedLatLonAltBox( d->m_visibleRegion );
321 case SpecifiedRegionMethod:
322 d->m_specifiedRegionMethodButton->setChecked(
true );
323 d->m_routeOffsetLabel->setEnabled(
false );
324 d->m_routeOffsetSpinBox->setEnabled(
false );
325 d->m_latLonBoxWidget->setEnabled(
true );
327 case RouteDownloadMethod:
328 d->m_routeDownloadMethodButton->setChecked(
true );
329 d->m_routeOffsetLabel->setEnabled(
true );
330 d->m_routeOffsetSpinBox->setEnabled(
true );
331 d->m_latLonBoxWidget->setEnabled(
false );
339 if ( !d->hasTextureLayers() && !d->hasVectorLayers() ) {
343 d->m_visibleTileLevel = (tileType() ==
TextureTileType && d->m_textureLayer->tileZoomLevel() != -1)
344 ? d->m_textureLayer->tileZoomLevel() : d->m_vectorTileLayer->tileZoomLevel();
346 const TileLayer * tileLayer = (tileType() ==
TextureTileType && d->m_textureLayer->layerCount() > 0)
347 ?
dynamic_cast<const TileLayer *
>(d->m_textureLayer)
348 :
dynamic_cast<const TileLayer *
>(d->m_vectorTileLayer);
350 d->m_downloadRegion.setTileLevelRange( d->m_tileLevelRangeWidget->topLevel(),
351 d->m_tileLevelRangeWidget->bottomLevel() );
352 d->m_downloadRegion.setVisibleTileLevel( d->m_visibleTileLevel );
355 GeoDataLatLonAltBox downloadRegion;
356 switch ( d->m_selectionMethod ) {
357 case VisibleRegionMethod:
358 downloadRegion = d->m_visibleRegion;
360 case SpecifiedRegionMethod:
361 downloadRegion = GeoDataLatLonAltBox( d->m_latLonBoxWidget->latLonBox(), 0, 0 );
363 case RouteDownloadMethod:
364 qreal offset = d->m_routeOffsetSpinBox->value();
365 if (d->m_routeOffsetSpinBox->suffix() ==
QLatin1String(
" km")) {
368 const GeoDataLineString waypoints = d->m_model->routingManager()->routingModel()->route().path();
369 return d->m_downloadRegion.fromPath( tileLayer, offset, waypoints );
373 if (tileLayer->tileProjection()->type() == GeoSceneAbstractTileProjection::Mercator) {
374 downloadRegion.setNorth(qMin(downloadRegion.north(), +1.4835));
375 downloadRegion.setSouth(qMax(downloadRegion.south(), -1.4835));
378 return d->m_downloadRegion.region( tileLayer, downloadRegion );
381TileType DownloadRegionDialog::tileType()
const
386void DownloadRegionDialog::setSpecifiedLatLonAltBox( GeoDataLatLonAltBox
const & region )
388 d->m_latLonBoxWidget->setLatLonBox( region );
391void DownloadRegionDialog::setVisibleLatLonAltBox( GeoDataLatLonAltBox
const & region )
393 d->m_visibleRegion = region;
397 if ( d->m_selectionMethod == VisibleRegionMethod ) {
398 setSpecifiedLatLonAltBox( region );
403void DownloadRegionDialog::updateTileLayer()
409void DownloadRegionDialog::delayUpdateTileLayer()
414void DownloadRegionDialog::hideEvent(
QHideEvent * event )
416 disconnect( d->m_widget, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)),
417 this, SLOT(setVisibleLatLonAltBox(GeoDataLatLonAltBox)) );
418 disconnect( d->m_widget, SIGNAL(themeChanged(
QString)),
419 this, SLOT(delayUpdateTileLayer()) );
420 disconnect( d->m_widget, SIGNAL(propertyValueChanged(
QString,
bool)),
421 this, SLOT(delayUpdateTileLayer()) );
427void DownloadRegionDialog::showEvent(
QShowEvent * event )
429 connect( d->m_widget, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)),
430 this, SLOT(setVisibleLatLonAltBox(GeoDataLatLonAltBox)) );
432 this, SLOT(delayUpdateTileLayer()) );
434 this, SLOT(delayUpdateTileLayer()) );
436 setVisibleTileLevel(d->m_widget->tileZoomLevel());
444void DownloadRegionDialog::toggleSelectionMethod()
446 if( d->m_specifiedRegionMethodButton->isChecked() ) {
447 setSelectionMethod( SpecifiedRegionMethod );
449 else if( d->m_routeDownloadMethodButton->isChecked() ) {
450 setSelectionMethod( RouteDownloadMethod );
452 else if( d->m_specifiedRegionMethodButton->isChecked() ) {
453 setSelectionMethod( SpecifiedRegionMethod );
457void DownloadRegionDialog::updateTileType()
459 bool hasVisibleTextureLayers = d->hasTextureLayers() && d->m_textureLayer->layerCount() > 0;
460 bool hasVisibleVectorLayers = d->hasVectorLayers() && d->m_vectorTileLayer->layerCount() > 0;
462 QStandardItemModel *model = qobject_cast<QStandardItemModel *>(d->m_layerComboBox->model());
463 Q_ASSERT(model !=
nullptr);
465 item = model->
item(0);
468 item = model->
item(1);
472 bool allTileTypesAvailable = hasVisibleTextureLayers && hasVisibleVectorLayers;
474 d->m_layerComboBox->setEnabled(allTileTypesAvailable);
475 if (hasVisibleVectorLayers) {
476 d->m_layerComboBox->setCurrentIndex(1);
478 else if (hasVisibleTextureLayers && !hasVisibleVectorLayers) {
479 d->m_layerComboBox->setCurrentIndex(0);
483void DownloadRegionDialog::updateTileCount()
485 if ( !isVisible() ) {
489 qint64 tilesCount = 0;
490 QString themeId( d->m_model->mapThemeId() );
492 Q_ASSERT( !pyramid.
isEmpty() );
493 if( pyramid.
size() == 1 ) {
494 tilesCount = pyramid[0].tilesCount();
497 for(
int level = pyramid[0].bottomLevel();
level>= pyramid[0].topLevel(); --
level ) {
499 for(
int i = 0; i < pyramid.
size(); ++i ) {
500 QRect const coords = pyramid[i].coords( level );
503 for (
int x = x1; x <= x2; ++x ) {
504 for (
int y = y1; y <= y2; ++y ) {
505 TileId
const tileId( 0, level, x, y );
506 tileIdSet.
insert( tileId );
510 tilesCount += tileIdSet.
count();
514 qreal tileDownloadSize = 0;
516 if ( tilesCount > maxTilesCount ) {
517 d->m_tileSizeInfo->setToolTip(
QString() );
520 d->m_tileSizeInfo->setText( tr(
"There is a limit of %n tile(s) to download.",
"",
523 if (themeId ==
QLatin1String(
"earth/openstreetmap/openstreetmap.dgml") ||
524 themeId ==
QLatin1String(
"earth/openstreetmap/openseamap.dgml") ||
525 themeId ==
QLatin1String(
"earth/vectorosm/vectorosm.dgml") ) {
528 ? tilesCount * averageTextureTileSize
529 : tilesCount * averageVectorTileSize;
531 d->m_tileSizeInfo->setToolTip( tr(
"Approximate size of the tiles to be downloaded" ) );
533 if( tileDownloadSize > 1024 ) {
534 tileDownloadSize = tileDownloadSize / 1024;
535 d->m_tileSizeInfo->setText( tr(
"Estimated download size: %1 MB" ).arg( ceil( tileDownloadSize ) ) );
538 d->m_tileSizeInfo->setText( tr(
"Estimated download size: %1 kB" ).arg( tileDownloadSize ) );
542 d->m_tileSizeInfo->setToolTip(
QString() );
543 d->m_tileSizeInfo->clear();
548 bool const tilesCountWithinLimits = tilesCount > 0 && tilesCount <= maxTilesCount;
549 d->m_okButton->setEnabled( tilesCountWithinLimits );
550 d->m_applyButton->setEnabled( tilesCountWithinLimits );
553void DownloadRegionDialog::updateRouteDialog()
555 d->m_routeDownloadMethodButton->setEnabled( d->hasRoute() );
556 d->m_routeDownloadMethodButton->setChecked( d->hasRoute() );
557 if( !d->hasRoute() ) {
558 setSelectionMethod( VisibleRegionMethod );
562void DownloadRegionDialog::setOffsetUnit()
564 qreal offset = d->m_routeOffsetSpinBox->value();
566 if( offset >= 1100 ) {
567 d->m_routeOffsetSpinBox->setSuffix(
" km" );
568 d->m_routeOffsetSpinBox->setRange( minimumRouteOffset * METER2KM, maximumRouteOffset * METER2KM );
569 d->m_routeOffsetSpinBox->setDecimals( 1 );
570 d->m_routeOffsetSpinBox->setValue( offset * METER2KM );
571 d->m_routeOffsetSpinBox->setSingleStep( 0.1 );
573 else if (offset <= 1 && d->m_routeOffsetSpinBox->suffix() ==
QLatin1String(
" km")) {
574 d->m_routeOffsetSpinBox->setSuffix(
" m" );
575 d->m_routeOffsetSpinBox->setRange( minimumRouteOffset, maximumRouteOffset );
576 d->m_routeOffsetSpinBox->setDecimals( 0 );
577 d->m_routeOffsetSpinBox->setValue( offset * KM2METER );
578 d->m_routeOffsetSpinBox->setSingleStep( 100 );
584#include "moc_DownloadRegionDialog.cpp"
This file contains the headers for MarbleModel.
QStringView level(QStringView ifopt)
Binds a QML item to a specific geodetic location in screen coordinates.
@ TextureTileType
Tiles that consist of bitmap data.
@ VectorTileType
Tiles that consist of vector data.
void addLayout(QLayout *layout, int stretch)
void addStretch(int stretch)
void insertSpacing(int index, int size)
void currentIndexChanged(int index)
void valueChanged(double d)
void setFrameShape(Shape)
bool isEmpty() const const
qsizetype size() const const
void getCoords(int *x1, int *y1, int *x2, int *y2) const const
qsizetype count() const const
iterator insert(const T &value)
Qt::ItemFlags flags() const const
void setFlags(Qt::ItemFlags flags)
QStandardItem * item(int row, int column) const const
QString number(double n, char format, int precision)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)