PDA

View Full Version : Use qobject with external qt class



SirJonas
22nd October 2016, 01:48
The question is i can use one outside class with qobject and download some files of my webpage without use one only instance. I am trying to update the code because i dont want to use singleton i will need more instances. And i am trying to update this code to use qobject to connect my external class and use different instances not only one. And if it possible to pass some arguments like one string to say where i download the file.
Code:

Main.cpp:
```
#include <QCoreApplication>
#include <QDebug>
#include "downloader.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QObject::connect(&Downloader::instance(),&Downloader::testSignal,
[](){
QString s="http://myweb/currxml.php";

});
return a.exec();
}
```

download.h:
```
#ifndef Downloader_H
#define Downloader_H

#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QDateTime>
#include <QFile>
#include <QDebug>
class Downloader : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(Downloader)
public:
static Downloader &instance();
explicit Downloader(QObject *parent = nullptr);
QString s;
//virtual ~Downloader(){}

void doSomething();
signals:

void testSignal();

public slots:
//void testSlot();
void replyFinished (QNetworkReply *reply);

private:
QNetworkAccessManager *manager;

};

#endif // Downloader_H
```
downloader.cpp
```
#include "downloader.h"
#include <QDebug>


Downloader &Downloader::instance()
{
static Downloader _instance;
return _instance;
}

Downloader::Downloader(QObject *parent) : QObject(parent)
{
doSomething();
}

void Downloader::doSomething()
{
//emit testSignal();
qDebug() << "It's working!!!!";
manager = new QNetworkAccessManager(this);
manager->get(QNetworkRequest(QUrl(s)));
emit instance().testSignal();
}

void Downloader::replyFinished (QNetworkReply *reply)
{
if(reply->error())
{
qDebug() << "ERROR!";
qDebug() << reply->errorString();
}
else
{
//qDebug() << reply->header(QNetworkRequest::ContentTypeHeader).toStrin g();
//qDebug() << reply->header(QNetworkRequest::LastModifiedHeader).toDate Time().toString();
//qDebug() << reply->header(QNetworkRequest::ContentLengthHeader).toULo ngLong();
//qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute ).toInt();
//qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribu te).toString();
QString p = reply->request().url().fileName();
QFile *file = new QFile("C:/Users/moh/"+p);
if(file->open(QFile::Append))
{
file->write(reply->readAll());
file->flush();
file->close();
}
delete file;
}

reply->deleteLater();
}
```

anda_skoa
22nd October 2016, 10:42
I am not sure what you are trying to do but the connect looks fine.

But you never emit the signal after the connection has been established, so the lambda will never be called.

Cheers,
_

SirJonas
22nd October 2016, 11:05
I want to connect to my class since outside so i want to use qobject::connect.. but i dont need singletone instance. I only in the other class have one signal and slot to download files of my page.

Code:



main.cpp:

#include <QCoreApplication>
#include "downloader.h"

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

Downloader d;
d.doDownload("http://myweb/currxml.php");

return a.exec();
}

downloader.cpp:

#include "downloader.h"

Downloader::Downloader(QObject *parent) :
QObject(parent)
{
}

void Downloader::doDownload(QString s)
{
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));

manager->get(QNetworkRequest(QUrl(s)));
}

void Downloader::replyFinished (QNetworkReply *reply)
{
if(reply->error())
{
qDebug() << "ERROR!";
qDebug() << reply->errorString();
}
else
{
//qDebug() << reply->header(QNetworkRequest::ContentTypeHeader).toStrin g();
//qDebug() << reply->header(QNetworkRequest::LastModifiedHeader).toDate Time().toString();
//qDebug() << reply->header(QNetworkRequest::ContentLengthHeader).toULo ngLong();
//qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute ).toInt();
//qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribu te).toString();
QString p = reply->request().url().fileName();
QFile *file = new QFile("C:/Users/moh/"+p);
if(file->open(QFile::Append))
{
file->write(reply->readAll());
file->flush();
file->close();
}
delete file;
}

reply->deleteLater();
}

downloader.h:

#ifndef DOWNLOADER_H
#define DOWNLOADER_H

#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QDateTime>
#include <QFile>
#include <QDebug>

class Downloader : public QObject
{
Q_OBJECT
public:
explicit Downloader(QObject *parent = 0);

void doDownload(QString s);
QString r;

signals:

public slots:
void replyFinished (QNetworkReply *reply);

private:
QNetworkAccessManager *manager;

};

#endif // DOWNLOADER_H



Sorry if i changed the code or something but i was wrong i am not interesting to use singleton only trying to call since outside with qobject using signal and slots.

anda_skoa
22nd October 2016, 17:00
Sorry if i changed the code or something but i was wrong i am not interesting to use singleton only trying to call since outside with qobject using signal and slots.

There is no "outside" in your code.

Maybe you can explain what you want to do instead of posting code that apparently does not what you to do?

Cheers,
_

SirJonas
22nd October 2016, 20:33
I'm trying to download files of my webpage with one class separately. But when i include in the main of my program and do this since mainwindow:

Downloader d;
d.doDownload("http://myweb/currxml.php");
Not works so i was thinking to use qobject to call since outside. But when i use like you saw in the first post singleton instance only download the file one time. I think because i am using lambda and sigletone thing so i am using only one instance. like you see in the first post.
At the moment i think it's better to include in the main of my program like signal and slot. And then call with some sender . like:

connect(this, SIGNAL(finished(QNetworkReply*)),this, SLOT(replyFinished(QNetworkReply*)));
but one question i can emit the signal of this code like:
emit finished(QNetworkReply*); but not seems to works too.
I need some way to emit this signal without using button, other way.

Conclusion, i was trying to use one class separately qobject but i think like i always use one instance with singleton pattern only download the file one time. When i connect again not download the file. I tried the other way second post. But when i included to my mainwindow program seems like is outside class it cant to call.

So finally i was thinking to include to my mainwindow and do this, i repeat:

connect(this, SIGNAL(finished(QNetworkReply*)),this, SLOT(replyFinished(QNetworkReply*)));
But i need to emit the signal some way without buttons etc.

anda_skoa
23rd October 2016, 10:13
Not works so i was thinking to use qobject to call since outside.

What does not work.
Where to you want to "call to"? And why do you want to do that?



But when i use like you saw in the first post singleton instance only download the file one time.

That's what you code does. It has a single doDownload() call which has a single get() call.
Why would you think that this would download the file more than once?



I think because i am using lambda and sigletone thing so i am using only one instance. like you see in the first post.

This has nothing to do with singleton or lambda.
You only ever execute one get() call.




At the moment i think it's better to include in the main of my program like signal and slot. And then call with some sender . like:

connect(this, SIGNAL(finished(QNetworkReply*)),this, SLOT(replyFinished(QNetworkReply*)));
but one question i can emit the signal of this code like:
emit finished(QNetworkReply*); but not seems to works too.
I need some way to emit this signal without using button, other way.

You don't have to emit finished(QNetworkReply*), the QNetworkAccessManager does that.

Cheers,
_