summaryrefslogtreecommitdiffstats
path: root/weather/src/addcitytool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'weather/src/addcitytool.cpp')
-rw-r--r--weather/src/addcitytool.cpp401
1 files changed, 401 insertions, 0 deletions
diff --git a/weather/src/addcitytool.cpp b/weather/src/addcitytool.cpp
new file mode 100644
index 0000000..219d92a
--- /dev/null
+++ b/weather/src/addcitytool.cpp
@@ -0,0 +1,401 @@
+#include "addcitytool.h"
+#include "settings.h"
+#include "forecastprovider.h"
+#include "painttextitem.h"
+#include "pixmaploader.h"
+
+#include <QPainter>
+#include <QInputDialog>
+#include <QEvent>
+#include <QGraphicsScene>
+#include <QGraphicsSceneMouseEvent>
+#include <QApplication>
+#include <QDebug>
+
+#define ADD_BACKGROUND (PixmapLoader::getPic("background_add_city"))
+#define ADD_ERROR_BACKGROUND (PixmapLoader::getPic("background_error_adding"))
+
+#define CLOSE_BUTTON_PIXMAP (PixmapLoader::getPic("button_list_delete"))
+#define ADD_BUTTON_PIXMAP (PixmapLoader::getPic("button_city_send"))
+#define BUTTON_LEFT (Settings::scaleWidth(408.0))
+
+#define ADD_TEXT_BACKGROUND (PixmapLoader::getPic("textfield_add_city"))
+#define ADD_TEXT_LEFT (Settings::scaleWidth(38.0))
+
+#define ADD_SCREEN_FONT_SIZE (Settings::scaleHeight(40.0))
+
+#define CITY_NAME_FONT_SIZE (Settings::scaleHeight(40.0))
+
+
+static inline qreal getCenterVerticalPos(QGraphicsItem *parent, QGraphicsItem *item)
+{
+ const qreal top = (parent->boundingRect().height() - item->boundingRect().height()) / 2;
+ return top - parent->boundingRect().top() - item->boundingRect().top();
+}
+
+static inline qreal getCenterVerticalPos(QGraphicsItem *item)
+{
+ return getCenterVerticalPos(item->parentItem(), item);
+}
+
+// AddCityScreen
+
+AddCityScreen::AddCityScreen(const QRectF &boundingRect, QGraphicsItem *parent)
+ : QGraphicsItem(parent)
+ , m_boundingRect(boundingRect)
+{
+}
+
+QRectF AddCityScreen::boundingRect () const
+{
+ return m_boundingRect;
+}
+
+void AddCityScreen::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *widget)
+{
+ Q_UNUSED(painter);
+ Q_UNUSED(opt);
+ Q_UNUSED(widget);
+}
+
+//
+
+#define ADD_A_CITY_TEXT "Add a city"
+
+AddCityLineEdit::AddCityLineEdit(QWidget *parent)
+ : QLineEdit(parent)
+ , m_clean(true)
+{
+ editReset();
+ connect(this, SIGNAL(textEdited(QString)), this, SLOT(textEditedSlot(QString)));
+}
+
+void AddCityLineEdit::editReset()
+{
+ m_clean = true;
+ setText(ADD_A_CITY_TEXT);
+}
+
+void AddCityLineEdit::focusOutEvent(QFocusEvent *event)
+{
+ if (m_clean)
+ setText(ADD_A_CITY_TEXT);
+ QLineEdit::focusOutEvent(event);
+}
+
+void AddCityLineEdit::focusInEvent(QFocusEvent *event)
+{
+ if (m_clean)
+ setText("");
+ QLineEdit::focusInEvent(event);
+}
+
+void AddCityLineEdit::textEditedSlot(const QString & text)
+{
+ Q_UNUSED(text);
+ static const QString cleanText(ADD_A_CITY_TEXT);
+ if (m_clean && text.length() >= cleanText.length() &&
+ text.left(cleanText.length()) == cleanText)
+ setText(text.right(text.length() - cleanText.length()));
+ m_clean = false;
+}
+
+// AddCityFirstScreen
+
+AddCityFirstScreen::AddCityFirstScreen(const QRectF &boundingRect, QGraphicsItem *parent)
+ : AddCityScreen(boundingRect, parent)
+ , m_textBackground(new QGraphicsPixmapItem(ADD_TEXT_BACKGROUND, this))
+ , m_button(new PixmapButton(80.0, ADD_BUTTON_PIXMAP, this))
+ , m_proxy(new QGraphicsProxyWidget(this))
+ , m_lineEdit(new AddCityLineEdit())
+{
+ setFlag(ItemHasNoContents, true);
+
+ m_button->setPos(BUTTON_LEFT, getCenterVerticalPos(m_button));
+ m_textBackground->setPos(ADD_TEXT_LEFT, getCenterVerticalPos(m_textBackground));
+
+
+ QFont font;
+ font.setFamily("Nokia Sans");
+ font.setPixelSize(CITY_NAME_FONT_SIZE);
+ font.setStyleStrategy(QFont::PreferAntialias);
+ m_lineEdit->setFont(font);
+
+ m_lineEdit->setFrame(false);
+ m_lineEdit->setTextMargins(0, 0, 0, 0);
+ m_lineEdit->setAttribute(Qt::WA_NoSystemBackground);
+ m_lineEdit->setStyleSheet("background: transparent; color:white");
+
+ QRect rect(0, 0, m_textBackground->pixmap().width(), m_textBackground->pixmap().height());
+ rect.adjust(5, 5, -5, -5);
+ m_lineEdit->setGeometry(rect);
+
+ m_proxy->setWidget(m_lineEdit);
+ m_proxy->setParentItem(m_textBackground);
+ m_proxy->setPos(5.0, 5.0);
+
+ m_lineEdit->setFocus();
+
+ connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClick()));
+}
+
+void AddCityFirstScreen::clean()
+{
+ m_lineEdit->editReset();
+}
+
+void AddCityFirstScreen::buttonClick()
+{
+ if (!m_lineEdit->text().isEmpty())
+ emit citySelected(m_lineEdit->text());
+}
+
+// AddCitySearchScreen
+
+AddCitySearchScreen::AddCitySearchScreen(const QRectF &boundingRect, QGraphicsItem *parent)
+ : AddCityScreen(boundingRect, parent)
+ , m_loading(new Loading(this))
+{
+ m_loading->hide();
+ m_loading->setPos(BUTTON_LEFT, getCenterVerticalPos(m_loading));
+
+}
+
+void AddCitySearchScreen::forecastResponse(int reqId, const ForecastData &forecast)
+{
+ if (reqId == m_reqId) {
+ reset();
+ if (!forecast.isNull() && !forecast.error())
+ emit forecastReceived(forecast);
+ else
+ emit forecastRequestError(m_city);
+ }
+}
+
+void AddCitySearchScreen::setCityName(const QString &name)
+{
+ m_city = name;
+ ForecastProvider::connectToResponseSignal(this, SLOT(forecastResponse(int, ForecastData)));
+ m_reqId = ForecastProvider::getForecast(m_city, false);
+ m_loading->start();
+ m_loading->show();
+ update();
+}
+
+void AddCitySearchScreen::reset()
+{
+ ForecastProvider::disconnectReceiver(this);
+ m_loading->stop();
+ m_loading->hide();
+}
+
+void AddCitySearchScreen::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *widget)
+{
+ Q_UNUSED(opt);
+ Q_UNUSED(widget);
+
+ TextPainter header(ADD_SCREEN_FONT_SIZE, QColor(255, 255, 255, 102), "Searching for");
+
+ TextPainter city(ADD_SCREEN_FONT_SIZE, QColor(255, 255, 255, 255), m_city);
+ city.setQuoted(true);
+ city.font().setBold(true);
+ city.setMaxWidth(BUTTON_LEFT);
+
+ qreal top = (boundingRect().height() - header.height() - city.height()) / 2;
+ top += boundingRect().top();
+
+ TextPainter::locateAtCenter(&header, 0.0, top, BUTTON_LEFT);
+ header.paint(painter);
+
+ TextPainter::locateAtCenter(&city, 0.0, top + header.height(), BUTTON_LEFT);
+ city.paint(painter);
+}
+
+// AddCityErrorScreen
+
+AddCityErrorScreen::AddCityErrorScreen(QGraphicsItem *parent)
+ : QGraphicsPixmapItem(ADD_ERROR_BACKGROUND, parent)
+ , m_button(new PixmapButton(80.0, CLOSE_BUTTON_PIXMAP, this))
+{
+ m_button->setPos(BUTTON_LEFT, getCenterVerticalPos(m_button));
+ connect(m_button, SIGNAL(clicked()), this, SIGNAL(closed()));
+}
+
+void AddCityErrorScreen::setCityName(const QString &name, ErrorType type)
+{
+ m_city = name;
+ m_type = type;
+ update();
+}
+
+void AddCityErrorScreen::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *widget)
+{
+ Q_UNUSED(opt);
+ Q_UNUSED(widget);
+ QGraphicsPixmapItem::paint(painter, opt, widget);
+ if (m_type == NotFound)
+ paintNotFound(painter);
+ else
+ paintAlreadyInList(painter);
+}
+
+void AddCityErrorScreen::paintNotFound(QPainter *painter)
+{
+ TextPainter header(ADD_SCREEN_FONT_SIZE, QColor(255, 255, 255, 102), "The city");
+ TextPainter footer(ADD_SCREEN_FONT_SIZE, QColor(255, 255, 255, 102), "wasn't found");
+
+ TextPainter city(ADD_SCREEN_FONT_SIZE, QColor(255, 255, 255, 255), m_city);
+ city.setQuoted(true);
+ city.font().setBold(true);
+ city.setMaxWidth(BUTTON_LEFT - header.width() - 5.0);
+
+ qreal top = (boundingRect().height() - city.height() - footer.height()) / 2;
+ top += boundingRect().top();
+
+ QList<TextPainter*> topLine;
+ topLine.append(&header);
+ topLine.append(&city);
+
+ TextPainter::locateAtCenter(topLine, 0.0, top, BUTTON_LEFT);
+ header.paint(painter);
+ city.paint(painter);
+
+ TextPainter::locateAtCenter(&footer, 0.0, top + city.height(), BUTTON_LEFT);
+ footer.paint(painter);
+}
+
+void AddCityErrorScreen::paintAlreadyInList(QPainter *painter)
+{
+ TextPainter header(ADD_SCREEN_FONT_SIZE, QColor(255, 255, 255, 102), "The city");
+ TextPainter header1(ADD_SCREEN_FONT_SIZE, QColor(255, 255, 255, 102), "is");
+ TextPainter footer(ADD_SCREEN_FONT_SIZE, QColor(255, 255, 255, 102), "already on your list");
+
+ TextPainter city(ADD_SCREEN_FONT_SIZE, QColor(255, 255, 255, 255), m_city);
+ city.setQuoted(true);
+ city.font().setBold(true);
+ city.setMaxWidth(BUTTON_LEFT - header.width() - header1.width() - 10.0);
+
+ qreal top = (boundingRect().height() - city.height() - footer.height()) / 2;
+ top += boundingRect().top();
+
+ QList<TextPainter*> topLine;
+ topLine.append(&header);
+ topLine.append(&city);
+ topLine.append(&header1);
+
+ TextPainter::locateAtCenter(topLine, 0.0, top, BUTTON_LEFT);
+ header.paint(painter);
+ city.paint(painter);
+ header1.paint(painter);
+
+ TextPainter::locateAtCenter(&footer, 0.0, top + city.height(), BUTTON_LEFT);
+ footer.paint(painter);
+}
+
+// AddCityTool
+
+AddCityTool::AddCityTool(const QList<ForecastData> &content, QGraphicsItem *parent)
+ : QGraphicsPixmapItem(ADD_BACKGROUND, parent)
+ , m_content(content)
+ , m_firstScreen(createFirstScreen())
+ , m_SearchScreen(createSearchScreen())
+ , m_ErrorScreen(createErrorScreen())
+{
+ setCurrentScreen(m_firstScreen);
+}
+
+AddCityTool::~AddCityTool()
+{
+}
+
+int AddCityTool::loadImages()
+{
+ PixmapLoader::load("background_add_city");
+ PixmapLoader::load("background_error_adding");
+ PixmapLoader::load("button_list_delete");
+ PixmapLoader::load("button_city_send");
+ PixmapLoader::load("textfield_add_city");
+ return 5;
+}
+
+void AddCityTool::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+void AddCityTool::cancel()
+{
+ m_SearchScreen->cancel();
+ setCurrentScreen(m_firstScreen);
+}
+
+AddCityFirstScreen *AddCityTool::createFirstScreen()
+{
+ AddCityFirstScreen *result = new AddCityFirstScreen(boundingRect(), this);
+ connect(result, SIGNAL(citySelected(QString)), this, SLOT(citySelected(QString)));
+ result->setPos(0.0, 0.0);
+ return result;
+}
+
+AddCitySearchScreen *AddCityTool::createSearchScreen()
+{
+ AddCitySearchScreen *result = new AddCitySearchScreen(boundingRect(), this);
+ connect(result, SIGNAL(forecastReceived(ForecastData)),
+ this, SLOT(forecastReceived(ForecastData)));
+ connect(result, SIGNAL(forecastRequestError(QString)),
+ this, SLOT(forecastRequestError(QString)));
+ result->setPos(0.0, 0.0);
+ return result;
+}
+
+AddCityErrorScreen *AddCityTool::createErrorScreen()
+{
+ AddCityErrorScreen *result = new AddCityErrorScreen(this);
+ connect(result, SIGNAL(closed()), this, SLOT(errorScreenClosed()));
+ result->setPos(0.0, 0.0);
+ return result;
+}
+
+void AddCityTool::setCurrentScreen(QGraphicsItem *screen)
+{
+ m_firstScreen->clean();
+ m_firstScreen->setVisible(screen == m_firstScreen);
+ m_SearchScreen->setVisible(screen == m_SearchScreen);
+ m_ErrorScreen->setVisible(screen == m_ErrorScreen);
+}
+
+void AddCityTool::errorScreenClosed()
+{
+ setCurrentScreen(m_firstScreen);
+}
+
+void AddCityTool::forecastReceived(const ForecastData &forecast)
+{
+ for (int i = 0; i < m_content.count(); ++i)
+ if (m_content[i].key() == forecast.key()) {
+ m_ErrorScreen->setCityName(forecast.cityName(), AddCityErrorScreen::AlreadyInList);
+ setCurrentScreen(m_ErrorScreen);
+ return;
+ }
+ emit newForecast(forecast);
+ setCurrentScreen(m_firstScreen);
+}
+
+void AddCityTool::forecastRequestError(const QString &name)
+{
+ m_ErrorScreen->setCityName(name, AddCityErrorScreen::NotFound);
+ setCurrentScreen(m_ErrorScreen);
+}
+
+void AddCityTool::citySelected(const QString &city)
+{
+ QString text = city.toUpper();
+ for (int i = 0; i < m_content.count(); ++i)
+ if (m_content[i].key().toUpper() == text) {
+ m_ErrorScreen->setCityName(city, AddCityErrorScreen::AlreadyInList);
+ setCurrentScreen(m_ErrorScreen);
+ return;
+ }
+ m_SearchScreen->setCityName(city);
+ setCurrentScreen(m_SearchScreen);
+}