From 1e327a6d6d5eac09f5692d9091043e87ea688e5d Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 13 Jan 2015 11:29:11 +0100 Subject: initial import --- finesketch.desktop | 7 + finesketch.png | Bin 0 -> 5095 bytes finesketch.pro | 41 + finesketch.svg | 1833 +++++++++++++++++++++++++++++++++++++++++ qml/cover/CoverPage.qml | 42 + qml/finesketch.qml | 40 + qml/items/SketchArea.qml | 84 ++ qml/items/SketchView.qml | 80 ++ qml/pages/SketchPage.qml | 12 + rpm/finesketch.changes.in | 15 + rpm/finesketch.spec | 72 ++ rpm/finesketch.yaml | 42 + src/finesketch.cpp | 26 + src/stylus.cpp | 160 ++++ src/stylus.h | 59 ++ translations/finesketch-de.ts | 27 + translations/finesketch.ts | 4 + 17 files changed, 2544 insertions(+) create mode 100644 finesketch.desktop create mode 100644 finesketch.png create mode 100644 finesketch.pro create mode 100644 finesketch.svg create mode 100644 qml/cover/CoverPage.qml create mode 100644 qml/finesketch.qml create mode 100644 qml/items/SketchArea.qml create mode 100644 qml/items/SketchView.qml create mode 100644 qml/pages/SketchPage.qml create mode 100644 rpm/finesketch.changes.in create mode 100644 rpm/finesketch.spec create mode 100644 rpm/finesketch.yaml create mode 100644 src/finesketch.cpp create mode 100644 src/stylus.cpp create mode 100644 src/stylus.h create mode 100644 translations/finesketch-de.ts create mode 100644 translations/finesketch.ts diff --git a/finesketch.desktop b/finesketch.desktop new file mode 100644 index 0000000..fb3ee89 --- /dev/null +++ b/finesketch.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Type=Application +X-Nemo-Application-Type=silica-qt5 +Name=Finesketch +Icon=finesketch +Exec=finesketch + diff --git a/finesketch.png b/finesketch.png new file mode 100644 index 0000000..ae641d5 Binary files /dev/null and b/finesketch.png differ diff --git a/finesketch.pro b/finesketch.pro new file mode 100644 index 0000000..d840436 --- /dev/null +++ b/finesketch.pro @@ -0,0 +1,41 @@ +# NOTICE: +# +# Application name defined in TARGET has a corresponding QML filename. +# If name defined in TARGET is changed, the following needs to be done +# to match new name: +# - corresponding QML filename must be changed +# - desktop icon filename must be changed +# - desktop filename must be changed +# - icon definition filename in desktop file must be changed +# - translation filenames have to be changed + +# The name of your application +TARGET = finesketch + +CONFIG += sailfishapp + +LIBS += -lgato + +SOURCES += src/finesketch.cpp \ + src/stylus.cpp + +OTHER_FILES += qml/finesketch.qml \ + qml/cover/CoverPage.qml \ + rpm/finesketch.changes.in \ + rpm/finesketch.spec \ + rpm/finesketch.yaml \ + translations/*.ts \ + finesketch.desktop \ + finesketch.png \ + qml/items/SketchView.qml \ + qml/pages/SketchPage.qml \ + qml/items/SketchArea.qml + +# to disable building translations every time, comment out the +# following CONFIG line +CONFIG += sailfishapp_i18n +TRANSLATIONS += translations/finesketch-de.ts + +HEADERS += \ + src/stylus.h + diff --git a/finesketch.svg b/finesketch.svg new file mode 100644 index 0000000..f2a10de --- /dev/null +++ b/finesketch.svg @@ -0,0 +1,1833 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/qml/cover/CoverPage.qml b/qml/cover/CoverPage.qml new file mode 100644 index 0000000..7679cfc --- /dev/null +++ b/qml/cover/CoverPage.qml @@ -0,0 +1,42 @@ +/* + Copyright (C) 2013 Jolla Ltd. + Contact: Thomas Perl + All rights reserved. + + You may use this file under the terms of 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 the Jolla Ltd 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 HOLDERS 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 QtQuick 2.0 +import Sailfish.Silica 1.0 + +CoverBackground { + Label { + id: label + anchors.centerIn: parent + text: "Finescript" + } +} + + diff --git a/qml/finesketch.qml b/qml/finesketch.qml new file mode 100644 index 0000000..e116e6f --- /dev/null +++ b/qml/finesketch.qml @@ -0,0 +1,40 @@ +/* + Copyright (C) 2013 Jolla Ltd. + Contact: Thomas Perl + All rights reserved. + + You may use this file under the terms of 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 the Jolla Ltd 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 HOLDERS 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 QtQuick 2.0 +import Sailfish.Silica 1.0 +import "pages" + +ApplicationWindow +{ + id: appWindow + initialPage: Component { SketchPage { } } + cover: Qt.resolvedUrl("cover/CoverPage.qml") +} diff --git a/qml/items/SketchArea.qml b/qml/items/SketchArea.qml new file mode 100644 index 0000000..3a528d9 --- /dev/null +++ b/qml/items/SketchArea.qml @@ -0,0 +1,84 @@ +import QtQuick 2.0 + +SketchView { + id: area + autoRepaint: false + + property color fingerLineColor: Qt.rgba(1.0, 0.0, 0.0, 1.0) + property color stylusLineColor: Qt.rgba(0.0, 0.0, 0.0, 1.0) + property color eraserLineColor: Qt.rgba(1.0, 1.0, 1.0, 1.0) + property real curLineWidth: 4 + + function _boundingBox(points) { + if (!points.length) return Qt.rect(0, 0, 0, 0); + var x1 = points[0].x, y1 = points[0].y; + var x2 = x1, y2 = y1; + + for (var i = 1; i < points.length; i++) { + if (points[i].x < x1) x1 = points[i].x; + if (points[i].y < y1) y1 = points[i].y; + if (points[i].x > x2) x2 = points[i].x; + if (points[i].y > y2) y2 = points[i].y; + } + + return Qt.rect(x1, y1, x2 - x1, y2 - y1); + } + + function _isStylusOn() { + return stylus.pressure > 0.15; + } + function _isEraserOn() { + return !_isStylusOn() && stylus.y > 0.85; + } + + MouseArea { + anchors.fill: parent + preventStealing: true + + onPressed: { + var point = Qt.point(mouse.x, mouse.y); + var stroke = { + lineWidth : curLineWidth, + lineColor : fingerLineColor, + stylus : false, + eraser : false, + boundingBox : Qt.rect(0, 0, area.width, area.height), + points : [point] + } + strokes.push(stroke); + canvas.requestPaint(); + } + onReleased: { + canvas.requestPaint(); + } + onPositionChanged: { + var cur_stroke = strokes[area.strokes.length - 1]; + var point = Qt.point(mouse.x, mouse.y); + var prev_point = cur_stroke.points[cur_stroke.points.length - 1]; + cur_stroke.points.push(point); + cur_stroke.boundingBox = _boundingBox(cur_stroke.points); + + var rect = Qt.rect(Math.floor(Math.min(point.x, prev_point.x) - cur_stroke.lineWidth/2), + Math.floor(Math.min(point.y, prev_point.y) - cur_stroke.lineWidth/2), + Math.ceil(Math.abs(point.x - prev_point.x) + cur_stroke.lineWidth), + Math.ceil(Math.abs(point.y - prev_point.y) + cur_stroke.lineWidth)); + + if (!cur_stroke.stylus) { + if (_isStylusOn()) { + cur_stroke.stylus = true; + cur_stroke.lineColor = stylusLineColor; + canvas.requestPaint(); + return; + } else if (_isEraserOn()) { + cur_stroke.stylus = true; + cur_stroke.eraser = true; + cur_stroke.lineColor = eraserLineColor; + canvas.requestPaint(); + return; + } + } + + canvas.markDirty(rect); + } + } +} diff --git a/qml/items/SketchView.qml b/qml/items/SketchView.qml new file mode 100644 index 0000000..8ded87a --- /dev/null +++ b/qml/items/SketchView.qml @@ -0,0 +1,80 @@ +import QtQuick 2.0 + +Item { + id: view + + property alias fillColor: rectangle.color + property alias border: rectangle.border + + property var strokes: [] + + property bool autoRepaint: true + property alias canvas: canvas + + function _drawStroke(ctx, stroke) { + var points = stroke.points; + ctx.save(); + ctx.lineWidth = stroke.lineWidth; + ctx.strokeStyle = stroke.lineColor; + ctx.lineCap = 'round'; + ctx.lineJoin = 'round'; + ctx.beginPath(); + ctx.moveTo(points[0].x, points[0].y); + for (var i = 1; i < points.length; i++) { + ctx.lineTo(points[i].x, points[i].y); + } + ctx.stroke(); + ctx.restore(); + } + + function _intersect(r1, r2) { + if (!r1.width || !r2.width) return false; + if (!r1.height || !r2.height) return false; + + if (r1.x >= r2.x + r2.width) return false; + if (r1.y >= r2.y + r2.height) return false; + if (r2.x >= r1.x + r1.width) return false; + if (r2.y >= r1.y + r1.height) return false; + return true; + } + + Rectangle { + id: rectangle + anchors.fill: parent + + color: Qt.rgba(1.0, 1.0, 1.0, 0.3) + radius: 10.0 + } + + Canvas { + id: canvas + anchors.fill: parent + + renderTarget: Canvas.Image + renderStrategy: Canvas.Immediate + + onPaint: { + var ctx = canvas.getContext('2d'); + ctx.clearRect(region.x, region.y, region.width, region.height); + + ctx.save(); + ctx.beginPath(); + ctx.rect(region.x, region.y, region.width, region.height); + ctx.clip(); + + for (var i = 0; i < strokes.length; i++) { + if (_intersect(region, strokes[i].boundingBox)) { + _drawStroke(ctx, strokes[i]); + } + } + + ctx.restore(); + } + } + + onStrokesChanged: { + if (autoRepaint) { + canvas.requestPaint(); + } + } +} diff --git a/qml/pages/SketchPage.qml b/qml/pages/SketchPage.qml new file mode 100644 index 0000000..449b2aa --- /dev/null +++ b/qml/pages/SketchPage.qml @@ -0,0 +1,12 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import "../items" + +Page { + id: sketchPage + + SketchArea { + id: area + anchors.fill: parent + } +} diff --git a/rpm/finesketch.changes.in b/rpm/finesketch.changes.in new file mode 100644 index 0000000..08a66ad --- /dev/null +++ b/rpm/finesketch.changes.in @@ -0,0 +1,15 @@ +# Rename this file as finesketch.changes to include changelog +# entries in your RPM file. +# +# Add new changelog entries following the format below. +# Add newest entries to the top of the list. +# Separate entries from eachother with a blank line. + +# * date Author's Name version-release +# - Summary of changes + +* Sun Apr 13 2014 Jack Tar 0.0.1-1 +- Scrubbed the deck +- Hoisted the sails + + diff --git a/rpm/finesketch.spec b/rpm/finesketch.spec new file mode 100644 index 0000000..d5ad334 --- /dev/null +++ b/rpm/finesketch.spec @@ -0,0 +1,72 @@ +# +# Do NOT Edit the Auto-generated Part! +# Generated by: spectacle version 0.27 +# + +Name: finesketch + +# >> macros +# << macros + +%{!?qtc_qmake:%define qtc_qmake %qmake} +%{!?qtc_qmake5:%define qtc_qmake5 %qmake5} +%{!?qtc_make:%define qtc_make make} +%{?qtc_builddir:%define _builddir %qtc_builddir} +Summary: My SailfishOS Application +Version: 0.1 +Release: 1 +Group: Qt/Qt +License: LICENSE +URL: http://example.org/ +Source0: %{name}-%{version}.tar.bz2 +Source100: finesketch.yaml +Requires: sailfishsilica-qt5 >= 0.10.9 +BuildRequires: pkgconfig(sailfishapp) >= 1.0.2 +BuildRequires: pkgconfig(Qt5Core) +BuildRequires: pkgconfig(Qt5Qml) +BuildRequires: pkgconfig(Qt5Quick) +BuildRequires: libgato-devel +BuildRequires: desktop-file-utils + +%description +Short description of my SailfishOS Application + + +%prep +%setup -q -n %{name}-%{version} + +# >> setup +# << setup + +%build +# >> build pre +# << build pre + +%qtc_qmake5 + +%qtc_make %{?_smp_mflags} + +# >> build post +# << build post + +%install +rm -rf %{buildroot} +# >> install pre +# << install pre +%qmake5_install + +# >> install post +# << install post + +desktop-file-install --delete-original \ + --dir %{buildroot}%{_datadir}/applications \ + %{buildroot}%{_datadir}/applications/*.desktop + +%files +%defattr(-,root,root,-) +%{_bindir} +%{_datadir}/%{name} +%{_datadir}/applications/%{name}.desktop +%{_datadir}/icons/hicolor/86x86/apps/%{name}.png +# >> files +# << files diff --git a/rpm/finesketch.yaml b/rpm/finesketch.yaml new file mode 100644 index 0000000..accb3d6 --- /dev/null +++ b/rpm/finesketch.yaml @@ -0,0 +1,42 @@ +Name: finesketch +Summary: My SailfishOS Application +Version: 0.1 +Release: 1 +# The contents of the Group field must be one of the groups listed here: +# http://gitorious.org/meego-developer-tools/spectacle/blobs/master/data/GROUPS +Group: Qt/Qt +URL: http://example.org/ +License: LICENSE +# This must be generated before uploading a package to a remote build service. +# Usually this line does not need to be modified. +Sources: +- '%{name}-%{version}.tar.bz2' +Description: | + Short description of my SailfishOS Application +Configure: none +# The qtc5 builder inserts macros to allow QtCreator to have fine +# control over qmake/make execution +Builder: qtc5 + +PkgConfigBR: + - sailfishapp >= 1.0.2 + - Qt5Core + - Qt5Qml + - Qt5Quick + +PkgBR: +- libgato-devel + +Requires: + - sailfishsilica-qt5 >= 0.10.9 + +# All installed files +Files: + - '%{_bindir}' + - '%{_datadir}/%{name}' + - '%{_datadir}/applications/%{name}.desktop' + - '%{_datadir}/icons/hicolor/86x86/apps/%{name}.png' + +# For more information about yaml and what's supported in Sailfish OS +# build system, please see https://wiki.merproject.org/wiki/Spectacle + diff --git a/src/finesketch.cpp b/src/finesketch.cpp new file mode 100644 index 0000000..1a5c45f --- /dev/null +++ b/src/finesketch.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include "stylus.h" + +int main(int argc, char *argv[]) +{ + QGuiApplication *app = SailfishApp::application(argc, argv); + QQuickView *view = SailfishApp::createView(); + + Stylus *stylus = new Stylus(); + stylus->connectDevice("F4:6A:BC:10:4F:E9"); + + view->rootContext()->setContextProperty("stylus", stylus); + view->setSource(SailfishApp::pathTo("qml/finesketch.qml")); + + view->show(); + + int res = app->exec(); + + delete stylus; + + return res; +} + diff --git a/src/stylus.cpp b/src/stylus.cpp new file mode 100644 index 0000000..f4fd0a8 --- /dev/null +++ b/src/stylus.cpp @@ -0,0 +1,160 @@ +#include +#include +#include "stylus.h" + +static const QString stylus_name(QString::fromLatin1("JN104FE9")); +static const GatoUUID stylus_service(QString::fromLatin1("dcd68980-aadc-11e1-a22a-0002a5d5c51b")); +static const GatoUUID agg_char_uuid(QString::fromLatin1("00002a5a-0000-1000-8000-00805f9b34fb")); + +Stylus::Stylus(QObject *parent) : + QObject(parent), + _manager(new GatoCentralManager(this)), + _peripheral(0), + _p(0), _x(0), _y(0), _z(0) +{ + connect(_manager, SIGNAL(discoveredPeripheral(GatoPeripheral*,int)), + SLOT(handleDiscoveredPeripheral(GatoPeripheral*,int))); +} + +Stylus::~Stylus() +{ + if (_peripheral) { + disconnect(_peripheral, 0, this, 0); + _peripheral->disconnectPeripheral(); + } +} + +qreal Stylus::pressure() const +{ + return _p; +} + +qreal Stylus::x() const +{ + return _x; +} + +qreal Stylus::y() const +{ + return _y; +} + +qreal Stylus::z() const +{ + return _z; +} + +void Stylus::connectToAnyDevice() +{ + _manager->scanForPeripherals(); +} + +void Stylus::connectDevice(const QString &addr) +{ + connectToPeripheral(new GatoPeripheral(GatoAddress(addr), this)); +} + +void Stylus::disconnectDevice() +{ + if (_peripheral) { + _peripheral->disconnectPeripheral(); + _peripheral->deleteLater(); + _peripheral = 0; + } +} + +void Stylus::connectToPeripheral(GatoPeripheral *peripheral) +{ + if (_peripheral) { + disconnectDevice(); + } + + _peripheral = peripheral; + + qDebug() << "Connecting to peripheral" << peripheral->name() << peripheral->address().toString(); + + connect(_peripheral, SIGNAL(connected()), SLOT(handleConnected())); + connect(_peripheral, SIGNAL(disconnected()), SLOT(handleDisconnected())); + connect(_peripheral, SIGNAL(servicesDiscovered()), SLOT(handleServices())); + connect(_peripheral, SIGNAL(characteristicsDiscovered(GatoService)), SLOT(handleCharacteristics(GatoService))); + connect(_peripheral, SIGNAL(valueUpdated(GatoCharacteristic,QByteArray)), SLOT(handleValueUpdated(GatoCharacteristic,QByteArray))); + + _peripheral->connectPeripheral(); +} + +void Stylus::handleDiscoveredPeripheral(GatoPeripheral *peripheral, int rssi) +{ + qDebug() << "Found peripheral" << peripheral->address().toString() << peripheral->name() << rssi; + if (peripheral->name() == stylus_name) { + _manager->stopScan(); + connectToPeripheral(peripheral); + } +} +void Stylus::handleConnected() +{ + qDebug() << "Connected to" << _peripheral->name(); + _peripheral->discoverServices(); +} + +void Stylus::handleDisconnected() +{ + qDebug() << "Peripheral disconnected"; +} + +void Stylus::handleServices() +{ + qDebug() << "Services found"; + foreach (const GatoService &service, _peripheral->services()) { + qDebug() << service.uuid(); + if (service.uuid() == stylus_service) { + // Found the service we want + qDebug() << "Found stylus service"; + _peripheral->discoverCharacteristics(service); + } + } +} + +void Stylus::handleCharacteristics(const GatoService &service) +{ + foreach (const GatoCharacteristic &c, service.characteristics()) { + if (c.uuid() == agg_char_uuid) { + qDebug() << c.uuid(); + _peripheral->setNotification(c, true); + } + } +} + +void Stylus::handleValueUpdated(const GatoCharacteristic &characteristic, const QByteArray &value) +{ + if (characteristic.uuid() == agg_char_uuid) { + QDataStream s(value); + s.setByteOrder(QDataStream::BigEndian); + qint16 p, x, y, z; + s >> p >> x >> y >> z; + handleReport(p, x, y, z); + } +} + +void Stylus::handleReport(int p, int x, int y, int z) +{ + qreal newp = p / 7000.0; + if (newp != _p) { + _p = newp; + emit pressureChanged(); + } + qreal newx = x / 268.0; + if (newx != _x) { + _x = newx; + emit xChanged(); + } + qreal newy = y / 268.0; + if (newy != _y) { + _y = newy; + emit yChanged(); + } + qreal newz = z / 268.0; + if (newz != _z) { + _z = newz; + emit zChanged(); + } +} diff --git a/src/stylus.h b/src/stylus.h new file mode 100644 index 0000000..9b845b9 --- /dev/null +++ b/src/stylus.h @@ -0,0 +1,59 @@ +#ifndef STYLUS_H +#define STYLUS_H + +#include +#include +#include + +class Stylus : public QObject +{ + Q_OBJECT + Q_PROPERTY(qreal pressure READ pressure NOTIFY pressureChanged) + Q_PROPERTY(qreal x READ x NOTIFY xChanged) + Q_PROPERTY(qreal y READ y NOTIFY yChanged) + Q_PROPERTY(qreal z READ z NOTIFY zChanged) + +public: + explicit Stylus(QObject *parent = 0); + ~Stylus(); + + qreal pressure() const; + qreal x() const; + qreal y() const; + qreal z() const; + +signals: + void autoUpdateChanged(); + void pressureChanged(); + void xChanged(); + void yChanged(); + void zChanged(); + +public slots: + void connectToAnyDevice(); + void connectDevice(const QString &addr); + void disconnectDevice(); + +private: + void connectToPeripheral(GatoPeripheral *peripheral); + +private slots: + void handleDiscoveredPeripheral(GatoPeripheral *peripheral, int rssi); + void handleConnected(); + void handleDisconnected(); + void handleServices(); + void handleCharacteristics(const GatoService &service); + void handleValueUpdated(const GatoCharacteristic &characteristic, const QByteArray &value); + void handleReport(int p, int x, int y, int z); + +private: + GatoCentralManager *_manager; + GatoPeripheral *_peripheral; + + qreal _p; + qreal _x; + qreal _y; + qreal _z; +}; + +#endif // STYLUS_H diff --git a/translations/finesketch-de.ts b/translations/finesketch-de.ts new file mode 100644 index 0000000..a4f35ad --- /dev/null +++ b/translations/finesketch-de.ts @@ -0,0 +1,27 @@ + + + + + FirstPage + + Show Page 2 + Zur Seite 2 + + + UI Template + UI-Vorlage + + + Hello Sailors + Hallo Matrosen + + + + SecondPage + + Nested Page + Unterseite + + + + diff --git a/translations/finesketch.ts b/translations/finesketch.ts new file mode 100644 index 0000000..07a7469 --- /dev/null +++ b/translations/finesketch.ts @@ -0,0 +1,4 @@ + + + + -- cgit v1.2.3