could anyone tell me how to do Reverse geocoding in BB10. I have got latitude , longitude and now I need to convert it into address.
There are geocoding and reverse-geocoding C++ examples on the BB10 Native documenation site, https://developer.blackberry.com/native/documentation/cascades/device_platform/location/geocoding.html did you look at that ?
I have done following code but having problem in that. QGeoCoordinate GCoor(lat,lang);
//Reverse GeoCoding
QStringList serviceProviders =
QGeoServiceProvider::availableServiceProviders();
if (serviceProviders.size()) {
QGeoServiceProvider *serviceProvider = new QGeoServiceProvider(
serviceProviders.at(0));
QGeoSearchManager *searchManager = serviceProvider->searchManager();
//searchManager->setProperty("boundary", "city");
reply = searchManager->reverseGeocode(GCoor);
bool finished_connected = QObject::connect(reply, SIGNAL(finished()),
this, SLOT(readReverseGeocode()));
bool error_connected = QObject::connect(reply,
SIGNAL(error(QGeoSearchReply::Error, QString)), this,
SLOT(reverseGeocodeError(QGeoSearchReply::Error, QString)));
//Reverse GeoLocation
void LocationHandler::readReverseGeocode() {
QList<QGeoPlace> LocDetList = reply->places();
QGeoPlace locDe = LocDetList.at(0);
qDebug() << "City --> " << locDe.address().state();
qDebug() << "Country Code --> " << locDe.address().countryCode();
qDebug() << "Country --> " << locDe.address().country();
reply->deleteLater();
}
`void LocationHandler::reverseGeocodeError(QGeoSearchReply::Error error,
QString errorString) {
qDebug() << "( Geo::reverseGeocodeError ) " << errorString;
reply->deleteLater();
}
The application is exiting at this line in this code -
QGeoPlace locDe = LocDetList.at(0);
whats the problem here?
Related
I'm new in C++ also with QT, my current QT version is 5.5.1.
I have an issue when using connect with QNetworkReply and QNetworkAccessManager. When I try to assign a variable from another file to data fetched from API, it always calls the function first before connecting to the API so that the variable is always empty. Can you guys help me?
void NioshFunc::fetchDataFromAPI(){
QUrl url;
QUrlQuery querystr;
querystr.addQueryItem("$format","json");
url.setScheme("https");
url.setHost("example.com");
url.setPath("/aaaa/dataset");
url.setQuery(querystr);
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("KeyId", "xxx-xxx-xxx");
reply = manager->get(request);
connect(reply, &QNetworkReply::readyRead, this, &NioshFunc::readyRead);
connect(reply, &QNetworkReply::finished, this, &NioshFunc::finished);
}
void NioshFunc::readyRead(){
dataBuffer.append(reply->readAll());
}
void NioshFunc::finished(){
if(reply->error())
{
qDebug() << "ERROR!";
qDebug() << reply->errorString();
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
}else{
qDebug() << "SUCCESS";
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
nioshWPDataFromAPI = QJsonDocument::fromJson(dataBuffer);
qDebug() << nioshWPDataFromAPI;
dataBuffer.clear();
}
reply->deleteLater();
}
bool NioshFunc::parse(){
Globals *g = Globals::getHandle();
if (nioshWPDataFromAPI.isEmpty() || nioshWPDataFromAPI.isNull()) return false;
QVariantMap root = nioshWPDataFromAPI.toVariant().toMap();
if (root.isEmpty()) return false;
QVariantMap d = root["d"].toMap();
if (d.isEmpty()) return false;
QVariantList results = d["results"].toList();
if (results.isEmpty()) return false;
foreach (QVariant varResult, results)
{
QVariantMap result = varResult.toMap();
if (result.isEmpty()) return false;
g->struct_tableColumn.input.duration = result["Duration"].toString();
g->struct_tableColumn.input.id = result["Id"].toString();
if (id.isEmpty() || id.isNull()) return false;
g->struct_tableColumn.input.load_cumul_Limit = result["LoadCumulLimit"].toString();
g->struct_tableColumn.input.Notes = result["Notes"].toString();
qDebug() << g->struct_tableColumn.input.id << g->struct_tableColumn.input.duration << g->struct_tableColumn.input.load_cumul_Limit << g->struct_tableColumn.input.Notes; // "it is empty for all variable from globals file.
}
return true;
}
When I can function fetchDataFromAPI() and call function parse() in another file named globals, that is always called 2 these functions first before connecting to API, so that the variable named "nioshWPDataFromAPI" is always empty. But when I read nioshWPDataFromAPI in function finished(), it still has data, but only in function finished(). Could you guys help me? Sorry if my question is not too clear for you guys
I am trying to get data out of slot with a signal readyRead(). But my method doesn't seem to work. I googled a lot but still I can't solve the problem.
Here what I have:
In my main function I call the method sendPOST() to get cookies. I got cookies from this method using inside of it SIGNAL finished(QNetworkReply *) and SLOT replyFinishedSlot_(QNetworkReply *) :
connect(manager_, SIGNAL(finished(QNetworkReply *)), this, SLOT(replyFinishedSlot_(QNetworkReply *)));
I made a public static bool variable isFinished = false by default to write if slot is finished it's job.
replyFinishedSlot_(QNetworkReply ):
if(reply->error())
qDebug() << "Error: " << reply->errorString();
else
{
cookie = reply->manager()->cookieJar()->cookiesForUrl(webReportsUrl);
QString cookieString = cookie[0].name() + "=" + cookie[0].value() + "; domain=" + cookie[0].domain() + "; path=" + cookie[0].path() + ";";
if(reply->isFinished()) isFinished = true; //isFinished is static public variable
}
reply->deleteLater();
And then I check in my main function if isFinished is true, and if it is I connect to another slot:
manager_ = new QNetworkAccessManager(this);
sendPOST("http://url");
if(isFinished)
{
QNetworkAccessManager *man = new QNetworkAccessManager();
QNetworkRequest request(webReportsUrl);
request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookie));
getReply = man->get(request);
connect(getReply, SIGNAL(readyRead()), this, SLOT(readyReadSlot_()));
if(isRead)
qDebug() << "reading";
else qDebug() << "not reading";
}
and isFinished in here works very well (but I am not sure if this is the right way to check finished or not like this). I get isFinished == true, and I can get cookies from replyFinishedSlot_.
But the problem is to get data from readyReadSlot_(). I tried different ways to receive the data from this slot, but there's no successful result.
I tried even something like this:
QEventLoop loop;
connect(getReply, SIGNAL(readyRead()), &loop, SLOT(readyReadSlot_()));
loop.exec();
But I got the error:
QObject::connect: No such slot QEventLoop::readyReadSlot_() in ...
Inside readyReadSlot_() I have to receive all the data from the page:
if(getReply->isReadable())
{
if(getReply->error() != QNetworkReply::NoError)
{
qDebug() << "Error: " << getReply->errorString();
}
else {
isRead = true;
response = getReply->readAll(); //here the data I need outside of this slot
qDebug() << "response: " << response;
}
}
getReply->deleteLater();
And I get it successfully inside, but I need to get response outside of this slot, in my main function, for example.
I know here's something with a threads, and I just don't wait till the data recieved, but I don't know how can I fix it.
I found a problem solvation for me.
void DataMartsModel::replyFinishedSlot_(QNetworkReply *reply)
{
static bool isRead = false;
if(reply->error())
qDebug() << "Error: " << reply->errorString();
else
{
cookie = reply->manager()->cookieJar()->cookiesForUrl(webReportsUrl);
QString cookieString = cookie[0].name() + "=" + cookie[0].value() + "; domain=" + cookie[0].domain() + "; path=" + cookie[0].path() + ";";
QNetworkAccessManager *man = new QNetworkAccessManager();
QNetworkRequest request(webReportsUrl);
request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookie));
getReply = man->get(request);
connect(getReply, &QNetworkReply::readyRead, [=](){
if(getReply->isReadable())
{
if(getReply->error() != QNetworkReply::NoError) qDebug() << "Error: " << getReply->errorString();
else {
isRead = true;
}
}
});
if(reply->isFinished() && getReply->isReadable()) isFinished = true; //here is the problem solvation I wanted
}
reply->deleteLater();
}
main function
manager_ = new QNetworkAccessManager(this);
sendPOST("http://url");
if(isFinished)
{
QByteArray array = getReply->readAll(); //here I got the data I needed to get from readyReady
qDebug() << array; //here I display it and I can use them in the future
}
If you know better way to solve the problem, I would like to check it, too.
I created a library which will handle all HTTP requests and parsing of response data in JSON format. When I called the method that includes get request in my main application (with GUI), I received a memory corruption error. So I added QEventLoop and a timer to wait for the response before proceeding to other processes. I was able to get the response data by calling QNetworkReply.readall(). I needed to get the char* value of the response data so I called the QNetworkReply.data() but it is empty. Why?
Here are the codes I wrote:
Library which handles HTTP requests:
void HttpRequest::getRequest(string param1, string param2)
{
pManager_ = new QNetworkAccessManager(this);
QUrl cUrl(sampleUrl);
QNetworkRequest request(cUrl);
request.setRawHeader(keyHeader.c_str(), param1.c_str());
connect(pManager_, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));
connect(pManager_, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError> & )), this,
SLOT(handleSslErrors(QNetworkReply*, const QList<QSslError> & )));
cUrl.addQueryItem("name", QString::fromStdString(param2));
pManager_->get(request); // memory corruption error encountered in main application after calling this
std::cout << "after calling get" << std::endl;
}
void HttpRequest::requestFinished(QNetworkReply *pReply)
{
QByteArray responseData;
std::cout << " request finished" << std::endl;
int responseStatus = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
std::cout << " status code: " << responseStatus << std::endl;
if(pReply->error())
std::cout << " Error: " << pReply->errorString().toStdString() << std::endl;
else
{
responseData = pReply->readAll();
qDebug() << " Response data: " << responseData;
const char* pResponseData = responseData.data();
qDebug() << "pResponseData: " << pResponseData ;
// parsing here
}
pReply->deleteLater();
pManager_->deleteLater();
}
void HttpRequest::handleSslErrors(QNetworkReply *pReply, const QList<QSslError> & )
{
std::cout << " SSL ERROR" << std::endl;
int responseStatus = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
}
Main GUI application:
DialogTest::DialogTest(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogTest)
{
// some codes here
if(enabled)
{
HttpRequest::instance()->getInformation(param1, param2); // memory corruption happened here when I called getRequest() method with no event loop
}
// other threads here
}
Here is the code that uses QEventLoop:
void HttpRequest::getRequest(string param1, string param2)
{
QTimer qTimer;
QEventLoop loop;
pManager_ = new QNetworkAccessManager(this);
QUrl cUrl(sampleUrl);
QNetworkRequest request(cUrl);
request.setRawHeader(keyHeader.c_str(), param1.c_str());
connect(&qTimer,SIGNAL(timeout()),&loop, SLOT(quit()));
connect(pManager_, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit()));
QNetworkReply *pReply = pManager_->get(request);
qTimer.start(1000);
loop.exec();
int responseCode = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
std::cout << "status code: " << responseCode << std::endl;
if(pReply->error())
{
std::cout << " Error: " << pReply->errorString().toStdString() << std::endl;
}
else
{
qDebug() << "[HttpRequest] Response data: " << pReply->readAll();
QByteArray response = pReply->readAll(); // it printed this value: "{"count":3,"codes":["x00000A","x00000B","x00000C"]}" which is correct
char* pResponseData = response.data();
qDebug() << "pResponseData: " << pResponseData ; //it printed this: pResponseData:
}
delete pReply;
delete pManager_;
}
I am expecting this response data from a HTTP get command:
"{"count":3,"codes":["x00000A","x00000B","x00000C"]}"
Problem:
What is the best way to implement this? I want to put all HTTP request in a library then call it my main application with GUI. Please note that:
When I use QEventLoop inside the library to wait for the response, QNetworkReply.data() is empty. I need the value of QNetworkReply.data() for parsing.
When I did not use QEventLoop and use signal and slot alone (as shown in the code above), memory corruption occurred in main application after executing HTTP get command. No response data is received.
an advice:
never use a direct delete for a QObject. BAD:
delete pReply;
delete pManager_;
Qt way,GOOD:
pReply->deleteLater();
pManager->deleteLater();
Better: no "new" (dynamic memory)
QNetworkAccessManager Manager_;
...
connect(&Manager_, SIGNAL(finished(QNetworkReply*)),&loop, SLOT(quit()));
..
pReply->deleteLater();
I have a QWebView where I'm watching the network requests by connecting:
QObject::connect(page()->networkAccessManager(),
SIGNAL(finished(QNetworkReply*)),
this,
SLOT(networkLoaded(QNetworkReply*)));
then:
void browserControl::networkLoaded(QNetworkReply *reply)
{
const QUrl reqUrl = reply->request().url();
qDebug() << "url = " << reqUrl;
QByteArray array = reply->readAll();
QString data = QString::fromUtf8(array.data(), array.size());
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).value<int>();
qDebug() << "data = " << data;
qDebug() << "http code = " << statusCode;
}
But data is always empty, not matter if statusCode is 200. browserControl class is inheried from QWebView class.
You get no data because QWebPage read all data before your slot is called
I want to see the results of a GET request. By my understanding, this code should do it. What am I doing wrong?
void getDoc::on_pushButton_2_clicked()
{
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("http://www.google.com")));
}
void getDoc::replyFinished(QNetworkReply *reply)
{
qDebug() << reply->error(); //prints 0. So it worked. Yay!
QByteArray data=reply->readAll();
qDebug() << data; // This is blank / empty
QString str(data);
qDebug() << "Contents of the reply: ";
qDebug() << str; //this is blank or does not print.
}
The code compiles and runs fine. It just doesn't work.
Try modifying your replyFinished slot to look like this:
QByteArray bytes = reply->readAll();
QString str = QString::fromUtf8(bytes.data(), bytes.size());
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
You can then print the statusCode to see if you are getting a 200 response:
qDebug() << QVariant(statusCode).toString();
If you are getting a 302 response, you are getting a status redirect. You will need to handle it like this:
if(statusCode == 302)
{
QUrl newUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
qDebug() << "redirected from " + replyUrl + " to " + newUrl.toString();
QNetworkRequest newRequest(newUrl);
manager->get(newRequest);
return;
}
I'm returning when encountering a status code of 302 since I don't want the rest of the method to execute.
I hope this helps!