File indexing completed on 2024-04-28 03:50:20

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2011 Daniel Marth <danielmarth@gmx.at>
0004 //
0005 
0006 #include "OpenCachingModel.h"
0007 #include "OpenCachingItem.h"
0008 
0009 #include "MarbleGlobal.h"
0010 #include "MarbleModel.h"
0011 #include "GeoDataCoordinates.h"
0012 #include "GeoDataLatLonAltBox.h"
0013 #include "MarbleDebug.h"
0014 #include "OpenCachingCache.h"
0015 
0016 #include <QDebug>
0017 #include <QString>
0018 #include <QUrl>
0019 #include <QXmlStreamReader>
0020 
0021 namespace Marble {
0022 
0023 class OpenCachingModelPrivate
0024 {
0025 public:
0026     QHash<QString, QVariant> parseCache( QXmlStreamReader& reader );
0027     QHash<QString, QVariant> parseLogEntry( QXmlStreamReader& reader );
0028     QHash<QString, QVariant> parseDescription( QXmlStreamReader& reader );
0029 };
0030 
0031 QHash<QString, QVariant> OpenCachingModelPrivate::parseCache( QXmlStreamReader& reader )
0032 {
0033     QHash<QString, QVariant> cache;
0034     while ( !reader.atEnd() ) {
0035         if (reader.isStartElement() && reader.name() != QLatin1String("cache")) {
0036             if (reader.name() == QLatin1String("id")) {
0037                 cache["id"] = reader.attributes().value("id").toString();
0038             }
0039             else if (reader.name() != QLatin1String("attributes") && reader.name() != QLatin1String("attribute")) {
0040                 cache[reader.name().toString()] = reader.readElementText();
0041             }
0042         }
0043         else if (reader.isEndElement() && reader.name() == QLatin1String("cache")) {
0044             return cache;
0045         }
0046         reader.readNext();
0047     }
0048     return QHash<QString, QVariant>();
0049 }
0050 
0051 QHash<QString, QVariant> OpenCachingModelPrivate::parseLogEntry( QXmlStreamReader& reader )
0052 {
0053     QHash<QString, QVariant> cacheLogEntry;
0054     while ( !reader.atEnd() ) {
0055         if (reader.isStartElement() && reader.name() != QLatin1String("cachelog")) {
0056             if (reader.name() == QLatin1String("cacheid")) {
0057                 cacheLogEntry["cacheid"] = reader.attributes().value( "id" ).toString();
0058             }
0059             else {
0060                 cacheLogEntry[reader.name().toString()] = reader.readElementText();
0061             }
0062         }
0063         else if (reader.isEndElement() && reader.name() == QLatin1String("cachelog")) {
0064             return cacheLogEntry;
0065         }
0066         reader.readNext();
0067     }
0068     return QHash<QString, QVariant>();
0069 }
0070 
0071 QHash<QString, QVariant> OpenCachingModelPrivate::parseDescription( QXmlStreamReader& reader )
0072 {
0073     QHash<QString, QVariant> cacheDesc;
0074     while ( !reader.atEnd() ) {
0075         if (reader.isStartElement() && reader.name() != QLatin1String("cachedesc")) {
0076             if (reader.name() == QLatin1String("cacheid")) {
0077                 cacheDesc["cacheid"] = reader.attributes().value( "id" ).toString();
0078             }
0079             else {
0080                 cacheDesc[reader.name().toString()] = reader.readElementText();
0081             }
0082         }
0083         else if (reader.isEndElement() && reader.name() == QLatin1String("cachedesc")) {
0084             return cacheDesc;
0085         }
0086         reader.readNext();
0087     }
0088     return QHash<QString, QVariant>();
0089 }
0090 
0091 OpenCachingModel::OpenCachingModel( const PluginManager *pluginManager, QObject *parent )
0092     : AbstractDataPluginModel( "opencaching", pluginManager, parent ),
0093       m_numResults( numberOfItemsOnScreen ),
0094       m_maxDistance( 20 ),
0095       m_minDifficulty( 0.0 ),
0096       m_maxDifficulty( 5.0 ),
0097       m_startDate( QDateTime::fromString( "2006-01-01", "yyyy-MM-dd" ) ),
0098       m_endDate( QDateTime::currentDateTime() ),
0099       d( new OpenCachingModelPrivate )
0100 {
0101 }
0102 
0103 OpenCachingModel::~OpenCachingModel()
0104 {
0105 }
0106 
0107 void OpenCachingModel::setNumResults( int numResults )
0108 {
0109     m_numResults = numResults;
0110 }
0111 
0112 void OpenCachingModel::setMaxDistance( int maxDistance )
0113 {
0114     m_maxDistance = maxDistance;
0115 }
0116 
0117 void OpenCachingModel::setMinDifficulty( double minDifficulty )
0118 {
0119     m_minDifficulty = minDifficulty;
0120 }
0121 
0122 void OpenCachingModel::setMaxDifficulty( double maxDifficulty )
0123 {
0124     m_maxDifficulty = maxDifficulty;
0125 }
0126 
0127 void OpenCachingModel::setStartDate( const QDateTime& startDate )
0128 {
0129     m_startDate = startDate;
0130 }
0131 
0132 void OpenCachingModel::setEndDate( const QDateTime& endDate )
0133 {
0134     m_endDate = endDate;
0135 }
0136 
0137 void OpenCachingModel::getAdditionalItems( const GeoDataLatLonAltBox& box, const MarbleModel *model, qint32 number )
0138 {
0139     Q_UNUSED( number );
0140 
0141     if (model->planetId() != QLatin1String("earth")) {
0142         return;
0143     }
0144 
0145     // https://www.opencaching.de/doc/xml/xml11.htm
0146     const QString openCachingUrl(QLatin1String("http://www.opencaching.de/xml/ocxml11.php") +
0147         QLatin1String("?modifiedsince=") + m_startDate.toString("yyyyMMddhhmmss") +
0148         QLatin1String("&cache=1&cachedesc=1&picture=0&cachelog=1&removedobject=0") +
0149         QLatin1String("&lat=") + QString::number(box.center().latitude() * RAD2DEG) +
0150         QLatin1String("&lon=") + QString::number(box.center().longitude() * RAD2DEG) +
0151         QLatin1String("&distance=") + QString::number(m_maxDistance) +
0152         QLatin1String("&charset=utf-8&cdata=0&session=0&zip=0"));
0153     downloadDescriptionFile( QUrl( openCachingUrl ) );
0154 }
0155 
0156 void OpenCachingModel::parseFile( const QByteArray& file )
0157 {
0158     QXmlStreamReader reader( file );
0159     QXmlStreamReader::TokenType token;
0160     QHash<int, OpenCachingCache> caches;
0161     QHash<int, QHash<QString, OpenCachingCacheDescription> > descriptions;
0162     QHash<int, OpenCachingCacheLog> logs;
0163 
0164     while( !reader.atEnd() && !reader.hasError() ) {
0165         token = reader.readNext();
0166         if( token == QXmlStreamReader::StartDocument ) {
0167             continue;
0168         }
0169         if( token == QXmlStreamReader::StartElement ) {
0170             if (reader.name() == QLatin1String("cache")) {
0171                 OpenCachingCache cache = d->parseCache( reader );
0172                 caches[cache.id()] = cache;
0173             }
0174             else if (reader.name() == QLatin1String("cachedesc")) {
0175                 OpenCachingCacheDescription description = d->parseDescription( reader );
0176                 descriptions[description.cacheId()][description.language()] = description;
0177             }
0178             else if (reader.name() == QLatin1String("cachelog")) {
0179                 OpenCachingCacheLogEntry logEntry = d->parseLogEntry( reader );
0180                 logs[logEntry.cacheId()].addLogEntry( logEntry );
0181             }
0182         }
0183     }
0184 
0185     QHash<int, OpenCachingCache>::iterator itpoint = caches.begin();
0186     QHash<int, OpenCachingCache>::iterator const endpoint = caches.end();
0187     for (; itpoint != endpoint; ++itpoint ) {
0188         if( caches[itpoint.key()].difficulty() >= m_minDifficulty &&
0189             caches[itpoint.key()].difficulty() <= m_maxDifficulty )
0190         {
0191             caches[itpoint.key()].setDescription( descriptions[itpoint.key()] );
0192             caches[itpoint.key()].setLog( logs[itpoint.key()] );
0193             addItemToList( new OpenCachingItem( caches[itpoint.key()], this ) );
0194         }
0195     }
0196 }
0197 
0198 }
0199 
0200 #include "moc_OpenCachingModel.cpp"