T.N.
T.N.

Reputation: 33

Emitted Signal Isn't Detected

I tried to emit signal finished() from my class. But when I'm connecting the signal to my slot, it didn't do anything.

My class' name is blend_install, I declared it as blendinstaller and tried to connect that to the QEventLoop.

....
QEventLoop ac;
connect(&blendinstaller, SIGNAL(finished()), &ac, SLOT(quit()));

blendinstaller.show_progress();
blendinstaller.download(); // this will execute everything and in the end emit finished()

ac.exec();
....

The download() function:

current_prog = BLEND_INSTALL_NONE;
emit progress_changed(current_prog);

manager = new QNetworkAccessManager;

file_handler = new QFile(downloadTo);

file_handler->open(QFile::WriteOnly);
.... handle error .... // each of this (error handling) will emit finished() signal and return;

.... // each of this will represent the process of reporting event changes (for logging), emit a SIGNAL()

QNetworkRequest request;
request.setUrl(QUrl(downloadFrom));

reply = manager->get(request);
event = new QEventLoop;
connect(reply,SIGNAL(finished()),event,SLOT(quit()));
connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(downloadError(QNetworkReply::NetworkError)));
connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(downloadProgressL(qint64,qint64)));


event->exec();

.... handle error ....

.... write reply.readAll() to file ....

....

// these are instruction for a custom QProcess instance
proc.setProgram(extractWith);
proc.setArguments(ar);
proc.setWorkingDirectory(downloadIn);

event = new QEventLoop;
connect(&proc,SIGNAL(finished(int)),event,SLOT(quit()));
connect(&proc,SIGNAL(error(QProcess::ProcessError)),this,SLOT(extractError(QProcess::ProcessError)));
connect(&proc,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(extractFinished(int,QProcess::ExitStatus)));

proc.start();
proc.open_console();

event->exec();

.... handle error ....

....

.... attempt to find output of QProcess (extract an archive) ....

.... handle error, output of QProcess not found ....

....

emit installed(installOn);
emit finished(); // the SIGNAL I want to get.

qDebug("It's finished installing!");

So, TL;DR each of errors handling will return from the function but also emit finished() and in the end of function (assuming there is no error) it will emit finished().

It won't quit the loop.

Any idea?

Upvotes: 0

Views: 259

Answers (1)

mfreiholz
mfreiholz

Reputation: 717

The problem with your download() method is, that it is already a synchron method. You don't need this event loop. You already do everything in event loops inside your download() method.

Side note: And you seem to have some memory leaks, since you create QEventLoop without parent and never delete it.

UPDATE #1: Your finished() event is not being handled by the outer QEventLoop (ac), because the finished() signal gets emitted before the QEventLoop even begins to handle events with exec(). As a ugly workarround you could invoke download() after exec() with a queued QMetaObject::invokeMethod() (Qt::QueuedConnection) call (but i would not recommend it).

Update #2 Here is a small example, which is not perfect, of course :P

class BlendDownloader
{
  Q_OBJECT

public:
  BlenDownloader() :
    _file(NULL)
  {
  }

  void download()
  {
    _file = new QFile("C:/myfile.blubb");

    QNetworkRequest req("your url here");
    QNetworkReply* reply = _mgr.get(req);
    QObject::connect(reply, SIGNAL(finished()), this, SLOT(onDownloadFinished()));
    // TODO: Also handle error callback here
  }

private slots:
  void onDownloadFinished()
  {
    QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
    reply->deleteLater();

    // Write response data to file.
    // Note: You might get problems with big files,
    // since this buffers the entire response of QNetworkReply
    // in internal buffer. It's better to use the "readyRead()"
    // signal and write incrementally.
    _file->write(reply->readAll());

    // Do your parsing stuff now and emit "finished()" at the end.
    // ... parsing, validation here ...

    // Clean up
    _file->close();
    delete _file;
    _file = NULL;

    emit finished();
  }

private:
  QNetworkManager _mgr;
  QFile* _file;
};

Upvotes: 1

Related Questions