Commit 8aab14a2 authored by Dennis Nienhüser's avatar Dennis Nienhüser
Browse files

Parse queries in a new class, improve output, support several databases

Features described in http://userbase.kde.org/Marble/OfflineSearch.
REVIEW: 101245
BUG: 267026
parent cb5239ef
......@@ -13,6 +13,7 @@ LocalOsmSearchPlugin.cpp
OsmPlacemark.cpp
OsmRegion.cpp
OsmDatabase.cpp
DatabaseQuery.cpp
)
marble_add_plugin( LocalOsmSearchPlugin ${localOsmSearch_SRCS} )
......
//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2011 Dennis Nienhüser <earthwings@gentoo.org>
//
#include "DatabaseQuery.h"
#include "MarbleMap.h"
#include "MarbleModel.h"
#include "PositionTracking.h"
#include "ViewportParams.h"
#include <QtCore/QMap>
namespace Marble
{
DatabaseQuery::DatabaseQuery( MarbleModel* model, const QString &searchTerm ) :
m_queryType( BroadSearch ), m_resultFormat( AddressFormat ), m_searchTerm( searchTerm.trimmed() ),
m_category( OsmPlacemark::UnknownCategory )
{
if ( model && model->positionTracking()->status() == PositionProviderStatusAvailable ) {
m_position = model->positionTracking()->currentLocation();
m_resultFormat = DistanceFormat;
} else {
m_resultFormat = AddressFormat;
}
QStringList terms = m_searchTerm.split( ",", QString::SkipEmptyParts );
QRegExp streetAndHouse( "^(.*)\\s+(\\d+\\D?)$" );
if ( streetAndHouse.indexIn( terms.first() ) != -1 ) {
if ( streetAndHouse.capturedTexts().size() == 3 ) {
terms.removeFirst();
terms.push_front( streetAndHouse.capturedTexts().at( 1 ) );
terms.push_front( streetAndHouse.capturedTexts().at( 2 ) );
}
}
Q_ASSERT( terms.size() > 0 );
if ( terms.size() == 1 ) {
m_queryType = isPointOfInterest( m_searchTerm ) ? CategorySearch : BroadSearch;
} else if ( terms.size() == 2 ) {
m_street = terms.first().trimmed();
m_region = terms.last().trimmed();
m_queryType = isPointOfInterest( m_street ) ? CategorySearch : AddressSearch;
} else {
m_houseNumber = terms.first().trimmed();
m_street = terms.at( 1 ).trimmed();
m_region = terms.last().trimmed(); // skips 2, 3, ..., if any
m_queryType = AddressSearch;
}
}
bool DatabaseQuery::isPointOfInterest( const QString &category )
{
static QMap<QString, OsmPlacemark::OsmCategory> pois;
if ( pois.isEmpty() ) {
pois[QObject::tr( "camping" ).toLower()] = OsmPlacemark::AccomodationCamping;
pois["camping"] = OsmPlacemark::AccomodationCamping;
pois[QObject::tr( "hostel" ).toLower()] = OsmPlacemark::AccomodationHostel;
pois["hostel"] = OsmPlacemark::AccomodationHostel;
pois[QObject::tr( "hotel" ).toLower()] = OsmPlacemark::AccomodationHotel;
pois["hotel"] = OsmPlacemark::AccomodationHotel;
pois[QObject::tr( "motel" ).toLower()] = OsmPlacemark::AccomodationMotel;
pois["motel"] = OsmPlacemark::AccomodationMotel;
pois[QObject::tr( "youth hostel" ).toLower()] = OsmPlacemark::AccomodationYouthHostel;
pois["youth hostel"] = OsmPlacemark::AccomodationYouthHostel;
pois[QObject::tr( "library" ).toLower()] = OsmPlacemark::AmenityLibrary;
pois["library"] = OsmPlacemark::AmenityLibrary;
pois[QObject::tr( "college" ).toLower()] = OsmPlacemark::EducationCollege;
pois["college"] = OsmPlacemark::EducationCollege;
pois[QObject::tr( "school" ).toLower()] = OsmPlacemark::EducationSchool;
pois["school"] = OsmPlacemark::EducationSchool;
pois[QObject::tr( "university" ).toLower()] = OsmPlacemark::EducationUniversity;
pois["university"] = OsmPlacemark::EducationUniversity;
pois[QObject::tr( "bar" ).toLower()] = OsmPlacemark::FoodBar;
pois["bar"] = OsmPlacemark::FoodBar;
pois[QObject::tr( "biergarten" ).toLower()] = OsmPlacemark::FoodBiergarten;
pois["biergarten"] = OsmPlacemark::FoodBiergarten;
pois[QObject::tr( "cafe" ).toLower()] = OsmPlacemark::FoodCafe;
pois["cafe"] = OsmPlacemark::FoodCafe;
pois[QObject::tr( "fast food" ).toLower()] = OsmPlacemark::FoodFastFood;
pois["fast food"] = OsmPlacemark::FoodFastFood;
pois[QObject::tr( "pub" ).toLower()] = OsmPlacemark::FoodPub;
pois["pub"] = OsmPlacemark::FoodPub;
pois[QObject::tr( "restaurant" ).toLower()] = OsmPlacemark::FoodRestaurant;
pois["restaurant"] = OsmPlacemark::FoodRestaurant;
pois[QObject::tr( "doctor" ).toLower()] = OsmPlacemark::HealthDoctors;
pois["doctor"] = OsmPlacemark::HealthDoctors;
pois[QObject::tr( "hospital" ).toLower()] = OsmPlacemark::HealthHospital;
pois["hospital"] = OsmPlacemark::HealthHospital;
pois[QObject::tr( "pharmacy" ).toLower()] = OsmPlacemark::HealthPharmacy;
pois["pharmacy"] = OsmPlacemark::HealthPharmacy;
pois[QObject::tr( "bank" ).toLower()] = OsmPlacemark::MoneyBank;
pois["bank"] = OsmPlacemark::MoneyBank;
pois[QObject::tr( "beverages" ).toLower()] = OsmPlacemark::ShoppingBeverages;
pois["beverages"] = OsmPlacemark::ShoppingBeverages;
pois[QObject::tr( "hifi" ).toLower()] = OsmPlacemark::ShoppingHifi;
pois["hifi"] = OsmPlacemark::ShoppingHifi;
pois[QObject::tr( "supermarket" ).toLower()] = OsmPlacemark::ShoppingSupermarket;
pois["supermarket"] = OsmPlacemark::ShoppingSupermarket;
pois[QObject::tr( "attraction" ).toLower()] = OsmPlacemark::TouristAttraction;
pois["attraction"] = OsmPlacemark::TouristAttraction;
pois[QObject::tr( "castle" ).toLower()] = OsmPlacemark::TouristCastle;
pois["castle"] = OsmPlacemark::TouristCastle;
pois[QObject::tr( "cinema" ).toLower()] = OsmPlacemark::TouristCinema;
pois["cinema"] = OsmPlacemark::TouristCinema;
pois[QObject::tr( "monument" ).toLower()] = OsmPlacemark::TouristMonument;
pois["monument"] = OsmPlacemark::TouristMonument;
pois[QObject::tr( "museum" ).toLower()] = OsmPlacemark::TouristMuseum;
pois["museum"] = OsmPlacemark::TouristMuseum;
pois[QObject::tr( "ruin" ).toLower()] = OsmPlacemark::TouristRuin;
pois["ruin"] = OsmPlacemark::TouristRuin;
pois[QObject::tr( "theatre" ).toLower()] = OsmPlacemark::TouristTheatre;
pois["theatre"] = OsmPlacemark::TouristTheatre;
pois[QObject::tr( "theme park" ).toLower()] = OsmPlacemark::TouristThemePark;
pois["theme park"] = OsmPlacemark::TouristThemePark;
pois[QObject::tr( "view point" ).toLower()] = OsmPlacemark::TouristViewPoint;
pois["view point"] = OsmPlacemark::TouristViewPoint;
pois[QObject::tr( "zoo" ).toLower()] = OsmPlacemark::TouristZoo;
pois["zoo"] = OsmPlacemark::TouristZoo;
pois[QObject::tr( "airport" ).toLower()] = OsmPlacemark::TransportAirportTerminal;
pois["airport"] = OsmPlacemark::TransportAirportTerminal;
pois[QObject::tr( "bus station" ).toLower()] = OsmPlacemark::TransportBusStation;
pois["bus station"] = OsmPlacemark::TransportBusStation;
pois[QObject::tr( "bus stop" ).toLower()] = OsmPlacemark::TransportBusStop;
pois["bus stop"] = OsmPlacemark::TransportBusStop;
pois[QObject::tr( "car share" ).toLower()] = OsmPlacemark::TransportCarShare;
pois["car share"] = OsmPlacemark::TransportCarShare;
pois[QObject::tr( "fuel" ).toLower()] = OsmPlacemark::TransportFuel;
pois["fuel"] = OsmPlacemark::TransportFuel;
pois[QObject::tr( "parking" ).toLower()] = OsmPlacemark::TransportParking;
pois["parking"] = OsmPlacemark::TransportParking;
pois[QObject::tr( "train station" ).toLower()] = OsmPlacemark::TransportTrainStation;
pois["train station"] = OsmPlacemark::TransportTrainStation;
pois[QObject::tr( "atm" ).toLower()] = OsmPlacemark::MoneyAtm;
pois["atm"] = OsmPlacemark::MoneyAtm;
pois[QObject::tr( "tram stop" ).toLower()] = OsmPlacemark::TransportTramStop;
pois["tram stop"] = OsmPlacemark::TransportTramStop;
pois[QObject::tr( "bicycle rental" ).toLower()] = OsmPlacemark::TransportRentalBicycle;
pois["bicycle rental"] = OsmPlacemark::TransportRentalBicycle;
pois[QObject::tr( "car rental" ).toLower()] = OsmPlacemark::TransportRentalCar;
pois["car rental"] = OsmPlacemark::TransportRentalCar;
pois[QObject::tr( "speed camera" ).toLower()] = OsmPlacemark::TransportSpeedCamera;
pois["speed camera"] = OsmPlacemark::TransportSpeedCamera;
pois[QObject::tr( "taxi" ).toLower()] = OsmPlacemark::TransportTaxiRank;
pois["taxi"] = OsmPlacemark::TransportTaxiRank;
}
Q_ASSERT( !pois.isEmpty() );
QString const searchTerm = category.toLower();
if ( pois.contains( searchTerm ) ) {
m_category = pois[searchTerm];
return true;
}
m_category = OsmPlacemark::UnknownCategory;
return false;
}
OsmPlacemark::OsmCategory DatabaseQuery::category() const
{
return m_category;
}
DatabaseQuery::QueryType DatabaseQuery::queryType() const
{
return m_queryType;
}
DatabaseQuery::ResultFormat DatabaseQuery::resultFormat() const
{
return m_resultFormat;
}
QString DatabaseQuery::street() const
{
return m_street;
}
QString DatabaseQuery::houseNumber() const
{
return m_houseNumber;
}
QString DatabaseQuery::region() const
{
return m_region;
}
QString DatabaseQuery::searchTerm() const
{
return m_searchTerm;
}
GeoDataCoordinates DatabaseQuery::position() const
{
return m_position;
}
}
//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2011 Dennis Nienhüser <earthwings@gentoo.org>
//
#ifndef MARBLE_DATABASEQUERY_H
#define MARBLE_DATABASEQUERY_H
#include "GeoDataCoordinates.h"
#include "OsmPlacemark.h"
#include <QtCore/QList>
#include <QtCore/QString>
namespace Marble {
class MarbleModel;
/**
* Parse result of a user's search term
*/
class DatabaseQuery
{
public:
enum QueryType {
AddressSearch,
CategorySearch,
BroadSearch
};
enum ResultFormat {
AddressFormat,
DistanceFormat
};
DatabaseQuery( MarbleModel* model, const QString &searchTerm );
QueryType queryType() const;
ResultFormat resultFormat() const;
QString street() const;
QString houseNumber() const;
QString region() const;
QString searchTerm() const;
OsmPlacemark::OsmCategory category() const;
GeoDataCoordinates position() const;
private:
bool isPointOfInterest( const QString &category );
QueryType m_queryType;
ResultFormat m_resultFormat;
QString m_street;
QString m_houseNumber;
QString m_region;
QString m_searchTerm;
GeoDataCoordinates m_position;
OsmPlacemark::OsmCategory m_category;
};
}
#endif // MARBLE_DATABASEQUERY_H
......@@ -29,6 +29,8 @@ LocalOsmSearchRunner::LocalOsmSearchRunner( OsmDatabase *database, QObject *pare
m_database( database )
{
if ( m_categoryMap.isEmpty() ) {
m_categoryMap[OsmPlacemark::UnknownCategory] = GeoDataFeature::OsmSite;
m_categoryMap[OsmPlacemark::Address] = GeoDataFeature::OsmSite;
m_categoryMap[OsmPlacemark::AccomodationCamping] = GeoDataFeature::AccomodationCamping;
m_categoryMap[OsmPlacemark::AccomodationHostel] = GeoDataFeature::AccomodationHostel;
m_categoryMap[OsmPlacemark::AccomodationHotel] = GeoDataFeature::AccomodationHotel;
......@@ -47,6 +49,7 @@ LocalOsmSearchRunner::LocalOsmSearchRunner( OsmDatabase *database, QObject *pare
m_categoryMap[OsmPlacemark::HealthDoctors] = GeoDataFeature::HealthDoctors;
m_categoryMap[OsmPlacemark::HealthHospital] = GeoDataFeature::HealthHospital;
m_categoryMap[OsmPlacemark::HealthPharmacy] = GeoDataFeature::HealthPharmacy;
m_categoryMap[OsmPlacemark::MoneyAtm] = GeoDataFeature::MoneyAtm;
m_categoryMap[OsmPlacemark::MoneyBank] = GeoDataFeature::MoneyBank;
m_categoryMap[OsmPlacemark::ShoppingBeverages] = GeoDataFeature::ShoppingBeverages;
m_categoryMap[OsmPlacemark::ShoppingHifi] = GeoDataFeature::ShoppingHifi;
......@@ -61,13 +64,20 @@ LocalOsmSearchRunner::LocalOsmSearchRunner( OsmDatabase *database, QObject *pare
m_categoryMap[OsmPlacemark::TouristThemePark] = GeoDataFeature::TouristThemePark;
m_categoryMap[OsmPlacemark::TouristViewPoint] = GeoDataFeature::TouristViewPoint;
m_categoryMap[OsmPlacemark::TouristZoo] = GeoDataFeature::TouristZoo;
m_categoryMap[OsmPlacemark::TransportAerodrome] = GeoDataFeature::TransportAerodrome;
m_categoryMap[OsmPlacemark::TransportAirport] = GeoDataFeature::TransportAerodrome;
m_categoryMap[OsmPlacemark::TransportAirportTerminal] = GeoDataFeature::TransportAirportTerminal;
m_categoryMap[OsmPlacemark::TransportBusStation] = GeoDataFeature::TransportBusStation;
m_categoryMap[OsmPlacemark::TransportBusStop] = GeoDataFeature::TransportBusStop;
m_categoryMap[OsmPlacemark::TransportCarShare] = GeoDataFeature::TransportCarShare;
m_categoryMap[OsmPlacemark::TransportFuel] = GeoDataFeature::TransportFuel;
m_categoryMap[OsmPlacemark::TransportParking] = GeoDataFeature::TransportParking; }
m_categoryMap[OsmPlacemark::TransportParking] = GeoDataFeature::TransportParking;
m_categoryMap[OsmPlacemark::TransportTrainStation] = GeoDataFeature::TransportTrainStation;
m_categoryMap[OsmPlacemark::TransportTramStop] = GeoDataFeature::TransportTramStop;
m_categoryMap[OsmPlacemark::TransportRentalBicycle] = GeoDataFeature::TransportRentalBicycle;
m_categoryMap[OsmPlacemark::TransportRentalCar] = GeoDataFeature::TransportRentalCar;
m_categoryMap[OsmPlacemark::TransportSpeedCamera] = GeoDataFeature::OsmSite;
m_categoryMap[OsmPlacemark::TransportTaxiRank] = GeoDataFeature::TransportTaxiRank;
}
}
LocalOsmSearchRunner::~LocalOsmSearchRunner()
......@@ -82,17 +92,17 @@ GeoDataFeature::GeoDataVisualCategory LocalOsmSearchRunner::category() const
void LocalOsmSearchRunner::search( const QString &searchTerm )
{
QList<OsmPlacemark> placemarks = m_database->find( searchTerm );
QList<OsmPlacemark> placemarks = m_database->find( model(), searchTerm );
QVector<GeoDataPlacemark*> result;
foreach( const OsmPlacemark &placemark, placemarks ) {
GeoDataPlacemark* hit = new GeoDataPlacemark;
hit->setName( placemark.name() );
if ( !placemark.houseNumber().isEmpty() ) {
if ( placemark.category() == OsmPlacemark::Address && !placemark.houseNumber().isEmpty() ) {
hit->setName( hit->name() + " " + placemark.houseNumber() );
}
if ( !placemark.regionName().isEmpty() ) {
hit->setName( hit->name() + ", " + placemark.regionName() );
if ( !placemark.additionalInformation().isEmpty() ) {
hit->setName( hit->name() + " (" + placemark.additionalInformation() + ")" );
}
if ( placemark.category() != OsmPlacemark::UnknownCategory ) {
hit->setVisualCategory( m_categoryMap[placemark.category()] );
......
......@@ -11,6 +11,9 @@
#include "OsmDatabase.h"
#include "OsmRegion.h"
#include "MarbleDebug.h"
#include "MarbleMath.h"
#include "MarbleLocale.h"
#include "DatabaseQuery.h"
#include <QtCore/QFile>
#include <QtCore/QDataStream>
......@@ -25,177 +28,159 @@
namespace Marble {
namespace {
quint32 const osmDatabaseFileMagicNumber = 0xAEB4E6D8;
quint32 const osmDatabaseFileVersion = 160;
}
OsmDatabase::OsmDatabase()
{
// nothing to do
m_database = QSqlDatabase::addDatabase( "QSQLITE" );
}
void OsmDatabase::addFile( const QString &fileName )
{
QSqlDatabase database = QSqlDatabase::addDatabase( "QSQLITE" );
database.setDatabaseName( fileName );
if ( !database.open() ) {
qDebug() << "Failed to connect to database " << fileName;
}
}
void OsmDatabase::save( const QString &filename )
{
QFile file( filename );
file.open( QFile::WriteOnly );
QDataStream stream( &file );
// Write a header with a "magic number" and a version
stream << (quint32) osmDatabaseFileMagicNumber;
stream << (quint32) osmDatabaseFileVersion;
stream.setVersion( QDataStream::Qt_4_0 );
/** @todo: Use a B-tree or similar */
stream << m_regions;
qSort( m_placemarks );
stream << m_placemarks;
file.close();
}
void OsmDatabase::addOsmRegion( const OsmRegion &region )
{
m_regions.push_back( region );
m_databases << fileName;
}
void OsmDatabase::addOsmPlacemark( const OsmPlacemark &placemark )
QList<OsmPlacemark> OsmDatabase::find( MarbleModel* model, const QString &searchTerm )
{
m_placemarks.push_back( placemark );
}
QList<OsmPlacemark> OsmDatabase::find( const QString &searchTerm ) const
{
QString const queryString = " SELECT regions.name,"
" placemarks.name, placemarks.number,"
" placemarks.category, placemarks.lon, placemarks.lat"
" FROM regions, placemarks"
" WHERE regions.id = placemarks.region"
" AND placemarks.name LIKE '%%1%'"
" LIMIT 20";
QList<OsmPlacemark> result;
QTime timer;
timer.start();
QSqlQuery query;
query.setForwardOnly( true );
if ( !query.exec( queryString.arg( searchTerm ) ) ) {
qDebug() << "Failed to execute query: " << query.lastError();
return result;
}
qDebug() << "Query took " << timer.elapsed() << " ms.";
while ( query.next() ) {
OsmPlacemark placemark;
placemark.setRegionName( query.value( 0 ).toString() );
placemark.setName( query.value(1).toString() );
placemark.setHouseNumber( query.value(2).toString() );
placemark.setCategory( (OsmPlacemark::OsmCategory) query.value(3).toInt() );
placemark.setLongitude( query.value(4).toFloat() );
placemark.setLatitude( query.value(5).toFloat() );
result.push_back( placemark );
qDebug() << "found " << placemark.name();
if ( m_databases.isEmpty() ) {
return QList<OsmPlacemark>();
}
return result;
QStringList terms = searchTerm.split( ",", QString::SkipEmptyParts );
QRegExp streetAndHouse( "^(.*)\\s+(\\d+\\D?)$" );
if ( streetAndHouse.indexIn( terms.first() ) != -1 ) {
if ( streetAndHouse.capturedTexts().size() == 3 ) {
terms.removeFirst();
terms.push_front( streetAndHouse.capturedTexts().at( 1 ) );
terms.push_front( streetAndHouse.capturedTexts().at( 2 ) );
DatabaseQuery userQuery( model, searchTerm );
QString queryString;
queryString = " SELECT regions.name,"
" places.name, places.number,"
" places.category, places.lon, places.lat"
" FROM regions, places";
if ( userQuery.queryType() == DatabaseQuery::CategorySearch ) {
queryString += " WHERE regions.id = places.region AND places.category = %1";
queryString = queryString.arg( (qint32) userQuery.category() );
if ( userQuery.resultFormat() == DatabaseQuery::DistanceFormat && userQuery.region().isEmpty() ) {
queryString += " ORDER BY ((places.lat-%1)*(places.lat-%1)+(places.lon-%2)*(places.lon-%2))";
GeoDataCoordinates position = userQuery.position();
queryString = queryString.arg( position.latitude( GeoDataCoordinates::Degree ), 0, 'f', 8 )
.arg( position.longitude( GeoDataCoordinates::Degree ), 0, 'f', 8 );
} else {
queryString += " AND regions.name LIKE '%%2%'";
queryString = queryString.arg( userQuery.region() );
}
}
if ( terms.size() == 1 ) {
return findOsmTerm( terms.first().trimmed() );
} else if ( terms.size() == 2 ) {
return findStreets( terms.last().trimmed(), terms.first().trimmed() );
} else if ( userQuery.queryType() == DatabaseQuery::BroadSearch ) {
queryString += " WHERE regions.id = places.region"
" AND places.name LIKE '%%1%'";
queryString = queryString.arg( searchTerm );
} else {
Q_ASSERT( terms.size() > 2 ); // according to split() docs
return findHouseNumber( terms.at( 2 ).trimmed(),
terms.at( 1 ).trimmed(),
terms.at( 0 ).trimmed() );
queryString += " WHERE regions.id = places.region"
" AND places.name LIKE '%%1%'";
queryString = queryString.arg( userQuery.street() );
if ( !userQuery.houseNumber().isEmpty() ) {
queryString += " AND places.number IS '%1'";
queryString = queryString.arg( userQuery.houseNumber() );
}
queryString += " AND regions.name LIKE '%%2%'";
queryString = queryString.arg( userQuery.region() );
}
/** @todo: alternative words, etc. */
queryString += " LIMIT 50;";
return QList<OsmPlacemark>();
}
QList<OsmPlacemark> OsmDatabase::findOsmTerm( const QString &term ) const
{
QList<OsmPlacemark> result;
foreach( const OsmRegion &region, m_regions ) {
if ( region.name().startsWith( term, Qt::CaseInsensitive ) ) {
OsmPlacemark placemark;
placemark.setLongitude( region.longitude() );
placemark.setLatitude( region.latitude() );
placemark.setName( region.name() );
result << placemark;
}
}
QTime timer;
timer.start();
foreach( const QString &databaseFile, m_databases ) {
/** @todo: sort/filter results from several databases */
foreach( const OsmPlacemark &placemark, m_placemarks ) {
if ( placemark.name().startsWith( term, Qt::CaseInsensitive ) ) {
result << placemark;
m_database.setDatabaseName( databaseFile );
if ( !m_database.open() ) {
qDebug() << "Failed to connect to database " << databaseFile;
}
}
return result;
}
QList<OsmPlacemark> OsmDatabase::findStreets( const QString &reg, const QString &street ) const
{
QList<OsmPlacemark> result;
QList<int> regions;
foreach( const OsmRegion &region, m_regions ) {
if ( region.name().startsWith( reg, Qt::CaseInsensitive ) ) {
regions << region.identifier();
QSqlQuery query;
query.setForwardOnly( true );
if ( !query.exec( queryString ) ) {
qDebug() << "Failed to execute query: " << query.lastError();
return result;
}
}
foreach( const OsmPlacemark &placemark, m_placemarks ) {
if ( regions.contains( placemark.regionId() ) && placemark.name().startsWith( street, Qt::CaseInsensitive ) ) {
while ( query.next() ) {
OsmPlacemark placemark;
if ( userQuery.resultFormat() == DatabaseQuery::DistanceFormat ) {
GeoDataCoordinates coordinates( query.value(4).toFloat(), query.value(5).toFloat(), 0.0, GeoDataCoordinates::Degree );
placemark.setAdditionalInformation( formatDistance( coordinates, userQuery.position() ) );
} else {
placemark.setAdditionalInformation( query.value( 0 ).toString() );