So, after I make my QJsonModel, load the data, and set the treeView model, it will load the data normally into the treeView. Although, when I do this after a network request has been finished (serviceRequestFinished(QNetworkReply* reply)), it just doesn't woek. I can qDebug the Json data that is passed, but when it comes down to the Json loading and the model setting. It just fails to finish. Also, for some reason it won't set the Json from the network request, but if I just set it to set the json from a separate button, the json get added successfully. So that means that the Json is formatted correctly. The QJsonModel & QJsonItem are external classes not provided with Qt, that located here.
Here is my code:
Mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QModelIndex>
#include <QItemSelection>
#include <QFile>
#include <QFileInfo>
#include <QList>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QStringList>
#include <QTimer>
#include <QUrl>
#include <QTreeWidgetItem>
#include <QJsonDocument>
#include <QJsonObject>
#include "qjsonmodel.h"
#include <QClipboard>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
void setJson(QString json);
void getPlaylistList(QString accessToken);
QString disableStreams();
void appendEditValues(int currentRow);
void addVectorItems();
void streamCheck();
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_radioButtonNoStream_clicked()
{
streamCheck();
}
void on_radioButtonTwitchStream_clicked()
{
streamCheck();
}
void on_radioButtonYTStream_clicked()
{
streamCheck();
}
void on_pushButtonAddVid_clicked();
void on_pushButtonApplyAddVid_clicked();
void on_pushButtonDeleteSelection_clicked();
void on_pushButtonApplyAll_clicked();
public slots:
void serviceRequestFinished(QNetworkReply* reply);
void connectAPI(QString code);
signals:
void authenticate(QString accessCode);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "authdialog.h"
#include <qDebug>
#include <QVector>
#include <QMessageBox>
#include <QStandardItemModel>
#include <QFile>
#include <QUrlQuery>
int val = 0;
int selected;
QVector<QString> vidTitles;
QVector<QString> vidUrls;
QVector<int> vidNumber;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
streamCheck();
ui->groupBoxEditVideo->setEnabled(false);
connect(this, SIGNAL(authenticate(QString)), SLOT(connectAPI(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::streamCheck()
{
if (ui->radioButtonNoStream->isChecked())
{
ui->groupBoxStreamSetup->setEnabled(false);
ui->groupBoxStreamSetup->setTitle("No Stream Selected!");
}
else if (ui->radioButtonTwitchStream->isChecked())
{
ui->groupBoxStreamSetup->setEnabled(true);
ui->groupBoxStreamSetup->setTitle("Twitch Setup");
}
else if (ui->radioButtonYTStream->isChecked())
{
ui->groupBoxStreamSetup->setEnabled(true);
ui->groupBoxStreamSetup->setTitle("YouTube Stream Setup");
}
}
void MainWindow::on_pushButtonAddVid_clicked()
{
AuthDialog *auth = new AuthDialog(this);
auth->setModal(true);
auth->exec();
delete auth;
}
void MainWindow::setJson(QString json)
{
qDebug() << json;
QJsonModel * model = new QJsonModel;
model->loadJson(json.toUtf8());
ui->treeView->setModel(model);
delete model;
}
void MainWindow::getPlaylistList(QString accessToken)
{
QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(serviceRequestFinished(QNetworkReply*)));
//
QNetworkRequest request(QUrl("https://www.googleapis.com/youtube/v3/search?part=snippet&forMine=true&order=viewCount&type=video&access_token=" + accessToken));
networkManager->get(request);
}
QString MainWindow::disableStreams()
{
QString line = "";
QString test = "";
QFile file;
file.setFileName("C:/WampStack/apache2/htdocs/index.html");
file.open(QIODevice::ReadWrite);
QTextStream in(&file);
while(!in.atEnd())
{
line += in.readAll();
}
if (line.contains("<!--t-->") && !line.contains("<!--y-->"))
{
//Twitch Stream is on, must turn it off
test = line.replace("<!--t-->", "<!--t");
test = test.replace("><!--tt-->", ">tt-->");
return test;
}
else if (line.contains("<!--y-->") && !line.contains("<!--t-->"))
{
//YouTube Stream is on, must turn it off
test = line.replace("<!--y-->", "<!--y");
test = test.replace("><!--yy-->", ">yy-->");
return test;
}
else if (line.contains("<!--y-->") && line.contains("<!--t-->"))
{
test = line.replace("<!--y-->", "<!--y");
test = test.replace("><!--yy-->", ">yy-->");
test = test.replace("<!--t-->", "<!--t");
test = test.replace("><!--tt-->", ">tt-->");
return test;
}
else
{
return line;
}
file.close();
return line;
}
void MainWindow::connectAPI(QString code)
{
QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(serviceRequestFinished(QNetworkReply*)));
QUrlQuery postData;
postData.addQueryItem("code", code);
postData.addQueryItem("client_id", "CLIENT-ID");
postData.addQueryItem("client_secret", "CLIENT-SECRET");
postData.addQueryItem("redirect_uri", "REDIRECT-URI");
postData.addQueryItem("grant_type", "authorization_code");
QNetworkRequest request(QUrl("https://accounts.google.com/o/oauth2/token"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
networkManager->post(request, postData.toString(QUrl::FullyEncoded).toUtf8());
}
void MainWindow::appendEditValues(int currentRow)
{
}
void MainWindow::addVectorItems()
{
}
void MainWindow::on_pushButtonApplyAddVid_clicked()
{
}
void MainWindow::on_pushButtonDeleteSelection_clicked()
{
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "Are you sure?", "Do you want to permanently delete this entry?", QMessageBox::Yes|QMessageBox::No);
if (reply == QMessageBox::Yes)
{
}
addVectorItems();
}
void MainWindow::on_pushButtonApplyAll_clicked()
{
QString line = disableStreams();
QFile::remove("C:/WampStack/apache2/htdocs/index.html");
QFile file;
file.setFileName("C:/WampStack/apache2/htdocs/index.html");
file.open(QIODevice::ReadWrite);
//Start code for streaming
if (ui->radioButtonTwitchStream->isChecked() && line.contains("<!--t") && line.contains(">tt-->") && !line.contains("<!--t-->") && !line.contains("<!--tt-->"))
{
QString test = line.replace("<!--t", "<!--t-->");
test = line.replace(">tt-->", "><!--tt-->");
QTextStream stream( &file );
stream << test;
}
else if (ui->radioButtonYTStream->isChecked() && line.contains("<!--y") && line.contains(">yy-->") && !line.contains("<!--y-->") && !line.contains("<!--yy-->"))
{
QString test = line.replace("<!--y", "<!--y-->");
test = test.replace(">yy-->", "><!--yy-->");
QTextStream stream( &file );
stream << test;
}
else if (ui->radioButtonNoStream->isChecked())
{
QTextStream stream(&file);
stream << line;
}
//End code for streaming
file.close();
}
void MainWindow::serviceRequestFinished(QNetworkReply* reply)
{
QByteArray json = reply->readAll();
QString output = QString::fromUtf8(json);
QJsonDocument settdoc = QJsonDocument::fromJson(output.toUtf8());
QJsonObject sett2 = settdoc.object();
if (val == 0)
{
val++;
getPlaylistList(sett2.value(QString("access_token")).toString());
}
else if (val == 1)
{
setJson(output.toUtf8());
}
}
Main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
QJsonModel only works if the the JSON's root element is an object (see the bug report on github.com). I guess your JSON's root is an array.
Related
In an earlier Question I asked about why my program/QTcpServer was crashing all the time, and I really appreciate the help I got from everyone.
However, I have decided to try and rebuild the Program from scratch in order to see why it crashes, and I may have found something.
Allow me to post the new Code below:
//mainwindow.h
#include <QMainWindow>
#include <QPushButton>
#include <QTextEdit>
#include <QStandardItemModel>
#include <QTcpServer>
#include <QTcpSocket>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void startServer();
void handleConnection();
void readMessage();
void ReadXML(QString XMLString);
private:
QPushButton *SServer;
QTextEdit * ContainerView; //not changing to QTableView just yet
int Pallet_Number;
QTcpServer *tcpServer;
QTcpSocket *tcpSocket;
};
//mainwindow.cpp
#include "mainwindow.h"
#include <QLabel>
#include <QLayout>
#include <QDebug>
#include <QDomDocument>
#include <QRegularExpression>
static QRegularExpression Box_Code("B");
static QRegularExpression Cylinder_Code("C");
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
SServer(new QPushButton("Start Listening")),
ContainerView(new /*QTableView*/QTextEdit),
tcpServer(new QTcpServer),
tcpSocket(new QTcpSocket)
{
QStringList HeaderRow;
HeaderRow.append("Pallet");
HeaderRow.append("Container");
HeaderRow.append("Code");
HeaderRow.append("Height");
HeaderRow.append("Breadth/Diameter");
HeaderRow.append("Length");
HeaderRow.append("Weight");
resize(800,300);
connect(SServer, &QPushButton::clicked, this, &MainWindow::startServer);
connect(tcpServer, &QTcpServer::newConnection, this, &MainWindow::handleConnection);
connect(tcpSocket, &QTcpSocket::readyRead, this, &MainWindow::handleConnection);
QLabel *Lab1(new QLabel("Listening on Port 6164"));
QHBoxLayout *HB(new QHBoxLayout);
QVBoxLayout *VB(new QVBoxLayout);
HB->addWidget(SServer);
HB->addWidget(Lab1);
VB->addItem(HB);
VB->addWidget(ContainerView);
QWidget *window(new QWidget);
window->setLayout(VB);
setCentralWidget(window);
}
MainWindow::~MainWindow()
{
}
void MainWindow::startServer()
{
if(!tcpServer->listen(QHostAddress::LocalHost, 6164)){
qDebug() << "Error connecting to Server";
tcpServer->close();
return;
} else {
qDebug() << "Started Successfully";
}
}
void MainWindow::handleConnection()
{
tcpSocket = tcpServer->nextPendingConnection();
qDebug() << "New Connection!";
connect(tcpSocket, &QTcpSocket::readyRead, this, &MainWindow::readMessage);
}
void MainWindow::readMessage()
{
ContainerView->clear(); //clear table to prepare for new XMLString
QByteArray buffer = tcpSocket->readAll();
QString FromContainer = QString::fromUtf8(buffer);
ReadXML(FromContainer);
}
void MainWindow::ReadXML(QString XMLString)
{
ContainerView->append(XMLString);
QDomDocument Xml_String;
Xml_String.setContent(XMLString);
QDomElement Xml_Root = Xml_String.documentElement();
if(Xml_Root.tagName() == "Pallets")
{
QDomElement Xml_Pallet = Xml_Root.firstChildElement();
while(!Xml_Pallet.isNull())
{
if(Xml_Pallet.tagName() == "Pallet")
{
int PN = Xml_Pallet.attribute("Number").toInt(nullptr,10);
QDomElement Box_Cyl = Xml_Pallet.firstChildElement();
while(!Box_Cyl.isNull())
{
if(Box_Cyl.tagName() == "Box")
{
QString BC = Box_Cyl.tagName();
ContainerView->append("Pallet No. " + QString::number(PN) + "\nContainer: " + BC);
// QDomElement Box_Info = Box_Cyl.firstChildElement();
// while(!Box_Info.isNull())
// {
// ...more code
// Box_Info = Box_Info.nextSiblingElement();
// }
} else if(Box_Cyl.tagName() == "Cylinder")
{
QString BC = Box_Cyl.tagName();
ContainerView->append("Pallet No. " + QString::number(PN) + "\nContainer: " + BC);
}
Box_Cyl = Box_Cyl.nextSiblingElement();
}
}
Xml_Pallet = Xml_Pallet.nextSiblingElement();
}
}
}
The XML String I am trying to read is shown below:
When I include the commented code to read the Elements within 'Box' or 'Cylinder' (I altered the code to check both sides), the program freezes.
This hasn't happened to me before, so I have no idea what to do.
Data Appending Problem While sending the data through Namedpipe using QT
localserver.h
#ifndef LOCALSERVER_H
#define LOCALSERVER_H
#include "QLocalSocket"
#include "QLocalServer"
class QLocalSocket;
class LocalServer : public QLocalServer
{
Q_OBJECT
public:
explicit LocalServer(QObject *parent = 0);
void send(QString &msj);
QLocalSocket *mSocket;
private slots:
void receive();
private:
};
#endif // LOCALSERVER_H
localserver.cpp
#include "localserver.h"
#include "QLocalSocket"
#include "QTextStream"
#include "QMessageBox"
LocalServer::LocalServer(QObject *parent) : QLocalServer(parent)
{
mSocket = nullptr;
connect(this,&LocalServer::newConnection,[&](){
mSocket = nextPendingConnection();
});
qDebug()<<"Hello World";
}
void LocalServer::send(QString &msj)
{
qDebug()<<"Sending Data";
if(mSocket)
{
QTextStream T(mSocket);
T<<msj.toStdString().c_str();
mSocket->flush();
}
}
void LocalServer::receive()
{
qDebug()<<"Im here";
QDataStream in(mSocket);
in.setVersion(QDataStream::Qt_5_2);
mSocket->readAll();
qDebug()<<"Data Received";
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "QProcess"
#include "QTimer"
#include "QLocalSocket"
#include "localserver.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
void Connection();
private slots:
void on_start_clicked();
void on_send_clicked();
void on_quit_clicked();
void detect_connection();
void connect_terminate();
void connected();
void send_data();
void receive_data();
QString RandomData();
void on_pbtn_Stop_clicked();
private:
Ui::Widget *ui;
LocalServer *mLocalServer;
QTimer *timer;
QLocalSocket *mSocket;
bool first;
QString data_received;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "QProcess"
#include "QDebug"
#include "localserver.h"
#include "QMessageBox"
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
Connection();
first = true;
}
void Widget::Connection()
{
mLocalServer = new LocalServer(this);
mLocalServer->listen("Server1");
connect(mLocalServer,SIGNAL(newConnection()),this,SLOT(detect_connection()));
first = true;
timer = new QTimer(this);
timer->setInterval(8);
connect(timer,SIGNAL(timeout()),this,SLOT(send_data()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_start_clicked()
{
timer->start();
}
void Widget::on_send_clicked()
{
timer->stop();
}
void Widget::on_quit_clicked()
{
timer->stop();
this->close();
}
void Widget::detect_connection()
{
qDebug()<<"Write Pipe Established";
mSocket = new QLocalSocket(this);
mSocket->connectToServer("Server2");
connect(mSocket,SIGNAL(disconnected()),this,SLOT(connect_terminate()));
connect(mSocket,SIGNAL(connected()),this,SLOT(connected()));
qDebug()<<"Connection Established, Ready to Read";
connect(mSocket,&QLocalSocket::readyRead, [&]() {
QTextStream T(mSocket);
ui->receivedText->addItem(T.readAll());
});
}
void Widget::connect_terminate()
{
qDebug()<<"Read Server Connection Terminated";
QString string = "Stop_Session";
mLocalServer->send(string);
ui->sentText->addItem(string);
}
void Widget::connected()
{
qDebug()<<"Socket Connected to Server";
QString s=" Connection Done ";
mLocalServer->send(s);
}
void Widget::send_data()
{
QString string = RandomData();
mLocalServer->send(string);
ui->sentText->addItem(string);
}
QString Widget::RandomData()
{
srand(time(NULL));
int random_number = rand()%(1920-0 + 1) + 0; // rand() return a number between 0 and RAND_MAX
int random_number1 = rand()%(1080-0 + 1) + 0;
int random_number2 = rand()%(10-0 + 1) + 0;
QString s="Contour,"+QString::number(random_number)+","+QString::number(random_number1)+","+QString::number(random_number2);
// Basically this data in "s" gives the actual contours detected data but am using a random generator to test the Local Server and Socket .
return s;
}
void Widget::receive_data()
{
QString string;
QTextStream T(mSocket);
T.readLine();
if(T.readAll()=="Stop")
{
qDebug()<<"Socket About to Close";
QString string = "Stop";
mLocalServer->send(string);
}
else
{
qDebug()<<"Program can continue"<<T.readAll();
}
}
void Widget::on_pbtn_Stop_clicked()
{
timer->stop();
}
At Receiver SIde Program
Receiver.cpp
void Receiver ::Declaration_Of_Server2()
{
// Declaration Of LocalServer i.e Server2
ServerIS = new LocalServer(this);
ServerIS->listen("Server2");
// Connect To a LocalSocket TO The Above LocalServer i.e Server_IS with Server_VS
connect(ServerIS,SIGNAL(newConnection()),this,SLOT(DetectConnection_WithServer1()));
}
void CoFire_MainPage::DetectConnection_WithServer1()
{
// Declaration of LocalSocket i.e Server_VS
SocketIS = new QLocalSocket(this);
SocketIS->connectToServer("Server1");
connect(SocketIS,SIGNAL(readyRead()),this,SLOT(Receiving_VS_Data()));
}
void CoFire_MainPage::Receiving_VS_Data()
{
// Receiving Vs Data From Socket "Socket_IS"
QTextStream msg(SocketIS);
QString str = msg.readLine();
qDebug()<<" VS DATA : "<<str;
}
By this am trying to send data ( example : Contour,1000,800,1 ) from one program to other program
with a speed of 1 data / 8msec but in real scenario it might even go to 1msec data transfer.
but by this at receving end every now and then incomming data is been appended
(example: Contour,1000,800,1Contour,200,400,1Contour,500,650,1 etc... ).
But actually expentected data is
1st
Contour,1000,800,1
next
Contour,200,400,1
next
Contour,500,650,1
etc....
This way the data is getting appeneded before i capture and process the data at receiver .
By this am loosing the precious information .
how do i solve this issue .
readLine() waits for an end-of-line ("\n" or "\r\n"), but in your case you do not send it, you must change to the following:
QString Widget::RandomData(){
srand(time(NULL));
int random_number = rand()%(1920-0 + 1) + 0; // rand() return a number between 0 and RAND_MAX
int random_number1 = rand()%(1080-0 + 1) + 0;
int random_number2 = rand()%(10-0 + 1) + 0;
return QString("Contour,%1,%2,%3\n")
.arg(random_number)
.arg(random_number1)
.arg(random_number2);
}
On the other hand it is not necessary to use the reference of the QString, and also it is unnecessary to use toStdString().c_str().
void LocalServer::send(const QString &msj)
{
qDebug()<<"Sending Data";
if(mSocket)
{
QTextStream T(mSocket);
T << msj;
mSocket->flush();
}
}
How to catch incorrect link errors? For example:
ftp://cddis.gsfc.nasa.gov/pub/slr/data/npt_crd/gracea/2010/gracea_20100101.npt.Z
-- this is incorrect link
Why doesn't any error signal work? Or How to determine the correct links? Please, write an example of correct work with errors.
#ifndef WIDGET_H
#define WIDGET_H
#include "Downloader.h"
#include <QWidget>
#include <QNetworkReply>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void onDownloadButtonClicked();
void onSelectTargetFolderButtonClicked();
void onCancelButtonClicked();
void onUpdateProgress(qint64 bytesReceived, qint64 bytesTotal);
void onResult(QNetworkReply *reply);
private:
Ui::Widget *ui;
Downloader m_downloader;
};
#endif // WIDGET_H
Widget.cpp
#include "Widget.h"
#include "ui_Widget.h"
#include <QFileDialog>
#include <QStandardPaths>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->downloadPushButton, &QPushButton::clicked, this, &Widget::onDownloadButtonClicked);
connect(ui->selectTargetFolderPushButton, &QPushButton::clicked, this, &Widget::onSelectTargetFolderButtonClicked);
connect(ui->cancelPushButton, &QPushButton::clicked, this, &Widget::onCancelButtonClicked);
connect(&m_downloader, &Downloader::updateDownloadProgress, this, &Widget::onUpdateProgress);
connect(&m_downloader.manager, &QNetworkAccessManager::finished, this, &Widget::onResult);
}
Widget::~Widget()
{
delete ui;
}
void Widget::onDownloadButtonClicked()
{
m_downloader.get(ui->targetFolderLineEdit->text(), ui->urlLineEdit->text());
}
void Widget::onSelectTargetFolderButtonClicked()
{
QString targetFolder = QFileDialog::getExistingDirectory(this,
tr("Select folder"),
QStandardPaths::writableLocation(QStandardPaths::DownloadLocation),
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
ui->targetFolderLineEdit->setText(targetFolder);
}
void Widget::onCancelButtonClicked()
{
m_downloader.cancelDownload();
ui->downloadProgressBar->setMaximum(100);
ui->downloadProgressBar->setValue(0);
}
void Widget::onUpdateProgress(qint64 bytesReceived, qint64 bytesTotal)
{
ui->downloadProgressBar->setMaximum(bytesTotal);
ui->downloadProgressBar->setValue(bytesReceived);
}
void Widget::onResult(QNetworkReply *reply)
{
if (reply->error()) {
qDebug() << "Error";
qDebug() << reply->error();
} else {
qDebug() << "Done";
}
}
Downloader.h
#ifndef DOWNLOADER_H
#define DOWNLOADER_H
#include <QNetworkAccessManager>
#include <QNetworkReply>
//class QNetworkReply;
class QFile;
class Downloader : public QObject
{
Q_OBJECT
using BaseClass = QObject;
public:
explicit Downloader(QObject* parent = nullptr);
bool get(const QString& targetFolder, const QUrl& url);
QNetworkReply* currentReply {nullptr};
QNetworkAccessManager manager;
QString fullName;
public slots:
void cancelDownload();
signals:
void updateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
private slots:
void onReadyRead();
void onReply(QNetworkReply* reply);
void errorSlot(QNetworkReply::NetworkError er);
private:
QFile* m_file {nullptr};
};
#endif // DOWNLOADER_H
Downloader.cpp
#include "Downloader.h"
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QFile>
#include <QDir>
Downloader::Downloader(QObject* parent) :
BaseClass(parent)
{
connect(&manager, &QNetworkAccessManager::finished, this, &Downloader::onReply);
}
bool Downloader::get(const QString& targetFolder, const QUrl& url)
{
qDebug() << "get";
if (targetFolder.isEmpty() || url.isEmpty())
{
return false;
}
fullName = targetFolder + QDir::separator() + url.fileName();
m_file = new QFile(fullName);
if (!m_file->open(QIODevice::WriteOnly))
{
delete m_file;
m_file = nullptr;
return false;
}
QNetworkRequest request(url);
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
currentReply = manager.get(request);
connect(currentReply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error),
this, &Downloader::errorSlot);
connect(currentReply, &QNetworkReply::readyRead, this, &Downloader::onReadyRead);
connect(currentReply, &QNetworkReply::downloadProgress, this, &Downloader::updateDownloadProgress);
return true;
}
void Downloader::onReadyRead()
{
qDebug() << "onReadyRead";
if (m_file)
{
m_file->write(currentReply->readAll());
}
}
void Downloader::cancelDownload()
{
qDebug() << "cancelDownload";
if (currentReply)
{
currentReply->abort();
}
}
void Downloader::onReply(QNetworkReply* reply)
{
qDebug() << "onReply";
if (reply->error() == QNetworkReply::NoError)
{
m_file->flush();
m_file->close();
}
else
{
m_file->remove();
}
delete m_file;
m_file = nullptr;
reply->deleteLater();
}
void Downloader::errorSlot(QNetworkReply::NetworkError er)
{
qDebug() << er;
}
I am trying to implement http://developer.nokia.com/community/wiki/Creating_an_HTTP_network_request_in_Qt and my code compiles without error but does not function. I have a warning that reply in "QNetworkReply* reply = nam->get(QNetworkRequest(url));" is not being used. I am sure this is my error and I am not setting up my HTTP GET correctly, but I am unsure of how to correct it.
//coreEng.h
#ifndef COREENG_H
#define COREENG_H
#include <QObject>
#include <QNetworkAccessManager>
class coreEng : public QObject
{
Q_OBJECT
public:
//coreEng(QObject);
coreEng(QObject *parent = 0) :
QObject(parent)
{
nam = new QNetworkAccessManager();
}
private slots:
public slots:
void connect();
void url(QNetworkReply *reply);
void finishedSlot(QNetworkReply* reply);
private:
QNetworkAccessManager* nam;
};
#endif // COREENG_H
//coreEng.cpp
"coreeng.h"
#include <QNetworkAccessManager>
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QImageReader>
void coreEng::connect(){
QObject::connect(nam, SIGNAL(finished(QNetworkReply*)),
this, SLOT(finishedSlot(QNetworkReply*)));
}
void coreEng::url(QNetworkReply*){
QUrl url("http://www.nyctelecomm.com");
QNetworkReply* reply = nam->get(QNetworkRequest(url));
}
void coreEng::finishedSlot(QNetworkReply* reply){
QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
QVariant redirectionTargetUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (reply->error() == QNetworkReply::NoError)
{
QImageReader imageReader(reply);
QImage pic = imageReader.read();
QByteArray bytes = reply->readAll(); // bytes
QString string(bytes); // string
}
else
{
}
//delete reply();
}
//main.cpp
#include <QCoreApplication>
#include "coreeng.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
coreEng mConnect;
mConnect.connect();
return a.exec();
}
changed void coreEng::url(QNetworkReply*) to void coreEng::url()
changed void url(QNetworkReply *reply); to void url();
added mConnect.url(); to main.cpp and I could see the http packet with wireshark exit the NIC and begin the session.
I don't know what the problem is...The compiler (Qt) runs program without errors, but the file is not downloaded...
Can you tell me please tell what is wrong?
I made by example "download", which is located in the qt folder. The only difference is that they have is a console, and I have windows application.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtNetwork>
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
class DownloadManager: public QObject
{
Q_OBJECT
QNetworkAccessManager manager;
QList<QNetworkReply *> currentDownloads;
public:
DownloadManager();
void doDownload(const QUrl &url);
QString saveFileName(const QUrl &url);
bool saveToDisk(const QString &filename, QIODevice *data);
public slots:
void execute();
void downloadFinished(QNetworkReply *reply);
};
#endif // MAINWINDOW_H
main.cpp
#include <QtGui/QApplication>
#include "mainwindow.h"
#include <QtNetwork>
#include <QNetworkAccessManager>
#include <QStringList>
#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
#include <QList>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QStringList>
#include <QTimer>
#include <QUrl>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
#if defined(Q_WS_S60)
w.showMaximized();
#else
w.show();
#endif
return a.exec();
}
DownloadManager::DownloadManager()
{
connect(&manager, SIGNAL(finished(QNetworkReply*)),
SLOT(downloadFinished(QNetworkReply*)));
}
void DownloadManager::doDownload(const QUrl &url)
{
QNetworkRequest request(url);
QNetworkReply *reply = manager.get(request);
currentDownloads.append(reply);
}
QString DownloadManager::saveFileName(const QUrl &url)
{
QString path = url.path();
QString basename = QFileInfo(path).fileName();
if (basename.isEmpty())
basename = "download";
if (QFile::exists(basename)) {
// already exists, don't overwrite
int i = 0;
basename += '.';
while (QFile::exists(basename + QString::number(i)))
++i;
basename += QString::number(i);
}
return basename;
}
bool DownloadManager::saveToDisk(const QString &filename, QIODevice *data)
{
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
fprintf(stderr, "Could not open %s for writing: %s\n",
qPrintable(filename),
qPrintable(file.errorString()));
return false;
}
file.write(data->readAll());
file.close();
return true;
}
void DownloadManager::execute()
{
QStringList args = QCoreApplication::instance()->arguments();
args[0]="http://www.google.ru/images/srpr/logo3w.png";
QString arg=args[0];
QUrl url = QUrl::fromEncoded(arg.toLocal8Bit());
doDownload(url);
}
void DownloadManager::downloadFinished(QNetworkReply *reply)
{
QUrl url = reply->url();
if (reply->error()) {
fprintf(stderr, "Download of %s failed: %s\n",
url.toEncoded().constData(),
qPrintable(reply->errorString()));
} else {
QString filename = saveFileName(url);
if (saveToDisk(filename, reply))
printf("Download of %s succeded (saved to %s)\n",
url.toEncoded().constData(), qPrintable(filename));
}
currentDownloads.removeAll(reply);
reply->deleteLater();
if (currentDownloads.isEmpty())
// all downloads finished
QCoreApplication::instance()->quit();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
DownloadManager manager;
manager.execute();
QTimer::singleShot(0, &manager, SLOT(execute()));
}
The problem is at that point of your code:
void MainWindow::on_pushButton_clicked()
{
DownloadManager manager;
manager.execute();
}
QNetworkAccessManager is asynchronous, so it needs an event loop to do any downloading. But when the function on_pushButton_clicked() returns and gives the control back to the event loop, the QNetworkAccessManager is already destroyed, and didn't have the time to do anything.
When you add a QMessageBox in DownloadManager::execute, you are in fact running another event loop withing the slot on_pushButton_clicked(), and it gives the opportunity to the QNetworkAccessManager to do its work.
The correct solution would be to allocate DownloadManager dynamically, and eventually to make it destroy itself when it has finished all downloads.
void MainWindow::on_pushButton_clicked()
{
DownloadManager *manager = new DownloadManager(this);
manager->execute();
}
void DownloadManager::downloadFinished(QNetworkReply *reply)
{
...
if (currentDownloads.isEmpty())
this->deleteLater();
}