File indexing completed on 2024-05-12 15:50:10
0001 #include <QDomDocument> 0002 #include <QEventLoop> 0003 #include <QFile> 0004 #include <QNetworkAccessManager> 0005 #include <QNetworkReply> 0006 #include <QNetworkRequest> 0007 #include <QThread> 0008 0009 #include <ThreadWeaver/Exception> 0010 #include <ThreadWeaver/ThreadWeaver> 0011 0012 #include "MainWidget.h" 0013 #include "ViewController.h" 0014 0015 ViewController::ViewController(MainWidget *mainwidget) 0016 : QObject() // no parent 0017 , m_apiPostUrl(QStringLiteral("http://fickedinger.tumblr.com/api/read?id=94635924143")) 0018 //@@snippet_begin(hellointernet-sequence) 0019 { 0020 connect(this, SIGNAL(setImage(QImage)), mainwidget, SLOT(setImage(QImage))); 0021 connect(this, SIGNAL(setCaption(QString)), mainwidget, SLOT(setCaption(QString))); 0022 connect(this, SIGNAL(setStatus(QString)), mainwidget, SLOT(setStatus(QString))); 0023 0024 using namespace ThreadWeaver; 0025 auto s = new Sequence; 0026 *s << make_job([=]() { 0027 loadPlaceholderFromResource(); 0028 }) << make_job([=]() { 0029 loadPostFromTumblr(); 0030 }) << make_job([=]() { 0031 loadImageFromTumblr(); 0032 }); 0033 stream() << s; 0034 } 0035 //@@snippet_end 0036 0037 ViewController::~ViewController() 0038 { 0039 ThreadWeaver::Queue::instance()->finish(); 0040 } 0041 0042 //@@snippet_begin(hellointernet-loadresource) 0043 void ViewController::loadPlaceholderFromResource() 0044 { 0045 QThread::msleep(500); 0046 showResourceImage("IMG_20140813_004131.png"); 0047 Q_EMIT setStatus(tr("Downloading post...")); 0048 } 0049 //@@snippet_end 0050 0051 //@@snippet_begin(hellointernet-loadpost) 0052 void ViewController::loadPostFromTumblr() 0053 { 0054 const QUrl url(m_apiPostUrl); 0055 0056 auto const data = download(url); 0057 Q_EMIT setStatus(tr("Post downloaded...")); 0058 0059 QDomDocument doc; 0060 if (!doc.setContent(data)) { 0061 error(tr("Post format not recognized!")); 0062 } 0063 0064 auto textOfFirst = [&doc](const char *name) { 0065 auto const s = QString::fromLatin1(name); 0066 auto elements = doc.elementsByTagName(s); 0067 if (elements.isEmpty()) { 0068 return QString(); 0069 } 0070 return elements.at(0).toElement().text(); 0071 }; 0072 0073 auto const caption = textOfFirst("photo-caption"); 0074 if (caption.isEmpty()) { 0075 error(tr("Post does not contain a caption!")); 0076 } 0077 Q_EMIT setCaption(caption); 0078 auto const imageUrl = textOfFirst("photo-url"); 0079 if (imageUrl.isEmpty()) { 0080 error(tr("Post does not contain an image!")); 0081 } 0082 0083 m_fullPostUrl = attributeTextFor(doc, "post", "url-with-slug"); 0084 if (m_fullPostUrl.isEmpty()) { 0085 error(tr("Response does not contain URL with slug!")); 0086 } 0087 m_imageUrl = QUrl(imageUrl); 0088 showResourceImage("IMG_20140813_004131-colors-cubed.png"); 0089 Q_EMIT setStatus(tr("Downloading image...")); 0090 QThread::msleep(500); 0091 } 0092 //@@snippet_end 0093 0094 void ViewController::loadImageFromTumblr() 0095 { 0096 auto const data = download(m_imageUrl); 0097 Q_EMIT setStatus(tr("Image downloaded...")); 0098 const QImage image = QImage::fromData(data); 0099 if (!image.isNull()) { 0100 Q_EMIT setImage(image); 0101 Q_EMIT setStatus(tr("Download complete (see %1).").arg(m_fullPostUrl)); 0102 } else { 0103 error(tr("Image format error!")); 0104 } 0105 } 0106 0107 QByteArray ViewController::download(const QUrl &url) 0108 { 0109 QNetworkAccessManager manager; 0110 QEventLoop loop; 0111 QObject::connect(&manager, SIGNAL(finished(QNetworkReply *)), &loop, SLOT(quit())); 0112 auto reply = manager.get(QNetworkRequest(url)); 0113 loop.exec(); 0114 if (reply->error() == QNetworkReply::NoError) { 0115 const QByteArray data = reply->readAll(); 0116 return data; 0117 } else { 0118 error(tr("Unable to download data for \"%1\"!").arg(url.toString())); 0119 return QByteArray(); 0120 } 0121 } 0122 0123 //@@snippet_begin(hellointernet-error) 0124 void ViewController::error(const QString &message) 0125 { 0126 showResourceImage("IMG_20140813_004131-colors-cubed.png"); 0127 Q_EMIT setCaption(tr("Error")); 0128 Q_EMIT setStatus(tr("%1").arg(message)); 0129 throw ThreadWeaver::JobFailed(message); 0130 } 0131 //@@snippet_end 0132 0133 void ViewController::showResourceImage(const char *file) 0134 { 0135 const QString path(QStringLiteral("://resources/%1").arg(QString::fromLatin1(file))); 0136 Q_ASSERT(QFile::exists(path)); 0137 const QImage i(path); 0138 Q_ASSERT(!i.isNull()); 0139 Q_EMIT setImage(i); 0140 } 0141 0142 QString ViewController::attributeTextFor(const QDomDocument &doc, const char *tag, const char *attribute) 0143 { 0144 auto const tagString = QString::fromLatin1(tag); 0145 auto const attributeString = QString::fromLatin1(attribute); 0146 auto elements = doc.elementsByTagName(tagString); 0147 if (elements.isEmpty()) { 0148 return QString(); 0149 } 0150 const QString content = elements.at(0).toElement().attribute(attributeString); 0151 return content; 0152 } 0153 0154 #include "moc_ViewController.cpp"