Fix more protocol bugs and try to organize UI into sensible pieces

This commit is contained in:
Mikko Ahlroth 2014-07-14 00:55:02 +03:00
parent e713439b70
commit 359b3b805b
11 changed files with 218 additions and 66 deletions

View file

@ -33,7 +33,10 @@ OTHER_FILES += qml/harbour-weechatrelay.qml \
qml/js/utils.js \ qml/js/utils.js \
qml/js/moment.js \ qml/js/moment.js \
qml/js/connection.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 += \ HEADERS += \
src/relayconnection.h \ src/relayconnection.h \

55
qml/js/buffers.js Normal file
View file

@ -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) {
}

View file

@ -3,6 +3,8 @@
.import harbour.weechatrelay.qsslcertificateinfo 1.0 as QSCI .import harbour.weechatrelay.qsslcertificateinfo 1.0 as QSCI
.import "storage.js" as S .import "storage.js" as S
.import "debug.js" as D .import "debug.js" as D
.import "eventqueue.js" as EQ
.import "buffers.js" as B
/* /*
* © Mikko Ahlroth 2014 * © Mikko Ahlroth 2014
@ -30,30 +32,45 @@ var sslVerifyDialog = null;
function init(connectionHandler, pageStack) { function init(connectionHandler, pageStack) {
handler = connectionHandler; handler = connectionHandler;
ps = pageStack; 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 // Signal handlers for incoming data from connection
function newEvent(id, data) { function newEvent(id, data) {
debugViewPage.display("Event received: " + id); D.d("Event received: " + id);
debugViewPage.display(JSON.stringify(data)); D.d(JSON.stringify(data));
_handleEvent(id, data); EQ.handleEvent(id, data);
} }
function onDisplayDebugData(str) { function onDisplayDebugData(str) {
debugViewPage.display(str); D.d(str);
} }
function onConnected() { function onConnected() {
connected = true; connected = true;
debugViewPage.connected(); debugViewPage.connected();
debug("Connected"); D.d("Connected");
EQ.handleEvent("__weecrapp_connected");
} }
function onDisconnected() { function onDisconnected() {
connected = false; connected = false;
debugViewPage.disconnected(); debugViewPage.disconnected();
debug("Disconnected"); D.d("Disconnected");
EQ.handleEvent("__weecrapp_disconnected");
} }
function onSslError(errorStrings, function onSslError(errorStrings,
@ -61,7 +78,7 @@ function onSslError(errorStrings,
startDate, startDate,
expiryDate, expiryDate,
digest) { digest) {
debug("SSL verification error when connecting"); D.d("SSL verification error when connecting");
sslVerifyDialog = ps.push("../pages/SslVerifyDialog.qml", sslVerifyDialog = ps.push("../pages/SslVerifyDialog.qml",
{ {
@ -78,7 +95,8 @@ function onSslError(errorStrings,
function connect(connObj) { function connect(connObj) {
debugViewPage = ps.replace("../pages/DebugView.qml"); debugViewPage = ps.replace("../pages/DebugView.qml");
debug("Connecting..."); D.setDebugPage(debugViewPage);
D.d("Connecting...");
var connType = (connObj.type === "ssl") var connType = (connObj.type === "ssl")
? CH.ConnectionHandler.SSL ? CH.ConnectionHandler.SSL
@ -111,13 +129,13 @@ function disconnect() {
} }
function reconnect() { function reconnect() {
debug("Reconnecting..."); D.d("Reconnecting...");
handler.reconnect(); handler.reconnect();
} }
// Reconnect, accepting the previously failed certificate // Reconnect, accepting the previously failed certificate
function reconnectWithFailed() { function reconnectWithFailed() {
debug("Reconnecting..."); D.d("Reconnecting...");
handler.reconnectWithFailed(); handler.reconnectWithFailed();
} }
@ -142,31 +160,12 @@ function clearConnection() {
handler.clearData(); handler.clearData();
} }
// Write a line to the debug view (will go to console if debug view isn't open) // Send a command to the WeeChat server
function debug(str) { function send(str) {
if (debugViewPage !== null) { D.d("Sending command: " + str);
debugViewPage.display(str); handler.send(str);
}
else {
console.log(str);
}
} }
// Private API // 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;
}

View file

@ -1,13 +1,31 @@
.pragma library
/* /*
* © Mikko Ahlroth 2014 * © Mikko Ahlroth 2014
* WeeCRApp is open source software. For licensing information, please check * WeeCRApp is open source software. For licensing information, please check
* the LICENCE file. * the LICENCE file.
*/ */
function d(o) { .pragma library
console.log(o);
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) { function e(o) {

55
qml/js/eventqueue.js Normal file
View file

@ -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);
}

19
qml/js/uniqid.js Normal file
View file

@ -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++;
}

View file

@ -176,6 +176,7 @@ void ConnectionHandler::sendDebugData(QString string)
void ConnectionHandler::send(QString string) void ConnectionHandler::send(QString string)
{ {
string = string.append("\n");
connection->write(string.toUtf8()); connection->write(string.toUtf8());
} }

View file

@ -1,3 +1,9 @@
/*
* © Mikko Ahlroth 2014
* WeeCRApp is open source software. For licensing information, please check
* the LICENCE file.
*/
#include "dynamictypeexception.h" #include "dynamictypeexception.h"
DynamicTypeException::DynamicTypeException(const std::string &__arg): DynamicTypeException::DynamicTypeException(const std::string &__arg):

View file

@ -1,3 +1,9 @@
/*
* © Mikko Ahlroth 2014
* WeeCRApp is open source software. For licensing information, please check
* the LICENCE file.
*/
#ifndef DYNAMICTYPEEXCEPTION_H #ifndef DYNAMICTYPEEXCEPTION_H
#define DYNAMICTYPEEXCEPTION_H #define DYNAMICTYPEEXCEPTION_H

View file

@ -23,8 +23,8 @@ WeeChatProtocolHandler::WeeChatProtocolHandler(QObject* parent) :
void WeeChatProtocolHandler::initialize(QString password) void WeeChatProtocolHandler::initialize(QString password)
{ {
emitData("init compression=off,password=" + password); emitData("init compression=off,password=" + password);
emitData("(init) info version");
emitData("(starttest) test"); emitData("(starttest) test");
emitData("sync");
} }
@ -64,13 +64,20 @@ QVariant WeeChatProtocolHandler::handleDynamicType(Type type, QDataStream* data)
{ {
return QVariant(handleHashTable(data)); return QVariant(handleHashTable(data));
} }
else if (type == HDATA) {
return QVariant(handleHdata(data));
}
else if (type == ARRAY) else if (type == ARRAY)
{ {
return QVariant(handleArray(data)); 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) QVariantMap WeeChatProtocolHandler::handleInfo(QDataStream* data)
{ {
// Info consists of a string key and a string value // Info consists of a string key and a string value
qDebug() << "Reading info";
QVariantMap ret; QVariantMap ret;
ret.insert("key", handleString(data)); QString key = handleString(data);
ret.insert("value", handleString(data)); qDebug() << "Key: " << key;
QString value = handleString(data);
qDebug() << "Value: " << value;
ret.insert("key", key);
ret.insert("value", value);
return ret; return ret;
} }
@ -469,15 +482,6 @@ void WeeChatProtocolHandler::handleBody(QDataStream* data)
// EVENTS // 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) void WeeChatProtocolHandler::handlePong(QString id, QDataStream* data)
{ {
QString response = handleString(data); QString response = handleString(data);
@ -502,23 +506,10 @@ void WeeChatProtocolHandler::handleOtherEvent(QString id, QDataStream* data)
// read all incoming types into a list // read all incoming types into a list
QVariantList ret; QVariantList ret;
// If the first element is a hdata, it is the only element
bool first = true;
while (!data->atEnd()) while (!data->atEnd())
{ {
Type type = readType(data); Type type = readType(data);
if (first && type == HDATA)
{
handleHdataEvent(id, data);
return;
}
else
{
first = false;
}
QVariant obj = handleDynamicType(type, data); QVariant obj = handleDynamicType(type, data);
ret.append(obj); ret.append(obj);
} }

View file

@ -78,7 +78,6 @@ protected:
void handlePong(QString id, QDataStream* data); void handlePong(QString id, QDataStream* data);
void handleUpgrade(QString id); void handleUpgrade(QString id);
void handleUpgradeEnded(QString id); void handleUpgradeEnded(QString id);
void handleHdataEvent(QString id, QDataStream* data);
void handleOtherEvent(QString id, QDataStream* data); void handleOtherEvent(QString id, QDataStream* data);
bool readingBody; bool readingBody;