Commit f5d91310 authored by Chupligin Sergey's avatar Chupligin Sergey

[Theme] remove theme helper

parent 729fd844
How to use the components generator
1. Have python 2 installed (the script don't work with Python 3 yet)
2. Add the components in "components.json"
3. call "./themehelper.py components.json"
4. copy all the generated files to the style folder in src
5. qmlRegisterUncreatableType the new created components in qquicknemostyleextensionplugin.cpp and
adds them in the style.pro file
6. update theme files if needed
You can also run ./generate.sh in the tools folder instead of doing 3 and 4.
#!/usr/bin/python
# Copyright (C) 2013 Lucien Xu. <sfietkonstantin@free.fr>
#
# You may use this file under the terms of the BSD license as follows:
#
# "Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Nemo Mobile nor the names of its contributors
# may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
import json
license = """/*
* Copyright (C) 2013 Lucien Xu <sfietkonstantin@free.fr>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
// This class is autogenerated using themehelper.py
// Any modification done in this file will be overridden
"""
# Used by formatting functions
basicTypes = ["int", "float", "double"]
# Formatting functions
def _getType(property):
if "type" in property:
return property["type"]
if "object" in property:
return "NemoTheme" + _getUpper(property["object"]) + " *"
return None
def _getArgumentType(property):
if "type" in property:
type = property["type"]
if type not in basicTypes:
return "const " + type + " &"
return type + " "
if "object" in property:
return "NemoTheme" + _getUpper(property["object"]) + " *"
return None
def _getUpper(name):
return name[0].upper() + name[1:]
# Generates some basic entries
# (includes, Q_PROPERTY macro, getter or setters etc)
def _getInclude(property):
if "type" in property:
type = property["type"]
if type in basicTypes:
return None
if type in ["QString", "QVariant", "QUrl", "QVariantMap", "QDateTime"]:
return "<QtCore/" + type + ">"
if type in ["QColor"]:
return "<QtGui/" + type + ">"
if "object" in property:
return "\"nemotheme" + property["object"].lower() + ".h\""
return None
def _getProperty(property):
propertyName = property["name"]
header = " Q_PROPERTY(" + _getType(property) + " " + propertyName
header += " READ " + propertyName
if "type" in property:
return header + " NOTIFY " + propertyName + "Changed)\n"
if "object" in property:
return header + " CONSTANT)\n"
def _getGetterSetter(property):
propertyName = property["name"]
header = " " + _getType(property) + " " + propertyName + "() const;\n"
if "type" in property:
header += " void set" + _getUpper(propertyName)
header += "(" + _getArgumentType(property) + propertyName + ");\n"
if "default" in property:
header += " void set" + _getUpper(propertyName) + "Default"
header += "();\n"
return header
def _getGetterSetterImpl(name, property):
propertyName = property["name"]
source = _getType(property) + " " + name + "::" + propertyName + "() const\n"
source += "{\n"
source += " return m_" + propertyName + ";\n"
source += "}\n"
source += "\n"
if "type" in property:
source += "void " + name + "::set" + _getUpper(propertyName)
source += "(" + _getArgumentType(property) + propertyName + ")\n"
source += "{\n"
source += " if (m_" + propertyName + " != " + propertyName + ") {\n"
source += " m_" + propertyName + " = " + propertyName + ";\n"
source += " emit " + propertyName + "Changed();\n"
source += " }\n"
source += "}\n"
source += "\n"
if "default" in property:
default = str(property["default"])
if isinstance(property["default"], str) or isinstance(property["default"], unicode):
default = "\"" + default + "\""
source += "void " + name + "::set" + _getUpper(propertyName) + "Default"
source += "()\n"
source += "{\n"
source += " if (m_" + propertyName + " != " + default + ") {\n"
source += " m_" + propertyName + " = " + default + ";\n"
source += " emit " + propertyName + "Changed();\n"
source += " }\n"
source += "}\n"
source += "\n"
return source
def _getSignal(property):
if "object" in property:
return ""
return " void " + property["name"] + "Changed();\n"
def _getLoadFromFile(name, data):
# Write helper methods that are used to parse theme file
source = """
static inline QJsonValue jsonValue(const QJsonObject &object, const QString &key,
const QString &objectName = QString())
{
if (!object.contains(key)) {
if (objectName.isEmpty()) {
qWarning() << "W" << "Root JSON object does not have value" << key;
} else {
qWarning() << "W" << "JSON Object" << objectName << "does not have value" << key;
}
return QJsonValue();
}
return object.value(key);
}
static inline QString jsonToString(const QJsonValue &value,
const QMap<QString, QJsonValue> &defines)
{
QString valueString = value.toString();
if (defines.contains(valueString)) {
return defines.value(valueString).toString();
}
return value.toString();
}
static inline QColor jsonToColor(const QJsonValue &value,
const QMap<QString, QJsonValue> &defines)
{
QString color = value.toString();
if (defines.contains(color)) {
color = defines.value(color).toString();
}
// We need to skip the warning caused by a null value,
// so we check if the color is not empty
if (!QColor::isValidColor(color) && !color.isEmpty()) {
qWarning() << "W" << color << "is not a valid color";
return QColor();
}
return QColor(color);
}
static inline int jsonToInt(const QJsonValue &value,
const QMap<QString, QJsonValue> &defines)
{
QJsonValue trueValue = value;
if (value.isString()) {
QString valueString = value.toString();
if (defines.contains(valueString)) {
trueValue = defines.value(valueString);
}
}
double doubleValue = trueValue.toDouble();
return (int) doubleValue;
}
static inline int jsonToDouble(const QJsonValue &value,
const QMap<QString, QJsonValue> &defines)
{
QJsonValue trueValue = value;
if (value.isString()) {
QString valueString = value.toString();
if (defines.contains(valueString)) {
trueValue = defines.value(valueString);
}
}
return trueValue.toDouble();
}
"""
# Generate the method that loads from file
source += "void " + name + "::loadFromFile(const QString &fileName)\n"
source += """{
QDir dir (THEME_DIR);
if (!dir.exists(fileName)) {
qWarning() << "E" << Q_FUNC_INFO << "Theme file" << fileName << "does not exists.";
return;
}
QFile themeFile (dir.absoluteFilePath(fileName));
if (!themeFile.open(QIODevice::ReadOnly)) {
qWarning() << "E" << Q_FUNC_INFO << "Theme file" << fileName << "could not be read.";
return;
}
QJsonParseError error;
QJsonDocument themeDocument = QJsonDocument::fromJson(themeFile.readAll(), &error);
themeFile.close();
if (error.error != QJsonParseError::NoError) {
qWarning() << "E" << Q_FUNC_INFO << "Cannot parse theme file:" << error.errorString();
return;
}
// Fetch all the defines
QMap<QString, QJsonValue> defines;
if (!themeDocument.isObject()) {
qWarning() << "E" << Q_FUNC_INFO << "Theme file has an invalid format";
return;
}
QJsonObject themeObject = themeDocument.object();
if (themeObject.contains(THEME_DEFINES_KEY)) {
QJsonValue definesJson = themeObject.value(THEME_DEFINES_KEY);
if (!definesJson.isObject()) {
qWarning() << "W" << Q_FUNC_INFO << "\\"defines\\" is not defined as an object";
} else {
QJsonObject definesObject = definesJson.toObject();
foreach (const QString key, definesObject.keys()) {
defines.insert(key, definesObject.value(key));
}
}
} else {
qWarning() << "W" << Q_FUNC_INFO
<< "Theme file does not contain a \\"defines\\" object. "\\
"Please add an empty \\"defines\\" object instead";
}
// Set the global values (name, description etc.)
setName(jsonValue(themeObject, THEME_NAME_KEY).toString());
setDescription(jsonValue(themeObject, THEME_DESCRIPTION_KEY).toString());
// Parse the defined objects
QJsonObject styles = jsonValue(themeObject, THEME_STYLES_KEY).toObject();
if (styles.isEmpty()) {
return;
}
"""
# We create a map of components that can be used
# to quickly retrieve a component based on the name
components = {}
for component in data["components"]:
components[component["name"]] = component["properties"]
for property in data["properties"]:
if "object" in property:
name = property["name"]
type = property["object"]
source += _getSetObject("styles", "m_" + name, name, components[type], components)
source += "}\n"
return source
def _getCasted(property, jsonObject, name, cppObject):
type = property["type"]
castedValue = None
value = "jsonValue(" + jsonObject + _getUpper(name) + ", \""
value += property["name"] + "\", \"" + name + "\")"
if "default" in property:
value = jsonObject + _getUpper(name) + ".value(\"" + property["name"] + "\")"
if type == "QString":
castedValue = "jsonToString(" + value + ", defines)"
elif type == "QColor":
castedValue = "jsonToColor(" + value + ", defines)"
elif type == "int":
castedValue = "jsonToInt(" + value + ", defines)"
elif type == "double":
castedValue = "jsonToDouble(" + value + ", defines)"
else:
print "\"" + type + "\" is not a known type. TODO !"
if castedValue == None:
return ""
if "default" in property:
data = " if (" + jsonObject + _getUpper(name) + ".contains(\""
data += property["name"] + "\")) {\n"
data += " " + cppObject + "->set" + _getUpper(property["name"])
data += "(" + castedValue + ");\n"
data += " } else {\n"
data += " " + cppObject + "->set" + _getUpper(property["name"]) + "Default();\n"
data += " }\n"
return data
else:
data = " " + cppObject + "->set" + _getUpper(property["name"])
data += "(" + castedValue + ");\n"
return data
# This method is used to generate the tree of components and set calls
# it will start with a root component property, try to load all properties
# from theme file (and ignore those already defined), and continue
# with children components.
def _getSetObject(jsonObject, cppObject, name, properties, components):
data = " // Setting properties for " + name + "\n"
data += " QJsonObject " + jsonObject + _getUpper(name) + " = " + jsonObject
data += ".value(\"" + name + "\").toObject();\n"
for property in properties:
if "object" in property:
type = property["object"]
data += _getSetObject(jsonObject + _getUpper(name),
cppObject + "->" + property["name"] + "()",
property["name"], components[type], components)
if "type" in property:
data += _getCasted(property, jsonObject, name, cppObject)
return data
def generate(data, writeThemeObject = False):
# If we have a name, we are generating a component,
# otherwise, we are generating the global theme object
if "name" in data:
name = "NemoTheme" + _getUpper(data["name"])
else:
name = "NemoTheme"
properties = []
if writeThemeObject:
properties.append({"name": "name", "type": "QString"})
properties.append({"name": "description", "type": "QString"})
for property in data["properties"]:
properties.append(property)
header = license
header += "#ifndef " + name.upper() + "_H\n"
header += "#define " + name.upper() + "_H\n"
header += "\n"
header += "#include <QtCore/QObject>\n"
includes = []
for property in properties:
include = _getInclude(property)
if include != None and not include in includes:
includes.append(include)
for include in includes:
header += "#include " + include + "\n"
header += "\n"
header += "class " + name + ": public QObject\n"
header += "{\n"
header += " Q_OBJECT\n"
# Generate properties
for property in properties:
header += _getProperty(property)
if writeThemeObject:
header += " Q_PROPERTY(QString fontFamily READ fontFamily CONSTANT)\n"
header += "public:\n"
# Constructor
header += " explicit " + name + "(QObject *parent = 0);\n"
# Generates getters and setters
for property in properties:
header += _getGetterSetter(property)
if writeThemeObject:
header += " QString fontFamily() const;\n"
header += "public Q_SLOTS:\n"
header += " void loadFromFile(const QString &fileName);\n"
header += "Q_SIGNALS:\n"
# Generate signals
for property in properties:
header += _getSignal(property)
header += "private:\n"
# Generate private members
for property in properties:
header += " " + _getType(property) + " m_" + property["name"] + ";\n"
if writeThemeObject:
header += " QString m_fontFamily;\n"
header += "};\n"
header += "\n"
header += "#endif //" + name.upper() + "_H\n"
try:
f = open(name.lower() + ".h", "w")
f.write(header)
f.close()
except:
print "Failed to write to " + name.lower() + ".h"
return
source = license
source += "#include \"" + name.lower() + ".h\"\n"
if writeThemeObject:
# Adds the additional includes
source += "#include <QtCore/QDebug>\n#include <QtCore/QDir>\n#include <QtCore/QFile>\n"
source += "#include <QtCore/QJsonDocument>\n#include <QtCore/QJsonArray>\n"
source += "#include <QtCore/QJsonObject>\n#include <QtCore/QJsonValue>\n"
source += "#include <QtGui/QFontDatabase>\n"
source += "\n"
if writeThemeObject:
# Adds the additional defines
source += "static const char *GLACIER_THEME = \"glacier.json\";\n"
source += "static const char *THEME_NAME_KEY = \"name\";\n"
source += "static const char *THEME_DESCRIPTION_KEY = \"description\";\n"
source += "static const char *THEME_DEFINES_KEY = \"defines\";\n"
source += "static const char *THEME_STYLES_KEY = \"styles\";\n"
source += "\n"
# Generate constructor
source += name + "::" + name + "(QObject *parent)\n"
source += " : QObject(parent)\n"
# Init members if needed
for property in properties:
if "type" in property:
if "default" in property:
default = str(property["default"])
if isinstance(property["default"], str) or isinstance(property["default"], unicode):
default = "\"" + default + "\""
source += " , m_" + property["name"] + "(" + default + ")\n"
else:
if property["type"] in basicTypes:
if property["type"] == "int":
source += " , m_" + property["name"] + "(0)\n"
else:
source += " , m_" + property["name"] + "(0.)\n"
elif "object" in property:
source += " , m_" + property["name"] + "(new NemoTheme" + _getUpper(property["object"])
source += "(this))\n"
source += "{\n"
if writeThemeObject:
source += """ loadFromFile(GLACIER_THEME);
int id = QFontDatabase::addApplicationFont(\"""" + data["font"] + """\");
QStringList families = QFontDatabase::applicationFontFamilies(id);
if (families.isEmpty()) {
qWarning() << "W" << "Failed to load font" << QString(\"""" + data["font"] + """\");
return;
}
m_fontFamily = families.first();
"""
source += "}\n"
source += "\n"
# Generate getters and setters
for property in properties:
source += _getGetterSetterImpl(name, property)
source = source[:-1]
if writeThemeObject:
source += "\n"
source += "QString " + name + "::fontFamily() const\n"
source += "{\n"
source += " return m_fontFamily;\n"
source += "}\n"
source += _getLoadFromFile(name, data)
try:
f = open(name.lower() + ".cpp", "w")
f.write(source)
f.close()
except:
print "Failed to write to " + name.lower() + ".cpp"
return
{
"components": [
{
"name": "Button",
"properties": [
{
"name": "background",
"type": "QColor"
},
{
"name": "text",
"object": "ButtonText"
},
{
"name": "pressedGradient",
"object": "ButtonPressedGradient"
}
]
},
{
"name": "Groove",
"properties": [
{
"name": "background",
"type": "QColor"
},
{
"name": "foreground",
"type": "QColor"
}
]
},
{
"name": "TextField",
"properties": [
{
"name": "selectedTextColor",
"type": "QColor"
},
{
"name": "selectionColor",
"type": "QColor"
},
{
"name": "pointSize",
"type": "int",
"default": 24
},
{
"name": "font",
"type": "QString",
"default": "Open Sans"
}
]
},
{
"name": "ToolBar",
"properties": [
{
"name": "background",
"type": "QColor"
}
]
},
{
"name": "Window",
"properties": [
{
"name": "background",
"type": "QColor"
}
]
},
{
"name": "Page",
"properties": [
{
"name": "background",
"type": "QColor"
}
]
},
{
"name": "ButtonPressedGradient",
"properties": [
{
"name": "centerColor",
"type": "QColor"
},
{
"name": "edgeColor",
"type": "QColor"
},
{
"name": "width",
"type": "int",
"default": 240
},
{
"name": "height",
"type": "int",
"default": 240
},
{
"name": "center",
"type": "double",
"default": 0.29
},
{
"name": "edge",
"type": "double",
"default": 0.5
}
]
},
{
"name": "ButtonText",
"properties": [
{
"name": "color",
"type": "QColor"
},
{
"name": "font",
"object": "Font"
}
]
},
{
"name": "Font",
"properties": [
{
"name": "pointSize",
"type": "int",
"default": 24
},
{
"name": "weight",
"type": "int",
"default": 25
}
]
},
{
"name": "Spinner",
"properties": [
{
"name": "radius",
"type": "int",
"default": 32
},
{
"name": "primaryColor",
"type": "QColor"
},
{
"name": "secondaryColor",
"type": "QColor"
},
{
"name": "horizontalSpacing",
"type": "int",
"default": 15
},
{
"name": "verticalSpacing",
"type": "int",
"default": 15
},
{
"name": "initialStateDuration",
"type": "int",
"default": 1500
},
{
"name": "transitionDuration",
"type": "int",
"default": 500
}
]
},
{
"name": "Label",
"properties": [
{
"name":"color",
"type":"QColor"
},
{
"name": "pointSize",
"type": "int",
"default": 24
}
]
},
{
"name": "Checkbox",
"properties": [
{
"name": "back1",
"type": "QColor"
},
{
"name": "back2",
"type": "QColor"
}
]
},
{
"name": "PageStack",
"properties": [
{
"name": "transitionDuration",
"type": "int",
"default": 500
}
]
},
{
"name": "ButtonRow",
"properties": [
{
"name": "background",
"type": "QColor"
},
{
"name": "buttonColor",
"type": "QColor"
}
]
},
{
"name": "Header",
"properties": [
{
"name": "background",
"type": "QColor"
},
{
"name": "dimmer",
"object": "HeaderDimmer"
}
]
},
{
"name": "HeaderDimmer",
"properties": [
{
"name": "startColor",
"type": "QColor"
},
{
"name": "endColor",
"type": "QColor"
},
{
"name": "height",
"type": "int",
"default": 16
},
{
"name": "startPosition",
"type": "double",
"default": 0
},
{
"name": "endPosition",
"type": "double",
"default": 1.0
}
]
}
],
"properties": [
{
"name": "button",
"object": "Button"
},
{
"name": "primaryButton",
"object": "Button"
},
{
"name": "groove",
"object": "Groove"
},
{
"name": "textField",
"object": "TextField"
},
{
"name": "toolBar",
"object": "ToolBar"
},
{
"name": "window",
"object": "Window"
},
{
"name": "page",
"object": "Page"
},
{
"name": "pageStack",
"object": "PageStack"
},
{
"name": "spinner",
"object": "Spinner"
},
{
"name": "label",
"object": "Label"
},
{
"name": "checkbox",
"object": "Checkbox"
},
{
"name": "buttonRow",
"object": "ButtonRow"
},
{
"name": "header",
"object": "Header"
}
],
"font": "/usr/share/fonts/google-opensans/OpenSans-Regular.ttf"
}
# Copyright (C) 2013 Jolla Ltd. <chris.adams@jollamobile.com>
#
# You may use this file under the terms of the BSD license as follows:
#
# "Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Nemo Mobile nor the names of its contributors
# may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
def includeGuard(name):
return name.replace("_", "").upper() + "_H"
def upperCamelCase(name):
camelCased = camelCase(split(name))
return camelCased[0].upper() + camelCased[1:]
def camelCase(name):
splitted = split(name)
newSplitted = []
for splittedWord in splitted:
splittedWord = splittedWord.lower()
splittedWord = splittedWord[0].upper() + splittedWord[1:]
newSplitted.append(splittedWord)
camelCase = "".join(newSplitted)
camelCase = camelCase[0].lower() + camelCase[1:]
return camelCase
def split(name):
return name.split("_")
def addSpaces(string, size):
spacesToAdd = max(size - len(string), 0)
return string + (" " * spacesToAdd)
#!/bin/sh
./themehelper.py components.json
mv *.h ../../src/styles/autogenerated/
mv *.cpp ../../src/styles/autogenerated/
#!/usr/bin/python
# Copyright (C) 2013 Lucien Xu. <sfietkonstantin@free.fr>
#
# You may use this file under the terms of the BSD license as follows:
#
# "Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Nemo Mobile nor the names of its contributors
# may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
# Generates components from a JSON description file
#
# This script generates components from a JSON description file.
# The JSON description file have the following organization
# {
# "components": [
# list of components
# ],
# "properties": [ list of properties ],
# "font": "/path/to/some_font.ttf"
# }
#
# The "components" is the list of components that should be generated.
# Each component have a "name", and a list of "properties". A property
# is a list of objects defined this way:
# {
# "name": "someName",
# "type": "some_type",
# ["default": some_value]
# }
# or
# {
# "name": "someName",
# "object": "some_object"
# }
#
# The first variation defines a simple property. "type" field should
# contain the name of either a basic type, like int, or float, or
# a Qt object, like QColor and QString. The optional "default" field
# contains a default value that is embedded in the component.
# Properties with default values don't need to be defined in the
# theme file.
#
# The second variation contains an object definition. Usually, an
# object defines a complex type, that needs several basic types to be
# defined, like a gradient, that needs 2 colors, and maybe a radius.
#
# The "properties" field of the root object behave the same, and
# describes the properties that the Theme object have. Note that
# "name" and "description" are automatically provided by the
# script, and don't need to be defined in the properties.
#
# The last field is the font. It provides the default font that
# is available from the Theme object.
import json
import classgenerator
import argparse
def generate(descriptionFile):
# First, we try to open JSON description file
try:
f = open(descriptionFile)
except:
print "Failed to open " + descriptionFile
return
data = json.load(f)
classgenerator.generate(data, True)
for componentData in data["components"]:
classgenerator.generate(componentData)
# Main
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Theme helper')
parser.add_argument('description_file', metavar='description_file', type=str,
help="""Input description file (JSON)""")
args = parser.parse_args()
description_file = args.description_file
generate(description_file)
\ No newline at end of file
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