From f8898170a77593e314d3cd187f259223e9bff0f8 Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Thu, 29 Mar 2018 15:27:06 +0200 Subject: Remove hardcoded size from QWebEngineView::sizeHint() 800x600 takes more space than expected when building a layout which contains QWebEngineView. Now this function does exactly the same as QWidget::sizeHint(). Add an auto test and update examples which were depending on this hardcoded size. Change-Id: I3b34b7d37cc99a8d6a49100d6c4b66b5b6a1c999 Reviewed-by: Allan Sandfeld Jensen --- .../webenginewidgets/contentmanipulation/main.cpp | 1 + examples/webenginewidgets/cookiebrowser/main.cpp | 1 + examples/webenginewidgets/maps/main.cpp | 1 + .../stylesheetbrowser/mainwindow.ui | 56 +++++++++++++++++++--- examples/webenginewidgets/videoplayer/main.cpp | 1 + 5 files changed, 54 insertions(+), 6 deletions(-) (limited to 'examples') diff --git a/examples/webenginewidgets/contentmanipulation/main.cpp b/examples/webenginewidgets/contentmanipulation/main.cpp index 5645f9b9a..e816079d2 100644 --- a/examples/webenginewidgets/contentmanipulation/main.cpp +++ b/examples/webenginewidgets/contentmanipulation/main.cpp @@ -63,6 +63,7 @@ int main(int argc, char * argv[]) else url = QUrl("http://www.google.com/ncr"); MainWindow *browser = new MainWindow(url); + browser->resize(1024, 768); browser->show(); return app.exec(); } diff --git a/examples/webenginewidgets/cookiebrowser/main.cpp b/examples/webenginewidgets/cookiebrowser/main.cpp index ae208c824..0ae5433ba 100644 --- a/examples/webenginewidgets/cookiebrowser/main.cpp +++ b/examples/webenginewidgets/cookiebrowser/main.cpp @@ -57,6 +57,7 @@ int main(int argc, char *argv[]) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication app(argc, argv); MainWindow window(QUrl("http://qt.io")); + window.resize(1024, 768); window.show(); return app.exec(); } diff --git a/examples/webenginewidgets/maps/main.cpp b/examples/webenginewidgets/maps/main.cpp index f62518274..cad9c7ea9 100644 --- a/examples/webenginewidgets/maps/main.cpp +++ b/examples/webenginewidgets/maps/main.cpp @@ -57,6 +57,7 @@ int main(int argc, char *argv[]) QApplication app(argc, argv); MainWindow mainWindow; + mainWindow.resize(1024, 768); mainWindow.show(); return app.exec(); diff --git a/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui b/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui index f9c1af969..bc68c16bb 100644 --- a/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui +++ b/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui @@ -18,11 +18,47 @@ + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + 0 + 0 + + @@ -32,13 +68,13 @@ - - Ctrl+R - :/view-refresh.png:/view-refresh.png + + Ctrl+R + @@ -52,8 +88,14 @@ - - + + + + 0 + 0 + + + about:blank @@ -84,6 +126,8 @@
QtWebEngineWidgets/QWebEngineView
- + + + diff --git a/examples/webenginewidgets/videoplayer/main.cpp b/examples/webenginewidgets/videoplayer/main.cpp index f62518274..cad9c7ea9 100644 --- a/examples/webenginewidgets/videoplayer/main.cpp +++ b/examples/webenginewidgets/videoplayer/main.cpp @@ -57,6 +57,7 @@ int main(int argc, char *argv[]) QApplication app(argc, argv); MainWindow mainWindow; + mainWindow.resize(1024, 768); mainWindow.show(); return app.exec(); -- cgit v1.2.3 From 694350898f4d96a57a1f91e36519070ed4b4c09b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCri=20Valdmann?= Date: Tue, 15 May 2018 11:51:16 +0200 Subject: Fix keyboard focus for speculative RenderFrameHosts When encountering a 301 redirect, one render frame/widget is created for the original URL plus one "speculative" render frame/widget for the new URL. Once the speculative frame commits, keyboard focus should switch to the corresponding widget. This doesn't work however, because QQuickItem::forceActiveFocus doesn't give focus to the containing QQuickWidget. Fixed by using QWidget::setFocus. Also changed simplebrowser to focus the QWebEngineView on startup. Task-number: QTBUG-68076 Change-Id: I8dc42ba89bfdcd46a86c7dca357fdf1e94f439d4 Reviewed-by: Allan Sandfeld Jensen --- examples/webenginewidgets/simplebrowser/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/webenginewidgets/simplebrowser/main.cpp b/examples/webenginewidgets/simplebrowser/main.cpp index 9b9bf80b5..96b1eab97 100644 --- a/examples/webenginewidgets/simplebrowser/main.cpp +++ b/examples/webenginewidgets/simplebrowser/main.cpp @@ -50,7 +50,7 @@ #include "browser.h" #include "browserwindow.h" -#include "webview.h" +#include "tabwidget.h" #include #include @@ -78,7 +78,7 @@ int main(int argc, char **argv) Browser browser; BrowserWindow *window = browser.createWindow(); - window->currentTab()->setUrl(url); + window->tabWidget()->setUrl(url); return app.exec(); } -- cgit v1.2.3 From 3e8fb932531bd66f0fe79960744df4f5f6656515 Mon Sep 17 00:00:00 2001 From: Szabolcs David Date: Wed, 2 May 2018 11:16:46 +0200 Subject: Improve user experience in stylesheet example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add checkboxes to make configurable whether a stylesheet should be applied - Add a default stylesheet which rotates the page by 180 degree. Task-number: QTBUG-64816 Change-Id: Ic82c61f9d1e5384f3271a260bc390ac50f5b9a12 Reviewed-by: Jüri Valdmann Reviewed-by: Kai Koehne --- .../webenginewidgets/stylesheetbrowser/main.cpp | 3 ++ .../stylesheetbrowser/mainwindow.cpp | 38 ++++++++++++++-- .../stylesheetbrowser/mainwindow.h | 2 + .../stylesheetbrowser/stylesheetdialog.cpp | 50 +++++++++++++++++++--- .../stylesheetbrowser/stylesheetdialog.h | 4 ++ 5 files changed, 87 insertions(+), 10 deletions(-) (limited to 'examples') diff --git a/examples/webenginewidgets/stylesheetbrowser/main.cpp b/examples/webenginewidgets/stylesheetbrowser/main.cpp index 957913f5a..54fce0ce3 100644 --- a/examples/webenginewidgets/stylesheetbrowser/main.cpp +++ b/examples/webenginewidgets/stylesheetbrowser/main.cpp @@ -49,6 +49,7 @@ ****************************************************************************/ #include "mainwindow.h" +#include "stylesheetdialog.h" #include #include @@ -58,6 +59,8 @@ int main(int argc, char *argv[]) QCoreApplication::setOrganizationDomain("www.qt.io"); QCoreApplication::setApplicationName("StyleSheet Browser"); + qRegisterMetaTypeStreamOperators("StyleSheet"); + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication a(argc, argv); MainWindow w(QUrl("http://qt.io")); diff --git a/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp b/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp index f7e6964cb..c93205b18 100644 --- a/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp +++ b/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp @@ -49,9 +49,12 @@ ****************************************************************************/ #include "mainwindow.h" +#include "stylesheetdialog.h" #include "ui_mainwindow.h" -#include "stylesheetdialog.h" +static QMap defaultStyleSheets = { + {"Upside down", "body { -webkit-transform: rotate(180deg); }"} +}; MainWindow::MainWindow(const QUrl &url) : QMainWindow(), @@ -67,8 +70,16 @@ MainWindow::MainWindow(const QUrl &url) : QSettings settings; settings.beginGroup("styleSheets"); QStringList styleSheets = settings.allKeys(); - for (auto name : qAsConst(styleSheets)) - insertStyleSheet(name, settings.value(name, QString()).toString(), false); + if (styleSheets.empty()) { + // Add back default style sheets if the user cleared them out + loadDefaultStyleSheets(); + } else { + for (auto name : qAsConst(styleSheets)) { + StyleSheet styleSheet = settings.value(name).value(); + if (styleSheet.second) + insertStyleSheet(name, styleSheet.first, false); + } + } settings.endGroup(); ui->webEngineView->setUrl(url); @@ -114,6 +125,27 @@ void MainWindow::removeStyleSheet(const QString &name, bool immediately) ui->webEngineView->page()->scripts().remove(script); } +bool MainWindow::hasStyleSheet(const QString &name) +{ + QWebEngineScript script = ui->webEngineView->page()->scripts().findScript(name); + return !script.isNull(); +} + +void MainWindow::loadDefaultStyleSheets() +{ + QSettings settings; + settings.beginGroup("styleSheets"); + + auto it = defaultStyleSheets.constBegin(); + while (it != defaultStyleSheets.constEnd()) { + settings.setValue(it.key(), QVariant::fromValue(qMakePair(it.value(), true))); + insertStyleSheet(it.key(), it.value(), false); + ++it; + } + + settings.endGroup(); +} + void MainWindow::urlEntered() { ui->webEngineView->setUrl(QUrl::fromUserInput(ui->urlBar->text())); diff --git a/examples/webenginewidgets/stylesheetbrowser/mainwindow.h b/examples/webenginewidgets/stylesheetbrowser/mainwindow.h index fb0c8e7be..c39735af8 100644 --- a/examples/webenginewidgets/stylesheetbrowser/mainwindow.h +++ b/examples/webenginewidgets/stylesheetbrowser/mainwindow.h @@ -71,6 +71,8 @@ public: void insertStyleSheet(const QString &name, const QString &source, bool immediately); void removeStyleSheet(const QString &name, bool immediately); + bool hasStyleSheet(const QString &name); + void loadDefaultStyleSheets(); private slots: void urlEntered(); diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp index eb8abe135..7351ab75f 100644 --- a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp +++ b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp @@ -59,6 +59,7 @@ StylesheetDialog::StylesheetDialog(QWidget *parent) : ui->setupUi(this); connect(ui->styleSheetList, &QListWidget::currentItemChanged, this, &StylesheetDialog::currentStyleSheetChanged); + connect(ui->styleSheetList, &QListWidget::itemClicked, this, &StylesheetDialog::listItemClicked); connect(ui->fileNameEdit, &QLineEdit::textChanged, this, &StylesheetDialog::fileNameChanged); connect(ui->addButton, &QPushButton::clicked, this, &StylesheetDialog::addButtonClicked); @@ -66,8 +67,12 @@ StylesheetDialog::StylesheetDialog(QWidget *parent) : QSettings settings; settings.beginGroup("styleSheets"); - for (auto name : settings.allKeys()) - new QListWidgetItem(name, ui->styleSheetList); + for (auto name : settings.allKeys()) { + QListWidgetItem *listItem = new QListWidgetItem(name, ui->styleSheetList); + listItem->setFlags(listItem->flags() | Qt::ItemIsUserCheckable); + bool checked = settings.value(name).value().second; + listItem->setCheckState(checked ? Qt::Checked : Qt::Unchecked); + } settings.endGroup(); } @@ -92,7 +97,33 @@ void StylesheetDialog::currentStyleSheetChanged(QListWidgetItem *current, QListW QSettings settings; settings.beginGroup("styleSheets"); ui->fileNameEdit->setText(current->text()); - ui->sourceCodeEdit->setPlainText(settings.value(current->text(), QString()).toString()); + const QString source = settings.value(current->text()).value().first; + ui->sourceCodeEdit->setPlainText(source); + settings.endGroup(); +} + +void StylesheetDialog::listItemClicked(QListWidgetItem *item) +{ + MainWindow *window = static_cast(parent()); + const QString name = item->text(); + bool checkedStateChanged = + (item->checkState() == Qt::Checked && !window->hasStyleSheet(name)) || + (item->checkState() == Qt::Unchecked && window->hasStyleSheet(name)); + if (!checkedStateChanged) + return; + + QSettings settings; + settings.beginGroup("styleSheets"); + const QString source = settings.value(name).value().first; + + if (item->checkState() == Qt::Checked) { + settings.setValue(name, QVariant::fromValue(qMakePair(source, true))); + window->insertStyleSheet(name, source, true); + } else { + settings.setValue(name, QVariant::fromValue(qMakePair(source, false))); + window->removeStyleSheet(name, true); + } + settings.endGroup(); } @@ -107,16 +138,21 @@ void StylesheetDialog::fileNameChanged(const QString &text) void StylesheetDialog::addButtonClicked() { - new QListWidgetItem(ui->fileNameEdit->text(), ui->styleSheetList); - - MainWindow *window = static_cast(parent()); const QString name = ui->fileNameEdit->text(); const QString source = ui->sourceCodeEdit->toPlainText(); + if (name.isEmpty() || source.isEmpty()) + return; + + QListWidgetItem *listItem = new QListWidgetItem(ui->fileNameEdit->text(), ui->styleSheetList); + listItem->setFlags(listItem->flags() | Qt::ItemIsUserCheckable); + listItem->setCheckState(Qt::Checked); + + MainWindow *window = static_cast(parent()); window->insertStyleSheet(name, source, true); QSettings settings; settings.beginGroup("styleSheets"); - settings.setValue(name, source); + settings.setValue(name, QVariant::fromValue(qMakePair(source, true))); settings.endGroup(); ui->addButton->setEnabled(false); diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h index f65cfe666..3bf3219ca 100644 --- a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h +++ b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h @@ -60,6 +60,9 @@ class StylesheetDialog; } QT_END_NAMESPACE +typedef QPair StyleSheet; // +Q_DECLARE_METATYPE(StyleSheet); + class StylesheetDialog : public QDialog { Q_OBJECT @@ -70,6 +73,7 @@ public: private slots: void currentStyleSheetChanged(QListWidgetItem *current, QListWidgetItem *previous); + void listItemClicked(QListWidgetItem *item); void fileNameChanged(const QString &text); void addButtonClicked(); -- cgit v1.2.3 From cd1af11a3a7fc41afa2f628b967344fd92f02a6f Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Wed, 9 May 2018 15:58:07 +0200 Subject: Remove qwebchannel.js from test and example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use qwebchannel.js shipped with qtwebchannel. Change-Id: Iceead5131d22a6988bbb4e7a3cca1e9f21908e3e Reviewed-by: Jüri Valdmann Reviewed-by: Michael Brüning --- .../markdowneditor/resources/index.html | 2 +- .../markdowneditor/resources/markdowneditor.qrc | 1 - .../markdowneditor/resources/qwebchannel.js | 430 --------------------- 3 files changed, 1 insertion(+), 432 deletions(-) delete mode 100644 examples/webenginewidgets/markdowneditor/resources/qwebchannel.js (limited to 'examples') diff --git a/examples/webenginewidgets/markdowneditor/resources/index.html b/examples/webenginewidgets/markdowneditor/resources/index.html index 8623a0642..5fa28fa17 100644 --- a/examples/webenginewidgets/markdowneditor/resources/index.html +++ b/examples/webenginewidgets/markdowneditor/resources/index.html @@ -4,7 +4,7 @@ - +
diff --git a/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc b/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc index 9a6bd3801..812c8850a 100644 --- a/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc +++ b/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc @@ -1,7 +1,6 @@ index.html - qwebchannel.js 3rdparty/marked.min.js default.md 3rdparty/markdown.css diff --git a/examples/webenginewidgets/markdowneditor/resources/qwebchannel.js b/examples/webenginewidgets/markdowneditor/resources/qwebchannel.js deleted file mode 100644 index 8ebfbb1c9..000000000 --- a/examples/webenginewidgets/markdowneditor/resources/qwebchannel.js +++ /dev/null @@ -1,430 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebChannel module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -"use strict"; - -var QWebChannelMessageTypes = { - signal: 1, - propertyUpdate: 2, - init: 3, - idle: 4, - debug: 5, - invokeMethod: 6, - connectToSignal: 7, - disconnectFromSignal: 8, - setProperty: 9, - response: 10, -}; - -var QWebChannel = function(transport, initCallback) -{ - if (typeof transport !== "object" || typeof transport.send !== "function") { - console.error("The QWebChannel expects a transport object with a send function and onmessage callback property." + - " Given is: transport: " + typeof(transport) + ", transport.send: " + typeof(transport.send)); - return; - } - - var channel = this; - this.transport = transport; - - this.send = function(data) - { - if (typeof(data) !== "string") { - data = JSON.stringify(data); - } - channel.transport.send(data); - } - - this.transport.onmessage = function(message) - { - var data = message.data; - if (typeof data === "string") { - data = JSON.parse(data); - } - switch (data.type) { - case QWebChannelMessageTypes.signal: - channel.handleSignal(data); - break; - case QWebChannelMessageTypes.response: - channel.handleResponse(data); - break; - case QWebChannelMessageTypes.propertyUpdate: - channel.handlePropertyUpdate(data); - break; - default: - console.error("invalid message received:", message.data); - break; - } - } - - this.execCallbacks = {}; - this.execId = 0; - this.exec = function(data, callback) - { - if (!callback) { - // if no callback is given, send directly - channel.send(data); - return; - } - if (channel.execId === Number.MAX_VALUE) { - // wrap - channel.execId = Number.MIN_VALUE; - } - if (data.hasOwnProperty("id")) { - console.error("Cannot exec message with property id: " + JSON.stringify(data)); - return; - } - data.id = channel.execId++; - channel.execCallbacks[data.id] = callback; - channel.send(data); - }; - - this.objects = {}; - - this.handleSignal = function(message) - { - var object = channel.objects[message.object]; - if (object) { - object.signalEmitted(message.signal, message.args); - } else { - console.warn("Unhandled signal: " + message.object + "::" + message.signal); - } - } - - this.handleResponse = function(message) - { - if (!message.hasOwnProperty("id")) { - console.error("Invalid response message received: ", JSON.stringify(message)); - return; - } - channel.execCallbacks[message.id](message.data); - delete channel.execCallbacks[message.id]; - } - - this.handlePropertyUpdate = function(message) - { - for (var i in message.data) { - var data = message.data[i]; - var object = channel.objects[data.object]; - if (object) { - object.propertyUpdate(data.signals, data.properties); - } else { - console.warn("Unhandled property update: " + data.object + "::" + data.signal); - } - } - channel.exec({type: QWebChannelMessageTypes.idle}); - } - - this.debug = function(message) - { - channel.send({type: QWebChannelMessageTypes.debug, data: message}); - }; - - channel.exec({type: QWebChannelMessageTypes.init}, function(data) { - for (var objectName in data) { - var object = new QObject(objectName, data[objectName], channel); - } - // now unwrap properties, which might reference other registered objects - for (var objectName in channel.objects) { - channel.objects[objectName].unwrapProperties(); - } - if (initCallback) { - initCallback(channel); - } - channel.exec({type: QWebChannelMessageTypes.idle}); - }); -}; - -function QObject(name, data, webChannel) -{ - this.__id__ = name; - webChannel.objects[name] = this; - - // List of callbacks that get invoked upon signal emission - this.__objectSignals__ = {}; - - // Cache of all properties, updated when a notify signal is emitted - this.__propertyCache__ = {}; - - var object = this; - - // ---------------------------------------------------------------------- - - this.unwrapQObject = function(response) - { - if (response instanceof Array) { - // support list of objects - var ret = new Array(response.length); - for (var i = 0; i < response.length; ++i) { - ret[i] = object.unwrapQObject(response[i]); - } - return ret; - } - if (!response - || !response["__QObject*__"] - || response.id === undefined) { - return response; - } - - var objectId = response.id; - if (webChannel.objects[objectId]) - return webChannel.objects[objectId]; - - if (!response.data) { - console.error("Cannot unwrap unknown QObject " + objectId + " without data."); - return; - } - - var qObject = new QObject( objectId, response.data, webChannel ); - qObject.destroyed.connect(function() { - if (webChannel.objects[objectId] === qObject) { - delete webChannel.objects[objectId]; - // reset the now deleted QObject to an empty {} object - // just assigning {} though would not have the desired effect, but the - // below also ensures all external references will see the empty map - // NOTE: this detour is necessary to workaround QTBUG-40021 - var propertyNames = []; - for (var propertyName in qObject) { - propertyNames.push(propertyName); - } - for (var idx in propertyNames) { - delete qObject[propertyNames[idx]]; - } - } - }); - // here we are already initialized, and thus must directly unwrap the properties - qObject.unwrapProperties(); - return qObject; - } - - this.unwrapProperties = function() - { - for (var propertyIdx in object.__propertyCache__) { - object.__propertyCache__[propertyIdx] = object.unwrapQObject(object.__propertyCache__[propertyIdx]); - } - } - - function addSignal(signalData, isPropertyNotifySignal) - { - var signalName = signalData[0]; - var signalIndex = signalData[1]; - object[signalName] = { - connect: function(callback) { - if (typeof(callback) !== "function") { - console.error("Bad callback given to connect to signal " + signalName); - return; - } - - object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || []; - object.__objectSignals__[signalIndex].push(callback); - - if (!isPropertyNotifySignal && signalName !== "destroyed") { - // only required for "pure" signals, handled separately for properties in propertyUpdate - // also note that we always get notified about the destroyed signal - webChannel.exec({ - type: QWebChannelMessageTypes.connectToSignal, - object: object.__id__, - signal: signalIndex - }); - } - }, - disconnect: function(callback) { - if (typeof(callback) !== "function") { - console.error("Bad callback given to disconnect from signal " + signalName); - return; - } - object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || []; - var idx = object.__objectSignals__[signalIndex].indexOf(callback); - if (idx === -1) { - console.error("Cannot find connection of signal " + signalName + " to " + callback.name); - return; - } - object.__objectSignals__[signalIndex].splice(idx, 1); - if (!isPropertyNotifySignal && object.__objectSignals__[signalIndex].length === 0) { - // only required for "pure" signals, handled separately for properties in propertyUpdate - webChannel.exec({ - type: QWebChannelMessageTypes.disconnectFromSignal, - object: object.__id__, - signal: signalIndex - }); - } - } - }; - } - - /** - * Invokes all callbacks for the given signalname. Also works for property notify callbacks. - */ - function invokeSignalCallbacks(signalName, signalArgs) - { - var connections = object.__objectSignals__[signalName]; - if (connections) { - connections.forEach(function(callback) { - callback.apply(callback, signalArgs); - }); - } - } - - this.propertyUpdate = function(signals, propertyMap) - { - // update property cache - for (var propertyIndex in propertyMap) { - var propertyValue = propertyMap[propertyIndex]; - object.__propertyCache__[propertyIndex] = propertyValue; - } - - for (var signalName in signals) { - // Invoke all callbacks, as signalEmitted() does not. This ensures the - // property cache is updated before the callbacks are invoked. - invokeSignalCallbacks(signalName, signals[signalName]); - } - } - - this.signalEmitted = function(signalName, signalArgs) - { - invokeSignalCallbacks(signalName, signalArgs); - } - - function addMethod(methodData) - { - var methodName = methodData[0]; - var methodIdx = methodData[1]; - object[methodName] = function() { - var args = []; - var callback; - for (var i = 0; i < arguments.length; ++i) { - if (typeof arguments[i] === "function") - callback = arguments[i]; - else - args.push(arguments[i]); - } - - webChannel.exec({ - "type": QWebChannelMessageTypes.invokeMethod, - "object": object.__id__, - "method": methodIdx, - "args": args - }, function(response) { - if (response !== undefined) { - var result = object.unwrapQObject(response); - if (callback) { - (callback)(result); - } - } - }); - }; - } - - function bindGetterSetter(propertyInfo) - { - var propertyIndex = propertyInfo[0]; - var propertyName = propertyInfo[1]; - var notifySignalData = propertyInfo[2]; - // initialize property cache with current value - // NOTE: if this is an object, it is not directly unwrapped as it might - // reference other QObject that we do not know yet - object.__propertyCache__[propertyIndex] = propertyInfo[3]; - - if (notifySignalData) { - if (notifySignalData[0] === 1) { - // signal name is optimized away, reconstruct the actual name - notifySignalData[0] = propertyName + "Changed"; - } - addSignal(notifySignalData, true); - } - - Object.defineProperty(object, propertyName, { - configurable: true, - get: function () { - var propertyValue = object.__propertyCache__[propertyIndex]; - if (propertyValue === undefined) { - // This shouldn't happen - console.warn("Undefined value in property cache for property \"" + propertyName + "\" in object " + object.__id__); - } - - return propertyValue; - }, - set: function(value) { - if (value === undefined) { - console.warn("Property setter for " + propertyName + " called with undefined value!"); - return; - } - object.__propertyCache__[propertyIndex] = value; - webChannel.exec({ - "type": QWebChannelMessageTypes.setProperty, - "object": object.__id__, - "property": propertyIndex, - "value": value - }); - } - }); - - } - - // ---------------------------------------------------------------------- - - data.methods.forEach(addMethod); - - data.properties.forEach(bindGetterSetter); - - data.signals.forEach(function(signal) { addSignal(signal, false); }); - - for (var name in data.enums) { - object[name] = data.enums[name]; - } -} - -//required for use with nodejs -if (typeof module === 'object') { - module.exports = { - QWebChannel: QWebChannel - }; -} -- cgit v1.2.3