Moar progress, sorry for no commit message

This commit is contained in:
Mikko Ahlroth 2014-09-22 20:54:52 +03:00
parent b9e9c58848
commit efbf4ba81d
11 changed files with 434 additions and 91 deletions

View file

@ -36,7 +36,10 @@ OTHER_FILES += qml/harbour-weechatrelay.qml \
qml/js/debug.js \
qml/js/buffers.js \
qml/js/eventqueue.js \
qml/js/uniqid.js
qml/js/uniqid.js \
qml/pages/BufferView.qml \
qml/js/config.js \
qml/pages/BufferList.qml
HEADERS += \
src/relayconnection.h \

View file

@ -10,24 +10,75 @@
.pragma library
.import QtQuick 2.0 as QQ
.import "eventqueue.js" as EQ
.import "moment.js" as M
.import "debug.js" as D
function Buffer(id) {
this.id = id;
this.window = null;
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);
// Add line to this buffer
this.add = function(moment, str) {
this.textList.add(moment, str);
};
}
// Dict of buffers, pointer as key, for fast referencing
var _buffers = {};
// List of all buffers for easy iteration, will be sorted ascending
// according to buffer number whenever requested
var _buffersList = [];
// Page that will own all of our textlistcomponents
var _parentPage = null;
function init() {
EQ.addHandler("__weecrapp_ready", connected);
EQ.addHandler("_buffer_line_added", lineAdded);
}
// Set the given page to be used for the core buffer
// This is so that we can reuse the debug page as the
// WeeChat core buffer
function setDebugPage(page) {
_parentPage = page;
var pointer = '0';
var buffer = new Buffer(pointer, 1, 'weechat', 'Debug/core');
_buffers[pointer] = buffer;
_buffersList.push(buffer);
D.setDebugBuffer(buffer);
page.changeBuffer(buffer);
}
function getBuffer(i) {
if (_buffers.hasOwnProperty(i)) {
return _buffers[i];
}
return null;
}
// Return bufferlist sorted by buffer number
function getBuffersByNumber() {
return _buffersList;
}
function connected() {
EQ.command("hdata buffer:gui_buffers(*) name,number", bufferListData);
D.d("Fetching all buffers...");
EQ.command("hdata buffer:gui_buffers(*) full_name,short_name,number,type,title", bufferListData);
EQ.command("sync");
}
@ -38,18 +89,51 @@ 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);
var pointer = buffers[i]['__path'][0];
var number = buffers[i].number;
var name = buffers[i].short_name;
var title = buffers[i].title;
var buffer = null;
//EQ.command("sync " + buffers[i].name + " buffer,nicklist");
if (buffers[i].type !== 0) {
// Currently only sync IRC buffers
continue;
}
// If this buffer is the core, merge it to the debug buffer
if (_parentPage !== null && number === 1 && buffers[i].full_name === 'core.weechat') {
_buffers[pointer] = _buffers['0'];
buffer = _buffers['0'];
buffer.pointer = pointer;
buffer.name = name;
buffer.title = title;
buffer.number = number;
}
else {
buffer = new Buffer(pointer, number, name, title);
_buffers[pointer] = buffer;
_buffersList.push(buffer);
}
}
function bufferSyncData(data) {
_sortBuffersList();
}
// A new line was added to a buffer
function lineAdded(data) {
data = data[0].objectSets[0];
var buffer = data.buffer;
var date = M.moment(data.date);
_buffers[buffer].add(date, data.message);
}
function _sortBuffersList() {
_buffersList.sort(function (a, b) {
return a.number - b.number;
});
}

62
qml/js/config.js Normal file
View file

@ -0,0 +1,62 @@
.pragma library
/*
* © Mikko Ahlroth 2014
* WeeCRApp is open source software. For licensing information, please check
* the LICENCE file.
*/
/*
* This file contains the configuration settings of the app (both hardcoded
* and user-settable) and the API to change them. Connection-specific settings
* are handled in AddConnection.qml.
*/
.import "storage.js" as S
/*
* Constants that cannot be changed
*/
// Regex to match weechat version strings
var SUPPORTED_WEECHAT_VERSIONS = /^(?:0\.4)|(?:1\.0)/;
/*
* All settings and their defaults
*/
var _s = {
timestamp_format: 'HH:mm:ss'
};
var _init = false;
// Load all settings on first config access
if (!_init) {
_loadConfig();
}
function set(key, value) {
_s[key] = value;
var db = S.connect();
S.storeSetting(db, key, value);
}
function get(key) {
return _s[key];
}
function _loadConfig() {
var db = S.connect();
for (var key in _s) {
var val = S.readSetting(db, key, _s[key]);
}
}

View file

@ -5,6 +5,7 @@
.import "debug.js" as D
.import "eventqueue.js" as EQ
.import "buffers.js" as B
.import "config.js" as C
/*
* © Mikko Ahlroth 2014
@ -25,6 +26,7 @@ var ps = null; // The PageStack
// Views
var debugViewPage = null;
var bufferListPage = null;
var sslVerifyDialog = null;
@ -40,11 +42,20 @@ function init(connectionHandler, pageStack) {
});
// Wait for init reply to let system know it's ready to send
EQ.addHandler("init", function() {
EQ.addHandler("init", function(data) {
// Check the received version, it must match the minimum supported
var version = data[0]['value'];
if (!C.SUPPORTED_WEECHAT_VERSIONS.test(version)) {
D.d("This version of WeeChat is not supported.");
disconnect();
}
else {
D.d("Welcome to WeeChat " + version);
EQ.handleEvent("__weecrapp_ready");
});
}
}, true);
B.init();
B.init(ps);
}
@ -94,8 +105,9 @@ function onSslError(errorStrings,
// Public API
function connect(connObj) {
debugViewPage = ps.replace("../pages/DebugView.qml");
D.setDebugPage(debugViewPage);
debugViewPage = ps.replace("../pages/BufferView.qml");
bufferListPage = ps.pushAttached("../pages/BufferList.qml");
B.setDebugPage(debugViewPage);
D.d("Connecting...");
var connType = (connObj.type === "ssl")
@ -158,6 +170,7 @@ function clearConnection() {
connection = null;
connected = false;
handler.clearData();
ps.replace("../pages/ConnectionList.qml");
}
// Send a command to the WeeChat server

View file

@ -6,21 +6,23 @@
.pragma library
.import "moment.js" as M
var _page = null;
// Buffer to push messages to
var _buffer = 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);
if (_buffer !== undefined && _buffer !== null) {
_buffer.add(M.moment(), str);
}
else {
console.log(str);
}
}
function setDebugPage(o) {
_page = o;
function setDebugBuffer(o) {
_buffer = o;
}
@ -28,19 +30,34 @@ function d(str) {
debug(str);
}
// Go straight to console
function c(str) {
console.log(str);
}
function e(o) {
enumerate(o);
}
function enumerate(o) {
d("Enumerating " + o);
d("---");
c("Enumerating object");
c("---");
var keys = Object.keys(o);
for (var i = 0; i < keys.length; ++i) {
d(keys[i] + ": " + o[keys[i]]);
var val = o[keys[i]];
if (typeof val === 'undefined') {
c(keys[i] + ": undefined");
}
else if (val === null) {
c(keys[i] + ": null");
}
else {
c(keys[i] + ": " + val);
}
}
d("");
c("");
}

View file

@ -45,7 +45,7 @@ function command(command, callback) {
var id = UID.get();
command = "(" + id + ") " + command;
D.d("Adding handler for " + id);
//D.d("Adding handler for " + id);
addHandler(id, callback, true);
}

108
qml/pages/BufferList.qml Normal file
View file

@ -0,0 +1,108 @@
/*
* © Mikko Ahlroth 2014
* WeeCRApp is open source software. For licensing information, please check
* the LICENCE file.
*/
import QtQuick 2.0
import Sailfish.Silica 1.0
import "../js/buffers.js" as B
Page {
id: bufferListPage
onVisibleChanged: bufferList.updateList();
SilicaListView {
id: bufferList
model: ListModel { id: bufferListModel }
anchors.fill: parent
function updateList() {
var buffers = B.getBuffersByNumber();
for (var i = 0; i < buffers.length; ++i) {
bufferListModel.append({
number: buffers[i].number,
name: buffers[i].name
});
}
}
header: PageHeader {
width: bufferList.width
title: "Buffers"
}
delegate: ListItem {
id: listItem
contentHeight: Theme.itemSizeSmall
menu: contextMenu
ListView.onRemove: animateRemoval(listItem);
function close() {
remorseAction("Closing buffer",
function() {
// TODO Close buffer forrealz
console.log("Closed " + name + "!");
});
}
Row {
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.paddingLarge
anchors {
left: parent.left
right: parent.right
}
Label {
text: number
color: listItem.highlighted ? Theme.secondaryHighlightColor
: Theme.secondaryColor;
width: parent.width / 7
horizontalAlignment: Qt.AlignRight
}
Label {
text: name
color: listItem.highlighted ? Theme.highlightColor
: Theme.primaryColor;
}
}
Component {
id: contextMenu
ContextMenu {
MenuItem {
text: "Close"
onClicked: close();
}
}
}
onClicked: {
console.log(name + " clicked!");
}
}
VerticalScrollDecorator { flickable: connectionList }
PullDownMenu {
MenuItem {
text: "???"
}
}
PushUpMenu {
MenuItem {
text: "Go to top"
onClicked: bufferList.scrollToTop();
}
}
}
}

101
qml/pages/BufferView.qml Normal file
View file

@ -0,0 +1,101 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
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
property bool isConnected: false;
property string pointer: "";
property int number: 0;
property string name: "";
function setTitle(str) {
topic.title = str;
}
function connected() {
isConnected = true;
}
function disconnected() {
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;
}
SilicaFlickable {
id: mainFlickable
anchors.fill: parent
PageHeader {
id: topic
title: "Debug"
anchors.top: parent.top
}
Item {
id: textListItem
}
Row {
id: inputRow
width: parent.width
anchors.bottom: parent.bottom
TextField {
id: inputField
width: parent.width
anchors.bottom: parent.bottom
placeholderText: "Type here"
EnterKey.enabled: text.length > 0
//EnterKey.iconSource: "image://theme/icon-m-send"
EnterKey.onClicked: {
var buffer = B.getBuffer(inputField.text);
if (buffer !== null) {
changeBuffer(buffer);
}
inputField.text = "";
}
}
}
PushUpMenu {
MenuItem {
text: isConnected? "Disconnect" : "Close";
onClicked: {
if (isConnected) {
C.disconnect();
isConnected = false;
}
else {
C.clearConnection();
}
}
}
}
}
}

View file

@ -15,15 +15,16 @@ Page {
onVisibleChanged: connectionList.updateList();
PageHeader {
title: "Connections"
}
SilicaListView {
id: connectionList
model: ListModel { id: connectionModel }
anchors.fill: parent
header: PageHeader {
width: connectionList.width
title: "Connections"
}
delegate: ListItem {
id: listItem
contentHeight: Theme.itemSizeLarge
@ -45,7 +46,7 @@ Page {
Label {
text: name
color: listItem.highlighted ? Theme.highlightColor
: Theme.primaryColor
: Theme.primaryColor;
anchors {
left: parent.left
right: parent.right
@ -56,7 +57,7 @@ Page {
Label {
text: host + ":" + port
color: listItem.highlighted ? Theme.secondaryHighlightColor
: Theme.secondaryColor
: Theme.secondaryColor;
anchors {
left: parent.left
right: parent.right

View file

@ -6,49 +6,8 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import harbour.weechatrelay.connectionhandler 1.0
import "."
import "../js/connection.js" as C
Page {
id: debugViewPage
property bool isConnected: false;
function display(str) {
debugList.add(new Date(), str);
}
function connected() {
isConnected = true;
}
function disconnected() {
isConnected = false;
}
TextListComponent {
id: debugList
anchors.fill: parent
PushUpMenu {
MenuItem {
text: isConnected? "Disconnect" : "Close";
onClicked: {
if (isConnected) {
C.disconnect();
isConnected = false;
}
else {
C.clearConnection();
pageStack.replace("ConnectionList.qml");
}
}
}
}
VerticalScrollDecorator { flickable: debugList }
}
BufferView {
id: fakeDebugView
}

View file

@ -8,42 +8,35 @@ SilicaListView {
function add(datetime, str) {
var snap = false;
if (textList.atYEnd) {
if (textList.atYBeginning) {
snap = true;
}
textListModel.append({ "time": datetime, "str": str });
// The top is the latest message on the bottom
textListModel.insert(0, { "time": datetime.format('HH:mm:ss'), "str": str });
if (snap) {
textList.positionViewAtEnd();
textList.positionViewAtBeginning();
}
}
function formatTime(datetime) {
function colorTime(time) {
return U.colored(Theme.secondaryHighlightColor,
padTime(datetime.getHours()) + ':'
+ padTime(datetime.getMinutes()) + ':'
+ padTime(datetime.getSeconds()));
}
function padTime(timeInt) {
if (timeInt < 10) {
return '0' + timeInt;
}
return '' + timeInt;
time);
}
model: ListModel { id: textListModel }
verticalLayoutDirection: ListView.BottomToTop
delegate: ListItem {
width: parent.width
contentHeight: messageLabel.height
Label {
id: messageLabel
text: formatTime(time) + " " + U.escapeStyled(str)
text: colorTime(time) + " " + U.escapeStyled(str)
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
color: Theme.highlightColor
@ -55,4 +48,6 @@ SilicaListView {
textFormat: Text.StyledText
}
}
VerticalScrollDecorator { flickable: textList }
}