[Libreoffice-commits] online.git: 9 commits - loleaflet/build loleaflet/debug loleaflet/dist loleaflet/package.json loleaflet/README loleaflet/spec loleaflet/src loolwsd/LOOLSession.cpp loolwsd/LOOLSession.hpp loolwsd/protocol.txt loolwsd/TileCache.cpp loolwsd/TileCache.hpp
Mihai Varga
mihai.varga at collabora.com
Thu Aug 20 04:44:09 PDT 2015
loleaflet/README | 19 +
loleaflet/build/deps.js | 12 +
loleaflet/debug/document/document_simple_example.html | 1
loleaflet/dist/leaflet.css | 5
loleaflet/package.json | 5
loleaflet/spec/headlessLoadTest.js | 179 ++++++++++++++++++
loleaflet/spec/loadtest/LoadTestSpec.js | 7
loleaflet/spec/suites/layer/marker/MarkerSpec.js | 2
loleaflet/spec/suites/layer/tile/GridLayerSpec.js | 74 -------
loleaflet/spec/suites/layer/vector/CircleSpec.js | 2
loleaflet/spec/suites/map/MapSpec.js | 2
loleaflet/src/control/Control.Styles.js | 61 ++++++
loleaflet/src/control/Styles.js | 17 +
loleaflet/src/layer/Layer.js | 3
loleaflet/src/layer/tile/GridLayer.js | 24 +-
loleaflet/src/layer/tile/TileLayer.js | 5
loleaflet/src/map/Map.js | 18 +
loolwsd/LOOLSession.cpp | 40 +++-
loolwsd/LOOLSession.hpp | 6
loolwsd/TileCache.cpp | 42 ++--
loolwsd/TileCache.hpp | 6
loolwsd/protocol.txt | 4
22 files changed, 412 insertions(+), 122 deletions(-)
New commits:
commit 573c6e5b3d3b82029560210878b13498b4f2e5c0
Author: Mihai Varga <mihai.varga at collabora.com>
Date: Thu Aug 20 14:43:40 2015 +0300
loleaflet: always return the current size
diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index c3f091a..ebe67ee 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -333,13 +333,11 @@ L.Map = L.Evented.extend({
},
getSize: function () {
- if (!this._size || this._sizeChanged) {
- this._size = new L.Point(
- this._container.clientWidth,
- this._container.clientHeight);
+ this._size = new L.Point(
+ this._container.clientWidth,
+ this._container.clientHeight);
- this._sizeChanged = false;
- }
+ this._sizeChanged = false;
return this._size.clone();
},
commit 7bd000a8fc3caeb36724f94c2dbe77cb7bfc16b0
Author: Mihai Varga <mihai.varga at collabora.com>
Date: Wed Aug 19 18:28:14 2015 +0300
loleaflet: adapted some of the unit tests
diff --git a/loleaflet/spec/suites/layer/marker/MarkerSpec.js b/loleaflet/spec/suites/layer/marker/MarkerSpec.js
index 2d28fac..d33a8c9 100644
--- a/loleaflet/spec/suites/layer/marker/MarkerSpec.js
+++ b/loleaflet/spec/suites/layer/marker/MarkerSpec.js
@@ -32,7 +32,7 @@ describe("Marker", function () {
var afterIcon = marker._icon;
expect(beforeIcon).to.be(afterIcon);
- expect(afterIcon.src).to.contain(icon2._getIconUrl('icon'));
+ expect(afterIcon.src.replace(/\.\.\//g, '')).to.be.(icon2._getIconUrl('icon').replace(/\.\.\//g, ''));
});
it("preserves draggability", function () {
diff --git a/loleaflet/spec/suites/layer/tile/GridLayerSpec.js b/loleaflet/spec/suites/layer/tile/GridLayerSpec.js
index 1ca4227..4181f7e 100644
--- a/loleaflet/spec/suites/layer/tile/GridLayerSpec.js
+++ b/loleaflet/spec/suites/layer/tile/GridLayerSpec.js
@@ -32,80 +32,6 @@ describe('GridLayer', function () {
});
});
- it('positions tiles correctly with wrapping and bounding', function () {
-
- map.setView([0, 0], 1);
-
- var tiles = [];
-
- var grid = L.gridLayer();
- grid.createTile = function (coords) {
- var tile = document.createElement('div');
- tiles.push({coords: coords, tile: tile});
- return tile;
- };
-
- map.addLayer(grid);
-
- var loaded = {};
-
- for (var i = 0; i < tiles.length; i++) {
- var coords = tiles[i].coords,
- pos = L.DomUtil.getPosition(tiles[i].tile);
-
- loaded[pos.x + ':' + pos.y] = [coords.x, coords.y];
- }
-
- expect(loaded).to.eql({
- '144:44': [0, 0],
- '400:44': [1, 0],
- '144:300': [0, 1],
- '400:300': [1, 1],
- '-112:44': [1, 0],
- '656:44': [0, 0],
- '-112:300': [1, 1],
- '656:300': [0, 1]
- });
- });
-
- describe('tile pyramid', function () {
- var clock;
-
- beforeEach(function () {
- clock = sinon.useFakeTimers();
- });
-
- afterEach(function () {
- clock.restore();
- });
-
- it('removes tiles for unused zoom levels', function (done) {
- map.remove();
- map = L.map(div, {fadeAnimation: false});
- map.setView([0, 0], 1);
-
- var grid = L.gridLayer();
- var tiles = {};
-
- grid.createTile = function (coords) {
- tiles[grid._tileCoordsToKey(coords)] = true;
- return document.createElement('div');
- };
-
- grid.on('tileunload', function (e) {
- delete tiles[grid._tileCoordsToKey(e.coords)];
- if (Object.keys(tiles).length === 1) {
- expect(Object.keys(tiles)).to.eql(['0:0:0']);
- done();
- }
- });
-
- map.addLayer(grid);
- map.setZoom(0, {animate: false});
- clock.tick(250);
- });
- });
-
describe("#onAdd", function () {
it('is called after viewreset on first map load', function () {
var layer = L.gridLayer().addTo(map);
diff --git a/loleaflet/spec/suites/layer/vector/CircleSpec.js b/loleaflet/spec/suites/layer/vector/CircleSpec.js
index 0b45bc8..d48a2c2 100644
--- a/loleaflet/spec/suites/layer/vector/CircleSpec.js
+++ b/loleaflet/spec/suites/layer/vector/CircleSpec.js
@@ -4,7 +4,7 @@ describe('Circle', function () {
var map, circle;
beforeEach(function () {
- map = L.map(document.createElement('div')).setView([0, 0], 4);
+ map = L.map(document.createElement('div'), {crs: L.CRS.EPSG3857}).setView([0, 0], 4);
circle = L.circle([50, 30], 200).addTo(map);
});
diff --git a/loleaflet/spec/suites/map/MapSpec.js b/loleaflet/spec/suites/map/MapSpec.js
index e7261ce..2125eae 100644
--- a/loleaflet/spec/suites/map/MapSpec.js
+++ b/loleaflet/spec/suites/map/MapSpec.js
@@ -2,7 +2,7 @@ describe("Map", function () {
var map,
spy;
beforeEach(function () {
- map = L.map(document.createElement('div'));
+ map = L.map(document.createElement('div'), {crs: L.CRS.EPSG3857});
});
describe("#remove", function () {
commit 8a99c8877acda14e7848a8d5724726b8549820dc
Author: Mihai Varga <mihai.varga at collabora.com>
Date: Wed Aug 19 18:27:33 2015 +0300
loleaflet: fixed some things reported by failing unit tests
diff --git a/loleaflet/src/layer/Layer.js b/loleaflet/src/layer/Layer.js
index 9d6fb1c..0af279f 100644
--- a/loleaflet/src/layer/Layer.js
+++ b/loleaflet/src/layer/Layer.js
@@ -59,7 +59,8 @@ L.Layer = L.Evented.extend({
},
_initDocument: function () {},
- _onMessage: function () {}
+ _onMessage: function () {},
+ sendMessage: function () {}
});
diff --git a/loleaflet/src/layer/tile/GridLayer.js b/loleaflet/src/layer/tile/GridLayer.js
index 5d5cbfd..9ba1301 100644
--- a/loleaflet/src/layer/tile/GridLayer.js
+++ b/loleaflet/src/layer/tile/GridLayer.js
@@ -40,8 +40,10 @@ L.GridLayer = L.Layer.extend({
this._viewReset();
this._map._docLayer = this;
- this._map.socket.onopen = L.bind(this._initDocument, this);
- this._map.socket.onmessage = L.bind(this._onMessage, this);
+ if (this._map.socket) {
+ this._map.socket.onopen = L.bind(this._initDocument, this);
+ this._map.socket.onmessage = L.bind(this._onMessage, this);
+ }
if (this._map.socket && this._map.socket.readyState === 1) {
// the connection is already open
this._initDocument();
@@ -65,18 +67,24 @@ L.GridLayer = L.Layer.extend({
this._tileZoom = null;
clearTimeout(this._preFetchIdle);
clearInterval(this._tilesPreFetcher);
- this._map.socket.onmessage = function () {};
- this._map.socket.onclose = function () {};
- this._map.socket.onerror = function () {};
- this._map.socket.close();
+ if (this._map.socket) {
+ this._map.socket.onmessage = function () {};
+ this._map.socket.onclose = function () {};
+ this._map.socket.onerror = function () {};
+ this._map.socket.close();
+ }
if (this._cursorMarker) {
this._cursorMarker.remove();
}
if (this._graphicMarker) {
this._graphicMarker.remove();
}
- this._startMarker.remove();
- this._endMarker.remove();
+ if (this._startMarker) {
+ this._startMarker.remove();
+ }
+ if (this._endMarker) {
+ this._endMarker.remove();
+ }
},
bringToFront: function () {
diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index 5799ca7..c3f091a 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -249,8 +249,12 @@ L.Map = L.Evented.extend({
this.fire('unload');
}
- this.removeLayer(this._docLayer._selections);
- this.removeLayer(this._docLayer);
+ if (this._docLayer) {
+ if (this._docLayer._selections) {
+ this.removeLayer(this._docLayer._selections);
+ }
+ this.removeLayer(this._docLayer);
+ }
this.removeControls();
return this;
},
commit e46766de1904f51b356aba1cb4e3258b5bb5d180
Author: Mihai Varga <mihai.varga at collabora.com>
Date: Wed Aug 19 10:57:42 2015 +0300
loleaflet: styles control
diff --git a/loleaflet/build/deps.js b/loleaflet/build/deps.js
index 98b5ee6..5488e50 100644
--- a/loleaflet/build/deps.js
+++ b/loleaflet/build/deps.js
@@ -289,6 +289,13 @@ var deps = {
desc: 'Handles vex dialogs for displaying alerts'
},
+ ControlStyles: {
+ src: ['control/Control.js',
+ 'control/Control.Styles.js'],
+ heading: 'Controls',
+ desc: 'Handles styles selection'
+ },
+
ControlAttrib: {
src: ['control/Control.js',
'control/Control.Attribution.js'],
diff --git a/loleaflet/debug/document/document_simple_example.html b/loleaflet/debug/document/document_simple_example.html
index 9d31f45..eb55c1e 100644
--- a/loleaflet/debug/document/document_simple_example.html
+++ b/loleaflet/debug/document/document_simple_example.html
@@ -67,6 +67,7 @@
});
////// Controls /////
+ globalMap.addControl(L.control.styles());
globalMap.addControl(L.control.buttons());
globalMap.addControl(L.control.zoom());
globalMap.addControl(L.control.parts());
diff --git a/loleaflet/dist/leaflet.css b/loleaflet/dist/leaflet.css
index c7c43b7..7c09fb6 100644
--- a/loleaflet/dist/leaflet.css
+++ b/loleaflet/dist/leaflet.css
@@ -762,6 +762,11 @@ input.leaflet-control-search-bar {
padding: 0.3em;
}
+.leaflet-control-styles {
+ padding: 0.2em 0.4em 0.4em 0em;
+ background-color: white;
+}
+
.leaflet-control-zoom.leaflet-bar {
margin-left: 0.5em;
}
diff --git a/loleaflet/src/control/Control.Styles.js b/loleaflet/src/control/Control.Styles.js
new file mode 100644
index 0000000..7bedc43
--- /dev/null
+++ b/loleaflet/src/control/Control.Styles.js
@@ -0,0 +1,61 @@
+/*
+ * L.Control.Styles is used to display a dropdown list of styles
+ */
+
+L.Control.Styles = L.Control.extend({
+ options: {
+ info: '- Please select a style -'
+ },
+
+ onAdd: function (map) {
+ var stylesName = 'leaflet-control-styles';
+ this._container = L.DomUtil.create('select', stylesName + ' leaflet-bar'),
+
+ map.on('updatepermission', this._onUpdatePermission, this);
+ map.on('updatestyles', this._initList, this);
+ L.DomEvent.on(this._container, 'change', this._onChange, this);
+
+ return this._container;
+ },
+
+ onRemove: function (map) {
+ map.off('updatepermission', this._searchResultFound, this);
+ },
+
+ _initList: function (e) {
+ var container = this._container;
+ var first = L.DomUtil.create('option', '', container);
+ first.innerHTML = this.options.info;
+ if (this._map._docLayer._docType === 'text') {
+ var styles = e.styles.ParagraphStyles.slice(0, 12);
+ styles.forEach(function (style) {
+ var item = L.DomUtil.create('option', '', container);
+ item.value = style;
+ item.innerHTML = style;
+ });
+ }
+ },
+
+ _onUpdatePermission: function (e) {
+ if (e.perm === 'edit') {
+ this._container.disabled = false;
+ }
+ else {
+ this._container.disabled = true;
+ }
+ },
+
+ _onChange: function (e) {
+ var style = e.target.value;
+ if (style === this.options.info) {
+ return;
+ }
+ if (this._map._docLayer._docType === 'text') {
+ this._map.setStyle(style, 'ParagraphStyles');
+ }
+ }
+});
+
+L.control.styles = function (options) {
+ return new L.Control.Styles(options);
+};
commit 438e4008591313c2be7ce2263e9091bf0d5e90e5
Author: Mihai Varga <mihai.varga at collabora.com>
Date: Tue Aug 18 21:24:58 2015 +0300
loleaflet: document style setter and getter
diff --git a/loleaflet/README b/loleaflet/README
index 78853f9..995f3ed 100644
--- a/loleaflet/README
+++ b/loleaflet/README
@@ -172,6 +172,15 @@ Writer pages:
+ e.pages = number of pages
+ e.docType = document type, should be 'text'
+Styles:
+ - API:
+ map.getStyles()
+ + returns a JSON object as a mapping of style families to a list of styles
+ map.setStyle(style, familyName)
+ - events:
+ map.on('updatestyles', function (e) {}) where:
+ e.styles = a JSON object as a mapping of style families to a list of styles
+
Error:
- events
map.on('error', function (e) {}) where
diff --git a/loleaflet/build/deps.js b/loleaflet/build/deps.js
index d527e7d..98b5ee6 100644
--- a/loleaflet/build/deps.js
+++ b/loleaflet/build/deps.js
@@ -332,6 +332,11 @@ var deps = {
desc: 'Scroll handler.'
},
+ Styles: {
+ src: ['control/Styles.js'],
+ desc: 'Document styles handler.'
+ },
+
AnimationPan: {
src: [
'dom/DomEvent.js',
diff --git a/loleaflet/src/control/Styles.js b/loleaflet/src/control/Styles.js
new file mode 100644
index 0000000..ca233de
--- /dev/null
+++ b/loleaflet/src/control/Styles.js
@@ -0,0 +1,17 @@
+L.Map.include({
+ getStyles: function () {
+ return this._docLayer._docStyles;
+ },
+
+ setStyle: function (style, familyName) {
+ if (!style || !familyName) {
+ this.fire('error', {cmd: 'setStyle', kind: 'incorrectparam'});
+ return;
+ }
+ var msg = 'uno .uno:StyleApply {' +
+ '"Style":{"type":"string", "value": "' + style + '"},' +
+ '"FamilyName":{"type":"string", "value":"' + familyName + '"}' +
+ '}';
+ this._docLayer.sendMessage(msg);
+ }
+});
diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index 8d7191e..010f7b0 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -105,6 +105,7 @@ L.TileLayer = L.GridLayer.extend({
}
this.sendMessage(msg);
this.sendMessage('status');
+ this.sendMessage('styles');
}
this._map.on('drag resize zoomend', this._updateScrollOffset, this);
this._map.on('clearselection', this._clearSelections, this);
@@ -509,6 +510,10 @@ L.TileLayer = L.GridLayer.extend({
var originalPhrase = textMsg.substring(16);
this._map.fire('search', {originalPhrase: originalPhrase, count: 0});
}
+ else if (textMsg.startsWith('styles:')) {
+ this._docStyles = JSON.parse(textMsg.substring(8));
+ this._map.fire('updatestyles', {styles: this._docStyles});
+ }
else if (textMsg.startsWith('error:')) {
command = this._parseServerCmd(textMsg);
this._map.fire('error', {cmd: command.errorCmd, kind: command.errorKind});
commit 1cfd1352ce70c546f2b11e32eadf8a408b49382d
Author: Mihai Varga <mihai.varga at collabora.com>
Date: Tue Aug 18 21:01:05 2015 +0300
loolwsd: renamed getStatus/saveStatus to getTextFile/saveTextFile
And added a getStyles method that uses the above methods to cache
document styles
diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index 1202639..b48af37 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -195,7 +195,11 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
}
else if (tokens[0] == "status:")
{
- peer->_tileCache->saveStatus(std::string(buffer, length));
+ peer->_tileCache->saveTextFile(std::string(buffer, length), "status.txt");
+ }
+ else if (tokens[0] == "styles:")
+ {
+ peer->_tileCache->saveTextFile(std::string(buffer, length), "styles.txt");
}
else if (tokens[0] == "invalidatetiles:")
{
@@ -277,6 +281,7 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
tokens[0] != "setclientpart" &&
tokens[0] != "setpage" &&
tokens[0] != "status" &&
+ tokens[0] != "styles" &&
tokens[0] != "tile" &&
tokens[0] != "uno")
{
@@ -301,6 +306,10 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
{
return getStatus(buffer, length);
}
+ else if (tokens[0] == "styles")
+ {
+ return getStyles(buffer, length);
+ }
else if (tokens[0] == "tile")
{
sendTile(buffer, length, tokens);
@@ -394,7 +403,7 @@ bool MasterProcessSession::getStatus(const char *buffer, int length)
{
std::string status;
- status = _tileCache->getStatus();
+ status = _tileCache->getTextFile("status.txt");
if (status.size() > 0)
{
sendTextFrame(status);
@@ -407,6 +416,23 @@ bool MasterProcessSession::getStatus(const char *buffer, int length)
return true;
}
+bool MasterProcessSession::getStyles(const char *buffer, int length)
+{
+ std::string styles;
+
+ styles = _tileCache->getTextFile("styles.txt");
+ if (styles.size() > 0)
+ {
+ sendTextFrame(styles);
+ return true;
+ }
+
+ if (_peer.expired())
+ dispatchChild();
+ forwardToPeer(buffer, length);
+ return true;
+}
+
void MasterProcessSession::sendTile(const char *buffer, int length, StringTokenizer& tokens)
{
int part, width, height, tilePosX, tilePosY, tileWidth, tileHeight;
@@ -608,6 +634,10 @@ bool ChildProcessSession::handleInput(const char *buffer, int length)
{
return getStatus(buffer, length);
}
+ else if (tokens[0] == "styles")
+ {
+ return getStyles(buffer, length);
+ }
else if (tokens[0] == "tile")
{
sendTile(buffer, length, tokens);
@@ -819,6 +849,12 @@ bool ChildProcessSession::getStatus(const char *buffer, int length)
return true;
}
+bool ChildProcessSession::getStyles(const char *buffer, int length)
+{
+ sendTextFrame("styles: " + std::string(_loKitDocument->pClass->getStyles(_loKitDocument)));
+ return true;
+}
+
void ChildProcessSession::sendTile(const char *buffer, int length, StringTokenizer& tokens)
{
int part, width, height, tilePosX, tilePosY, tileWidth, tileHeight;
diff --git a/loolwsd/LOOLSession.hpp b/loolwsd/LOOLSession.hpp
index 0030f28..a63e40e 100644
--- a/loolwsd/LOOLSession.hpp
+++ b/loolwsd/LOOLSession.hpp
@@ -45,6 +45,8 @@ public:
virtual bool getStatus(const char *buffer, int length) = 0;
+ virtual bool getStyles(const char *buffer, int length) = 0;
+
virtual bool handleInput(const char *buffer, int length) = 0;
protected:
@@ -109,6 +111,8 @@ public:
virtual bool getStatus(const char *buffer, int length);
+ virtual bool getStyles(const char *buffer, int length);
+
protected:
bool invalidateTiles(const char *buffer, int length, Poco::StringTokenizer& tokens);
@@ -154,6 +158,8 @@ public:
virtual bool getStatus(const char *buffer, int length);
+ virtual bool getStyles(const char *buffer, int length);
+
LibreOfficeKitDocument *_loKitDocument;
std::string _docType;
diff --git a/loolwsd/TileCache.cpp b/loolwsd/TileCache.cpp
index 01714a4..76ca730 100644
--- a/loolwsd/TileCache.cpp
+++ b/loolwsd/TileCache.cpp
@@ -106,37 +106,37 @@ void TileCache::saveTile(int part, int width, int height, int tilePosX, int tile
outStream.close();
}
-std::string TileCache::getStatus()
+std::string TileCache::getTextFile(std::string fileName)
{
- const char statusFile[] = "/status.txt";
+ const char *textFile = std::string("/" + fileName).c_str();
std::string dirName = cacheDirName(false);
if (_hasUnsavedChanges)
{
- // try the Editing cache first, and prefer its status.txt if it exists
+ // try the Editing cache first, and prefer it if it exists
std::string editingDirName = cacheDirName(true);
File dir(editingDirName);
- File status(editingDirName + statusFile);
- if (dir.exists() && dir.isDirectory() && status.exists() && !status.isDirectory())
+ File text(editingDirName + textFile);
+ if (dir.exists() && dir.isDirectory() && text.exists() && !text.isDirectory())
dirName = editingDirName;
}
if (!File(dirName).exists() || !File(dirName).isDirectory())
return "";
- std::string fileName = dirName + statusFile;
- std::fstream statusStream(fileName, std::ios::in);
- if (!statusStream.is_open())
+ fileName = dirName + textFile;
+ std::fstream textStream(fileName, std::ios::in);
+ if (!textStream.is_open())
return "";
std::vector<char> result;
- statusStream.seekg(0, std::ios_base::end);
- std::streamsize size = statusStream.tellg();
+ textStream.seekg(0, std::ios_base::end);
+ std::streamsize size = textStream.tellg();
result.resize(size);
- statusStream.seekg(0, std::ios_base::beg);
- statusStream.read(result.data(), size);
- statusStream.close();
+ textStream.seekg(0, std::ios_base::beg);
+ textStream.read(result.data(), size);
+ textStream.close();
if (result[result.size()-1] == '\n')
result.resize(result.size() - 1);
@@ -170,24 +170,22 @@ void TileCache::setEditing(bool editing)
_isEditing = editing;
}
-void TileCache::saveStatus(const std::string& status)
+void TileCache::saveTextFile(const std::string& text, std::string fileName)
{
std::string dirName = cacheDirName(_hasUnsavedChanges);
File(dirName).createDirectories();
- StringTokenizer tokens(status, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+ StringTokenizer tokens(text, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
- assert(tokens[0] == "status:");
+ fileName = dirName + "/" + fileName;
+ std::fstream textStream(fileName, std::ios::out);
- std::string fileName = dirName + "/status.txt";
- std::fstream statusStream(fileName, std::ios::out);
-
- if (!statusStream.is_open())
+ if (!textStream.is_open())
return;
- statusStream << status << std::endl;
- statusStream.close();
+ textStream << text << std::endl;
+ textStream.close();
}
void TileCache::invalidateTiles(int part, int x, int y, int width, int height)
diff --git a/loolwsd/TileCache.hpp b/loolwsd/TileCache.hpp
index 1e01078..8294784 100644
--- a/loolwsd/TileCache.hpp
+++ b/loolwsd/TileCache.hpp
@@ -40,7 +40,7 @@ public:
std::unique_ptr<std::fstream> lookupTile(int part, int width, int height, int tilePosX, int tilePosY, int tileWidth, int tileHeight);
void saveTile(int part, int width, int height, int tilePosX, int tilePosY, int tileWidth, int tileHeight, const char *data, size_t size);
- std::string getStatus();
+ std::string getTextFile(std::string fileName);
/// Notify the cache that the document was saved - to copy tiles from the Editing cache to Persistent.
void documentSaved();
@@ -48,8 +48,8 @@ public:
/// Notify whether we need to use the Editing cache.
void setEditing(bool editing = true);
- // The parameter is a status: message
- void saveStatus(const std::string& status);
+ // The parameter is a message
+ void saveTextFile(const std::string& text, std::string fileName);
// The tiles parameter is an invalidatetiles: message as sent by the child process
void invalidateTiles(const std::string& tiles);
diff --git a/loolwsd/protocol.txt b/loolwsd/protocol.txt
index 734d317..369bb69 100644
--- a/loolwsd/protocol.txt
+++ b/loolwsd/protocol.txt
@@ -65,6 +65,8 @@ selectgraphic type=<type> x=<x> y=<y>
status
+styles
+
tile part=<partNumber> width=<width> height=<height> tileposx=<xpos> tileposy=<ypos> tilewidth=<tileWidth> tileheight=<tileHeight>
All parameters are numbers.
@@ -113,6 +115,8 @@ status: type=<typeName> parts=<numberOfParts> current=<currentPartNumber> width=
<typeName> is 'text, 'spreadsheet', 'presentation', 'drawing' or 'other. Others are numbers.
if the document has multiple parts and those have names, part names follow separated by '\n'
+styles: {"styleFamily": ["styles in family"], etc. }
+
textselectioncontent: <content>
Current selection's content
commit b5688840adb7eb72340e28d0e40d0e463b0780c4
Author: Mihai Varga <mihai.varga at collabora.com>
Date: Tue Aug 18 14:34:10 2015 +0300
loleaflet: mention how to run the tests
diff --git a/loleaflet/README b/loleaflet/README
index 0ce0f70..78853f9 100644
--- a/loleaflet/README
+++ b/loleaflet/README
@@ -179,6 +179,16 @@ Error:
+ [e.cmd] = the command that caused the error
+ [e.kind] = the kind of error
+Testing
+-------
+ - to simulate an editing session and to get the tile loading times
+ + open spec/tilebench.html in the browser
+ - to simulate a client opening several documents in the browser
+ + open spec/loadtest.html in the browser
+ - to simulate a client opening several documents in the console
+ + run: mocha headlessLoadTest.js
+
+
Contributing
------------
commit 7e7e458b1ef8107f211cbdd76c9df453eeca1497
Author: Mihai Varga <mihai.varga at collabora.com>
Date: Tue Aug 18 14:27:17 2015 +0300
loleaflet: headless load test
diff --git a/loleaflet/package.json b/loleaflet/package.json
index b6e4b12..9c423c4 100644
--- a/loleaflet/package.json
+++ b/loleaflet/package.json
@@ -38,5 +38,8 @@
"type": "BSD-2-Clause",
"url": "https://github.com/Leaflet/Leaflet/blob/master/LICENSE"
}
- ]
+ ],
+ "dependencies": {
+ "ws": "~0.7.2"
+ }
}
diff --git a/loleaflet/spec/headlessLoadTest.js b/loleaflet/spec/headlessLoadTest.js
new file mode 100644
index 0000000..fa88982
--- /dev/null
+++ b/loleaflet/spec/headlessLoadTest.js
@@ -0,0 +1,179 @@
+var WebSocket = require('ws');
+var events = require('events');
+
+if (typeof String.prototype.startsWith != 'function') {
+ String.prototype.startsWith = function (str){
+ return this.indexOf(str) === 0;
+ };
+}
+
+describe('LoadTest', function () {
+ // 10s timeout
+ this.timeout(10000);
+ // set the slow time to 5ms knowing each test takes more than that,
+ // so the run time is always printed
+ this.slow(5);
+ var testsRan = 0,
+ tileSize = 256,
+ tileSizeTwips = 3000,
+ host = 'ws://localhost:9980';
+
+ var docPath = 'file:///PATH';
+ var docs = ['eval.odt', 'lorem.odt'];
+
+ var _parseServerCmd = function (msg) {
+ var tokens = msg.split(/[ \n]+/);
+ var command = {};
+ for (var i = 0; i < tokens.length; i++) {
+ if (tokens[i].substring(0, 9) === 'tileposx=') {
+ command.x = parseInt(tokens[i].substring(9));
+ }
+ else if (tokens[i].substring(0, 9) === 'tileposy=') {
+ command.y = parseInt(tokens[i].substring(9));
+ }
+ else if (tokens[i].substring(0, 10) === 'tilewidth=') {
+ command.tileWidth = parseInt(tokens[i].substring(10));
+ }
+ else if (tokens[i].substring(0, 11) === 'tileheight=') {
+ command.tileHeight = parseInt(tokens[i].substring(11));
+ }
+ else if (tokens[i].substring(0, 6) === 'width=') {
+ command.width = parseInt(tokens[i].substring(6));
+ }
+ else if (tokens[i].substring(0, 7) === 'height=') {
+ command.height = parseInt(tokens[i].substring(7));
+ }
+ else if (tokens[i].substring(0, 5) === 'part=') {
+ command.part = parseInt(tokens[i].substring(5));
+ }
+ else if (tokens[i].substring(0, 6) === 'parts=') {
+ command.parts = parseInt(tokens[i].substring(6));
+ }
+ else if (tokens[i].substring(0, 8) === 'current=') {
+ command.currentPart = parseInt(tokens[i].substring(8));
+ }
+ }
+ return command;
+ };
+
+ before(function () {
+ if (docPath === 'file:///PATH') {
+ throw new Error('Document file path not set');
+ }
+ else if (docPath[docPath.length - 1] !== '/') {
+ docPath += '/';
+ }
+ });
+
+ docs.forEach(function (testDoc) {
+ testsRan += 1;
+ describe('Document #' + testsRan + ' (' + testDoc + ')', function () {
+ var ws;
+ var requestedTiles = 0;
+ var docWidthTwips, docHeightTwips, midY, endY;
+ var eventEmitter = new events.EventEmitter();
+
+ var onMessage = function (evt) {
+ var bytes, index, textMsg;
+
+ if (typeof (evt.data) === 'string') {
+ textMsg = evt.data;
+ }
+ else if (typeof (evt.data) === 'object') {
+ bytes = new Uint8Array(evt.data);
+ index = 0;
+ // search for the first newline which marks the end of the message
+ while (index < bytes.length && bytes[index] !== 10) {
+ index++;
+ }
+ textMsg = String.fromCharCode.apply(null, bytes.subarray(0, index));
+ }
+
+ if (textMsg.startsWith('status:')) {
+ command = _parseServerCmd(textMsg);
+ docWidthTwips = command.width;
+ docHeightTwips = command.height;
+ endY = Math.floor(docHeightTwips / tileSizeTwips);
+ midY = Math.floor(endY / 2);
+ eventEmitter.emit('status');
+ }
+ else if (textMsg.startsWith('tile:')) {
+ requestedTiles -= 1;
+ if (requestedTiles <= 0) {
+ eventEmitter.emit('alltilesloaded');
+ }
+ }
+ else if (textMsg.startsWith('error:')) {
+ console.log(textMsg);
+ throw new Error(textMsg);
+ }
+ };
+
+ var requestTiles = function (x, y) {
+ requestedTiles += 1;
+ ws.send('tile ' +
+ 'part=0 ' +
+ 'width=' + tileSize + ' ' +
+ 'height=' + tileSize + ' ' +
+ 'tileposx=' + x * tileSizeTwips + ' ' +
+ 'tileposy=' + y * tileSizeTwips + ' ' +
+ 'tilewidth=' + tileSizeTwips + ' ' +
+ 'tileheight=' + tileSizeTwips);
+ };
+
+ var isValidTile = function (x, y) {
+ return x >= 0 && y >= 0 && (x * tileSizeTwips < docWidthTwips) && (y * tileSizeTwips < docHeightTwips);
+ };
+
+ after(function () {
+ ws.onmessage = function () {};
+ ws.close();
+ });
+
+ it('Connect to the server', function (done) {
+ eventEmitter.once('status', done);
+ ws = new WebSocket(host);
+ ws.onmessage = onMessage;
+ ws.onerror = function (e) {console.log(e)};
+ ws.binaryType = 'arraybuffer';
+ ws.onopen = function () {
+ ws.send('load url=' + docPath + testDoc);
+ ws.send('status');
+ };
+ });
+
+ it('Load the document', function (done) {
+ eventEmitter.once('alltilesloaded', done);
+ for (var i = 0; i < 3; i++) {
+ for (j = 0; j < 5; j++) {
+ if (isValidTile(j, i)) {
+ requestTiles(j, i);
+ }
+ }
+ }
+ });
+
+ it('Scroll to the middle', function (done) {
+ eventEmitter.once('alltilesloaded', done);
+ for (var i = midY; i < midY + 3; i++) {
+ for (j = 0; j < 5; j++) {
+ if (isValidTile(j, i)) {
+ requestTiles(j, i);
+ }
+ }
+ }
+ });
+
+ it('Scroll to the end', function (done) {
+ eventEmitter.once('alltilesloaded', done);
+ for (var i = endY; i > endY - 3; i--) {
+ for (j = 0; j < 5; j++) {
+ if (isValidTile(j, i)) {
+ requestTiles(j, i);
+ }
+ }
+ }
+ });
+ });
+ });
+});
commit 6dc45b5825316ba9aeb1389acd9580fab7b4ad66
Author: Mihai Varga <mihai.varga at collabora.com>
Date: Tue Aug 18 13:52:00 2015 +0300
loleaflet: load test check if doc path is set
diff --git a/loleaflet/spec/loadtest/LoadTestSpec.js b/loleaflet/spec/loadtest/LoadTestSpec.js
index e04350a..c339926 100644
--- a/loleaflet/spec/loadtest/LoadTestSpec.js
+++ b/loleaflet/spec/loadtest/LoadTestSpec.js
@@ -1,6 +1,9 @@
describe('LoadTest', function () {
// 25 s timeout
this.timeout(25000);
+ // set the slow time to 5ms knowing each test takes more than that,
+ // so the run time is always printed
+ this.slow(5);
var testsRan = 0,
checkTimeOut = null,
map = null,
@@ -9,6 +12,10 @@ describe('LoadTest', function () {
y = 0;
before(function() {
+ if (docPath === 'file:///PATH') {
+ throw new Error('Document file path not set');
+ }
+
map = L.map('map-test', {
center: [0, 0],
zoom: 10,
More information about the Libreoffice-commits
mailing list