/*************************************************************************\
*   Copyright (C) 2011 by Ulf Kreissig                                    *
*   udev@gmx.net                                                          *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
*   This program is distributed in the hope that it will be useful,       *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU General Public License for more details.                          *
*                                                                         *
*   You should have received a copy of the GNU General Public License     *
*   along with this program; if not, write to the                         *
*   Free Software Foundation, Inc.,                                       *
*   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
\*************************************************************************/

//--- LOCAL ---
#include "panelpainter.h"
#include "logger/streamlogger.h"

//--- QT4 ---
#include <QLatin1String>

//--- KDE4 ----
#include <KGlobalSettings>
#include <Plasma/Applet>
#include <Plasma/Theme>

const qreal PanelPainter::HORIZONTAL_COMPACT_ICON_SIZE = 0.65;
const qreal PanelPainter::HORIZONTAL_TODAYS_COMPACT_TEMPERATURE = 0.35;
const qreal PanelPainter::HORIZONTAL_TODAYS_TEMPERATURE = 0.75;
const qreal PanelPainter::HORIZONTAL_FORECAST_COMPACT_TEMPERATURE = 0.20;
const qreal PanelPainter::HORIZONTAL_FORECAST_TEMPERATURE = 0.40;

const qreal PanelPainter::VERTICAL_COMPACT_ICON_SIZE = 0.45;
const qreal PanelPainter::VERTICAL_TODAYS_COMPACT_TEMPERATURE = 0.35;
const qreal PanelPainter::VERTICAL_TODAYS_TEMPERATURE = 0.60;
const qreal PanelPainter::VERTICAL_FORECAST_COMPACT_TEMPERATURE = 0.20;
const qreal PanelPainter::VERTICAL_FORECAST_TEMPERATURE = 0.40;


PanelPainter::PanelPainter(
	QGraphicsWidget * graphicsWidget,
	const Yawp::ConfigData * configData,
	StateMachine * stateMachine,
	Plasma::FormFactor formFactor)
    : BasePanelPainter(graphicsWidget, configData, stateMachine),
      m_formFactor(formFactor),
      m_pfLayoutDelegate( formFactor == Plasma::Horizontal ? calculateHorizontalLayout : calculateVerticalLayout),
      m_pfCompactLayoutDelegate( formFactor == Plasma::Horizontal ? calculateCompactHorizontalLayout : calculateCompactVerticalLayout)
{
}

PanelPainter::~PanelPainter()
{
}

Plasma::FormFactor
PanelPainter::formFactor() const
{
	return m_formFactor;
}

Yawp::PainterType
PanelPainter::painterType() const
{
	return Yawp::PanelPainter;
}

int
PanelPainter::widthForHeight(int height) const
{
	QSize requiredContentSize;
	QRect todaysIconRect;
	QRect todaysTempRect;
	
	const PanelLayoutDelegate layoutDelegate = getLayoutDelegate();

	if (m_formFactor == Plasma::Horizontal)
	{
		(*layoutDelegate)(height, configData(), requiredContentSize, todaysTempRect, todaysIconRect, NULL, NULL);
		return requiredContentSize.width();
	}
	else
	{
		// When we are in vertical panel mode, we can not get panel width for a specific height,
		// because the panel height depends on panel width.
		// Therefore we calculate the panel height for a specific width and scale this rectangle
		// to the required height to get the requested width.
		int fakeWidth = 30;
		(*layoutDelegate)(fakeWidth, configData(), requiredContentSize, todaysTempRect, todaysIconRect, NULL, NULL);
		return qRound((qreal)(height * requiredContentSize.width()) / (qreal)(requiredContentSize.height()));
	}
}

int
PanelPainter::heightForWidth(int width) const
{
	QSize requiredContentSize;
	QRect todaysIconRect;
	QRect todaysTempRect;
	
	const PanelLayoutDelegate layoutDelegate = getLayoutDelegate();
	
	if (m_formFactor == Plasma::Vertical)
	{
		(*layoutDelegate)(width, configData(), requiredContentSize, todaysTempRect, todaysIconRect, NULL, NULL);
		return requiredContentSize.height();
	}
	else
	{
		// When we are in horizontal panel mode, we can not get panel height for a specific width,
		// because the panel width depends on panel height.
		// Therefore we calculate the panel width for a specific height and scale this rectangle
		// to the required width to get the requested height.
		int fakeHeight = 30;
		(*layoutDelegate)(fakeHeight, configData(), requiredContentSize, todaysTempRect, todaysIconRect, NULL, NULL);
		return qRound((qreal)(width * requiredContentSize.height()) / (qreal)(requiredContentSize.width()));
	}
}

void
PanelPainter::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
	const CityWeather * city = stateMachine()->currentCity();
	if (city == 0 ||
	    city->days().count() == 0 ||
	    !configData()->forecastWeatherPanelFormat.testFlag( Yawp::PanelIcon ))
	{
		return;
	}

	const int maxDays = qMin(city->days().count(), m_vForecastIconRects.size());

	for (int dayIndex = 0; dayIndex < maxDays; ++dayIndex)
	{
		const QRect iconRect = m_vForecastIconRects.at(dayIndex);
	  
		if (iconRect.contains(event->pos().x(), event->pos().y()))
		{
			if (city->days().at(dayIndex)->hasNightValues())
			{
			      if (popupPainter() != 0)
				      popupPainter()->triggerWeatherIconAnimation(dayIndex);
			      else
				      initWeatherIconChange(iconRect, dayIndex, !(dayIndex == 0));
			}
			event->accept();
			return;
		}
	}
}

QRect
PanelPainter::getContentsRect(const QRect & contentsRect) const
{
	return contentsRect;
}

void
PanelPainter::handleLayoutChanges()
{
	const QRect currContentsRect = contentsRect();
	QSize requiredContentSize;
	
	const PanelLayoutDelegate layoutDelegate = getLayoutDelegate();
	(*layoutDelegate)(
		m_formFactor == Plasma::Horizontal ? currContentsRect.height() : currContentsRect.width(),
		configData(),
		requiredContentSize,
		m_todaysTempRect, m_todaysIconRect,
		&m_vForecastTemperatureRects, &m_vForecastIconRects);
}

void
PanelPainter::slotToggleWeatherIcon(int dayIndex)
{
	if (dayIndex < m_vForecastIconRects.size())
	{
		initWeatherIconChange(m_vForecastIconRects.at(dayIndex), dayIndex, !(dayIndex == 0));
	}
	else
	{
		setAnimationType(DummyAnimation);
		timeLine()->start();

		emit signalToggleWeatherIcon(dayIndex);
	}
}

void
PanelPainter::drawPage(QPainter * painter, const QRect & contentsRect) const
{
	dStartFunct();
	const CityWeather * city = stateMachine()->currentCity();
	
	if (!city || city->days().count() == 0)
	{
		dWarning() << "No city available";
		dEndFunct();
		return;
	}

	/*******************************************************************\
	*   This will paint the rectangles of all temperatures and icons.   *
	*   This might come handy when you modify the layout.               *
	********************************************************************
	
	painter->save();
	if (m_todaysTempRect.isValid())
	{
		painter->setBrush(QColor(Qt::blue));
		painter->setPen(QColor(Qt::green));
		painter->drawRect(m_todaysTempRect);
	}
	
	if (m_todaysIconRect.isValid())
	{
		painter->setBrush(QColor(Qt::green));
		painter->setPen(QColor(Qt::red));
		painter->drawRect(m_todaysIconRect);
	}
	
	painter->setBrush(QColor(Qt::blue));
	painter->setPen(QColor(Qt::green));
	foreach(QRect rect, m_vForecastTemperatureRects)
		painter->drawRect(rect);
	
	painter->setBrush(QColor(Qt::green));
	painter->setPen(QColor(Qt::red));
	foreach(QRect icon, m_vForecastIconRects)
		painter->drawRect(icon);
	
	painter->restore();
	
	********************************************************************/
	
	const YawpWeather * weather = stateMachine()->weather(0, true);
	if (!weather)
	{
		dWarning() << "No weather information available";
		dEndFunct();
		return;
	}

	QFont font = painter->font();
	
	int todaysTemperatureFontSize;
	int todaysTemperatureAlignmentFlags = Qt::AlignCenter;
	int forecastTempertatureFontSize;
	int forecastTemperatureAlignmentFlags = Qt::AlignCenter;
	
	if (m_formFactor == Plasma::Horizontal)
	{
		const qreal panelHeight = (qreal)contentsRect.height();
		
		if (configData()->bUseCompactPanelLayout)
		{
			todaysTemperatureFontSize = qRound(panelHeight * HORIZONTAL_TODAYS_COMPACT_TEMPERATURE);
			forecastTempertatureFontSize = qRound(panelHeight * HORIZONTAL_FORECAST_COMPACT_TEMPERATURE);
		}
		else
		{
			todaysTemperatureFontSize = qRound(panelHeight * HORIZONTAL_TODAYS_TEMPERATURE);
			todaysTemperatureAlignmentFlags = Qt::AlignVCenter | Qt::AlignRight;
			forecastTempertatureFontSize = qRound(panelHeight * HORIZONTAL_FORECAST_TEMPERATURE);
			forecastTemperatureAlignmentFlags = Qt::AlignRight | Qt::AlignVCenter;
		}
	}
	else
	{
		const qreal panelWidth = (qreal)contentsRect.width();
		
		if (configData()->bUseCompactPanelLayout)
		{
			todaysTemperatureFontSize = qRound(panelWidth * VERTICAL_TODAYS_COMPACT_TEMPERATURE);
			forecastTempertatureFontSize = qRound(panelWidth * VERTICAL_FORECAST_COMPACT_TEMPERATURE);
		}
		else
		{
			todaysTemperatureFontSize = qRound(panelWidth * VERTICAL_TODAYS_TEMPERATURE);
			forecastTempertatureFontSize = qRound(panelWidth * VERTICAL_FORECAST_TEMPERATURE);
		}
	}
	
	/***  PAINT TODAYS ICON AND TEMPERATURE ***
	*/
	if (m_todaysIconRect.isValid())
		drawWeatherIcon(painter, weather, m_todaysIconRect);

	if (m_todaysTempRect.isValid() && weather->currentTemperature() < SHRT_MAX)
	{
		font.setBold(false);
		font.setPixelSize(todaysTemperatureFontSize);
		painter->setFont(font);
		
		drawText(painter, m_todaysTempRect, todaysTemperatureAlignmentFlags,
			QString::number(weather->currentTemperature()) + QChar(0xB0) );
	}
	
	/***  PAINT FORECAST ICON AND TEMPERATURE ***
	*/
	font.setBold(false);
	font.setPixelSize(forecastTempertatureFontSize);
	painter->setFont(font);

	const int maxDays = qMin(stateMachine()->currentCity()->days().count(), configData()->iPanelForecastDays);
	
	for (int forecastDayIndex = 0; forecastDayIndex < maxDays; ++forecastDayIndex)
	{
		weather = stateMachine()->weather(forecastDayIndex);
		
		if (animationType() == AbstractPainter::IconAnimation && animationIndex() == forecastDayIndex)
		{
		      // we do not draw animated weather icon here
		}
		else if (forecastDayIndex < m_vForecastIconRects.size())
		{
			drawWeatherIcon(
				painter,
				weather,
				m_vForecastIconRects.at(forecastDayIndex),
				forecastDayIndex != 0);
		}
		
		if (forecastDayIndex < m_vForecastTemperatureRects.size())
		{
			drawTemperature(
				painter,
				weather,
				forecastTemperatureAlignmentFlags,
				m_vForecastTemperatureRects.at(forecastDayIndex));
		}
	}
	dEndFunct();
}

void
PanelPainter::drawTemperature(QPainter * painter, const YawpWeather * weather, int alignmentFlag, const QRect & tempRect) const
{
	QRect rect(tempRect.x(), tempRect.y(), tempRect.width(), qRound(tempRect.height() / 2.0f));

	if (weather->highTemperature() < SHRT_MAX)
	{
		QString text = QString::number(weather->highTemperature()) + QChar(0xB0);
		drawText( painter, rect, alignmentFlag, text );
	}
	if (weather->lowTemperature() < SHRT_MAX)
	{
		rect.moveTop( rect.bottom() );
		QString text  = QString::number(weather->lowTemperature()) + QChar(0xB0);

		drawGreyText( painter, rect, alignmentFlag, text );
	}
}

PanelPainter::PanelLayoutDelegate
PanelPainter::getLayoutDelegate() const
{
      return configData()->bUseCompactPanelLayout ? m_pfCompactLayoutDelegate : m_pfLayoutDelegate;
}

void
PanelPainter::getHorizontalTemperatureSize(
	const int contentsHeight,
	const bool bUseCompactPanelLayout,
	int & todaysTemperatureWidth,
	int & forecastTemperatureWidth)
{
	int todaysPixelSize = 0;
	int forecastPixelSize = 0;
	
	if (bUseCompactPanelLayout)
	{
		todaysPixelSize = qRound((qreal)contentsHeight * HORIZONTAL_TODAYS_COMPACT_TEMPERATURE);
		forecastPixelSize = qRound((qreal)contentsHeight * HORIZONTAL_FORECAST_COMPACT_TEMPERATURE);
	}
	else
	{
		todaysPixelSize = qRound((qreal)contentsHeight * HORIZONTAL_TODAYS_TEMPERATURE);
		forecastPixelSize = qRound((qreal)contentsHeight * HORIZONTAL_FORECAST_TEMPERATURE);
	}
	todaysTemperatureWidth = getTemperatureWidth(todaysPixelSize, QLatin1String("-99") + QChar(0xB0));
	forecastTemperatureWidth = getTemperatureWidth(forecastPixelSize, QLatin1String("-99") + QChar(0xB0));
	
	
	// todays temperature width will be set to maximum size of icon size an temperature size
	if (bUseCompactPanelLayout)
	{
		int iconSize = qRound((qreal)contentsHeight * HORIZONTAL_COMPACT_ICON_SIZE);
		todaysTemperatureWidth = qMax(todaysTemperatureWidth, iconSize);
		forecastTemperatureWidth = qMax(forecastTemperatureWidth, iconSize);
	}
	else
	{
		// leave a little space to the weather icon of the previous day
		forecastTemperatureWidth = qRound(1.05 * (qreal)forecastTemperatureWidth);
	}
}

void
PanelPainter::getVerticalTemperatureSize(
	const int contentsWidth,
	const bool bUseCompactPanelLayout,
	int & todaysTemperatureHeight,
	int & forecastTemperatureHeight)
{
	if (bUseCompactPanelLayout)
	{
		todaysTemperatureHeight = qRound(contentsWidth * VERTICAL_TODAYS_COMPACT_TEMPERATURE);
		forecastTemperatureHeight = qRound(2.0f * contentsWidth * VERTICAL_FORECAST_COMPACT_TEMPERATURE);
	}
	else
	{
		todaysTemperatureHeight = qRound(contentsWidth * VERTICAL_TODAYS_TEMPERATURE);
		forecastTemperatureHeight = qRound(2.0f * contentsWidth * VERTICAL_FORECAST_TEMPERATURE);
	}
}

int
PanelPainter::getTemperatureWidth( int pixelSize, const QString & text )
{
	Plasma::Theme * theme = Plasma::Theme::defaultTheme();
	QFont font = theme->font(Plasma::Theme::DefaultFont);
	
	font.setBold(false);
	font.setPixelSize( pixelSize );
	QFontMetrics fm(font);
	return fm.width( text );
}

void
PanelPainter::calculateHorizontalLayout(
	const int panelHeight,
	const Yawp::ConfigData * configData,
	QSize & contentsSize,
	QRect & todaysTempRect,
	QRect & todaysIconRect,
	QList<QRect> * forecastTempRects,
	QList<QRect> * forecastIconRects)
{
	//--- clear all old values ---
	contentsSize = QSize();
	todaysTempRect = todaysIconRect = QRect();
	
	if (forecastIconRects != NULL)
		forecastIconRects->clear();
	if (forecastTempRects != NULL)
		forecastTempRects->clear();

	//--- when we have no config data, just exit ---
	if (!configData)
		return;
	
	 // Spacer between today and first forecast day
	const int todayForecastSpacer = qRound(0.10 * (qreal)panelHeight);
	
	 // Spacer between two forecast days
	const int betweenForecastDaysSpacer = qRound(0.09 * (qreal)panelHeight);
	
	// Spacer between temperature and icon of one forecast day
	const int betweenForecastItemsSpacer = qRound(0.02 * (qreal)panelHeight);
	
	int todaysTemperatureWidth = 0;
	int forecastTemperatureWidth = 0;
	int currentPosition = 0;

	getHorizontalTemperatureSize(
		panelHeight,
		configData->bUseCompactPanelLayout,
		todaysTemperatureWidth,
		forecastTemperatureWidth);
	
	if (configData->todaysWeatherPanelFormat.testFlag( Yawp::PanelTemperature ))
	{
		todaysTempRect = QRect(currentPosition, 0, todaysTemperatureWidth, panelHeight);
		currentPosition = todaysTempRect.right() + 1;
	}
	
	if (configData->todaysWeatherPanelFormat.testFlag( Yawp::PanelIcon ))
	{
		todaysIconRect = QRect(currentPosition, 0, panelHeight, panelHeight);
		currentPosition = todaysIconRect.right() + 1;
	}
	
	if (currentPosition > 0 && configData->iPanelForecastDays > 0)
		currentPosition += todayForecastSpacer;
	
	for(int forecastDayIndex = 0; forecastDayIndex < configData->iPanelForecastDays; ++forecastDayIndex)
	{
		int itemCounter = 0;
		
		if (configData->forecastWeatherPanelFormat.testFlag( Yawp::PanelTemperature ))
		{
			QRect temp = QRect(currentPosition, 0, forecastTemperatureWidth, panelHeight);
			currentPosition = temp.right() + 1;
			itemCounter += 1;

			if (forecastTempRects != NULL)
				forecastTempRects->append(temp);
		}
		
		if (configData->forecastWeatherPanelFormat.testFlag( Yawp::PanelIcon ))
		{
			if (itemCounter > 0)
				currentPosition += betweenForecastItemsSpacer;
			
			QRect icon = QRect(currentPosition, 0, panelHeight, panelHeight);
			currentPosition = icon.right() + 1;
			itemCounter += 1;

			if (forecastIconRects != NULL)
				forecastIconRects->append(icon);
		}
		
		if (itemCounter > 0 && forecastDayIndex + 1 < configData->iPanelForecastDays)
			currentPosition += betweenForecastDaysSpacer;
	}
	
	contentsSize = QSize(currentPosition, panelHeight);
}

void
PanelPainter::calculateCompactHorizontalLayout(
	const int panelHeight,
	const Yawp::ConfigData * configData,
	QSize & contentsSize,
	QRect & todaysTempRect,
	QRect & todaysIconRect,
	QList<QRect> * forecastTempRects,
	QList<QRect> * forecastIconRects)
{
	//--- clear all old values ---
	contentsSize = QSize();
	todaysTempRect = todaysIconRect = QRect();
	
	if (forecastIconRects != NULL)
		forecastIconRects->clear();
	if (forecastTempRects != NULL)
		forecastTempRects->clear();

	//--- when we have no config data, just exit ---
	if (!configData)
		return;
	
	int todaysTemperatureWidth = 0;
	int forecastTemperatureWidth = 0;
	int currentPosition = 0;
	
	getHorizontalTemperatureSize(
		panelHeight,
		configData->bUseCompactPanelLayout,
		todaysTemperatureWidth,
		forecastTemperatureWidth);
	
	int iconSize = qRound((qreal)panelHeight * HORIZONTAL_COMPACT_ICON_SIZE);
	int offset = todaysTemperatureWidth > iconSize ? (todaysTemperatureWidth - iconSize) / 2 : 0;
	todaysIconRect = QRect( offset, 0, iconSize, iconSize );
	todaysTempRect = QRect(0, todaysIconRect.bottom(), todaysTemperatureWidth, panelHeight - iconSize);
	currentPosition = todaysTempRect.right() + qRound(0.08 * (qreal)panelHeight);
	
	int forecastIconSize = qRound((qreal)panelHeight * (HORIZONTAL_COMPACT_ICON_SIZE - 0.10));
	int forecastIconOffset = forecastTemperatureWidth > forecastIconSize ? (forecastTemperatureWidth - forecastIconSize) / 2 : 0;
	for(int forecastDayIndex = 0; forecastDayIndex < configData->iPanelForecastDays; ++forecastDayIndex)
	{
		QRect iconRect = QRect(currentPosition + forecastIconOffset, 0, forecastIconSize, forecastIconSize);
		QRect tempRect = QRect(currentPosition, iconRect.bottom(),
			forecastTemperatureWidth - 4, panelHeight - iconRect.height() - 2);
		
		currentPosition = tempRect.right() + 1;
		
		if (forecastIconRects != NULL)
			forecastIconRects->append(iconRect);
		if (forecastTempRects != NULL)
			forecastTempRects->append(tempRect);
	}
	
	contentsSize = QSize(currentPosition, panelHeight);
}

void
PanelPainter::calculateVerticalLayout(
	const int panelWidth,
	const Yawp::ConfigData * configData,
	QSize & contentsSize,
	QRect & todaysTempRect,
	QRect & todaysIconRect,
	QList<QRect> * forecastTempRects,
	QList<QRect> * forecastIconRects)
{
	//--- clear all old values ---
	contentsSize = QSize();
	todaysTempRect = todaysIconRect = QRect();
	
	if (forecastIconRects != NULL)
		forecastIconRects->clear();
	if (forecastTempRects != NULL)
		forecastTempRects->clear();

	//--- when we have no config data, just exit ---
	if (!configData)
		return;

	 // Spacer between today and first forecast day
	const int todayForecastSpacer = qRound(0.10 * (qreal)panelWidth);
	
	 // Spacer between two forecast days
	const int betweenForecastDaysSpacer = qRound(0.09 * (qreal)panelWidth);
	
	// Spacer between temperature and icon of one forecast day
	const int betweenForecastItemsSpacer = qRound(0.02 * (qreal)panelWidth);

	int todaysTemperatureHeight = 0;
	int forecastTemperatureHeight = 0;
	int currentPosition = 0;
	
	getVerticalTemperatureSize(
		panelWidth,
		configData->bUseCompactPanelLayout,
		todaysTemperatureHeight,
		forecastTemperatureHeight);

	if (configData->todaysWeatherPanelFormat.testFlag( Yawp::PanelTemperature ))
	{
		todaysTempRect = QRect(0, 0, panelWidth, todaysTemperatureHeight);
		currentPosition = todaysTempRect.bottom() + 1;
	}
	
	if (configData->todaysWeatherPanelFormat.testFlag( Yawp::PanelIcon ))
	{
		todaysIconRect = QRect(0, currentPosition, panelWidth, panelWidth);
		currentPosition = todaysIconRect.bottom() + 1;
	}
	
	if (currentPosition > 0 && configData->iPanelForecastDays > 0)
		currentPosition += todayForecastSpacer;
	
	for(int forecastDayIndex = 0; forecastDayIndex < configData->iPanelForecastDays; ++forecastDayIndex)
	{
		int itemCounter = 0;
		
		if (configData->forecastWeatherPanelFormat.testFlag( Yawp::PanelTemperature ))
		{
			QRect temp = QRect(0, currentPosition, panelWidth, forecastTemperatureHeight);
			currentPosition = temp.bottom() + 1;
			itemCounter += 1;

			if (forecastTempRects != NULL)
				forecastTempRects->append(temp);
		}
		
		if (configData->forecastWeatherPanelFormat.testFlag( Yawp::PanelIcon ))
		{
			if (itemCounter > 0)
				currentPosition += betweenForecastItemsSpacer;
			
			QRect icon = QRect(0, currentPosition, panelWidth, panelWidth);
			currentPosition = icon.bottom() + 1;
			itemCounter += 1;

			if (forecastIconRects != NULL)
				forecastIconRects->append(icon);
		}
		
		if (itemCounter > 0 && forecastDayIndex + 1 < configData->iPanelForecastDays)
			currentPosition += betweenForecastDaysSpacer;
	}
	
	contentsSize = QSize(panelWidth, currentPosition);
}

void
PanelPainter::calculateCompactVerticalLayout(
	const int panelWidth,
	const Yawp::ConfigData * configData,
	QSize & contentsSize,
	QRect & todaysTempRect,
	QRect & todaysIconRect,
	QList<QRect> * forecastTempRects,
	QList<QRect> * forecastIconRects)
{
	//--- clear all old values ---
	contentsSize = QSize();
	todaysTempRect = todaysIconRect = QRect();
	
	if (forecastIconRects != NULL)
		forecastIconRects->clear();
	if (forecastTempRects != NULL)
		forecastTempRects->clear();

	//--- when we have no config data, just exit ---
	if (!configData)
		return;
	
	int todaysTemperatureHeight = 0;
	int forecastTemperatureHeight = 0;
	int currentPosition = 0;
	
	getVerticalTemperatureSize(
		panelWidth,
		configData->bUseCompactPanelLayout,
		todaysTemperatureHeight,
		forecastTemperatureHeight);
	
	int iconSize = qRound((qreal)panelWidth * VERTICAL_COMPACT_ICON_SIZE);
	todaysTemperatureHeight = qMax(todaysTemperatureHeight, iconSize);
	
	int todaysIconOffset = todaysTemperatureHeight > iconSize ? (todaysTemperatureHeight - iconSize) / 2 : 0;
	todaysIconRect = QRect(0, todaysIconOffset, iconSize, iconSize );
	todaysTempRect = QRect(todaysIconRect.right(), 0, panelWidth - iconSize, todaysTemperatureHeight);
	currentPosition = todaysTempRect.bottom();
	
	int forecastIconSize = qRound((qreal)panelWidth * (VERTICAL_COMPACT_ICON_SIZE - 0.10));
	int forecastIconOffset = forecastTemperatureHeight > forecastIconSize ? (forecastTemperatureHeight - forecastIconSize) / 2 : 0;
	for(int forecastDayIndex = 0; forecastDayIndex < configData->iPanelForecastDays; ++forecastDayIndex)
	{
		QRect iconRect = QRect(0, currentPosition + forecastIconOffset,
				       forecastIconSize, forecastIconSize);
		QRect tempRect = QRect(iconRect.right() + 2, currentPosition,
				       panelWidth - iconRect.width() - 2, forecastTemperatureHeight);

		currentPosition = tempRect.bottom() + 1;
		
		if (forecastIconRects != NULL)
			forecastIconRects->append(iconRect);
		if (forecastTempRects != NULL)
			forecastTempRects->append(tempRect);
	}
	
	contentsSize = QSize(panelWidth, currentPosition);
}
