Qcompleter which is associated with a lineEdit doesn't work in the slot of a QNetworkRequest finished.The Qcompleter disappeared quite quickly.Each time the text in lineEdit changed a request was send.I tried a demo without other code,it also occured.
Every time the text in lineEdit was edit,a request contains the text will be send to my server.And then I want to show the content in reply in a Qcompleter.But the prompt disappears in a instant.
void MainWindow::onRequestFinished(QNetworkReply* reply){
QStringList stringList;
stringList << "test1" <<"test2"<<"test3";
QCompleter* completer = new QCompleter(stringList,this);
completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
ui->lineEdit->setCompleter(completer);
reply->deleteLater();
}
void MainWindow::on_lineEdit_textChanged(const QString &arg1)
{
QUrl url("http://www.google.com");
QNetworkRequest request;
request.setUrl(url);
manager->get(request);
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow){
...
this->manager = new QNetworkAccessManager(this);
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(onRequestFinished(QNetworkReply*)));
...
}
The logic is similar to an old answer of mine, in it a model is created that will store the information this prevents you from creating a QCompleter at every moment avoiding the problem the disappearance of the popup.
#include <QtWidgets>
#include <QtNetwork>
class SuggestModel: public QStandardItemModel
{
Q_OBJECT
public:
using QStandardItemModel::QStandardItemModel;
void search(const QString & text)
{
QNetworkRequest request = create_request(text);
if(m_reply)
m_reply->abort();
m_reply = manager.get(request);
connect(m_reply, &QNetworkReply::finished, this, &SuggestModel::onFinished);
QEventLoop loop;
connect(this, &SuggestModel::finished, &loop, &QEventLoop::quit);
loop.exec();
}
private Q_SLOTS:
void onFinished(){
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
QUrl url = reply->url();
if (reply->error() == QNetworkReply::NoError) {
QVector<QString> choices;
QByteArray response(reply->readAll());
QXmlStreamReader xml(response);
while (!xml.atEnd()) {
xml.readNext();
if (xml.tokenType() == QXmlStreamReader::StartElement)
if (xml.name() == "suggestion") {
QStringRef str = xml.attributes().value("data");
choices << str.toString();
}
}
clear();
for(const QString & choice: choices)
appendRow(new QStandardItem(choice));
}
reply->deleteLater();
Q_EMIT finished();
m_reply = nullptr;
}
Q_SIGNALS:
void finished();
private:
QNetworkRequest create_request(const QString & text){
const QString suggestUrl(QStringLiteral("http://google.com/complete/search?output=toolbar&q=%1"));
QString url = suggestUrl.arg(text);
return QNetworkRequest(url);
}
QNetworkAccessManager manager;
QNetworkReply *m_reply = nullptr;
};
class SuggestCompleter: public QCompleter{
public:
SuggestCompleter(QObject *parent=nullptr):
QCompleter(parent)
{
SuggestModel *m_model = new SuggestModel(this);
setModel(m_model);
setCompletionMode(QCompleter::UnfilteredPopupCompletion);
}
QStringList splitPath(const QString &path) const override{
if(SuggestModel * m = qobject_cast<SuggestModel *>(model()))
m->search(path);
return QCompleter::splitPath(path);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QLineEdit le;
le.setCompleter(new SuggestCompleter(&le));
le.show();
return a.exec();
}
#include "main.moc"
Related
I'm new to Qt Framework and I'm trying to get the list of earthquakes from EMSC api. My code looks like this:
void MainWindow::getJsonData(QNetworkAccessManager *mNetworkManager) {
const QUrl json("https://www.seismicportal.eu/fdsnws/event/1/query?limit=100&format=json");
QNetworkRequest *mNetworkRequest = new QNetworkRequest;
mNetworkRequest->setUrl(json);
mNetworkRequest->setRawHeader("Content-Type", "application/json");
mNetworkRequest->setRawHeader("Accept", "application/json");
QNetworkReply *mNetworkReply = mNetworkManager->get(*mNetworkRequest);
QString replyString = (QString) mNetworkReply->readAll();
QJsonDocument document = QJsonDocument::fromJson(replyString.toUtf8());
QJsonObject object = document.object();
QJsonValue type = object["type"].toString();
QJsonArray featuresArray = object["features"].toArray();
qDebug() << type;
qDebug() << featuresArray;
}
The problem is that I'm not getting any response from the server.
Qt is a library (not a framework) that handles all transactions asynchronously through signals and slots, so don't expect the response to be obtained synchronously.
#include <QCoreApplication>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
class Client: public QObject{
public:
void startRequest(){
const QUrl json("https://www.seismicportal.eu/fdsnws/event/1/query?limit=100&format=json");
QNetworkRequest request;
request.setUrl(json);
request.setRawHeader("Content-Type", "application/json");
request.setRawHeader("Accept", "application/json");
QNetworkReply *reply = mNetworkManager.get(request);
connect(reply, &QNetworkReply::finished, this, &Client::processRequest);
}
private:
void processRequest(){
QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender());
if(!reply) return;
QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
QJsonObject object = document.object();
QJsonValue type = object["type"].toString();
QJsonArray featuresArray = object["features"].toArray();
qDebug() << type << featuresArray;
reply->deleteLater();
}
QNetworkAccessManager mNetworkManager;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Client client;
client.startRequest();
return a.exec();
}
Output:
QJsonValue(string, "FeatureCollection") QJsonArray([{"geometry":{"coordinates":[16.23,45.4,-2],"type":"Point"},"id":"20210202_0000178", ...
Here's some of my code:
QNetworkRequest req (QUrl(QString::fromStdString(url)));
req.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
if (authHeader.length() > 0) {
req.setRawHeader(QByteArray("Authorization"), QByteArray::fromStdString(authHeader));
}
QByteArray bodyArray;
if (body.length() > 0) {
bodyArray.append(QString::fromStdString(body).toUtf8());
}
QNetworkReply * reply = method(req, bodyArray);
QObject::connect(reply, &QNetworkReply::finished, [=]{
.... });
I wrote a piece of code that sends me, via a post request, a json to my API Rest; and works!
main.cpp
void replyFinished(QNetworkReply *reply)
{
reply->deleteLater();
qDebug() << "reply delete!";
qDebug() << "https post_request done!";
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QNetworkAccessManager *manager = new QNetworkAccessManager();
QUrl url("https://.../");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QObject::connect(manager, &QNetworkAccessManager::finished, replyFinished);
quint8 speed = 0x12;
quint8 accelleration = 0x2b;
QString json = QString("{\"speed\":\"%1\",\"acceleration\":\"%2\"}").arg(speed).arg(accelleration);
manager->post(request, json.toUtf8());
return a.exec();
}
But when I want to integrate this piece of code in my program, it does not work. Briefly, my program gets through the SIGNAL and SLOT mechanism, a QByteArray, from which I take the data and I send them to my API Rest.
This is my Header.h
...
class Packet : public QObject
{
Q_OBJECT
public:
Packet();
public slots:
void receivePayload(QByteArray &bufferToJson);
void replyFinished(QNetworkReply *reply);
private:
QNetworkAccessManager *m_manager;
quint8 m_speed;
quint8 m_accelleration;
public:
QString json;
};
...
This is my class.cpp
Packet::Packet()
: m_manager { new QNetworkAccessManager }
{
QObject::connect(m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
}
void Packet::replyFinished(QNetworkReply *reply)
{
reply->deleteLater();
qDebug() << "reply delete!";
qDebug() << "https post_request done!";
}
void Packet::receivePayload(QByteArray &bufferToJson){
m_speed = bufferToJson.at(0);
m_accelleration = bufferToJson.at(1);
QUrl url("https://.../");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QString json = QString("{\"speed\":\"%1\",\"acceleration\":\"%2\"}").arg(m_speed).arg(m_accelleration);
m_manager->post(request, json.toUtf8());
}
What's the problem of my change?
I am trying to connect to a FTP server but I got the following issue :
QObject::connect: No such slot Object::replyFinished
in ...\ here my program name ......
Where is my mistake? I suppose it is in the following code :
///////////////Connection.h file////////
class Connection : public QObject
{
public:
explicit Connection(QObject *parent=0);
Connection(QString uri, QString usernmae, QString password);
void FTP_Connection();
public slots:
void replyFinished(QNetworkReply *);
private:
QString URI;
QString USERNAME;
QString PASSWORD;
QNetworkAccessManager *manager;
};
///////////////Connection.cpp file////////
Connection::Connection(QString uri, QString usernmae, QString password)
{
this->URI=uri;
this->USERNAME=usernmae;
this->PASSWORD=password;
}
void Connection::FTP_Connection()
{
QUrl url(this->URI);
url.setUserName(this->USERNAME);
url.setPassword(this->PASSWORD);
url.setPort(21);
QNetworkRequest request(url);
manager=new QNetworkAccessManager(this);
connect(manager,
SIGNAL(finished(QNetworkReply*)),
this,
SLOT(replyFinished(QNetworkReply *)));
manager->get(request);
}
///////////////main.cpp file////////
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Connection *con=new Connection("ftp://192.168.3.62//",
"win7",
"053253");
con->FTP_Connection();
return a.exec();
}
i am a beginner in c++ and i am trying to retrieve data from a website using http request and to download the data in a file .
I am using the classes :
QMainWindow
QtNetwork/QNetworkAccessManager
QtNetwork/QNetworkRequest
QtNetwork/QNetworkReply
QUrl
The thing is that the file is created but there is no data in the file and i am getting an error that i don't understand . I searched through the forum found some similar kind of problems but did not understand as i am a beginner . Please help me its a school project and i am really stuck here.
Here is the httpWindow.h code
#ifndef HTTPWINDOW_H
#define HTTPWINDOW_H
#include <QMainWindow>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QUrl>
#include <QString>
class QFile;
namespace Ui {
class httpWindow;
}
class httpWindow : public QMainWindow
{
Q_OBJECT
public:
explicit httpWindow(QWidget *parent = 0);
~httpWindow();
void request(QUrl url);
private slots:
void downloadFile();
void httpFinished();
void httpReadyRead();
private:
Ui::httpWindow *ui;
QUrl url;
QNetworkAccessManager *manager;
QNetworkRequest requete;
QNetworkReply *reply;
QFile *file;
int httpGetId;
bool httpRequestAborted;
};
#endif // HTTPWINDOW_H
Here is the httpwindow.cpp
#include <QtWidgets>
#include <qnetwork.h>
#include <QString>
#include "httpwindow.h"
#include "ui_httpwindow.h"
httpWindow::httpWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::httpWindow)
{
ui->setupUi(this);
downloadFile();
}
httpWindow::~httpWindow()
{
delete ui;
}
void httpWindow::request(QUrl url)
{
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished()),
this, SLOT(httpFinished()));
//requete.setUrl(QUrl("http://fxrates.fr.forexprostools.com/index.php?force_lang=5&pairs_ids=1;3;2;4;7;5;8;6;&header-text-color=%23FFFFFF&curr-name-color=%230059b0&inner-text-color=%23000000&green-text-color=%232A8215&green-background=%23B7F4C2&red-text-color=%23DC0001&red-background=%23FFE2E2&inner-border-color=%23CBCBCB&border-color=%23cbcbcb&bg1=%23F6F6F6&bg2=%23ffffff&bid=show&ask=show&last=show&change=hide&last_update=hide"));
requete.setUrl(url);
reply = manager->get(requete);
connect(reply, SIGNAL(&reply::readyRead()), this, SLOT(httpReadyRead()));
}
void httpWindow::downloadFile()
{
QMessageBox msg ;
QUrl url("http://fxrates.fr.forexprostools.com/index.php?force_lang=5&pairs_ids=1;3;2;4;7;5;8;6;&header-text-color=%23FFFFFF&curr-name-color=%230059b0&inner-text-color=%23000000&green-text-color=%232A8215&green-background=%23B7F4C2&red-text-color=%23DC0001&red-background=%23FFE2E2&inner-border-color=%23CBCBCB&border-color=%23cbcbcb&bg1=%23F6F6F6&bg2=%23ffffff&bid=show&ask=show&last=show&change=hide&last_update=hide") ;
qDebug() << url.toString();
QFileInfo fileInfo(url.path());
//msg.setText("fileInfo = " + fileInfo);
QString fileName = "C:\\testQt\\" + fileInfo.fileName();
msg.setText("fileName = " + fileName);
if (fileName.isEmpty()){
fileName = "C:\testQt\fichier.html";
msg.setText(" création d'un nouveau fichier fichier.html ");
}
if (QFile::exists(fileName)) {
QFile::remove(fileName);
return;
}
file = new QFile(fileName);
msg.setText(" QFile::exists(fileName) == true , file : ");
if (!file->open(QIODevice::WriteOnly)) {
delete file;
file = 0;
return;
}
// schedule the request
httpRequestAborted = false;
request(url);
}
void httpWindow::httpFinished()
{
if (httpRequestAborted) {
if (file) {
file->close();
file->remove();
delete file;
file = 0;
}
reply->deleteLater();
return;
}
file->flush();
file->close();
QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (reply->error()) {
file->remove();
// QMessageBox::information(this, tr("HTTP"),
// tr("Download failed: %1.")
// .arg(reply->errorString()));
// downloadButton->setEnabled(true);
} else if (!redirectionTarget.isNull()) {
QUrl newUrl = url.resolved(redirectionTarget.toUrl());
// if (QMessageBox::question(this, tr("HTTP"),
// tr("Redirect to %1 ?").arg(newUrl.toString()),
// QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
url = newUrl;
reply->deleteLater();
file->open(QIODevice::WriteOnly);
file->resize(0);
request(url);
return;
}
reply->deleteLater();
reply = 0;
delete file;
file = 0;
}
void httpWindow::httpReadyRead()
{
// this slot gets called every time the QNetworkReply has new data.
// We read all of its new data and write it into the file.
// That way we use less RAM than when reading it at the finished()
// signal of the QNetworkReply
if (file)
file->write(reply->readAll());
}
Here is the main.cpp code
#include "httpwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
httpWindow w;
w.show();
return a.exec();
}
The errors :
can't find linker symbol for virtual table for `QMessageBox' value
found `RGB_MASK' instead
can't find linker symbol for virtual table for `QMessageBox' value
found `RGB_MASK' instead
"http://fxrates.fr.forexprostools.com/index.php?force_lang=5&pairs_ids=1;3;2;4;7;5;8;6;&header-text-color=%23FFFFFF&curr-name-color=%230059b0&inner-text-color=%23000000&green-text-color=%232A8215&green-background=%23B7F4C2&red-text-color=%23DC0001&red-background=%23FFE2E2&inner-border-color=%23CBCBCB&border-color=%23cbcbcb&bg1=%23F6F6F6&bg2=%23ffffff&bid=show&ask=show&last=show&change=hide&last_update=hide"
QObject::connect: No such signal QNetworkAccessManager::finished() in ..\ppe3_trading_test\httpwindow.cpp:24
QObject::connect: (receiver name: 'httpWindow')
QObject::connect: No such signal QNetworkReplyHttpImpl::&reply::readyRead() in ..\ppe3_trading_test\httpwindow.cpp:31
QObject::connect: (receiver name: 'httpWindow')
Please do help me its really important for my schooling .
connect(reply, SIGNAL(&reply::readyRead()), this, SLOT(httpReadyRead()));
You're mixing up old syntax and new syntax, it should be
connect(reply, SIGNAL(readyRead()), this, SLOT(httpReadyRead()));
or better yet using new syntax(Qt5 only):
connect(reply, &QNetworkReply::readyRead, this, &httpWindow::httpReadyRead);
QNetworkAccessManager doesn't have a finished() signal it has a finished(QNetworkReply*) signal, read the docs.
This is my code (C++: Qt) for getting webpage source:
QString htmlString;
QEventLoop eventLoop;
QNetworkAccessManager mgr;
QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
QNetworkRequest req( QUrl( QString( "http://stackoverflow.com" ) ) );
QNetworkReply *reply = mgr.get(req);
eventLoop.exec();
htmlString = reply->readAll();
Is there any way to get webpage source with progress bar ?!
Write special class for this:
#ifndef DOWNLOADER_H
#define DOWNLOADER_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QDebug>
#include <QProgressBar>
class Downloader : public QObject
{
Q_OBJECT
public:
explicit Downloader(QObject *parent = 0);
void doDownload();
public slots:
void replyFinished (QNetworkReply *reply);
void updateDownloadProgress(qint64, qint64);
private:
QNetworkAccessManager *manager;
QProgressBar *bar;
};
#endif
Cpp:
Downloader::Downloader(QObject *parent) :
QObject(parent)
{
}
void Downloader::doDownload()
{
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
QNetworkReply * rep = manager->get(QNetworkRequest(QUrl("http://qt-project.org/")));
connect(rep, SIGNAL(downloadProgress(qint64, qint64)),
this, SLOT(updateDownloadProgress(qint64, qint64)));
bar = new QProgressBar;
bar->show();
}
void Downloader::replyFinished (QNetworkReply *reply)
{
if(reply->error())
{
qDebug() << "ERROR!";
qDebug() << reply->errorString();
}
else
{
qDebug() << reply->readAll();
}
reply->deleteLater();
}
void Downloader::updateDownloadProgress(qint64 read, qint64 total)
{
qDebug() << read << total;
bar->setMaximum(total);
bar->setValue(read);
}
Usage:
Downloader down;
down.doDownload();
Main idea here is to use void QNetworkReply::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) [signal] to get progress and show this progress in QProgressBar.
And you can do this with your current code without class:
QString htmlString;
QEventLoop eventLoop;
QNetworkAccessManager mgr;
QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
QProgressBar *bar = new QProgressBar;
bar->show();
QNetworkRequest req( QUrl( QString( "http://stackoverflow.com" ) ) );
QNetworkReply *reply = mgr.get(req);
QObject::connect(reply,&QNetworkReply::downloadProgress,[=](qint64 bytesReceived, qint64 bytesTotal) {//with lambda
bar->setMaximum(bytesTotal);
bar->setValue(bytesReceived);
});
eventLoop.exec();
htmlString = reply->readAll();
qDebug() << htmlString;
I used here C++11 (CONFIG += c++11 to .pro file) and new syntax of signals and slots.