diff --git a/harbour-weechatrelay.pro b/harbour-weechatrelay.pro
index 852ca71..207a364 100644
--- a/harbour-weechatrelay.pro
+++ b/harbour-weechatrelay.pro
@@ -39,7 +39,8 @@ OTHER_FILES += qml/harbour-weechatrelay.qml \
qml/js/uniqid.js \
qml/pages/BufferView.qml \
qml/js/config.js \
- qml/pages/BufferList.qml
+ qml/pages/BufferList.qml \
+ qml/js/weechatcolors.js
HEADERS += \
src/relayconnection.h \
diff --git a/qml/js/buffers.js b/qml/js/buffers.js
index 5658e20..0e7a778 100644
--- a/qml/js/buffers.js
+++ b/qml/js/buffers.js
@@ -16,19 +16,28 @@
.import "moment.js" as M
.import "debug.js" as D
-var _textListComponent = Qt.createComponent('../pages/TextListComponent.qml');
-
function Buffer(pointer, number, name, title) {
this.pointer = pointer;
this.number = number;
this.name = name;
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
- this.add = function(moment, str) {
- this.textList.add(moment, str);
+ this.add = function(moment, prefix, 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
var _buffersList = [];
-// Page that will own all of our textlistcomponents
+// Page that will own all of our textlistmodels
var _parentPage = null;
@@ -129,7 +138,7 @@ function lineAdded(data) {
var buffer = data.buffer;
var date = M.moment(data.date);
- _buffers[buffer].add(date, data.message);
+ _buffers[buffer].add(date, data.prefix, data.message);
}
function _sortBuffersList() {
diff --git a/qml/js/connection.js b/qml/js/connection.js
index a09913b..e037a38 100644
--- a/qml/js/connection.js
+++ b/qml/js/connection.js
@@ -61,13 +61,13 @@ function init(connectionHandler, pageStack) {
// Signal handlers for incoming data from connection
function newEvent(id, data) {
- D.d("Event received: " + id);
- D.d(JSON.stringify(data));
+ D.c("Event received: " + id);
+ D.c(JSON.stringify(data));
EQ.handleEvent(id, data);
}
function onDisplayDebugData(str) {
- D.d(str);
+ D.c(str);
}
function onConnected() {
@@ -89,7 +89,7 @@ function onSslError(errorStrings,
startDate,
expiryDate,
digest) {
- D.d("SSL verification error when connecting");
+ D.d("SSL verification error when connecting!");
sslVerifyDialog = ps.push("../pages/SslVerifyDialog.qml",
{
@@ -106,7 +106,9 @@ function onSslError(errorStrings,
function connect(connObj) {
debugViewPage = ps.replace("../pages/BufferView.qml");
- bufferListPage = ps.pushAttached("../pages/BufferList.qml");
+ bufferListPage = ps.pushAttached("../pages/BufferList.qml", {
+ bufferViewPage: debugViewPage
+ });
B.setDebugPage(debugViewPage);
D.d("Connecting...");
@@ -175,7 +177,7 @@ function clearConnection() {
// Send a command to the WeeChat server
function send(str) {
- D.d("Sending command: " + str);
+ D.c("Sending command: " + str);
handler.send(str);
}
diff --git a/qml/js/debug.js b/qml/js/debug.js
index d575afe..f926428 100644
--- a/qml/js/debug.js
+++ b/qml/js/debug.js
@@ -14,7 +14,7 @@ var _buffer = null;
// Write a line to the debug view (will go to console if debug view isn't open)
function debug(str) {
if (_buffer !== undefined && _buffer !== null) {
- _buffer.add(M.moment(), str);
+ _buffer.add(M.moment(), 'DEBUG', str);
}
else {
console.log(str);
diff --git a/qml/js/eventqueue.js b/qml/js/eventqueue.js
index b03b867..2d8795e 100644
--- a/qml/js/eventqueue.js
+++ b/qml/js/eventqueue.js
@@ -17,8 +17,6 @@
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);
@@ -44,8 +42,6 @@ function command(command, callback) {
if (read_write) {
var id = UID.get();
command = "(" + id + ") " + command;
-
- //D.d("Adding handler for " + id);
addHandler(id, callback, true);
}
diff --git a/qml/js/utils.js b/qml/js/utils.js
index 2ff10c3..98bec2e 100644
--- a/qml/js/utils.js
+++ b/qml/js/utils.js
@@ -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
+.pragma library
+
// Escape strings for Text.StyledText
function escapeStyled(string) {
string = string.replace('&', '&');
@@ -11,3 +19,8 @@ function escapeStyled(string) {
function colored(color, string) {
return '' + string + '';
}
+
+// Return bold text
+function bold(string) {
+ return '' + string + '';
+}
diff --git a/qml/js/weechatcolors.js b/qml/js/weechatcolors.js
new file mode 100644
index 0000000..8798333
--- /dev/null
+++ b/qml/js/weechatcolors.js
@@ -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) {
+
+}
diff --git a/qml/pages/AddConnection.qml b/qml/pages/AddConnection.qml
index 33368c6..27e724b 100644
--- a/qml/pages/AddConnection.qml
+++ b/qml/pages/AddConnection.qml
@@ -107,7 +107,9 @@ Dialog {
spacing: Theme.paddingLarge
DialogHeader {
- title: "Save"
+ title: "Add connection"
+ acceptText: "Save"
+ cancelText: "Cancel"
}
TextField {
diff --git a/qml/pages/BufferList.qml b/qml/pages/BufferList.qml
index 7370722..f0b0008 100644
--- a/qml/pages/BufferList.qml
+++ b/qml/pages/BufferList.qml
@@ -12,6 +12,8 @@ import "../js/buffers.js" as B
Page {
id: bufferListPage
+ property BufferView bufferViewPage : null;
+
onVisibleChanged: bufferList.updateList();
SilicaListView {
@@ -20,10 +22,13 @@ Page {
anchors.fill: parent
function updateList() {
+ bufferListModel.clear();
+
var buffers = B.getBuffersByNumber();
for (var i = 0; i < buffers.length; ++i) {
bufferListModel.append({
+ pointer: buffers[i].pointer,
number: buffers[i].number,
name: buffers[i].name
});
@@ -85,7 +90,9 @@ Page {
}
onClicked: {
- console.log(name + " clicked!");
+ var buffer = B.getBuffer(pointer);
+ bufferViewPage.changeBuffer(buffer);
+ pageStack.navigateBack(PageStackAction.Animated);
}
}
diff --git a/qml/pages/BufferView.qml b/qml/pages/BufferView.qml
index e70e8c6..462c1cf 100644
--- a/qml/pages/BufferView.qml
+++ b/qml/pages/BufferView.qml
@@ -4,8 +4,6 @@ import "."
import "../js/debug.js" as D
import "../js/connection.js" as C
-import "../js/moment.js" as M
-import "../js/buffers.js" as B
Page {
id: bufferViewPage
@@ -14,6 +12,7 @@ Page {
property string pointer: "";
property int number: 0;
property string name: "";
+ property var buffer: null;
function setTitle(str) {
topic.title = str;
@@ -27,20 +26,12 @@ Page {
isConnected = false;
}
- function changeBuffer(buffer) {
- var textList = buffer.textList;
-
- // Replace current list with new list
- textListItem = textList;
- textListItem.parent = mainFlickable;
- // 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;
+ function changeBuffer(newBuffer) {
+ // Replace current list model with new list
+ D.c('Changing buffer to ' + newBuffer.name);
+ buffer = newBuffer;
+ topic.title = newBuffer.title;
+ textList.model = newBuffer.textList;
}
SilicaFlickable {
@@ -53,8 +44,13 @@ Page {
anchors.top: parent.top
}
- Item {
- id: textListItem
+ TextListComponent {
+ id: textList
+
+ anchors.top: topic.bottom
+ anchors.bottom: inputRow.top
+ width: parent.width
+ clip: true
}
Row {
@@ -71,11 +67,10 @@ Page {
placeholderText: "Type here"
EnterKey.enabled: text.length > 0
- //EnterKey.iconSource: "image://theme/icon-m-send"
+ EnterKey.iconSource: "image://theme/icon-m-enter-accept"
EnterKey.onClicked: {
- var buffer = B.getBuffer(inputField.text);
if (buffer !== null) {
- changeBuffer(buffer);
+ buffer.input(inputField.text);
}
inputField.text = "";
diff --git a/qml/pages/SslVerifyDialog.qml b/qml/pages/SslVerifyDialog.qml
index 2c90d13..c02ca1f 100644
--- a/qml/pages/SslVerifyDialog.qml
+++ b/qml/pages/SslVerifyDialog.qml
@@ -49,7 +49,8 @@ Dialog {
DialogHeader {
id: connectHeader
- title: "Connect"
+ title: "SSL Verification"
+ acceptText: "Connect"
cancelText: "Disconnect"
width: sslVerifyFlickable.width
}
diff --git a/qml/pages/TextListComponent.qml b/qml/pages/TextListComponent.qml
index e7a28f3..8610c3b 100644
--- a/qml/pages/TextListComponent.qml
+++ b/qml/pages/TextListComponent.qml
@@ -6,28 +6,11 @@ import "../js/utils.js" as U
SilicaListView {
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) {
return U.colored(Theme.secondaryHighlightColor,
time);
}
-
- model: ListModel { id: textListModel }
-
verticalLayoutDirection: ListView.BottomToTop
delegate: ListItem {
@@ -36,7 +19,7 @@ SilicaListView {
Label {
id: messageLabel
- text: colorTime(time) + " " + U.escapeStyled(str)
+ text: colorTime(time) + " " + U.bold(U.escapeStyled(prefix)) + " " + U.escapeStyled(str)
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
color: Theme.highlightColor