/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: openBossa - INdT (renato.chencarek@openbossa.org) ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** 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, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** the openBossa stream from INdT (renato.chencarek@openbossa.org). ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "forecastview.h" #include "settings.h" #include #include #include #include // Variations struct VariationData { const qreal x; const qreal y; }; static const int variationCount = 3; static const VariationData variationArray[variationCount] = { {35.0, 20.0}, {25.0, 15.0}, {15.0, 10.0} }; // Sun positions struct SunPosition { const ForecastHungItem::ItemType type; const qreal linePos; const qreal picTop; }; static const int sunPositionsArrayCount = 3; static const SunPosition sunPositionsArray[sunPositionsArrayCount] = { {ForecastHungItem::Sun, 240, 124}, {ForecastHungItem::ColdSun, 240, 205}, {ForecastHungItem::Moon, 240, 235} }; class ForecastMostlyCloudyView : public ForecastView { public: ForecastMostlyCloudyView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::MostlyCloudy, parent) { if (night) { addHungItem(ForecastHungItem::CloudRain1, QPointF(357, 308), 0); addHungItem(ForecastHungItem::CloudRain2, QPointF(46, 274), 1); addHungItem(ForecastHungItem::CloudRain2, QPointF(463, 273), 1); addHungItem(ForecastHungItem::CloudRain3, QPointF(139, 221), 2); setMainHangItem(ForecastHungItem::Moon); } else { addHungItem(ForecastHungItem::Cloud1, QPointF(357, 308), 0); addHungItem(ForecastHungItem::Cloud2, QPointF(46, 274), 1); addHungItem(ForecastHungItem::Cloud2, QPointF(463, 273), 1); addHungItem(ForecastHungItem::Cloud3, QPointF(139, 221), 2); setMainHangItem(ForecastHungItem::ColdSun); } } }; class ForecastCloudyView : public ForecastView { public: ForecastCloudyView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::Cloudy, parent) { if (night) { addHungItem(ForecastHungItem::CloudRain1, QPointF(440, 275), 0); addHungItem(ForecastHungItem::CloudRain1, QPointF(121, 273), 0); addHungItem(ForecastHungItem::CloudRain2, QPointF(307, 266), 1); addHungItem(ForecastHungItem::CloudRain3, QPointF(372, 224), 2); addHungItem(ForecastHungItem::CloudRain3, QPointF(33, 227), 2); setMainHangItem(ForecastHungItem::Moon); } else { addHungItem(ForecastHungItem::Cloud1, QPointF(440, 275), 0); addHungItem(ForecastHungItem::Cloud1, QPointF(121, 273), 0); addHungItem(ForecastHungItem::Cloud2, QPointF(307, 266), 1); addHungItem(ForecastHungItem::Cloud3, QPointF(372, 224), 2); addHungItem(ForecastHungItem::Cloud3, QPointF(33, 227), 2); setMainHangItem(ForecastHungItem::ColdSun); } } }; class ForecastMostlySunnyView : public ForecastView { public: ForecastMostlySunnyView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::MostlySunny, parent) { if (night) { addHungItem(ForecastHungItem::CloudRain2, QPointF(72, 389), 1); addHungItem(ForecastHungItem::CloudRain3, QPointF(454, 295), 2); addHungItem(ForecastHungItem::CloudRain3, QPointF(48, 164), 2); setMainHangItem(ForecastHungItem::Moon); addStars(); } else { addHungItem(ForecastHungItem::Cloud2, QPointF(72, 389), 1); addHungItem(ForecastHungItem::Cloud3, QPointF(454, 295), 2); addHungItem(ForecastHungItem::Cloud3, QPointF(48, 164), 2); setMainHangItem(ForecastHungItem::Sun); } } }; class ForecastPartlyCloudyView : public ForecastView { public: ForecastPartlyCloudyView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::PartlyCloudy, parent) { if (night) { addHungItem(ForecastHungItem::CloudRain1, QPointF(389, 315), 0); addHungItem(ForecastHungItem::CloudRain2, QPointF(92, 300), 1); addHungItem(ForecastHungItem::CloudRain3, QPointF(451, 258), 2); setMainHangItem(ForecastHungItem::Moon); } else { addHungItem(ForecastHungItem::Cloud1, QPointF(389, 315), 0); addHungItem(ForecastHungItem::Cloud2, QPointF(92, 300), 1); addHungItem(ForecastHungItem::Cloud3, QPointF(451, 258), 2); setMainHangItem(ForecastHungItem::Sun); } } }; class ForecastSunnyView : public ForecastView { public: ForecastSunnyView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::Sunny, parent) { if (night) { setMainHangItem(ForecastHungItem::Moon); addStars(); } else { setMainHangItem(ForecastHungItem::Sun); } } }; class ForecastFlurriesView : public ForecastView { public: ForecastFlurriesView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::Flurries, parent) { setMainHangItem(night ? ForecastHungItem::Moon : ForecastHungItem::ColdSun); addHungItem(ForecastHungItem::CloudRain1, QPointF(113, 300), 0); addHungItem(ForecastHungItem::CloudRain1, QPointF(382, 267), 0, true); addHungItem(ForecastHungItem::CloudRain2, QPointF(72, 243), 1); addHungItem(ForecastHungItem::CloudRain3, QPointF(349, 226), 2); addSnow(10); } }; class ForecastFogView : public ForecastView { public: ForecastFogView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::Fog, parent) { setMainHangItem(night ? ForecastHungItem::Moon : ForecastHungItem::ColdSun); addHungItem(ForecastHungItem::CloudRain2, QPointF(95, 311), 1); addHungItem(ForecastHungItem::CloudRain3, QPointF(363, 236), 2); } }; class ForecastHazeView : public ForecastView { // haze || sand || dust public: ForecastHazeView(Forecast::ForecastType type, bool night, QGraphicsItem *parent = 0) : ForecastView(type, parent) { setMainHangItem(night ? ForecastHungItem::Moon : ForecastHungItem::ColdSun); addHungItem(ForecastHungItem::CloudRain2, QPointF(98, 311), 1); addHungItem(ForecastHungItem::CloudRain3, QPointF(396, 235), 2); } }; class ForecastIcyView : public ForecastView { public: ForecastIcyView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::Icy, parent) { setMainHangItem(night ? ForecastHungItem::Moon : ForecastHungItem::ColdSun); addHungItem(ForecastHungItem::CloudRain1, QPointF(113, 300), 0); addHungItem(ForecastHungItem::CloudRain1, QPointF(382, 267), 0, true); addHungItem(ForecastHungItem::CloudRain2, QPointF(72, 243), 1); addHungItem(ForecastHungItem::CloudRain3, QPointF(349, 226), 2); addSnow(10); } }; class ForecastSleetView : public ForecastView { public: ForecastSleetView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::Sleet, parent) { setMainHangItem(night ? ForecastHungItem::Moon : ForecastHungItem::ColdSun); addHungItem(ForecastHungItem::CloudRain1, QPointF(135, 317), 0); addHungItem(ForecastHungItem::CloudRain2, QPointF(341, 313), 1, true); addHungItem(ForecastHungItem::CloudRain2, QPointF(72, 276), 1); addHungItem(ForecastHungItem::CloudRain3, QPointF(199, 250), 2); addHungItem(ForecastHungItem::CloudRain3, QPointF(417, 268), 2); addSnow(10); addRain(ForecastRain::Light); } }; class ForecastSnowView : public ForecastView { public: ForecastSnowView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::Snow, parent) { setMainHangItem(night ? ForecastHungItem::Moon : ForecastHungItem::ColdSun); addHungItem(ForecastHungItem::CloudRain1, QPointF(46, 325), 0); addHungItem(ForecastHungItem::CloudRain1, QPointF(359, 302), 0, true); addHungItem(ForecastHungItem::CloudRain2, QPointF(158, 288), 1); addHungItem(ForecastHungItem::CloudRain3, QPointF(73, 267), 2); addHungItem(ForecastHungItem::CloudRain3, QPointF(401, 273), 2); addSnow(20); } }; class ForecastMistView : public ForecastView { public: ForecastMistView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::Mist, parent) { setMainHangItem(night ? ForecastHungItem::Moon : ForecastHungItem::ColdSun); addHungItem(ForecastHungItem::CloudRain1, QPointF(52, 312), 0); addHungItem(ForecastHungItem::CloudRain1, QPointF(437, 255), 0); addHungItem(ForecastHungItem::CloudRain2, QPointF(246, 311), 1, true); addHungItem(ForecastHungItem::CloudRain3, QPointF(119, 268), 2); addHungItem(ForecastHungItem::CloudRain3, QPointF(352, 244), 2); addRain(ForecastRain::Light); } }; class ForecastRainView : public ForecastView { public: ForecastRainView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::Rain, parent) { setMainHangItem(night ? ForecastHungItem::Moon : ForecastHungItem::ColdSun); addHungItem(ForecastHungItem::CloudRain1, QPointF(60, 317), 0); addHungItem(ForecastHungItem::CloudRain1, QPointF(308, 287), 0, true); addHungItem(ForecastHungItem::CloudRain2, QPointF(192, 251), 1); addHungItem(ForecastHungItem::CloudRain2, QPointF(432, 268), 1); addHungItem(ForecastHungItem::CloudRain3, QPointF(355, 235), 2); addRain(ForecastRain::Medium); } }; class ForecastStormView : public ForecastView { public: ForecastStormView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::Storm, parent) { setMainHangItem(night ? ForecastHungItem::Moon : ForecastHungItem::ColdSun); addHungItem(ForecastHungItem::CloudStorm1, QPointF(324, 296), 0); addHungItem(ForecastHungItem::CloudStorm1, QPointF(91, 261), 0, true); addHungItem(ForecastHungItem::CloudStorm2, QPointF(432, 257), 1); addHungItem(ForecastHungItem::CloudStorm3, QPointF(92, 210), 2); addHungItem(ForecastHungItem::CloudStorm3, QPointF(334, 224), 2); addRain(ForecastRain::Heavy); } }; class ForecastThunderstormView : public ForecastView { public: ForecastThunderstormView(bool night, QGraphicsItem *parent = 0) : ForecastView(Forecast::Thunderstorm, parent) { setMainHangItem(night ? ForecastHungItem::Moon : ForecastHungItem::ColdSun); addHungItem(ForecastHungItem::CloudTStorm1, QPointF(371, 303), 0); addHungItem(ForecastHungItem::CloudStorm1, QPointF(110, 283), 0, true); addHungItem(ForecastHungItem::CloudTStorm2, QPointF(207, 272), 1); addHungItem(ForecastHungItem::CloudStorm2, QPointF(367, 248), 1); addHungItem(ForecastHungItem::CloudStorm3, QPointF(111, 223), 2); addRain(ForecastRain::Heavy); } }; static const qreal minHungItemsZ = -1.0; static const qreal maxHungItemsZ = 0.0; static const qreal sunZ = (minHungItemsZ + maxHungItemsZ) / 2.0 + 0.01; static const qreal starsZ = -10.0; static const qreal radius = (maxHungItemsZ - minHungItemsZ) * 1; static const qreal maxDisplacementFactor = 1.5; // HungItemsManager static QAbstractAnimation *addPause(QAbstractAnimation *animation, int pause_ms) { if (!animation || pause_ms <= 0) return animation; QSequentialAnimationGroup *result = new QSequentialAnimationGroup(); result->addPause(pause_ms); result->addAnimation(animation); return result; } void HungItemsManager::reset() { for (int i = 0; i < m_items.count(); ++i) { m_items[i]->reset(); m_items[i]->setPos(m_positions[i], 0.0); } if (m_sun) { m_sun->reset(); m_sun->setPos(m_sunPos, 0.0); } } QAbstractAnimation *HungItemsManager::getAnimation() { QList list; const qreal diff = (m_maxZ - m_minZ) / qreal(m_items.count()); for (int i = 0; i < m_items.count(); ++i) { m_items[i]->setZValue(m_maxZ - i * diff); QAbstractAnimation *animation = m_items[i]->getAnimation(); if (animation) list.append(animation); } QAbstractAnimation *clouds = 0; switch (list.count()) { case 0: break; case 1: clouds = list[0]; break; default: { QParallelAnimationGroup *animation = new QParallelAnimationGroup(); for (int i = 0; i < list.count(); ++i) animation->addAnimation(addPause(list[i], i * 200)); clouds = animation; } } QAbstractAnimation *sun = m_sun ? m_sun->getAnimation() : 0; if (clouds && m_sun) { QSequentialAnimationGroup *result = new QSequentialAnimationGroup(); result->addAnimation(clouds); result->addAnimation(sun); return result; } return clouds ? clouds : sun; } void HungItemsManager::addItem(ForecastHungItem *item) { m_items.append(item); m_positions.append(item->pos().x()); } void HungItemsManager::setSun(ForecastHungItem *sun) { m_sun = sun; m_sunPos = sun->pos().x(); } void HungItemsManager::doSetDisplacement(ForecastHungItem *item, qreal max, qreal pos) { const qreal itemRadius = radius + item->zValue(); const qreal itemDisplacement = (itemRadius / radius) * max * m_displacement; item->setPos(pos + itemDisplacement, 0.0); } void HungItemsManager::setElementsDisplacement(qreal displacement) { const qreal max = maxDisplacementFactor * Settings::windowSize().width(); m_displacement = qMin(qMax(displacement, qreal(-1.0)), qreal(1.0)); for (int i = 0; i < m_items.count(); ++i) doSetDisplacement(m_items[i], max, m_positions[i]); if (m_sun) doSetDisplacement(m_sun, max, m_sunPos); } // ForecastView void ForecastView::setElementsDisplacement(qreal displacement) { m_hungManager.setElementsDisplacement(displacement); } ForecastView *ForecastView::createView(Forecast::ForecastType type, bool night, QGraphicsItem *parent) { switch (type) { case Forecast::MostlyCloudy : return new ForecastMostlyCloudyView(night, parent); case Forecast::Cloudy : return new ForecastCloudyView(night, parent); case Forecast::MostlySunny : return new ForecastMostlySunnyView(night, parent); case Forecast::PartlyCloudy : return new ForecastPartlyCloudyView(night, parent); case Forecast::Sunny : return new ForecastSunnyView(night, parent); case Forecast::Flurries : return new ForecastFlurriesView(night, parent); case Forecast::Fog : return new ForecastFogView(night, parent); case Forecast::Haze : return new ForecastHazeView(Forecast::Haze, night, parent); case Forecast::Sand : return new ForecastHazeView(Forecast::Sand, night, parent); case Forecast::Dust : return new ForecastHazeView(Forecast::Dust, night, parent); case Forecast::Icy : return new ForecastIcyView(night, parent); case Forecast::Sleet : return new ForecastSleetView(night, parent); case Forecast::ChanceOfSleet : return new ForecastSleetView(night, parent); case Forecast::Snow : return new ForecastSnowView(night, parent); case Forecast::ChanceOfSnow : return new ForecastSnowView(night, parent); case Forecast::Mist : return new ForecastMistView(night, parent); case Forecast::Rain : return new ForecastRainView(night, parent); case Forecast::ChanceOfRain : return new ForecastRainView(night, parent); case Forecast::Storm : return new ForecastStormView(night, parent); case Forecast::ChanceOfStorm : return new ForecastStormView(night, parent); case Forecast::Thunderstorm : return new ForecastThunderstormView(night, parent); case Forecast::ChanceOfThunderstorm : return new ForecastThunderstormView(night, parent); default : return 0; } } ForecastView::ForecastView(Forecast::ForecastType type, bool night, QGraphicsItem *parent) : QGraphicsItem(parent) , m_type(type) , m_night(night) , m_boundingRect(QPointF(0.0, 0.0), Settings::windowSize()) , m_hungManager(minHungItemsZ, maxHungItemsZ) , m_stars(0) , m_reference(0) , m_rain(0) , m_snow(0) { } ForecastView::~ForecastView() { delete m_snow; } QRectF ForecastView::boundingRect () const { return m_boundingRect; } void ForecastView::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *widget) { Q_UNUSED(opt); Q_UNUSED(widget); if (m_snow) m_snow->paint(painter); } static const qreal cloudAdjustment = 20.0; void ForecastView::addHungItem(ForecastHungItem::ItemType type, const QPointF &itemPos, int deviation, bool reference) { const bool validDev = deviation >= 0 && deviation < variationCount; qreal devX = validDev ? variationArray[deviation].x : 0.0; qreal devY = validDev ? variationArray[deviation].y : 0.0; devX *= 1.0 - qreal(qrand()) / qreal(RAND_MAX >> 1); devY *= 1.0 - qreal(qrand()) / qreal(RAND_MAX >> 1); ForecastHungItem *item = new ForecastHungItem(type, this); item->setLinePos(Settings::scaleWidth(itemPos.x() + devX - cloudAdjustment)); item->setPicPos(item->pos().x(), Settings::scaleHeight(itemPos.y() + devY)); if (reference) m_reference = item; m_hungManager.addItem(item); } void ForecastView::reset() { m_hungManager.reset(); if (m_rain) { m_rain->stop(); m_rain->hide(); } if (m_snow) { m_snow->stop(); m_snow->hide(); } } void ForecastView::addStars() { if (!m_stars) { m_stars = new ForecastStars(8, this); QRectF rect = m_boundingRect; rect.setHeight(Settings::scaleHeight(522.0)); m_stars->setRect(rect); m_stars->setZValue(starsZ); } } QRectF ForecastView::getEffectRect() { QRectF result = m_boundingRect; if (m_reference) { QRectF ref(m_reference->boundingRect()); result.setTop(ref.bottom()); result.setHeight(m_boundingRect.height() - ref.bottom()); } return result; } template QAbstractAnimation *ForecastView::createEffectAnimation(T *effect) { effect->setOpacity(0.0); EffectAnimation *result = new EffectAnimation(); result->setTargetObject(effect); result->setPropertyName("opacity"); result->setStartValue(0.0); result->setEndValue(1.0); result->setDuration(200); result->setEasingCurve(QEasingCurve::InQuart); connect(result, SIGNAL(started()), effect, SLOT(show())); connect(result, SIGNAL(finished()), effect, SLOT(start())); return result; } void ForecastView::addRain(ForecastRain::RainType type) { if (!m_rain) { m_rain = new ForecastRain(type, this); m_rain->setPos(getEffectRect().topLeft()); m_rain->hide(); m_rain->setZValue(-1); } } void ForecastView::addSnow(int count) { if (!m_snow) { m_snow = new ForecastSnow(count, getEffectRect(), this); m_snow->hide(); } } void ForecastView::setMainHangItem(ForecastHungItem::ItemType type) { if (!m_hungManager.sun()) { for (int i = 0; i < sunPositionsArrayCount; ++i) { if (sunPositionsArray[i].type == type ){ ForecastHungItem *sun = new ForecastHungItem(type, this); sun->setPicPos(0.0, Settings::scaleHeight(sunPositionsArray[i].picTop)); sun->setLinePos(Settings::scaleWidth(sunPositionsArray[i].linePos)); sun->setZValue(sunZ); m_hungManager.setSun(sun); break; } } } } QAbstractAnimation *ForecastView::getAnimation() { QList list; QAbstractAnimation *animation = m_hungManager.getAnimation(); if (animation) list.append(animation); animation = m_stars ? m_stars->getAnimation() : 0; if (animation) list.append(animation); animation = m_rain ? createEffectAnimation(m_rain) : 0; if (animation) list.append(animation); QAbstractAnimation *result = 0; switch (list.count()) { case 0: break; case 1: result = list[0]; break; default: { QSequentialAnimationGroup *group = new QSequentialAnimationGroup(); foreach (QAbstractAnimation *a, list) group->addAnimation(a); result = group; } } if (result && m_snow) connect(result, SIGNAL(finished()), m_snow, SLOT(start())); else if (m_snow) m_snow->show(); return result; }