clipboard: Copying of complex data with detection
Complex data is now flagged based on Core's feedback and/or the size of the payload. Download now works as expected and copying to the clipboard is also functional. Change-Id: I7405517e3a6afcc4c8f5843130476578c1ff06f6
This commit is contained in:
parent
00a4fc0cd7
commit
8ce397b758
5 changed files with 98 additions and 36 deletions
|
@ -351,6 +351,56 @@ public:
|
|||
return mpDoc->pClass->getTextSelection(mpDoc, pMimeType, pUsedMimeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the selected content.
|
||||
*
|
||||
* @return an element of the LibreOfficeKitSelectionType enum.
|
||||
*/
|
||||
int getSelectionType()
|
||||
{
|
||||
return mpDoc->pClass->getSelectionType(mpDoc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content on the clipboard for the current view as a series of binary streams.
|
||||
*
|
||||
* NB. returns a complete set of possible selection types if nullptr is passed for pMimeTypes.
|
||||
*
|
||||
* @param pMimeTypes passes in a nullptr terminated list of mime types to fetch
|
||||
* @param pOutCount returns the size of the other @pOut arrays
|
||||
* @param pOutMimeTypes returns an array of mime types
|
||||
* @param pOutSizes returns the size of each pOutStream
|
||||
* @param pOutStreams the content of each mime-type, of length in @pOutSizes
|
||||
*
|
||||
* @returns: true on success, false on error.
|
||||
*/
|
||||
bool getClipboard(const char **pMimeTypes,
|
||||
size_t *pOutCount,
|
||||
char ***pOutMimeTypes,
|
||||
size_t **pOutSizes,
|
||||
char ***pOutStreams)
|
||||
{
|
||||
return mpDoc->pClass->getClipboard(mpDoc, pMimeTypes, pOutCount, pOutMimeTypes, pOutSizes, pOutStreams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the clipboard for this view with multiple types of content.
|
||||
*
|
||||
* @param nInCount the number of types to paste
|
||||
* @param pInMimeTypes array of mime type strings
|
||||
* @param pInSizes array of sizes of the data to paste
|
||||
* @param pInStreams array containing the data of the various types
|
||||
*
|
||||
* @return if the supplied data was populated successfully.
|
||||
*/
|
||||
bool setClipboard(const size_t nInCount,
|
||||
const char **pInMimeTypes,
|
||||
const size_t *pInSizes,
|
||||
const char **pInStreams)
|
||||
{
|
||||
return mpDoc->pClass->setClipboard(mpDoc, nInCount, pInMimeTypes, pInSizes, pInStreams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pastes content at the current cursor position.
|
||||
*
|
||||
|
|
|
@ -917,7 +917,31 @@ bool ChildSession::getTextSelection(const char* /*buffer*/, int /*length*/, cons
|
|||
return false;
|
||||
}
|
||||
|
||||
sendTextFrame("textselectioncontent: " + getTextSelectionInternal(mimeType));
|
||||
if (getLOKitDocument()->getDocumentType() != LOK_DOCTYPE_TEXT)
|
||||
{
|
||||
const std::string selection = getTextSelectionInternal(mimeType);
|
||||
if (selection.size() >= 1024 * 1024) // Don't return huge data.
|
||||
{
|
||||
// Flag complex data so the client will download async.
|
||||
sendTextFrame("complexselection:");
|
||||
return true;
|
||||
}
|
||||
|
||||
sendTextFrame("textselectioncontent: " + selection);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string selection;
|
||||
const int selectionType = getLOKitDocument()->getSelectionType();
|
||||
if (selectionType == LOK_SELTYPE_LARGE_TEXT || selectionType == LOK_SELTYPE_COMPLEX ||
|
||||
(selection = getTextSelectionInternal(mimeType)).size() >= 1024 * 1024) // Don't return huge data.
|
||||
{
|
||||
// Flag complex data so the client will download async.
|
||||
sendTextFrame("complexselection:");
|
||||
return true;
|
||||
}
|
||||
|
||||
sendTextFrame("textselectioncontent: " + selection);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -996,7 +1020,7 @@ bool ChildSession::setClipboard(const char* buffer, int length, const std::vecto
|
|||
// data.dumpState(std::cerr);
|
||||
|
||||
size_t nInCount = data.size();
|
||||
size_t pInSizes[nInCount] = { 0, };
|
||||
size_t pInSizes[nInCount];
|
||||
const char *pInMimeTypes[nInCount];
|
||||
const char *pInStreams[nInCount];
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ L.Control.DownloadProgress = L.Control.extend({
|
|||
confirmCopy.style.alignment = 'center';
|
||||
confirmCopy.style.height = 20 + 'px';
|
||||
L.DomEvent.on(confirmCopy, 'click', this._onConfirmCopyAction, this);
|
||||
this._closed = false;
|
||||
},
|
||||
|
||||
show: function () {
|
||||
|
@ -62,6 +63,10 @@ L.Control.DownloadProgress = L.Control.extend({
|
|||
this._container.style.visibility = '';
|
||||
},
|
||||
|
||||
isClosed: function () {
|
||||
return this._closed;
|
||||
},
|
||||
|
||||
setURI: function (uri) {
|
||||
// set up data uri to be downloaded
|
||||
this._uri = uri;
|
||||
|
@ -112,8 +117,8 @@ L.Control.DownloadProgress = L.Control.extend({
|
|||
this._content.appendChild(this._confirmPasteButton);
|
||||
},
|
||||
|
||||
_onConfirmCopyAction: function (ev) {
|
||||
this._map._clip.copy(ev);
|
||||
_onConfirmCopyAction: function () {
|
||||
this._map._clip.filterExecCopyPaste('.uno:Copy');
|
||||
this._map._clip._downloadProgress = null;
|
||||
this._onClose();
|
||||
},
|
||||
|
@ -127,6 +132,7 @@ L.Control.DownloadProgress = L.Control.extend({
|
|||
this._content.removeChild(this._progress);
|
||||
this._map.focus();
|
||||
this.remove();
|
||||
this._closed = true;
|
||||
},
|
||||
|
||||
_download: function () {
|
||||
|
@ -138,12 +144,12 @@ L.Control.DownloadProgress = L.Control.extend({
|
|||
// annoying async parse of the blob ...
|
||||
var reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
console.log('async clipboard parse done: ' + text.substring(0, 256))
|
||||
var text = reader.result;
|
||||
console.log('async clipboard parse done: ' + text.substring(0, 256))
|
||||
var idx = text.indexOf('<!DOCTYPE HTML');
|
||||
if (idx > 0)
|
||||
text = text.substring(idx, text.length());
|
||||
that._map._clip.setSelection(text);
|
||||
text = text.substring(idx, text.length);
|
||||
that._map._clip.setTextSelectionContent(text);
|
||||
// TODO: now swap to the 'copy' button (?)
|
||||
};
|
||||
// TODO: failure to parse ? ...
|
||||
|
|
|
@ -585,7 +585,7 @@ L.TileLayer = L.GridLayer.extend({
|
|||
// message is received from lowsd, *then* a 'celladdress' message.
|
||||
var address = textMsg.substring(13);
|
||||
if (!this._map['wopi'].DisableCopy) {
|
||||
this._map._clip.setSelection(this._lastFormula);
|
||||
this._map._clip.setTextSelectionContent(this._lastFormula);
|
||||
}
|
||||
this._map.fire('celladdress', {address: address});
|
||||
},
|
||||
|
@ -2636,17 +2636,6 @@ L.TileLayer = L.GridLayer.extend({
|
|||
}
|
||||
},
|
||||
|
||||
_selectionType: function() {
|
||||
if (this._graphicSelection !== null &&
|
||||
!this._isEmptyRectangle(this._graphicSelection)) {
|
||||
return 'complex'; // FIXME: Ash - complex ...
|
||||
} else if (this._selections.getLayers().length > 0) {
|
||||
return 'simpletext';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
_onCopy: function (e) {
|
||||
e = e.originalEvent;
|
||||
this._map._clip.copy(e);
|
||||
|
|
|
@ -13,6 +13,7 @@ L.Clipboard = L.Class.extend({
|
|||
initialize: function(map) {
|
||||
this._map = map;
|
||||
this._selectionContent = '';
|
||||
this._selectionType = null;
|
||||
this._accessKey = [ '', '' ];
|
||||
this._clipboardSerial = 0; // incremented on each operation
|
||||
|
||||
|
@ -273,12 +274,11 @@ L.Clipboard = L.Class.extend({
|
|||
},
|
||||
|
||||
populateClipboard: function(ev) {
|
||||
var t = this._map._docLayer._selectionType();
|
||||
var text;
|
||||
if (t === null) {
|
||||
if (this._selectionType === null) {
|
||||
console.log('Copy/Cut with no selection!');
|
||||
text = this.getStubHtml();
|
||||
} else if (t === 'complex') {
|
||||
} else if (this._selectionType === 'complex') {
|
||||
console.log('Copy/Cut with complex/graphical selection');
|
||||
text = this.getStubHtml();
|
||||
this._onDownloadOnLargeCopyPaste();
|
||||
|
@ -468,26 +468,19 @@ L.Clipboard = L.Class.extend({
|
|||
|
||||
clearSelection: function() {
|
||||
this._selectionContent = '';
|
||||
},
|
||||
|
||||
setSelection: function(content) {
|
||||
this._selectionContent = content;
|
||||
this._selectionType = null;
|
||||
},
|
||||
|
||||
// textselectioncontent: message
|
||||
setTextSelectionContent: function(text) {
|
||||
this.setSelection(text);
|
||||
this._selectionType = 'text';
|
||||
this._selectionContent = text;
|
||||
},
|
||||
|
||||
// complexselection: message
|
||||
onComplexSelection: function (text) {
|
||||
// Put in the clipboard a helpful explanation of what the user should do.
|
||||
// Currently we don't have a payload, though we might in the future
|
||||
text = _('Please use the following link to download the selection from you document and paste into other applications on your device')
|
||||
+ ': '; //FIXME: MISSING URL
|
||||
this.setSelection(text);
|
||||
|
||||
//TODO: handle complex selection download.
|
||||
onComplexSelection: function (/*text*/) {
|
||||
// Mark this selection as complex.
|
||||
this._selectionType = 'complex';
|
||||
},
|
||||
|
||||
_startProgress: function() {
|
||||
|
@ -501,7 +494,7 @@ L.Clipboard = L.Class.extend({
|
|||
},
|
||||
|
||||
_onDownloadOnLargeCopyPaste: function () {
|
||||
if (!this._downloadProgress) {
|
||||
if (!this._downloadProgress || this._downloadProgress.isClosed()) {
|
||||
this._warnFirstLargeCopyPaste();
|
||||
this._startProgress();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue