1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
#include <QDomDocument>
#include <QEventLoop>
#include <QFile>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QThread>
#include <ThreadWeaver/Exception>
#include <ThreadWeaver/ThreadWeaver>
#include "MainWidget.h"
#include "ViewController.h"
ViewController::ViewController(MainWidget *mainwidget)
: QObject() // no parent
, m_apiPostUrl(QStringLiteral("http://fickedinger.tumblr.com/api/read?id=94635924143"))
//@@snippet_begin(hellointernet-sequence)
{
connect(this, SIGNAL(setImage(QImage)), mainwidget, SLOT(setImage(QImage)));
connect(this, SIGNAL(setCaption(QString)), mainwidget, SLOT(setCaption(QString)));
connect(this, SIGNAL(setStatus(QString)), mainwidget, SLOT(setStatus(QString)));
using namespace ThreadWeaver;
auto s = new Sequence;
*s << make_job([=]() {
loadPlaceholderFromResource();
}) << make_job([=]() {
loadPostFromTumblr();
}) << make_job([=]() {
loadImageFromTumblr();
});
stream() << s;
}
//@@snippet_end
ViewController::~ViewController()
{
ThreadWeaver::Queue::instance()->finish();
}
//@@snippet_begin(hellointernet-loadresource)
void ViewController::loadPlaceholderFromResource()
{
QThread::msleep(500);
showResourceImage("IMG_20140813_004131.png");
Q_EMIT setStatus(tr("Downloading post..."));
}
//@@snippet_end
//@@snippet_begin(hellointernet-loadpost)
void ViewController::loadPostFromTumblr()
{
const QUrl url(m_apiPostUrl);
auto const data = download(url);
Q_EMIT setStatus(tr("Post downloaded..."));
QDomDocument doc;
if (!doc.setContent(data)) {
error(tr("Post format not recognized!"));
}
auto textOfFirst = [&doc](const char *name) {
auto const s = QString::fromLatin1(name);
auto elements = doc.elementsByTagName(s);
if (elements.isEmpty()) {
return QString();
}
return elements.at(0).toElement().text();
};
auto const caption = textOfFirst("photo-caption");
if (caption.isEmpty()) {
error(tr("Post does not contain a caption!"));
}
Q_EMIT setCaption(caption);
auto const imageUrl = textOfFirst("photo-url");
if (imageUrl.isEmpty()) {
error(tr("Post does not contain an image!"));
}
m_fullPostUrl = attributeTextFor(doc, "post", "url-with-slug");
if (m_fullPostUrl.isEmpty()) {
error(tr("Response does not contain URL with slug!"));
}
m_imageUrl = QUrl(imageUrl);
showResourceImage("IMG_20140813_004131-colors-cubed.png");
Q_EMIT setStatus(tr("Downloading image..."));
QThread::msleep(500);
}
//@@snippet_end
void ViewController::loadImageFromTumblr()
{
auto const data = download(m_imageUrl);
Q_EMIT setStatus(tr("Image downloaded..."));
const QImage image = QImage::fromData(data);
if (!image.isNull()) {
Q_EMIT setImage(image);
Q_EMIT setStatus(tr("Download complete (see %1).").arg(m_fullPostUrl));
} else {
error(tr("Image format error!"));
}
}
QByteArray ViewController::download(const QUrl &url)
{
QNetworkAccessManager manager;
QEventLoop loop;
QObject::connect(&manager, SIGNAL(finished(QNetworkReply *)), &loop, SLOT(quit()));
auto reply = manager.get(QNetworkRequest(url));
loop.exec();
if (reply->error() == QNetworkReply::NoError) {
const QByteArray data = reply->readAll();
return data;
} else {
error(tr("Unable to download data for \"%1\"!").arg(url.toString()));
return QByteArray();
}
}
//@@snippet_begin(hellointernet-error)
void ViewController::error(const QString &message)
{
showResourceImage("IMG_20140813_004131-colors-cubed.png");
Q_EMIT setCaption(tr("Error"));
Q_EMIT setStatus(tr("%1").arg(message));
throw ThreadWeaver::JobFailed(message);
}
//@@snippet_end
void ViewController::showResourceImage(const char *file)
{
const QString path(QStringLiteral("://resources/%1").arg(QString::fromLatin1(file)));
Q_ASSERT(QFile::exists(path));
const QImage i(path);
Q_ASSERT(!i.isNull());
Q_EMIT setImage(i);
}
QString ViewController::attributeTextFor(const QDomDocument &doc, const char *tag, const char *attribute)
{
auto const tagString = QString::fromLatin1(tag);
auto const attributeString = QString::fromLatin1(attribute);
auto elements = doc.elementsByTagName(tagString);
if (elements.isEmpty()) {
return QString();
}
const QString content = elements.at(0).toElement().attribute(attributeString);
return content;
}
#include "moc_ViewController.cpp"
|