diff options
| author | Javier <dev.git@javispedro.com> | 2014-12-14 03:26:46 +0100 |
|---|---|---|
| committer | Javier <dev.git@javispedro.com> | 2014-12-14 03:26:46 +0100 |
| commit | f40514fe681f5163deb5f579140ef4f7ac77f5a8 (patch) | |
| tree | c3edddde3cbc98a797d5a1a7b745c2c5d3b99eba /daemon/appmanager.cpp | |
| parent | df30ca18eebd2dfec03c589b607d45a5891cf2b2 (diff) | |
add icons to the slots managament UI
Diffstat (limited to 'daemon/appmanager.cpp')
| -rw-r--r-- | daemon/appmanager.cpp | 142 |
1 files changed, 132 insertions, 10 deletions
diff --git a/daemon/appmanager.cpp b/daemon/appmanager.cpp index 10f2e3e..8745160 100644 --- a/daemon/appmanager.cpp +++ b/daemon/appmanager.cpp @@ -4,6 +4,17 @@ #include <QJsonArray> #include <QDir> #include "appmanager.h" +#include "unpacker.h" +#include "stm32crc.h" + +namespace { +struct ResourceEntry { + int index; + quint32 offset; + quint32 length; + quint32 crc; +}; +} AppManager::AppManager(QObject *parent) : QObject(parent), @@ -116,18 +127,55 @@ void AppManager::scanApp(const QString &path) info.setWatchface(watchapp["watchface"].toBool()); info.setJSKit(appDir.exists("pebble-js-app.js")); - const QJsonArray capabilities = root["capabilities"].toArray(); - AppInfo::Capabilities caps = 0; - for (QJsonArray::const_iterator it = capabilities.constBegin(); it != capabilities.constEnd(); ++it) { - QString cap = (*it).toString(); - if (cap == "location") caps |= AppInfo::Location; - if (cap == "configurable") caps |= AppInfo::Configurable; + if (root.contains("capabilities")) { + const QJsonArray capabilities = root["capabilities"].toArray(); + AppInfo::Capabilities caps = 0; + for (auto it = capabilities.constBegin(); it != capabilities.constEnd(); ++it) { + QString cap = (*it).toString(); + if (cap == "location") caps |= AppInfo::Location; + if (cap == "configurable") caps |= AppInfo::Configurable; + } + info.setCapabilities(caps); } - info.setCapabilities(caps); - const QJsonObject appkeys = root["appKeys"].toObject(); - for (QJsonObject::const_iterator it = appkeys.constBegin(); it != appkeys.constEnd(); ++it) { - info.addAppKey(it.key(), it.value().toInt()); + if (root.contains("appKeys")) { + const QJsonObject appkeys = root["appKeys"].toObject(); + for (auto it = appkeys.constBegin(); it != appkeys.constEnd(); ++it) { + info.addAppKey(it.key(), it.value().toInt()); + } + } + + if (root.contains("resources")) { + const QJsonObject resources = root["resources"].toObject(); + const QJsonArray media = resources["media"].toArray(); + int index = 0; + + for (auto it = media.constBegin(); it != media.constEnd(); ++it) { + const QJsonObject res = (*it).toObject(); + const QJsonValue menuIcon = res["menuIcon"]; + + bool is_menu_icon = false; + switch (menuIcon.type()) { + case QJsonValue::Bool: + is_menu_icon = menuIcon.toBool(); + break; + case QJsonValue::String: + is_menu_icon = !menuIcon.toString().isEmpty(); + break; + default: + break; + } + + if (is_menu_icon) { + QByteArray data = extractFromResourcePack(appDir.filePath("app_resources.pbpack"), index); + if (!data.isEmpty()) { + QImage icon = decodeResourceImage(data); + info.setMenuIcon(icon); + } + } + + index++; + } } info.setPath(path); @@ -143,3 +191,77 @@ void AppManager::scanApp(const QString &path) const char *type = info.isWatchface() ? "watchface" : "app"; logger()->debug() << "found installed" << type << info.shortName() << info.versionLabel() << "with uuid" << info.uuid().toString(); } + +QByteArray AppManager::extractFromResourcePack(const QString &file, int wanted_id) const +{ + QFile f(file); + if (!f.open(QIODevice::ReadOnly)) { + logger()->warn() << "cannot open resource file" << f.fileName(); + return QByteArray(); + } + + QByteArray data = f.readAll(); + Unpacker u(data); + + int num_files = u.readLE<quint32>(); + u.readLE<quint32>(); // crc for entire file + u.readLE<quint32>(); // timestamp + + logger()->debug() << "reading" << num_files << "resources from" << file; + + QList<ResourceEntry> table; + + for (int i = 0; i < num_files; i++) { + ResourceEntry e; + e.index = u.readLE<quint32>(); + e.offset = u.readLE<quint32>(); + e.length = u.readLE<quint32>(); + e.crc = u.readLE<quint32>(); + + if (u.bad()) { + logger()->warn() << "short read on resource file"; + return QByteArray(); + } + + table.append(e); + } + + if (wanted_id >= table.size()) { + logger()->warn() << "specified resource does not exist"; + return QByteArray(); + } + + const ResourceEntry &e = table[wanted_id]; + + int offset = 12 + 256 * 16 + e.offset; + + QByteArray res = data.mid(offset, e.length); + + Stm32Crc crc; + crc.addData(res); + + if (crc.result() != e.crc) { + logger()->warn() << "CRC failure in resource" << e.index << "on file" << file; + return QByteArray(); + } + + return res; +} + +QImage AppManager::decodeResourceImage(const QByteArray &data) const +{ + Unpacker u(data); + int scanline = u.readLE<quint16>(); + u.skip(sizeof(quint16) + sizeof(quint32)); + int width = u.readLE<quint16>(); + int height = u.readLE<quint16>(); + + QImage img(width, height, QImage::Format_MonoLSB); + const uchar *src = reinterpret_cast<const uchar *>(&data.constData()[12]); + for (int line = 0; line < height; ++line) { + memcpy(img.scanLine(line), src, qMin(scanline, img.bytesPerLine())); + src += scanline; + } + + return img; +} |
