summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/applicationinfo.cpp193
-rw-r--r--src/applicationinfo.h139
-rw-r--r--src/applicationpaths.h75
-rw-r--r--src/cities.cpp164
-rw-r--r--src/cities.h92
-rw-r--r--src/citieslistmodel.cpp125
-rw-r--r--src/citieslistmodel.h84
-rw-r--r--src/citymodel.cpp302
-rw-r--r--src/citymodel.h138
-rw-r--r--src/daymodel.cpp149
-rw-r--r--src/daymodel.h116
-rw-r--r--src/main.cpp138
-rw-r--r--src/src.pri16
-rw-r--r--src/weatherimageprovider.h72
14 files changed, 1803 insertions, 0 deletions
diff --git a/src/applicationinfo.cpp b/src/applicationinfo.cpp
new file mode 100644
index 0000000..dcbc54f
--- /dev/null
+++ b/src/applicationinfo.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QFile>
+#include <QtCore/qmath.h>
+#include <QtCore/QRegExp>
+#include <QtCore/QUrl>
+#include <QtCore/QUrlQuery>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QScreen>
+#include <QtNetwork/QNetworkReply>
+#include <QtNetwork/QNetworkRequest>
+
+#include "applicationinfo.h"
+#include "weatherimageprovider.h"
+#include <QDebug>
+
+ApplicationInfo::ApplicationInfo(WeatherImageProvider *provider)
+ : imageProvider(provider)
+{
+
+ m_isMobile = false;
+#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_BLACKBERRY)
+ m_isMobile = true;
+#endif
+
+ m_colors = new QQmlPropertyMap(this);
+ m_colors->insert(QLatin1String("white"), QVariant("#ffffff"));
+ m_colors->insert(QLatin1String("smokeGray"), QVariant("#eeeeee"));
+ m_colors->insert(QLatin1String("paleGray"), QVariant("#d7d6d5"));
+ m_colors->insert(QLatin1String("lightGray"), QVariant("#aeadac"));
+ m_colors->insert(QLatin1String("darkGray"), QVariant("#35322f"));
+ m_colors->insert(QLatin1String("mediumGray"), QVariant("#5d5b59"));
+ m_colors->insert(QLatin1String("doubleDarkGray"), QVariant("#1e1b18"));
+ m_colors->insert(QLatin1String("blue"), QVariant("#14aaff"));
+ m_colors->insert(QLatin1String("darkBlue"), QVariant("#14148c"));
+
+ m_constants = new QQmlPropertyMap(this);
+ m_constants->insert(QLatin1String("isMobile"), QVariant(m_isMobile));
+ m_constants->insert(QLatin1String("errorLoadingImage"), QVariant(tr("Error loading image - Host not found or unreachable")));
+
+ manager = new QNetworkAccessManager(this);
+ connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
+ m_citiesFound = new CitiesListModel(this);
+
+ QRect rect = qApp->primaryScreen()->geometry();
+ m_ratio = m_isMobile ? qMin(qMax(rect.width(), rect.height())/1136. , qMin(rect.width(), rect.height())/640.) : 1;
+ m_sliderHandleWidth = getSizeWithRatio(70);
+ m_sliderHandleHeight = getSizeWithRatio(87);
+ m_sliderGapWidth = getSizeWithRatio(100);
+ m_isPortraitMode = m_isMobile ? rect.height() > rect.width() : false;
+ m_hMargin = m_isPortraitMode ? 20 * ratio() : 50 * ratio();
+ m_applicationWidth = m_isMobile ? rect.width() : 1120;
+
+ m_currentIndexDay = -1;
+
+ if (m_isMobile)
+ connect(qApp->primaryScreen(), SIGNAL(physicalSizeChanged(QSizeF)), this, SLOT(notifyPortraitMode()));
+
+ // Search in English
+ // In order to use yr.no weather data service, refer to their terms
+ // and conditions of use. http://om.yr.no/verdata/free-weather-data/
+ QUrl searchUrl2("http://www.yr.no/_/settspr.aspx");
+ QUrlQuery query2;
+ query2.addQueryItem("spr", "eng");
+ query2.addQueryItem("redir", "/");
+ searchUrl2.setQuery(query2);
+ manager->get(QNetworkRequest(searchUrl2));
+}
+
+void ApplicationInfo::setCurrentCityModel(CityModel *model)
+{
+ if (model != m_currentCityModel)
+ {
+ m_currentCityModel = model;
+ emit currentCityModelChanged();
+ }
+}
+
+void ApplicationInfo::setCurrentIndexDay(const int index)
+{
+ if (index != m_currentIndexDay) {
+ m_currentIndexDay = index;
+ emit currentIndexDayChanged();
+ }
+}
+
+void ApplicationInfo::setApplicationWidth(const int newWidth)
+{
+ if (newWidth != m_applicationWidth) {
+ m_applicationWidth = newWidth;
+ emit applicationWidthChanged();
+ }
+}
+
+QString ApplicationInfo::getImagePath(const QString image)
+{
+ return QString("qrc:/weatherapp/qml/touch/images/%1").arg(image);
+}
+
+void ApplicationInfo::notifyPortraitMode()
+{
+ int width = qApp->primaryScreen()->geometry().width();
+ int height = qApp->primaryScreen()->geometry().height();
+ setIsPortraitMode(height > width);
+}
+
+void ApplicationInfo::setIsPortraitMode(const bool newMode)
+{
+ if (m_isPortraitMode != newMode) {
+ m_isPortraitMode = newMode;
+ m_hMargin = m_isPortraitMode ? 20 * ratio() : 50 * ratio();
+ emit portraitModeChanged();
+ emit hMarginChanged();
+ }
+}
+
+void ApplicationInfo::queryCities(const QString input)
+{
+ if (input.isEmpty())
+ return;
+ // In order to use yr.no weather data service, refer to their terms
+ // and conditions of use. http://om.yr.no/verdata/free-weather-data/
+ QUrl searchUrl("http://www.yr.no/_/websvc/jsonforslagsboks.aspx");
+ QUrlQuery query;
+ query.addQueryItem("s", input);
+ searchUrl.setQuery(query);
+ manager->get(QNetworkRequest(searchUrl));
+ m_citiesFound->clear();
+ waitForCitiesQueryReply(tr("Waiting for cities, network may be slow..."));
+}
+
+void ApplicationInfo::replyFinished(QNetworkReply *reply)
+{
+ waitForCitiesQueryReply("");
+ if (reply->request().url().query() != "spr=eng&redir=/" ) {
+ if (reply->error() != QNetworkReply::NoError) {
+ emit(errorOnQueryCities(tr("Network error: %1").arg(reply->errorString())));
+ m_citiesFound->addCities();
+ } else {
+ QString data = reply->readAll();
+ QRegExp regExp;
+ regExp.setPattern("^\\[\\[.*\\],\\[\\[(.*)\\]\\]\\]$");
+ regExp.exactMatch(data);
+ QString foundCities = regExp.capturedTexts().at(1);
+ QStringList citiesFound = foundCities.split(QRegExp("\\],\\["), QString::SkipEmptyParts);
+ m_citiesFound->addCities(citiesFound);
+ }
+ }
+ if (reply) {
+ reply->deleteLater();
+ reply = 0;
+ }
+}
+
diff --git a/src/applicationinfo.h b/src/applicationinfo.h
new file mode 100644
index 0000000..4e001dd
--- /dev/null
+++ b/src/applicationinfo.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef APPLICATIONINFO_H
+#define APPLICATIONINFO_H
+
+#include <QtCore/QObject>
+#include <QtQml/QQmlPropertyMap>
+
+QT_BEGIN_NAMESPACE
+class QNetworkAccessManager;
+class QNetworkReply;
+QT_END_NAMESPACE
+
+class WeatherImageProvider;
+
+#include "citymodel.h"
+#include "citieslistmodel.h"
+
+class ApplicationInfo : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int applicationWidth READ applicationWidth WRITE setApplicationWidth NOTIFY applicationWidthChanged)
+ Q_PROPERTY(QObject *colors READ colors CONSTANT)
+ Q_PROPERTY(QObject *constants READ constants CONSTANT)
+ Q_PROPERTY(bool isPortraitMode READ isPortraitMode WRITE setIsPortraitMode NOTIFY portraitModeChanged)
+ Q_PROPERTY(int currentIndexDay READ currentIndexDay WRITE setCurrentIndexDay NOTIFY currentIndexDayChanged)
+ Q_PROPERTY(CityModel *currentCityModel READ currentCityModel WRITE setCurrentCityModel NOTIFY currentCityModelChanged)
+ Q_PROPERTY(CitiesListModel *foundCities READ foundCities NOTIFY foundCitiesChanged)
+ Q_PROPERTY(qreal ratio READ ratio NOTIFY ratioChanged)
+ Q_PROPERTY(qreal hMargin READ hMargin NOTIFY hMarginChanged)
+ Q_PROPERTY(qreal sliderHandleWidth READ sliderHandleWidth NOTIFY ratioChanged)
+ Q_PROPERTY(qreal sliderHandleHeight READ sliderHandleHeight NOTIFY ratioChanged)
+ Q_PROPERTY(qreal sliderGapWidth READ sliderGapWidth NOTIFY ratioChanged)
+
+public:
+ ApplicationInfo(WeatherImageProvider *provider);
+
+ QQmlPropertyMap *colors() const { return m_colors; }
+ QQmlPropertyMap *constants() const { return m_constants; }
+
+ CityModel *currentCityModel() const { return m_currentCityModel; }
+ void setCurrentCityModel(CityModel *model);
+
+ int applicationWidth() const { return m_applicationWidth; }
+ void setApplicationWidth(const int newWidth);
+
+ int currentIndexDay() const { return m_currentIndexDay; }
+ void setCurrentIndexDay(const int index);
+
+ bool isPortraitMode() const { return m_isPortraitMode; }
+ void setIsPortraitMode(const bool newMode);
+
+ CitiesListModel *foundCities() { return m_citiesFound; }
+
+ qreal hMargin() const { return m_hMargin; }
+ qreal ratio() const { return m_ratio; }
+ qreal sliderHandleHeight() { return m_sliderHandleHeight; }
+ qreal sliderGapWidth() { return m_sliderGapWidth; }
+ qreal sliderHandleWidth() { return m_sliderHandleWidth; }
+
+ Q_INVOKABLE QString getImagePath(const QString image);
+ Q_INVOKABLE void queryCities(const QString input);
+
+protected slots:
+ void notifyPortraitMode();
+
+private slots:
+ void replyFinished(QNetworkReply *reply);
+
+protected:
+ qreal getSizeWithRatio(const qreal height) { return ratio() * height; }
+
+signals:
+ void applicationWidthChanged();
+ void portraitModeChanged();
+ void hMarginChanged();
+ void currentCityModelChanged();
+ void currentIndexDayChanged();
+ void foundCitiesChanged();
+ void ratioChanged();
+ void waitForCitiesQueryReply(const QString message);
+ void errorOnQueryCities(const QString errorMessage);
+
+private:
+ int m_applicationWidth;
+ QQmlPropertyMap *m_colors;
+ QQmlPropertyMap *m_constants;
+ CityModel *m_currentCityModel;
+ bool m_isPortraitMode;
+ int m_currentIndexDay;
+ QNetworkAccessManager *manager;
+ CitiesListModel *m_citiesFound;
+ bool m_isMobile;
+ qreal m_ratio;
+ qreal m_hMargin;
+ qreal m_sliderHandleHeight, m_sliderHandleWidth, m_sliderGapWidth;
+ WeatherImageProvider *imageProvider;
+};
+
+#endif // APPLICATIONINFO_H
diff --git a/src/applicationpaths.h b/src/applicationpaths.h
new file mode 100644
index 0000000..efce270
--- /dev/null
+++ b/src/applicationpaths.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef APPLICATIONPATHS_H
+#define APPLICATIONPATHS_H
+
+#include <QtCore/QDir>
+#include <QtCore/QStandardPaths>
+#include <QtCore/QStringList>
+#include <QDebug>
+
+class ApplicationPaths
+{
+public:
+ inline static QString settingsPath()
+ {
+ return getPath(QStandardPaths::DataLocation);
+ }
+ inline static QString dowloadedFilesPath()
+ {
+ return getPath(QStandardPaths::CacheLocation);
+ }
+protected:
+
+ inline static QString getPath(QStandardPaths::StandardLocation location)
+ {
+ QString path = QStandardPaths::standardLocations(location).value(0);
+ QDir dir(path);
+ if (!dir.exists())
+ dir.mkpath(path);
+ if (!path.isEmpty() && !path.endsWith("/"))
+ path += "/";
+ return path;
+ }
+};
+
+#endif // APPLICATIONPATHS_H
diff --git a/src/cities.cpp b/src/cities.cpp
new file mode 100644
index 0000000..b91c276
--- /dev/null
+++ b/src/cities.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QIODevice>
+#include <QtCore/QTextStream>
+#include <QtGlobal>
+
+#include "cities.h"
+#include "citymodel.h"
+#include "applicationpaths.h"
+#include <QDebug>
+
+Cities::Cities(QObject *parent) :
+ QAbstractListModel(parent)
+{
+ m_citiesFileName = QString("%1cities.settings").arg(ApplicationPaths::settingsPath());
+ readCities();
+}
+
+Cities::~Cities()
+{
+ saveCities();
+}
+
+CityModel* Cities::getCityModel(int index)
+{
+ Q_ASSERT(index > -1);
+ Q_ASSERT(index < m_cityMap.count());
+ return m_cityMap.at(index).second;
+}
+
+void Cities::removeCityModel(int index)
+{
+ if (index < m_cityMap.count() && index >=0 )
+ {
+ beginRemoveRows(QModelIndex(), index, index);
+ CityModel *modelToDelete = m_cityMap.at(index).second;
+ modelToDelete->cleanAll();
+ modelToDelete->deleteLater();
+ m_cityMap.removeAt(index);
+ endRemoveRows();
+ }
+}
+
+int Cities::addCityModel(CityModel *model)
+{
+ CityModelPair pair = qMakePair(model->sourceXml(), model);
+ int modelIndex = m_cityMap.indexOf(pair);
+ if (modelIndex == -1) {
+ m_cityMap.prepend(pair);
+ connect(model, SIGNAL(contentXmlChanged()), this, SIGNAL(cityModelReady()));
+ if (m_cityMap.count() > 15)
+ removeCityModel(m_cityMap.count() - 1);
+ return 0;
+ }
+ return modelIndex;
+}
+
+void Cities::readCities()
+{
+ QFile file(m_citiesFileName);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ return;
+ QTextStream in(&file);
+ while (!in.atEnd()) {
+ QString sourceXml = in.readLine().trimmed();
+ processSourceXml(sourceXml);
+ }
+ file.close();
+}
+
+int Cities::processSourceXml(const QString sourceXml)
+{
+ // Dont add save town/identical sourceXml twice
+ for (int i = 0; i <m_cityMap.count(); i++) {
+ if (m_cityMap.at(i).first == sourceXml)
+ return i;
+ }
+ CityModel *model = new CityModel(this);
+ if (model->setSourceXml(sourceXml))
+ return addCityModel(model);
+
+ model->deleteLater();
+ return -1;
+}
+
+void Cities::saveCities()
+{
+ QFile file(m_citiesFileName);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
+ return;
+ QTextStream out(&file);
+ for (int index = m_cityMap.count()-1; index >= 0; index--)
+ out << m_cityMap.at(index).first << endl;
+ file.close();
+}
+
+QVariant Cities::data(const QModelIndex & index, int role) const
+{
+ CityModel *model = m_cityMap.at(index.row()).second;
+ if (model) {
+ switch (role) {
+ case CityNameRole:
+ return model->cityNameDisplay().replace("_", " ");
+ case CountryRole:
+ return model->countryName().replace("_", " ");
+ }
+ }
+ return QVariant();
+}
+
+int Cities::rowCount(const QModelIndex & /*parent*/) const
+{
+ return m_cityMap.count();
+}
+
+QHash<int, QByteArray> Cities::roleNames() const
+{
+ QHash<int, QByteArray> rn;
+ rn[CityNameRole] = "name";
+ rn[CountryRole] = "country";
+ return rn;
+}
diff --git a/src/cities.h b/src/cities.h
new file mode 100644
index 0000000..6839074
--- /dev/null
+++ b/src/cities.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CITIES_H
+#define CITIES_H
+
+#include <QtCore/QAbstractListModel>
+#include <QtCore/QList>
+#include <QtCore/QPair>
+#include <QtQml/qqml.h>
+
+class CityModel;
+
+typedef QPair<QString, CityModel*> CityModelPair;
+
+class Cities : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ enum {
+ CityNameRole = Qt::UserRole + 1,
+ CountryRole = Qt::UserRole + 2
+ };
+
+ Cities(QObject *parent = 0);
+ ~Cities();
+
+ Q_INVOKABLE CityModel* getCityModel(const int index);
+ Q_INVOKABLE void removeCityModel(const int index);
+ int addCityModel(CityModel *model);
+ Q_INVOKABLE int processSourceXml(const QString sourceXml);
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ QHash<int, QByteArray> roleNames() const;
+ int rowCount(const QModelIndex & parent = QModelIndex()) const;
+ Q_INVOKABLE void saveCities();
+
+protected:
+ void readCities();
+
+signals:
+ void cityModelReady();
+ void modelChanged(const int index);
+
+private:
+ QString m_wantedCity;
+ QString m_citiesFileName;
+ QString m_cachePath;
+ QList<CityModelPair> m_cityMap;
+};
+
+QML_DECLARE_TYPE(Cities)
+
+#endif // CITIES_H
diff --git a/src/citieslistmodel.cpp b/src/citieslistmodel.cpp
new file mode 100644
index 0000000..e86bd0d
--- /dev/null
+++ b/src/citieslistmodel.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "citieslistmodel.h"
+#include <QDebug>
+
+CitiesListModel::CitiesListModel(QObject *parent) :
+ QAbstractListModel(parent), m_isEmpty(true)
+{
+}
+
+QVariant CitiesListModel::data(const QModelIndex & index, int role) const
+{
+ Q_ASSERT(index.row() < m_foundCities.count());
+ if (role == CountryRole)
+ return QString(m_foundCities.at(index.row()).first).replace("_", " ");
+ else
+ return QVariant("");
+}
+
+int CitiesListModel::rowCount(const QModelIndex & /*parent*/) const
+{
+ return m_foundCities.count();
+}
+
+QString CitiesListModel::getCitySourceXml(const int index)
+{
+ Q_ASSERT(index > -1);
+ Q_ASSERT(index < m_foundCities.count());
+ CityXmlPair pair = m_foundCities.at(index);
+ // In order to use yr.no weather data service, refer to their terms
+ // and conditions of use. http://om.yr.no/verdata/free-weather-data/
+ return QString("http://www.yr.no%1forecast.xml").arg(pair.second);
+}
+
+void CitiesListModel::addCities(QStringList listCities)
+{
+ clear();
+ QList<CityXmlPair> temp;
+ if (!listCities.empty()) {
+ for (int i = 0; i < listCities.count(); i++)
+ {
+ QRegExp regExp2;
+ regExp2.setPattern("^\"(.*)\",\"(.*)\",\"(.*)\",\"(.*)\"$");
+ regExp2.exactMatch(listCities.at(i));
+ QString cityName = regExp2.capturedTexts().at(1);
+ QString countryName = regExp2.capturedTexts().at(3);
+ QString xml = regExp2.capturedTexts().at(2);
+ QRegExp regExp3;
+ regExp3.setPattern("^/place/.*/.*/.*/$");
+ if (countryName.isEmpty() || countryName.contains("Municipality") || !regExp3.exactMatch(xml))
+ continue; // We want cities forecast only
+ QString name = cityName + " - " + countryName;
+ temp.append(qMakePair(name, xml));
+ }
+ }
+
+ if (!temp.isEmpty()) {
+ beginInsertRows(QModelIndex(), 0, temp.count() - 1);
+ m_foundCities.append(temp);
+ m_isEmpty = false;
+ } else {
+ beginInsertRows(QModelIndex(), 0, 0);
+ m_foundCities.append(qMakePair(tr("no city found"), QString("")));
+ }
+
+ endInsertRows();
+}
+
+void CitiesListModel::clear()
+{
+ m_isEmpty = true;
+ if (m_foundCities.count() > 0) {
+ beginRemoveRows(QModelIndex(), 0, m_foundCities.count() - 1);
+ m_foundCities.clear();
+ endRemoveRows();
+ }
+}
+
+QHash<int, QByteArray> CitiesListModel::roleNames() const
+{
+ QHash<int, QByteArray> rn;
+ rn[CountryRole] = "country";
+ rn[NameRole] = "name"; // needed to use in delegate that read both roles (country and name)
+ return rn;
+}
+
diff --git a/src/citieslistmodel.h b/src/citieslistmodel.h
new file mode 100644
index 0000000..7120620
--- /dev/null
+++ b/src/citieslistmodel.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CITIESLISTMODEL_H
+#define CITIESLISTMODEL_H
+
+#include <QtCore/QAbstractListModel>
+#include <QtCore/QList>
+#include <QtCore/QPair>
+#include <QtCore/QStringList>
+#include <QtQml/qqml.h>
+
+typedef QPair<QString, QString> CityXmlPair;
+
+class CitiesListModel : public QAbstractListModel
+{
+ Q_OBJECT
+ Q_PROPERTY(bool isEmpty READ isEmpty NOTIFY isEmptyChanged)
+public:
+ enum {
+ NameRole = Qt::UserRole + 1,
+ CountryRole = Qt::UserRole + 2
+ };
+ CitiesListModel(QObject *parent = 0);
+
+ Q_INVOKABLE QString getCitySourceXml(const int index);
+ void addCities(QStringList listCities = QStringList());
+
+ bool isEmpty() const { return m_isEmpty; }
+
+ void clear();
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ Q_INVOKABLE int rowCount(const QModelIndex & parent = QModelIndex()) const;
+ QHash<int, QByteArray> roleNames() const;
+
+signals:
+ void isEmptyChanged();
+
+private:
+ QList<CityXmlPair> m_foundCities;
+ bool m_isEmpty;
+};
+
+QML_DECLARE_TYPE(CitiesListModel)
+
+#endif // CITIESLISTMODEL_H
diff --git a/src/citymodel.cpp b/src/citymodel.cpp
new file mode 100644
index 0000000..9056398
--- /dev/null
+++ b/src/citymodel.cpp
@@ -0,0 +1,302 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QDateTime>
+#include <QtCore/QFile>
+#include <QtCore/QIODevice>
+#include <QtCore/QRegExp>
+#include <QtCore/QStringList>
+#include <QtNetwork/QNetworkRequest>
+#include <QtNetwork/QNetworkReply>
+#include <QtNetwork/QNetworkAccessManager>
+
+#include "citymodel.h"
+#include "applicationpaths.h"
+#include <QDebug>
+
+CityModel::CityModel(QObject *parent) :
+ QObject(parent), m_timeStamp(0)
+{
+ manager = new QNetworkAccessManager(this);
+ connect(manager, SIGNAL(finished(QNetworkReply*)),
+ this, SLOT(replyFinished(QNetworkReply*)));
+ connect(this, SIGNAL(ready()), this, SLOT(readXml()));
+}
+
+void CityModel::setCopyright(const QString copyright)
+{
+ if (copyright != m_copyright) {
+ m_copyright = copyright;
+ emit copyrightChanged();
+ }
+}
+
+bool CityModel::setSourceXml(const QString xml)
+{
+ if (xml != m_sourceXml) {
+ QRegExp regExp;
+ // will reject invalid xml string
+ regExp.setPattern("^http://www\\.yr\\.no/place/(([^/]*)/.*/([^/]*))/forecast\\.xml$");
+ if (!regExp.exactMatch(xml))
+ return false;
+ m_sourceXml = xml;
+
+ // get city name, country and filename from sourceXml
+ QStringList list = regExp.capturedTexts();
+ setCityNameDisplay(list.at(3));
+ setCountryName(list.at(2));
+ QString tempFileName = regExp.capturedTexts().at(1);
+ tempFileName = tempFileName.replace(QString("/"), QString("_"));
+ m_filename = QString("%1%2.wa").arg(ApplicationPaths::dowloadedFilesPath()).arg(tempFileName);
+ emit sourceXmlChanged();
+ }
+ return true;
+}
+
+void CityModel::setCityNameDisplay(QString name)
+{
+ int pos = name.indexOf("~");
+ if ( pos > 0)
+ name.truncate(pos);
+
+ if (name != m_cityNameDisplay) {
+ m_cityNameDisplay = name;
+ emit cityNameDisplayChanged();
+ }
+}
+
+QString CityModel::cityNameDisplay() const
+{
+ QString cityName = m_cityNameDisplay;
+ return cityName.replace("_", " ");
+}
+
+void CityModel::setCountryName(const QString name)
+{
+ if (name != m_countryName) {
+ m_countryName = name;
+ emit countryNameChanged();
+ }
+}
+
+QString CityModel::countryName() const
+{
+ QString countryName = m_countryName;
+ return countryName.replace("_", " ");
+}
+
+void CityModel::setError(const QString errorMessage)
+{
+ // Always emit error message
+ emit error(tr("Network error: ") + errorMessage);
+}
+
+QVariant CityModel::data(const QModelIndex & /*index*/, int role) const
+{
+ if (role == CityNameDisplayRole)
+ return m_cityNameDisplay;
+ return QVariant();
+}
+
+QHash<int, QByteArray> CityModel::roleNames() const
+{
+ QHash<int, QByteArray> rn;
+ rn[CityNameDisplayRole] = "name";
+ return rn;
+}
+
+void CityModel::clear()
+{
+ m_copyright = QString();
+ m_timeStamp = 0;
+ for (int i = 0; i < m_citydata.count(); i++) {
+ DayModel *temp = m_citydata.takeAt(i);
+ temp->clear();
+ temp->deleteLater();
+ }
+ m_citydata.clear();
+}
+
+void CityModel::cleanAll()
+{
+ clear();
+ // Clear eventual cached file
+ QFile file(m_filename);
+ if (file.exists())
+ file.remove();
+}
+
+void CityModel::addDayModel(DayModel *newDayModel)
+{
+ m_citydata.append(newDayModel);
+ connect(newDayModel, SIGNAL(addedImages(QStringList)), this, SLOT(addImages(QStringList)));
+}
+
+void CityModel::addImages(const QStringList images)
+{
+ for (int i = 0; i < images.count(); i++)
+ downloadImage(images.at(i));
+}
+
+DayModel* CityModel::getDayModel(QString date)
+{
+ for (int i = 0; i < m_citydata.count(); i++) {
+ if ( m_citydata.at(i)->getDate() == date )
+ return m_citydata.at(i);
+ }
+ return 0;
+}
+
+DayModel* CityModel::getDayModel(int indexDay)
+{
+ Q_ASSERT(indexDay > -1);
+ Q_ASSERT(indexDay < m_citydata.count());
+ return m_citydata.at(indexDay);
+}
+
+void CityModel::refreshData()
+{
+ if (sourceXml() == QString()) {
+ qWarning("Warning: source xml not set");
+ return;
+ }
+ QNetworkRequest request;
+ request.setUrl(QUrl(sourceXml()));
+ request.setRawHeader("Accept", "application/xml,*/*");
+ manager->get(request);
+}
+
+void CityModel::loadData()
+{
+ Q_ASSERT(!m_filename.isEmpty());
+ QFile file(m_filename);
+ m_timeStamp = 0;
+ if (file.exists() && file.open(QIODevice::ReadOnly)) {
+ m_timeStamp = QString(file.readLine().trimmed()).toLongLong();
+ file.close();
+ }
+ if (dataExpired(m_timeStamp))
+ refreshData();
+ else
+ emit ready();
+}
+
+bool CityModel::dataExpired(qint64 timeStamp) {
+ // 10 minutes caching
+ qint64 tenMinutesMSecs = 10 * 60 * 1000;
+ qint64 timeElapsed = QDateTime::currentMSecsSinceEpoch() - timeStamp;
+ return timeStamp == 0 || timeElapsed > tenMinutesMSecs;
+}
+
+void CityModel::replyFinished(QNetworkReply *reply)
+{
+ if (reply->error() != QNetworkReply::NoError) {
+ setError(reply->errorString());
+ } else {
+ QString requestUrl = reply->request().url().toString();
+ if (requestUrl.endsWith(".xml")) {
+ QByteArray data = reply->readAll();
+ if (!data.isEmpty()) {
+ data.prepend("\n");
+ data.prepend(QByteArray::number(QDateTime::currentMSecsSinceEpoch(), 'f', 0));
+ QFile file(m_filename);
+ if (file.open(QIODevice::WriteOnly)) {
+ file.write(data);
+ file.close();
+ emit ready();
+ } else {
+ setError(file.errorString());
+ }
+ } else {
+ setError(tr("No data at given url"));
+ }
+ } else { // download image
+ QString filename = getImageFileName(reply->url().toString());
+ QByteArray data = reply->readAll();
+ if (!data.isEmpty()) {
+ QFile file(filename);
+ if (!file.exists() && file.open(QIODevice::WriteOnly)) {
+ file.write(data);
+ file.close();
+ }
+ }
+ }
+ }
+ if (reply) {
+ reply->deleteLater();
+ reply = 0;
+ }
+}
+
+void CityModel::downloadImage(const QString imageUrl)
+{
+ QString filename = getImageFileName(imageUrl);
+ QFile file(filename);
+ if (!file.exists()) {
+ QNetworkRequest request;
+ request.setUrl(QUrl(imageUrl));
+ manager->get(request);
+ }
+}
+
+QString CityModel::getImageFileName(const QString url)
+{
+ bool isLargeImage = url.contains("b200");
+ QString filename = url.right(url.length() - url.lastIndexOf("/") - 1);
+ if (isLargeImage)
+ filename.prepend("large_");
+ filename = QString("%1%2").arg(ApplicationPaths::dowloadedFilesPath()).arg(filename);
+ return filename;
+}
+
+void CityModel::readXml()
+{
+ QFile file(m_filename);
+ QString content;
+ if (file.open(QIODevice::ReadOnly)) {
+ m_timeStamp = QString(file.readLine().trimmed()).toLongLong();
+ m_contentXml = QString(file.readAll());
+ emit contentXmlChanged(); // always emit this signal
+ file.close();
+ } else {
+ setError(file.errorString());
+ }
+}
diff --git a/src/citymodel.h b/src/citymodel.h
new file mode 100644
index 0000000..34d40ec
--- /dev/null
+++ b/src/citymodel.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CITYMODEL_H
+#define CITYMODEL_H
+
+#include <QtCore/QModelIndex>
+#include <QtCore/QObject>
+#include <QtQml/qqml.h>
+#include <QDebug>
+
+#include "daymodel.h"
+
+QT_BEGIN_NAMESPACE
+class QNetworkAccessManager;
+class QNetworkReply;
+QT_END_NAMESPACE
+
+class CityModel : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(Status)
+ Q_PROPERTY(QString copyright READ copyright WRITE setCopyright NOTIFY copyrightChanged)
+ Q_PROPERTY(QString cityNameDisplay READ cityNameDisplay NOTIFY cityNameDisplayChanged)
+ Q_PROPERTY(QString countryName READ countryName NOTIFY countryNameChanged)
+ Q_PROPERTY(QString sourceXml READ sourceXml NOTIFY sourceXmlChanged)
+ Q_PROPERTY(QString contentXml READ contentXml NOTIFY contentXmlChanged)
+
+public:
+ enum {
+ CityNameDisplayRole = Qt::UserRole + 1
+ };
+
+ CityModel(QObject *parent = 0);
+
+ void setError(const QString msg);
+
+ QString copyright() const { return m_copyright;}
+ void setCopyright(const QString copyright);
+
+ QString cityNameDisplay() const;
+ void setCityNameDisplay(QString name);
+
+ QString countryName() const;
+ void setCountryName(const QString name);
+
+ QString sourceXml() const { return m_sourceXml; }
+ bool setSourceXml(const QString xml);
+
+ QString contentXml() const { return m_contentXml; }
+
+ QVariant data(const QModelIndex &index, int role) const;
+ QHash<int, QByteArray> roleNames() const;
+
+ Q_INVOKABLE int daysCount() const { return m_citydata.count(); }
+ Q_INVOKABLE void loadData();
+ Q_INVOKABLE void clear();
+ Q_INVOKABLE void addDayModel(DayModel *newDayModel);
+ Q_INVOKABLE DayModel* getDayModel(QString dayName);
+ Q_INVOKABLE DayModel* getDayModel(int indexDay);
+
+ void cleanAll();
+
+ void downloadImage(const QString imageUrl);
+
+private:
+ void refreshData();
+ bool dataExpired(qint64 timeStamp);
+ QString getImageFileName(const QString url);
+
+private Q_SLOTS:
+ void replyFinished(QNetworkReply*);
+ void readXml();
+ void addImages(const QStringList images);
+
+Q_SIGNALS:
+ void copyrightChanged();
+ void countryNameChanged();
+ void error(const QString errorMessage);
+ void sourceXmlChanged();
+ void contentXmlChanged();
+ void cityNameDisplayChanged();
+ void fileNameChanged();
+ void ready();
+
+private:
+ QString m_copyright;
+ QString m_countryName, m_contentXml;
+ qreal m_timeStamp;
+ QList<DayModel*> m_citydata;
+ QNetworkAccessManager *manager;
+ QString m_filename;
+ QString m_url;
+ QString m_sourceXml;
+ QString m_cityNameDisplay;
+};
+
+QML_DECLARE_TYPE(CityModel)
+
+#endif // CITYMODEL_H
diff --git a/src/daymodel.cpp b/src/daymodel.cpp
new file mode 100644
index 0000000..a0ae9ac
--- /dev/null
+++ b/src/daymodel.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QDir>
+#include <QtCore/QCoreApplication>
+#include <QtNetwork/QNetworkRequest>
+#include <QtNetwork/QNetworkReply>
+#include <QtNetwork/QNetworkAccessManager>
+
+#include "daymodel.h"
+#include "applicationpaths.h"
+#include <QDebug>
+
+DayModel::DayModel()
+ : QObject(), m_afternoonindex(0) {
+}
+
+QVariant DayModel::data(const QModelIndex &index, int role) const
+{
+ if (role == DayRole)
+ return m_data.at(index.row()).day;
+ if (role == WeatherUrlRole)
+ return m_data.at(index.row()).weatherUrl;
+ if (role == TimeRangeRole)
+ return m_data.at(index.row()).timeRange;
+ if (role == TemperatureRole)
+ return m_data.at(index.row()).temperature;
+ if (role == WindSpeedRole)
+ return m_data.at(index.row()).windSpeed;
+ if (role == WindUrlRole)
+ return m_data.at(index.row()).windUrl;
+ if (role == RainRole)
+ return m_data.at(index.row()).rain;
+ return QVariant();
+}
+
+QHash<int, QByteArray> DayModel::roleNames() const
+{
+ QHash<int, QByteArray> rn;
+ rn[DayRole] = "day";
+ rn[WeatherUrlRole] = "weatherUrl";
+ rn[TimeRangeRole] = "timeRange";
+ rn[TemperatureRole] = "temperature";
+ rn[WindSpeedRole] = "windSpeed";
+ rn[WindUrlRole] = "windUrl";
+ rn[RainRole] = "rain";
+ return rn;
+}
+
+void DayModel::clear()
+{
+ m_date = QString();
+ m_afternoonindex = 0;
+ m_data.clear();
+}
+
+void DayModel::addRow(QString day, QString weatherUrl, QString timeRange, QString temperature, QString windSpeed, QString windUrl, QString rain) {
+ QStringList m_images;
+ DayModelStructure temp;
+ temp.day = day;
+ temp.weatherUrl = weatherUrl;
+ m_images.append(weatherUrl);
+ QString largeWeatherIconUrl = weatherUrl;
+ m_images.append(largeWeatherIconUrl.replace("b100", "b200"));
+ temp.timeRange = timeRange;
+ temp.temperature = temperature;
+ temp.windSpeed = windSpeed;
+ temp.windUrl = windUrl;
+ m_images.append(windUrl);
+ temp.rain = rain;
+ m_data.append(temp);
+ emit addedImages(m_images);
+}
+
+QUrl DayModel::getCachedImageFile(const QString url)
+{
+ bool isLargeImage = url.contains("b200");
+ QString filename = url.right(url.length() - url.lastIndexOf("/") - 1);
+ if (isLargeImage)
+ filename.prepend("large_");
+ filename = QString("%1%2").arg(ApplicationPaths::dowloadedFilesPath()).arg(filename);
+ QFile file(filename);
+ if (file.exists())
+ return QUrl(QString("image://weatherImages/%1").arg(filename));
+ else
+ return QUrl(url);
+}
+
+QString DayModel::getDayDetails(int index, QString prop) const
+{
+ if (index == -1)
+ index = 0;
+ if (index < m_data.count()) {
+ DayModelStructure temp = m_data.at(index);
+ if (prop == "day")
+ return temp.day;
+ if (prop == "weatherUrl")
+ return temp.weatherUrl;
+ if (prop == "timeRange")
+ return temp.timeRange;
+ if (prop == "temperature")
+ return temp.temperature;
+ if (prop == "windSpeed")
+ return temp.windSpeed;
+ if (prop == "windUrl")
+ return temp.windUrl;
+ if (prop == "rain")
+ return temp.rain;
+ }
+ return QString();
+}
diff --git a/src/daymodel.h b/src/daymodel.h
new file mode 100644
index 0000000..d93e905
--- /dev/null
+++ b/src/daymodel.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DAYMODEL_H
+#define DAYMODEL_H
+
+#include <QtCore/QModelIndex>
+
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+#include <QtQml/qqml.h>
+
+QT_BEGIN_NAMESPACE
+class QNetworkAccessManager;
+class QNetworkReply;
+QT_END_NAMESPACE
+
+class DayModel : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString date READ getDate WRITE setDate NOTIFY dateChanged)
+ Q_PROPERTY(int afternoonIndex READ getAfternoonIndex WRITE setAfternoonIndex NOTIFY afternoonIndexChanged)
+
+public:
+
+ struct DayModelStructure {
+ QString day;
+ QString weatherUrl;
+ QString timeRange;
+ QString temperature;
+ QString windSpeed;
+ QString windUrl;
+ QString rain;
+ };
+
+ enum {
+ DayRole = Qt::UserRole + 1,
+ WeatherUrlRole = Qt::UserRole + 2,
+ TimeRangeRole = Qt::UserRole + 3,
+ TemperatureRole = Qt::UserRole + 4,
+ WindSpeedRole = Qt::UserRole + 5,
+ WindUrlRole = Qt::UserRole + 6,
+ RainRole = Qt::UserRole + 7
+ };
+
+ DayModel();
+
+ QString getDate() const { return m_date;}
+ void setDate(QString date) { m_date = date; }
+
+ int getAfternoonIndex() const { return m_afternoonindex;}
+ void setAfternoonIndex(int index) { m_afternoonindex = index; }
+
+ void clear();
+
+ QVariant data(const QModelIndex &index, int role) const;
+ QHash<int, QByteArray> roleNames() const;
+
+ Q_INVOKABLE void addRow(QString day, QString weatherUrl, QString timeRange, QString temperature, QString windSpeed, QString windUrl, QString rain);
+ Q_INVOKABLE QString getDayDetails(int index, QString prop) const;
+ Q_INVOKABLE int periodCount() const { return m_data.count(); }
+
+ Q_INVOKABLE QUrl getCachedImageFile(const QString url);
+
+Q_SIGNALS:
+ void dateChanged();
+ void afternoonIndexChanged();
+ void addedImages(const QStringList images);
+
+private:
+ QString m_date;
+ int m_afternoonindex;
+ QList<DayModelStructure> m_data;
+};
+
+QML_DECLARE_TYPE(DayModel)
+
+#endif // DAYMODEL_H
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..1704fe2
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QString>
+#include <QtGui/QFont>
+#include <QtGui/QFontDatabase>
+#include <QtGui/QGuiApplication>
+#include <QtQuick/QQuickWindow>
+#include <QtQml>
+
+#include "daymodel.h"
+#include "citymodel.h"
+#include "cities.h"
+#include "applicationinfo.h"
+#include "weatherimageprovider.h"
+
+static const struct {
+ const char *type;
+ int major, minor;
+} qmldir_touch [] = {
+ { "TouchSlider", 1, 0 },
+ { "TouchScrollView", 1, 0 },
+ { "TouchLabel", 1, 0 },
+ { "TouchTextField", 1, 0 },
+ { "ListViewDelegate", 1, 0 },
+ { "ListViewDelegateLoading", 1, 0 },
+};
+
+static const struct {
+ const char *type;
+ int major, minor;
+} qmldir_models [] = {
+ { "CitiesModel", 1, 0 },
+ { "WeatherModel", 1, 0 },
+};
+
+static const struct {
+ const char *type;
+ int major, minor;
+} qmldir_pages [] = {
+ { "CitiesPage", 1, 0 },
+ { "LongTermPage", 1, 0 },
+ { "OneDayPage", 1, 0 },
+};
+
+static QObject *systeminfo_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
+{
+ Q_UNUSED(engine)
+ Q_UNUSED(scriptEngine)
+ WeatherImageProvider *provider = new WeatherImageProvider();
+ engine->addImageProvider(QLatin1String("weatherImages"), provider);
+ return new ApplicationInfo(provider);
+}
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+ app.setOrganizationName("Digia");
+ app.setApplicationName("QuickForecast");
+
+#ifndef Q_OS_IOS //QTBUG-34490
+ QFontDatabase::addApplicationFont(":/weatherapp/fonts/OpenSans-Bold.ttf");
+ QFontDatabase::addApplicationFont(":/weatherapp/fonts/OpenSans-Semibold.ttf");
+ int openSansID = QFontDatabase::addApplicationFont(":/weatherapp/fonts/OpenSans-Regular.ttf");
+ QStringList loadedFontFamilies = QFontDatabase::applicationFontFamilies(openSansID);
+ if (!loadedFontFamilies.empty()) {
+ QString fontName = loadedFontFamilies.at(0);
+ QGuiApplication::setFont(QFont(fontName));
+ } else {
+ qWarning("Error: fail to load Open Sans font");
+ }
+#endif
+
+ const char *uri = "org.qtproject.demo.weather";
+ qmlRegisterType<DayModel>(uri, 1, 0, "DayModel");
+ qmlRegisterType<CityModel>(uri, 1, 0, "CityModel");
+ qmlRegisterType<Cities>(uri, 1, 0, "Cities");
+ qmlRegisterType<CitiesListModel>(uri, 1, 0, "CitiesListModel");
+ qmlRegisterSingletonType<ApplicationInfo>(uri, 1, 0, "ApplicationInfo", systeminfo_provider);
+
+ for (int i = 0; i < int(sizeof(qmldir_touch)/sizeof(qmldir_touch[0])); i++)
+ qmlRegisterType(QUrl(QString("qrc:/weatherapp/qml/touch/%1.qml").arg(qmldir_touch[i].type)), uri, qmldir_touch[i].major, qmldir_touch[i].minor, qmldir_touch[i].type);
+
+ for (int i = 0; i < int(sizeof(qmldir_models)/sizeof(qmldir_models[0])); i++)
+ qmlRegisterType(QUrl(QString("qrc:/weatherapp/qml/models/%1.qml").arg(qmldir_models[i].type)), uri, qmldir_models[i].major, qmldir_models[i].minor, qmldir_models[i].type);
+
+ for (int i = 0; i < int(sizeof(qmldir_pages)/sizeof(qmldir_pages[0])); i++)
+ qmlRegisterType(QUrl(QString("qrc:/weatherapp/qml/pages/%1.qml").arg(qmldir_pages[i].type)), uri, qmldir_pages[i].major, qmldir_pages[i].minor, qmldir_pages[i].type);
+
+ QQmlApplicationEngine engine(QUrl("qrc:/weatherapp/qml/main.qml"));
+ QObject *topLevel = engine.rootObjects().value(0);
+
+ QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
+ if ( !window ) {
+ qWarning("Error: Your root item has to be a Window.");
+ return -1;
+ }
+ window->show();
+ return app.exec();
+}
diff --git a/src/src.pri b/src/src.pri
new file mode 100644
index 0000000..5a3bbdf
--- /dev/null
+++ b/src/src.pri
@@ -0,0 +1,16 @@
+SOURCES += \
+ $$PWD/main.cpp \
+ $$PWD/citymodel.cpp \
+ $$PWD/daymodel.cpp \
+ $$PWD/cities.cpp \
+ $$PWD/applicationinfo.cpp \
+ $$PWD/citieslistmodel.cpp
+
+HEADERS += \
+ $$PWD/citymodel.h \
+ $$PWD/daymodel.h \
+ $$PWD/cities.h \
+ $$PWD/applicationinfo.h \
+ $$PWD/citieslistmodel.h \
+ $$PWD/weatherimageprovider.h \
+ $$PWD/applicationpaths.h
diff --git a/src/weatherimageprovider.h b/src/weatherimageprovider.h
new file mode 100644
index 0000000..59fcbcc
--- /dev/null
+++ b/src/weatherimageprovider.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WEATHERIMAGEPROVIDER_H
+#define WEATHERIMAGEPROVIDER_H
+
+#include <QtQuick/QQuickImageProvider>
+#include <QtGui/QImage>
+#include <QtCore/QSize>
+
+class WeatherImageProvider : public QQuickImageProvider
+{
+public:
+ WeatherImageProvider()
+ : QQuickImageProvider(QQuickImageProvider::Image)
+ {
+ }
+
+ QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize)
+ {
+ int width = 50;
+ int height = 50;
+
+ if (size)
+ *size = QSize(width, height);
+ QImage image(requestedSize.width() > 0 ? requestedSize.width() : width,
+ requestedSize.height() > 0 ? requestedSize.height() : height,
+ QImage::Format_ARGB32);
+ image.load(id);
+ return image;
+ }
+};
+
+#endif // WEATHERIMAGEPROVIDER_H