~ubuntu-branches/ubuntu/quantal/qtmobility/quantal

« back to all changes in this revision

Viewing changes to plugins/landmarks/sqlite/databaseoperations.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-11-16 16:18:07 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20101116161807-k2dzt2nyse975r3l
Tags: 1.1.0-0ubuntu1
* New upstream release
* Syncronise with Debian, no remaining changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
**
9
9
** $QT_BEGIN_LICENSE:LGPL$
10
10
** Commercial Usage
11
 
** Licensees holding valid Qt Commercial licenses may use this file in
12
 
** accordance with the Qt Solutions Commercial License Agreement provided
13
 
** with the Software or, alternatively, in accordance with the terms
 
11
** Licensees holding valid Qt Commercial licenses may use this file in 
 
12
** accordance with the Qt Commercial License Agreement provided with
 
13
** the Software or, alternatively, in accordance with the terms
14
14
** contained in a written agreement between you and Nokia.
15
15
**
16
16
** GNU Lesser General Public License Usage
33
33
** ensure the GNU General Public License version 3.0 requirements will be
34
34
** met: http://www.gnu.org/copyleft/gpl.html.
35
35
**
36
 
** Please note Third Party Software included with Qt Solutions may impose
37
 
** additional restrictions and it is the user's responsibility to ensure
38
 
** that they have met the licensing requirements of the GPL, LGPL, or Qt
39
 
** Solutions Commercial license and the relevant license of the Third
40
 
** Party Software they are using.
41
 
**
42
36
** If you are unsure which license is appropriate for your use, please
43
37
** contact the sales department at qt-sales@nokia.com.
44
38
** $QT_END_LICENSE$
115
109
    return q;
116
110
}
117
111
 
 
112
bool isValidLat(double lat)
 
113
{
 
114
    return -90.0 <= lat && lat <=90.0;
 
115
}
 
116
 
 
117
bool isValidLong(double lng)
 
118
{
 
119
    return -180.0 <= lng && lng <= 180.0;
 
120
}
 
121
 
118
122
bool matchString(const QString &sourceString, const QString &matchString, QLandmarkFilter::MatchFlags matchFlags )
119
123
{
120
124
    Qt::CaseSensitivity cs;
135
139
    }
136
140
}
137
141
 
 
142
QVariant getCategoryAttribute(QLandmarkCategory *category, const QString &key)
 
143
{
 
144
    if (key.compare("name",Qt::CaseSensitive) == 0) {
 
145
        return category->name();
 
146
    } else if (key.compare("iconUrl",Qt::CaseSensitive) ==0) {
 
147
        return category->iconUrl();
 
148
    }
 
149
 
 
150
    Q_ASSERT(false);//This should not be reachable
 
151
    return QVariant();
 
152
}
 
153
 
 
154
void setCategoryAttribute(QLandmarkCategory *category, const QString &key, const QVariant &value)
 
155
{
 
156
    if (key.compare("name",Qt::CaseInsensitive) == 0) {
 
157
        category->setName(value.toString());
 
158
        return;
 
159
    } else if (key.compare("iconUrl",Qt::CaseInsensitive) ==0) {
 
160
        category->setIconUrl(QUrl(value.toUrl()));
 
161
        return;
 
162
    }
 
163
 
 
164
    Q_ASSERT(false);//This should not be reachable
 
165
    return;
 
166
}
 
167
 
 
168
QVariant getLandmarkAttribute(QLandmark *landmark, const QString &key) {
 
169
    if (key.compare("name",Qt::CaseSensitive) == 0) {
 
170
        return landmark->name();
 
171
    } else if (key.compare("description", Qt::CaseSensitive) == 0) {
 
172
        return landmark->description();
 
173
    } else if (key.compare("iconUrl",Qt::CaseSensitive) ==0) {
 
174
        return landmark->iconUrl();
 
175
    } else if (key.compare("radius", Qt::CaseSensitive) == 0) {
 
176
        return landmark->radius();
 
177
    } else if (key.compare("phoneNumber", Qt::CaseSensitive) == 0) {
 
178
        return landmark->phoneNumber();
 
179
    } else if (key.compare("url", Qt::CaseSensitive) ==0 ) {
 
180
        return landmark->url();
 
181
    } else if (key.compare("latitude", Qt::CaseSensitive)== 0) {
 
182
        return landmark->coordinate().latitude();
 
183
    } else if (key.compare("longitude", Qt::CaseSensitive) ==0) {
 
184
        return landmark->coordinate().longitude();
 
185
    } else if (key.compare("altitude", Qt::CaseSensitive) ==0) {
 
186
        return landmark->coordinate().altitude();
 
187
    } else if (key.compare("country", Qt::CaseSensitive) ==0 ){
 
188
        return landmark->address().country();
 
189
    }  else if (key.compare("countryCode", Qt::CaseSensitive) ==0 ){
 
190
        return landmark->address().countryCode();
 
191
    } else if (key.compare("state", Qt::CaseSensitive) ==0 ){
 
192
        return landmark->address().state();
 
193
    } else if (key.compare("county", Qt::CaseSensitive) ==0 ){
 
194
        return landmark->address().county();
 
195
    } else if (key.compare("city", Qt::CaseSensitive) ==0 ){
 
196
        return landmark->address().city();
 
197
    } else if (key.compare("district", Qt::CaseSensitive) ==0 ){
 
198
        return landmark->address().district();
 
199
    } else if (key.compare("street", Qt::CaseSensitive) ==0 ){
 
200
        return landmark->address().street();
 
201
    } else if (key.compare("postcode", Qt::CaseSensitive) ==0 ){
 
202
        return landmark->address().postcode();
 
203
    }
 
204
    Q_ASSERT(false);//It shouldn't be possible to get here
 
205
    return QVariant();
 
206
}
 
207
 
 
208
void setLandmarkAttribute(QLandmark *landmark, const QString &key, const QVariant &value)
 
209
{
 
210
    if (key.compare("name",Qt::CaseSensitive) == 0) {
 
211
        landmark->setName(value.toString());
 
212
        return;
 
213
    } else if (key.compare("description", Qt::CaseSensitive) == 0) {
 
214
        landmark->setDescription(value.toString());
 
215
        return;
 
216
    } else if (key.compare("iconUrl",Qt::CaseSensitive) ==0) {
 
217
        landmark->setIconUrl(QUrl(value.toUrl()));
 
218
        return;
 
219
    } else if (key.compare("radius", Qt::CaseSensitive) == 0) {
 
220
        landmark->setRadius(value.toReal());
 
221
        return;
 
222
    } else if (key.compare("phoneNumber", Qt::CaseSensitive) == 0) {
 
223
        landmark->setPhoneNumber(value.toString());
 
224
        return;
 
225
    } else if (key.compare("url", Qt::CaseSensitive) ==0 ) {
 
226
        landmark->setUrl(QUrl(value.toUrl()));
 
227
        return;
 
228
    } else if (key.compare("latitude", Qt::CaseSensitive)== 0) {
 
229
        QGeoCoordinate coord = landmark->coordinate();
 
230
        coord.setLatitude(value.toDouble());
 
231
        landmark->setCoordinate(coord);
 
232
        return;
 
233
    } else if (key.compare("longitude", Qt::CaseSensitive) ==0) {
 
234
        QGeoCoordinate coord = landmark->coordinate();
 
235
        coord.setLongitude(value.toDouble());
 
236
        landmark->setCoordinate(coord);
 
237
        return;
 
238
    } else if (key.compare("altitude", Qt::CaseSensitive) ==0) {
 
239
        QGeoCoordinate coord = landmark->coordinate();
 
240
        coord.setAltitude(value.toDouble());
 
241
        landmark->setCoordinate(coord);
 
242
        return;
 
243
    } else if (key.compare("country", Qt::CaseSensitive) ==0 ){
 
244
        QGeoAddress address = landmark->address();
 
245
        address.setCountry(value.toString());
 
246
        landmark->setAddress(address);
 
247
        return;
 
248
    }  else if (key.compare("countryCode", Qt::CaseSensitive) ==0 ){
 
249
        QGeoAddress address = landmark->address();
 
250
        address.setCountryCode(value.toString());
 
251
        landmark->setAddress(address);
 
252
        return;
 
253
    } else if (key.compare("state", Qt::CaseSensitive) ==0 ){
 
254
        QGeoAddress address = landmark->address();
 
255
        address.setState(value.toString());
 
256
        landmark->setAddress(address);
 
257
        return;
 
258
    } else if (key.compare("county", Qt::CaseSensitive) ==0 ){
 
259
        QGeoAddress address = landmark->address();
 
260
        address.setCounty(value.toString());
 
261
        landmark->setAddress(address);
 
262
        return;
 
263
    } else if (key.compare("city", Qt::CaseSensitive) == 0 ){
 
264
        QGeoAddress address = landmark->address();
 
265
        address.setCity(value.toString());
 
266
        landmark->setAddress(address);
 
267
        return;
 
268
    } else if (key.compare("district", Qt::CaseSensitive) ==0 ){
 
269
        QGeoAddress address = landmark->address();
 
270
        address.setDistrict(value.toString());
 
271
        landmark->setAddress(address);
 
272
        return;
 
273
    } else if (key.compare("street", Qt::CaseSensitive) ==0 ){
 
274
        QGeoAddress address = landmark->address();
 
275
        address.setStreet(value.toString());
 
276
        landmark->setAddress(address);
 
277
        return;
 
278
    } else if (key.compare("postcode", Qt::CaseSensitive) ==0 ){
 
279
        QGeoAddress address = landmark->address();
 
280
        address.setPostcode(value.toString());
 
281
        landmark->setAddress(address);
 
282
        return;
 
283
    }
 
284
    Q_ASSERT(false);//it shouldn't be possible to get here
 
285
}
 
286
 
138
287
/*
139
288
    \internal
140
289
    Returns true if value is in between min and max(inclusive of min and max)
213
362
 
214
363
    if (a.isValid()) {
215
364
        if (b.isValid()) {
216
 
            double da = c.distanceTo(a);
217
 
            double db = c.distanceTo(b);
 
365
            qreal da = c.distanceTo(a);
 
366
            qreal db = c.distanceTo(b);
218
367
 
219
368
            if (qFuzzyCompare(da,db)) {
220
369
                result = 0;
262
411
    QList<LandmarkPoint>  sortedPoints;
263
412
    LandmarkPoint point;
264
413
 
265
 
    double radius = proximityFilter.radius();
266
 
    QGeoCoordinate center = proximityFilter.coordinate();
 
414
    qreal radius = proximityFilter.radius();
 
415
    QGeoCoordinate center = proximityFilter.center();
267
416
 
268
417
    while(query->next()) {
269
418
        if (queryRun && queryRun->isCanceled) {
278
427
        point.landmarkId.setManagerUri(managerUri);
279
428
        point.landmarkId.setLocalId(QString::number(query->value(0).toInt()));
280
429
 
281
 
        if (radius == -1 || (point.coordinate.distanceTo(center) < radius)
282
 
            || qFuzzyCompare((double)(point.coordinate.distanceTo(center)), radius)) {
 
430
        if (radius < 0 || (point.coordinate.distanceTo(center) < radius)
 
431
            || qFuzzyCompare(point.coordinate.distanceTo(center), radius)) {
283
432
            addSortedPoint(&sortedPoints,point,center);
284
433
        }
285
434
    }
286
435
 
287
436
    for (int i=0;i < sortedPoints.count(); ++i) {
288
437
        result << sortedPoints.at(i).landmarkId;
289
 
        if (i==0 && proximityFilter.selection() == QLandmarkProximityFilter::SelectNearestOnly)
290
 
            break;
291
438
    }
292
439
    return result;
293
440
}
301
448
    bool success = false;
302
449
    enum {Prepare =0 , Execute=1};
303
450
    for(int stage=Prepare; stage <= Execute; ++stage) {
304
 
        if ( stage == Prepare)
305
 
            success = query->prepare(statement);
306
 
        else // stage == Execute
307
 
            success = query->exec();
 
451
        if ( stage == Prepare) {
 
452
            if (bindValues.count() != 0)
 
453
                success = query->prepare(statement);
 
454
            else
 
455
                 success = true;
 
456
        }
 
457
        else { // stage == Execute
 
458
            if (bindValues.count() != 0)
 
459
                success = query->exec();
 
460
            else
 
461
                success = query->exec(statement);
 
462
        }
308
463
 
309
464
        if (!success) {
310
465
            QString errorText;
343
498
        }
344
499
 
345
500
        QStringList keys = bindValues.keys();
346
 
        if (stage == Prepare) {
 
501
        if (stage == Prepare && bindValues.count()!=0) {
347
502
            foreach(const QString &key, keys)
348
503
                query->bindValue(QString(":") + key,bindValues.value(key));
349
504
        }
354
509
    return true;
355
510
}
356
511
 
357
 
QString queryStringForRadius(const QGeoCoordinate &coord, double radius)
 
512
QString queryStringForRadius(const QGeoCoordinate &coord, qreal radius)
358
513
{
 
514
    Q_UNUSED(radius);
359
515
    return "SELECT id, latitude, longitude FROM landmark;";
360
516
}
361
517
 
424
580
    return queryString;
425
581
}
426
582
 
427
 
QString landmarkIdsNearestQueryString(const QLandmarkProximityFilter &filter)
428
 
{
429
 
   return QString("SELECT id, latitude, longitude FROM landmark ");
430
 
}
431
 
 
432
583
bool removeLandmarkHelper(const QString &connectionName, const QLandmarkId &landmarkId,
433
584
        QLandmarkManager::Error *error,
434
585
        QString *errorString,
435
586
        const QString &managerUri)
436
587
{
 
588
    Q_ASSERT(error);
 
589
    Q_ASSERT(errorString);
 
590
 
437
591
    if (landmarkId.managerUri() != managerUri) {
438
592
        if (error)
439
 
            *error = QLandmarkManager::BadArgumentError;
 
593
            *error = QLandmarkManager::LandmarkDoesNotExistError;
440
594
        if (errorString)
441
595
            *errorString = "Landmark id comes from different landmark manager.";
442
596
        return false;
448
602
    QSqlQuery query(q0, db);
449
603
    if (!query.next()) {
450
604
        if (error)
451
 
            *error = QLandmarkManager::DoesNotExistError;
 
605
            *error = QLandmarkManager::LandmarkDoesNotExistError;
452
606
         if (errorString)
453
607
            *errorString = QString("Landmark with local id, %1, does not exist in database").arg(landmarkId.localId());
454
608
        return false;
458
612
    queryStrings << "DELETE FROM landmark WHERE id = :lmId;";
459
613
    queryStrings << "DELETE FROM landmark_category WHERE landmarkId = :lmId;";
460
614
    queryStrings << "DELETE FROM landmark_attribute WHERE landmarkId=:lmId";
461
 
    queryStrings << "DELETE FROM landmark_custom_attribute WHERE landmarkId=:lmId";
462
615
 
463
616
    foreach(const QString &queryString, queryStrings) {
464
617
        if(!query.prepare(queryString)) {
480
633
        }
481
634
 
482
635
    }
 
636
    *error = QLandmarkManager::NoError;
 
637
    *errorString ="";
483
638
    return true;
484
639
}
485
640
 
496
651
 
497
652
using namespace DatabaseOperationsHelpers;
498
653
 
499
 
DatabaseOperations::DatabaseOperations(const volatile bool &isExtendedAttribsEnabled, const volatile bool &isCustomAttribsEnabled)
 
654
DatabaseOperations::DatabaseOperations()
500
655
    : connectionName(QString()),
501
656
    managerUri(QString()),
502
 
    queryRun(0),
503
 
    isExtendedAttributesEnabled(isExtendedAttribsEnabled),
504
 
    isCustomAttributesEnabled(isCustomAttribsEnabled)
 
657
    queryRun(0)
505
658
{
506
659
}
507
660
 
511
664
{
512
665
    Q_ASSERT(error);
513
666
    Q_ASSERT(errorString);
514
 
    *error = QLandmarkManager::NoError;
515
 
    *errorString ="";
516
667
 
517
668
    //it is assumed the connection name is valid when this call is made.
518
669
    QSqlDatabase db = QSqlDatabase::database(connectionName,false);
520
671
    QString uri = managerUri;
521
672
    if (landmarkId.managerUri() != uri) {
522
673
        if (error)
523
 
            *error = QLandmarkManager::BadArgumentError;
 
674
            *error = QLandmarkManager::LandmarkDoesNotExistError;
524
675
        if (errorString)
525
676
            *errorString = "Landmark id comes from different landmark manager.";
526
677
        return QLandmark();
527
678
    }
528
679
 
529
680
    if (landmarkId.localId().isEmpty()) {
530
 
        *error = QLandmarkManager::BadArgumentError;
 
681
        *error = QLandmarkManager::LandmarkDoesNotExistError;
531
682
        *errorString = "Landmark local id is empty";
532
683
        return QLandmark();
533
684
    }
639
790
 
640
791
        query2.clear();
641
792
        query2.finish();
 
793
 
642
794
        QMap<QString,QVariant> bindValues;
643
795
        bindValues.insert("lmId", landmarkId.localId());
644
796
        if (!executeQuery(&query2,"SELECT key,value FROM landmark_attribute WHERE landmarkId = :lmId",bindValues,error,errorString)){
648
800
        while(query2.next()) {
649
801
            QString key = query2.value(0).toString();
650
802
            if (coreGenericAttributes.contains(key)) {
651
 
                lm.setAttribute(key, query2.value(1));
652
 
            } else if (extendedGenericAttributes.contains(key) && isExtendedAttributesEnabled) {
653
 
                lm.setAttribute(key, query2.value(1));
 
803
                //TODO: optimization
 
804
                setLandmarkAttribute(&lm, key, query2.value(1));
654
805
            } else {
655
806
                qWarning() << "Database is corrupt it contains an unrecognised generic key: " << key;
656
807
            }
657
808
        }
658
809
 
659
 
        if (DatabaseOperations::isCustomAttributesEnabled) {
660
 
            QSqlQuery query(db);
661
 
            if (!query.prepare("SELECT key, value from landmark_custom_attribute WHERE landmarkId=:lmId")) {
662
 
                *error = QLandmarkManager::UnknownError;
663
 
                *errorString = QString("Query Failed: \n Query: %1 \n Reason: %2").arg(query.lastQuery()).arg(query.lastError().text());
664
 
                return QLandmark();
665
 
            }
666
 
 
667
 
            query.bindValue(":lmId", lm.landmarkId().localId());
668
 
 
669
 
            if (!query.exec()) {
670
 
                *error = QLandmarkManager::UnknownError;
671
 
                *errorString = QString("Query Failed: \n Query: %1 \n Reason: %2").arg(query.lastQuery()).arg(query.lastError().text());
672
 
                return QLandmark();
673
 
            }
674
 
 
675
 
            while(query.next()) {
676
 
                lm.setCustomAttribute(query.value(0).toString(),query.value(1));
677
 
            }
678
 
        }
679
 
 
680
810
        if (error)
681
811
            *error = QLandmarkManager::NoError;
682
812
        if (errorString)
685
815
    } else {
686
816
        Q_ASSERT(error);
687
817
        Q_ASSERT(errorString);
688
 
        *error = QLandmarkManager::DoesNotExistError;
 
818
        *error = QLandmarkManager::LandmarkDoesNotExistError;
689
819
        *errorString = QString("Landmark with id, %1, does not exist.").arg(landmarkId.localId());
690
820
    }
691
821
 
706
836
    QList<QLandmarkId> result;
707
837
    bool alreadySorted = false;
708
838
 
 
839
    for (int i=0; i < sortOrders.count(); ++i) {
 
840
        if (sortOrders.at(i).type() == QLandmarkSortOrder::NameSort) {
 
841
            QLandmarkNameSort nameSort = sortOrders.at(i);
 
842
            if (nameSort.caseSensitivity() == Qt::CaseSensitive) {
 
843
                *error = QLandmarkManager::NotSupportedError;
 
844
                *errorString = "Case sensitive sorting is not supported";
 
845
                return QList<QLandmarkId>();
 
846
            }
 
847
 
 
848
        }
 
849
    }
 
850
 
709
851
    QSqlDatabase db = QSqlDatabase::database(connectionName, false);
710
852
    if (!db.isValid()) {
711
853
        if(error)
743
885
                QList<QLandmarkId> lmIds;
744
886
 
745
887
                bool selectAll =false;
746
 
                if (attributeFilter.attributeType() ==  QLandmarkAttributeFilter::ManagerAttributes) {
747
 
                    foreach(const QString key, filterKeys) {
748
 
                        if (!supportedSearchableAttributes.contains(key)) {
749
 
                            *error = QLandmarkManager::NotSupportedError;
750
 
                            *errorString = QString("Attribute key not searchable: ").arg(key);
751
 
                            return QList<QLandmarkId>();
752
 
                        }
 
888
 
 
889
                foreach(const QString key, filterKeys) {
 
890
                    if (!supportedSearchableAttributes.contains(key)) {
 
891
                        *error = QLandmarkManager::NotSupportedError;
 
892
                        *errorString = QString("Attribute key not searchable: ").arg(key);
 
893
                        return QList<QLandmarkId>();
753
894
                    }
754
 
                    QVariant attributeValue;
 
895
                }
 
896
                QVariant attributeValue;
755
897
 
756
 
                    //try to see if we need to select all landmarks
757
 
                    //ie OR operation with a single invalid QVariant parameter
758
 
                    //AND operation with all invalid QVariant parameter
759
 
                    for ( int i = 0; i < filterKeys.count(); ++i) {
760
 
                        key = filterKeys.at(i);
761
 
                        attributeValue = attributeFilter.attribute(key).toString();
762
 
                        if (!attributeFilter.attribute(key).isValid()) {
763
 
                            if( attributeFilter.operationType() == QLandmarkAttributeFilter::OrOperation) {
764
 
                                selectAll = true;
765
 
                                break;
766
 
                            } else {
767
 
                                selectAll = true;
768
 
                                continue;
769
 
                            }
 
898
                //try to see if we need to select all landmarks
 
899
                //ie OR operation with a single invalid QVariant parameter
 
900
                //AND operation with all invalid QVariant parameter
 
901
                for ( int i = 0; i < filterKeys.count(); ++i) {
 
902
                    key = filterKeys.at(i);
 
903
                    attributeValue = attributeFilter.attribute(key).toString();
 
904
                    if (!attributeFilter.attribute(key).isValid()) {
 
905
                        if( attributeFilter.operationType() == QLandmarkAttributeFilter::OrOperation) {
 
906
                            selectAll = true;
 
907
                            break;
770
908
                        } else {
771
 
                            if (attributeFilter.operationType() == QLandmarkAttributeFilter::OrOperation)
772
 
                                continue;
773
 
                            else{
774
 
                                selectAll = false;
775
 
                                break;
776
 
                            }
 
909
                            selectAll = true;
 
910
                            continue;
 
911
                        }
 
912
                    } else {
 
913
                        if (attributeFilter.operationType() == QLandmarkAttributeFilter::OrOperation)
 
914
                            continue;
 
915
                        else{
 
916
                            selectAll = false;
 
917
                            break;
777
918
                        }
778
919
                    }
779
920
                }
785
926
                } else {
786
927
                    if (attributeFilter.operationType() == QLandmarkAttributeFilter::AndOperation) {
787
928
                        QStringList lmLocalIds;
788
 
                        if (attributeFilter.attributeType() ==  QLandmarkAttributeFilter::ManagerAttributes
789
 
                            && attributeFilter.attributeKeys().contains("name")) {
 
929
                        if (attributeFilter.attributeKeys().contains("name")) {
790
930
                            QLandmarkNameFilter nameFilter;
791
931
                            nameFilter.setName(attributeFilter.attribute("name").toString());
792
932
                            nameFilter.setMatchFlags(attributeFilter.matchFlags("name"));
803
943
                        } else {
804
944
                            bindValues.insert("key", filterKeys.at(0));
805
945
                            queryString = QString("SELECT landmarkId FROM %1 WHERE key = :key");
806
 
 
807
 
                            if (attributeFilter.attributeType() ==  QLandmarkAttributeFilter::ManagerAttributes)
808
 
                                queryString = queryString.arg("landmark_attribute");
809
 
                            else
810
 
                                queryString = queryString.arg("landmark_custom_attribute");
 
946
                            queryString = queryString.arg("landmark_attribute");
811
947
 
812
948
                            if (!executeQuery(&query, queryString,
813
949
                                              bindValues,error,errorString)) {
824
960
                            id.setManagerUri(managerUri);
825
961
 
826
962
                            queryString = QString("SELECT key, value FROM %1 WHERE landmarkId=:lmId");
827
 
                            if (attributeFilter.attributeType() == QLandmarkAttributeFilter::ManagerAttributes)
828
 
                                queryString = queryString.arg("landmark_attribute");
829
 
                            else
830
 
                                queryString = queryString.arg("landmark_custom_attribute");
831
 
 
 
963
                            queryString = queryString.arg("landmark_attribute");
832
964
 
833
965
                            for (int i=0; i < lmLocalIds.count(); ++i) {
834
966
                                bindValues.clear();
891
1023
                            }
892
1024
                        }
893
1025
                    } else {
894
 
                        if (attributeFilter.attributeType() ==  QLandmarkAttributeFilter::ManagerAttributes
895
 
                            && attributeFilter.attributeKeys().contains("name")) {
 
1026
                        if (attributeFilter.attributeKeys().contains("name")) {
896
1027
                            QLandmarkNameFilter nameFilter;
897
1028
                            nameFilter.setName(attributeFilter.attribute("name").toString());
898
1029
                            nameFilter.setMatchFlags(attributeFilter.matchFlags("name"));
906
1037
                        }
907
1038
 
908
1039
                        queryString = QString("SELECT landmarkId FROM %1 WHERE ");
909
 
                        if (attributeFilter.attributeType() == QLandmarkAttributeFilter::ManagerAttributes)
910
 
                            queryString = queryString.arg("landmark_attribute");
911
 
                        else
912
 
                            queryString = queryString.arg("landmark_custom_attribute");
 
1040
                        queryString = queryString.arg("landmark_attribute");
913
1041
 
914
1042
                        QVariant attributeValue;
915
1043
                        for (int i=0; i < filterKeys.count(); ++i) {
970
1098
    case QLandmarkFilter::NameFilter: {
971
1099
            QLandmarkNameFilter nameFilter;
972
1100
            nameFilter = filter;
973
 
            if (DatabaseOperations::filterSupportLevel(nameFilter)== QLandmarkManager::None) {
 
1101
            if (DatabaseOperations::filterSupportLevel(nameFilter)== QLandmarkManager::NoSupport) {
974
1102
                *error = QLandmarkManager::NotSupportedError;
975
1103
                *errorString = "The name filter's configuration is not supported";
976
1104
                return result;
980
1108
            QString nameKey = "name";
981
1109
            QString nameValue = nameFilter.name();
982
1110
 
983
 
            if (nameFilter.matchFlags() == QLandmarkFilter::MatchExactly) {
 
1111
            if (nameValue.isEmpty()) {
 
1112
                    if (nameFilter.matchFlags() == QLandmarkFilter::MatchExactly
 
1113
                        || nameFilter.matchFlags() == QLandmarkFilter::MatchFixedString) {
 
1114
                        queryString.append(nameKey + " IS NULL ");
 
1115
                    } else {
 
1116
                        queryString = "SELECT id from landmark ";
 
1117
                    }
 
1118
            } else if (nameFilter.matchFlags() == QLandmarkFilter::MatchExactly) {
984
1119
                queryString.append(nameKey + " = :" + nameKey + " ");
985
1120
                bindValues.insert(nameKey, nameValue);
986
1121
            } else {
999
1134
        }
1000
1135
    case QLandmarkFilter::LandmarkIdFilter: {
1001
1136
            QLandmarkIdFilter idFilter = filter;
1002
 
            if (sortOrders.length() == 1
1003
 
                && sortOrders.at(0).type() == QLandmarkSortOrder::NameSort) {
1004
1137
                //provide a query string exeecute so to that sqlite can handle sorting by name
1005
1138
                queryString = landmarkIdsQueryString(idFilter.landmarkIds());
1006
 
            } else {
1007
 
                result = idFilter.landmarkIds();
1008
 
                idsFound = true;
1009
 
            }
1010
1139
            break;
1011
1140
        }
1012
1141
    case QLandmarkFilter::CategoryFilter: {
 
1142
        QSqlQuery query(db);
 
1143
        QMap<QString, QVariant> bindValues;
1013
1144
        QLandmarkCategoryFilter categoryFilter = filter;
 
1145
        QLandmarkCategoryId categoryId = categoryFilter.categoryId();
 
1146
 
 
1147
        if (categoryId.managerUri() != managerUri) {
 
1148
            *error = QLandmarkManager::NoError;
 
1149
            *errorString = "";
 
1150
            return result;
 
1151
        } else if (categoryId.localId().isEmpty()) {
 
1152
            *error = QLandmarkManager::NoError;
 
1153
            *errorString = "";
 
1154
            return result;
 
1155
        }
 
1156
        bindValues.clear();
 
1157
        bindValues.insert("catId",categoryId.localId());
 
1158
        if (!executeQuery(&query,"SELECT * from category WHERE id = :catId", bindValues, error, errorString)){
 
1159
            return result;
 
1160
        }
 
1161
 
 
1162
        if (!query.next()) {
 
1163
            *error = QLandmarkManager::NoError;
 
1164
            *errorString = "";
 
1165
            return result;
 
1166
        }
 
1167
 
1014
1168
        queryString = landmarkIdsCategoryQueryString(categoryFilter);
1015
1169
        break;
1016
1170
        }
1017
1171
    case QLandmarkFilter::ProximityFilter: {
1018
1172
            QLandmarkProximityFilter proximityFilter = filter;
 
1173
            QGeoCoordinate center = proximityFilter.center();
 
1174
            if ( (qIsNaN(center.latitude()) || qIsNaN(center.longitude())
 
1175
                || !isValidLat(center.latitude()) || !isValidLong(center.longitude()))
 
1176
                ) {
 
1177
                *error = QLandmarkManager::BadArgumentError;
 
1178
                *errorString = "Center coordinate of proximity filter is invalid";
 
1179
                return result;
 
1180
            }
 
1181
 
1019
1182
            if (proximityFilter.radius() < 0) {
1020
 
                if (proximityFilter.selection() == QLandmarkProximityFilter::SelectNearestOnly) {
1021
 
                    queryString = ::landmarkIdsNearestQueryString(proximityFilter);
1022
 
                } else {
1023
 
                    queryString =  ::landmarkIdsDefaultQueryString();
1024
 
                }
 
1183
                queryString =  ::landmarkIdsDefaultQueryString();
1025
1184
                break;
1026
1185
            }
1027
1186
           //fall through if we have a radius, we can use a box filter
1033
1192
                boxFilter = filter;
1034
1193
            } else {
1035
1194
                QGeoCoordinate center;
1036
 
                double radius;
 
1195
                double radius; //use double since these are going to be usd in calculation with lat/long
1037
1196
                if(filter.type() == QLandmarkFilter::ProximityFilter) {
1038
1197
                    QLandmarkProximityFilter proximityFilter;
1039
1198
                    proximityFilter = filter;
1040
 
                    center = proximityFilter.coordinate();
 
1199
                    center = proximityFilter.center();
1041
1200
                    radius = proximityFilter.radius();
1042
1201
                }
1043
1202
 
1124
1283
            if (filters.size() == 0) {
1125
1284
                //do nothing
1126
1285
            } else if (filters.size() == 1) {
1127
 
                result = landmarkIds( filters.at(0), QList<QLandmarkSortOrder>(), limit, offset, error, errorString);
 
1286
                result = landmarkIds( filters.at(0), QList<QLandmarkSortOrder>(), -1, 0, error, errorString);
1128
1287
                if (*error != QLandmarkManager::NoError) {
1129
1288
                    result.clear();
1130
1289
                    return result;
1144
1303
 
1145
1304
                QSet<QLandmarkId> ids;
1146
1305
                QList<QLandmarkId> firstResult = landmarkIds(filters.at(0),
1147
 
                                                QList<QLandmarkSortOrder>(), limit, offset, error, errorString);
 
1306
                                                QList<QLandmarkSortOrder>(), -1, 0, error, errorString);
1148
1307
                ids = firstResult.toSet();
1149
1308
 
1150
1309
                for (int i = 1; i < filters.size(); ++i) {
1156
1315
                    }
1157
1316
 
1158
1317
                    QList<QLandmarkId> subResult = landmarkIds(filters.at(i),
1159
 
                                                QList<QLandmarkSortOrder>(), limit, offset, error, errorString);
 
1318
                                                QList<QLandmarkSortOrder>(), -1, 0, error, errorString);
1160
1319
 
1161
1320
                    if (*error != QLandmarkManager::NoError) {
1162
1321
                        result.clear();
1197
1356
                //do nothing
1198
1357
            } else if (filters.size() == 1) {
1199
1358
                result =  landmarkIds(filters.at(0),
1200
 
                                        QList<QLandmarkSortOrder>(), limit, offset, error, errorString);
 
1359
                                        QList<QLandmarkSortOrder>(), -1, 0, error, errorString);
1201
1360
                if (*error != QLandmarkManager::NoError) {
1202
1361
                    result.clear();
1203
1362
                    return result;
1212
1371
                    }
1213
1372
                    QList<QLandmarkId> subResult = landmarkIds(filters.at(i),
1214
1373
                                                               QList<QLandmarkSortOrder>(),
1215
 
                                                               limit, offset,
 
1374
                                                               -1, 0,
1216
1375
                                                               error, errorString);
1217
1376
 
1218
1377
                    if (*error != QLandmarkManager::NoError) {
1423
1582
        QLandmarkManager::Error *error,
1424
1583
        QString *errorString)  const
1425
1584
{
 
1585
    if (errorMap)
 
1586
        errorMap->clear();
 
1587
 
1426
1588
    QList<QLandmark> result;
1427
1589
    QLandmark lm;
1428
1590
    QLandmarkManager::Error lastError = QLandmarkManager::NoError;
1451
1613
{
1452
1614
    Q_ASSERT(error);
1453
1615
    Q_ASSERT(errorString);
1454
 
    *error = QLandmarkManager::NoError;
1455
 
    *errorString="";
1456
1616
 
1457
1617
    if (!landmark->landmarkId().managerUri().isEmpty() && landmark->landmarkId().managerUri() != managerUri) {
1458
1618
        if (error)
1459
 
            *error = QLandmarkManager::DoesNotExistError;
 
1619
            *error = QLandmarkManager::LandmarkDoesNotExistError;
1460
1620
        if (errorString)
1461
1621
            *errorString = "Landmark id comes from different landmark manager.";
1462
1622
        return false;
1463
1623
    }
1464
1624
 
1465
 
    if ((landmark->customAttributeKeys().count() > 0) && (!DatabaseOperations::isCustomAttributesEnabled))
1466
 
    {
1467
 
        *error = QLandmarkManager::BadArgumentError;
1468
 
        *errorString = "Landmark contains custom attributes but the manager does not support "
1469
 
                 "them or has them enabled";
1470
 
        return false;
1471
 
    }
1472
 
 
1473
1625
    bool update = landmark->landmarkId().isValid();
1474
1626
 
1475
1627
    QSqlDatabase db = QSqlDatabase::database(connectionName);
1483
1635
        QSqlQuery query0(q0, db);
1484
1636
        if (!query0.next()) {
1485
1637
            if (error)
1486
 
                *error = QLandmarkManager::DoesNotExistError;
 
1638
                *error = QLandmarkManager::LandmarkDoesNotExistError;
1487
1639
            if (errorString)
1488
1640
                *errorString = "Landmark id does not exist in this landmark manager.";
1489
1641
 
1490
1642
            return false;
1491
1643
        }
1492
1644
    }
1493
 
 
1494
 
    QStringList landmarkAttributes = landmark->attributeKeys();
1495
 
    foreach (const QString &key, landmarkAttributes) {
1496
 
        if (!coreAttributes.contains(key) && !coreGenericAttributes.contains(key)) {
1497
 
            if (isExtendedAttributesEnabled && !extendedGenericAttributes.contains(key)) {
1498
 
                *error = QLandmarkManager::NotSupportedError;
1499
 
                *errorString = QString("The manager does not recognise the following key:") + key;
1500
 
                return false;
1501
 
            }
1502
 
        }
1503
 
    }
1504
 
 
1505
1645
    if (!landmark->name().isEmpty())
1506
1646
        bindValues.insert("name", landmark->name());
1507
1647
    else
1509
1649
 
1510
1650
    QGeoCoordinate coord;
1511
1651
    coord = landmark->coordinate();
1512
 
    if (!qIsNaN(coord.latitude()))
 
1652
 
 
1653
    if (qIsNaN(coord.latitude()) && qIsNaN(coord.longitude())) {
 
1654
        bindValues.insert("latitude", QVariant());
 
1655
        bindValues.insert("longitude", QVariant());
 
1656
    } else if (!qIsNaN(coord.latitude()) && !qIsNaN(coord.longitude())
 
1657
        && isValidLat(coord.latitude()) && isValidLong(coord.longitude())) {
1513
1658
        bindValues.insert("latitude", coord.latitude());
1514
 
    else
1515
 
        bindValues.insert("latitude", QVariant());
1516
 
 
1517
 
    if (!qIsNaN(coord.longitude()))
1518
1659
        bindValues.insert("longitude", coord.longitude());
1519
 
    else
1520
 
        bindValues.insert("longitude", QVariant());
 
1660
    } else {
 
1661
        *error = QLandmarkManager::BadArgumentError;
 
1662
        *errorString = "Landmark coordinate is not valid, latitude must between -90 and 90 and longitude must be between -180 and 180, or both "
 
1663
                       "latitude and longitude are NaN";
 
1664
        return false;
 
1665
    }
1521
1666
 
1522
1667
    if (!qIsNaN(coord.altitude()))
1523
1668
        bindValues.insert("altitude", coord.altitude());
1569
1714
        QLandmarkCategoryId id = landmark->categoryIds().at(i);
1570
1715
        if (id.managerUri() == managerUri)
1571
1716
            lmCats << id.localId();
1572
 
        else
1573
 
            landmark->removeCategoryId(id);
 
1717
        else {
 
1718
            *error = QLandmarkManager::CategoryDoesNotExistError;
 
1719
            *errorString = "Landmark contains category that belongs to another manager";
 
1720
            return false;
 
1721
        }
 
1722
 
1574
1723
    }
1575
1724
 
1576
1725
    QStringList queries;
1586
1735
 
1587
1736
        if (!catQuery.next()) {
1588
1737
            if (error)
1589
 
                *error = QLandmarkManager::BadArgumentError;
 
1738
                *error = QLandmarkManager::CategoryDoesNotExistError;
1590
1739
            if (errorString)
1591
1740
                *errorString = "Landmark contains a category id that does not exist";
1592
1741
            return false;
1619
1768
    }
1620
1769
 
1621
1770
    QStringList attributeKeys = coreGenericAttributes;
1622
 
    if (this->isExtendedAttributesEnabled)
1623
 
        attributeKeys << extendedGenericAttributes;
1624
 
 
1625
1771
    QSqlQuery query(db);
1626
1772
 
1627
1773
    foreach(const QString &key, attributeKeys) {
1628
 
        if (!landmark->attributeKeys().contains(key))
1629
 
            continue;
1630
1774
        if (!query.prepare("REPLACE INTO landmark_attribute (landmarkId,key,value) VALUES(:lmId,:key,:value)")) {
1631
1775
            *error = QLandmarkManager::UnknownError;
1632
1776
            *errorString = QString("Unable to prepare statement: %1 \nReason: %2")
1636
1780
 
1637
1781
        query.bindValue(":lmId", landmark->landmarkId().localId());
1638
1782
        query.bindValue(":key", key);
1639
 
        query.bindValue(":value", landmark->attribute(key));
1640
 
 
1641
 
        if (!query.exec()) {
1642
 
            *error = QLandmarkManager::UnknownError;
1643
 
            *errorString = QString("Unable to execute statement: %1\nReason:%2")
1644
 
                           .arg(query.lastQuery()).arg(query.lastError().text());
1645
 
            return false;
1646
 
        }
1647
 
    }
1648
 
 
1649
 
    attributeKeys= landmark->customAttributeKeys();
1650
 
 
1651
 
    if( !query.prepare("DELETE FROM landmark_custom_attribute WHERE landmarkId= :lmId"))
1652
 
    {
1653
 
        *error = QLandmarkManager::UnknownError;
1654
 
        *errorString = QString("Unable to prepare statement: %1 \nReason: %2")
1655
 
                       .arg(query.lastQuery()).arg(query.lastError().text());
1656
 
        return false;
1657
 
    }
1658
 
 
1659
 
    query.bindValue(":lmId", landmark->landmarkId().localId());
1660
 
 
1661
 
    if (!query.exec()) {
1662
 
        *error = QLandmarkManager::UnknownError;
1663
 
        *errorString = QString("Unable to execute statement: %1\nReason:%2")
1664
 
                       .arg(query.lastQuery()).arg(query.lastError().text());
1665
 
        return false;
1666
 
    }
1667
 
 
1668
 
    for (int i =0; i < attributeKeys.count(); ++i) {
1669
 
        if (!query.prepare("INSERT INTO landmark_custom_attribute (landmarkId,key,value) VALUES(:lmId,:key,:value)")) {
1670
 
            *error = QLandmarkManager::UnknownError;
1671
 
            *errorString = QString("Unable to prepare statement: %1 \nReason: %2")
1672
 
                           .arg(query.lastQuery()).arg(query.lastError().text());
1673
 
            return false;
1674
 
        }
1675
 
 
1676
 
        query.bindValue(":lmId", landmark->landmarkId().localId());
1677
 
        query.bindValue(":key", attributeKeys[i]);
1678
 
        query.bindValue(":value", landmark->customAttribute(attributeKeys.at(i)));
1679
 
 
1680
 
        if (!query.exec()) {
1681
 
            *error = QLandmarkManager::UnknownError;
1682
 
            *errorString = QString("Unable to execute statement: %1\nReason:%2")
1683
 
                           .arg(query.lastQuery()).arg(query.lastError().text());
1684
 
            return false;
1685
 
        }
1686
 
    }
1687
 
 
1688
 
    /*
1689
 
    // grab keys from attributes tables for current id
1690
 
    // delete those we no longer have
1691
 
    // use replace for the rest
1692
 
 
1693
 
    // loop through attributes
1694
 
    */
1695
 
 
 
1783
        query.bindValue(":value", getLandmarkAttribute(landmark, key));
 
1784
 
 
1785
        if (!query.exec()) {
 
1786
            *error = QLandmarkManager::UnknownError;
 
1787
            *errorString = QString("Unable to execute statement: %1\nReason:%2")
 
1788
                           .arg(query.lastQuery()).arg(query.lastError().text());
 
1789
            return false;
 
1790
        }
 
1791
    }
 
1792
 
 
1793
    *error = QLandmarkManager::NoError;
 
1794
    *errorString="";
1696
1795
    return true;
1697
1796
}
1698
1797
 
1723
1822
{
1724
1823
    Q_ASSERT(error);
1725
1824
    Q_ASSERT(errorString);
 
1825
    if (errorMap)
 
1826
        errorMap->clear();
1726
1827
 
1727
1828
    QSqlDatabase db = QSqlDatabase::database(connectionName);
1728
1829
    if (!db.transaction()) {
1820
1921
{
1821
1922
    Q_ASSERT(error);
1822
1923
    Q_ASSERT(errorString);
 
1924
    if (errorMap)
 
1925
        errorMap->clear();
1823
1926
 
1824
1927
    QSqlDatabase db = QSqlDatabase::database(connectionName);
1825
1928
    if (!db.transaction()) {
1906
2009
    QString queryString("SELECT id FROM category ORDER BY name ");
1907
2010
    if (nameSort.caseSensitivity() == Qt::CaseInsensitive)
1908
2011
        queryString.append("COLLATE NOCASE ");
 
2012
    else {
 
2013
        *error = QLandmarkManager::NotSupportedError;
 
2014
        *errorString = "Case sensitive name sorting of categories is not supported";
 
2015
        return QList<QLandmarkCategoryId>();
 
2016
    }
1909
2017
 
1910
2018
    if (nameSort.direction() == Qt::AscendingOrder)
1911
2019
        queryString.append("ASC;");
1957
2065
{
1958
2066
    if (!landmarkCategoryId.isValid() || landmarkCategoryId.managerUri() != managerUri) {
1959
2067
        if (error)
1960
 
            *error = QLandmarkManager::BadArgumentError;
 
2068
            *error = QLandmarkManager::CategoryDoesNotExistError;
1961
2069
        if (errorString)
1962
2070
            *errorString = "Category id is not valid for this manager";
1963
2071
        return QLandmarkCategory();
1999
2107
    }
2000
2108
 
2001
2109
    if (!found) {
2002
 
        if (error)
2003
 
            *error = QLandmarkManager::DoesNotExistError;
2004
 
        if (errorString)
 
2110
            *error = QLandmarkManager::CategoryDoesNotExistError;
2005
2111
            *errorString = "None of the existing categories match the given category id.";
2006
2112
    } else {
2007
2113
        query.finish();
2015
2121
        while(query.next()) {
2016
2122
            QString key = query.value(0).toString();
2017
2123
            if (coreGenericCategoryAttributes.contains(key)) {
2018
 
                cat.setAttribute(key, query.value(1));
2019
 
            } else if (extendedGenericCategoryAttributes.contains(key) && isExtendedAttributesEnabled) {
2020
 
                cat.setAttribute(key, query.value(1));
 
2124
                setCategoryAttribute(&cat,key,query.value(1));
2021
2125
            } else {
2022
2126
                qWarning() << "Database is corrupt it contains an unrecognised generic key: " << key;
2023
2127
            }
2024
2128
        }
2025
2129
 
2026
 
        if (DatabaseOperations::isCustomAttributesEnabled) {
2027
 
            bindValues.insert("catId", cat.categoryId().localId());
2028
 
            if (!executeQuery(&query, "SELECT key, value from category_custom_attribute WHERE categoryId=:catId",bindValues, error, errorString )) {
2029
 
                return QLandmarkCategory();
2030
 
            }
2031
 
 
2032
 
            while(query.next()) {
2033
 
                cat.setCustomAttribute(query.value(0).toString(),query.value(1));
2034
 
            }
2035
 
        }
2036
 
 
2037
 
        if (error)
2038
 
            *error = QLandmarkManager::NoError;
2039
 
        if (errorString)
2040
 
            *errorString = "";
 
2130
 
 
2131
        *error = QLandmarkManager::NoError;
 
2132
        *errorString = "";
2041
2133
    }
2042
2134
    return cat;
2043
2135
}
2067
2159
    for (int i = 0; i < ids.size(); ++i) {
2068
2160
        *error = QLandmarkManager::NoError;
2069
2161
        (*errorString).clear();
 
2162
        if (errorString)
2070
2163
 
2071
2164
        if (queryRun && queryRun->isCanceled) {
2072
2165
            *error = QLandmarkManager::CancelError;
2105
2198
                QMap<int, QLandmarkManager::Error> *errorMap,
2106
2199
                QLandmarkManager::Error *error, QString *errorString) const
2107
2200
{
 
2201
    if (errorMap)
 
2202
        errorMap->clear();
2108
2203
    QList<QLandmarkCategory> result;
2109
2204
    QLandmarkCategory cat;
2110
2205
    QLandmarkManager::Error lastError = QLandmarkManager::NoError;
2144
2239
 
2145
2240
    if (!category->categoryId().managerUri().isEmpty() && category->categoryId().managerUri() != managerUri) {
2146
2241
        if (error)
2147
 
            *error = QLandmarkManager::DoesNotExistError;
 
2242
            *error = QLandmarkManager::CategoryDoesNotExistError;
2148
2243
        if (errorString)
2149
2244
            *errorString = "Category id comes from different landmark manager.";
2150
2245
        return false;
2151
2246
    }
2152
2247
 
2153
 
    if ((category->customAttributeKeys().count() >0) && (!DatabaseOperations::isCustomAttributesEnabled))
2154
 
    {
2155
 
        *error = QLandmarkManager::BadArgumentError;
2156
 
        *errorString = "Category contains custom attributes but the manager does not support "
2157
 
                       "them or has them enabled";
2158
 
        return false;
2159
 
    }
2160
 
 
2161
2248
    bool update = category->categoryId().isValid();
2162
2249
 
2163
2250
    QSqlDatabase db = QSqlDatabase::database(connectionName);
2174
2261
 
2175
2262
        if (!query.next()) {
2176
2263
            if (error)
2177
 
                *error = QLandmarkManager::DoesNotExistError;
 
2264
                *error = QLandmarkManager::CategoryDoesNotExistError;
2178
2265
            if (errorString)
2179
2266
                *errorString = "Category id does not exist in this landmark manager.";
2180
2267
 
2234
2321
    bindValues.clear();
2235
2322
    bindValues.insert("catId",category->categoryId().localId());
2236
2323
    QStringList attributeKeys = coreGenericCategoryAttributes;
2237
 
    if (this->isExtendedAttributesEnabled)
2238
 
        attributeKeys << extendedGenericCategoryAttributes;
2239
2324
 
2240
2325
    foreach(const QString &key, attributeKeys) {
2241
 
        if (!category->attributeKeys().contains(key))
2242
 
            continue;
2243
2326
        bindValues.clear();
2244
2327
        bindValues.insert(":catId", category->categoryId().localId());
2245
2328
        bindValues.insert(":key", key);
2246
 
        bindValues.insert(":value", category->attribute(key));
 
2329
        bindValues.insert(":value", getCategoryAttribute(category,key));
2247
2330
        if (!executeQuery(&query, "REPLACE INTO category_attribute(categoryId,key,value) VALUES(:catId,:key,:value)", bindValues,error,errorString)) {
2248
2331
            return false;
2249
2332
        }
2250
2333
    }
2251
2334
 
2252
 
    attributeKeys = category->customAttributeKeys();
2253
 
    bindValues.clear();
2254
 
    bindValues.insert("catId", category->categoryId().localId());
2255
 
    if (!executeQuery(&query,"DELETE FROM category_custom_attribute WHERE categoryId= :catId", bindValues, error, errorString)) {
2256
 
        return false;
2257
 
    }
2258
 
 
2259
 
    for (int i =0; i < attributeKeys.count(); ++i) {
2260
 
        bindValues.clear();
2261
 
        bindValues.insert("catId",category->categoryId().localId());
2262
 
        bindValues.insert("key",attributeKeys[i]);
2263
 
        bindValues.insert("value",category->customAttribute(attributeKeys.at(i)));
2264
 
 
2265
 
        if (!executeQuery(&query,"INSERT INTO category_custom_attribute (categoryId,key,value) VALUES(:catId,:key,:value)", bindValues,
2266
 
                         error, errorString)) {
2267
 
            return false;
2268
 
        }
2269
 
    }
2270
 
 
2271
 
    if (error)
2272
 
        *error = QLandmarkManager::NoError;
2273
 
    if (errorString)
2274
 
        *errorString = "";
 
2335
 
 
2336
    *error = QLandmarkManager::NoError;
 
2337
    *errorString = "";
2275
2338
 
2276
2339
    return true;
2277
2340
}
2300
2363
        QLandmarkManager::Error *error,
2301
2364
        QString *errorString)
2302
2365
{
2303
 
    QList<QLandmarkCategoryId> addedIds;
2304
 
    QList<QLandmarkCategoryId> changedIds;
 
2366
    Q_ASSERT(error);
 
2367
    Q_ASSERT(errorString);
 
2368
    if (errorMap)
 
2369
        errorMap->clear();
 
2370
 
 
2371
 
 
2372
    QSqlDatabase db = QSqlDatabase::database(connectionName);
 
2373
    if (!db.transaction()) {
 
2374
        *error = QLandmarkManager::UnknownError;
 
2375
        *errorString = QString("Save Categories: unable to begin transaction, reason: %1").arg(db.lastError().text());
 
2376
 
 
2377
        if (errorMap) {
 
2378
            for (int i=0; i < categories->size(); ++i)
 
2379
                errorMap->insert(i, *error);
 
2380
        }
 
2381
        return false;
 
2382
    }
 
2383
 
2305
2384
    bool noErrors = true;
2306
2385
    QLandmarkManager::Error lastError = QLandmarkManager::NoError;
2307
2386
    QString lastErrorString;
2308
2387
    QLandmarkManager::Error loopError;
2309
2388
    QString loopErrorString;
 
2389
    bool result;
2310
2390
    for (int i = 0; i < categories->size(); ++i) {
2311
2391
        loopError = QLandmarkManager::NoError;
2312
2392
        loopErrorString = "";
2313
 
        bool added = false;
2314
 
        bool changed = false;
2315
 
 
2316
 
        bool result = saveCategory(&(categories->operator [](i)), &loopError, &loopErrorString);
2317
 
 
2318
 
        if (errorMap)
2319
 
            errorMap->insert(i, loopError);
 
2393
 
 
2394
        if (queryRun && queryRun->isCanceled) {
 
2395
            lastError = QLandmarkManager::CancelError;
 
2396
            lastErrorString = "Category save was canceled";
 
2397
            if (errorMap) {
 
2398
                for (i; i < categories->size(); ++i)
 
2399
                    errorMap->insert(i, lastError);
 
2400
            }
 
2401
            noErrors = false;
 
2402
            break;
 
2403
        }
 
2404
        QSqlQuery query(db);
 
2405
        if (!query.exec("SAVEPOINT save")) {
 
2406
            loopError = QLandmarkManager::UnknownError;
 
2407
            loopErrorString = QString("Save categories: could not execute statement: %1\nReason:%2").arg(query.lastQuery()).arg(query.lastError().text());
 
2408
            result = false;
 
2409
        } else {
 
2410
           result = saveCategoryHelper(&(categories->operator [](i)), &loopError, &loopErrorString);
 
2411
        }
2320
2412
 
2321
2413
        if (!result) {
2322
2414
            noErrors = false;
2323
2415
            lastError = loopError;
2324
2416
            lastErrorString = loopErrorString;
 
2417
 
 
2418
            if (errorMap)
 
2419
                errorMap->insert(i, loopError);
 
2420
            query.exec("ROLLBACK TO SAVEPOINT save");
 
2421
        } else {
 
2422
            query.exec("RELEASE SAVEPOINT save");
2325
2423
        }
2326
 
 
2327
 
        if (added)
2328
 
            addedIds << categories->at(i).categoryId();
2329
 
        if (changed)
2330
 
            changedIds << categories->at(i).categoryId();
2331
2424
    }
2332
2425
 
 
2426
    db.commit();
 
2427
 
2333
2428
    if (noErrors) {
2334
2429
        if (error)
2335
2430
            *error = QLandmarkManager::NoError;
2342
2437
            *errorString = lastErrorString;
2343
2438
    }
2344
2439
 
2345
 
    //TODO: Notifications
2346
 
    //if (addedIds.size() != 0)
2347
 
    //    emit landmarksAdded(addedIds);
2348
 
 
2349
 
    //TODO: Notifications
2350
 
    //if (changedIds.size() != 0)
2351
 
    //    emit landmarksChanged(changedIds);
2352
 
 
2353
2440
    return noErrors;
2354
2441
}
2355
2442
 
2356
2443
bool DatabaseOperations::removeCategory(const QLandmarkCategoryId &categoryId,
 
2444
                                      QLandmarkManager::Error *error, QString *errorString)
 
2445
{
 
2446
    QSqlDatabase db = QSqlDatabase::database(connectionName);
 
2447
    if (!db.transaction()) {
 
2448
        *error = QLandmarkManager::UnknownError;
 
2449
        *errorString = QString("Remove category: unable to begin transaction, reason: %1").arg(db.lastError().text());
 
2450
        return false;
 
2451
    }
 
2452
 
 
2453
    bool result = removeCategoryHelper(categoryId, error, errorString);
 
2454
    if (result)
 
2455
        db.commit();
 
2456
    else
 
2457
        db.rollback();
 
2458
    return result;
 
2459
}
 
2460
 
 
2461
bool DatabaseOperations::removeCategoryHelper(const QLandmarkCategoryId &categoryId,
2357
2462
                QLandmarkManager::Error *error,
2358
2463
                QString *errorString)
2359
2464
{
2361
2466
    Q_ASSERT(errorString);
2362
2467
    if (categoryId.managerUri() != managerUri) {
2363
2468
        if (error)
2364
 
            *error = QLandmarkManager::BadArgumentError;
 
2469
            *error = QLandmarkManager::CategoryDoesNotExistError;
2365
2470
        if (errorString)
2366
2471
            *errorString = "Category id comes from different landmark manager.";
2367
2472
        return false;
2368
2473
    }
2369
2474
 
2370
2475
    QSqlDatabase db = QSqlDatabase::database(connectionName);
2371
 
 
2372
 
    if (!db.transaction()) {
2373
 
        *error = QLandmarkManager::UnknownError;
2374
 
        *errorString = QString("Save landmark: unable to begin transaction, reason: %1").arg(db.lastError().text());
2375
 
        return false;
2376
 
    }
2377
 
 
2378
2476
    QMap<QString,QVariant> bindValues;
2379
2477
    bindValues.insert("catId", categoryId.localId());
2380
2478
    QString q0 = QString("SELECT 1 FROM category WHERE id = :catId");
2381
2479
 
2382
2480
    QSqlQuery query(db);
2383
2481
    if(!executeQuery(&query,q0,bindValues,error,errorString)) {
2384
 
        db.rollback();
2385
2482
        return false;
2386
2483
    }
2387
2484
 
2388
2485
    if (!query.next()) {
2389
 
        db.rollback();
2390
 
        *error = QLandmarkManager::DoesNotExistError;
 
2486
        *error = QLandmarkManager::CategoryDoesNotExistError;
2391
2487
        *errorString = QString("Category with local id %1, does not exist in database")
2392
2488
                        .arg(categoryId.localId());
2393
2489
        return false;
2397
2493
    queryStrings << "DELETE FROM category WHERE id = :catId";
2398
2494
    queryStrings << "DELETE FROM landmark_category WHERE categoryId = :catId";
2399
2495
    queryStrings << "DELETE FROM category_attribute WHERE categoryId= :catId";
2400
 
    queryStrings << "DELETE FROM category_custom_attribute WHERE categoryId= :catId";
2401
2496
 
2402
2497
    foreach(const QString &queryString, queryStrings) {
2403
2498
        if (!executeQuery(&query, queryString, bindValues, error,errorString)) {
2404
 
            db.rollback();
2405
2499
            return false;
2406
2500
        }
2407
2501
    }
2408
2502
 
2409
 
     db.commit();
2410
2503
     *error = QLandmarkManager::NoError;
2411
2504
     *errorString = "";
2412
2505
 
2418
2511
                    QLandmarkManager::Error *error,
2419
2512
                    QString *errorString)
2420
2513
{
2421
 
    QList<QLandmarkCategoryId> removedIds;
 
2514
    Q_ASSERT(error);
 
2515
    Q_ASSERT(errorString);
 
2516
    if (errorMap)
 
2517
        errorMap->clear();
 
2518
 
 
2519
    QSqlDatabase db = QSqlDatabase::database(connectionName);
 
2520
    if (!db.transaction()) {
 
2521
        *error = QLandmarkManager::UnknownError;
 
2522
        *errorString = QString("Remove category: unable to begin transaction, reason: %1").arg(db.lastError().text());
 
2523
 
 
2524
        if (errorMap) {
 
2525
            for (int i=0; i < categoryIds.size(); ++i)
 
2526
                errorMap->insert(i, *error);
 
2527
        }
 
2528
        return false;
 
2529
    }
2422
2530
 
2423
2531
    bool noErrors = true;
2424
2532
    QLandmarkManager::Error lastError = QLandmarkManager::NoError;
2425
2533
    QString lastErrorString;
2426
2534
    QLandmarkManager::Error loopError;
2427
2535
    QString loopErrorString;
 
2536
    bool result;
2428
2537
    for (int i = 0; i < categoryIds.size(); ++i) {
2429
2538
        loopError = QLandmarkManager::NoError;
2430
2539
        loopErrorString.clear();
2431
2540
 
2432
 
        bool result = removeCategory(categoryIds.at(i), &loopError, &loopErrorString);
 
2541
        if (queryRun && queryRun->isCanceled) {
 
2542
            lastError = QLandmarkManager::CancelError;
 
2543
            lastErrorString = "Category remove was canceled";
 
2544
            if (errorMap) {
 
2545
                for (i; i < categoryIds.size(); ++i)
 
2546
                    errorMap->insert(i, lastError);
 
2547
            }
 
2548
            noErrors = false;
 
2549
            break;
 
2550
        }
2433
2551
 
2434
 
        if (errorMap)
2435
 
            errorMap->insert(i, loopError);
 
2552
        QSqlQuery query(db);
 
2553
        if (!query.exec("SAVEPOINT save")) {
 
2554
            loopError = QLandmarkManager::UnknownError;
 
2555
            loopErrorString = QString("Remove category: could not execute statement: %1\nReason:%2").arg(query.lastQuery()).arg(query.lastError().text());
 
2556
            result = false;
 
2557
        } else {
 
2558
            result = removeCategoryHelper(categoryIds.at(i), &loopError, &loopErrorString);
 
2559
        }
2436
2560
 
2437
2561
        if (!result) {
 
2562
            if (errorMap)
 
2563
                errorMap->insert(i, loopError);
 
2564
 
2438
2565
            noErrors = false;
2439
2566
            lastError = loopError;
2440
2567
            lastErrorString = loopErrorString;
 
2568
            query.exec("ROLLBACK TO SAVEPOINT save");
 
2569
        } else {
 
2570
            query.exec("RELEASE SAVEPOINT save");
2441
2571
        }
2442
 
 
2443
 
        if (result)
2444
 
            removedIds << categoryIds.at(i);
2445
2572
    }
2446
2573
 
 
2574
    db.commit();
 
2575
 
2447
2576
    if (noErrors) {
2448
2577
        if (error)
2449
2578
            *error = QLandmarkManager::NoError;
2456
2585
            *errorString = lastErrorString;
2457
2586
    }
2458
2587
 
2459
 
    //TODO: notifications
2460
 
    //if (removedIds.size() != 0)
2461
 
    //    emit landmarksRemoved(removedIds);
2462
 
 
2463
2588
    return noErrors;
2464
2589
}
2465
2590
 
2577
2702
 
2578
2703
bool DatabaseOperations::exportLandmarks( QIODevice *device,
2579
2704
                     const QString &format,
2580
 
                     QList<QLandmarkId> landmarkIds,
 
2705
                     const QList<QLandmarkId> &landmarkIds,
2581
2706
                     QLandmarkManager::TransferOption option,
2582
2707
                     QLandmarkManager::Error *error,
2583
2708
                     QString *errorString) const
2777
2902
}
2778
2903
 
2779
2904
bool DatabaseOperations::exportLandmarksLmx(QIODevice *device,
2780
 
                        QList<QLandmarkId> landmarkIds,
 
2905
                        const QList<QLandmarkId> &landmarkIds,
2781
2906
                        QLandmarkManager::TransferOption option,
2782
2907
                        QLandmarkManager::Error *error,
2783
2908
                        QString *errorString) const
2793
2918
        lms = landmarks(filter, sortOrders, -1, 0, error, errorString);
2794
2919
    }
2795
2920
 
2796
 
    if (error && *error != QLandmarkManager::NoError)
2797
 
    {
2798
 
        if (*error == QLandmarkManager::CancelError)
2799
 
            *errorString = "Export of lmx file was canceled";
2800
 
            return false;
2801
 
    }
 
2921
    if (*error != QLandmarkManager::NoError)
 
2922
        return false;
2802
2923
 
2803
2924
    QList<QLandmarkCategory> categories = this->categories(QList<QLandmarkCategoryId>(),QLandmarkNameSort(),-1,0,error,errorString,true);
2804
2925
    if (*error != QLandmarkManager::NoError) {
2831
2952
}
2832
2953
 
2833
2954
bool DatabaseOperations::exportLandmarksGpx(QIODevice *device,
2834
 
                        QList<QLandmarkId> landmarkIds,
 
2955
                        const QList<QLandmarkId> &landmarkIds,
2835
2956
                        QLandmarkManager::Error *error,
2836
2957
                        QString *errorString) const
2837
2958
{
2872
2993
{
2873
2994
    switch(filter.type()) {
2874
2995
        case QLandmarkFilter::DefaultFilter:
2875
 
            return QLandmarkManager::Native;
 
2996
            return QLandmarkManager::NativeSupport;
2876
2997
        case QLandmarkFilter::AttributeFilter:
2877
2998
        {
2878
2999
            const QLandmarkAttributeFilter attribFilter(filter);
2879
3000
            QStringList filterKeys = attribFilter.attributeKeys();
2880
3001
 
2881
3002
            QStringList landmarkKeys;
2882
 
            if (attribFilter.attributeType() == QLandmarkAttributeFilter::ManagerAttributes) {
2883
 
                foreach(const QString key, filterKeys) {
2884
 
                    if (!supportedSearchableAttributes.contains(key))
2885
 
                        return QLandmarkManager::None;
2886
 
                }
 
3003
 
 
3004
            foreach(const QString key, filterKeys) {
 
3005
                if (!supportedSearchableAttributes.contains(key))
 
3006
                    return QLandmarkManager::NoSupport;
2887
3007
            }
 
3008
 
2888
3009
            foreach (const QString &key, filterKeys) {
2889
3010
                if (attribFilter.matchFlags(key) & QLandmarkFilter::MatchCaseSensitive)
2890
 
                    return QLandmarkManager::None;
 
3011
                    return QLandmarkManager::NoSupport;
2891
3012
            }
2892
3013
        }
2893
3014
        case QLandmarkFilter::BoxFilter:
2894
3015
        {
2895
 
            return QLandmarkManager::Native;
 
3016
            return QLandmarkManager::NativeSupport;
2896
3017
        }
2897
3018
        case QLandmarkFilter::CategoryFilter:
2898
3019
        {
2899
 
            return QLandmarkManager::Native;
 
3020
            return QLandmarkManager::NativeSupport;
2900
3021
        }
2901
3022
        case QLandmarkFilter::IntersectionFilter:
2902
3023
        {
2903
3024
            const QLandmarkIntersectionFilter andFilter(filter);
2904
3025
            const QList<QLandmarkFilter>& terms = andFilter.filters();
2905
 
            QLandmarkManager::SupportLevel currentLevel = QLandmarkManager::Native;
 
3026
            QLandmarkManager::SupportLevel currentLevel = QLandmarkManager::NativeSupport;
2906
3027
            if (terms.count() ==0)
2907
3028
                return currentLevel;
2908
3029
 
2909
3030
            for(int i=0; i < terms.count();i++) {
2910
 
                    if (filterSupportLevel(terms.at(i)) == QLandmarkManager::None)
2911
 
                        return QLandmarkManager::None;
2912
 
                    else if (filterSupportLevel(terms.at(i)) == QLandmarkManager::Emulated)
2913
 
                        currentLevel = QLandmarkManager::Emulated;
 
3031
                    if (filterSupportLevel(terms.at(i)) == QLandmarkManager::NoSupport)
 
3032
                        return QLandmarkManager::NoSupport;
 
3033
                    else if (filterSupportLevel(terms.at(i)) == QLandmarkManager::EmulatedSupport)
 
3034
                        currentLevel = QLandmarkManager::EmulatedSupport;
2914
3035
            }
2915
3036
            return currentLevel;
2916
3037
        }
2917
3038
        case QLandmarkFilter::LandmarkIdFilter:
2918
3039
        {
2919
 
            return QLandmarkManager::Native;
 
3040
            return QLandmarkManager::NativeSupport;
2920
3041
        }
2921
3042
        case QLandmarkFilter::InvalidFilter:
2922
3043
        {
2923
 
            return QLandmarkManager::Native;
 
3044
            return QLandmarkManager::NativeSupport;
2924
3045
        }
2925
3046
        case QLandmarkFilter::NameFilter:
2926
3047
        {
2927
3048
            const QLandmarkNameFilter nameFilter(filter);
2928
3049
            if (nameFilter.matchFlags() & QLandmarkFilter::MatchCaseSensitive)
2929
 
                return QLandmarkManager::None;
 
3050
                return QLandmarkManager::NoSupport;
2930
3051
            else
2931
 
                return QLandmarkManager::Native;
 
3052
                return QLandmarkManager::NativeSupport;
2932
3053
        }
2933
3054
        case QLandmarkFilter::ProximityFilter:
2934
3055
        {
2935
 
            return QLandmarkManager::Native;
 
3056
            return QLandmarkManager::NativeSupport;
2936
3057
        }
2937
3058
        case QLandmarkFilter::UnionFilter:
2938
3059
        {
2939
3060
            const QLandmarkUnionFilter orFilter(filter);
2940
3061
            const QList<QLandmarkFilter>& terms = orFilter.filters();
2941
 
            QLandmarkManager::SupportLevel currentLevel = QLandmarkManager::Native;
 
3062
            QLandmarkManager::SupportLevel currentLevel = QLandmarkManager::NativeSupport;
2942
3063
            if (terms.count() == 0)
2943
3064
                return currentLevel;
2944
3065
 
2945
3066
            for (int i=0; i < terms.count(); i++) {
2946
 
                if (filterSupportLevel(terms.at(i)) == QLandmarkManager::None)
2947
 
                    return QLandmarkManager::None;
2948
 
                else if (filterSupportLevel(terms.at(i)) == QLandmarkManager::Emulated)
2949
 
                    currentLevel = QLandmarkManager::Emulated;
 
3067
                if (filterSupportLevel(terms.at(i)) == QLandmarkManager::NoSupport)
 
3068
                    return QLandmarkManager::NoSupport;
 
3069
                else if (filterSupportLevel(terms.at(i)) == QLandmarkManager::EmulatedSupport)
 
3070
                    currentLevel = QLandmarkManager::EmulatedSupport;
2950
3071
            }
2951
3072
 
2952
3073
            return currentLevel;
2953
3074
        }
2954
3075
        default: {
2955
 
            return QLandmarkManager::None;
 
3076
            return QLandmarkManager::NoSupport;
2956
3077
        }
2957
3078
    }
2958
 
    return QLandmarkManager::None;
 
3079
    return QLandmarkManager::NoSupport;
2959
3080
}
2960
3081
 
2961
 
QLandmarkManager::SupportLevel DatabaseOperations::sortOrderSupportLevel(const QList<QLandmarkSortOrder> &sortOrders) const
 
3082
QLandmarkManager::SupportLevel DatabaseOperations::sortOrderSupportLevel(const QLandmarkSortOrder &sortOrder) const
2962
3083
{
2963
 
    QLandmarkManager::SupportLevel currentLevel = QLandmarkManager::Native;
2964
 
    foreach(const QLandmarkSortOrder &sortOrder, sortOrders){
2965
 
        switch(sortOrder.type()) {
2966
 
            case (QLandmarkSortOrder::DefaultSort):
2967
 
                continue;
2968
 
            case (QLandmarkSortOrder::NameSort):
2969
 
                continue;
2970
 
            default:
2971
 
                currentLevel = QLandmarkManager::None;
2972
 
        }
2973
 
    }
 
3084
    QLandmarkManager::SupportLevel currentLevel = QLandmarkManager::NativeSupport;
 
3085
 
 
3086
    switch(sortOrder.type()) {
 
3087
    case (QLandmarkSortOrder::NoSort):
 
3088
        break;
 
3089
    case (QLandmarkSortOrder::NameSort): {
 
3090
        QLandmarkNameSort  nameSort = sortOrder;
 
3091
        if (nameSort.caseSensitivity() == Qt::CaseSensitive)
 
3092
            currentLevel = QLandmarkManager::NoSupport;
 
3093
        break;
 
3094
    }
 
3095
    default:
 
3096
        currentLevel = QLandmarkManager::NoSupport;
 
3097
    }
 
3098
 
2974
3099
    return currentLevel;
2975
3100
}
2976
3101
 
2997
3122
        connectionName = QUuid::createUuid().toString();//each connection needs a unique name
2998
3123
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
2999
3124
        db.setDatabaseName(engine->m_dbFilename);
3000
 
        DatabaseOperations databaseOperations(engine->m_isExtendedAttributesEnabled, engine->m_isCustomAttributesEnabled);
 
3125
        DatabaseOperations databaseOperations;
3001
3126
        databaseOperations.connectionName = connectionName;
3002
3127
        databaseOperations.managerUri = managerUri;
3003
3128
        databaseOperations.queryRun = this;
3048
3173
                    ml.unlock();
3049
3174
                }
3050
3175
 
3051
 
                if (!isDeleted) {                    
 
3176
                if (!isDeleted) {
3052
3177
                    ml.relock();
3053
3178
                    if (engine->m_requestRunHash.contains(request))
3054
3179
                        engine->m_requestRunHash.remove(request);
3485
3610
                                                              << "city"
3486
3611
                                                              << "district"
3487
3612
                                                              << "street"
3488
 
                                                              << "postCode"
 
3613
                                                              << "postcode"
3489
3614
                                                              << "phoneNumber"
3490
3615
                                                              << "url";
3491
 
const QStringList DatabaseOperations::extendedGenericAttributes = QStringList();
3492
3616
 
3493
3617
const QStringList DatabaseOperations::supportedSearchableAttributes = QStringList() << "name"
3494
3618
                                                         << "description"
3499
3623
                                                         << "city"
3500
3624
                                                         << "district"
3501
3625
                                                         << "street"
3502
 
                                                         << "postCode"
 
3626
                                                         << "postcode"
3503
3627
                                                         << "phoneNumber";
3504
3628
 
3505
3629
const QStringList DatabaseOperations::coreCategoryAttributes = QStringList()
3507
3631
 
3508
3632
const QStringList DatabaseOperations::coreGenericCategoryAttributes = QStringList()
3509
3633
                                                               << "iconUrl";
3510
 
 
3511
 
const QStringList DatabaseOperations::extendedGenericCategoryAttributes = QStringList();