• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.14
  • kdeedu
  • marble
  • src
  • lib
  • marble
TileLoader.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Marble Virtual Globe.
3  *
4  * Copyright 2010 Jens-Michael Hoffmann <jmho@c-xx.com>
5  * Copyright 2010-2012 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "TileLoader.h"
22 
23 #include <QDateTime>
24 #include <QFileInfo>
25 #include <QMetaType>
26 #include <QImage>
27 
28 #include "GeoSceneTextureTile.h"
29 #include "GeoSceneTiled.h"
30 #include "GeoSceneVectorTile.h"
31 #include "GeoDataContainer.h"
32 #include "HttpDownloadManager.h"
33 #include "MarbleDebug.h"
34 #include "MarbleDirs.h"
35 #include "ParsingRunnerManager.h"
36 #include "TileLoaderHelper.h"
37 
38 Q_DECLARE_METATYPE( Marble::DownloadUsage )
39 
40 namespace Marble
41 {
42 
43 TileLoader::TileLoader(HttpDownloadManager * const downloadManager, const PluginManager *pluginManager) :
44  m_pluginManager( pluginManager )
45 {
46  qRegisterMetaType<DownloadUsage>( "DownloadUsage" );
47  connect( this, SIGNAL(downloadTile(QUrl,QString,QString,DownloadUsage)),
48  downloadManager, SLOT(addJob(QUrl,QString,QString,DownloadUsage)));
49  connect( downloadManager, SIGNAL(downloadComplete(QByteArray,QString)),
50  SLOT(updateTile(QByteArray,QString)));
51 }
52 
53 // If the tile image file is locally available:
54 // - if not expired: create ImageTile, set state to "uptodate", return it => done
55 // - if expired: create TextureTile, state is set to Expired by default, trigger dl,
56 QImage TileLoader::loadTileImage( GeoSceneTextureTile const *textureLayer, TileId const & tileId, DownloadUsage const usage )
57 {
58  QString const fileName = tileFileName( textureLayer, tileId );
59 
60  TileStatus status = tileStatus( textureLayer, tileId );
61  if ( status != Missing ) {
62  // check if an update should be triggered
63 
64  if ( status == Available ) {
65  mDebug() << Q_FUNC_INFO << tileId << "StateUptodate";
66  } else {
67  Q_ASSERT( status == Expired );
68  mDebug() << Q_FUNC_INFO << tileId << "StateExpired";
69  triggerDownload( textureLayer, tileId, usage );
70  }
71 
72  QImage const image( fileName );
73  if ( !image.isNull() ) {
74  // file is there, so create and return a tile object in any case
75  return image;
76  }
77  }
78 
79  // tile was not locally available => trigger download and look for tiles in other levels
80  // for scaling
81  QImage replacementTile = scaledLowerLevelTile( textureLayer, tileId );
82  Q_ASSERT( !replacementTile.isNull() );
83 
84  triggerDownload( textureLayer, tileId, usage );
85 
86  return replacementTile;
87 }
88 
89 
90 GeoDataDocument *TileLoader::loadTileVectorData( GeoSceneVectorTile const *textureLayer, TileId const & tileId, DownloadUsage const usage )
91 {
92  // FIXME: textureLayer->fileFormat() could be used in the future for use just that parser, instead of all available parsers
93 
94  QString const fileName = tileFileName( textureLayer, tileId );
95 
96  TileStatus status = tileStatus( textureLayer, tileId );
97  if ( status != Missing ) {
98  // check if an update should be triggered
99 
100  if ( status == Available ) {
101  mDebug() << Q_FUNC_INFO << tileId << "StateUptodate";
102  } else {
103  Q_ASSERT( status == Expired );
104  mDebug() << Q_FUNC_INFO << tileId << "StateExpired";
105  triggerDownload( textureLayer, tileId, usage );
106  }
107 
108  QFile file ( fileName );
109  if ( file.exists() ) {
110 
111  // File is ready, so parse and return the vector data in any case
112  ParsingRunnerManager man( m_pluginManager );
113  GeoDataDocument* document = man.openFile( fileName );
114 
115  if (document){
116  return document;
117  }
118  }
119  }
120 
121  // tile was not locally available => trigger download
122  triggerDownload( textureLayer, tileId, usage );
123 
124  return new GeoDataDocument;
125 }
126 
127 // This method triggers a download of the given tile (without checking
128 // expiration). It is called by upper layer (StackedTileLoader) when the tile
129 // that should be reloaded is currently loaded in memory.
130 //
131 // post condition
132 // - download is triggered
133 void TileLoader::downloadTile( GeoSceneTiled const *textureLayer, TileId const &tileId, DownloadUsage const usage )
134 {
135  triggerDownload( textureLayer, tileId, usage );
136 }
137 
138 int TileLoader::maximumTileLevel( GeoSceneTiled const & texture )
139 {
140  // if maximum tile level is configured in the DGML files,
141  // then use it, otherwise use old detection code.
142  if ( texture.maximumTileLevel() >= 0 ) {
143  return texture.maximumTileLevel();
144  }
145 
146  int maximumTileLevel = -1;
147  const QFileInfo themeStr( texture.themeStr() );
148  const QString tilepath = themeStr.isAbsolute() ? themeStr.absoluteFilePath() : MarbleDirs::path( texture.themeStr() );
149  // mDebug() << "StackedTileLoader::maxPartialTileLevel tilepath" << tilepath;
150  QStringList leveldirs = QDir( tilepath ).entryList( QDir::AllDirs | QDir::NoSymLinks
151  | QDir::NoDotAndDotDot );
152 
153  QStringList::const_iterator it = leveldirs.constBegin();
154  QStringList::const_iterator const end = leveldirs.constEnd();
155  for (; it != end; ++it ) {
156  bool ok = true;
157  const int value = (*it).toInt( &ok, 10 );
158 
159  if ( ok && value > maximumTileLevel )
160  maximumTileLevel = value;
161  }
162 
163  // mDebug() << "Detected maximum tile level that contains data: "
164  // << maxtilelevel;
165  return maximumTileLevel + 1;
166 }
167 
168 bool TileLoader::baseTilesAvailable( GeoSceneTiled const & texture )
169 {
170  const int levelZeroColumns = texture.levelZeroColumns();
171  const int levelZeroRows = texture.levelZeroRows();
172 
173  bool result = true;
174 
175  // Check whether the tiles from the lowest texture level are available
176  //
177  for ( int column = 0; result && column < levelZeroColumns; ++column ) {
178  for ( int row = 0; result && row < levelZeroRows; ++row ) {
179  const TileId id( 0, 0, column, row );
180  const QString tilepath = tileFileName( &texture, id );
181  result &= QFile::exists( tilepath );
182  if (!result) {
183  mDebug() << "Base tile " << texture.relativeTileFileName( id ) << " is missing for source dir " << texture.sourceDir();
184  }
185  }
186  }
187 
188  return result;
189 }
190 
191 TileLoader::TileStatus TileLoader::tileStatus( GeoSceneTiled const *textureLayer, const TileId &tileId )
192 {
193  QString const fileName = tileFileName( textureLayer, tileId );
194  QFileInfo fileInfo( fileName );
195  if ( !fileInfo.exists() ) {
196  return Missing;
197  }
198 
199  const QDateTime lastModified = fileInfo.lastModified();
200  const int expireSecs = textureLayer->expire();
201  const bool isExpired = lastModified.secsTo( QDateTime::currentDateTime() ) >= expireSecs;
202  return isExpired ? Expired : Available;
203 }
204 
205 void TileLoader::updateTile( QByteArray const & data, QString const & idStr )
206 {
207  QStringList const components = idStr.split( ':', QString::SkipEmptyParts );
208  Q_ASSERT( components.size() == 4 );
209 
210  QString const sourceDir = components[ 0 ];
211  int const zoomLevel = components[ 1 ].toInt();
212  int const tileX = components[ 2 ].toInt();
213  int const tileY = components[ 3 ].toInt();
214 
215  TileId const id = TileId( sourceDir, zoomLevel, tileX, tileY );
216 
217  QImage const tileImage = QImage::fromData( data );
218  if ( tileImage.isNull() )
219  return;
220 
221  emit tileCompleted( id, tileImage );
222 }
223 
224 QString TileLoader::tileFileName( GeoSceneTiled const * textureLayer, TileId const & tileId )
225 {
226  QString const fileName = textureLayer->relativeTileFileName( tileId );
227  QFileInfo const dirInfo( fileName );
228  return dirInfo.isAbsolute() ? fileName : MarbleDirs::path( fileName );
229 }
230 
231 void TileLoader::triggerDownload( GeoSceneTiled const *textureLayer, TileId const &id, DownloadUsage const usage )
232 {
233  QUrl const sourceUrl = textureLayer->downloadUrl( id );
234  QString const destFileName = textureLayer->relativeTileFileName( id );
235  QString const idStr = QString( "%1:%2:%3:%4" ).arg( textureLayer->sourceDir() ).arg( id.zoomLevel() ).arg( id.x() ).arg( id.y() );
236  emit downloadTile( sourceUrl, destFileName, idStr, usage );
237 }
238 
239 QImage TileLoader::scaledLowerLevelTile( const GeoSceneTextureTile * textureLayer, TileId const & id )
240 {
241  mDebug() << Q_FUNC_INFO << id;
242 
243  for ( int level = qMax<int>( 0, id.zoomLevel() - 1 ); level >= 0; --level ) {
244  int const deltaLevel = id.zoomLevel() - level;
245  TileId const replacementTileId( id.mapThemeIdHash(), level,
246  id.x() >> deltaLevel, id.y() >> deltaLevel );
247  QString const fileName = tileFileName( textureLayer, replacementTileId );
248  mDebug() << "TileLoader::scaledLowerLevelTile" << "trying" << fileName;
249  QImage toScale = QFile::exists(fileName) ? QImage(fileName) : QImage();
250 
251  if ( level == 0 && toScale.isNull() ) {
252  mDebug() << "No level zero tile installed in map theme dir. Falling back to a transparent image for now.";
253  QSize tileSize = textureLayer->tileSize();
254  Q_ASSERT( !tileSize.isEmpty() ); // assured by textureLayer
255  toScale = QImage( tileSize, QImage::Format_ARGB32_Premultiplied );
256  toScale.fill( qRgba( 0, 0, 0, 0 ) );
257  }
258 
259  if ( !toScale.isNull() ) {
260  // which rect to scale?
261  int const restTileX = id.x() % ( 1 << deltaLevel );
262  int const restTileY = id.y() % ( 1 << deltaLevel );
263  int const partWidth = toScale.width() >> deltaLevel;
264  int const partHeight = toScale.height() >> deltaLevel;
265  int const startX = restTileX * partWidth;
266  int const startY = restTileY * partHeight;
267  mDebug() << "QImage::copy:" << startX << startY << partWidth << partHeight;
268  QImage const part = toScale.copy( startX, startY, partWidth, partHeight );
269  mDebug() << "QImage::scaled:" << toScale.size();
270  return part.scaled( toScale.size() );
271  }
272  }
273 
274  Q_ASSERT_X( false, "scaled image", "level zero image missing" ); // not reached
275  return QImage();
276 }
277 
278 }
279 
280 #include "TileLoader.moc"
Marble::GeoSceneTiled::relativeTileFileName
QString relativeTileFileName(const TileId &) const
Definition: GeoSceneTiled.cpp:204
TileLoader.h
Marble::PluginManager
The class that handles Marble's plugins.
Definition: PluginManager.h:45
Marble::GeoDataDocument
A container for Features, Styles and in the future Schemas.
Definition: GeoDataDocument.h:65
Marble::GeoSceneVectorTile
Definition: GeoSceneVectorTile.h:23
QImage::fromData
QImage fromData(const uchar *data, int size, const char *format)
Marble::TileLoader::TileStatus
TileStatus
Definition: TileLoader.h:49
Marble::MarbleDirs::path
static QString path(const QString &relativePath)
Definition: MarbleDirs.cpp:59
Marble::DownloadUsage
DownloadUsage
This enum is used to describe the type of download.
Definition: MarbleGlobal.h:164
QByteArray
GeoDataContainer.h
Marble::TileLoader::tileStatus
static TileStatus tileStatus(GeoSceneTiled const *textureLayer, const TileId &tileId)
Returns the status of the downloaded tile file:
Definition: TileLoader.cpp:191
QSize::isEmpty
bool isEmpty() const
Marble::ParsingRunnerManager
Definition: ParsingRunnerManager.h:31
Marble::TileLoader::baseTilesAvailable
static bool baseTilesAvailable(GeoSceneTiled const &texture)
Returns whether the mandatory most basic tile level is fully available for the given texture layer...
Definition: TileLoader.cpp:168
Marble::TileLoader::maximumTileLevel
static int maximumTileLevel(GeoSceneTiled const &texture)
Definition: TileLoader.cpp:138
QString::split
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
HttpDownloadManager.h
Marble::GeoSceneTiled::levelZeroColumns
int levelZeroColumns() const
Definition: GeoSceneTiled.cpp:97
Marble::GeoSceneTiled
Definition: GeoSceneTiled.h:43
Marble::GeoSceneTiled::themeStr
QString themeStr() const
Definition: GeoSceneTiled.cpp:242
QImage::isNull
bool isNull() const
QFile::exists
bool exists() const
QImage::copy
QImage copy(const QRect &rectangle) const
Marble::TileLoader::loadTileVectorData
GeoDataDocument * loadTileVectorData(GeoSceneVectorTile const *textureLayer, TileId const &tileId, DownloadUsage const usage)
Definition: TileLoader.cpp:90
MarbleDebug.h
QList::const_iterator
QFile
Marble::TileLoader::updateTile
void updateTile(QByteArray const &imageData, QString const &tileId)
Definition: TileLoader.cpp:205
Marble::GeoSceneTiled::maximumTileLevel
int maximumTileLevel() const
Definition: GeoSceneTiled.cpp:117
ParsingRunnerManager.h
QList::size
int size() const
Marble::TileLoader::Expired
Definition: TileLoader.h:51
Marble::TileLoader::tileCompleted
void tileCompleted(TileId const &tileId, QImage const &tileImage)
Marble::ParsingRunnerManager::openFile
GeoDataDocument * openFile(const QString &fileName, DocumentRole role=UserDocument, int timeout=30000)
Definition: ParsingRunnerManager.cpp:121
Marble::TileLoader::Missing
Definition: TileLoader.h:50
MarbleDirs.h
QString
QFileInfo::lastModified
QDateTime lastModified() const
QStringList
Marble::GeoSceneTiled::sourceDir
QString sourceDir() const
Definition: GeoSceneTiled.cpp:56
QFileInfo
Marble::GeoSceneTiled::levelZeroRows
int levelZeroRows() const
Definition: GeoSceneTiled.cpp:107
QFileInfo::exists
bool exists() const
GeoSceneVectorTile.h
QSize
QUrl
QImage
QDir
Marble::TileId
Definition: TileId.h:27
QDateTime::currentDateTime
QDateTime currentDateTime()
GeoSceneTiled.h
QDateTime::secsTo
int secsTo(const QDateTime &other) const
QDir::entryList
QStringList entryList(QFlags< QDir::Filter > filters, QFlags< QDir::SortFlag > sort) const
Marble::TileLoader::downloadTile
void downloadTile(GeoSceneTiled const *textureLayer, TileId const &, DownloadUsage const )
Definition: TileLoader.cpp:133
Marble::TileLoader::Available
Definition: TileLoader.h:52
Marble::GeoSceneTextureTile
Definition: GeoSceneTextureTile.h:23
GeoSceneTextureTile.h
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Marble::TileLoader::loadTileImage
QImage loadTileImage(GeoSceneTextureTile const *textureLayer, TileId const &tileId, DownloadUsage const )
Definition: TileLoader.cpp:56
TileLoaderHelper.h
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
Marble::GeoSceneAbstractDataset::expire
int expire() const
Definition: GeoSceneAbstractDataset.cpp:53
Marble::mDebug
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:36
QImage::scaled
QImage scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const
QDateTime
Marble::HttpDownloadManager
This class manages scheduled downloads.
Definition: HttpDownloadManager.h:44
usage
void usage(const QString &app)
Definition: merge_ts_po.cpp:16
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:42 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal