File indexing completed on 2025-01-05 03:59:26

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2011 Thibaut Gridel <tgridel@free.fr>
0004 
0005 #include "CacheRunner.h"
0006 
0007 // Qt includes
0008 
0009 #include <QFile>
0010 #include <QDataStream>
0011 #include <QSet>
0012 
0013 // Local includes
0014 
0015 #include "GeoDataDocument.h"
0016 #include "GeoDataExtendedData.h"
0017 #include "GeoDataData.h"
0018 #include "GeoDataPlacemark.h"
0019 #include "digikam_debug.h"
0020 
0021 namespace Marble
0022 {
0023 
0024 const quint32 MarbleMagicNumber = 0x31415926;
0025 
0026 CacheRunner::CacheRunner(QObject* const parent)
0027     : ParsingRunner(parent)
0028 {
0029 }
0030 
0031 CacheRunner::~CacheRunner()
0032 {
0033 }
0034 
0035 GeoDataDocument* CacheRunner::parseFile( const QString &fileName, DocumentRole role, QString& error )
0036 {
0037     QFile file( fileName );
0038 
0039     if ( !file.exists() )
0040     {
0041         error = QStringLiteral("File %1 does not exist").arg(fileName);
0042         qCDebug(DIGIKAM_MARBLE_LOG) << error;
0043         return nullptr;
0044     }
0045 
0046     file.open( QIODevice::ReadOnly );
0047     QDataStream in( &file );
0048 
0049     // Read and check the header
0050     quint32 magic;
0051     in >> magic;
0052 
0053     if ( magic != MarbleMagicNumber )
0054     {
0055         return nullptr;
0056     }
0057 
0058     // Read the version
0059     qint32 version;
0060     in >> version;
0061 
0062     if ( version < 015 )
0063     {
0064         error = QStringLiteral("Bad cache file %1: Version %2 is too old, need 15 or later").arg(fileName).arg(version);
0065         qCDebug(DIGIKAM_MARBLE_LOG) << error;
0066         return nullptr;
0067     }
0068 
0069     /*
0070       if (version > 002) {
0071       qCDebug(DIGIKAM_MARBLE_LOG) << "Bad file - too new!";
0072       return;
0073       }
0074     */
0075 
0076     GeoDataDocument *document = new GeoDataDocument();
0077     document->setDocumentRole( role );
0078 
0079     in.setVersion( QDataStream::Qt_4_2 );
0080 
0081     // Read the data itself
0082     // Use double to provide a single cache file format across architectures
0083 
0084     double   lon;
0085     double   lat;
0086     double   alt;
0087     double   area;
0088 
0089     QString  tmpstr;
0090     qint64   tmpint64;
0091     qint8    tmpint8;
0092     qint16   tmpint16;
0093 
0094     // share string data on the heap at least for this file
0095     QSet<QString> stringPool;
0096     const QString gmtId = QStringLiteral("gmt");
0097     const QString dstId = QStringLiteral("dst");
0098 
0099     while ( !in.atEnd() )
0100     {
0101         GeoDataPlacemark *mark = new GeoDataPlacemark;
0102         in >> tmpstr; tmpstr = *stringPool.insert(tmpstr);
0103         mark->setName( tmpstr );
0104         in >> lon >> lat >> alt;
0105         mark->setCoordinate( (qreal)(lon), (qreal)(lat), (qreal)(alt) );
0106         in >> tmpstr; tmpstr = *stringPool.insert(tmpstr);
0107         mark->setRole( tmpstr );
0108         in >> tmpstr; tmpstr = *stringPool.insert(tmpstr);
0109         mark->setDescription( tmpstr );
0110         in >> tmpstr; tmpstr = *stringPool.insert(tmpstr);
0111         mark->setCountryCode( tmpstr );
0112         in >> tmpstr; tmpstr = *stringPool.insert(tmpstr);
0113         mark->setState( tmpstr );
0114         in >> area;
0115         mark->setArea( (qreal)(area) );
0116         in >> tmpint64;
0117         mark->setPopulation( tmpint64 );
0118         in >> tmpint16;
0119         mark->extendedData().addValue(GeoDataData(gmtId, int(tmpint16)));
0120         in >> tmpint8;
0121         mark->extendedData().addValue(GeoDataData(dstId, int(tmpint8)));
0122 
0123         document->append( mark );
0124     }
0125 
0126     document->setFileName( fileName );
0127 
0128     file.close();
0129 
0130     return document;
0131 }
0132 
0133 } // namespace Marble
0134 
0135 #include "moc_CacheRunner.cpp"