File indexing completed on 2024-05-05 03:50:44

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2012 Utku Aydın <utkuaydin34@gmail.com>
0004 //
0005 
0006 #include "FoursquareModel.h"
0007 #include "FoursquarePlugin.h"
0008 #include "FoursquareItem.h"
0009 
0010 #include "MarbleGlobal.h"
0011 #include "MarbleModel.h"
0012 #include "GeoDataCoordinates.h"
0013 #include "GeoDataLatLonAltBox.h"
0014 #include "MarbleDebug.h"
0015 #include "MarbleMath.h"
0016 
0017 #include <QUrl>
0018 #include <QJsonDocument>
0019 #include <QJsonArray>
0020 #include <QJsonObject>
0021 
0022 namespace Marble
0023 {
0024     
0025 FoursquareModel::FoursquareModel(const MarbleModel *marbleModel, QObject* parent)
0026     : AbstractDataPluginModel("foursquare", marbleModel, parent)
0027 {
0028     // Enjoy laziness
0029 }
0030 
0031 FoursquareModel::~FoursquareModel()
0032 {
0033 }
0034 
0035 void FoursquareModel::getAdditionalItems( const GeoDataLatLonAltBox& box, qint32 number )
0036 {
0037     if (marbleModel()->planetId() != QLatin1String("earth")) {
0038         return;
0039     }
0040     
0041     QString clientId = "YPRWSYFW1RVL4PJQ2XS5G14RTOGTHOKZVHC1EP5KCCCYQPZF";
0042     QString clientSecret = "5L2JDCAYQCEJWY5FNDU4A1RWATE4E5FIIXXRM41YBTFSERUH";
0043     
0044     QString apiUrl( "https://api.foursquare.com/v2/venues/search" );
0045     qreal const distanceLon = marbleModel()->planetRadius() * distanceSphere( box.west(), box.north(), box.east(), box.north() );
0046     qreal const distanceLat = marbleModel()->planetRadius() * distanceSphere( box.west(), box.north(), box.west(), box.south() );
0047     qreal const area = distanceLon * distanceLat;
0048     if ( area > 10 * 1000 * KM2METER * KM2METER ) {
0049         // Large area (> 10.000 km^2) => too large for bbox queries
0050         apiUrl += QLatin1String("?ll=") + QString::number(box.center().latitude(Marble::GeoDataCoordinates::Degree)) +
0051                   QLatin1Char(',') + QString::number(box.center().longitude(Marble::GeoDataCoordinates::Degree)) +
0052                   QLatin1String("&intent=checkin");
0053     } else {
0054         apiUrl += QLatin1String("?ne=") + QString::number(box.north(Marble::GeoDataCoordinates::Degree)) +
0055                   QLatin1Char(',') + QString::number(box.east(Marble::GeoDataCoordinates::Degree)) +
0056                   QLatin1String("&sw=") + QString::number(box.south(Marble::GeoDataCoordinates::Degree)) +
0057                   QLatin1Char(',') + QString::number(box.west(Marble::GeoDataCoordinates::Degree)) +
0058                   QLatin1String("&intent=browse");
0059     }
0060     apiUrl += QLatin1String("&limit=") + QString::number(number) +
0061               QLatin1String("&client_id=") + clientId +
0062               QLatin1String("&client_secret=") + clientSecret +
0063               QLatin1String("&v=20120601");
0064     downloadDescriptionFile( QUrl( apiUrl ) );
0065 }
0066 
0067 void FoursquareModel::parseFile( const QByteArray& file )
0068 {
0069     const QJsonDocument jsonDoc = QJsonDocument::fromJson(file);
0070     const QJsonObject responseObject = jsonDoc.object().value(QStringLiteral("response")).toObject();
0071     const QJsonValue venuesValue = responseObject.value(QStringLiteral("response"));
0072 
0073     // Parse if any result exists
0074     if (venuesValue.isArray()) {
0075         // Add items to the list
0076         QList<AbstractDataPluginItem*> items;
0077 
0078         const QJsonArray venueArray = venuesValue.toArray();
0079         for (int venueIndex = 0; venueIndex < venueArray.size(); ++venueIndex) {
0080             const QJsonObject venueObject = venueArray[venueIndex].toObject();
0081 
0082             const QJsonObject firstCategoryObject = venueObject.value(QStringLiteral("categories")).toArray().at(0).toObject();
0083 
0084             const QString id = venueObject.value(QStringLiteral("id")).toString();
0085             const QString name = venueObject.value(QStringLiteral("name")).toString();
0086             const QString category = firstCategoryObject.value(QStringLiteral("name")).toString();
0087             const QJsonObject locationObject = venueObject.value(QStringLiteral("location")).toObject();
0088             const QString address = locationObject.value(QStringLiteral("address")).toString();
0089             const QString city = locationObject.value(QStringLiteral("city")).toString();
0090             const QString country = locationObject.value(QStringLiteral("country")).toString();
0091             const double latitude = locationObject.value(QStringLiteral("lat")).toString().toDouble();
0092             const double longitude = locationObject.value(QStringLiteral("lng")).toString().toDouble();
0093             const int usersCount = venueObject.value(QStringLiteral("stats")).toObject().value(QStringLiteral("usersCount")).toInt();
0094 
0095             const QJsonValue categoryIconValue = firstCategoryObject.value(QStringLiteral("icon"));
0096             QString iconUrl;
0097             QString largeIconUrl;
0098             if (categoryIconValue.isObject()) {
0099                 const QJsonObject categoryIconObject = categoryIconValue.toObject();
0100                 const QString iconPrefix = categoryIconObject.value(QStringLiteral("prefix")).toString();
0101                 const QString iconName = categoryIconObject.value(QStringLiteral("name")).toString();
0102                 iconUrl = iconPrefix
0103                         + QLatin1String("32") // That's the icon size hardcoded
0104                         + iconName;
0105 
0106                 largeIconUrl = iconPrefix
0107                         + QLatin1String("64") // Larger icon
0108                         + iconName;
0109             }
0110 
0111             if( !itemExists( id ) ) {
0112                 GeoDataCoordinates coordinates( longitude, latitude, 0.0, GeoDataCoordinates::Degree );
0113                 FoursquareItem *item = new FoursquareItem( this );
0114                 item->setId( id );
0115                 item->setCoordinate( coordinates );
0116                 item->setName( name );
0117                 item->setCategory( category );
0118                 item->setAddress( address );
0119                 item->setCity( city );
0120                 item->setCountry( country );
0121                 item->setUsersCount( usersCount );
0122                 item->setCategoryIconUrl( iconUrl );
0123                 item->setCategoryLargeIconUrl( largeIconUrl );
0124                 
0125                 items << item;
0126             }
0127         }
0128         addItemsToList( items );
0129     }
0130 }
0131 
0132 }
0133 
0134 #include "moc_FoursquareModel.cpp"