Commit 824ba007 authored by Wescoeur's avatar Wescoeur

feat(App): svg images supports color override

parent c19b1956
......@@ -5,7 +5,7 @@
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="settings_call_selected" stroke="#FE5E00" stroke-width="1.5">
<g id="settings_call_selected" class="color-i-stroke" stroke="#FE5E00" stroke-width="1.5">
<path d="M4.55461126,14.3889991 L4.61101441,14.4450242 C7.3002852,17.1350119 12.0969113,18.7974809 15.4512283,17.6111264 L17.995659,14.2747867 L14.5299113,10.8085083 L11.3593468,13.4904363 L8.46175774,10.5924679 L8.4061407,10.5364429 L5.50894471,7.63847454 L8.18956832,4.46588524 L4.7251964,1 L1.38876333,3.54530555 C0.202724956,6.90169626 1.8647509,11.6984217 4.55461126,14.3889991 Z" id="call_icon"></path>
</g>
</g>
......
......@@ -106,9 +106,7 @@ App::~App () {
// -----------------------------------------------------------------------------
inline QQuickWindow *createSubWindow (App *app, const char *path) {
QQmlEngine *engine = app->getEngine();
inline QQuickWindow *createSubWindow (QQmlApplicationEngine *engine, const char *path) {
QQmlComponent component(engine, QUrl(path));
if (component.isError()) {
qWarning() << component.errors();
......@@ -117,16 +115,16 @@ inline QQuickWindow *createSubWindow (App *app, const char *path) {
QObject *object = component.create();
QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
object->setParent(app->getEngine());
object->setParent(engine);
return qobject_cast<QQuickWindow *>(object);
}
// -----------------------------------------------------------------------------
inline void activeSplashScreen (App *app) {
inline void activeSplashScreen (QQmlApplicationEngine *engine) {
qInfo() << QStringLiteral("Open splash screen...");
QQuickWindow *splashScreen = ::createSubWindow(app, QML_VIEW_SPLASH_SCREEN);
QQuickWindow *splashScreen = ::createSubWindow(engine, QML_VIEW_SPLASH_SCREEN);
QObject::connect(CoreManager::getInstance()->getHandlers().get(), &CoreHandlers::coreStarted, splashScreen, [splashScreen] {
splashScreen->close();
splashScreen->deleteLater();
......@@ -176,17 +174,20 @@ void App::initContentApp () {
mEngine->addImageProvider(ImageProvider::PROVIDER_ID, new ImageProvider());
mEngine->addImageProvider(ThumbnailProvider::PROVIDER_ID, new ThumbnailProvider());
mColors = new Colors(this);
registerTypes();
registerSharedTypes();
registerToolTypes();
registerSharedToolTypes();
// Enable notifications.
createNotifier();
mNotifier = new Notifier(mEngine);
// Load splashscreen.
bool selfTest = mParser->isSet("self-test");
if (!selfTest)
::activeSplashScreen(this);
::activeSplashScreen(mEngine);
// Set a self test limit.
else
QTimer::singleShot(SELF_TEST_DELAY, this, [] {
......@@ -224,7 +225,7 @@ void App::executeCommand (const QString &command) {
QQuickWindow *App::getCallsWindow () {
if (!mCallsWindow)
mCallsWindow = ::createSubWindow(this, QML_VIEW_CALLS_WINDOW);
mCallsWindow = ::createSubWindow(mEngine, QML_VIEW_CALLS_WINDOW);
return mCallsWindow;
}
......@@ -237,7 +238,7 @@ QQuickWindow *App::getMainWindow () const {
QQuickWindow *App::getSettingsWindow () {
if (!mSettingsWindow) {
mSettingsWindow = ::createSubWindow(this, QML_VIEW_SETTINGS_WINDOW);
mSettingsWindow = ::createSubWindow(mEngine, QML_VIEW_SETTINGS_WINDOW);
QObject::connect(mSettingsWindow, &QWindow::visibilityChanged, this, [](QWindow::Visibility visibility) {
if (visibility == QWindow::Hidden) {
qInfo() << QStringLiteral("Update nat policy.");
......@@ -338,6 +339,15 @@ void registerToolType (const char *name) {
});
}
#define registerSharedToolType(TYPE, NAME, METHOD) qmlRegisterSingletonType<TYPE>( \
NAME, 1, 0, NAME, \
[](QQmlEngine *, QJSEngine *) -> QObject *{ \
QObject *object = METHOD(); \
QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership); \
return object; \
} \
)
void App::registerTypes () {
qInfo() << QStringLiteral("Registering types...");
......@@ -387,12 +397,18 @@ void App::registerToolTypes () {
qInfo() << QStringLiteral("Registering tool types...");
registerToolType<Clipboard>("Clipboard");
registerToolType<Colors>("Colors");
registerToolType<TextToSpeech>("TextToSpeech");
registerToolType<Units>("Units");
}
void App::registerSharedToolTypes () {
qInfo() << QStringLiteral("Registering shared tool types...");
registerSharedToolType(Colors, "Colors", App::getInstance()->getColors);
}
#undef registerUncreatableType
#undef registerSharedToolType
#undef registerSharedSingletonType
// -----------------------------------------------------------------------------
......@@ -436,13 +452,6 @@ void App::setTrayIcon () {
// -----------------------------------------------------------------------------
void App::createNotifier () {
if (!mNotifier)
mNotifier = new Notifier(this);
}
// -----------------------------------------------------------------------------
void App::initLocale () {
// Try to use preferred locale.
QString locale;
......
......@@ -27,6 +27,7 @@
#include <QQuickWindow>
#include "../components/notifier/Notifier.hpp"
#include "../components/other/colors/Colors.hpp"
#include "../externals/single-application/SingleApplication.hpp"
#define APP_CODE_RESTART 1000
......@@ -63,6 +64,10 @@ public:
return mNotifier;
}
Colors *getColors () const {
return mColors;
}
QQuickWindow *getMainWindow () const;
bool hasFocus () const;
......@@ -92,6 +97,7 @@ private:
void registerTypes ();
void registerSharedTypes ();
void registerToolTypes ();
void registerSharedToolTypes ();
void setTrayIcon ();
void createNotifier ();
......@@ -128,6 +134,8 @@ private:
QQuickWindow *mCallsWindow = nullptr;
QQuickWindow *mSettingsWindow = nullptr;
Colors *mColors = nullptr;
Cli *mCli = nullptr;
};
......
......@@ -28,6 +28,8 @@
#include <QXmlStreamReader>
#include <QtDebug>
#include "../App.hpp"
#include "ImageProvider.hpp"
// Max image size in bytes. (100Kb)
......@@ -35,28 +37,73 @@
// =============================================================================
const QString ImageProvider::PROVIDER_ID = "internal";
static QByteArray buildByteArrayAttribute (const QByteArray &name, const QByteArray &value) {
QByteArray attribute = name;
attribute.append("=\"");
attribute.append(value);
attribute.append("\" ");
return attribute;
}
ImageProvider::ImageProvider () : QQuickImageProvider(
QQmlImageProviderBase::Image,
QQmlImageProviderBase::ForceAsynchronousImageLoading
) {}
static QByteArray fillFillAndStroke (QXmlStreamAttributes &readerAttributes, bool &fill, bool &stroke, const Colors &colors) {
static QRegExp regex("^color-([^-]+)-(fill|stroke)$");
// -----------------------------------------------------------------------------
static QByteArray parseAttributes (QXmlStreamReader &reader) {
QByteArray attributes;
for (const auto &attribute : reader.attributes()) {
const QByteArray prefix = attribute.prefix().toLatin1();
QByteArray value = readerAttributes.value("class").toLatin1();
if (!value.length())
return attributes;
for (const auto &subValue : value.split(' ')) {
regex.indexIn(subValue.trimmed());
const QStringList list = regex.capturedTexts();
if (list.length() != 3)
continue;
const QString colorName = list[1];
QVariant colorValue = colors.property(colorName.toStdString().c_str());
if (!colorValue.isValid()) {
qWarning() << QStringLiteral("Color name `%1` does not exist.").arg(colorName);
continue;
}
QByteArray property = list[2].toLatin1();
if (property == QStringLiteral("fill"))
fill = true;
else
stroke = true;
attributes.append(
buildByteArrayAttribute(
property,
colorValue.value<QColor>().name().toLatin1()
)
);
}
return attributes;
}
static QByteArray parseAttributes (QXmlStreamReader &reader, const Colors &colors) {
QXmlStreamAttributes readerAttributes = reader.attributes();
bool fill = false, stroke = false;
QByteArray attributes = fillFillAndStroke(readerAttributes, fill, stroke, colors);
for (const auto &attribute : readerAttributes) {
QByteArray name = attribute.name().toLatin1();
if (fill && name == QStringLiteral("fill"))
continue;
if (stroke && name == QStringLiteral("stroke"))
continue;
QByteArray prefix = attribute.prefix().toLatin1();
QByteArray value = attribute.value().toLatin1();
if (prefix.length() > 0) {
attributes.append(prefix);
attributes.append(":");
}
attributes.append(attribute.name().toLatin1());
attributes.append("=\"");
attributes.append(attribute.value().toLatin1());
attributes.append("\" ");
attributes.append(buildByteArrayAttribute(name, value));
}
return attributes;
......@@ -65,7 +112,7 @@ static QByteArray parseAttributes (QXmlStreamReader &reader) {
static QByteArray parseDeclarations (QXmlStreamReader &reader) {
QByteArray declarations;
for (const auto &declaration : reader.namespaceDeclarations()) {
const QByteArray prefix = declaration.prefix().toLatin1();
QByteArray prefix = declaration.prefix().toLatin1();
if (prefix.length() > 0) {
declarations.append("xmlns:");
declarations.append(prefix);
......@@ -89,11 +136,11 @@ static QByteArray parseStartDocument (QXmlStreamReader &reader) {
return startDocument;
}
static QByteArray parseStartElement (QXmlStreamReader &reader) {
static QByteArray parseStartElement (QXmlStreamReader &reader, const Colors &colors) {
QByteArray startElement = "<";
startElement.append(reader.name().toLatin1());
startElement.append(" ");
startElement.append(parseAttributes(reader));
startElement.append(parseAttributes(reader, colors));
startElement.append(" ");
startElement.append(parseDeclarations(reader));
startElement.append(">");
......@@ -110,6 +157,8 @@ static QByteArray parseEndElement (QXmlStreamReader &reader) {
// -----------------------------------------------------------------------------
static QByteArray computeContent (QFile &file) {
const Colors *colors = App::getInstance()->getColors();
QByteArray content;
QXmlStreamReader reader(&file);
while (!reader.atEnd())
......@@ -127,7 +176,7 @@ static QByteArray computeContent (QFile &file) {
break;
case QXmlStreamReader::StartElement:
content.append(parseStartElement(reader));
content.append(parseStartElement(reader, *colors));
break;
case QXmlStreamReader::EndElement:
......@@ -148,6 +197,15 @@ static QByteArray computeContent (QFile &file) {
// -----------------------------------------------------------------------------
const QString ImageProvider::PROVIDER_ID = "internal";
ImageProvider::ImageProvider () : QQuickImageProvider(
QQmlImageProviderBase::Image,
QQmlImageProviderBase::ForceAsynchronousImageLoading
) {}
// -----------------------------------------------------------------------------
QImage ImageProvider::requestImage (const QString &id, QSize *, const QSize &) {
const QString path = QStringLiteral(":/assets/images/%1").arg(id);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment