14 #include <QDataStream>
39 class FileLoaderPrivate
42 FileLoaderPrivate( FileLoader* parent, MarbleModel *model,
bool recenter,
43 const QString& file,
const QString& property, GeoDataStyle* style,
DocumentRole role )
45 m_runner( model->pluginManager() ),
46 m_recenter( recenter ),
48 m_property( property ),
50 m_documentRole ( role ),
51 m_styleMap( new GeoDataStyleMap ),
53 m_clock( model->clock() )
56 m_styleMap->setStyleId(
"default-map");
57 m_styleMap->insert(
"normal", QString(
"#").append(m_style->styleId()));
61 FileLoaderPrivate( FileLoader* parent, MarbleModel *model,
62 const QString& contents,
const QString& file,
DocumentRole role )
64 m_runner( model->pluginManager() ),
67 m_contents ( contents ),
68 m_documentRole ( role ),
70 m_clock( model->clock() )
78 void saveFile(
const QString& filename );
79 void savePlacemarks(QDataStream &out,
const GeoDataContainer *container);
81 void createFilterProperties( GeoDataContainer *container );
82 int cityPopIdx( qint64 population )
const;
83 int spacePopIdx( qint64 population )
const;
84 int areaPopIdx( qreal area )
const;
86 void documentParsed( GeoDataDocument *doc,
const QString& error);
89 ParsingRunnerManager m_runner;
93 QString m_nonExistentLocalCacheFile;
95 GeoDataStyle* m_style;
97 GeoDataStyleMap* m_styleMap;
98 GeoDataDocument *m_document;
101 const MarbleClock *m_clock;
107 d( new FileLoaderPrivate( this, model, recenter, file, property, style, role ) )
114 d( new FileLoaderPrivate( this, model, contents, file, role ) )
125 return d->m_filepath;
130 return d->m_document;
140 if ( d->m_contents.isEmpty() ) {
141 QString defaultSourceName;
143 mDebug() <<
"starting parser for" << d->m_filepath;
145 QFileInfo fileinfo( d->m_filepath );
146 QString
path = fileinfo.path();
147 if ( path ==
"." ) path.clear();
148 QString name = fileinfo.completeBaseName();
149 QString suffix = fileinfo.suffix();
153 if ( fileinfo.isAbsolute() ) {
155 defaultSourceName = path +
'/' + name +
'.' + suffix;
157 else if ( d->m_filepath.contains(
'/' ) ) {
163 defaultSourceName =
MarbleDirs::path(
"placemarks/" + path + name +
'.' + suffix );
166 if ( cacheFile.isEmpty()) {
168 if ( !QFileInfo( cacheFile ).exists() ) {
169 d->m_nonExistentLocalCacheFile = cacheFile;
175 if ( QFile::exists( cacheFile ) ) {
176 mDebug() <<
"Loading Cache File:" + cacheFile;
178 QDateTime sourceLastModified;
180 if ( QFile::exists( defaultSourceName ) ) {
181 sourceLastModified = QFileInfo( defaultSourceName ).lastModified();
184 const QDateTime cacheLastModified = QFileInfo( cacheFile ).lastModified();
186 if ( sourceLastModified < cacheLastModified ) {
187 connect( &d->m_runner, SIGNAL(parsingFinished(
GeoDataDocument*,QString)),
189 d->m_runner.parseFile( cacheFile, d->m_documentRole );
193 else if ( QFile::exists( defaultSourceName ) ) {
194 mDebug() <<
"No recent Default Placemark Cache File available!";
197 connect( &d->m_runner, SIGNAL(parsingFinished(
GeoDataDocument*,QString)),
199 d->m_runner.parseFile( defaultSourceName, d->m_documentRole );
202 mDebug() <<
"No Default Placemark Source File for " << name;
209 QByteArray ba( d->m_contents.toUtf8() );
210 QBuffer buffer( &ba );
211 buffer.open( QIODevice::ReadOnly );
213 if ( !parser.
read( &buffer ) ) {
214 qWarning(
"Could not import kml buffer!" );
220 Q_ASSERT( document );
223 d->m_document->setProperty( d->m_property );
224 d->m_document->setDocumentRole( d->m_documentRole );
225 d->createFilterProperties( d->m_document );
228 mDebug() <<
"newGeoDataDocumentAdded" << d->m_filepath;
238 return d->m_recenter;
243 void FileLoaderPrivate::saveFile(
const QString& filename )
249 mDebug() <<
"Creating cache at " << filename ;
251 QFile file( filename );
252 if ( !file.open( QIODevice::WriteOnly ) ) {
253 mDebug() << Q_FUNC_INFO <<
"Can't open" << filename <<
"for writing";
256 QDataStream out( &file );
263 out.setVersion( QDataStream::Qt_4_2 );
265 savePlacemarks(out, m_document);
268 void FileLoaderPrivate::savePlacemarks(QDataStream &out,
const GeoDataContainer *container)
275 const QVector<GeoDataPlacemark*> placemarks = container->placemarkList();
276 QVector<GeoDataPlacemark*>::const_iterator it = placemarks.constBegin();
277 QVector<GeoDataPlacemark*>::const_iterator
const end = placemarks.constEnd();
278 for (; it != end; ++it ) {
279 out << (*it)->name();
280 (*it)->coordinate( m_clock->dateTime() ).geoCoordinates( lon, lat, alt );
283 out << (double)(lon) << (double)(lat) << (double)(alt);
284 out << QString( (*it)->role() );
285 out << QString( (*it)->description() );
286 out << QString( (*it)->countryCode() );
287 out << QString( (*it)->state() );
288 out << (double) (*it)->area();
289 out << (qint64) (*it)->population();
290 out << ( qint16 ) ( (*it)->extendedData().value(
"gmt").value().toInt() );
291 out << ( qint8 ) ( (*it)->extendedData().value(
"dst").value().toInt() );
294 const QVector<GeoDataFolder*> folders = container->folderList();
295 QVector<GeoDataFolder*>::const_iterator cont = folders.constBegin();
296 QVector<GeoDataFolder*>::const_iterator endcont = folders.constEnd();
297 for (; cont != endcont; ++cont ) {
298 savePlacemarks(out, *cont);
302 void FileLoaderPrivate::documentParsed( GeoDataDocument* doc,
const QString& error )
307 doc->setProperty( m_property );
309 doc->addStyleMap( *m_styleMap );
310 doc->addStyle( *m_style );
313 createFilterProperties( doc );
314 emit q->newGeoDataDocumentAdded( m_document );
315 if ( !m_nonExistentLocalCacheFile.isEmpty() ) {
316 saveFile( m_nonExistentLocalCacheFile );
319 emit q->loaderFinished( q );
322 void FileLoaderPrivate::createFilterProperties( GeoDataContainer *container )
324 QVector<GeoDataFeature*>::Iterator i = container->begin();
325 QVector<GeoDataFeature*>::Iterator
const end = container->end();
326 for (; i != end; ++i ) {
329 GeoDataContainer *child =
static_cast<GeoDataContainer*
>( *i );
330 createFilterProperties( child );
336 Q_ASSERT( dynamic_cast<GeoDataPlacemark*>( *i ) );
338 GeoDataPlacemark* placemark =
static_cast<GeoDataPlacemark*
>( *i );
339 Q_ASSERT( placemark->geometry() );
341 bool hasPopularity =
false;
347 placemark->setStyleUrl( QString(
"#").append( m_styleMap->styleId() ) );
351 if ( placemark->role() ==
"H" || placemark->role() ==
"V" || placemark->role() ==
"W" )
353 qreal altitude = placemark->coordinate( m_clock->dateTime() ).altitude();
354 if ( altitude != 0.0 )
356 hasPopularity =
true;
357 placemark->setPopularity( (qint64)(altitude * 1000.0) );
358 placemark->setZoomLevel( cityPopIdx( qAbs( (qint64)(altitude * 1000.0) ) ) );
362 else if ( placemark->role() ==
"K" || placemark->role() ==
"O" || placemark->role() ==
"S" )
364 qreal area = placemark->area();
367 hasPopularity =
true;
369 placemark->setPopularity( (qint64)(area * 100) );
370 placemark->setZoomLevel( areaPopIdx( area ) );
374 else if ( placemark->role() ==
"P" )
376 placemark->setPopularity( 1000000000 );
377 placemark->setZoomLevel( 1 );
380 else if ( placemark->role() ==
"M" )
382 placemark->setPopularity( 10000000 );
383 placemark->setZoomLevel( 3 );
386 else if ( placemark->role() ==
"h" )
388 placemark->setPopularity( 1000000000 );
389 placemark->setZoomLevel( 1 );
392 else if ( placemark->role() ==
"r" )
394 placemark->setPopularity( 10000000 );
395 placemark->setZoomLevel( 2 );
398 else if ( placemark->role() ==
"u" )
400 placemark->setPopularity( 1000000 );
401 placemark->setZoomLevel( 3 );
404 else if ( placemark->role() ==
"i" )
406 placemark->setPopularity( 1000000 );
407 placemark->setZoomLevel( 3 );
410 else if ( placemark->role() ==
"m" || placemark->role() ==
"v"
411 || placemark->role() ==
"o" || placemark->role() ==
"c"
412 || placemark->role() ==
"a" )
414 qint64 diameter = placemark->population();
417 hasPopularity =
true;
418 placemark->setPopularity( diameter );
419 if ( placemark->role() ==
"c" ) {
420 placemark->setZoomLevel( spacePopIdx( diameter ) );
421 if ( placemark->name() ==
"Tycho" || placemark->name() ==
"Copernicus" ) {
422 placemark->setZoomLevel( 1 );
426 placemark->setZoomLevel( spacePopIdx( diameter ) );
429 if ( placemark->role() ==
"a" && diameter == 0 ) {
430 placemark->setPopularity( 1000000000 );
431 placemark->setZoomLevel( 1 );
437 qint64 population = placemark->population();
438 if ( population >= 0 )
440 hasPopularity =
true;
441 placemark->setPopularity( population );
442 placemark->setZoomLevel( cityPopIdx( population ) );
466 if ( placemark->role()==
"PPL"
467 || placemark->role()==
"PPLF"
468 || placemark->role()==
"PPLG"
469 || placemark->role()==
"PPLL"
470 || placemark->role()==
"PPLQ"
471 || placemark->role()==
"PPLR"
472 || placemark->role()==
"PPLS"
473 || placemark->role()==
"PPLW" ) placemark->setVisualCategory(
475 + (( 20- ( 2*placemark->zoomLevel()) ) / 4 * 4 ) ) );
476 else if ( placemark->role() ==
"PPLA" ) placemark->setVisualCategory(
478 + (( 20- ( 2*placemark->zoomLevel()) ) / 4 * 4 ) ) );
479 else if ( placemark->role()==
"PPLC" ) placemark->setVisualCategory(
481 + (( 20- ( 2*placemark->zoomLevel()) ) / 4 * 4 ) ) );
482 else if ( placemark->role()==
"PPLA2" || placemark->role()==
"PPLA3" ) placemark->setVisualCategory(
484 + (( 20- ( 2*placemark->zoomLevel()) ) / 4 * 4 ) ) );
487 placemark->setZoomLevel(0);
494 if ( placemark->role() ==
"W" && placemark->zoomLevel() < 4 )
495 placemark->setZoomLevel( 4 );
496 if ( placemark->role() ==
"O" )
497 placemark->setZoomLevel( 2 );
498 if ( placemark->role() ==
"K" )
499 placemark->setZoomLevel( 0 );
500 if ( !placemark->isVisible() ) {
501 placemark->setZoomLevel( 18 );
505 if ( placemark->population() < -1 ) {
506 placemark->setZoomLevel( 18 );
509 qWarning() << Q_FUNC_INFO <<
"Unknown feature" << (*i)->nodeType() <<
". Skipping.";
514 int FileLoaderPrivate::cityPopIdx( qint64 population )
const
518 if ( population < 2500 ) popidx=10;
519 else if ( population < 5000) popidx=9;
520 else if ( population < 25000) popidx=8;
521 else if ( population < 75000) popidx=7;
522 else if ( population < 250000) popidx=6;
523 else if ( population < 750000) popidx=5;
524 else if ( population < 2500000) popidx=4;
529 int FileLoaderPrivate::spacePopIdx( qint64 population )
const
533 if ( population < 1000 ) popidx=10;
534 else if ( population < 2000) popidx=9;
535 else if ( population < 8000) popidx=8;
536 else if ( population < 20000) popidx=7;
537 else if ( population < 60000) popidx=6;
538 else if ( population < 100000) popidx=5;
539 else if ( population < 200000 ) popidx=4;
540 else if ( population < 400000 ) popidx=2;
541 else if ( population < 600000 ) popidx=1;
546 int FileLoaderPrivate::areaPopIdx( qreal area )
const
549 if ( area < 200000 ) popidx=5;
550 else if ( area < 1000000 ) popidx=4;
551 else if ( area < 2500000 ) popidx=3;
552 else if ( area < 5000000 ) popidx=2;
559 #include "FileLoader.moc"
A container for Features, Styles and in the future Schemas.
const char * GeoDataPointType
static QString path(const QString &relativePath)
void newGeoDataDocumentAdded(GeoDataDocument *)
GeoDataDocument * document()
This file contains the headers for MarbleModel.
const char * GeoDataPlacemarkType
const char * GeoDataDocumentType
const char * GeoDataGroundOverlayType
static QString localPath()
const quint32 MarbleMagicNumber
an addressable style group
const char * GeoDataScreenOverlayType
bool read(QIODevice *)
Main API for reading the XML document.
void loaderFinished(FileLoader *)
const char * GeoDataFolderType
The data model (not based on QAbstractModel) for a MarbleWidget.
FileLoader(QObject *parent, MarbleModel *model, bool recenter, const QString &file, const QString &property, GeoDataStyle *style, DocumentRole role)
A shared base class between GeoDataDocument/GeoSourceDocument.
GeoDataVisualCategory
A categorization of a placemark as defined by ...FIXME.
const char * GeoDataTrackType
QDebug mDebug()
a function to replace qDebug() in Marble library code
const char * GeoDataPhotoOverlayType
GeoDocument * releaseDocument()
retrieve the parsed document and reset the parser If parsing was successful, retrieve the resulting d...