From e3ba0476684edda1b48afd8a1dd01700bdb1bedd Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 23 Apr 2015 00:44:50 +0200 Subject: add fonts, dithering, weather rendering --- saltoqd/global.h | 6 ++ saltoqd/main.cpp | 14 ++++- saltoqd/msolimageiohandler.cpp | 59 +++++++++++++++++- saltoqd/msolimageiohandler.h | 1 + saltoqd/res/Q-Bold.otf | Bin 0 -> 71592 bytes saltoqd/res/Q-Light.otf | Bin 0 -> 68152 bytes saltoqd/res/Q-Regular.otf | Bin 0 -> 67996 bytes saltoqd/res/Q-Semibold.otf | Bin 0 -> 70744 bytes saltoqd/res/cardtemp0.png | Bin 0 -> 15589 bytes saltoqd/res/cardtemp10.png | Bin 0 -> 23311 bytes saltoqd/res/cardtemp20.png | Bin 0 -> 16169 bytes saltoqd/res/cardtemp30.png | Bin 0 -> 13797 bytes saltoqd/res/cardtemp40.png | Bin 0 -> 18856 bytes saltoqd/res/cardtempminus10.png | Bin 0 -> 23445 bytes saltoqd/res/cardtempminus20.png | Bin 0 -> 14294 bytes saltoqd/res/icon_weathercurrentlocation.png | Bin 0 -> 397 bytes saltoqd/res/temp0.png | Bin 0 -> 16977 bytes saltoqd/res/temp10.png | Bin 0 -> 26122 bytes saltoqd/res/temp20.png | Bin 0 -> 16208 bytes saltoqd/res/temp30.png | Bin 0 -> 14030 bytes saltoqd/res/temp40.png | Bin 0 -> 20274 bytes saltoqd/res/tempminus10.png | Bin 0 -> 26125 bytes saltoqd/res/tempminus20.png | Bin 0 -> 14836 bytes saltoqd/saltoqd.pro | 11 +++- saltoqd/settings.h | 1 + saltoqd/weathermanager.cpp | 93 +++++++++++++++++++++++++--- saltoqd/weathermanager.h | 10 ++- 27 files changed, 178 insertions(+), 17 deletions(-) create mode 100644 saltoqd/global.h create mode 100644 saltoqd/res/Q-Bold.otf create mode 100644 saltoqd/res/Q-Light.otf create mode 100644 saltoqd/res/Q-Regular.otf create mode 100644 saltoqd/res/Q-Semibold.otf create mode 100644 saltoqd/res/cardtemp0.png create mode 100644 saltoqd/res/cardtemp10.png create mode 100644 saltoqd/res/cardtemp20.png create mode 100644 saltoqd/res/cardtemp30.png create mode 100644 saltoqd/res/cardtemp40.png create mode 100644 saltoqd/res/cardtempminus10.png create mode 100644 saltoqd/res/cardtempminus20.png create mode 100644 saltoqd/res/icon_weathercurrentlocation.png create mode 100644 saltoqd/res/temp0.png create mode 100644 saltoqd/res/temp10.png create mode 100644 saltoqd/res/temp20.png create mode 100644 saltoqd/res/temp30.png create mode 100644 saltoqd/res/temp40.png create mode 100644 saltoqd/res/tempminus10.png create mode 100644 saltoqd/res/tempminus20.png (limited to 'saltoqd') diff --git a/saltoqd/global.h b/saltoqd/global.h new file mode 100644 index 0000000..2f02232 --- /dev/null +++ b/saltoqd/global.h @@ -0,0 +1,6 @@ +#ifndef GLOBAL_H +#define GLOBAL_H + +#define RES_PATH "/usr/share/saltoq/res" + +#endif // GLOBAL_H diff --git a/saltoqd/main.cpp b/saltoqd/main.cpp index 570f6c4..556c389 100644 --- a/saltoqd/main.cpp +++ b/saltoqd/main.cpp @@ -1,10 +1,18 @@ -#include -#include +#include +#include +#include +#include "global.h" #include "toqmanager.h" Q_DECL_EXPORT int main(int argc, char **argv) { - QCoreApplication app(argc, argv); + QGuiApplication app(argc, argv); + + QFontDatabase::addApplicationFont(RES_PATH "/Q-Light.otf"); + int id = QFontDatabase::addApplicationFont(RES_PATH "/Q-Regular.otf"); + qDebug() << QFontDatabase::applicationFontFamilies(id); + QFontDatabase::addApplicationFont(RES_PATH "/Q-Semibold.otf"); + QFontDatabase::addApplicationFont(RES_PATH "/Q-Bold.otf"); QScopedPointer settings(new Settings("/apps/saltoq")); QScopedPointer manager(new ToqManager(settings.data())); diff --git a/saltoqd/msolimageiohandler.cpp b/saltoqd/msolimageiohandler.cpp index e6a9065..5a18ff6 100644 --- a/saltoqd/msolimageiohandler.cpp +++ b/saltoqd/msolimageiohandler.cpp @@ -21,6 +21,17 @@ static inline QRgb decode_color(uchar p, uchar a = 255) return qRgba(p & 0xC0, (p & 0x30) << 2, (p & 0x0C) << 4, a); } +static inline uchar add_saturate(uchar val, int addend) +{ + int sum = val + addend; + return qMax(0, qMin(sum, 255)); +} + +static inline void add_saturate(uchar* val, int addend) +{ + *val = add_saturate(*val, addend); +} + } MSOLImageIOHandler::MSOLImageIOHandler() : QImageIOHandler() @@ -93,6 +104,7 @@ bool MSOLImageIOHandler::write(const QImage &image) const int line_size = width * pixel_size; QImage img = image.convertToFormat(alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32); + img = ditherForMsol(img); uchar header[header_size] = { 0 }; strcpy(reinterpret_cast(&header[0]), "MSOL "); @@ -159,7 +171,8 @@ QVariant MSOLImageIOHandler::option(ImageOption option) const void MSOLImageIOHandler::setOption(ImageOption option, const QVariant &value) { - + Q_UNUSED(option); + Q_UNUSED(value); } QByteArray convertImageToMsol(const QImage &img) @@ -186,3 +199,47 @@ QImage convertMsolToImage(const QByteArray &msol) } return img; } + +QImage ditherForMsol(const QImage &src) +{ + Q_ASSERT(src.format() == QImage::Format_ARGB32 || src.format() == QImage::Format_RGB32); + const int width = src.width(), height = src.height(); + const int bytesPerLine = src.bytesPerLine(); + + QImage dst(src); + + // If we are on Big endian, then we must skip the first channel (=alpha). + // In LE, use the first three channels and skip the final one (=alpha). + const bool bigEndian = QSysInfo::ByteOrder == QSysInfo::BigEndian; + uchar *line = dst.bits() + (bigEndian ? 1 : 0); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + for (int chan = 0; chan < 3; chan++) { + const uchar val = line[x * 4 + chan]; + const uchar quant = add_saturate(val, 0x20) & 0xC0; + const int error = val - quant; + + line[x * 4 + chan] = quant; + + if (x + 1 < width) + add_saturate(&line[(x + 1) * 4 + chan], (error * 7) / 16); + + if (y + 1 < height) { + uchar *nextLine = line + bytesPerLine; + + if (x > 0) + add_saturate(&nextLine[(x - 1) * 4 + chan], (error * 3) / 16); + + add_saturate(&nextLine[x * 4 + chan], (error * 5) / 16); + + if (x + 1 < width) + add_saturate(&nextLine[(x + 1) * 4 + chan], (error * 1) / 16); + } + } + } + + line += bytesPerLine; + } + + return dst; +} diff --git a/saltoqd/msolimageiohandler.h b/saltoqd/msolimageiohandler.h index fbfb1b5..ad0120e 100644 --- a/saltoqd/msolimageiohandler.h +++ b/saltoqd/msolimageiohandler.h @@ -19,5 +19,6 @@ public: QByteArray convertImageToMsol(const QImage &img); QImage convertMsolToImage(const QByteArray &msol); +QImage ditherForMsol(const QImage &src); #endif // MSOLIMAGEIOHANDLER_H diff --git a/saltoqd/res/Q-Bold.otf b/saltoqd/res/Q-Bold.otf new file mode 100644 index 0000000..cb033f4 Binary files /dev/null and b/saltoqd/res/Q-Bold.otf differ diff --git a/saltoqd/res/Q-Light.otf b/saltoqd/res/Q-Light.otf new file mode 100644 index 0000000..457ba17 Binary files /dev/null and b/saltoqd/res/Q-Light.otf differ diff --git a/saltoqd/res/Q-Regular.otf b/saltoqd/res/Q-Regular.otf new file mode 100644 index 0000000..79fe9a3 Binary files /dev/null and b/saltoqd/res/Q-Regular.otf differ diff --git a/saltoqd/res/Q-Semibold.otf b/saltoqd/res/Q-Semibold.otf new file mode 100644 index 0000000..2644588 Binary files /dev/null and b/saltoqd/res/Q-Semibold.otf differ diff --git a/saltoqd/res/cardtemp0.png b/saltoqd/res/cardtemp0.png new file mode 100644 index 0000000..a434b53 Binary files /dev/null and b/saltoqd/res/cardtemp0.png differ diff --git a/saltoqd/res/cardtemp10.png b/saltoqd/res/cardtemp10.png new file mode 100644 index 0000000..16b77cf Binary files /dev/null and b/saltoqd/res/cardtemp10.png differ diff --git a/saltoqd/res/cardtemp20.png b/saltoqd/res/cardtemp20.png new file mode 100644 index 0000000..a166f20 Binary files /dev/null and b/saltoqd/res/cardtemp20.png differ diff --git a/saltoqd/res/cardtemp30.png b/saltoqd/res/cardtemp30.png new file mode 100644 index 0000000..781990d Binary files /dev/null and b/saltoqd/res/cardtemp30.png differ diff --git a/saltoqd/res/cardtemp40.png b/saltoqd/res/cardtemp40.png new file mode 100644 index 0000000..5cd5ad7 Binary files /dev/null and b/saltoqd/res/cardtemp40.png differ diff --git a/saltoqd/res/cardtempminus10.png b/saltoqd/res/cardtempminus10.png new file mode 100644 index 0000000..4d37871 Binary files /dev/null and b/saltoqd/res/cardtempminus10.png differ diff --git a/saltoqd/res/cardtempminus20.png b/saltoqd/res/cardtempminus20.png new file mode 100644 index 0000000..ae6f6f8 Binary files /dev/null and b/saltoqd/res/cardtempminus20.png differ diff --git a/saltoqd/res/icon_weathercurrentlocation.png b/saltoqd/res/icon_weathercurrentlocation.png new file mode 100644 index 0000000..0ebf63a Binary files /dev/null and b/saltoqd/res/icon_weathercurrentlocation.png differ diff --git a/saltoqd/res/temp0.png b/saltoqd/res/temp0.png new file mode 100644 index 0000000..e288a15 Binary files /dev/null and b/saltoqd/res/temp0.png differ diff --git a/saltoqd/res/temp10.png b/saltoqd/res/temp10.png new file mode 100644 index 0000000..09735c5 Binary files /dev/null and b/saltoqd/res/temp10.png differ diff --git a/saltoqd/res/temp20.png b/saltoqd/res/temp20.png new file mode 100644 index 0000000..18afc4b Binary files /dev/null and b/saltoqd/res/temp20.png differ diff --git a/saltoqd/res/temp30.png b/saltoqd/res/temp30.png new file mode 100644 index 0000000..1327fd2 Binary files /dev/null and b/saltoqd/res/temp30.png differ diff --git a/saltoqd/res/temp40.png b/saltoqd/res/temp40.png new file mode 100644 index 0000000..87004a9 Binary files /dev/null and b/saltoqd/res/temp40.png differ diff --git a/saltoqd/res/tempminus10.png b/saltoqd/res/tempminus10.png new file mode 100644 index 0000000..0ff04ca Binary files /dev/null and b/saltoqd/res/tempminus10.png differ diff --git a/saltoqd/res/tempminus20.png b/saltoqd/res/tempminus20.png new file mode 100644 index 0000000..786f177 Binary files /dev/null and b/saltoqd/res/tempminus20.png differ diff --git a/saltoqd/saltoqd.pro b/saltoqd/saltoqd.pro index 18322b0..1c40e7c 100644 --- a/saltoqd/saltoqd.pro +++ b/saltoqd/saltoqd.pro @@ -50,7 +50,8 @@ HEADERS += \ settingsmanager.h \ toqmanageradaptor.h \ msolimageiohandler.h \ - cardmanageradaptor.h + cardmanageradaptor.h \ + global.h DBUS_INTERFACES += com.nokia.profiled.xml org.nemomobile.voicecall.VoiceCallManager.xml org.nemomobile.voicecall.VoiceCall.xml QDBUSXML2CPP_INTERFACE_HEADER_FLAGS = -i voicecallmanager.h @@ -58,10 +59,14 @@ QDBUSXML2CPP_INTERFACE_HEADER_FLAGS = -i voicecallmanager.h target.path = /usr/bin INSTALLS += target -unit.path = /usr/lib/systemd/user/ +res.path = /usr/share/saltoq/res +res.files = res/Q-Bold.otf res/Q-Light.otf res/Q-Regular.otf res/Q-Semibold.otf res/*.png +INSTALLS += res + +unit.path = /usr/lib/systemd/user unit.files = saltoqd.service INSTALLS += unit -workaround.path = /usr/lib/systemd/system/ +workaround.path = /usr/lib/systemd/system workaround.files = saltoq-bt-sniff-subrate.service INSTALLS += workaround diff --git a/saltoqd/settings.h b/saltoqd/settings.h index bfc0dcb..4c1ef87 100644 --- a/saltoqd/settings.h +++ b/saltoqd/settings.h @@ -2,6 +2,7 @@ #define SETTINGS_H #include +#include "global.h" class Settings : public MDConfGroup { diff --git a/saltoqd/weathermanager.cpp b/saltoqd/weathermanager.cpp index ce36f8c..82126d7 100644 --- a/saltoqd/weathermanager.cpp +++ b/saltoqd/weathermanager.cpp @@ -1,18 +1,93 @@ +#include +#include +#include +#include + #include "fmsmanager.h" +#include "msolimageiohandler.h" #include "weathermanager.h" +static QString getBackgroundImage(int temp) +{ + if (temp > 35) { + return "temp40.png"; + } else if (temp > 25) { + return "temp30.png"; + } else if (temp > 15) { + return "temp20.png"; + } else if (temp > 5) { + return "temp10.png"; + } else if (temp > -5) { + return "temp0.png"; + } else if (temp > -15) { + return "tempminus10.png"; + } else { + return "tempminus20.png"; + } +} + WeatherManager::WeatherManager(FmsManager *fms, ToqManager *toq) : - QObject(toq), _toq(toq), _fms(fms) + QObject(toq), _toq(toq), _fms(fms), + _file(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/sailfish-weather/weather.json"), + _watcher(new QFileSystemWatcher(QStringList(_file), this)), + _refreshTimer(new QTimer(this)) { - connect(_toq, &ToqManager::connected, - this, &WeatherManager::handleToqConnected); + connect(_watcher, &QFileSystemWatcher::fileChanged, + _refreshTimer, static_cast(&QTimer::start)); + connect(_refreshTimer, &QTimer::timeout, + this, &WeatherManager::doRefresh); + + qDebug() << "Monitoring file" << _file; + + _refreshTimer->setSingleShot(true); + _refreshTimer->setInterval(2000); + _refreshTimer->start(); } -void WeatherManager::handleToqConnected() +QImage WeatherManager::constructImage(const QJsonObject &obj) { -#if 0 - qDebug() << "Putting file"; - QByteArray data(img_data, sizeof(img_data)); - _fms->updateFile("/apps/weather/99.img", data); -#endif + QJsonObject weather = obj["weather"].toObject(); + QString city = obj["city"].toString(); + int temp = weather["temperatureFeel"].toInt(); + QImage img(RES_PATH "/card" + getBackgroundImage(temp)); + + if (img.isNull()) { + qWarning() << "Invalid background image" << QString(RES_PATH "/card" + getBackgroundImage(temp)); + return img; + } + + QPainter p(&img); + p.setPen(QColor(230, 230, 230)); + p.setFont(QFont("Qualcomm", 22)); + p.drawText(10, 36, city); + + p.setFont(QFont("Qualcomm", 48)); + p.drawText(14, 110, QString::fromUtf8("%1 °C").arg(temp)); + + return img; +} + +void WeatherManager::doRefresh() +{ + QFile file(_file); + + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Failed to open" << _file; + return; + } + + QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); + QJsonObject root = doc.object(); + QJsonObject currentLoc = root["currentLocation"].toObject(); + QJsonArray locs = root["savedLocations"].toArray(); + + int index = 1; + QImage img = constructImage(currentLoc); + _fms->updateFile(QString::fromLatin1("/apps/weather/%1.img").arg(index), convertImageToMsol(img)); + + for (const QJsonValue &value : locs) { + index++; + img = constructImage(value.toObject()); + _fms->updateFile(QString::fromLatin1("/apps/weather/%1.img").arg(index), convertImageToMsol(img)); + } } diff --git a/saltoqd/weathermanager.h b/saltoqd/weathermanager.h index 522f797..cc36c41 100644 --- a/saltoqd/weathermanager.h +++ b/saltoqd/weathermanager.h @@ -1,6 +1,8 @@ #ifndef WEATHERMANAGER_H #define WEATHERMANAGER_H +#include +#include #include "toqmanager.h" class WeatherManager : public QObject @@ -9,12 +11,18 @@ class WeatherManager : public QObject public: explicit WeatherManager(FmsManager *fms, ToqManager *toq); +private: + QImage constructImage(const QJsonObject &obj); + private slots: - void handleToqConnected(); + void doRefresh(); private: ToqManager *_toq; FmsManager *_fms; + QString _file; + QFileSystemWatcher *_watcher; + QTimer *_refreshTimer; }; #endif // WEATHERMANAGER_H -- cgit v1.2.3