2011-02-07 2 views
1

Я недавно начал утомительный процесс модуляции большого монолитного приложения для аудиоплеера, которое я написал примерно 2 месяца назад.QNetworkRequest (HTTP GET) не срабатывает, после рефакторинга в автономный класс

Этот процесс идет достаточно хорошо, хотя кажется, что один из методов (ScrobbleMedia - который, скорее всего, делает HTTP-запросы для отправки информации о воспроизводимой дорожке в last.fm), больше не кажется, что делает сетевые запросы.

Однако объект QUrl, который будет передан экземпляру QNetworkAccessManager/QNetworkRequest, строится правильно.

Для сравнения функциональная Mercurial-версия кода доступна на BitBucket.

Метод ScrobbleMedia в настоящее время выглядит следующим образом, после рефакторинга:

#include "scrobblemedia.h" 

#include <QDebug> 
#include <cstdio> 

ScrobbleMedia::ScrobbleMedia(QString asUsername, QString asPassword, 
         QString asArtist, QString asTrack, QString asAlbum) 
{ 

    QString KEndPointURL = "http://lastfmstats.livefrombmore.com/universalscrobbler/scrobble.php"; 
    QUrl iScrobbleEndPoint(KEndPointURL); 

     QNetworkAccessManager *iScrobbleDispatcher = new QNetworkAccessManager(this); 


iScrobbleEndPoint.addQueryItem("submissionType","track"); 
iScrobbleEndPoint.addQueryItem("username", asUsername); 
iScrobbleEndPoint.addQueryItem("password", asPassword); 
iScrobbleEndPoint.addQueryItem("artist", asArtist); 
iScrobbleEndPoint.addQueryItem("track", asTrack); 
iScrobbleEndPoint.addQueryItem("album", asAlbum); 
iScrobbleEndPoint.addQueryItem("number","1"); 
iScrobbleEndPoint.addQueryItem("duration","200"); 

iScrobbleDispatcher->get(QNetworkRequest(iScrobbleEndPoint)); 
connect(iScrobbleDispatcher, SIGNAL(finished(QNetworkReply*)), 
SLOT(replyFinished(QNetworkReply*))); 

// QString Outside = iScrobbleEndPoint.toEncoded(); 

qDebug() << "Received: " + 
    asUsername + " " + 
    asPassword + " " + 
    asArtist + " " + 
    asTrack + " " + 
     asAlbum; 

qDebug() << iScrobbleEndPoint.toString(); 

} 

ScrobbleMedia::~ScrobbleMedia() { 

} 

Соответствующий файл заголовка выглядит следующим образом:

#ifndef SCROBBLEMEDIA_H 
#define SCROBBLEMEDIA_H 

#include <QString> 
#include <QtNetwork> 
#include <QUrl> 
#include <QNetworkAccessManager> 



class ScrobbleMedia : public QObject 
{ 
    Q_OBJECT; 


private: 

public: 

    ScrobbleMedia(QString asUsername, QString asPassword, QString asArtist, QString asTrack, QString asAlbum); 
    ~ScrobbleMedia(); 

}; 

#endif // SCROBBLEMEDIA_H 

Я в настоящее время здание само приложение Против MinGW строить версии 4.7.0 библиотек Qt (входит в состав Qt SDK 2010.05) под Windows 7 x86-64.

Любая помощь будет оценена по достоинству.

Заранее спасибо.

+1

Два вопроса: почему точка с запятой после макроса Q_OBJECT? Почему в заголовке нет объявленного слота ответа()? Если вы находитесь в Windows, вы можете перекомпилировать свой проект, используя CONFIG + = консоль qmake, так как это позволит вам видеть предупреждения Qt во время выполнения (например, сообщения «нет такого слота»). –

+0

Спасибо, Сергей. Сегодня я обновлю код и дам вам знать, что произойдет (так как на данный момент у меня нет инструментальной возможности Qt). Точка с запятой была привычной, и я был не уверен в том, изменит ли это. – Tyson

+1

@Tyson, также вы должны предоставить свою версию Qt SDK. Есть много проблем с QNAM и final() сигналом для более старых версий Qt. – Johnny

ответ

0

После прочтения ряда различных источников информации (большинство из которых были противоречивыми), я обнаружил, что следующие результаты в рабочем решении - хотя и с косметической проблемой в отладочном выходе, который, похоже, не влияет операция (Object::connect: No such signal QNetworkReplyImpl::finished(QNetworkReply*) in ../AudioPlayer/scrobblemedia.cpp:29):

В scrobblemedia.cpp:

#include "scrobblemedia.h" 

#include <QDebug> 
#include <cstdio> 

ScrobbleMedia::ScrobbleMedia(QString asUsername, QString asPassword, 
          QString asArtist, QString asTrack, QString asAlbum) 
{ 

    QByteArray iDataSink; 
    QEventLoop iLoop; 

    QString KEndPointURL = "http://lastfmstats.livefrombmore.com/universalscrobbler/scrobble.php"; 
    QUrl iScrobbleEndPoint(KEndPointURL); 

    iScrobbleEndPoint.addQueryItem("submissionType","track"); 
    iScrobbleEndPoint.addQueryItem("username", asUsername); 
    iScrobbleEndPoint.addQueryItem("password", asPassword); 
    iScrobbleEndPoint.addQueryItem("artist", asArtist); 
    iScrobbleEndPoint.addQueryItem("track", asTrack); 
    iScrobbleEndPoint.addQueryItem("album", asAlbum); 
    iScrobbleEndPoint.addQueryItem("number","1"); 
    iScrobbleEndPoint.addQueryItem("duration","200"); 

    QNetworkAccessManager iScrobbleDispatcher; 
    QNetworkRequest iScrobbleRequest(iScrobbleEndPoint); 
    QNetworkReply *iScrobbleReply = iScrobbleDispatcher.get(iScrobbleRequest); 

    QObject::connect(iScrobbleReply, SIGNAL(finished(QNetworkReply*)), &iLoop, 
    SLOT(quit())); 

    iDataSink = iScrobbleReply->readAll(); 

    qDebug() << "Received: " + asUsername + " " + asPassword + " " + asArtist + " " + asTrack + " " + asAlbum; 

    qDebug() << iScrobbleEndPoint.toString(); 

    iLoop.exec(); 
} 

ScrobbleMedia::~ScrobbleMedia() { 

} 

void ScrobbleMedia::replyFinished(QNetworkReply*) { 

} 

void ScrobbleMedia::reallyDone() { 

    qDebug() << "We've probably successfully Scrobbled..."; 
} 

В scrobblemedia.h:

#ifndef SCROBBLEMEDIA_H 
#define SCROBBLEMEDIA_H 

#include <QString> 
#include <QtNetwork> 
#include <QUrl> 
#include <QNetworkAccessManager> 



class ScrobbleMedia : public QObject 
{ 
    Q_OBJECT 


private: 


public: 

    ScrobbleMedia(QString asUsername, QString asPassword, QString asArtist, QString asTrack, QString asAlbum); 
    ~ScrobbleMedia(); 

private slots: 
    void replyFinished(QNetworkReply*); 
    void reallyDone(); 

}; 

#endif // SCROBBLEMEDIA_H 

Спасибо всем за помощь.

Надеюсь, этот код послужит полезным шаблоном для других, в будущем.

+0

Где именно вызывается слот reallyDone()? Я не вижу этого в коде. Зачем вам нужен цикл событий? Если это не многопоточное приложение, то использование отдельного цикла событий необязательно, по крайней мере, или, возможно, даже опасно. И, наконец, ваша проблема не «косметическая». Вы получаете его, потому что пытаетесь подключиться к несуществующему сигналу 'finished (QNetworkReply *)' в iScrobbleReply. Он имеет только готовый() сигнал без параметров. Это QNetworkAccessManager, у которого есть завершенный() слот с параметром QNetworkReply *. Вот почему ваш метод quit() никогда не будет вызван. –

+0

reallyDone() не называется нигде - он просто оставлен после предыдущей попытки заставить работу работать. Идея цикла событий была предложена по адресу http://stackoverflow.com/questions/2572985/how-can-i-use-qt-to-get-html-code-of-the-redirected-page и, казалось, работала в мое дело. – Tyson

+0

Имея это в виду, я удалил 'reallyDone()' и определил 'void finished (QNetworkReply *)', в дополнение к обеспечению его реализации. Сам код по-прежнему работает (я вижу HTTP-запросы в Wireshark), но проблема с «бездонными слотами» - это что-то для более позднего, так как мне нужно уехать куда-нибудь скоро. – Tyson