diff options
Diffstat (limited to 'weather/src/addcitytool.cpp')
-rw-r--r-- | weather/src/addcitytool.cpp | 401 |
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); +} |