[Marble-devel] RFC: Download Region, first try
Jens-Michael Hoffmann
jensmh at gmx.de
Tue Jan 12 03:31:43 CET 2010
Hi,
please see below for a draft implementation for the download region feature.
It is not indended for committing but for discussing.
This patch applies to current svn, key points as follows:
working:
- download current region with range of tile levels
- download policy restrictions regarding concurrent connections
missing/not working:
- download specified (by lat/lon box) region
- restriction of total number of tiles (like <100k per download region request)
- perhaps display some kind of bar which indicates how many tiles are going
to be downloaded
some other issue:
- new code in MarbleModel is not very nice and also undocumented
- TileId becomes visible and has to be exported, should be avoided
(possibly by moving the corresponding method to MarbleModelPrivate)
- UI needs work
- perhaps only allow download of current region? makes UI simpler and
covers the (imho) most important use case.
Any feedback appreciated.
Best Regards,
Jens-Michael
diff --git a/marble/src/lib/CMakeLists.txt b/marble/src/lib/CMakeLists.txt
index a36d287..a60efd7 100644
--- a/marble/src/lib/CMakeLists.txt
+++ b/marble/src/lib/CMakeLists.txt
@@ -75,7 +75,10 @@ set(marblewidget_SRCS
MarbleDataFacade.cpp
MarbleDebug.cpp
+ DownloadRegionDialog.cpp
+ LatLonBoxWidget.cpp
QtMarbleConfigDialog.cpp
+ TileLevelRangeWidget.cpp
ClipPainter.cpp
DownloadPolicy.cpp
DownloadQueueSet.cpp
@@ -198,6 +201,8 @@ set (marblewidget_UI
MarbleAboutDialog.ui
SunControlWidget.ui
LatLonEdit.ui
+ LatLonBoxWidget.ui
+ TileLevelRangeWidget.ui
)
# FIXME: cleaner approach of src/lib/MarbleControlBox.* vs. marble.qrc
diff --git a/marble/src/lib/DownloadRegionDialog.cpp b/marble/src/lib/DownloadRegionDialog.cpp
new file mode 100644
index 0000000..55a8f22
--- /dev/null
+++ b/marble/src/lib/DownloadRegionDialog.cpp
@@ -0,0 +1,91 @@
+// Copyright 2009, 2010 Jens-Michael Hoffmann <jmho at c-xx.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+#include "DownloadRegionDialog.h"
+
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QPushButton>
+
+#include "TileLevelRangeWidget.h"
+
+namespace Marble
+{
+
+class DownloadRegionDialog::Private
+{
+public:
+ explicit Private( QWidget * parent = 0 );
+
+ TileLevelRangeWidget *m_tileLevelRangeWidget;
+ int m_originatingTileLevel;
+ int m_minimumAllowedTileLevel;
+ int m_maximumAllowedTileLevel;
+};
+
+DownloadRegionDialog::Private::Private( QWidget * parent )
+ : m_tileLevelRangeWidget( new TileLevelRangeWidget( parent )),
+ m_originatingTileLevel( -1 ),
+ m_minimumAllowedTileLevel( -1 ),
+ m_maximumAllowedTileLevel( -1 )
+{
+}
+
+DownloadRegionDialog::DownloadRegionDialog( QWidget * parent, Qt::WindowFlags f )
+ : QDialog( parent, f ),
+ d( new Private )
+{
+ QHBoxLayout *buttonBox = new QHBoxLayout;
+ QPushButton *okButton = new QPushButton( "Ok" );
+ connect( okButton, SIGNAL( clicked () ), this, SLOT( accept() ));
+ QPushButton *cancelButton = new QPushButton( "Cancel" );
+ connect( cancelButton, SIGNAL( clicked () ), this, SLOT( reject() ));
+ buttonBox->addWidget( okButton );
+ buttonBox->addWidget( cancelButton );
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget( d->m_tileLevelRangeWidget );
+ layout->addLayout( buttonBox );
+
+ setLayout( layout );
+}
+
+void DownloadRegionDialog::setOriginatingTileLevel( const int tileLevel )
+{
+ d->m_originatingTileLevel = tileLevel;
+ d->m_tileLevelRangeWidget->setDefaultTileLevel( tileLevel );
+}
+
+void DownloadRegionDialog::setAllowedTileLevelRange( const int minimumTileLevel,
+ const int maximumTileLevel )
+{
+ d->m_minimumAllowedTileLevel = minimumTileLevel;
+ d->m_maximumAllowedTileLevel = maximumTileLevel;
+ d->m_tileLevelRangeWidget->setAllowedTileLevelRange( minimumTileLevel, maximumTileLevel );
+}
+
+int DownloadRegionDialog::fromTileLevel() const
+{
+ return d->m_tileLevelRangeWidget->fromTileLevel();
+}
+
+int DownloadRegionDialog::toTileLevel() const
+{
+ return d->m_tileLevelRangeWidget->toTileLevel();
+}
+
+}
+
+#include "DownloadRegionDialog.moc"
diff --git a/marble/src/lib/DownloadRegionDialog.h b/marble/src/lib/DownloadRegionDialog.h
new file mode 100644
index 0000000..db50876
--- /dev/null
+++ b/marble/src/lib/DownloadRegionDialog.h
@@ -0,0 +1,49 @@
+// Copyright 2009, 2010 Jens-Michael Hoffmann <jmho at c-xx.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MARBLE_DOWNLOAD_REGION_DIALOG_H
+#define MARBLE_DOWNLOAD_REGION_DIALOG_H
+
+#include <QtGui/QDialog>
+
+#include "marble_export.h"
+
+namespace Marble
+{
+
+class TileLevelRangeWidget;
+
+class MARBLE_EXPORT DownloadRegionDialog: public QDialog
+{
+ Q_OBJECT
+
+ public:
+ explicit DownloadRegionDialog( QWidget * parent = 0, Qt::WindowFlags f = 0 );
+
+ void setOriginatingTileLevel( const int tileLevel );
+ void setAllowedTileLevelRange( const int minimumTileLevel,
+ const int maximumTileLevel );
+
+ int fromTileLevel() const;
+ int toTileLevel() const;
+
+ private:
+ class Private;
+ Private * const d;
+};
+
+}
+
+#endif
diff --git a/marble/src/lib/LatLonBoxWidget.cpp b/marble/src/lib/LatLonBoxWidget.cpp
new file mode 100644
index 0000000..4a35fdf
--- /dev/null
+++ b/marble/src/lib/LatLonBoxWidget.cpp
@@ -0,0 +1,29 @@
+// Copyright 2009, 2010 Jens-Michael Hoffmann <jmho at c-xx.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+#include "LatLonBoxWidget.h"
+
+namespace Marble
+{
+
+LatLonBoxWidget::LatLonBoxWidget( QWidget * parent, Qt::WindowFlags f )
+ : QWidget( parent, f )
+{
+ m_ui.setupUi( this );
+}
+
+}
+
+#include "LatLonBoxWidget.moc"
diff --git a/marble/src/lib/LatLonBoxWidget.h b/marble/src/lib/LatLonBoxWidget.h
new file mode 100644
index 0000000..e8f1f65
--- /dev/null
+++ b/marble/src/lib/LatLonBoxWidget.h
@@ -0,0 +1,40 @@
+// Copyright 2009, 2010 Jens-Michael Hoffmann <jmho at c-xx.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MARBLE_LAT_LON_BOX_WIDGET_H
+#define MARBLE_LAT_LON_BOX_WIDGET_H
+
+#include <QtGui/QWidget>
+
+#include "ui_LatLonBoxWidget.h"
+#include "marble_export.h"
+
+namespace Marble
+{
+
+class MARBLE_EXPORT LatLonBoxWidget: public QWidget
+{
+ Q_OBJECT
+
+ public:
+ explicit LatLonBoxWidget( QWidget * parent = 0, Qt::WindowFlags f = 0 );
+
+ private:
+ Ui::LatLonBoxWidget m_ui;
+};
+
+}
+
+#endif
diff --git a/marble/src/lib/LatLonBoxWidget.ui b/marble/src/lib/LatLonBoxWidget.ui
new file mode 100644
index 0000000..1f889c7
--- /dev/null
+++ b/marble/src/lib/LatLonBoxWidget.ui
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Marble::LatLonBoxWidget</class>
+ <widget class="QWidget" name="latLonBoxWidget">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>312</width>
+ <height>100</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Select a geographic region</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>13</width>
+ <height>13</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QDoubleSpinBox" name="northSpinBox">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip">
+ <string>Northern Latitude</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="minimum">
+ <double>-90.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>90.000000000000000</double>
+ </property>
+ <property name="value">
+ <double>90.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="northLabel">
+ <property name="text">
+ <string>&N</string>
+ </property>
+ <property name="buddy">
+ <cstring>northSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="2">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>13</width>
+ <height>13</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QDoubleSpinBox" name="westSpinBox">
+ <property name="toolTip">
+ <string>Western Longitude</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="minimum">
+ <double>-180.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>180.000000000000000</double>
+ </property>
+ <property name="value">
+ <double>-180.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="westLabel">
+ <property name="text">
+ <string>&W</string>
+ </property>
+ <property name="buddy">
+ <cstring>westSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="1">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>13</width>
+ <height>13</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="2">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QDoubleSpinBox" name="eastSpinBox">
+ <property name="toolTip">
+ <string>Eastern Longitude</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="minimum">
+ <double>-180.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>180.000000000000000</double>
+ </property>
+ <property name="value">
+ <double>180.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="eastLabel">
+ <property name="text">
+ <string>&E</string>
+ </property>
+ <property name="buddy">
+ <cstring>eastSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0">
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>13</width>
+ <height>13</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QDoubleSpinBox" name="southSpinBox">
+ <property name="toolTip">
+ <string>Southern Latitude</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="decimals">
+ <number>3</number>
+ </property>
+ <property name="minimum">
+ <double>-90.000000000000000</double>
+ </property>
+ <property name="maximum">
+ <double>90.000000000000000</double>
+ </property>
+ <property name="value">
+ <double>-90.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="southLabel">
+ <property name="text">
+ <string>&S</string>
+ </property>
+ <property name="buddy">
+ <cstring>southSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="2">
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>13</width>
+ <height>13</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>northSpinBox</tabstop>
+ <tabstop>westSpinBox</tabstop>
+ <tabstop>eastSpinBox</tabstop>
+ <tabstop>southSpinBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/marble/src/lib/MarbleModel.cpp b/marble/src/lib/MarbleModel.cpp
index 065865a..342f145 100644
--- a/marble/src/lib/MarbleModel.cpp
+++ b/marble/src/lib/MarbleModel.cpp
@@ -16,6 +16,7 @@
#include <cmath>
#include <QtCore/QAtomicInt>
+#include <QtCore/QMap>
#include <QtCore/QPointer>
#include <QtCore/QTime>
#include <QtCore/QTimer>
@@ -917,6 +918,128 @@ void MarbleModel::reloadMap() const
}
}
+QRect MarbleModel::tileRect( const QList<TileId> & tileIds ) const
+{
+ if ( tileIds.isEmpty() )
+ return QRect();
+
+ int minimumTileX = tileIds.first().x();
+ int minimumTileY = tileIds.first().y();
+ int maximumTileX = tileIds.first().x();
+ int maximumTileY = tileIds.first().y();
+ const int currentTileLevel = tileZoomLevel();
+
+ QList<TileId>::const_iterator pos = tileIds.constBegin();
+ QList<TileId>::const_iterator const end = tileIds.constEnd();
+ for (; pos != end; ++pos ) {
+ TileId const & id = *pos;
+ Q_ASSERT( id.zoomLevel() == currentTileLevel );
+
+ if ( id.x() < minimumTileX )
+ minimumTileX = id.x();
+ else if ( id.x() > maximumTileX )
+ maximumTileX = id.x();
+
+ if ( id.y() < minimumTileY )
+ minimumTileY = id.y();
+ else if ( id.y() > maximumTileY )
+ maximumTileY = id.y();
+ }
+ return QRect( minimumTileX, minimumTileY, maximumTileX - minimumTileX + 1,
+ maximumTileY - minimumTileY + 1 );
+}
+
+void MarbleModel::downloadCurrentRegion( const int fromTileLevel, const int toTileLevel ) const
+{
+ Q_ASSERT( fromTileLevel <= toTileLevel );
+ mDebug() << "MarbleModel::downloadCurrentRegion"
+ << "from" << fromTileLevel << "to" << toTileLevel;
+
+ // 1) first current tile level,
+ // 2) then lower tile levels (as it is likely only very few tiles),
+ // 3) finally higher tile levels as this will take most time
+ if ( !d->m_mapTheme->map()->hasTextureLayers() )
+ return;
+
+ const QString themeId = d->m_mapTheme->head()->theme();
+ GeoSceneLayer * const layer = static_cast<GeoSceneLayer*>( d->m_mapTheme->map()->
+ layer( themeId ));
+ Q_ASSERT( layer );
+ GeoSceneTexture * const texture = static_cast<GeoSceneTexture*>( layer->groundDataset() );
+ Q_ASSERT( texture );
+
+
+ const int currentTileLevel = tileZoomLevel();
+
+ Q_ASSERT( d->m_tileLoader );
+ QList<TileId> displayed = d->m_tileLoader->tilesOnDisplay();
+ //mDebug() << "tilesOnDisplay" << displayed;
+
+ QRect currentTileRect = tileRect( displayed );
+ mDebug() << "currentTileRect" << currentTileRect;
+
+ // we have now the tile coordinates reactangle for the current (in view)
+ // tile level, now we need to transform it for levels
+ // fromTileLevel..toTileLevel
+ QRect fromTileRect;
+ if ( fromTileLevel != currentTileLevel ) {
+ int x1, y1, x2, y2;
+ currentTileRect.getCoords( &x1, &y1, &x2, &y2 );
+ if ( fromTileLevel < currentTileLevel ) {
+ const int levelDiff = currentTileLevel - fromTileLevel;
+ fromTileRect.setCoords( x1 >> levelDiff, y1 >> levelDiff,
+ x2 >> levelDiff, y2 >> levelDiff );
+ }
+ else {
+ const int levelDiff = fromTileLevel - currentTileLevel;
+ fromTileRect.setCoords( x1 << levelDiff, y1 << levelDiff,
+ (( x2 + 1 ) << levelDiff ) - 1,
+ (( y2 + 1 ) << levelDiff ) - 1 );
+ }
+ }
+ else {
+ fromTileRect = currentTileRect;
+ }
+
+ // put all the tile rects (one per level) into a map
+ QMap<int, QRect> tileRectsToBeDownloaded;
+ int x1, x2, y1, y2;
+ fromTileRect.getCoords( &x1, &y1, &x2, &y2 );
+
+ for ( int level = fromTileLevel; level <= toTileLevel; ++level ) {
+ QRect rect;
+ rect.setCoords( x1, y1, x2, y2 );
+ tileRectsToBeDownloaded[ level ] = rect;
+ qDebug() << "rect level/x1/y1/x2/y2=" << level << x1 << y1 << x2 << y2
+ << " => #tiles=" << (x2-x1+1)*(y2-y1+1);
+ x1 <<= 1;
+ y1 <<= 1;
+ x2 = ( x2 << 1 ) + 1;
+ y2 = ( y2 << 1 ) + 1;
+ }
+
+ // create download jobs for all the levels
+ QMap<int, QRect>::const_iterator pos = tileRectsToBeDownloaded.constBegin();
+ QMap<int, QRect>::const_iterator const end = tileRectsToBeDownloaded.constEnd();
+ for (; pos != end; ++pos ) {
+ const int level = pos.key();
+ const QRect rect = pos.value();
+ int x1, x2, y1, y2;
+ rect.getCoords( &x1, &y1, &x2, &y2 );
+
+ for ( int x = x1; x <= x2; ++x ) {
+ for ( int y = y1; y <= y2; ++y ) {
+ const TileId id( level, x, y );
+ QUrl sourceUrl = TileLoaderHelper::downloadUrl( texture, level, x, y );
+ QString destFileName = TileLoaderHelper::relativeTileFileName( texture,
+ level, x, y );
+ emit downloadTile( sourceUrl, destFileName, TileId( level, x, y ).toString(),
+ DownloadBulk );
+ }
+ }
+ }
+}
+
void MarbleModel::addDownloadPolicies( GeoSceneDocument *mapTheme )
{
if ( !mapTheme )
diff --git a/marble/src/lib/MarbleModel.h b/marble/src/lib/MarbleModel.h
index b1e9629..661fa1e 100644
--- a/marble/src/lib/MarbleModel.h
+++ b/marble/src/lib/MarbleModel.h
@@ -35,6 +35,7 @@
#include <QtCore/QVector>
#include <QtGui/QRegion>
+#include "TileId.h"
#include "global.h"
class QItemSelectionModel;
@@ -302,6 +303,10 @@ class MARBLE_EXPORT MarbleModel : public QObject
void reloadMap() const;
+ QRect tileRect( const QList<TileId> & tileIds ) const;
+ void downloadCurrentRegion( const int fromTileLevel, const int toTileLevel ) const;
+ void reloadTiles( GeoSceneTexture * const texture, const QVector<TileId>& tileIds ) const;
+
public Q_SLOTS:
void clearVolatileTileCache();
/**
diff --git a/marble/src/lib/TileLevelRangeWidget.cpp b/marble/src/lib/TileLevelRangeWidget.cpp
new file mode 100644
index 0000000..5735795
--- /dev/null
+++ b/marble/src/lib/TileLevelRangeWidget.cpp
@@ -0,0 +1,72 @@
+// Copyright 2009, 2010 Jens-Michael Hoffmann <jmho at c-xx.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+#include "TileLevelRangeWidget.h"
+
+#include "ui_TileLevelRangeWidget.h"
+
+namespace Marble
+{
+
+class TileLevelRangeWidget::Private
+{
+public:
+ explicit Private( QWidget * parent = 0 );
+
+ Ui::TileLevelRangeWidget m_ui;
+};
+
+TileLevelRangeWidget::Private::Private( QWidget * parent )
+{
+ m_ui.setupUi( parent );
+}
+
+TileLevelRangeWidget::TileLevelRangeWidget( QWidget * parent, Qt::WindowFlags f )
+ : QWidget( parent, f ),
+ d( new Private( this ))
+{
+}
+
+TileLevelRangeWidget::~TileLevelRangeWidget()
+{
+ delete d;
+}
+
+void TileLevelRangeWidget::setAllowedTileLevelRange( const int minimumTileLevel,
+ const int maximumTileLevel )
+{
+ d->m_ui.minSpinBox->setRange( minimumTileLevel, maximumTileLevel );
+ d->m_ui.maxSpinBox->setRange( minimumTileLevel, maximumTileLevel );
+}
+
+void TileLevelRangeWidget::setDefaultTileLevel( const int tileLevel )
+{
+ d->m_ui.minSpinBox->setValue( tileLevel );
+ d->m_ui.maxSpinBox->setValue( tileLevel );
+}
+
+int TileLevelRangeWidget::fromTileLevel() const
+{
+ return d->m_ui.minSpinBox->value();
+}
+
+int TileLevelRangeWidget::toTileLevel() const
+{
+ return d->m_ui.maxSpinBox->value();
+}
+
+}
+
+#include "TileLevelRangeWidget.moc"
diff --git a/marble/src/lib/TileLevelRangeWidget.h b/marble/src/lib/TileLevelRangeWidget.h
new file mode 100644
index 0000000..604075c
--- /dev/null
+++ b/marble/src/lib/TileLevelRangeWidget.h
@@ -0,0 +1,48 @@
+// Copyright 2009, 2010 Jens-Michael Hoffmann <jmho at c-xx.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef MARBLE_TILE_LEVEL_RANGE_WIDGET_H
+#define MARBLE_TILE_LEVEL_RANGE_WIDGET_H
+
+#include <QtGui/QWidget>
+
+#include "marble_export.h"
+
+namespace Marble
+{
+
+class MARBLE_EXPORT TileLevelRangeWidget: public QWidget
+{
+ Q_OBJECT
+
+ public:
+ explicit TileLevelRangeWidget( QWidget * parent = 0, Qt::WindowFlags f = 0 );
+ ~TileLevelRangeWidget();
+
+ void setAllowedTileLevelRange( const int minimumTileLevel,
+ const int maximumTileLevel );
+ void setDefaultTileLevel( const int );
+
+ int fromTileLevel() const;
+ int toTileLevel() const;
+
+ private:
+ class Private;
+ Private * const d;
+};
+
+}
+
+#endif
diff --git a/marble/src/lib/TileLevelRangeWidget.ui b/marble/src/lib/TileLevelRangeWidget.ui
new file mode 100644
index 0000000..ca0a72c
--- /dev/null
+++ b/marble/src/lib/TileLevelRangeWidget.ui
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Marble::TileLevelRangeWidget</class>
+ <widget class="QWidget" name="tileLevelRangeWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>458</width>
+ <height>335</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Select Download Region</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QLabel" name="descriptionLabel">
+ <property name="text">
+ <string>Here you can download regional map data for future offline usage.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="margin">
+ <number>7</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Selected Region</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QRadioButton" name="currentRadioButton">
+ <property name="text">
+ <string>&Current Map View</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="specifiedRadioButton">
+ <property name="text">
+ <string>&Specified Area</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="Marble::LatLonBoxWidget" name="latLonBoxWidget" native="true">
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>50</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_7">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Zoom</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QLabel" name="tileLevelLabel">
+ <property name="text">
+ <string>&Tile Level Range:</string>
+ </property>
+ <property name="buddy">
+ <cstring>minSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="minSpinBox">
+ <property name="toolTip">
+ <string>Minimum Tile Level</string>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>20</number>
+ </property>
+ <property name="value">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="toLabel">
+ <property name="text">
+ <string>to</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="maxSpinBox">
+ <property name="toolTip">
+ <string>Maximum Tile Level</string>
+ </property>
+ <property name="minimum">
+ <number>0</number>
+ </property>
+ <property name="maximum">
+ <number>20</number>
+ </property>
+ <property name="value">
+ <number>4</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_8">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>68</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Marble::LatLonBoxWidget</class>
+ <extends>QWidget</extends>
+ <header>LatLonBoxWidget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>specifiedRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>marbleLatLonWidget</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>101</x>
+ <y>106</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>117</x>
+ <y>154</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/marble/src/marble_part.cpp b/marble/src/marble_part.cpp
index c93f621..ed32ad4 100644
--- a/marble/src/marble_part.cpp
+++ b/marble/src/marble_part.cpp
@@ -53,6 +53,7 @@
#include <kdeprintdialog.h>
// Marble library
+#include "DownloadRegionDialog.h"
#include "GeoDataCoordinates.h"
#include "lib/SunControlWidget.h"
@@ -592,6 +593,13 @@ void MarblePart::writeStatusBarSettings()
void MarblePart::setupActions()
{
+ // Action: Download Region
+ m_downloadRegionAction = new KAction( this );
+ m_downloadRegionAction->setText( i18nc( "Action for downloading an entire region of a map",
+ "Download Region..." ));
+ actionCollection()->addAction( "file_download_region", m_downloadRegionAction );
+ connect( m_downloadRegionAction, SIGNAL( triggered() ), SLOT( showDownloadRegionDialog() ));
+
// Action: Print Map
m_printMapAction = KStandardAction::print( this, SLOT( printMapScreenShot() ),
actionCollection() );
@@ -1168,6 +1176,26 @@ void MarblePart::reload()
m_controlView->marbleWidget()->map()->reload();
}
+void MarblePart::showDownloadRegionDialog()
+{
+ QPointer<DownloadRegionDialog> dialog = new DownloadRegionDialog;
+ dialog->setOriginatingTileLevel( m_controlView->marbleWidget()->map()
+ ->model()->tileZoomLevel() );
+ // FIXME: get range
+ dialog->setAllowedTileLevelRange( 0, 18 );
+ if ( dialog->exec() == QDialog::Accepted ) {
+ bool downloadCurrentRegion = true; // FIXME
+ bool downloadSpecifiedRegion = false; // FIXME
+ if ( downloadCurrentRegion ) {
+ m_controlView->marbleWidget()->map()->model()
+ ->downloadCurrentRegion( dialog->fromTileLevel(), dialog->toTileLevel() );
+ }
+ else if ( downloadSpecifiedRegion ) {
+ }
+ }
+ delete dialog;
+}
+
void MarblePart::showPluginAboutDialog( QString nameId )
{
QList<RenderPlugin *> renderItemList = m_controlView->marbleWidget()->renderPlugins();
diff --git a/marble/src/marble_part.h b/marble/src/marble_part.h
index 2b7f44c..7ff318c 100644
--- a/marble/src/marble_part.h
+++ b/marble/src/marble_part.h
@@ -125,6 +125,7 @@ class MarblePart: public KParts::ReadOnlyPart
void slotUpdateSettings();
void reload();
+ void showDownloadRegionDialog();
/**
* Shows the about dialog for the plugin with the corresponding @p nameId.
@@ -180,6 +181,7 @@ class MarblePart: public KParts::ReadOnlyPart
KAction *m_fullScreenAct;
KAction *m_openAct;
KAction *m_newStuffAction;
+ KAction *m_downloadRegionAction;
KAction *m_controlSunAction;
KAction *m_lockFloatItemsAct;
diff --git a/marble/src/marble_part.rc b/marble/src/marble_part.rc
index 584d371..e10b67c 100644
--- a/marble/src/marble_part.rc
+++ b/marble/src/marble_part.rc
@@ -6,6 +6,7 @@
<text>&File</text>
<Action name="file_open"/>
<Action name="new_stuff"/>
+ <Action name="file_download_region"/>
<Action name="exportMap"/>
<Separator/>
<Action name="file_print"/>
More information about the Marble-devel
mailing list