/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the examples of the Qt Mobility Components. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "flickrdemo.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // static constant initialization const QSize FlickrDemo::gridSize = QSize(52, 52); const QSize FlickrDemo::thumbnailSize = QSize(50, 50); const QSize FlickrDemo::imageSize = QSize(150, 150); const QString FlickrDemo::apikey = QString("e36784df8a03fea04c22ed93318b291c"); FlickrDemo::FlickrDemo(QWidget* parent) : QMainWindow(parent), m_logfileInUse(false), m_session(0), m_pictureListReply(0), m_thumbnailReply(0), m_pictureReply(0), m_pages(0), m_page(1), m_satellitesInView(0), m_satellitesUsed(0), m_latitude(-1000), m_longitude(-1000), m_downloadPictureList(true), m_shuttingDown(false) { resize(252, 344); locationLabel = new QLabel(tr("Lat: Long:")); satellitesLabel = new QLabel(tr("Using 0 of 0 satellites")); listWidget = new XQListWidget(); downloadButton = new QPushButton(tr("Download Picture List")); QVBoxLayout *verticalLayout = new QVBoxLayout(); verticalLayout->addWidget(locationLabel); verticalLayout->addWidget(satellitesLabel); verticalLayout->addWidget(listWidget); verticalLayout->addWidget(downloadButton); QWidget *centralWidget = new QWidget; centralWidget->setLayout(verticalLayout); setCentralWidget(centralWidget); createMenus(); listWidget->setGridSize(gridSize); listWidget->setIconSize(thumbnailSize); m_progressDialog = new QProgressDialog(this); m_progressDialog->setModal(true); connect(m_progressDialog, SIGNAL(canceled()), this, SLOT(cancelDownload())); setWindowTitle(tr("Flickr Demo")); // QGeoPositionInfoSource m_location = QGeoPositionInfoSource::createDefaultSource(this); if (m_location == 0) { QNmeaPositionInfoSource *nmeaLocation = new QNmeaPositionInfoSource(QNmeaPositionInfoSource::SimulationMode, this); QFile *logFile = new QFile(QApplication::applicationDirPath() + QDir::separator() + "nmealog.txt", this); nmeaLocation->setDevice(logFile); m_location = nmeaLocation; m_logfileInUse = true; } // Listen gps position changes connect(m_location, SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(positionUpdated(QGeoPositionInfo))); // QGeoSatelliteInfoSource m_satellite = QGeoSatelliteInfoSource::createDefaultSource(this); // Listen satellite status changes if (m_satellite != 0) { connect(m_satellite, SIGNAL(satellitesInViewUpdated(const QList&)), this, SLOT(satellitesInViewUpdated(const QList&))); connect(m_satellite, SIGNAL(satellitesInUseUpdated(const QList&)), this, SLOT(satellitesInUseUpdated(const QList&))); } m_nam = new QNetworkAccessManager(this); QTimer::singleShot(0, this, SLOT(delayedInit())); } FlickrDemo::~FlickrDemo() { m_shuttingDown = true; m_location->stopUpdates(); if (m_satellite) m_satellite->stopUpdates(); if (m_pictureListReply) { m_pictureListReply->abort(); delete m_pictureListReply; } if (m_thumbnailReply) { m_thumbnailReply->abort(); delete m_thumbnailReply; } if (m_pictureReply) { m_pictureReply->abort(); delete m_pictureReply; } if (m_session) m_session->close(); } void FlickrDemo::delayedInit() { if (m_logfileInUse) { QMessageBox::information(this, tr("Flickr Demo"), tr("No GPS support detected, using GPS data from a sample log file instead.")); } #ifdef BEARER_IN_QTNETWORK QNetworkConfigurationManager manager; const bool canStartIAP = (manager.capabilities() & QNetworkConfigurationManager::CanStartAndStopInterfaces); QNetworkConfiguration cfg = manager.defaultConfiguration(); if (!cfg.isValid() || (!canStartIAP && cfg.state() != QNetworkConfiguration::Active)) { #else QTM_PREPEND_NAMESPACE(QNetworkConfigurationManager) manager; const bool canStartIAP = (manager.capabilities() & QTM_PREPEND_NAMESPACE(QNetworkConfigurationManager)::CanStartAndStopInterfaces); QTM_PREPEND_NAMESPACE(QNetworkConfiguration) cfg = manager.defaultConfiguration(); if (!cfg.isValid() || (!canStartIAP && cfg.state() != QTM_PREPEND_NAMESPACE(QNetworkConfiguration)::Active)) { #endif QMessageBox::information(this, tr("Flickr Demo"), tr("Available Access Points not found.")); qApp->quit(); } m_session = new QNetworkSession(cfg, this); m_connectivityHelper = new ConnectivityHelper(m_session, this); connect(m_session, SIGNAL(opened()), this, SLOT(networkSessionOpened())); connect(m_connectivityHelper, SIGNAL(networkingCancelled()), qApp, SLOT(quit())); m_session->open(); } void FlickrDemo::networkSessionOpened() { connect(downloadButton, SIGNAL(clicked()), this, SLOT(downloadButtonClicked())); // Start listening GPS position updates m_location->startUpdates(); // Start listening GPS satellite status changes if (m_satellite != 0) { m_satellite->startUpdates(); } else { satellitesLabel->setText(tr("GPS not detected, replaying coordinates from sample log file.")); } } void FlickrDemo::createMenus() { m_downloadAct = new QAction(tr("Download Picture List"), this); #if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) menuBar()->addAction(m_downloadAct); #endif connect(m_downloadAct, SIGNAL(triggered()), this, SLOT(downloadButtonClicked())); QAction* exitAct = new QAction(tr("Exit"), this); #if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) menuBar()->addAction(exitAct); #endif connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); } void FlickrDemo::positionUpdated(const QGeoPositionInfo &gpsPos) { if (gpsPos.isValid()) { QGeoCoordinate coord = gpsPos.coordinate(); m_latitude = coord.latitude(); m_longitude = coord.longitude(); locationLabel->setText(tr("Lat: %1 Long: %2").arg(QString::number(m_latitude), QString::number(m_longitude))); } } void FlickrDemo::satellitesInViewUpdated(const QList &satellites) { m_satellitesInView = satellites.count(); viewSatelliteInfo(); } void FlickrDemo::satellitesInUseUpdated(const QList &satellites) { m_satellitesUsed = satellites.count(); viewSatelliteInfo(); } void FlickrDemo::viewSatelliteInfo() { if (m_satellite != 0) { satellitesLabel->setText(tr("Using %1 of %2 satellites").arg(QString::number(m_satellitesUsed), QString::number(m_satellitesInView))); } else { satellitesLabel->setText(tr("GPS not detected, replaying coordinates from sample log file.")); } } void FlickrDemo::downloadButtonClicked() { if (m_downloadPictureList) { downloadFlickerPictureList(); } else { downloadPictureFromFlickr(); } } void FlickrDemo::downloadFlickerPictureList() { if (m_latitude == -1000 || m_longitude == -1000) { if (QMessageBox::question(this, tr("Flickr Demo"), tr("No satellite connection.\n""Use hard coded coordinates?"), QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Cancel) { return; } // If GPS signal is not detected, Tampere area is used as default location m_latitude = 61.4500; m_longitude = 23.8502; } // Set IAP name satellitesLabel->setText(tr("Access Point: %1").arg(m_session->configuration().name())); locationLabel->setText(tr("Lat: %1 Long: %2").arg(QString::number(m_latitude), QString::number(m_longitude))); QString urlstring = "http://api.flickr.com/services/rest/?min_taken_date=2000-01-01+0:00:00&extras=date_taken&method=flickr.photos.search&per_page=30&sort=date-taken-desc"; urlstring.append("&api_key="); urlstring.append(apikey); urlstring.append("&lat="); urlstring.append(QString::number(m_latitude)); urlstring.append("&lon="); urlstring.append(QString::number(m_longitude)); urlstring.append("&page="); urlstring.append(QString::number(m_page)); QUrl url(urlstring); QNetworkRequest req(url); m_pictureListReply = m_nam->get(req); connect(m_pictureListReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(pictureListDownloadProgress(qint64, qint64))); connect(m_pictureListReply, SIGNAL(finished()), this, SLOT(pictureListFinished())); connect(m_pictureListReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(pictureListError(QNetworkReply::NetworkError))); m_progressDialog->setWindowTitle(tr("FlickrDemo")); m_progressDialog->setLabelText(tr("Downloading\nPicture List.")); m_progressDialog->setMaximum(10); m_progressDialog->setValue(0); m_progressDialog->show(); } bool FlickrDemo::parsePictureList(QString xmlString) { QString errorStr; int errorLine; int errorColumn; QDomDocument domDocument; if (!domDocument.setContent(xmlString, true, &errorStr, &errorLine, &errorColumn)) { QMessageBox::information(window(), tr("Flickr Demo"), tr("XML Parse error at line %1, column %2:\n%3").arg(errorLine).arg(errorColumn).arg(errorStr)); return false; } QDomElement root = domDocument.documentElement(); if (root.tagName() != "rsp") { QMessageBox::information(window(), tr("Flickr Demo"), tr("Invalid XML format.")); return false; } if (root.attribute("stat") != "ok") { QMessageBox::information(window(), tr("Flickr Demo"), tr("Query failed.")); return false; } listWidget->clear(); QListWidgetItem* listItem; QDomElement photosElement = root.firstChildElement("photos"); if (!photosElement.isNull()) { m_pages = (photosElement.attribute("pages")).toInt(); m_page = (photosElement.attribute("page")).toInt(); QDomElement child = photosElement.firstChildElement("photo"); while (!child.isNull()) { QString url = "http://farm"; url.append(child.attribute("farm")); url.append(".static.flickr.com/"); url.append(child.attribute("server")); url.append("/"); url.append(child.attribute("id")); url.append("_"); url.append(child.attribute("secret")); m_names << url; listItem = new QListWidgetItem(child.attribute("title")); QImage image(thumbnailSize, QImage::Format_Mono); image.fill(1); listItem->setIcon(QPixmap::fromImage(image)); listItem->setData(Qt::UserRole, url); listWidget->addItem(listItem); child = child.nextSiblingElement("photo"); } } else { return false; } m_nameCounter = -1; downloadNextThumbnail(); return true; } void FlickrDemo::downloadPictureFromFlickr() { QListWidgetItem* item = listWidget->currentItem(); if (!item) { return; } QString pictureUrl = item->data(Qt::UserRole).toString(); pictureUrl.append("_m.jpg"); QUrl url(pictureUrl); QNetworkRequest req(url); m_pictureReply = m_nam->get(req); connect(m_pictureReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(pictureDownloadProgress(qint64, qint64))); connect(m_pictureReply, SIGNAL(finished()), this, SLOT(pictureFinished())); connect(m_pictureReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(pictureError(QNetworkReply::NetworkError))); m_progressDialog->setWindowTitle(tr("Flickr Demo")); m_progressDialog->setLabelText(tr("Downloading:\n%1").arg(pictureUrl)); m_progressDialog->setMaximum(10); m_progressDialog->setValue(0); m_progressDialog->show(); downloadButton->setEnabled(false); } void FlickrDemo::cancelDownload() { if (m_pictureListReply) { m_pictureListReply->abort(); delete m_pictureListReply; m_pictureListReply = 0; } if (m_pictureReply) { m_pictureReply->abort(); delete m_pictureReply; m_pictureReply = 0; } downloadButton->setEnabled(true); } void FlickrDemo::pictureListDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { m_progressDialog->setMaximum(bytesTotal); m_progressDialog->setValue(bytesReceived); } void FlickrDemo::pictureListFinished() { m_progressDialog->hide(); if (parsePictureList(QString::fromUtf8(m_pictureListReply->readAll()))) { m_downloadPictureList = false; downloadButton->setText(tr("Download Selected Picture")); m_downloadAct->setText(tr("Download Selected Picture")); } downloadButton->setEnabled(true); QTimer::singleShot(0, this, SLOT(clearPictureListRequest())); } void FlickrDemo::pictureListError(QNetworkReply::NetworkError /*code*/) { if (m_shuttingDown) return; m_progressDialog->hide(); QMessageBox::information(this, tr("Flickr Demo"), tr("Error downloading picture list: %1.").arg(m_pictureListReply->errorString())); QTimer::singleShot(0, this, SLOT(clearPictureListRequest())); } void FlickrDemo::clearPictureListRequest() { delete m_pictureListReply; m_pictureListReply = 0; } void FlickrDemo::thumbnailFinished() { QByteArray picture = m_thumbnailReply->readAll(); if (!picture.isNull() && picture.size() > 0) { QListWidgetItem* item = listWidget->item(m_nameCounter); QImage image; if (image.loadFromData(picture, "jpg")) { item->setIcon(QPixmap::fromImage( image.scaled(thumbnailSize, Qt::KeepAspectRatio, Qt::SmoothTransformation))); listWidget->update(); } } downloadNextThumbnail(); } void FlickrDemo::thumbnailError(QNetworkReply::NetworkError /*code*/) { if (m_shuttingDown) return; QMessageBox::information(this, tr("Flickr Demo"), tr("Error downloading thumbnails: %1.").arg(m_thumbnailReply->errorString())); QTimer::singleShot(0, this, SLOT(clearThumbnailRequest())); } void FlickrDemo::clearThumbnailRequest() { delete m_thumbnailReply; m_thumbnailReply = 0; } void FlickrDemo::pictureDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { m_progressDialog->setMaximum(bytesTotal); m_progressDialog->setValue(bytesReceived); } void FlickrDemo::pictureFinished() { m_progressDialog->hide(); downloadButton->setEnabled(true); QByteArray picture = m_pictureReply->readAll(); if (picture.isNull() || picture.size() <= 0) return; QImage image; if (!image.loadFromData(picture, "jpg")) return; QPixmap pixmap = QPixmap::fromImage( image.scaled(imageSize, Qt::KeepAspectRatio, Qt::SmoothTransformation)); displayImage(pixmap); QTimer::singleShot(0, this, SLOT(clearPictureRequest())); } void FlickrDemo::pictureError(QNetworkReply::NetworkError /*code*/) { if (m_shuttingDown) return; m_progressDialog->hide(); QMessageBox::information(this, tr("Flickr Demo"), tr("Error downloading picture: %1.").arg(m_pictureReply->errorString())); downloadButton->setEnabled(true); QTimer::singleShot(0, this, SLOT(clearPictureRequest())); } void FlickrDemo::clearPictureRequest() { delete m_pictureReply; m_pictureReply = 0; } void FlickrDemo::displayImage(const QPixmap &pixmap) { PictureDialog dialog(pixmap, listWidget->currentItem()->text(), this); #if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) dialog.showMaximized(); #endif dialog.exec(); } void FlickrDemo::downloadNextThumbnail() { m_nameCounter++; if (m_nameCounter < m_names.count()) { QString pictureUrl = m_names[m_nameCounter]; pictureUrl.append("_s.jpg"); QUrl url(pictureUrl); QNetworkRequest req(url); m_thumbnailReply = m_nam->get(req); connect(m_thumbnailReply, SIGNAL(finished()), this, SLOT(thumbnailFinished())); connect(m_thumbnailReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(thumbnailError(QNetworkReply::NetworkError))); } else { QTimer::singleShot(0, this, SLOT(clearThumbnailRequest())); } } PictureDialog::PictureDialog(const QPixmap& pixmap, const QString& pictureName, QWidget* parent) : QDialog(parent) { resize(252, 361); QVBoxLayout *verticalLayout = new QVBoxLayout(); verticalLayout->setSpacing(6); verticalLayout->setContentsMargins(11, 11, 11, 11); label = new QLabel(); label->setText(tr("Downloaded:\n%1").arg(pictureName)); QSizePolicy sizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); sizePolicy.setHorizontalStretch(0); sizePolicy.setVerticalStretch(0); sizePolicy.setHeightForWidth(label->sizePolicy().hasHeightForWidth()); label->setSizePolicy(sizePolicy); verticalLayout->addWidget(label); imageLabel = new QLabel(); imageLabel->setPixmap(pixmap); verticalLayout->addWidget(imageLabel); buttonBox = new QDialogButtonBox(); buttonBox->setStandardButtons(QDialogButtonBox::Close); connect(buttonBox, SIGNAL(rejected()), this, SLOT(accept())); verticalLayout->addWidget(buttonBox); setLayout(verticalLayout); setWindowTitle(tr("Flickr Demo")); }