aboutsummaryrefslogtreecommitdiffstats
path: root/builtin/qtcpp
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/qtcpp')
-rw-r--r--builtin/qtcpp/log.yaml18
-rwxr-xr-xbuiltin/qtcpp/qtcpp.py69
-rw-r--r--builtin/qtcpp/templates/abstractinterface.cpp53
-rw-r--r--builtin/qtcpp/templates/abstractinterface.h51
-rw-r--r--builtin/qtcpp/templates/generated.pri33
-rw-r--r--builtin/qtcpp/templates/interface.cpp35
-rw-r--r--builtin/qtcpp/templates/interface.h23
-rw-r--r--builtin/qtcpp/templates/module.cpp46
-rw-r--r--builtin/qtcpp/templates/module.h41
-rw-r--r--builtin/qtcpp/templates/plugin.cpp26
-rw-r--r--builtin/qtcpp/templates/plugin.h18
-rw-r--r--builtin/qtcpp/templates/plugin.pro47
-rw-r--r--builtin/qtcpp/templates/qmldir3
-rw-r--r--builtin/qtcpp/templates/struct.cpp21
-rw-r--r--builtin/qtcpp/templates/struct.h29
-rw-r--r--builtin/qtcpp/templates/structmodel.cpp106
-rw-r--r--builtin/qtcpp/templates/structmodel.h40
-rw-r--r--builtin/qtcpp/templates/variantmodel.cpp102
-rw-r--r--builtin/qtcpp/templates/variantmodel.h38
19 files changed, 799 insertions, 0 deletions
diff --git a/builtin/qtcpp/log.yaml b/builtin/qtcpp/log.yaml
new file mode 100644
index 0000000..21b5bba
--- /dev/null
+++ b/builtin/qtcpp/log.yaml
@@ -0,0 +1,18 @@
+version: 1
+formatters:
+ simple:
+ format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
+handlers:
+ console:
+ class: logging.StreamHandler
+ level: INFO
+ formatter: simple
+ stream: ext://sys.stdout
+loggers:
+ qface.generator:
+ level: WARN
+ handlers: [console]
+ propagate: no
+root:
+ level: DEBUG
+ handlers: [console]
diff --git a/builtin/qtcpp/qtcpp.py b/builtin/qtcpp/qtcpp.py
new file mode 100755
index 0000000..56882a7
--- /dev/null
+++ b/builtin/qtcpp/qtcpp.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+# Copyright (c) Pelagicore AB 2016
+
+import click
+import logging
+import logging.config
+import yaml
+from path import Path
+
+from qface.generator import FileSystem, Generator
+from qface.helper.qtcpp import Filters
+
+
+here = Path(__file__).dirname()
+
+logging.config.dictConfig(yaml.load(open(here / 'log.yaml')))
+
+log = logging.getLogger(__file__)
+
+
+def run(src, dst):
+ log.debug('run {0} {1}'.format(src, dst))
+ system = FileSystem.parse(src)
+ generator = Generator(searchpath=here / 'templates')
+ generator.register_filter('returnType', Filters.returnType)
+ generator.register_filter('parameterType', Filters.parameterType)
+ generator.register_filter('defaultValue', Filters.defaultValue)
+ ctx = {'dst': dst}
+ for module in system.modules:
+ log.debug('generate code for module %s', module)
+ ctx.update({'module': module})
+ dst = generator.apply('{{dst}}/{{module|lower|replace(".", "-")}}', ctx)
+ generator.destination = dst
+ generator.write('qmldir', 'qmldir', ctx, preserve=True)
+ generator.write('plugin.cpp', 'plugin.cpp', ctx, preserve=True)
+ generator.write('plugin.h', 'plugin.h', ctx, preserve=True)
+ generator.write('{{module|lower|replace(".", "-")}}.pro', 'plugin.pro', ctx, preserve=True)
+ generator.write('generated/generated.pri', 'generated.pri', ctx)
+ generator.write('generated/qml{{module.module_name|lower}}module.h', 'module.h', ctx)
+ generator.write('generated/qml{{module.module_name|lower}}module.cpp', 'module.cpp', ctx)
+ for interface in module.interfaces:
+ log.debug('generate code for interface %s', interface)
+ ctx.update({'interface': interface})
+ generator.write('qml{{interface|lower}}.h', 'interface.h', ctx, preserve=True)
+ generator.write('qml{{interface|lower}}.cpp', 'interface.cpp', ctx, preserve=True)
+ generator.write('generated/qmlabstract{{interface|lower}}.h', 'abstractinterface.h', ctx)
+ generator.write('generated/qmlabstract{{interface|lower}}.cpp', 'abstractinterface.cpp', ctx)
+ for struct in module.structs:
+ log.debug('generate code for struct %s', struct)
+ ctx.update({'struct': struct})
+ generator.write('generated/qml{{struct|lower}}.h', 'struct.h', ctx)
+ generator.write('generated/qml{{struct|lower}}.cpp', 'struct.cpp', ctx)
+ generator.write('generated/qml{{struct|lower}}model.h', 'structmodel.h', ctx)
+ generator.write('generated/qml{{struct|lower}}model.cpp', 'structmodel.cpp', ctx)
+ generator.write('generated/qmlvariantmodel.h', 'variantmodel.h', ctx)
+ generator.write('generated/qmlvariantmodel.cpp', 'variantmodel.cpp', ctx)
+
+
+@click.command()
+@click.argument('src', nargs=-1, type=click.Path(exists=True))
+@click.argument('dst', nargs=1, type=click.Path(exists=True))
+def app(src, dst):
+ """Takes several files or directories as src and generates the code
+ in the given dst directory."""
+ run(src, dst)
+
+
+if __name__ == '__main__':
+ app()
diff --git a/builtin/qtcpp/templates/abstractinterface.cpp b/builtin/qtcpp/templates/abstractinterface.cpp
new file mode 100644
index 0000000..e0ac7cc
--- /dev/null
+++ b/builtin/qtcpp/templates/abstractinterface.cpp
@@ -0,0 +1,53 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+{% set class = 'QmlAbstract{0}'.format(interface) %}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+
+#include "{{class|lower}}.h"
+
+#include <QtQml>
+
+{{interface.comment}}
+{{class}}::{{class}}(QObject *parent)
+ : QObject(parent)
+{% for property in interface.properties %}
+ , m_{{property}}({{property|defaultValue}})
+{% endfor %}
+{
+}
+
+{{class}}::~{{class}}()
+{
+}
+
+{% for property in interface.properties %}
+{% if not property.is_readonly %}
+void {{class}}::set{{property|upperfirst}}({{ property|parameterType }})
+{
+ if(m_{{property}} == {{property}}) {
+ return;
+ }
+ m_{{property}} = {{property}};
+ emit {{property}}Changed();
+}
+{% endif %}
+
+{{property|returnType}} {{class}}::{{property}}() const
+{
+ return m_{{property}};
+}
+{% endfor %}
+
+{%- for operation in interface.operations %}
+{{operation|returnType}} {{class}}::{{operation}}({{operation.parameters|map('parameterType')|join(', ')}})
+{
+ {% for parameter in operation.parameters %}
+ Q_UNUSED({{parameter.name}});
+ {% endfor %}
+ qWarning() << "{{class}}::{{operation}}(...) not implemented";
+ return {{operation|defaultValue}};
+}
+{% endfor %}
+
diff --git a/builtin/qtcpp/templates/abstractinterface.h b/builtin/qtcpp/templates/abstractinterface.h
new file mode 100644
index 0000000..d6921ca
--- /dev/null
+++ b/builtin/qtcpp/templates/abstractinterface.h
@@ -0,0 +1,51 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+{% set class = 'QmlAbstract{0}'.format(interface) %}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+
+#pragma once
+
+#include <QtCore>
+
+#include "qml{{module.module_name|lower}}module.h"
+
+class {{class}} : public QObject
+{
+ Q_OBJECT
+{% for property in interface.properties %}
+ Q_PROPERTY({{property|returnType}} {{property}} READ {{property}} NOTIFY {{property}}Changed)
+{% endfor %}
+
+public:
+ {{class}}(QObject *parent=0);
+ ~{{class}}();
+
+public Q_SLOTS:
+{% for operation in interface.operations %}
+ virtual {{operation|returnType}} {{operation}}({{operation.parameters|map('parameterType')|join(', ')}});
+{% endfor %}
+
+public:
+{% for property in interface.properties %}
+{% if not property.is_readonly %}
+ virtual void set{{property|upperfirst}}({{ property|parameterType }});
+{% endif %}
+{% endfor %}
+
+public:
+{% for property in interface.properties %}
+ virtual {{property|returnType}} {{property}}() const;
+{% endfor %}
+
+Q_SIGNALS:
+{% for property in interface.properties %}
+ void {{property}}Changed();
+{% endfor %}
+
+protected:
+{% for property in interface.properties %}
+ {{property|returnType}} m_{{property}};
+{% endfor %}
+};
diff --git a/builtin/qtcpp/templates/generated.pri b/builtin/qtcpp/templates/generated.pri
new file mode 100644
index 0000000..4baac95
--- /dev/null
+++ b/builtin/qtcpp/templates/generated.pri
@@ -0,0 +1,33 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+#############################################################################
+## This is an auto-generated file.
+## Do not edit! All changes made to it will be lost.
+#############################################################################
+
+QT += qml quick
+CONFIG += c++11
+
+HEADERS += \
+ $$PWD/qml{{module.module_name|lower}}module.h \
+{% for interface in module.interfaces %}
+ $$PWD/qmlabstract{{interface|lower}}.h \
+{% endfor %}
+ $$PWD/qmlvariantmodel.h \
+{% for struct in module.structs %}
+ $$PWD/qml{{struct|lower}}.h \
+ $$PWD/qml{{struct|lower}}model.h {% if not loop.last %}\{% endif %}
+{% endfor %}
+
+
+SOURCES += \
+ $$PWD/qml{{module.module_name|lower}}module.cpp \
+{% for interface in module.interfaces %}
+ $$PWD/qmlabstract{{interface|lower}}.cpp \
+{% endfor %}
+ $$PWD/qmlvariantmodel.cpp \
+{% for struct in module.structs %}
+ $$PWD/qml{{struct|lower}}.cpp \
+ $$PWD/qml{{struct|lower}}model.cpp {% if not loop.last %}\{% endif %}
+{% endfor %}
+
+
diff --git a/builtin/qtcpp/templates/interface.cpp b/builtin/qtcpp/templates/interface.cpp
new file mode 100644
index 0000000..abde3d7
--- /dev/null
+++ b/builtin/qtcpp/templates/interface.cpp
@@ -0,0 +1,35 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+{% set class = 'Qml{0}'.format(interface) %}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+
+#include "{{class|lower}}.h"
+
+#include <QtQml>
+
+QObject* {{class|lower}}_singletontype_provider(QQmlEngine*, QJSEngine*)
+{
+ return new {{class}}();
+}
+
+
+{{interface.comment}}
+{{class}}::{{class}}(QObject *parent)
+ : QmlAbstract{{interface}}(parent)
+{
+}
+
+{{class}}::~{{class}}()
+{
+}
+
+void {{class}}::registerQmlTypes(const QString& uri, int majorVersion, int minorVersion)
+{
+ {% if 'singleton' in interface.tags %}
+ qmlRegisterSingletonType<{{class}}>(uri.toLatin1(), majorVersion, minorVersion, "{{interface}}", {{class|lower}}_singletontype_provider);
+ {% else %}
+ qmlRegisterType<{{class}}>(uri.toLatin1(), majorVersion, minorVersion, "{{interface}}");
+ {% endif %}
+}
diff --git a/builtin/qtcpp/templates/interface.h b/builtin/qtcpp/templates/interface.h
new file mode 100644
index 0000000..8978be5
--- /dev/null
+++ b/builtin/qtcpp/templates/interface.h
@@ -0,0 +1,23 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+{% set class = 'Qml{0}'.format(interface) %}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+
+#pragma once
+
+#include <QtCore>
+
+#include "generated/qml{{module.module_name|lower}}module.h"
+#include "generated/qmlabstract{{interface|lower}}.h"
+
+class {{class}} : public QmlAbstract{{interface}}
+{
+ Q_OBJECT
+public:
+ {{class}}(QObject *parent=0);
+ virtual ~{{class}}();
+
+ static void registerQmlTypes(const QString& uri, int majorVersion=1, int minorVersion=0);
+};
diff --git a/builtin/qtcpp/templates/module.cpp b/builtin/qtcpp/templates/module.cpp
new file mode 100644
index 0000000..6579b2c
--- /dev/null
+++ b/builtin/qtcpp/templates/module.cpp
@@ -0,0 +1,46 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+{% set class = 'Qml{0}Module'.format(module.module_name) %}
+
+
+#include "{{class|lower}}.h"
+
+#include <QtQml>
+
+QObject* {{class|lower}}_singletontype_provider(QQmlEngine*, QJSEngine*)
+{
+ return new {{class}}();
+}
+
+{{class}}::{{class}}(QObject *parent)
+ : QObject(parent)
+{
+}
+
+{% for struct in module.structs %}
+Qml{{struct}} {{class}}::create{{struct}}()
+{
+ return Qml{{struct}}();
+}
+{% endfor %}
+
+void {{class}}::registerTypes()
+{
+ {% for struct in module.structs %}
+ qRegisterMetaType<Qml{{struct}}>();
+ {% endfor %}
+ {% for enum in module.enums %}
+ qRegisterMetaType<{{class}}::{{enum}}>();
+ {% endfor %}
+}
+
+void {{class}}::registerQmlTypes(const QString& uri, int majorVersion, int minorVersion)
+{
+ {% for struct in module.structs %}
+ qmlRegisterUncreatableType<Qml{{struct}}Model>(uri.toLatin1(), majorVersion, minorVersion, "{{struct}}Model", "Model can not be instantiated from QML");
+ {% endfor %}
+ qmlRegisterSingletonType<{{class}}>(uri.toLatin1(), majorVersion, minorVersion, "{{module.module_name}}Module", {{class|lower}}_singletontype_provider);
+}
diff --git a/builtin/qtcpp/templates/module.h b/builtin/qtcpp/templates/module.h
new file mode 100644
index 0000000..39b5026
--- /dev/null
+++ b/builtin/qtcpp/templates/module.h
@@ -0,0 +1,41 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+{% set class = 'Qml{0}Module'.format(module.module_name) %}
+
+#pragma once
+
+#include <QtCore>
+
+#include "qmlvariantmodel.h"
+{% for struct in module.structs %}
+#include "qml{{struct|lower}}.h"
+#include "qml{{struct|lower}}model.h"
+{% endfor %}
+
+class {{class}} : public QObject {
+ Q_OBJECT
+public:
+ {{class}}(QObject *parent=0);
+
+{% for enum in module.enums %}
+ {% set comma = joiner(",") %}
+ enum {{enum}} {
+ {%- for member in enum.members -%}
+ {{ comma() }}
+ {{member.name}} = {{member.value}}
+ {%- endfor %}
+
+ };
+ Q_ENUM({{enum}})
+{% endfor %}
+
+{% for struct in module.structs %}
+ Q_INVOKABLE Qml{{struct}} create{{struct}}();
+{% endfor %}
+
+ static void registerTypes();
+ static void registerQmlTypes(const QString& uri, int majorVersion = 1, int minorVersion = 0);
+};
diff --git a/builtin/qtcpp/templates/plugin.cpp b/builtin/qtcpp/templates/plugin.cpp
new file mode 100644
index 0000000..aa8fb9a
--- /dev/null
+++ b/builtin/qtcpp/templates/plugin.cpp
@@ -0,0 +1,26 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+{% set module_name = 'Qml{0}Module'.format(module.module_name) %}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+
+#include "plugin.h"
+
+#include <qqml.h>
+
+#include "generated/{{module_name|lower}}.h"
+
+{% for interface in module.interfaces %}
+#include "qml{{interface|lower}}.h"
+{% endfor %}
+
+void Plugin::registerTypes(const char *uri)
+{
+ {{module_name}}::registerTypes();
+ // @uri {{module|lower}}
+ {{module_name}}::registerQmlTypes(uri, 1, 0);
+{% for interface in module.interfaces %}
+ Qml{{interface}}::registerQmlTypes(uri, 1, 0);
+{% endfor %}
+}
diff --git a/builtin/qtcpp/templates/plugin.h b/builtin/qtcpp/templates/plugin.h
new file mode 100644
index 0000000..1952c35
--- /dev/null
+++ b/builtin/qtcpp/templates/plugin.h
@@ -0,0 +1,18 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+
+#pragma once
+
+#include <QtQml>
+
+class Plugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+
+public:
+ void registerTypes(const char *uri);
+};
diff --git a/builtin/qtcpp/templates/plugin.pro b/builtin/qtcpp/templates/plugin.pro
new file mode 100644
index 0000000..00c9d6e
--- /dev/null
+++ b/builtin/qtcpp/templates/plugin.pro
@@ -0,0 +1,47 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+#############################################################################
+## This is an auto-generated file.
+## Do not edit! All changes made to it will be lost.
+#############################################################################
+
+TEMPLATE = lib
+QT += qml quick
+CONFIG += qt plugin c++11
+TARGET = $$qtLibraryTarget({{module|lower}})
+
+uri = {{module}}
+
+
+HEADERS += \
+{% for interface in module.interfaces %}
+ qml{{interface|lower}}.h \
+{% endfor %}
+ plugin.h
+
+
+SOURCES += \
+{% for interface in module.interfaces %}
+ qml{{interface|lower}}.cpp \
+{% endfor %}
+ plugin.cpp
+
+
+include( generated/generated.pri )
+
+DISTFILES = qmldir
+
+!equals(_PRO_FILE_PWD_, $$OUT_PWD) {
+ copy_qmldir.target = $$OUT_PWD/qmldir
+ copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir
+ copy_qmldir.commands = $(COPY_FILE) \"$$replace(copy_qmldir.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_qmldir.target, /, $$QMAKE_DIR_SEP)\"
+ QMAKE_EXTRA_TARGETS += copy_qmldir
+ PRE_TARGETDEPS += $$copy_qmldir.target
+}
+
+qmldir.files = qmldir
+unix {
+ installPath = $$[QT_INSTALL_QML]/$$replace(uri, \\., /)
+ qmldir.path = $$installPath
+ target.path = $$installPath
+ INSTALLS += target qmldir
+}
diff --git a/builtin/qtcpp/templates/qmldir b/builtin/qtcpp/templates/qmldir
new file mode 100644
index 0000000..9fe5d2b
--- /dev/null
+++ b/builtin/qtcpp/templates/qmldir
@@ -0,0 +1,3 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+module {{module}}
+plugin {{module}} \ No newline at end of file
diff --git a/builtin/qtcpp/templates/struct.cpp b/builtin/qtcpp/templates/struct.cpp
new file mode 100644
index 0000000..5b132ec
--- /dev/null
+++ b/builtin/qtcpp/templates/struct.cpp
@@ -0,0 +1,21 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+{% set class = 'Qml{0}'.format(struct) %}
+{% set ampersand = joiner(" &&") %}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+
+#include "{{class|lower}}.h"
+
+
+{{struct.comment}}
+
+bool {{class}}::operator==(const {{class}} &other) const
+{
+ return (
+ {%- for field in struct.fields %}{{ ampersand() }}
+ m_{{field}} == other.m_{{field}}
+ {%- endfor %} );
+}
+
diff --git a/builtin/qtcpp/templates/struct.h b/builtin/qtcpp/templates/struct.h
new file mode 100644
index 0000000..2e0d6d1
--- /dev/null
+++ b/builtin/qtcpp/templates/struct.h
@@ -0,0 +1,29 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+{% set class = 'Qml{0}'.format(struct) %}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+
+#pragma once
+
+#include <QtCore>
+
+class {{class}}
+{
+ Q_GADGET
+{% for field in struct.fields %}
+ Q_PROPERTY({{field|returnType}} {{field}} MEMBER m_{{field}})
+{% endfor %}
+
+public:
+{% for field in struct.fields %}
+ {{field|returnType}} m_{{field}};
+{% endfor %}
+
+ bool operator==(const {{class}} &other) const;
+};
+
+Q_DECLARE_METATYPE({{class}})
+
+
diff --git a/builtin/qtcpp/templates/structmodel.cpp b/builtin/qtcpp/templates/structmodel.cpp
new file mode 100644
index 0000000..3f13cb6
--- /dev/null
+++ b/builtin/qtcpp/templates/structmodel.cpp
@@ -0,0 +1,106 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+{% set class = 'Qml{0}Model'.format(struct) %}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+
+#include "{{class|lower}}.h"
+
+{{class}}::{{class}}(QObject *parent)
+ : QAbstractListModel(parent)
+{
+ {% for field in struct.fields %}
+ m_roleNames.insert(Roles::{{field|upperfirst}}, QByteArray("{{field}}"));
+ {% endfor %}
+}
+
+int {{class}}::count() const
+{
+ return m_data.count();
+}
+
+Qml{{struct}} {{class}}::get(int index)
+{
+ return m_data.value(index);
+}
+
+int {{class}}::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+ return m_data.count();
+}
+
+QVariant {{class}}::data(const QModelIndex &index, int role) const
+{
+ if(index.row() < 0 || index.row() >= count()) {
+ return QVariant();
+ }
+ const Qml{{struct}} &{{struct|lower}} = m_data.at(index.row());
+ switch(role) {
+ {% for field in struct.fields %}
+ case Roles::{{field|upperfirst}}:
+ return QVariant::fromValue({{struct|lower}}.m_{{field}});
+ {% endfor %}
+ }
+ return QVariant();
+}
+
+QHash<int, QByteArray> {{class}}::roleNames() const
+{
+ return m_roleNames;
+}
+
+
+void {{class}}::insert(int row, const Qml{{struct}} &{{struct|lower}})
+{
+ if (row < 0)
+ row = 0;
+ if (row >= m_data.count())
+ row = m_data.count();
+
+ beginInsertRows(QModelIndex(), row, row);
+ m_data.insert(row, {{struct|lower}});
+ endInsertRows();
+ emit countChanged(count());
+}
+
+void {{class}}::reset(const QList<Qml{{struct}}> data)
+{
+ beginResetModel();
+ m_data = data;
+ endResetModel();
+}
+
+void {{class}}::append(const Qml{{struct}} &{{struct|lower}})
+{
+ insert(m_data.count(), {{struct|lower}});
+}
+
+void {{class}}::update(int row, const Qml{{struct}} &{{struct|lower}})
+{
+ if(row < 0 || row >= m_data.count()) {
+ return;
+ }
+ m_data[row] = {{struct|lower}};
+ const QModelIndex &index = createIndex(row, 0);
+ emit dataChanged(index, index);
+}
+
+void {{class}}::remove(int row)
+{
+ if(row < 0 || row >= m_data.count()) {
+ return;
+ }
+ beginRemoveRows(QModelIndex(), row, row);
+ m_data.removeAt(row);
+ endRemoveRows();
+}
+
+void {{class}}::clear()
+{
+ beginResetModel();
+ m_data.clear();
+ endResetModel();
+}
+
diff --git a/builtin/qtcpp/templates/structmodel.h b/builtin/qtcpp/templates/structmodel.h
new file mode 100644
index 0000000..96597be
--- /dev/null
+++ b/builtin/qtcpp/templates/structmodel.h
@@ -0,0 +1,40 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+{% set class = 'Qml{0}Model'.format(struct) %}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+
+#pragma once
+
+#include <QtCore>
+
+#include "qml{{struct|lower}}.h"
+
+class {{class}} : public QAbstractListModel
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+public:
+ enum Roles { {{struct.fields|map('upperfirst')|join(', ')}} };
+ {{class}}(QObject *parent=0);
+ Q_INVOKABLE Qml{{struct}} get(int index);
+ int count() const;
+ void insert(int row, const Qml{{struct}} &{{struct|lower}});
+ void append(const Qml{{struct}} &{{struct|lower}});
+ void update(int row, const Qml{{struct}} &{{struct|lower}});
+ void remove(int row);
+ void reset(const QList<Qml{{struct}}> data);
+ void clear();
+public: // from QAbstractListModel
+ virtual int rowCount(const QModelIndex &parent) const;
+ virtual QVariant data(const QModelIndex &index, int role) const;
+ virtual QHash<int, QByteArray> roleNames() const;
+Q_SIGNALS:
+ void countChanged(int count);
+private:
+ QList<Qml{{struct}}> m_data;
+ QHash<int, QByteArray> m_roleNames;
+};
+
+
diff --git a/builtin/qtcpp/templates/variantmodel.cpp b/builtin/qtcpp/templates/variantmodel.cpp
new file mode 100644
index 0000000..6e197f4
--- /dev/null
+++ b/builtin/qtcpp/templates/variantmodel.cpp
@@ -0,0 +1,102 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+{% set class = 'QmlVariantModel' %}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+
+#include "{{class|lower}}.h"
+
+{{class}}::{{class}}(QObject *parent)
+ : QAbstractListModel(parent)
+{
+ m_roleNames.insert(Roles::ModelData, QByteArray("modelData"));
+}
+
+int {{class}}::count() const
+{
+ return m_data.count();
+}
+
+QVariant {{class}}::get(int index)
+{
+ return m_data.value(index);
+}
+
+int {{class}}::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+ return m_data.count();
+}
+
+QVariant {{class}}::data(const QModelIndex &index, int role) const
+{
+ if(index.row() < 0 || index.row() >= count()) {
+ return QVariant();
+ }
+ const QVariant &entry = m_data.at(index.row());
+ switch(role) {
+ case Roles::ModelData:
+ return entry;
+ }
+ return QVariant();
+}
+
+QHash<int, QByteArray> {{class}}::roleNames() const
+{
+ return m_roleNames;
+}
+
+
+void {{class}}::insert(int row, const QVariant &entry)
+{
+ if (row < 0)
+ row = 0;
+ if (row >= m_data.count())
+ row = m_data.count();
+
+ beginInsertRows(QModelIndex(), row, row);
+ m_data.insert(row, entry);
+ endInsertRows();
+ emit countChanged(count());
+}
+
+void {{class}}::reset(const QVariantList entries)
+{
+ beginResetModel();
+ m_data = entries;
+ endResetModel();
+}
+
+void {{class}}::append(const QVariant &entry)
+{
+ insert(m_data.count(), entry);
+}
+
+void {{class}}::update(int row, const QVariant &entry)
+{
+ if(row < 0 || row >= m_data.count()) {
+ return;
+ }
+ m_data[row] = entry;
+ const QModelIndex &index = createIndex(row, 0);
+ emit dataChanged(index, index);
+}
+
+void {{class}}::remove(int row)
+{
+ if(row < 0 || row >= m_data.count()) {
+ return;
+ }
+ beginRemoveRows(QModelIndex(), row, row);
+ m_data.removeAt(row);
+ endRemoveRows();
+}
+
+void {{class}}::clear()
+{
+ beginResetModel();
+ m_data.clear();
+ endResetModel();
+}
+
diff --git a/builtin/qtcpp/templates/variantmodel.h b/builtin/qtcpp/templates/variantmodel.h
new file mode 100644
index 0000000..67be224
--- /dev/null
+++ b/builtin/qtcpp/templates/variantmodel.h
@@ -0,0 +1,38 @@
+{# Copyright (c) Pelagicore AB 2016 #}
+{% set class = 'QmlVariantModel' %}
+/****************************************************************************
+** This is an auto-generated file.
+** Do not edit! All changes made to it will be lost.
+****************************************************************************/
+
+#pragma once
+
+#include <QtCore>
+
+class {{class}} : public QAbstractListModel
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+public:
+ enum Roles { ModelData = Qt::UserRole };
+ {{class}}(QObject *parent=0);
+ Q_INVOKABLE QVariant get(int index);
+ int count() const;
+ void insert(int row, const QVariant &entry);
+ void append(const QVariant &entry);
+ void update(int row, const QVariant &entry);
+ void remove(int row);
+ void reset(const QVariantList entries);
+ void clear();
+public: // from QAbstractListModel
+ virtual int rowCount(const QModelIndex &parent) const;
+ virtual QVariant data(const QModelIndex &index, int role) const;
+ virtual QHash<int, QByteArray> roleNames() const;
+Q_SIGNALS:
+ void countChanged(int count);
+private:
+ QVariantList m_data;
+ QHash<int, QByteArray> m_roleNames;
+};
+
+