diff --git a/harbour-weechatrelay.pro b/harbour-weechatrelay.pro index b746dcc..8450134 100644 --- a/harbour-weechatrelay.pro +++ b/harbour-weechatrelay.pro @@ -33,7 +33,10 @@ OTHER_FILES += qml/harbour-weechatrelay.qml \ qml/js/utils.js \ qml/js/moment.js \ qml/js/connection.js \ - qml/js/debug.js + qml/js/debug.js \ + qml/js/buffers.js \ + qml/js/eventqueue.js \ + qml/js/uniqid.js HEADERS += \ src/relayconnection.h \ diff --git a/qml/js/buffers.js b/qml/js/buffers.js new file mode 100644 index 0000000..b4b9e6a --- /dev/null +++ b/qml/js/buffers.js @@ -0,0 +1,55 @@ +/* + * © Mikko Ahlroth 2014 + * WeeCRApp is open source software. For licensing information, please check + * the LICENCE file. + */ + +/* + * + */ + +.pragma library + +.import "eventqueue.js" as EQ +.import "debug.js" as D + +function Buffer(id) { + this.id = id; + this.window = null; +} + +var _buffers = {}; + + +function init() { + EQ.addHandler("__weecrapp_ready", connected); +} + + +function connected() { + EQ.command("hdata buffer:gui_buffers(*) name,number", bufferListData); + EQ.command("sync"); +} + +function disconnected() { + +} + + + +function bufferListData(data) { + D.d("Got buffer list data:"); + + data = data[0]; + var buffers = data.objectSets; + + for (var i = 0; i < buffers.length; ++i) { + D.d(buffers[i].number + " " + buffers[i].name); + + //EQ.command("sync " + buffers[i].name + " buffer,nicklist"); + } +} + +function bufferSyncData(data) { + +} diff --git a/qml/js/connection.js b/qml/js/connection.js index e66f6f8..b6f28f1 100644 --- a/qml/js/connection.js +++ b/qml/js/connection.js @@ -3,6 +3,8 @@ .import harbour.weechatrelay.qsslcertificateinfo 1.0 as QSCI .import "storage.js" as S .import "debug.js" as D +.import "eventqueue.js" as EQ +.import "buffers.js" as B /* * © Mikko Ahlroth 2014 @@ -30,30 +32,45 @@ var sslVerifyDialog = null; function init(connectionHandler, pageStack) { handler = connectionHandler; ps = pageStack; + + // Register to receive all send events to actually send them to the backend + // This is done so we can avoid cyclic imports + EQ.addHandler("__weecrapp_send", function(str) { + send(str); + }); + + // Wait for init reply to let system know it's ready to send + EQ.addHandler("init", function() { + EQ.handleEvent("__weecrapp_ready"); + }); + + B.init(); } // Signal handlers for incoming data from connection function newEvent(id, data) { - debugViewPage.display("Event received: " + id); - debugViewPage.display(JSON.stringify(data)); - _handleEvent(id, data); + D.d("Event received: " + id); + D.d(JSON.stringify(data)); + EQ.handleEvent(id, data); } function onDisplayDebugData(str) { - debugViewPage.display(str); + D.d(str); } function onConnected() { connected = true; debugViewPage.connected(); - debug("Connected"); + D.d("Connected"); + EQ.handleEvent("__weecrapp_connected"); } function onDisconnected() { connected = false; debugViewPage.disconnected(); - debug("Disconnected"); + D.d("Disconnected"); + EQ.handleEvent("__weecrapp_disconnected"); } function onSslError(errorStrings, @@ -61,7 +78,7 @@ function onSslError(errorStrings, startDate, expiryDate, digest) { - debug("SSL verification error when connecting"); + D.d("SSL verification error when connecting"); sslVerifyDialog = ps.push("../pages/SslVerifyDialog.qml", { @@ -78,7 +95,8 @@ function onSslError(errorStrings, function connect(connObj) { debugViewPage = ps.replace("../pages/DebugView.qml"); - debug("Connecting..."); + D.setDebugPage(debugViewPage); + D.d("Connecting..."); var connType = (connObj.type === "ssl") ? CH.ConnectionHandler.SSL @@ -111,13 +129,13 @@ function disconnect() { } function reconnect() { - debug("Reconnecting..."); + D.d("Reconnecting..."); handler.reconnect(); } // Reconnect, accepting the previously failed certificate function reconnectWithFailed() { - debug("Reconnecting..."); + D.d("Reconnecting..."); handler.reconnectWithFailed(); } @@ -142,31 +160,12 @@ function clearConnection() { handler.clearData(); } -// Write a line to the debug view (will go to console if debug view isn't open) -function debug(str) { - if (debugViewPage !== null) { - debugViewPage.display(str); - } - else { - console.log(str); - } +// Send a command to the WeeChat server +function send(str) { + D.d("Sending command: " + str); + handler.send(str); } - - // Private API -var _pendingEvents = {}; - -function _handleEvent(id, data) { - if (id in _pendingEvents) { - _pendingEvents.id(data); - delete _pendingEvents.id; - } -} - -function _addPendingEvent(id, callback) { - _pendingEvents.id = callback; -} - diff --git a/qml/js/debug.js b/qml/js/debug.js index 68987c9..2af8ab0 100644 --- a/qml/js/debug.js +++ b/qml/js/debug.js @@ -1,13 +1,31 @@ -.pragma library - /* * © Mikko Ahlroth 2014 * WeeCRApp is open source software. For licensing information, please check * the LICENCE file. */ -function d(o) { - console.log(o); +.pragma library + + +var _page = null; + +// Write a line to the debug view (will go to console if debug view isn't open) +function debug(str) { + if (_page != null) { + _page.display(str); + } + else { + console.log(str); + } +} + +function setDebugPage(o) { + _page = o; +} + + +function d(str) { + debug(str); } function e(o) { diff --git a/qml/js/eventqueue.js b/qml/js/eventqueue.js new file mode 100644 index 0000000..7f2ddac --- /dev/null +++ b/qml/js/eventqueue.js @@ -0,0 +1,55 @@ +/* + * © Mikko Ahlroth 2014 + * WeeCRApp is open source software. For licensing information, please check + * the LICENCE file. + */ + +/* + * The event queue allows attaching callbacks to event IDs coming from the + * backend. Callbacks can be one-shot or continuous. + */ + +.pragma library + +.import "uniqid.js" as UID +.import "debug.js" as D + +var _pendingEvents = {}; + +function handleEvent(id, data) { + //D.d("Handling " + id); + //D.d(JSON.stringify(_pendingEvents)); + if (id in _pendingEvents) { + var c = _pendingEvents[id]; + c.callback(data); + + if (c.isOneshot) { + delete _pendingEvents[id]; + } + } +} + +function addHandler(id, callback, isOneshot) { + _pendingEvents[id] = { + "callback": callback, + "isOneshot": !!isOneshot + }; +} + +// Send a command and execute callback when the response arrives +function command(command, callback) { + // If callback is null, don't add an ID + var read_write = !!callback; + + if (read_write) { + var id = UID.get(); + command = "(" + id + ") " + command; + + D.d("Adding handler for " + id); + addHandler(id, callback, true); + } + + handleEvent("__weecrapp_send", command); +} + + diff --git a/qml/js/uniqid.js b/qml/js/uniqid.js new file mode 100644 index 0000000..b32a049 --- /dev/null +++ b/qml/js/uniqid.js @@ -0,0 +1,19 @@ +/* + * © Mikko Ahlroth 2014 + * WeeCRApp is open source software. For licensing information, please check + * the LICENCE file. + */ + +/* + * Unique IDs will be used to match responses with the right + * callbacks. + */ + +.pragma library + +var _counter = 0; +var _prefix = "msg_"; + +function get() { + return _prefix + _counter++; +} diff --git a/src/connectionhandler.cpp b/src/connectionhandler.cpp index ca96e65..4494bbc 100644 --- a/src/connectionhandler.cpp +++ b/src/connectionhandler.cpp @@ -176,6 +176,7 @@ void ConnectionHandler::sendDebugData(QString string) void ConnectionHandler::send(QString string) { + string = string.append("\n"); connection->write(string.toUtf8()); } diff --git a/src/weechat/dynamictypeexception.cpp b/src/weechat/dynamictypeexception.cpp index 353312e..0226fab 100644 --- a/src/weechat/dynamictypeexception.cpp +++ b/src/weechat/dynamictypeexception.cpp @@ -1,3 +1,9 @@ +/* + * © Mikko Ahlroth 2014 + * WeeCRApp is open source software. For licensing information, please check + * the LICENCE file. + */ + #include "dynamictypeexception.h" DynamicTypeException::DynamicTypeException(const std::string &__arg): diff --git a/src/weechat/dynamictypeexception.h b/src/weechat/dynamictypeexception.h index 44eb8cc..d240581 100644 --- a/src/weechat/dynamictypeexception.h +++ b/src/weechat/dynamictypeexception.h @@ -1,3 +1,9 @@ +/* + * © Mikko Ahlroth 2014 + * WeeCRApp is open source software. For licensing information, please check + * the LICENCE file. + */ + #ifndef DYNAMICTYPEEXCEPTION_H #define DYNAMICTYPEEXCEPTION_H diff --git a/src/weechatprotocolhandler.cpp b/src/weechatprotocolhandler.cpp index 7253bf2..4b30b78 100644 --- a/src/weechatprotocolhandler.cpp +++ b/src/weechatprotocolhandler.cpp @@ -23,8 +23,8 @@ WeeChatProtocolHandler::WeeChatProtocolHandler(QObject* parent) : void WeeChatProtocolHandler::initialize(QString password) { emitData("init compression=off,password=" + password); + emitData("(init) info version"); emitData("(starttest) test"); - emitData("sync"); } @@ -64,13 +64,20 @@ QVariant WeeChatProtocolHandler::handleDynamicType(Type type, QDataStream* data) { return QVariant(handleHashTable(data)); } + else if (type == HDATA) { + return QVariant(handleHdata(data)); + } else if (type == ARRAY) { return QVariant(handleArray(data)); } - else + else if (type == INFO) { - throw new DynamicTypeException("Cannot read hdata as QVariant."); + return QVariant(handleInfo(data)); + } + else if (type == INFOLIST) + { + return QVariant(handleInfoList(data)); } } @@ -294,9 +301,15 @@ QVariantMap WeeChatProtocolHandler::handleHdata(QDataStream* data) QVariantMap WeeChatProtocolHandler::handleInfo(QDataStream* data) { // Info consists of a string key and a string value + qDebug() << "Reading info"; QVariantMap ret; - ret.insert("key", handleString(data)); - ret.insert("value", handleString(data)); + QString key = handleString(data); + qDebug() << "Key: " << key; + QString value = handleString(data); + qDebug() << "Value: " << value; + + ret.insert("key", key); + ret.insert("value", value); return ret; } @@ -469,15 +482,6 @@ void WeeChatProtocolHandler::handleBody(QDataStream* data) // EVENTS -// Handle event containing a hdata -void WeeChatProtocolHandler::handleHdataEvent(QString id, QDataStream* data) -{ - qDebug() << "Making hdata!"; - QVariantMap hdata = handleHdata(data); - qDebug() << "Got hdata made!"; - emit newEvent(id, hdata); -} - void WeeChatProtocolHandler::handlePong(QString id, QDataStream* data) { QString response = handleString(data); @@ -502,23 +506,10 @@ void WeeChatProtocolHandler::handleOtherEvent(QString id, QDataStream* data) // read all incoming types into a list QVariantList ret; - // If the first element is a hdata, it is the only element - bool first = true; - while (!data->atEnd()) { Type type = readType(data); - if (first && type == HDATA) - { - handleHdataEvent(id, data); - return; - } - else - { - first = false; - } - QVariant obj = handleDynamicType(type, data); ret.append(obj); } diff --git a/src/weechatprotocolhandler.h b/src/weechatprotocolhandler.h index 3ab79e6..1683613 100644 --- a/src/weechatprotocolhandler.h +++ b/src/weechatprotocolhandler.h @@ -78,7 +78,6 @@ protected: void handlePong(QString id, QDataStream* data); void handleUpgrade(QString id); void handleUpgradeEnded(QString id); - void handleHdataEvent(QString id, QDataStream* data); void handleOtherEvent(QString id, QDataStream* data); bool readingBody;