From aa1c0fd3146b4ed055d181c99d52463afa6bedbb Mon Sep 17 00:00:00 2001 From: "Javier S. Pedro" Date: Fri, 16 Sep 2011 17:47:24 +0200 Subject: Initial import --- declarativewatchlet.cpp | 94 +++++++ declarativewatchlet.h | 43 ++++ declarativewatchwrapper.cpp | 29 +++ declarativewatchwrapper.h | 41 ++++ graphicswatchlet.cpp | 47 ++++ graphicswatchlet.h | 35 +++ main.cpp | 31 +++ metawatch.cpp | 409 +++++++++++++++++++++++++++++++ metawatch.h | 117 +++++++++ metawatchpaintengine.cpp | 75 ++++++ metawatchpaintengine.h | 32 +++ metawatchsimulator.cpp | 72 ++++++ metawatchsimulator.h | 30 +++ metawatchsimulatorform.cpp | 82 +++++++ metawatchsimulatorform.h | 46 ++++ metawatchsimulatorform.ui | 294 ++++++++++++++++++++++ qt.png | Bin 0 -> 1307 bytes qtc_packaging/debian_harmattan/README | 6 + qtc_packaging/debian_harmattan/changelog | 5 + qtc_packaging/debian_harmattan/compat | 1 + qtc_packaging/debian_harmattan/control | 14 ++ qtc_packaging/debian_harmattan/copyright | 40 +++ qtc_packaging/debian_harmattan/rules | 91 +++++++ sowatch.h | 11 + sowatch.pro | 76 ++++++ testdeclarativewatchlet.cpp | 9 + testdeclarativewatchlet.h | 19 ++ testdeclarativewatchlet.qml | 104 ++++++++ tests.qrc | 6 + testwatchlet.cpp | 37 +++ testwatchlet.h | 34 +++ watch.cpp | 62 +++++ watch.h | 49 ++++ watchlet.cpp | 25 ++ watchlet.h | 38 +++ watchmanager.cpp | 8 + watchmanager.h | 23 ++ watchpaintengine.cpp | 295 ++++++++++++++++++++++ watchpaintengine.h | 59 +++++ watchserver.cpp | 57 +++++ watchserver.h | 46 ++++ watchsimulator.cpp | 11 + watchsimulator.h | 20 ++ 43 files changed, 2623 insertions(+) create mode 100644 declarativewatchlet.cpp create mode 100644 declarativewatchlet.h create mode 100644 declarativewatchwrapper.cpp create mode 100644 declarativewatchwrapper.h create mode 100644 graphicswatchlet.cpp create mode 100644 graphicswatchlet.h create mode 100644 main.cpp create mode 100644 metawatch.cpp create mode 100644 metawatch.h create mode 100644 metawatchpaintengine.cpp create mode 100644 metawatchpaintengine.h create mode 100644 metawatchsimulator.cpp create mode 100644 metawatchsimulator.h create mode 100644 metawatchsimulatorform.cpp create mode 100644 metawatchsimulatorform.h create mode 100644 metawatchsimulatorform.ui create mode 100644 qt.png create mode 100644 qtc_packaging/debian_harmattan/README create mode 100644 qtc_packaging/debian_harmattan/changelog create mode 100644 qtc_packaging/debian_harmattan/compat create mode 100644 qtc_packaging/debian_harmattan/control create mode 100644 qtc_packaging/debian_harmattan/copyright create mode 100755 qtc_packaging/debian_harmattan/rules create mode 100644 sowatch.h create mode 100644 sowatch.pro create mode 100644 testdeclarativewatchlet.cpp create mode 100644 testdeclarativewatchlet.h create mode 100644 testdeclarativewatchlet.qml create mode 100644 tests.qrc create mode 100644 testwatchlet.cpp create mode 100644 testwatchlet.h create mode 100644 watch.cpp create mode 100644 watch.h create mode 100644 watchlet.cpp create mode 100644 watchlet.h create mode 100644 watchmanager.cpp create mode 100644 watchmanager.h create mode 100644 watchpaintengine.cpp create mode 100644 watchpaintengine.h create mode 100644 watchserver.cpp create mode 100644 watchserver.h create mode 100644 watchsimulator.cpp create mode 100644 watchsimulator.h diff --git a/declarativewatchlet.cpp b/declarativewatchlet.cpp new file mode 100644 index 0000000..1b9c836 --- /dev/null +++ b/declarativewatchlet.cpp @@ -0,0 +1,94 @@ +#include +#include +#include "watchserver.h" +#include "declarativewatchwrapper.h" +#include "declarativewatchlet.h" + +using namespace sowatch; + +bool DeclarativeWatchlet::_registered = false; + +DeclarativeWatchlet::DeclarativeWatchlet(WatchServer* server, const QString& id) : + GraphicsWatchlet(server, id), + _engine(0), + _component(0), + _item(0), + _wrapper(0) +{ + setScene(new QGraphicsScene(this)); + + if (!_registered) { + qmlRegisterUncreatableType("com.javispedro.sowatch", 1, 0, + "Watch", "Watch is only available via attached properties"); + _registered = true; + } + + _engine = new QDeclarativeEngine(this); + _wrapper = new DeclarativeWatchWrapper(server->watch(), this); + + _engine->rootContext()->setContextProperty("watch", _wrapper); +} + +void DeclarativeWatchlet::setSource(const QUrl &url) +{ + if (_item) { + scene()->removeItem(_item); + delete _item; + _item = 0; + } + if (_component) { + delete _component; + _component = 0; + } + if (!url.isEmpty()) { + _component = new QDeclarativeComponent(_engine, url, this); + connect(_component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), + SLOT(handleComponentStatus(QDeclarativeComponent::Status))); + if (!_component->isLoading()) { + /* No signals are going to be generated for this. */ + handleComponentStatus(_component->status()); + } else { + connect(_component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), + this, SLOT(handleComponentStatus(QDeclarativeComponent::Status))); + } + } +} + +void DeclarativeWatchlet::activate() +{ + _wrapper->activate(); + _scene->update(); +} + +void DeclarativeWatchlet::deactivate() +{ + _wrapper->deactivate(); +} + +void DeclarativeWatchlet::handleComponentStatus(QDeclarativeComponent::Status status) +{ + QObject *obj; + disconnect(_component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), + this, SLOT(handleComponentStatus(QDeclarativeComponent::Status))); + switch (status) { + case QDeclarativeComponent::Null: + case QDeclarativeComponent::Loading: + /* Nothing to do */ + break; + case QDeclarativeComponent::Ready: + obj = _component->create(); + if (_component->isError()) { + qWarning() << "QML has instantation errors:"; + qWarning() << _component->errors(); + return; + } + Q_ASSERT(_item == 0); + _item = qobject_cast(obj); + scene()->addItem(_item); + break; + case QDeclarativeComponent::Error: + qWarning() << "QML has errors:"; + qWarning() << _component->errors(); + break; + } +} diff --git a/declarativewatchlet.h b/declarativewatchlet.h new file mode 100644 index 0000000..bd42841 --- /dev/null +++ b/declarativewatchlet.h @@ -0,0 +1,43 @@ +#ifndef DECLARATIVEWATCHLET_H +#define DECLARATIVEWATCHLET_H + +#include +#include +#include +#include "graphicswatchlet.h" + +namespace sowatch +{ + +class DeclarativeWatchWrapper; + +class DeclarativeWatchlet : public GraphicsWatchlet +{ + Q_OBJECT +public: + explicit DeclarativeWatchlet(WatchServer* server, const QString& id); + + void setSource(const QUrl& url); + + void activate(); + void deactivate(); + +signals: + +public slots: + +protected slots: + void handleComponentStatus(QDeclarativeComponent::Status status); + +protected: + static bool _registered; + QDeclarativeEngine* _engine; + QDeclarativeComponent* _component; + QDeclarativeItem* _item; + DeclarativeWatchWrapper* _wrapper; + +}; + +} + +#endif // DECLARATIVEWATCHLET_H diff --git a/declarativewatchwrapper.cpp b/declarativewatchwrapper.cpp new file mode 100644 index 0000000..127b6d6 --- /dev/null +++ b/declarativewatchwrapper.cpp @@ -0,0 +1,29 @@ +#include +#include "watch.h" +#include "declarativewatchwrapper.h" + +using namespace sowatch; + +DeclarativeWatchWrapper::DeclarativeWatchWrapper(Watch* watch, QObject *parent) : + QObject(parent), _watch(watch) +{ + +} + +QString DeclarativeWatchWrapper::model() const +{ + return _watch->model(); +} + +void DeclarativeWatchWrapper::activate() +{ + connect(_watch, SIGNAL(buttonPressed(int)), this, SIGNAL(buttonPressed(int))); + connect(_watch, SIGNAL(buttonReleased(int)), this, SIGNAL(buttonReleased(int))); +} + +void DeclarativeWatchWrapper::deactivate() +{ + disconnect(this, SIGNAL(buttonPressed(int))); + disconnect(this, SIGNAL(buttonReleased(int))); +} + diff --git a/declarativewatchwrapper.h b/declarativewatchwrapper.h new file mode 100644 index 0000000..09e0923 --- /dev/null +++ b/declarativewatchwrapper.h @@ -0,0 +1,41 @@ +#ifndef DECLARATIVEWATCHWRAPPER_H +#define DECLARATIVEWATCHWRAPPER_H + +#include + +namespace sowatch +{ + +class Watch; +class DeclarativeWatchlet; + +class DeclarativeWatchWrapper : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString model READ model NOTIFY modelChanged) + +public: + explicit DeclarativeWatchWrapper(Watch *watch, QObject *parent = 0); + + Q_INVOKABLE QString model() const; + +signals: + void buttonPressed(int button); + void buttonReleased(int button); + + void modelChanged(); + +protected: + Watch* _watch; + + void activate(); + void deactivate(); + +friend class DeclarativeWatchlet; +}; + +} + +QML_DECLARE_TYPE(sowatch::DeclarativeWatchWrapper) + +#endif // DECLARATIVEWATCHWRAPPER_H diff --git a/graphicswatchlet.cpp b/graphicswatchlet.cpp new file mode 100644 index 0000000..130e1cc --- /dev/null +++ b/graphicswatchlet.cpp @@ -0,0 +1,47 @@ +#include +#include + +#include "watch.h" +#include "graphicswatchlet.h" + +using namespace sowatch; + +GraphicsWatchlet::GraphicsWatchlet(WatchServer* server, const QString& id) : + Watchlet(server, id), _scene(0), _damaged() +{ +} + +QGraphicsScene* GraphicsWatchlet::scene() +{ + return _scene; +} + +void GraphicsWatchlet::setScene(QGraphicsScene *scene) +{ + if (_scene) { + disconnect(this, SLOT(sceneChanged(QList))); + } + _scene = scene; + if (_scene) { + connect(_scene, SIGNAL(changed(QList)), + this, SLOT(sceneChanged(QList))); + } +} + +void GraphicsWatchlet::sceneChanged(const QList ®ion) +{ + foreach(const QRectF& r, region) + { + _damaged += r.toRect(); + } + + if (!_damaged.isEmpty() && !watch()->busy()) { + const QVector rects = _damaged.rects(); + QPainter p(watch()); + foreach(const QRect& r, rects) + { + _scene->render(&p, r, r, Qt::IgnoreAspectRatio); + } + _damaged = QRegion(); + } +} diff --git a/graphicswatchlet.h b/graphicswatchlet.h new file mode 100644 index 0000000..abf1da2 --- /dev/null +++ b/graphicswatchlet.h @@ -0,0 +1,35 @@ +#ifndef GRAPHICSWATCHLET_H +#define GRAPHICSWATCHLET_H + +#include +#include +#include "watchlet.h" + +namespace sowatch +{ + +class GraphicsWatchlet : public Watchlet +{ + Q_OBJECT +public: + explicit GraphicsWatchlet(WatchServer* server, const QString& id); + + QGraphicsScene* scene(); + void setScene(QGraphicsScene* scene); + +signals: + +public slots: + +protected: + QGraphicsScene* _scene; + QRegion _damaged; + +protected slots: + void sceneChanged(const QList& region); + +}; + +} + +#endif // GRAPHICSWATCHLET_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..8bad8ce --- /dev/null +++ b/main.cpp @@ -0,0 +1,31 @@ +#include +#include + +#include "metawatchsimulator.h" +#include "metawatch.h" +#include "watchserver.h" +#include "testwatchlet.h" +#include "testdeclarativewatchlet.h" + +using namespace sowatch; +QTM_USE_NAMESPACE + +static Watch *watch; +static WatchServer *server; +static Watchlet *watchlet; + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + //watch = new MetaWatchSimulator(); + watch = new MetaWatch(QBluetoothAddress("D0:37:61:C3:C7:99")); + server = new WatchServer(watch); + //watchlet = new TestDeclarativeWatchlet(server); + watchlet = new TestWatchlet(server); + + //server->runWatchlet("com.javispedro.sowatch.testdeclarativewatchlet"); + server->runWatchlet("com.javispedro.sowatch.testwatchlet"); + + return a.exec(); +} diff --git a/metawatch.cpp b/metawatch.cpp new file mode 100644 index 0000000..d523e1c --- /dev/null +++ b/metawatch.cpp @@ -0,0 +1,409 @@ +#include +#include + +#include "metawatchpaintengine.h" +#include "metawatch.h" + +using namespace sowatch; +QTM_USE_NAMESPACE + +#define SINGLE_LINE_UPDATE 0 + +const quint8 MetaWatch::bitRevTable[16] = { + 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 +}; + +const quint16 MetaWatch::crcTable[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + +#if 0 /* This snippet was used to build the table seen above. */ + quint16 remainder; + int dividend; + quint8 bit; + + for (dividend = 0; dividend < 256; dividend++) { + remainder = dividend << 8; + for (bit = 8; bit > 0; bit--) { + if (remainder & 0x8000) { + remainder = (remainder << 1) ^ 0x1021; + } else { + remainder = (remainder << 1); + } + } + if ((dividend % 8) == 0) { + printf(",\n0x%04hx", remainder); + } else { + printf(", 0x%04hx", remainder); + } + } +#endif + +MetaWatch::MetaWatch(const QBluetoothAddress& address, QObject *parent) : + Watch(QImage(96, 96, QImage::Format_MonoLSB), parent), + _socket(new QBluetoothSocket(QBluetoothSocket::RfcommSocket)), + _sendTimer(new QTimer(this)) +{ + connect(_socket, SIGNAL(connected()), SLOT(socketConnected())); + connect(_socket, SIGNAL(disconnected()), SLOT(socketDisconnected())); + connect(_socket, SIGNAL(readyRead()), SLOT(socketData())); + connect(_socket, SIGNAL(error(QBluetoothSocket::SocketError)), + SLOT(socketError(QBluetoothSocket::SocketError))); + connect(_socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)), + SLOT(socketState(QBluetoothSocket::SocketState))); + + _sendTimer->setInterval(30); + connect(_sendTimer, SIGNAL(timeout()), SLOT(timedSend())); + + _socket->connectToService(address, 1, QIODevice::ReadWrite | QIODevice::Unbuffered); +} + +QPaintEngine* MetaWatch::paintEngine() const +{ + if (!_paintEngine) { + _paintEngine = new MetaWatchPaintEngine(const_cast(this), + const_cast(&_image)); + } + + return _paintEngine; +} + +QString MetaWatch::model() const +{ + return "metawatch-digital"; +} + +bool MetaWatch::isConnected() const +{ + return _socket->state() == QBluetoothSocket::ConnectedState; +} + +bool MetaWatch::busy() const +{ + return _socket->state() != QBluetoothSocket::ConnectedState || + _toSend.size() > 20; +} + +void MetaWatch::update(const QList &rects) +{ + if (_socket->state() != QBluetoothSocket::ConnectedState) return; + const QRect imageRect = _image.rect(); + QVector lines(_image.height(), false); + + foreach (const QRect& rect, rects) { + QRect r = rect.intersect(imageRect); + for (int i = r.top(); i <= r.bottom(); i++) { + lines[i] = true; + } + } + + updateLines(1, _image, lines); + updateDisplay(1); +} + +void MetaWatch::clear(bool white) +{ + if (_socket->state() != QBluetoothSocket::ConnectedState) return; + loadTemplate(1, white ? 1 : 0); +} + +void MetaWatch::vibrate(bool on) +{ + +} + +void MetaWatch::setDateTime(const QDateTime &dateTime) +{ + Message msg(SetRealTimeClock, QByteArray(10, 0)); + const QDate& date = dateTime.date(); + const QTime& time = dateTime.time(); + + msg.data[0] = date.year() & 0xF00; + msg.data[1] = date.year() & 0xFF; + msg.data[2] = date.month(); + msg.data[3] = date.day(); + msg.data[4] = date.dayOfWeek() - 1; + msg.data[5] = time.hour(); + msg.data[6] = time.minute(); + msg.data[7] = time.second(); + msg.data[8] = 1; + msg.data[9] = 1; + + send(msg); +} + +quint16 MetaWatch::calcCrc(const QByteArray &data, int size) +{ + quint16 remainder = 0xFFFF; + + for (int i = 0; i < size; i++) { + quint8 byte = data[i]; + byte = (bitRevTable[byte & 0xF] << 4) | bitRevTable[(byte & 0xF0) >> 4]; + remainder = crcTable[byte ^ (remainder >> 8)] ^ (remainder << 8); + } + + return remainder; +} + +quint16 MetaWatch::calcCrc(const Message& msg) +{ + QByteArray data; + const int msgSize = msg.data.size(); + + data.resize(msgSize + 4); + data[0] = 0x01; + data[1] = msgSize + 6; + data[2] = msg.type; + data[3] = msg.options; + data.replace(4, msgSize, msg.data); + + return calcCrc(data, msgSize + 4); +} + +void MetaWatch::send(const Message &msg) +{ + _toSend.enqueue(msg); + if (!_sendTimer->isActive()) { + _sendTimer->start(); + } +} + +void MetaWatch::handleMessage(const Message &msg) +{ + switch (msg.type) { + case StatusChangeEvent: + handleStatusChange(msg); + break; + case ButtonEvent: + handleButtonEvent(msg); + break; + default: + qWarning() << "Unknown message of type" << msg.type << "received"; + break; + } +} + +void MetaWatch::updateLine(int mode, const QImage& image, int line) +{ + Message msg(WriteBuffer, QByteArray(13, 0), (1 << 4) | (mode & 0xF)); + const char * scanLine = (const char *) image.constScanLine(line); + + msg.data[0] = line; + msg.data.replace(1, 12, scanLine, 12); + + send(msg); +} + +void MetaWatch::updateLines(int mode, const QImage& image, int lineA, int lineB) +{ + Message msg(WriteBuffer, QByteArray(26, 0), mode & 0xF); + const char * scanLine = (const char *) image.constScanLine(lineA); + + msg.data[0] = lineA; + msg.data.replace(1, 12, scanLine, 12); + + scanLine = (const char *) image.constScanLine(lineB); + msg.data[13] = lineB; + msg.data.replace(14, 12, scanLine, 12); + + send(msg); +} + +void MetaWatch::updateLines(int mode, const QImage& image, const QVector& lines) +{ + int lineCount = lines.count(true); + int lineA = -1; + + if (lineCount == 0) return; + + for (int line = 0; line < lines.size(); line++) { + if (lines[line]) { + lineCount--; +#if SINGLE_LINE_UPDATE + updateLine(mode, image, line); + continue; +#endif + if (lineA >= 0) { + // We have a pair of lines to send. + updateLines(mode, image, lineA, line); + lineA = -1; + } else if (lineCount > 0) { + // Still another line to send. + lineA = line; + } else { + updateLine(mode, image, line); + break; // No more lines + } + } + } +} + +void MetaWatch::configureWatchMode(int mode, int timeout, bool invert) +{ + Message msg(ConfigureMode, QByteArray(2, 0), mode & 0xF); + msg.data[0] = timeout; + msg.data[1] = invert ? 1 : 0; + send(msg); +} + +void MetaWatch::updateDisplay(int mode, bool copy) +{ + Message msg(UpdateDisplay, QByteArray(), + (copy ? 0x10 : 0) | (mode & 0xF)); + send(msg); +} + +void MetaWatch::loadTemplate(int mode, int templ) +{ + Message msg(LoadTemplate, QByteArray(1, templ), mode & 0xF); + send(msg); +} + +void MetaWatch::handleStatusChange(const Message &msg) +{ + qDebug() << "watch status changed"; +} + +void MetaWatch::handleButtonEvent(const Message &msg) +{ + if (msg.data.size() < 1) return; + quint8 button = msg.data[0]; + + emit buttonPressed(button); // TODO This is completely broken +} + +void MetaWatch::socketConnected() +{ + qDebug() << "connected"; + _partialReceived.type = NoMessage; + _partialReceived.data.clear(); + _buttonState = 0; + setDateTime(QDateTime::currentDateTime()); + configureWatchMode(1); + emit connected(); +} + +void MetaWatch::socketDisconnected() +{ + _toSend.clear(); + _sendTimer->stop(); + emit disconnected(); +} + +void MetaWatch::socketData() +{ + qint64 dataRead; + + if (_partialReceived.type == 0) { + if (_socket->bytesAvailable() < 4) return; /* Wait for more. */ + char header[4]; + + dataRead = _socket->read(header, 4); + if (dataRead < 4 || header[0] != 0x01) { + qWarning() << "TODO: Resync/Handle Garbage"; + return; + } + + _partialReceived.type = static_cast(header[2]); + _partialReceived.data.resize(header[1] - 6); + _partialReceived.options = header[3]; + } + if (_socket->bytesAvailable() < _partialReceived.data.size() + 2) { + return; /* Wait for more. */ + } + dataRead = _socket->read(_partialReceived.data.data(), _partialReceived.data.size()); + if (dataRead < _partialReceived.data.size()) { + qWarning() << "Short read"; + return; + } + + char tail[2]; + dataRead = _socket->read(tail, 2); + if (dataRead < 2) { + qWarning() << "Short read"; + return; + } + + quint16 realCrc = calcCrc(_partialReceived); + quint16 expectedCrc = tail[1] << 8 | (tail[0] & 0xFFU); + if (realCrc == expectedCrc) { + handleMessage(_partialReceived); + } else { + qWarning() << "CRC error?"; + } + + _partialReceived.data.clear(); + _partialReceived.type = NoMessage; +} + +void MetaWatch::socketError(QBluetoothSocket::SocketError error) +{ + qWarning() << "Socket error:" << error; +} + +void MetaWatch::socketState(QBluetoothSocket::SocketState error) +{ + qDebug() << "socket is in" << error; +} + +void MetaWatch::timedSend() +{ + if (_toSend.count() > 0) { + realSend(_toSend.dequeue()); + } + if (_toSend.count() == 0) { + _sendTimer->stop(); + } +} + +void MetaWatch::realSend(const Message &msg) +{ + const int msgSize = msg.data.size(); + QByteArray data; + quint16 crc; + + data.resize(msgSize + 6); + data[0] = 0x01; + data[1] = msgSize + 6; + data[2] = msg.type; + data[3] = msg.options; + data.replace(4, msgSize, msg.data); + crc = calcCrc(data, msgSize + 4); + data[msgSize+4] = crc & 0xFF; + data[msgSize+5] = crc >> 8; + + //qDebug() << "Sending" << data.toHex(); + + _socket->write(data); +} diff --git a/metawatch.h b/metawatch.h new file mode 100644 index 0000000..2ec56f9 --- /dev/null +++ b/metawatch.h @@ -0,0 +1,117 @@ +#ifndef METAWATCH_H +#define METAWATCH_H + +#include +#include +#include +#include +#include "watch.h" + +using QTM_PREPEND_NAMESPACE(QBluetoothSocket); +using QTM_PREPEND_NAMESPACE(QBluetoothAddress); + +namespace sowatch +{ + +class MetaWatch : public Watch +{ + Q_OBJECT + Q_ENUMS(MessageType) + +public: + explicit MetaWatch(const QBluetoothAddress& address, QObject *parent = 0); + + QPaintEngine* paintEngine() const; + + QString model() const; + bool isConnected() const; + bool busy() const; + void update(const QList& rects); + void clear(bool white = false); + void vibrate(bool on); + + void setDateTime(const QDateTime& dateTime); + + enum MessageType { + NoMessage = 0, + GetDeviceType = 0x01, + GetDeviceTypeResponse = 0x02, + GetInformationString = 0x03, + GetInformationStringResponse = 0x04, + AdvanceWatchHands = 0x20, + SetVibrateMode = 0x23, + SetRealTimeClock = 0x26, + GetRealTimeClock = 0x27, + GetRealTimeClockResponse = 0x28, + StatusChangeEvent = 0x33, + ButtonEvent = 0x34, + WriteBuffer = 0x40, + ConfigureMode = 0x41, + ConfigureIdleBufferSize = 0x42, + UpdateDisplay = 0x43, + LoadTemplate = 0x44, + EnableButton = 0x46, + DisableButton = 0x47, + ReadButtonConfiguration = 0x48, + ReadButtonConfigurationResponse = 0x49, + BatteryConfiguration = 0x53, + LowBatteryWarning = 0x54, + LowBatteryBluetoothOff = 0x55, + ReadBatteryVoltage = 0x56, + ReadBatteryVoltageResponse = 0x57, + Accelerometer = 0xea + }; + +protected: + QBluetoothSocket* _socket; + + struct Message { + MessageType type; + quint8 options; + QByteArray data; + Message(MessageType ntype = NoMessage, QByteArray ndata = QByteArray(), quint8 noptions = 0) : + type(ntype), options(noptions), data(ndata) + { + + } + }; + + QQueue _toSend; + QTimer* _sendTimer; + Message _partialReceived; + + quint8 _buttonState; + + static const quint8 bitRevTable[16]; + static const quint16 crcTable[256]; + quint16 calcCrc(const QByteArray& data, int size); + quint16 calcCrc(const Message& msg); + + void send(const Message& msg); + void handleMessage(const Message& msg); + + void updateLine(int mode, const QImage& image, int line); + void updateLines(int mode, const QImage& image, int lineA, int lineB); + void updateLines(int mode, const QImage& image, const QVector& lines); + void configureWatchMode(int mode, int timeout = 10, bool invert = false); + void updateDisplay(int mode, bool copy = true); + void loadTemplate(int mode, int templ); + + void handleStatusChange(const Message& msg); + void handleButtonEvent(const Message& msg); + +protected slots: + void socketConnected(); + void socketDisconnected(); + void socketData(); + void socketError(QBluetoothSocket::SocketError error); + void socketState(QBluetoothSocket::SocketState error); + void timedSend(); + +private: + void realSend(const Message& msg); +}; + +} + +#endif // METAWATCH_H diff --git a/metawatchpaintengine.cpp b/metawatchpaintengine.cpp new file mode 100644 index 0000000..96e78a7 --- /dev/null +++ b/metawatchpaintengine.cpp @@ -0,0 +1,75 @@ +#include "metawatch.h" +#include "metawatchpaintengine.h" + +using namespace sowatch; + +MetaWatchPaintEngine::MetaWatchPaintEngine(MetaWatch* watch, QImage* image) : + WatchPaintEngine(watch, image), _watch(watch), + _imageRect(image->rect()) +{ +} + +void MetaWatchPaintEngine::drawRects(const QRectF *rects, int rectCount) +{ + int i; + for (i = 0; i < rectCount; i++) { + const QRectF& r = rects[i]; + if (_hasBrush && r.toRect() == _imageRect && (_isBrushBlack | _isBrushWhite)) { + _watch->clear(_isBrushWhite); + _damaged = QRegion(); + continue; + } + if (_hasBrush) { + damageRect(r); + } + if (_hasPen) { + damagePenStroke(QLineF(r.left(), r.top(), r.right(), r.top())); + damagePenStroke(QLineF(r.right(), r.top(), r.right(), r.bottom())); + damagePenStroke(QLineF(r.left(), r.bottom(), r.right(), r.bottom())); + damagePenStroke(QLineF(r.left(), r.top(), r.left(), r.bottom())); + } + } + _painter.drawRects(rects, rectCount); +} + +void MetaWatchPaintEngine::drawRects(const QRect *rects, int rectCount) +{ + int i; + for (i = 0; i < rectCount; i++) { + const QRect& r = rects[i]; + if (_hasBrush && r == _imageRect && (_isBrushBlack | _isBrushWhite)) { + _watch->clear(_isBrushWhite); + _damaged = QRegion(); + continue; + } + if (_hasBrush) { + damageRect(r); + } + if (_hasPen) { + damagePenStroke(QLine(r.left(), r.top(), r.right(), r.top())); + damagePenStroke(QLine(r.right(), r.top(), r.right(), r.bottom())); + damagePenStroke(QLine(r.left(), r.bottom(), r.right(), r.bottom())); + damagePenStroke(QLine(r.left(), r.top(), r.left(), r.bottom())); + } + } + + _painter.drawRects(rects, rectCount); +} + +void MetaWatchPaintEngine::updateState(const QPaintEngineState &state) +{ + WatchPaintEngine::updateState(state); + if (state.state() & QPaintEngine::DirtyBrush) { + QBrush brush = state.brush(); + _isBrushBlack = false; + _isBrushWhite = false; + if (brush.style() == Qt::SolidPattern) { + const QColor color = brush.color(); + if (color == Qt::black) { + _isBrushBlack = true; + } else if (color == Qt::white) { + _isBrushWhite = true; + } + } + } +} diff --git a/metawatchpaintengine.h b/metawatchpaintengine.h new file mode 100644 index 0000000..7c76beb --- /dev/null +++ b/metawatchpaintengine.h @@ -0,0 +1,32 @@ +#ifndef METAWATCHPAINTENGINE_H +#define METAWATCHPAINTENGINE_H + +#include +#include "watchpaintengine.h" + +namespace sowatch +{ + +class MetaWatch; + +/** This WatchPaintEngine accelerates fillRects by using the MetaWatch's template command. */ +class MetaWatchPaintEngine : public WatchPaintEngine +{ +public: + explicit MetaWatchPaintEngine(MetaWatch* watch, QImage* image); + + void drawRects(const QRectF *rects, int rectCount); + void drawRects(const QRect *rects, int rectCount); + + void updateState(const QPaintEngineState &state); + +protected: + MetaWatch* _watch; + QRect _imageRect; + bool _isBrushBlack; + bool _isBrushWhite; +}; + +} + +#endif // METAWATCHPAINTENGINE_H diff --git a/metawatchsimulator.cpp b/metawatchsimulator.cpp new file mode 100644 index 0000000..1cf7def --- /dev/null +++ b/metawatchsimulator.cpp @@ -0,0 +1,72 @@ +#include +#include + +#include "metawatchsimulator.h" + +#define SIMULATE_DAMAGES 1 + +using namespace sowatch; + +MetaWatchSimulator::MetaWatchSimulator(QObject *parent) : + WatchSimulator(QImage(96, 96, QImage::Format_Mono), parent), + _screen(96, 96), + _form(new MetaWatchSimulatorForm) +{ + _form->showNormal(); + connect(_form, SIGNAL(destroyed()), SIGNAL(disconnected())); + connect(_form, SIGNAL(buttonPressed(int)), SIGNAL(buttonPressed(int))); + connect(_form, SIGNAL(buttonReleased(int)), SIGNAL(buttonReleased(int))); +} + +MetaWatchSimulator::~MetaWatchSimulator() +{ + delete _form; +} + +QString MetaWatchSimulator::model() const +{ + return "metawatch-digital"; +} + +bool MetaWatchSimulator::isConnected() const +{ + return true; +} + +bool MetaWatchSimulator::busy() const +{ + return false; +} + +void MetaWatchSimulator::update(const QList &rects) +{ +#if SIMULATE_DAMAGES + const QRect imageRect = _image.rect(); + QPainter p; + QVector rows(96, false); + unsigned total = 0; + + p.begin(&_screen); + foreach (const QRect& rect, rects) { + QRect r = rect.intersect(imageRect); + for (int i = r.top(); i <= r.bottom(); i++) { + rows[i] = true; + } + total += r.width() * r.height(); + + p.drawImage(r, _image, r); + } + p.end(); + + _form->refreshScreen(_screen); + + qDebug() << "updated " << total << " pixels " << rows.count(true) << " lines"; +#else + _form->refreshScreen(QPixmap::fromImage(_image)); +#endif +} + +void MetaWatchSimulator::vibrate(bool on) +{ + +} diff --git a/metawatchsimulator.h b/metawatchsimulator.h new file mode 100644 index 0000000..22ca4b0 --- /dev/null +++ b/metawatchsimulator.h @@ -0,0 +1,30 @@ +#ifndef METAWATCHSIMULATOR_H +#define METAWATCHSIMULATOR_H + +#include "watchsimulator.h" +#include "metawatchsimulatorform.h" + +namespace sowatch { + +class MetaWatchSimulator : public WatchSimulator +{ + Q_OBJECT +public: + explicit MetaWatchSimulator(QObject *parent = 0); + ~MetaWatchSimulator(); + + QString model() const; + bool isConnected() const; + bool busy() const; + + void update(const QList &rects); + void vibrate(bool on); + +protected: + QPixmap _screen; + MetaWatchSimulatorForm* _form; +}; + +} + +#endif // METAWATCHSIMULATOR_H diff --git a/metawatchsimulatorform.cpp b/metawatchsimulatorform.cpp new file mode 100644 index 0000000..f2323bd --- /dev/null +++ b/metawatchsimulatorform.cpp @@ -0,0 +1,82 @@ +#include "metawatchsimulatorform.h" +#include "ui_metawatchsimulatorform.h" + +using namespace sowatch; + +MetaWatchSimulatorForm::MetaWatchSimulatorForm(QWidget* parent) : + QWidget(parent), + ui(new Ui::MetaWatchSimulatorForm) +{ + ui->setupUi(this); +} + +MetaWatchSimulatorForm::~MetaWatchSimulatorForm() +{ + delete ui; +} + +void MetaWatchSimulatorForm::refreshScreen(const QPixmap& pixmap) +{ + ui->lblDisplay->setPixmap(pixmap); + ui->lblDisplay->update(); +} + +void MetaWatchSimulatorForm::btnAPressed() +{ + emit buttonPressed(0); +} + +void MetaWatchSimulatorForm::btnAReleased() +{ + emit buttonReleased(0); +} + +void MetaWatchSimulatorForm::btnBPressed() +{ + emit buttonPressed(1); +} + +void MetaWatchSimulatorForm::btnBReleased() +{ + emit buttonReleased(1); +} + +void MetaWatchSimulatorForm::btnCPressed() +{ + emit buttonPressed(2); +} + +void MetaWatchSimulatorForm::btnCReleased() +{ + emit buttonReleased(2); +} + +void MetaWatchSimulatorForm::btnDPressed() +{ + emit buttonPressed(3); +} + +void MetaWatchSimulatorForm::btnDReleased() +{ + emit buttonReleased(3); +} + +void MetaWatchSimulatorForm::btnEPressed() +{ + emit buttonPressed(4); +} + +void MetaWatchSimulatorForm::btnEReleased() +{ + emit buttonReleased(4); +} + +void MetaWatchSimulatorForm::btnFPressed() +{ + emit buttonPressed(5); +} + +void MetaWatchSimulatorForm::btnFReleased() +{ + emit buttonReleased(5); +} diff --git a/metawatchsimulatorform.h b/metawatchsimulatorform.h new file mode 100644 index 0000000..0b45746 --- /dev/null +++ b/metawatchsimulatorform.h @@ -0,0 +1,46 @@ +#ifndef METAWATCHSIMULATORFORM_H +#define METAWATCHSIMULATORFORM_H + +#include + +namespace Ui { + class MetaWatchSimulatorForm; +} + +namespace sowatch { + +class MetaWatchSimulatorForm : public QWidget +{ + Q_OBJECT + +public: + explicit MetaWatchSimulatorForm(QWidget *parent = 0); + ~MetaWatchSimulatorForm(); + + void refreshScreen(const QPixmap& screen); + +signals: + void buttonPressed(int button); + void buttonReleased(int button); + +protected slots: + void btnAPressed(); + void btnAReleased(); + void btnBPressed(); + void btnBReleased(); + void btnCPressed(); + void btnCReleased(); + void btnDPressed(); + void btnDReleased(); + void btnEPressed(); + void btnEReleased(); + void btnFPressed(); + void btnFReleased(); + +private: + Ui::MetaWatchSimulatorForm *ui; +}; + +} + +#endif // METAWATCHSIMULATORFORM_H diff --git a/metawatchsimulatorform.ui b/metawatchsimulatorform.ui new file mode 100644 index 0000000..39280b3 --- /dev/null +++ b/metawatchsimulatorform.ui @@ -0,0 +1,294 @@ + + + MetaWatchSimulatorForm + + + + 0 + 0 + 262 + 113 + + + + MetaWatch-Digital Simulator + + + + + + + + A + + + + + + + B + + + + + + + C + + + + + + + + + + 0 + 0 + + + + + + + Qt::AlignCenter + + + + + + + + + D + + + + + + + E + + + + + + + F + + + + + + + + + + + btnA + pressed() + MetaWatchSimulatorForm + btnAPressed() + + + 44 + 20 + + + 105 + 4 + + + + + btnA + released() + MetaWatchSimulatorForm + btnAReleased() + + + 71 + 21 + + + 4 + 10 + + + + + btnB + pressed() + MetaWatchSimulatorForm + btnBPressed() + + + 68 + 57 + + + 98 + 75 + + + + + btnB + released() + MetaWatchSimulatorForm + btnBReleased() + + + 86 + 56 + + + 98 + 58 + + + + + btnC + pressed() + MetaWatchSimulatorForm + btnCPressed() + + + 37 + 90 + + + 73 + 108 + + + + + btnC + released() + MetaWatchSimulatorForm + btnCReleased() + + + 21 + 89 + + + 19 + 105 + + + + + btnD + pressed() + MetaWatchSimulatorForm + btnDPressed() + + + 203 + 18 + + + 205 + 5 + + + + + btnD + released() + MetaWatchSimulatorForm + btnDReleased() + + + 244 + 22 + + + 258 + 21 + + + + + btnE + pressed() + MetaWatchSimulatorForm + btnEPressed() + + + 237 + 50 + + + 256 + 51 + + + + + btnE + released() + MetaWatchSimulatorForm + btnEReleased() + + + 174 + 46 + + + 164 + 40 + + + + + btnF + pressed() + MetaWatchSimulatorForm + btnFPressed() + + + 236 + 89 + + + 258 + 87 + + + + + btnF + released() + MetaWatchSimulatorForm + btnFReleased() + + + 185 + 90 + + + 187 + 108 + + + + + + btnAPressed() + btnAReleased() + btnBPressed() + btnBReleased() + btnCPressed() + btnCReleased() + btnDPressed() + btnDReleased() + btnEPressed() + btnEReleased() + btnFPressed() + btnFReleased() + + diff --git a/qt.png b/qt.png new file mode 100644 index 0000000..eaedc3d Binary files /dev/null and b/qt.png differ diff --git a/qtc_packaging/debian_harmattan/README b/qtc_packaging/debian_harmattan/README new file mode 100644 index 0000000..be8bc96 --- /dev/null +++ b/qtc_packaging/debian_harmattan/README @@ -0,0 +1,6 @@ +The Debian Package sowatch +---------------------------- + +Comments regarding the Package + + -- Javier Fri, 16 Sep 2011 03:19:28 +0200 diff --git a/qtc_packaging/debian_harmattan/changelog b/qtc_packaging/debian_harmattan/changelog new file mode 100644 index 0000000..4ce001f --- /dev/null +++ b/qtc_packaging/debian_harmattan/changelog @@ -0,0 +1,5 @@ +sowatch (0.0.1) unstable; urgency=low + + * Initial Release. + + -- Javier Fri, 16 Sep 2011 03:19:28 +0200 diff --git a/qtc_packaging/debian_harmattan/compat b/qtc_packaging/debian_harmattan/compat new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/qtc_packaging/debian_harmattan/compat @@ -0,0 +1 @@ +7 diff --git a/qtc_packaging/debian_harmattan/control b/qtc_packaging/debian_harmattan/control new file mode 100644 index 0000000..b43216c --- /dev/null +++ b/qtc_packaging/debian_harmattan/control @@ -0,0 +1,14 @@ +Source: sowatch +Section: user/other +Priority: optional +Maintainer: Javier +Build-Depends: debhelper (>= 5), libqt4-dev +Standards-Version: 3.7.3 +Homepage: + +Package: sowatch +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: + +XSBC-Maemo-Display-Name: sowatch diff --git a/qtc_packaging/debian_harmattan/copyright b/qtc_packaging/debian_harmattan/copyright new file mode 100644 index 0000000..5a99d4d --- /dev/null +++ b/qtc_packaging/debian_harmattan/copyright @@ -0,0 +1,40 @@ +This package was debianized by Javier on +Fri, 16 Sep 2011 03:19:28 +0200. + +It was downloaded from + +Upstream Author(s): + + + + +Copyright: + + + + +License: + + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This package 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this package; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +On Debian systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. + +The Debian packaging is (C) 2011, Javier and +is licensed under the GPL, see above. + + +# Please also look if there are files or directories which have a +# different copyright/license attached and list them here. diff --git a/qtc_packaging/debian_harmattan/rules b/qtc_packaging/debian_harmattan/rules new file mode 100755 index 0000000..da02eb9 --- /dev/null +++ b/qtc_packaging/debian_harmattan/rules @@ -0,0 +1,91 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + + + + +configure: configure-stamp +configure-stamp: + dh_testdir + # qmake PREFIX=/usr# Uncomment this line for use without Qt Creator + + touch configure-stamp + + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + # Add here commands to compile the package. + # $(MAKE) # Uncomment this line for use without Qt Creator + #docbook-to-man debian/sowatch.sgml > sowatch.1 + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + $(MAKE) clean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/sowatch. + $(MAKE) INSTALL_ROOT="$(CURDIR)"/debian/sowatch install + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples +# dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_makeshlibs + dh_installdeb + # dh_shlibdeps # Uncomment this line for use without Qt Creator + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/sowatch.h b/sowatch.h new file mode 100644 index 0000000..79c631c --- /dev/null +++ b/sowatch.h @@ -0,0 +1,11 @@ +#ifndef SOWATCH_H +#define SOWATCH_H + +#include "watch.h" +#include "watchlet.h" +#include "graphicswatchlet.h" +#include "declarativewatchlet.h" +#include "watchserver.h" +#include "watchsimulator.h" + +#endif // SOWATCH_H diff --git a/sowatch.pro b/sowatch.pro new file mode 100644 index 0000000..402a17f --- /dev/null +++ b/sowatch.pro @@ -0,0 +1,76 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2011-09-12T20:48:51 +# +#------------------------------------------------- + +QT += core gui declarative + +CONFIG += mobility +MOBILITY += connectivity + +TARGET = sowatch +TEMPLATE = app + + +SOURCES += main.cpp\ + watchmanager.cpp \ + watchserver.cpp \ + watch.cpp \ + watchsimulator.cpp \ + metawatchsimulatorform.cpp \ + metawatchsimulator.cpp \ + watchlet.cpp \ + testwatchlet.cpp \ + watchpaintengine.cpp \ + graphicswatchlet.cpp \ + declarativewatchlet.cpp \ + testdeclarativewatchlet.cpp \ + declarativewatchwrapper.cpp \ + metawatch.cpp \ + metawatchpaintengine.cpp + +HEADERS += \ + watchmanager.h \ + watchserver.h \ + watch.h \ + watchsimulator.h \ + metawatchsimulatorform.h \ + metawatchsimulator.h \ + watchlet.h \ + testwatchlet.h \ + watchpaintengine.h \ + graphicswatchlet.h \ + declarativewatchlet.h \ + testdeclarativewatchlet.h \ + declarativewatchwrapper.h \ + metawatch.h \ + sowatch.h \ + metawatchpaintengine.h + +FORMS += \ + metawatchsimulatorform.ui + +OTHER_FILES += \ + testdeclarativewatchlet.qml \ + qtc_packaging/debian_harmattan/rules \ + qtc_packaging/debian_harmattan/README \ + qtc_packaging/debian_harmattan/copyright \ + qtc_packaging/debian_harmattan/control \ + qtc_packaging/debian_harmattan/compat \ + qtc_packaging/debian_harmattan/changelog \ + qt.png + +RESOURCES += \ + tests.qrc + +contains(MEEGO_EDITION,harmattan) { + target.path = /opt/sowatch/bin + INSTALLS += target +} + + + + + + diff --git a/testdeclarativewatchlet.cpp b/testdeclarativewatchlet.cpp new file mode 100644 index 0000000..432d525 --- /dev/null +++ b/testdeclarativewatchlet.cpp @@ -0,0 +1,9 @@ +#include "testdeclarativewatchlet.h" + +using namespace sowatch; + +TestDeclarativeWatchlet::TestDeclarativeWatchlet(WatchServer* server) : + DeclarativeWatchlet(server, "com.javispedro.sowatch.testdeclarativewatchlet") +{ + setSource(QUrl("qrc:/testdeclarativewatchlet.qml")); +} diff --git a/testdeclarativewatchlet.h b/testdeclarativewatchlet.h new file mode 100644 index 0000000..b7b6dcd --- /dev/null +++ b/testdeclarativewatchlet.h @@ -0,0 +1,19 @@ +#ifndef TESTDECLARATIVEWATCHLET_H +#define TESTDECLARATIVEWATCHLET_H + +#include "declarativewatchlet.h" + +namespace sowatch +{ + +class TestDeclarativeWatchlet : public DeclarativeWatchlet +{ + Q_OBJECT +public: + explicit TestDeclarativeWatchlet(WatchServer* server); + +}; + +} + +#endif // TESTDECLARATIVEWATCHLET_H diff --git a/testdeclarativewatchlet.qml b/testdeclarativewatchlet.qml new file mode 100644 index 0000000..08a3b06 --- /dev/null +++ b/testdeclarativewatchlet.qml @@ -0,0 +1,104 @@ +import QtQuick 1.0 +import com.javispedro.sowatch 1.0 + +Rectangle { + width: 96 + height: 96 + + Image { + anchors.centerIn: parent + source: "qt.png" + + transform: Rotation { + axis { x : 0; y : 1; z: 0 } + origin { x: width / 4; y: 0; } + RotationAnimation on angle { + loops: Animation.Infinite + running: true + duration: 10000 + from: 0 + to: 360 + } + } + } + + /*color: "white" + + Rectangle { + width: 90 + height: 90 + + color: "black" + + Rectangle { + width: 10 + height: 10 + + x: 0 + y: 0 + + SequentialAnimation on y { + loops: Animation.Infinite + NumberAnimation { from: 0; to: 60; duration: 1000 } + NumberAnimation { from: 60; to: 0; duration: 1000 } + } + } + + Rectangle { + width: 10 + height: 10 + + x: 80 + y: 00 + + SequentialAnimation on y { + loops: Animation.Infinite + NumberAnimation { from: 0; to: 60; duration: 1000 } + } + } + + Rectangle { + width: 10 + height: 10 + x: 10 + y: 10 + + SequentialAnimation on visible { + loops: Animation.Infinite + PropertyAnimation { to: false; duration: 1000 } + PropertyAnimation { to: true; duration: 1000 } + } + } + + Rectangle { + id: big1 + width: 20 + height: 20 + x: 40 + y: 40 + + color: "white" + visible: false + } + + Text { + id: name + x: 20 + text: "hello" + color: "white" + + SequentialAnimation on y { + loops: Animation.Infinite + NumberAnimation { from: 0; to: 60; duration: 1000 } + NumberAnimation { from: 60; to: 0; duration: 1000 } + } + } + + Connections { + target: watch + onButtonPressed: { + console.log(button); + } + } + }*/ +} diff --git a/tests.qrc b/tests.qrc new file mode 100644 index 0000000..c86f361 --- /dev/null +++ b/tests.qrc @@ -0,0 +1,6 @@ + + + testdeclarativewatchlet.qml + qt.png + + diff --git a/testwatchlet.cpp b/testwatchlet.cpp new file mode 100644 index 0000000..b29eb0f --- /dev/null +++ b/testwatchlet.cpp @@ -0,0 +1,37 @@ +#include +#include + +#include "testwatchlet.h" +#include "watch.h" + +using namespace sowatch; + +TestWatchlet::TestWatchlet(WatchServer* server) : + Watchlet(server, "com.javispedro.sowatch.testwatchlet"), _timer(new QTimer(this)), _y(0) +{ + _timer->setInterval(50); + connect(_timer, SIGNAL(timeout()), SLOT(interv())); +} + +void TestWatchlet::activate() +{ + qDebug() << "test watchlet activated"; + QPainter p(watch()); + p.fillRect(0, 0, watch()->width(), watch()->height(), Qt::white); + _timer->start(); +} + +void TestWatchlet::deactivate() +{ + _timer->stop(); + qDebug() << "test watchlet deactivated"; +} + +void TestWatchlet::interv() +{ + QPainter p(watch()); + //p.fillRect(8, _y, 8, 1, Qt::black); + _y = (_y + 1) % watch()->height(); + p.fillRect(0, _y, _y, 2, Qt::black); + //p.fillRect(0, 0, watch()->width(), watch()->height(), Qt::black); +} diff --git a/testwatchlet.h b/testwatchlet.h new file mode 100644 index 0000000..75568ca --- /dev/null +++ b/testwatchlet.h @@ -0,0 +1,34 @@ +#ifndef TESTWATCHLET_H +#define TESTWATCHLET_H + +#include +#include "watchlet.h" + +namespace sowatch +{ + +class TestWatchlet : public Watchlet +{ + Q_OBJECT +public: + explicit TestWatchlet(WatchServer* server); + + void activate(); + void deactivate(); + +signals: + +public slots: + +protected slots: + void interv(); + +private: + QTimer *_timer; + int _y; + +}; + +} + +#endif // TESTWATCHLET_H diff --git a/watch.cpp b/watch.cpp new file mode 100644 index 0000000..e8da790 --- /dev/null +++ b/watch.cpp @@ -0,0 +1,62 @@ +#include "watch.h" +#include "watchpaintengine.h" + +using namespace sowatch; + +Watch::Watch(const QImage& image, QObject* parent) : + QObject(parent), _image(image), _paintEngine(0) +{ + +} + +Watch::~Watch() +{ + if (_paintEngine) { + delete _paintEngine; + } +} + +QPaintEngine* Watch::paintEngine() const +{ + if (!_paintEngine) { + _paintEngine = new WatchPaintEngine(const_cast(this), + const_cast(&_image)); + } + + return _paintEngine; +} + +int Watch::metric(PaintDeviceMetric metric) const +{ + switch (metric) { + case PdmWidth: + return _image.width(); + case PdmHeight: + return _image.height(); + case PdmWidthMM: + return _image.widthMM(); + case PdmHeightMM: + return _image.heightMM(); + case PdmNumColors: + return _image.numColors(); + case PdmDepth: + return _image.depth(); + case PdmDpiX: + return _image.logicalDpiX(); + case PdmDpiY: + return _image.logicalDpiY(); + case PdmPhysicalDpiX: + return _image.physicalDpiX(); + case PdmPhysicalDpiY: + return _image.physicalDpiY(); + } + + return -1; +} + +void Watch::update(const QRect &rect) +{ + QList rects; + rects << rect; + update(rects); +} diff --git a/watch.h b/watch.h new file mode 100644 index 0000000..3581ada --- /dev/null +++ b/watch.h @@ -0,0 +1,49 @@ +#ifndef WATCH_H +#define WATCH_H + +#include +#include +#include + +namespace sowatch +{ + +class Watch : public QObject, public QPaintDevice +{ + Q_OBJECT + Q_PROPERTY(QString model READ model) + Q_PROPERTY(bool connected READ isConnected) +public: + explicit Watch(const QImage& image, QObject* parent = 0); + ~Watch(); + + QPaintEngine* paintEngine() const; + int metric(PaintDeviceMetric metric) const; + + Q_INVOKABLE virtual QString model() const = 0; + Q_INVOKABLE virtual bool isConnected() const = 0; + + /** Indicates if watch is too busy atm and we should limit frame rate. */ + Q_INVOKABLE virtual bool busy() const = 0; + +signals: + void connected(); + void disconnected(); + void buttonPressed(int button); + void buttonReleased(int button); + +public slots: + virtual void update(const QList& rects) = 0; + virtual void update(const QRect& rect); + virtual void vibrate(bool on) = 0; + +protected: + QImage _image; + mutable QPaintEngine* _paintEngine; + +friend class WatchPaintEngine; +}; + +} + +#endif // WATCH_H diff --git a/watchlet.cpp b/watchlet.cpp new file mode 100644 index 0000000..2e76d5e --- /dev/null +++ b/watchlet.cpp @@ -0,0 +1,25 @@ +#include "watchlet.h" +#include "watchserver.h" + +using namespace sowatch; + +Watchlet::Watchlet(WatchServer *server, const QString& id) : + QObject(server), _id(id), _server(server) +{ + _server->registerWatchlet(this); +} + +WatchServer* Watchlet::server() +{ + return _server; +} + +Watch* Watchlet::watch() +{ + return _server->watch(); +} + +QString Watchlet::id() +{ + return _id; +} diff --git a/watchlet.h b/watchlet.h new file mode 100644 index 0000000..fd2c7f4 --- /dev/null +++ b/watchlet.h @@ -0,0 +1,38 @@ +#ifndef WATCHLET_H +#define WATCHLET_H + +#include + +namespace sowatch +{ + +class Watch; +class WatchServer; + +class Watchlet : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString id READ id) + +public: + explicit Watchlet(WatchServer *server, const QString& id); + + WatchServer* server(); + Watch* watch(); + + QString id(); + +protected: + virtual void activate() = 0; + virtual void deactivate() = 0; + +private: + QString _id; + WatchServer* _server; + +friend class WatchServer; +}; + +} + +#endif // WATCHLET_H diff --git a/watchmanager.cpp b/watchmanager.cpp new file mode 100644 index 0000000..b511a31 --- /dev/null +++ b/watchmanager.cpp @@ -0,0 +1,8 @@ +#include "watchmanager.h" + +using namespace sowatch; + +WatchManager::WatchManager(QObject *parent) : + QObject(parent) +{ +} diff --git a/watchmanager.h b/watchmanager.h new file mode 100644 index 0000000..6d945ff --- /dev/null +++ b/watchmanager.h @@ -0,0 +1,23 @@ +#ifndef WATCHMANAGER_H +#define WATCHMANAGER_H + +#include + +namespace sowatch +{ + +class WatchManager : public QObject +{ + Q_OBJECT +public: + explicit WatchManager(QObject *parent = 0); + +signals: + +public slots: + +}; + +} + +#endif // WATCHMANAGER_H diff --git a/watchpaintengine.cpp b/watchpaintengine.cpp new file mode 100644 index 0000000..f506da7 --- /dev/null +++ b/watchpaintengine.cpp @@ -0,0 +1,295 @@ +#include +#include + +#include "watch.h" +#include "watchpaintengine.h" + +using namespace sowatch; + +WatchPaintEngine::WatchPaintEngine(Watch* watch, QImage* image) + : QPaintEngine(QPaintEngine::AllFeatures), + _watch(watch), _painter(), + _hasPen(false), _hasBrush(false), _clipEnabled(false) +{ +} + +bool WatchPaintEngine::begin(QPaintDevice *pdev) +{ + _damaged = QRegion(); + _watch = static_cast(pdev); + + return _painter.begin(&_watch->_image); +} + +bool WatchPaintEngine::end() +{ + bool ret = _painter.end(); + if (ret) { + _watch->update(_damaged.rects().toList()); + } + return ret; +} + +void WatchPaintEngine::damageRect(const QRect &r) +{ + if (_clipEnabled) { + _damaged += _clipRegion.intersect(r); + } else { + _damaged += r; + } +} + +void WatchPaintEngine::damageRect(const QRectF &r) +{ + damageRect(r.toRect()); +} + +void WatchPaintEngine::damagePenStroke(const QLineF &line) +{ + if (!_hasPen) return; + + const qreal a = line.angle(); + const qreal sn = sinf(a); + const qreal cs = cosf(a); + const qreal w = _penWidth = 0.0 ? 1.0 : _penWidth; + const qreal x1 = line.x1(); + const qreal x2 = line.x2(); + const qreal y1 = line.x1(); + const qreal y2 = line.y2(); + + damageRect(QRectF(x1-(w*sn/2.0f), y1+(w*cs/2.0f), x2+(w*sn/2.0f), y2-(w*cs/2.0f)).normalized()); +} + +void WatchPaintEngine::updateClipRegion(const QRegion& region, Qt::ClipOperation op) +{ + switch(op) { + case Qt::NoClip: + _clipEnabled = false; + break; + case Qt::ReplaceClip: + _clipEnabled = true; + _clipRegion = region; + break; + case Qt::IntersectClip: + _clipEnabled = true; + _clipRegion &= region; + break; + case Qt::UniteClip: + _clipEnabled = true; + _clipRegion |= region; + break; + } +} + +void WatchPaintEngine::drawEllipse(const QRectF &r) +{ +} + +void WatchPaintEngine::drawEllipse(const QRect &r) +{ +} + +void WatchPaintEngine::drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags) +{ + damageRect(r); + _painter.drawImage(r, pm, sr, flags); +} + +void WatchPaintEngine::drawLines(const QLineF *lines, int lineCount) +{ + int i; + for (i = 0; i < lineCount; i++) { + const QLineF& line = lines[i]; + damagePenStroke(line); + } + _painter.drawLines(lines, lineCount); +} + +void WatchPaintEngine::drawLines(const QLine *lines, int lineCount) +{ + int i; + for (i = 0; i < lineCount; i++) { + const QLine& line = lines[i]; + damagePenStroke(line); + } + _painter.drawLines(lines, lineCount); +} + +void WatchPaintEngine::drawPath(const QPainterPath &path) +{ + damageRect(path.boundingRect()); + _painter.drawPath(path); +} + +void WatchPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) +{ + damageRect(r); + _painter.drawPixmap(r, pm, sr); +} + +void WatchPaintEngine::drawPoints(const QPointF *points, int pointCount) +{ + const qreal penWidth = _painter.pen().widthF(); + int i; + for (i = 0; i < pointCount; i++) { + const QPointF& p = points[i]; + damageRect(QRect(p.x() - penWidth/2, p.y() - penWidth/2, + p.x() + penWidth/2, p.y() + penWidth/2)); + } + _painter.drawPoints(points, pointCount); +} + +void WatchPaintEngine::drawPoints(const QPoint *points, int pointCount) +{ + const qreal penWidth = _painter.pen().widthF(); + int i; + for (i = 0; i < pointCount; i++) { + const QPoint& p = points[i]; + damageRect(QRect(p.x() - penWidth/2, p.y() - penWidth/2, + p.x() + penWidth/2, p.y() + penWidth/2)); + } + _painter.drawPoints(points, pointCount); +} + +void WatchPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) +{ + QPolygonF p(pointCount); + int i; + for (i = 0; i < pointCount; i++) { + p[i] = points[i]; + } + damageRect(p.boundingRect()); + _painter.drawPolygon(points, pointCount, + mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill); +} + +void WatchPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) +{ + QPolygon p(pointCount); + int i; + for (i = 0; i < pointCount; i++) { + p[i] = points[i]; + } + damageRect(p.boundingRect()); + _painter.drawPolygon(points, pointCount, + mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill); +} + +void WatchPaintEngine::drawRects(const QRectF *rects, int rectCount) +{ + int i; + for (i = 0; i < rectCount; i++) { + const QRectF& r = rects[i]; + if (_hasBrush) { + damageRect(r); + } + if (_hasPen) { + damagePenStroke(QLineF(r.left(), r.top(), r.right(), r.top())); + damagePenStroke(QLineF(r.right(), r.top(), r.right(), r.bottom())); + damagePenStroke(QLineF(r.left(), r.bottom(), r.right(), r.bottom())); + damagePenStroke(QLineF(r.left(), r.top(), r.left(), r.bottom())); + } + } + _painter.drawRects(rects, rectCount); +} + +void WatchPaintEngine::drawRects(const QRect *rects, int rectCount) +{ + int i; + for (i = 0; i < rectCount; i++) { + const QRect& r = rects[i]; + if (_hasBrush) { + damageRect(r); + } + if (_hasPen) { + damagePenStroke(QLine(r.left(), r.top(), r.right(), r.top())); + damagePenStroke(QLine(r.right(), r.top(), r.right(), r.bottom())); + damagePenStroke(QLine(r.left(), r.bottom(), r.right(), r.bottom())); + damagePenStroke(QLine(r.left(), r.top(), r.left(), r.bottom())); + } + } + + _painter.drawRects(rects, rectCount); +} + +void WatchPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) +{ + const qreal height = textItem.ascent() + textItem.descent(); + damageRect(QRect(p.x(), p.y(), p.x() + textItem.width(), p.y() + height)); + _painter.drawTextItem(p, textItem); +} + +void WatchPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s) +{ + damageRect(r); + _painter.drawTiledPixmap(r, pixmap, s); +} + +QPaintEngine::Type WatchPaintEngine::type() const +{ + return QPaintEngine::Raster; +} + +void WatchPaintEngine::updateState(const QPaintEngineState &state) +{ + const QPaintEngine::DirtyFlags flags = state.state(); + if (flags & QPaintEngine::DirtyBackground) + { + _painter.setBackground(state.backgroundBrush()); + } + if (flags & QPaintEngine::DirtyBackgroundMode) + { + _painter.setBackgroundMode(state.backgroundMode()); + } + if (flags & QPaintEngine::DirtyBrush) + { + QBrush brush = state.brush(); + _hasBrush = brush.style() != Qt::NoBrush; + _painter.setBrush(brush); + } + if (flags & QPaintEngine::DirtyBrushOrigin) + { + _painter.setBrushOrigin(state.brushOrigin()); + } + if (flags & QPaintEngine::DirtyClipEnabled) + { + _clipEnabled = state.isClipEnabled(); + _painter.setClipping(_clipEnabled); + } + if (flags & QPaintEngine::DirtyClipPath) + { + _clipEnabled = true; + QRegion region = state.clipPath().boundingRect().toRect(); + updateClipRegion(region, state.clipOperation()); + _painter.setClipPath(state.clipPath(), state.clipOperation()); + } + if (flags & QPaintEngine::DirtyClipRegion) + { + _clipEnabled = true; + updateClipRegion(state.clipRegion(), state.clipOperation()); + _painter.setClipRegion(state.clipRegion(), state.clipOperation()); + } + if (flags & QPaintEngine::DirtyCompositionMode) + { + _painter.setCompositionMode(state.compositionMode()); + } + if (flags & QPaintEngine::DirtyFont) + { + _painter.setFont(state.font()); + } + if (flags & QPaintEngine::DirtyHints) + { + _painter.setRenderHints(state.renderHints()); + } + if (flags & QPaintEngine::DirtyPen) + { + QPen pen = state.pen(); + _hasPen = pen.style() != Qt::NoPen; + _penWidth = pen.widthF(); + _painter.setPen(pen); + } + if (flags & QPaintEngine::DirtyTransform) + { + _painter.setTransform(state.transform()); + } +} diff --git a/watchpaintengine.h b/watchpaintengine.h new file mode 100644 index 0000000..59010c0 --- /dev/null +++ b/watchpaintengine.h @@ -0,0 +1,59 @@ +#ifndef WATCHPAINTENGINE_H +#define WATCHPAINTENGINE_H + +#include + +namespace sowatch +{ + +class Watch; + +class WatchPaintEngine : public QPaintEngine +{ +public: + WatchPaintEngine(Watch* watch, QImage* image); + + bool begin(QPaintDevice *pdev); + bool end(); + + void drawEllipse(const QRectF &r); + void drawEllipse(const QRect &r); + void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags); + void drawLines(const QLineF *lines, int lineCount); + void drawLines(const QLine *lines, int lineCount); + void drawPath(const QPainterPath &path); + void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); + void drawPoints(const QPointF *points, int pointCount); + void drawPoints(const QPoint *points, int pointCount); + void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); + void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode); + void drawRects(const QRectF *rects, int rectCount); + void drawRects(const QRect *rects, int rectCount); + void drawTextItem(const QPointF &p, const QTextItem &textItem); + void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); + + Type type() const; + void updateState(const QPaintEngineState &state); + +protected: + void damageRect(const QRect& r); + void damageRect(const QRectF& r); + void damagePenStroke(const QLineF& line); + void updateClipRegion(const QRegion& region, Qt::ClipOperation op); + + Watch* _watch; + QPainter _painter; + QRegion _damaged; + + bool _hasPen; + qreal _penWidth; + + bool _hasBrush; + + bool _clipEnabled; + QRegion _clipRegion; +}; + +} + +#endif // WATCHPAINTENGINE_H diff --git a/watchserver.cpp b/watchserver.cpp new file mode 100644 index 0000000..ad49995 --- /dev/null +++ b/watchserver.cpp @@ -0,0 +1,57 @@ +#include "watch.h" +#include "watchlet.h" +#include "watchserver.h" + +using namespace sowatch; + +WatchServer::WatchServer(Watch* watch, QObject* parent) : + QObject(parent), _watch(watch), _currentWatchlet(0) +{ + connect(_watch, SIGNAL(connected()), SLOT(watchConnected())); + connect(_watch, SIGNAL(disconnected()), SLOT(watchDisconnected())); +} + +Watch* WatchServer::watch() +{ + return _watch; +} + +void WatchServer::runWatchlet(const QString& id) +{ + if (_currentWatchlet) { + closeWatchlet(); + } + _currentWatchlet = watchlets[id]; + if (_watch->isConnected()) { + _currentWatchlet->activate(); + } +} + +void WatchServer::closeWatchlet() +{ + Q_ASSERT(_currentWatchlet != 0); + if (_watch->isConnected()) { + _currentWatchlet->deactivate(); + } + _currentWatchlet = 0; +} + +void WatchServer::registerWatchlet(Watchlet *watchlet) +{ + Q_ASSERT(watchlet->_server == this); + watchlets[watchlet->id()] = watchlet; +} + +void WatchServer::watchConnected() +{ + if (_currentWatchlet) { + _currentWatchlet->activate(); + } +} + +void WatchServer::watchDisconnected() +{ + if (_currentWatchlet) { + _currentWatchlet->deactivate(); + } +} diff --git a/watchserver.h b/watchserver.h new file mode 100644 index 0000000..78454d4 --- /dev/null +++ b/watchserver.h @@ -0,0 +1,46 @@ +#ifndef WATCHSERVER_H +#define WATCHSERVER_H + +#include +#include + +namespace sowatch +{ + +class Watch; +class Watchlet; + +class WatchServer : public QObject +{ + Q_OBJECT + Q_PROPERTY(Watch* watch READ watch) +public: + explicit WatchServer(Watch* watch, QObject* parent = 0); + + Watch* watch(); + + void runWatchlet(const QString& id); + void closeWatchlet(); + +signals: + +public slots: + +protected: + Watch* _watch; + Watchlet* _currentWatchlet; + + QMap watchlets; + + void registerWatchlet(Watchlet *watchlet); + +protected slots: + void watchConnected(); + void watchDisconnected(); + +friend class Watchlet; +}; + +} + +#endif // WATCHSERVER_H diff --git a/watchsimulator.cpp b/watchsimulator.cpp new file mode 100644 index 0000000..464f3a5 --- /dev/null +++ b/watchsimulator.cpp @@ -0,0 +1,11 @@ +#include + +#include "watchsimulator.h" + +using namespace sowatch; + +WatchSimulator::WatchSimulator(const QImage& image, QObject* parent) : + Watch(image, parent) +{ + +} diff --git a/watchsimulator.h b/watchsimulator.h new file mode 100644 index 0000000..564118c --- /dev/null +++ b/watchsimulator.h @@ -0,0 +1,20 @@ +#ifndef WATCHSIMULATOR_H +#define WATCHSIMULATOR_H + +#include + +#include "watch.h" + +namespace sowatch +{ + +class WatchSimulator : public Watch +{ + Q_OBJECT +public: + explicit WatchSimulator(const QImage& image, QObject *parent = 0); +}; + +} + +#endif // WATCHSIMULATOR_H -- cgit v1.2.3