diff -r 000000000000 -r 876b1a06bc25 examples/flickrdemo/flickrdemo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/flickrdemo/flickrdemo.cpp Wed Aug 25 15:49:42 2010 +0300 @@ -0,0 +1,629 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part 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 Nokia Corporation 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 intialization + +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")); + + connect(downloadButton, SIGNAL(clicked()), this, SLOT(downloadButtonClicked())); + + // 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.")); + } + + 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)) { + QMessageBox::information(this, tr("Flickr Demo"), tr("Available Access Points not found.")); + return; + } + + 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() +{ + // 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")); +}