Start color code parsing, hook up input to actually send it. ITS ALIVE
This commit is contained in:
parent
efbf4ba81d
commit
7561c4ccc9
12 changed files with 196 additions and 61 deletions
|
@ -39,7 +39,8 @@ OTHER_FILES += qml/harbour-weechatrelay.qml \
|
||||||
qml/js/uniqid.js \
|
qml/js/uniqid.js \
|
||||||
qml/pages/BufferView.qml \
|
qml/pages/BufferView.qml \
|
||||||
qml/js/config.js \
|
qml/js/config.js \
|
||||||
qml/pages/BufferList.qml
|
qml/pages/BufferList.qml \
|
||||||
|
qml/js/weechatcolors.js
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
src/relayconnection.h \
|
src/relayconnection.h \
|
||||||
|
|
|
@ -16,19 +16,28 @@
|
||||||
.import "moment.js" as M
|
.import "moment.js" as M
|
||||||
.import "debug.js" as D
|
.import "debug.js" as D
|
||||||
|
|
||||||
var _textListComponent = Qt.createComponent('../pages/TextListComponent.qml');
|
|
||||||
|
|
||||||
function Buffer(pointer, number, name, title) {
|
function Buffer(pointer, number, name, title) {
|
||||||
this.pointer = pointer;
|
this.pointer = pointer;
|
||||||
this.number = number;
|
this.number = number;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
|
|
||||||
this.textList = _textListComponent.createObject(_parentPage);
|
// A listmodel where we put the messages of this buffer
|
||||||
|
this.textList = Qt.createQmlObject('import QtQuick 2.0; ListModel {}',
|
||||||
|
_parentPage);
|
||||||
|
|
||||||
// Add line to this buffer
|
// Add line to this buffer
|
||||||
this.add = function(moment, str) {
|
this.add = function(moment, prefix, str) {
|
||||||
this.textList.add(moment, str);
|
this.textList.insert(0, {
|
||||||
|
time: moment.format('HH:mm:ss'),
|
||||||
|
prefix: prefix,
|
||||||
|
str: str
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send input into this buffer
|
||||||
|
this.input = function(str) {
|
||||||
|
EQ.command('input 0x' + this.pointer + ' ' + str);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +48,7 @@ var _buffers = {};
|
||||||
// according to buffer number whenever requested
|
// according to buffer number whenever requested
|
||||||
var _buffersList = [];
|
var _buffersList = [];
|
||||||
|
|
||||||
// Page that will own all of our textlistcomponents
|
// Page that will own all of our textlistmodels
|
||||||
var _parentPage = null;
|
var _parentPage = null;
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,7 +138,7 @@ function lineAdded(data) {
|
||||||
|
|
||||||
var buffer = data.buffer;
|
var buffer = data.buffer;
|
||||||
var date = M.moment(data.date);
|
var date = M.moment(data.date);
|
||||||
_buffers[buffer].add(date, data.message);
|
_buffers[buffer].add(date, data.prefix, data.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _sortBuffersList() {
|
function _sortBuffersList() {
|
||||||
|
|
|
@ -61,13 +61,13 @@ function init(connectionHandler, pageStack) {
|
||||||
|
|
||||||
// Signal handlers for incoming data from connection
|
// Signal handlers for incoming data from connection
|
||||||
function newEvent(id, data) {
|
function newEvent(id, data) {
|
||||||
D.d("Event received: " + id);
|
D.c("Event received: " + id);
|
||||||
D.d(JSON.stringify(data));
|
D.c(JSON.stringify(data));
|
||||||
EQ.handleEvent(id, data);
|
EQ.handleEvent(id, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDisplayDebugData(str) {
|
function onDisplayDebugData(str) {
|
||||||
D.d(str);
|
D.c(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onConnected() {
|
function onConnected() {
|
||||||
|
@ -89,7 +89,7 @@ function onSslError(errorStrings,
|
||||||
startDate,
|
startDate,
|
||||||
expiryDate,
|
expiryDate,
|
||||||
digest) {
|
digest) {
|
||||||
D.d("SSL verification error when connecting");
|
D.d("SSL verification error when connecting!");
|
||||||
|
|
||||||
sslVerifyDialog = ps.push("../pages/SslVerifyDialog.qml",
|
sslVerifyDialog = ps.push("../pages/SslVerifyDialog.qml",
|
||||||
{
|
{
|
||||||
|
@ -106,7 +106,9 @@ function onSslError(errorStrings,
|
||||||
|
|
||||||
function connect(connObj) {
|
function connect(connObj) {
|
||||||
debugViewPage = ps.replace("../pages/BufferView.qml");
|
debugViewPage = ps.replace("../pages/BufferView.qml");
|
||||||
bufferListPage = ps.pushAttached("../pages/BufferList.qml");
|
bufferListPage = ps.pushAttached("../pages/BufferList.qml", {
|
||||||
|
bufferViewPage: debugViewPage
|
||||||
|
});
|
||||||
B.setDebugPage(debugViewPage);
|
B.setDebugPage(debugViewPage);
|
||||||
D.d("Connecting...");
|
D.d("Connecting...");
|
||||||
|
|
||||||
|
@ -175,7 +177,7 @@ function clearConnection() {
|
||||||
|
|
||||||
// Send a command to the WeeChat server
|
// Send a command to the WeeChat server
|
||||||
function send(str) {
|
function send(str) {
|
||||||
D.d("Sending command: " + str);
|
D.c("Sending command: " + str);
|
||||||
handler.send(str);
|
handler.send(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ var _buffer = null;
|
||||||
// Write a line to the debug view (will go to console if debug view isn't open)
|
// Write a line to the debug view (will go to console if debug view isn't open)
|
||||||
function debug(str) {
|
function debug(str) {
|
||||||
if (_buffer !== undefined && _buffer !== null) {
|
if (_buffer !== undefined && _buffer !== null) {
|
||||||
_buffer.add(M.moment(), str);
|
_buffer.add(M.moment(), 'DEBUG', str);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log(str);
|
console.log(str);
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
var _pendingEvents = {};
|
var _pendingEvents = {};
|
||||||
|
|
||||||
function handleEvent(id, data) {
|
function handleEvent(id, data) {
|
||||||
//D.d("Handling " + id);
|
|
||||||
//D.d(JSON.stringify(_pendingEvents));
|
|
||||||
if (id in _pendingEvents) {
|
if (id in _pendingEvents) {
|
||||||
var c = _pendingEvents[id];
|
var c = _pendingEvents[id];
|
||||||
c.callback(data);
|
c.callback(data);
|
||||||
|
@ -44,8 +42,6 @@ function command(command, callback) {
|
||||||
if (read_write) {
|
if (read_write) {
|
||||||
var id = UID.get();
|
var id = UID.get();
|
||||||
command = "(" + id + ") " + command;
|
command = "(" + id + ") " + command;
|
||||||
|
|
||||||
//D.d("Adding handler for " + id);
|
|
||||||
addHandler(id, callback, true);
|
addHandler(id, callback, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
|
/*
|
||||||
|
* © Mikko Ahlroth 2014
|
||||||
|
* WeeCRApp is open source software. For licensing information, please check
|
||||||
|
* the LICENCE file.
|
||||||
|
*/
|
||||||
|
|
||||||
// Miscellaneous functions for generic use
|
// Miscellaneous functions for generic use
|
||||||
|
|
||||||
|
.pragma library
|
||||||
|
|
||||||
// Escape strings for Text.StyledText
|
// Escape strings for Text.StyledText
|
||||||
function escapeStyled(string) {
|
function escapeStyled(string) {
|
||||||
string = string.replace('&', '&');
|
string = string.replace('&', '&');
|
||||||
|
@ -11,3 +19,8 @@ function escapeStyled(string) {
|
||||||
function colored(color, string) {
|
function colored(color, string) {
|
||||||
return '<font color="' + color + '">' + string + '</font>';
|
return '<font color="' + color + '">' + string + '</font>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return bold text
|
||||||
|
function bold(string) {
|
||||||
|
return '<b>' + string + '</b>';
|
||||||
|
}
|
||||||
|
|
126
qml/js/weechatcolors.js
Normal file
126
qml/js/weechatcolors.js
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* © Mikko Ahlroth 2014
|
||||||
|
* WeeCRApp is open source software. For licensing information, please check
|
||||||
|
* the LICENCE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Utilities for parsing WeeChat color codes sent
|
||||||
|
// in the relay protocol
|
||||||
|
|
||||||
|
.pragma library
|
||||||
|
|
||||||
|
// Protocol specific constants
|
||||||
|
// Starting bytes
|
||||||
|
var COLOR_START = 0x19;
|
||||||
|
var SET_ATTR = 0x1A;
|
||||||
|
var REMOVE_ATTR = 0x1B;
|
||||||
|
var RESET = 0x1C;
|
||||||
|
|
||||||
|
var START_RE = /^(\u0019|\u001a|\u001b|\u001c)/;
|
||||||
|
|
||||||
|
// Attributes
|
||||||
|
var ATTR_BOLD = '*';
|
||||||
|
var ATTR_REVERSE = '!';
|
||||||
|
var ATTR_ITALIC = '/';
|
||||||
|
var ATTR_UNDERLINE = '_';
|
||||||
|
var ATTR_KEEP = '|';
|
||||||
|
|
||||||
|
// A section of text which has the given attributes:
|
||||||
|
// fgColor: Foreground color as weechat color number
|
||||||
|
// bgColor: Background color --//--
|
||||||
|
// attributes: List of attributes from the selection above,
|
||||||
|
// except ATTR_KEEP.
|
||||||
|
function CodedTextSection(str, fgColor, bgColor, attributes) {
|
||||||
|
this.str = str;
|
||||||
|
this.fgColor = fgColor;
|
||||||
|
this.bgColor = bgColor;
|
||||||
|
this.attributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse coded text and return list of CodedTextSection
|
||||||
|
function parseString(str) {
|
||||||
|
var out = [];
|
||||||
|
var currentMode = null;
|
||||||
|
var currentFg = null;
|
||||||
|
var currentBg = null;
|
||||||
|
var currentAttr = [];
|
||||||
|
var currentStr = null;
|
||||||
|
var parts = str.split(START_RE);
|
||||||
|
|
||||||
|
for (var i = 0; i < parts.length; ++i) {
|
||||||
|
// Every even index is a content part
|
||||||
|
if ((i % 2) === 0) {
|
||||||
|
// The first part won't have any extra info
|
||||||
|
if (i !== 0) {
|
||||||
|
switch (currentMode) {
|
||||||
|
case COLOR_START:
|
||||||
|
currentStr = parseColorStart(parts[i], currentFg, currentBg, currentAttr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SET_ATTR:
|
||||||
|
currentStr = parseSetAttr(parts[i], currentFg, currentBg, currentAttr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOVE_ATTR:
|
||||||
|
currentStr = parseRemoveAttr(parts[i], currentFg, currentBg, currentAttr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RESET:
|
||||||
|
currentFg = null;
|
||||||
|
currentBg = null;
|
||||||
|
currentAttr = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.push(new CodedTextSection(currentStr, currentFg, currentBg, currentAttr));
|
||||||
|
}
|
||||||
|
// The odd parts give the next mode
|
||||||
|
else {
|
||||||
|
currentMode = parts[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseColorStart(part, currentFg, currentBg, currentAttr) {
|
||||||
|
var data = null;
|
||||||
|
|
||||||
|
if (part[0] === 'F') {
|
||||||
|
data = parseASTD(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseSetAttr(part, currentFg, currentBg, currentAttr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseRemoveAttr(part, currentFg, currentBg, currentAttr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse STD (standard color), removing it from the beginning of string
|
||||||
|
function parseSTD(str) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse EXT (extended color), --//--
|
||||||
|
function parseEXT(str) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse attributes + STD
|
||||||
|
function parseASTD(str) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse attributes + EXT
|
||||||
|
function parseAEXT(str) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse single attribute
|
||||||
|
function parseATTR(str) {
|
||||||
|
|
||||||
|
}
|
|
@ -107,7 +107,9 @@ Dialog {
|
||||||
spacing: Theme.paddingLarge
|
spacing: Theme.paddingLarge
|
||||||
|
|
||||||
DialogHeader {
|
DialogHeader {
|
||||||
title: "Save"
|
title: "Add connection"
|
||||||
|
acceptText: "Save"
|
||||||
|
cancelText: "Cancel"
|
||||||
}
|
}
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
|
|
|
@ -12,6 +12,8 @@ import "../js/buffers.js" as B
|
||||||
Page {
|
Page {
|
||||||
id: bufferListPage
|
id: bufferListPage
|
||||||
|
|
||||||
|
property BufferView bufferViewPage : null;
|
||||||
|
|
||||||
onVisibleChanged: bufferList.updateList();
|
onVisibleChanged: bufferList.updateList();
|
||||||
|
|
||||||
SilicaListView {
|
SilicaListView {
|
||||||
|
@ -20,10 +22,13 @@ Page {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
function updateList() {
|
function updateList() {
|
||||||
|
bufferListModel.clear();
|
||||||
|
|
||||||
var buffers = B.getBuffersByNumber();
|
var buffers = B.getBuffersByNumber();
|
||||||
|
|
||||||
for (var i = 0; i < buffers.length; ++i) {
|
for (var i = 0; i < buffers.length; ++i) {
|
||||||
bufferListModel.append({
|
bufferListModel.append({
|
||||||
|
pointer: buffers[i].pointer,
|
||||||
number: buffers[i].number,
|
number: buffers[i].number,
|
||||||
name: buffers[i].name
|
name: buffers[i].name
|
||||||
});
|
});
|
||||||
|
@ -85,7 +90,9 @@ Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
console.log(name + " clicked!");
|
var buffer = B.getBuffer(pointer);
|
||||||
|
bufferViewPage.changeBuffer(buffer);
|
||||||
|
pageStack.navigateBack(PageStackAction.Animated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ import "."
|
||||||
|
|
||||||
import "../js/debug.js" as D
|
import "../js/debug.js" as D
|
||||||
import "../js/connection.js" as C
|
import "../js/connection.js" as C
|
||||||
import "../js/moment.js" as M
|
|
||||||
import "../js/buffers.js" as B
|
|
||||||
|
|
||||||
Page {
|
Page {
|
||||||
id: bufferViewPage
|
id: bufferViewPage
|
||||||
|
@ -14,6 +12,7 @@ Page {
|
||||||
property string pointer: "";
|
property string pointer: "";
|
||||||
property int number: 0;
|
property int number: 0;
|
||||||
property string name: "";
|
property string name: "";
|
||||||
|
property var buffer: null;
|
||||||
|
|
||||||
function setTitle(str) {
|
function setTitle(str) {
|
||||||
topic.title = str;
|
topic.title = str;
|
||||||
|
@ -27,20 +26,12 @@ Page {
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeBuffer(buffer) {
|
function changeBuffer(newBuffer) {
|
||||||
var textList = buffer.textList;
|
// Replace current list model with new list
|
||||||
|
D.c('Changing buffer to ' + newBuffer.name);
|
||||||
// Replace current list with new list
|
buffer = newBuffer;
|
||||||
textListItem = textList;
|
topic.title = newBuffer.title;
|
||||||
textListItem.parent = mainFlickable;
|
textList.model = newBuffer.textList;
|
||||||
// HOW DO I SHOT WEB
|
|
||||||
//mainFlickable.children.push(textListItem);
|
|
||||||
//textListItem.anchors.top = topic.bottom;
|
|
||||||
//textListItem.anchors.bottom = inpuRow.top;
|
|
||||||
textListItem.width = textListItem.parent.width;
|
|
||||||
textListItem.clip = true;
|
|
||||||
|
|
||||||
topic.title = buffer.title;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SilicaFlickable {
|
SilicaFlickable {
|
||||||
|
@ -53,8 +44,13 @@ Page {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
TextListComponent {
|
||||||
id: textListItem
|
id: textList
|
||||||
|
|
||||||
|
anchors.top: topic.bottom
|
||||||
|
anchors.bottom: inputRow.top
|
||||||
|
width: parent.width
|
||||||
|
clip: true
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
|
@ -71,11 +67,10 @@ Page {
|
||||||
placeholderText: "Type here"
|
placeholderText: "Type here"
|
||||||
|
|
||||||
EnterKey.enabled: text.length > 0
|
EnterKey.enabled: text.length > 0
|
||||||
//EnterKey.iconSource: "image://theme/icon-m-send"
|
EnterKey.iconSource: "image://theme/icon-m-enter-accept"
|
||||||
EnterKey.onClicked: {
|
EnterKey.onClicked: {
|
||||||
var buffer = B.getBuffer(inputField.text);
|
|
||||||
if (buffer !== null) {
|
if (buffer !== null) {
|
||||||
changeBuffer(buffer);
|
buffer.input(inputField.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
inputField.text = "";
|
inputField.text = "";
|
||||||
|
|
|
@ -49,7 +49,8 @@ Dialog {
|
||||||
|
|
||||||
DialogHeader {
|
DialogHeader {
|
||||||
id: connectHeader
|
id: connectHeader
|
||||||
title: "Connect"
|
title: "SSL Verification"
|
||||||
|
acceptText: "Connect"
|
||||||
cancelText: "Disconnect"
|
cancelText: "Disconnect"
|
||||||
width: sslVerifyFlickable.width
|
width: sslVerifyFlickable.width
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,28 +6,11 @@ import "../js/utils.js" as U
|
||||||
SilicaListView {
|
SilicaListView {
|
||||||
id: textList
|
id: textList
|
||||||
|
|
||||||
function add(datetime, str) {
|
|
||||||
var snap = false;
|
|
||||||
if (textList.atYBeginning) {
|
|
||||||
snap = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The top is the latest message on the bottom
|
|
||||||
textListModel.insert(0, { "time": datetime.format('HH:mm:ss'), "str": str });
|
|
||||||
|
|
||||||
if (snap) {
|
|
||||||
textList.positionViewAtBeginning();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function colorTime(time) {
|
function colorTime(time) {
|
||||||
return U.colored(Theme.secondaryHighlightColor,
|
return U.colored(Theme.secondaryHighlightColor,
|
||||||
time);
|
time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
model: ListModel { id: textListModel }
|
|
||||||
|
|
||||||
verticalLayoutDirection: ListView.BottomToTop
|
verticalLayoutDirection: ListView.BottomToTop
|
||||||
|
|
||||||
delegate: ListItem {
|
delegate: ListItem {
|
||||||
|
@ -36,7 +19,7 @@ SilicaListView {
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
id: messageLabel
|
id: messageLabel
|
||||||
text: colorTime(time) + " " + U.escapeStyled(str)
|
text: colorTime(time) + " " + U.bold(U.escapeStyled(prefix)) + " " + U.escapeStyled(str)
|
||||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
color: Theme.highlightColor
|
color: Theme.highlightColor
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue