From 9883dca4714c82079d390da18d1e3ff36f29b5a7 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Wed, 17 May 2017 16:56:30 +0200 Subject: [macOS] Use the OpenGL CoreProfile when the global shared context does Previously when a default QSurfaceFormat was set with an OpenGL Core profile, all the contexts created on the Qt side would obey the profile, but Chromium would still use the Compatibility profile for its contexts leading to warnings when trying to create shared contexts. The fix is to check which OpenGL profile is used in the Qt global shared context, and pass that information along to Chromium. Note that this works only on macOS for now, and the default non-Core profile is used on other platforms, even though Core was requested. Passing CoreProfile to Chromium on Windows and Linux currently leads to crashes. Task-number: QTBUG-60605 Change-Id: I27a77091923624d19ccc2019953a5b07f9282916 Reviewed-by: Peter Varga Reviewed-by: Kai Koehne --- src/core/web_engine_context.cpp | 16 +++++++++++++++- .../tst_qquickwebenginedefaultsurfaceformat.cpp | 3 +++ .../tst_qwebenginedefaultsurfaceformat.cpp | 4 ++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 2748d2a0f..56dbb84b7 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -389,8 +389,22 @@ WebEngineContext::WebEngineContext() } } } else { - if (!qt_gl_global_share_context()->isOpenGLES()) + if (!qt_gl_global_share_context()->isOpenGLES()) { + // Default to Desktop non-Core profile OpenGL. glType = gl::kGLImplementationDesktopName; + + // Check if Core profile was requested and is supported. + QSurfaceFormat globalSharedFormat = qt_gl_global_share_context()->format(); + if (globalSharedFormat.profile() == QSurfaceFormat::CoreProfile) { +#ifdef Q_OS_MACOS + glType = gl::kGLImplementationCoreProfileName; +#else + qWarning("An OpenGL Core Profile was requested, but it is not supported " + "on the current platform. Falling back to a non-Core profile. " + "Note that this might cause rendering issues."); +#endif + } + } } } else { qWarning("WebEngineContext used before QtWebEngine::initialize() or OpenGL context creation failed."); diff --git a/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp b/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp index 3d44efa6a..2afaf03a3 100644 --- a/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp +++ b/tests/auto/quick/qquickwebenginedefaultsurfaceformat/tst_qquickwebenginedefaultsurfaceformat.cpp @@ -110,6 +110,9 @@ QUrl tst_QQuickWebEngineDefaultSurfaceFormat::urlFromTestPath(const char *localF void tst_QQuickWebEngineDefaultSurfaceFormat::customDefaultSurfaceFormat() { +#if !defined(Q_OS_MACOSX) + QSKIP("OpenGL Core Profile is currently only supported on macOS."); +#endif // Setting a new default QSurfaceFormat with a core OpenGL profile, before // app instantiation should succeed, without abort() being called. int argc = 1; diff --git a/tests/auto/widgets/qwebenginedefaultsurfaceformat/tst_qwebenginedefaultsurfaceformat.cpp b/tests/auto/widgets/qwebenginedefaultsurfaceformat/tst_qwebenginedefaultsurfaceformat.cpp index 3757a7842..1e8cc74e2 100644 --- a/tests/auto/widgets/qwebenginedefaultsurfaceformat/tst_qwebenginedefaultsurfaceformat.cpp +++ b/tests/auto/widgets/qwebenginedefaultsurfaceformat/tst_qwebenginedefaultsurfaceformat.cpp @@ -51,8 +51,8 @@ private Q_SLOTS: void tst_QWebEngineDefaultSurfaceFormat::customDefaultSurfaceFormat() { -#if defined(Q_OS_WIN) - QSKIP("Crashes on Windows"); +#if !defined(Q_OS_MACOSX) + QSKIP("OpenGL Core Profile is currently only supported on macOS."); #endif // Setting a new default QSurfaceFormat with a core OpenGL profile before // app instantiation should succeed, without abort() being called. -- cgit v1.2.3 From c2f786d59c8171c05cc7ff8c98b8a85175e5e5a2 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Fri, 7 Jul 2017 18:24:43 +0200 Subject: Fix "Could not share GL contexts" warnings on Windows Make sure that a non-Core Profile OpenGL Context is created on the Chromium side, so that sharing between the Qt global context and the Chromium ones works. Change-Id: Ifc5f39268395615fe50c8aa9467f833c0de233a8 Reviewed-by: Joerg Bornemann Reviewed-by: Kai Koehne Reviewed-by: Viktor Engelmann --- src/core/web_engine_context.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 56dbb84b7..9d993b7f4 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -332,6 +332,17 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisablePepper3DImageChromium); #endif +#if defined(Q_OS_WIN) + // This switch is used in Chromium's gl_context_wgl.cc file to determine whether to create + // an OpenGL Core Profile context. If the switch is not set, it would always try to create a + // Core Profile context, even if Qt uses a legacy profile, which causes + // "Could not share GL contexts" warnings, because it's not possible to share between Core and + // legacy profiles. + // Given that Core profile is not currently supported on Windows anyway, pass this switch to + // get rid of the warnings. + parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext); +#endif + if (useEmbeddedSwitches) { // Inspired by the Android port's default switches if (!parsedCommandLine->HasSwitch(switches::kDisableOverlayScrollbar)) -- cgit v1.2.3 From ef09ea48c36e00dc2a03188936887caf95c2307e Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Mon, 19 Jun 2017 11:35:43 +0200 Subject: Take into account the value of the --touch-events Chromium switch In Chromium 56 the --touch-events switch controls both the availability of the Touch Events API in JavaScript (presence of 'ontouchstart' in 'window' object), and whether touch events are dispatched at all. In Chromium 57, the switch controls only the Touch Events API availability, and touch events are always dispatched. In Qt 5.9.0 which is based on Chromium 56, we always dispatched touch events, ignored the value of --touch-events, and determined the availability of the Touch Events API by checking if QTouchDevice lists any touch screen devices (essentially Chromium's --touch-events=auto option). This commit changes the behavior of WebEngine to match that of Chromium 57, so that users can choose to enable or disable the Touch Events API via the --touch-events switch, whereas the default will be 'auto' mode. Touch events will always be dispatched as usual. Users that wish to stop dispatching touch events can install an event filter on WebEngine's view focus proxy. Task-number: QTBUG-61045 Change-Id: I07404af3336619869aa87a90a1b426036548dd55 Reviewed-by: Leena Miettinen Reviewed-by: Kai Koehne --- src/core/web_engine_settings.cpp | 27 ++++++++++++++++++++++++- src/webengine/doc/src/qtwebengine-features.qdoc | 17 ++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index 58f0a3e2c..0079e02ba 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -48,6 +48,7 @@ #include "content/browser/gpu/gpu_process_host.h" #include "content/public/common/content_switches.h" #include "content/public/common/web_preferences.h" +#include "ui/events/event_switches.h" #include #include @@ -97,6 +98,29 @@ static inline bool isTouchScreenAvailable() { return touchScreenAvailable; } +static inline bool isTouchEventsAPIEnabled() { + static bool initialized = false; + static bool touchEventsAPIEnabled = false; + if (!initialized) { + base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess(); + + // By default the Touch Events API support (presence of 'ontouchstart' in 'window' object) + // will be determined based on the availability of touch screen devices. + const std::string touchEventsSwitchValue = + parsedCommandLine->HasSwitch(switches::kTouchEvents) ? + parsedCommandLine->GetSwitchValueASCII(switches::kTouchEvents) : + switches::kTouchEventsAuto; + + if (touchEventsSwitchValue == switches::kTouchEventsEnabled) + touchEventsAPIEnabled = true; + else if (touchEventsSwitchValue == switches::kTouchEventsAuto) + touchEventsAPIEnabled = isTouchScreenAvailable(); + + initialized = true; + } + return touchEventsAPIEnabled; +} + WebEngineSettings::WebEngineSettings(WebEngineSettings *_parentSettings) : m_adapter(0) @@ -298,7 +322,8 @@ void WebEngineSettings::doApply() void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *prefs) { // Override for now - prefs->touch_enabled = isTouchScreenAvailable(); + prefs->touch_enabled = isTouchEventsAPIEnabled(); + prefs->device_supports_touch = isTouchScreenAvailable(); if (prefs->viewport_enabled) { // We should enable viewport and viewport-meta together, but since 5.7 we // no longer have a command-line flag for viewport-meta. diff --git a/src/webengine/doc/src/qtwebengine-features.qdoc b/src/webengine/doc/src/qtwebengine-features.qdoc index 11d3a4ca1..b80ad6a35 100644 --- a/src/webengine/doc/src/qtwebengine-features.qdoc +++ b/src/webengine/doc/src/qtwebengine-features.qdoc @@ -45,6 +45,7 @@ \li \l{Pepper Plugin API} \li \l{Print to PDF} \li \l{Spellchecker} + \li \l{Touch} \li \l{View Source} \li \l{WebRTC} \endlist @@ -312,6 +313,22 @@ Support for this feature was added in Qt 5.8.0. + \section1 Touch + + Qt WebEngine supports touch devices for navigating and interacting with web pages. + + Applications can prohibit the use of touch events in the following ways: + + \list + \li Passing the flag \c --touch-events=disabled on the command line will disable touch event + support in JavaScript API (meaning \c ontouchstart and related handlers will not be present + in the \c document.window object). Touch events will still be delivered to web pages. + + \li Installing an event filter object using \l {QObject::installEventFilter} on the WebEngine + view focus proxy object, and filtering out all touch events. + + \endlist + \section1 View Source Qt WebEngine supports viewing the HTML source of a web page. -- cgit v1.2.3 From de2e77720e522b91325e5ff9507b32b23b6c6700 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Thu, 29 Jun 2017 17:04:31 +0200 Subject: Document about popups not appearing on Windows when in fullscreen mode On Windows there is an issue that an OpenGL-backed fullscreen window will prevent other top-level windows from appearing on top of it (for example a select / combo box popup). This appears to be a limitation of the Windows platform compositor (DWM). The workaround is to call QWindowsWindowFunctions::setHasBorderInFullScreen on the QWindow which will show the fullscreen WebEngine view. Task-number: QTBUG-61563 Change-Id: I5e0f08ef49de6119ef7910cec2b32ea267301c18 Reviewed-by: Leena Miettinen --- src/webengine/doc/qtwebengine.qdocconf | 1 + src/webengine/doc/src/qtwebengine-platform-notes.qdoc | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/webengine/doc/qtwebengine.qdocconf b/src/webengine/doc/qtwebengine.qdocconf index ea9c6f21b..7b1bad4e6 100644 --- a/src/webengine/doc/qtwebengine.qdocconf +++ b/src/webengine/doc/qtwebengine.qdocconf @@ -42,6 +42,7 @@ depends += qtcore \ qtgui \ qtlocation \ qtnetwork \ + qtplatformheaders \ qtprintsupport \ qtpositioning \ qtqml \ diff --git a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc index ec678672c..068d395b6 100644 --- a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc +++ b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc @@ -182,4 +182,10 @@ It can be re-enabled by setting the \c QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY environment variable to a non-empty value. + \section1 Popups in Fullscreen Applications on Windows + Because of a limitation in the Windows compositor, applications that show a fullscreen web + engine view will not properly display popups or other top-level windows. The reason and + workaround for the issue can be found at \l {Fullscreen OpenGL Based Windows} and + \l {QWindowsWindowFunctions::setHasBorderInFullScreen}. + */ -- cgit v1.2.3 From 636b61fcf626e67fc34b3f16d857d8c089353095 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Thu, 13 Jul 2017 11:51:21 +0200 Subject: Update Chromium Pulls following changes: 1a14be1 Enable using gnu thin archives on Linux 296b240 Silence gcc -Waddress warnings in logging.h fabd7e0 Fix building without git installed 1173dda Do not export c memory handling functions 25ceaa6 Do not launch zygote processes in single-process mode 721a4d1 Carry over user-agent override when opening new windows Change-Id: If48223d76fbb35f1847e416a7f244e4b6ed85f33 Reviewed-by: Alexandru Croitor --- src/3rdparty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty b/src/3rdparty index 53521384e..1a14be1c4 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 53521384e3d0ab71727ae950c37951f7d3402ce3 +Subproject commit 1a14be1c45c61b3d4c65519ec203f2d039eb34c9 -- cgit v1.2.3 From 82adf72d1eb3f2ec8e212a55fdcc3151863664c8 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 12 Jul 2017 09:00:30 +0200 Subject: Examples: Add recipebrowser to top-level .pro file Change-Id: I7d22a9c2a4f4aed1f364e672985da357158467e7 Reviewed-by: Alexandru Croitor --- examples/webengine/webengine.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/webengine/webengine.pro b/examples/webengine/webengine.pro index 969681e9d..3f55888cb 100644 --- a/examples/webengine/webengine.pro +++ b/examples/webengine/webengine.pro @@ -3,4 +3,5 @@ TEMPLATE=subdirs SUBDIRS += \ customdialogs \ minimal \ - quicknanobrowser + quicknanobrowser \ + recipebrowser -- cgit v1.2.3 From a0f7ba909905ea917f47154cb5b18b8f108e0613 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 3 Jul 2017 17:14:57 +0200 Subject: Properly document third party code in examples Move files from marked, markdown.css to a 3rdparty directory, and properly document them with a qt_attribution.json file. Finally, reference the (automatically generated) documentation in the respective examples documentation. Task-number: QTBUG-61706 Change-Id: I8fd3f894e6e81647bc4804df784b1e00b83d12d6 Reviewed-by: Alexandru Croitor --- .../recipebrowser/doc/src/recipebrowser.qdoc | 14 +- examples/webengine/recipebrowser/recipebrowser.pro | 4 + .../resources/pages/assets/3rdparty/3RDPARTY.md | 23 -- .../pages/assets/3rdparty/MARKDOWN-LICENSE.txt | 16 ++ .../pages/assets/3rdparty/MARKED-LICENSE.txt | 19 ++ .../resources/pages/assets/3rdparty/default.md | 12 - .../pages/assets/3rdparty/qt_attribution.json | 35 +++ .../recipebrowser/resources/resources.qrc | 1 - .../webenginewidgets/markdowneditor/3RDPARTY.md | 23 -- .../markdowneditor/doc/src/markdowneditor.qdoc | 15 +- .../markdowneditor/markdowneditor.pro | 3 +- .../resources/3rdparty/MARKDOWN-LICENSE.txt | 16 ++ .../resources/3rdparty/MARKED-LICENSE.txt | 19 ++ .../markdowneditor/resources/3rdparty/markdown.css | 260 +++++++++++++++++++++ .../resources/3rdparty/marked.min.js | 6 + .../resources/3rdparty/qt_attribution.json | 35 +++ .../markdowneditor/resources/default.md | 2 +- .../markdowneditor/resources/index.html | 4 +- .../markdowneditor/resources/markdown.css | 260 --------------------- .../markdowneditor/resources/markdowneditor.qrc | 4 +- .../markdowneditor/resources/marked.min.js | 6 - 21 files changed, 444 insertions(+), 333 deletions(-) delete mode 100644 examples/webengine/recipebrowser/resources/pages/assets/3rdparty/3RDPARTY.md create mode 100644 examples/webengine/recipebrowser/resources/pages/assets/3rdparty/MARKDOWN-LICENSE.txt create mode 100644 examples/webengine/recipebrowser/resources/pages/assets/3rdparty/MARKED-LICENSE.txt delete mode 100644 examples/webengine/recipebrowser/resources/pages/assets/3rdparty/default.md create mode 100644 examples/webengine/recipebrowser/resources/pages/assets/3rdparty/qt_attribution.json delete mode 100644 examples/webenginewidgets/markdowneditor/3RDPARTY.md create mode 100644 examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKDOWN-LICENSE.txt create mode 100644 examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKED-LICENSE.txt create mode 100644 examples/webenginewidgets/markdowneditor/resources/3rdparty/markdown.css create mode 100644 examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.min.js create mode 100644 examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json delete mode 100644 examples/webenginewidgets/markdowneditor/resources/markdown.css delete mode 100644 examples/webenginewidgets/markdowneditor/resources/marked.min.js diff --git a/examples/webengine/recipebrowser/doc/src/recipebrowser.qdoc b/examples/webengine/recipebrowser/doc/src/recipebrowser.qdoc index d33f6bf10..7b8c6d5d0 100644 --- a/examples/webengine/recipebrowser/doc/src/recipebrowser.qdoc +++ b/examples/webengine/recipebrowser/doc/src/recipebrowser.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -213,4 +213,16 @@ \quotefromfile webengine/recipebrowser/resources/pages/soup.html \printuntil + \section1 Files and Attributions + + The example bundles the following code with third-party licenses: + + \table + \row + \li \l{recipebrowser-marked}{Marked} + \li MIT License + \row + \li \l{recipebrowser-markdowncss}{Markdown.css} + \li Apache License 2.0 + \endtable */ diff --git a/examples/webengine/recipebrowser/recipebrowser.pro b/examples/webengine/recipebrowser/recipebrowser.pro index ea6db13fb..c7e4dcaf8 100644 --- a/examples/webengine/recipebrowser/recipebrowser.pro +++ b/examples/webengine/recipebrowser/recipebrowser.pro @@ -10,5 +10,9 @@ SOURCES += main.cpp RESOURCES += resources/resources.qrc +DISTFILES += \ + resources/pages/assets/3rdparty/MARKDOWN-LICENSE.txt \ + resources/pages/assets/3rdparty/MARKED-LICENSE.txt + target.path = $$[QT_INSTALL_EXAMPLES]/webengine/recipebrowser INSTALLS += target diff --git a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/3RDPARTY.md b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/3RDPARTY.md deleted file mode 100644 index 9e91ab302..000000000 --- a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/3RDPARTY.md +++ /dev/null @@ -1,23 +0,0 @@ -## markd license - -``` -Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -``` diff --git a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/MARKDOWN-LICENSE.txt b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/MARKDOWN-LICENSE.txt new file mode 100644 index 000000000..23c52cc43 --- /dev/null +++ b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/MARKDOWN-LICENSE.txt @@ -0,0 +1,16 @@ +Copyright 2011 Kevin Burke unless otherwise noted. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Some content is copyrighted by Twitter, Inc., and also released under an +Apache License; these sections are noted in the source. diff --git a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/MARKED-LICENSE.txt b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/MARKED-LICENSE.txt new file mode 100644 index 000000000..a7b812ed6 --- /dev/null +++ b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/MARKED-LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/default.md b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/default.md deleted file mode 100644 index 8f9c807aa..000000000 --- a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/default.md +++ /dev/null @@ -1,12 +0,0 @@ -## WebEngine Markdown Editor Example - -This example uses [QWebEngineView](http://doc.qt.io/qt-5/qwebengineview.html) -to preview text written using the [Markdown](https://en.wikipedia.org/wiki/Markdown) -syntax. - -### Acknowledgments - -The conversion from Markdown to HTML is done with the help of the -[marked JavaScript library](https://github.com/chjj/marked) by _Christopher Jeffrey_. -The [style sheet](http://kevinburke.bitbucket.org/markdowncss/markdown.css) -was created by _Kevin Burke_. diff --git a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/qt_attribution.json b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/qt_attribution.json new file mode 100644 index 000000000..42947ca0b --- /dev/null +++ b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/qt_attribution.json @@ -0,0 +1,35 @@ +[ + { + "Id": "recipebrowser-marked", + "Name": "Marked (WebEngine RecipeBrowser example)", + "QDocModule": "qtwebengine", + "QtUsage": "Marked is used in the WebEngine RecipeBrowser example", + "QtParts": [ "examples" ], + "Files": "marked.min.js", + "Description": "A full-featured markdown parser and compiler, written in JavaScript. Built for speed.", + "Homepage": "https://github.com/chjj/marked", + "Version": "0.3.6", + "DownloadLocation": "https://github.com/chjj/marked/blob/v0.3.6/marked.min.js", + "Copyright": "Copyright (c) 2011-2014, Christopher Jeffrey", + "License": "MIT License", + "LicenseId": "MIT", + "LicenseFile": "MARKED-LICENSE.txt" + }, + { + "Id": "recipebrowser-markdowncss", + "Name": "Markdown.css (WebEngine RecipeBrowser example)", + "QDocModule": "qtwebengine", + "QtUsage": "markdown.css is used in the WebEngine RecipeBrowser example", + "QtParts": [ "examples" ], + "Files": "markdown.css", + "Description": "Markdown.css is better default styling for your Markdown files.", + "Homepage": "https://kevinburke.bitbucket.io/markdowncss/", + "Version": "188530e4b5d020d7e237fc6b26be13ebf4a8def3", + "DownloadLocation": "https://bitbucket.org/kevinburke/markdowncss/src/188530e4b5d020d7e237fc6b26be13ebf4a8def3/markdown.css", + "Copyright": "Copyright 2011 Kevin Burke + Copyright Twitter Inc.", + "License": "Apache License 2.0", + "LicenseId": "Apache-2.0", + "LicenseFile": "MARKDOWN-LICENSE.txt" + } +] diff --git a/examples/webengine/recipebrowser/resources/resources.qrc b/examples/webengine/recipebrowser/resources/resources.qrc index ae5aa2ed3..88919159b 100644 --- a/examples/webengine/recipebrowser/resources/resources.qrc +++ b/examples/webengine/recipebrowser/resources/resources.qrc @@ -12,7 +12,6 @@ pages/cupcakes.html pages/assets/3rdparty/marked.min.js - pages/assets/3rdparty/default.md pages/assets/3rdparty/markdown.css pages/assets/custom.css pages/assets/custom.js diff --git a/examples/webenginewidgets/markdowneditor/3RDPARTY.md b/examples/webenginewidgets/markdowneditor/3RDPARTY.md deleted file mode 100644 index 9e91ab302..000000000 --- a/examples/webenginewidgets/markdowneditor/3RDPARTY.md +++ /dev/null @@ -1,23 +0,0 @@ -## markd license - -``` -Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -``` diff --git a/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc b/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc index a20dc04c5..b06d4ee84 100644 --- a/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc +++ b/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -166,5 +166,18 @@ Finally, we set up the web channel to access the \c content proxy object and make sure that \c updateText() is called whenever \c content.text changes. + + \section1 Files and Attributions + + The example bundles the following code with third-party licenses: + + \table + \row + \li \l{markdowneditor-marked}{Marked} + \li MIT License + \row + \li \l{markdowneditor-markdowncss}{Markdown.css} + \li Apache License 2.0 + \endtable */ diff --git a/examples/webenginewidgets/markdowneditor/markdowneditor.pro b/examples/webenginewidgets/markdowneditor/markdowneditor.pro index bfd16698a..2f58ae061 100644 --- a/examples/webenginewidgets/markdowneditor/markdowneditor.pro +++ b/examples/webenginewidgets/markdowneditor/markdowneditor.pro @@ -21,7 +21,8 @@ FORMS += \ mainwindow.ui DISTFILES += \ - 3RDPARTY.md + resources/3rdparty/MARKDOWN-LICENSE.txt \ + resources/3rdparty/MARKED-LICENSE.txt # install target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/markdowneditor diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKDOWN-LICENSE.txt b/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKDOWN-LICENSE.txt new file mode 100644 index 000000000..23c52cc43 --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKDOWN-LICENSE.txt @@ -0,0 +1,16 @@ +Copyright 2011 Kevin Burke unless otherwise noted. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Some content is copyrighted by Twitter, Inc., and also released under an +Apache License; these sections are noted in the source. diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKED-LICENSE.txt b/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKED-LICENSE.txt new file mode 100644 index 000000000..a7b812ed6 --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKED-LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/markdown.css b/examples/webenginewidgets/markdowneditor/resources/3rdparty/markdown.css new file mode 100644 index 000000000..24fc2ffe2 --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/resources/3rdparty/markdown.css @@ -0,0 +1,260 @@ +body{ + margin: 0 auto; + font-family: Georgia, Palatino, serif; + color: #444444; + line-height: 1; + max-width: 960px; + padding: 30px; +} +h1, h2, h3, h4 { + color: #111111; + font-weight: 400; +} +h1, h2, h3, h4, h5, p { + margin-bottom: 24px; + padding: 0; +} +h1 { + font-size: 48px; +} +h2 { + font-size: 36px; + /* The bottom margin is small. It's designed to be used with gray meta text + * below a post title. */ + margin: 24px 0 6px; +} +h3 { + font-size: 24px; +} +h4 { + font-size: 21px; +} +h5 { + font-size: 18px; +} +a { + color: #0099ff; + margin: 0; + padding: 0; + vertical-align: baseline; +} +a:hover { + text-decoration: none; + color: #ff6600; +} +a:visited { + color: purple; +} +ul, ol { + padding: 0; + margin: 0; +} +li { + line-height: 24px; +} +li ul, li ul { + margin-left: 24px; +} +p, ul, ol { + font-size: 16px; + line-height: 24px; + max-width: 540px; +} +pre { + padding: 0px 24px; + max-width: 800px; + white-space: pre-wrap; +} +code { + font-family: Consolas, Monaco, Andale Mono, monospace; + line-height: 1.5; + font-size: 13px; +} +aside { + display: block; + float: right; + width: 390px; +} +blockquote { + border-left:.5em solid #eee; + padding: 0 2em; + margin-left:0; + max-width: 476px; +} +blockquote cite { + font-size:14px; + line-height:20px; + color:#bfbfbf; +} +blockquote cite:before { + content: '\2014 \00A0'; +} + +blockquote p { + color: #666; + max-width: 460px; +} +hr { + width: 540px; + text-align: left; + margin: 0 auto 0 0; + color: #999; +} + +/* Code below this line is copyright Twitter Inc. */ + +button, +input, +select, +textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; +} +button, input { + line-height: normal; + *overflow: visible; +} +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0; +} +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} +input[type=checkbox], input[type=radio] { + cursor: pointer; +} +/* override default chrome & firefox settings */ +input:not([type="image"]), textarea { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +input[type="search"] { + -webkit-appearance: textfield; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +label, +input, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: normal; + margin-bottom: 18px; +} +input[type=checkbox], input[type=radio] { + cursor: pointer; + margin-bottom: 0; +} +input[type=text], +input[type=password], +textarea, +select { + display: inline-block; + width: 210px; + padding: 4px; + font-size: 13px; + font-weight: normal; + line-height: 18px; + height: 18px; + color: #808080; + border: 1px solid #ccc; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +select, input[type=file] { + height: 27px; + line-height: 27px; +} +textarea { + height: auto; +} + +/* grey out placeholders */ +:-moz-placeholder { + color: #bfbfbf; +} +::-webkit-input-placeholder { + color: #bfbfbf; +} + +input[type=text], +input[type=password], +select, +textarea { + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); +} +input[type=text]:focus, input[type=password]:focus, textarea:focus { + outline: none; + border-color: rgba(82, 168, 236, 0.8); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); +} + +/* buttons */ +button { + display: inline-block; + padding: 4px 14px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + line-height: 18px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + background-color: #0064cd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); + background-image: -moz-linear-gradient(top, #049cdb, #0064cd); + background-image: -ms-linear-gradient(top, #049cdb, #0064cd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); + background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); + background-image: -o-linear-gradient(top, #049cdb, #0064cd); + background-image: linear-gradient(top, #049cdb, #0064cd); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border: 1px solid #004b9a; + border-bottom-color: #003f81; + -webkit-transition: 0.1s linear all; + -moz-transition: 0.1s linear all; + transition: 0.1s linear all; + border-color: #0064cd #0064cd #003f81; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +button:hover { + color: #fff; + background-position: 0 -15px; + text-decoration: none; +} +button:active { + -webkit-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} +button::-moz-focus-inner { + padding: 0; + border: 0; +} diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.min.js b/examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.min.js new file mode 100644 index 000000000..f3542fff0 --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.min.js @@ -0,0 +1,6 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) + * https://github.com/chjj/marked + */ +(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",//)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]||""});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&(cap[1]==="pre"||cap[1]==="script"||cap[1]==="style"),text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^/i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(cap[0]):escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.text(escape(this.smartypants(cap[0])));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){if(!this.options.mangle)return text;var out="",l=text.length,i=0,ch;for(;i.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return"
"+(escaped?code:escape(code,true))+"\n
"}return'
'+(escaped?code:escape(code,true))+"\n
\n"};Renderer.prototype.blockquote=function(quote){return"
\n"+quote+"
\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"'+text+"\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"
\n":"
\n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"\n"};Renderer.prototype.listitem=function(text){return"
  • "+text+"
  • \n"};Renderer.prototype.paragraph=function(text){return"

    "+text+"

    \n"};Renderer.prototype.table=function(header,body){return"\n"+"\n"+header+"\n"+"\n"+body+"\n"+"
    \n"};Renderer.prototype.tablerow=function(content){return"\n"+content+"\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"\n"};Renderer.prototype.strong=function(text){return""+text+""};Renderer.prototype.em=function(text){return""+text+""};Renderer.prototype.codespan=function(text){return""+text+""};Renderer.prototype.br=function(){return this.options.xhtml?"
    ":"
    "};Renderer.prototype.del=function(text){return""+text+""};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0||prot.indexOf("vbscript:")===0){return""}}var out='
    ";return out};Renderer.prototype.image=function(href,title,text){var out=''+text+'":">";return out};Renderer.prototype.text=function(text){return text};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i/g,">").replace(/"/g,""").replace(/'/g,"'")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;iAn error occurred:

    "+escape(e.message+"",true)+"
    "}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,sanitizer:null,mangle:true,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); \ No newline at end of file diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json b/examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json new file mode 100644 index 000000000..3400ef27a --- /dev/null +++ b/examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json @@ -0,0 +1,35 @@ +[ + { + "Id": "markdowneditor-marked", + "Name": "Marked (WebEngine Markdown Editor example)", + "QDocModule": "qtwebengine", + "QtUsage": "Marked is used in the WebEngine MarkDown Editor example", + "QtParts": [ "examples" ], + "Files": "marked.min.js", + "Description": "A full-featured markdown parser and compiler, written in JavaScript. Built for speed.", + "Homepage": "https://github.com/chjj/marked", + "Version": "0.3.6", + "DownloadLocation": "https://github.com/chjj/marked/blob/v0.3.6/marked.min.js", + "Copyright": "Copyright (c) 2011-2014, Christopher Jeffrey", + "License": "MIT License", + "LicenseId": "MIT", + "LicenseFile": "MARKED-LICENSE.txt" + }, + { + "Id": "markdowneditor-markdowncss", + "Name": "Markdown.css (WebEngine Markdown Editor example)", + "QDocModule": "qtwebengine", + "QtUsage": "markdown.css is used in the WebEngine MarkDown Editor example", + "QtParts": [ "examples" ], + "Files": "markdown.css", + "Description": "Markdown.css is better default styling for your Markdown files.", + "Homepage": "https://kevinburke.bitbucket.io/markdowncss/", + "Version": "188530e4b5d020d7e237fc6b26be13ebf4a8def3", + "DownloadLocation": "https://bitbucket.org/kevinburke/markdowncss/src/188530e4b5d020d7e237fc6b26be13ebf4a8def3/markdown.css", + "Copyright": "Copyright 2011 Kevin Burke + Copyright Twitter Inc.", + "License": "Apache License 2.0", + "LicenseId": "Apache-2.0", + "LicenseFile": "MARKDOWN-LICENSE.txt" + } +] diff --git a/examples/webenginewidgets/markdowneditor/resources/default.md b/examples/webenginewidgets/markdowneditor/resources/default.md index 8f9c807aa..af835fa4d 100644 --- a/examples/webenginewidgets/markdowneditor/resources/default.md +++ b/examples/webenginewidgets/markdowneditor/resources/default.md @@ -8,5 +8,5 @@ syntax. The conversion from Markdown to HTML is done with the help of the [marked JavaScript library](https://github.com/chjj/marked) by _Christopher Jeffrey_. -The [style sheet](http://kevinburke.bitbucket.org/markdowncss/markdown.css) +The [style sheet](https://kevinburke.bitbucket.io/markdowncss/) was created by _Kevin Burke_. diff --git a/examples/webenginewidgets/markdowneditor/resources/index.html b/examples/webenginewidgets/markdowneditor/resources/index.html index 2f45479ed..8623a0642 100644 --- a/examples/webenginewidgets/markdowneditor/resources/index.html +++ b/examples/webenginewidgets/markdowneditor/resources/index.html @@ -2,8 +2,8 @@ - - + + diff --git a/examples/webenginewidgets/markdowneditor/resources/markdown.css b/examples/webenginewidgets/markdowneditor/resources/markdown.css deleted file mode 100644 index 24fc2ffe2..000000000 --- a/examples/webenginewidgets/markdowneditor/resources/markdown.css +++ /dev/null @@ -1,260 +0,0 @@ -body{ - margin: 0 auto; - font-family: Georgia, Palatino, serif; - color: #444444; - line-height: 1; - max-width: 960px; - padding: 30px; -} -h1, h2, h3, h4 { - color: #111111; - font-weight: 400; -} -h1, h2, h3, h4, h5, p { - margin-bottom: 24px; - padding: 0; -} -h1 { - font-size: 48px; -} -h2 { - font-size: 36px; - /* The bottom margin is small. It's designed to be used with gray meta text - * below a post title. */ - margin: 24px 0 6px; -} -h3 { - font-size: 24px; -} -h4 { - font-size: 21px; -} -h5 { - font-size: 18px; -} -a { - color: #0099ff; - margin: 0; - padding: 0; - vertical-align: baseline; -} -a:hover { - text-decoration: none; - color: #ff6600; -} -a:visited { - color: purple; -} -ul, ol { - padding: 0; - margin: 0; -} -li { - line-height: 24px; -} -li ul, li ul { - margin-left: 24px; -} -p, ul, ol { - font-size: 16px; - line-height: 24px; - max-width: 540px; -} -pre { - padding: 0px 24px; - max-width: 800px; - white-space: pre-wrap; -} -code { - font-family: Consolas, Monaco, Andale Mono, monospace; - line-height: 1.5; - font-size: 13px; -} -aside { - display: block; - float: right; - width: 390px; -} -blockquote { - border-left:.5em solid #eee; - padding: 0 2em; - margin-left:0; - max-width: 476px; -} -blockquote cite { - font-size:14px; - line-height:20px; - color:#bfbfbf; -} -blockquote cite:before { - content: '\2014 \00A0'; -} - -blockquote p { - color: #666; - max-width: 460px; -} -hr { - width: 540px; - text-align: left; - margin: 0 auto 0 0; - color: #999; -} - -/* Code below this line is copyright Twitter Inc. */ - -button, -input, -select, -textarea { - font-size: 100%; - margin: 0; - vertical-align: baseline; - *vertical-align: middle; -} -button, input { - line-height: normal; - *overflow: visible; -} -button::-moz-focus-inner, input::-moz-focus-inner { - border: 0; - padding: 0; -} -button, -input[type="button"], -input[type="reset"], -input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; -} -input[type=checkbox], input[type=radio] { - cursor: pointer; -} -/* override default chrome & firefox settings */ -input:not([type="image"]), textarea { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -input[type="search"] { - -webkit-appearance: textfield; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -} -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} -label, -input, -select, -textarea { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - font-weight: normal; - line-height: normal; - margin-bottom: 18px; -} -input[type=checkbox], input[type=radio] { - cursor: pointer; - margin-bottom: 0; -} -input[type=text], -input[type=password], -textarea, -select { - display: inline-block; - width: 210px; - padding: 4px; - font-size: 13px; - font-weight: normal; - line-height: 18px; - height: 18px; - color: #808080; - border: 1px solid #ccc; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -select, input[type=file] { - height: 27px; - line-height: 27px; -} -textarea { - height: auto; -} - -/* grey out placeholders */ -:-moz-placeholder { - color: #bfbfbf; -} -::-webkit-input-placeholder { - color: #bfbfbf; -} - -input[type=text], -input[type=password], -select, -textarea { - -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; - -moz-transition: border linear 0.2s, box-shadow linear 0.2s; - transition: border linear 0.2s, box-shadow linear 0.2s; - -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); -} -input[type=text]:focus, input[type=password]:focus, textarea:focus { - outline: none; - border-color: rgba(82, 168, 236, 0.8); - -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); - -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); - box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); -} - -/* buttons */ -button { - display: inline-block; - padding: 4px 14px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - line-height: 18px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - background-color: #0064cd; - background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); - background-image: -moz-linear-gradient(top, #049cdb, #0064cd); - background-image: -ms-linear-gradient(top, #049cdb, #0064cd); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); - background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); - background-image: -o-linear-gradient(top, #049cdb, #0064cd); - background-image: linear-gradient(top, #049cdb, #0064cd); - color: #fff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - border: 1px solid #004b9a; - border-bottom-color: #003f81; - -webkit-transition: 0.1s linear all; - -moz-transition: 0.1s linear all; - transition: 0.1s linear all; - border-color: #0064cd #0064cd #003f81; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} -button:hover { - color: #fff; - background-position: 0 -15px; - text-decoration: none; -} -button:active { - -webkit-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -} -button::-moz-focus-inner { - padding: 0; - border: 0; -} diff --git a/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc b/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc index 8b7471a9c..9a6bd3801 100644 --- a/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc +++ b/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc @@ -2,8 +2,8 @@ index.html qwebchannel.js - marked.min.js + 3rdparty/marked.min.js default.md - markdown.css + 3rdparty/markdown.css diff --git a/examples/webenginewidgets/markdowneditor/resources/marked.min.js b/examples/webenginewidgets/markdowneditor/resources/marked.min.js deleted file mode 100644 index f3542fff0..000000000 --- a/examples/webenginewidgets/markdowneditor/resources/marked.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * marked - a markdown parser - * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) - * https://github.com/chjj/marked - */ -(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",//)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]||""});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&(cap[1]==="pre"||cap[1]==="script"||cap[1]==="style"),text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^
    /i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(cap[0]):escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.text(escape(this.smartypants(cap[0])));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){if(!this.options.mangle)return text;var out="",l=text.length,i=0,ch;for(;i.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return"
    "+(escaped?code:escape(code,true))+"\n
    "}return'
    '+(escaped?code:escape(code,true))+"\n
    \n"};Renderer.prototype.blockquote=function(quote){return"
    \n"+quote+"
    \n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"'+text+"\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"
    \n":"
    \n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"\n"};Renderer.prototype.listitem=function(text){return"
  • "+text+"
  • \n"};Renderer.prototype.paragraph=function(text){return"

    "+text+"

    \n"};Renderer.prototype.table=function(header,body){return"\n"+"\n"+header+"\n"+"\n"+body+"\n"+"
    \n"};Renderer.prototype.tablerow=function(content){return"\n"+content+"\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"\n"};Renderer.prototype.strong=function(text){return""+text+""};Renderer.prototype.em=function(text){return""+text+""};Renderer.prototype.codespan=function(text){return""+text+""};Renderer.prototype.br=function(){return this.options.xhtml?"
    ":"
    "};Renderer.prototype.del=function(text){return""+text+""};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0||prot.indexOf("vbscript:")===0){return""}}var out='
    ";return out};Renderer.prototype.image=function(href,title,text){var out=''+text+'":">";return out};Renderer.prototype.text=function(text){return text};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i/g,">").replace(/"/g,""").replace(/'/g,"'")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;iAn error occurred:

    "+escape(e.message+"",true)+"
    "}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,sanitizer:null,mangle:true,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); \ No newline at end of file -- cgit v1.2.3 From 19e5c2057b9f127726018d3e39a62066317a983f Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 13 Jul 2017 14:37:18 +0200 Subject: Fix propagation of unhandled key press events Unhandled key presses for printable keys were not received by the parent widget anymore. This was a regression from 5.8.0. The propagation is suppressed if NativeWebKeyboardEvent::skip_in_browser is true. Commit 4501b9d8 accidentally removed the wrong skip_in_browser assignment. Task-number: QTBUG-61621 Change-Id: I7eafa1fac5fb9a7edc4af2bc1aac21c106264713 Reviewed-by: Peter Varga --- src/core/render_widget_host_view_qt.cpp | 5 +++-- tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp | 11 ++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 131f2a664..dd372b72f 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -1145,8 +1145,9 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) if (keyDownTextInsertion) { // Blink won't consume the RawKeyDown, but rather the Char event in this case. - // Make sure to skip the former on the way back. The same os_event will be set on both of them. - webEvent.skip_in_browser = true; + // The RawKeyDown is skipped on the way back (see above). + // The same os_event will be set on both NativeWebKeyboardEvents. + webEvent.skip_in_browser = false; webEvent.type = blink::WebInputEvent::Char; m_host->ForwardKeyboardEvent(webEvent); } diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 8509e9a2d..7fbbd63d3 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -447,16 +447,25 @@ void tst_QWebEngineView::unhandledKeyEventPropagation() QTRY_COMPARE(parentWidget.releaseEvents.size(), 3); QCOMPARE(evaluateJavaScriptSync(webView.page(), "document.activeElement.id").toString(), QStringLiteral("second_div")); + // Focus the button and press 'y'. + evaluateJavaScriptSync(webView.page(), "document.getElementById('submit_button').focus()"); + QTRY_COMPARE(evaluateJavaScriptSync(webView.page(), "document.activeElement.id").toString(), QStringLiteral("submit_button")); + QTest::sendKeyEvent(QTest::Press, webView.focusProxy(), Qt::Key_Y, 'y', Qt::NoModifier); + QTest::sendKeyEvent(QTest::Release, webView.focusProxy(), Qt::Key_Y, 'y', Qt::NoModifier); + QTRY_COMPARE(parentWidget.releaseEvents.size(), 4); + // The page will consume the Tab key to change focus between elements while the arrow // keys won't be used. - QCOMPARE(parentWidget.pressEvents.size(), 2); + QCOMPARE(parentWidget.pressEvents.size(), 3); QCOMPARE(parentWidget.pressEvents[0].key(), (int)Qt::Key_Right); QCOMPARE(parentWidget.pressEvents[1].key(), (int)Qt::Key_Left); + QCOMPARE(parentWidget.pressEvents[2].key(), (int)Qt::Key_Y); // Key releases will all come back unconsumed. QCOMPARE(parentWidget.releaseEvents[0].key(), (int)Qt::Key_Right); QCOMPARE(parentWidget.releaseEvents[1].key(), (int)Qt::Key_Tab); QCOMPARE(parentWidget.releaseEvents[2].key(), (int)Qt::Key_Left); + QCOMPARE(parentWidget.releaseEvents[3].key(), (int)Qt::Key_Y); } void tst_QWebEngineView::horizontalScrollbarTest() -- cgit v1.2.3 From c218716497093e5961c24b7c7fb9ed2c4160c204 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 13 Jul 2017 09:41:12 +0200 Subject: Yield error if the build directory contains spaces Task-number: QTBUG-61275 Change-Id: I7e741ffaaa4044b3b61b6df06ea3eab181db9c97 Reviewed-by: Michal Klocek --- qtwebengine.pro | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/qtwebengine.pro b/qtwebengine.pro index 5ae80ea8c..034e946c4 100644 --- a/qtwebengine.pro +++ b/qtwebengine.pro @@ -1,10 +1,13 @@ load(qt_parts) isPlatformSupported() { - !exists(src/3rdparty/chromium): \ - error("Submodule qtwebengine-chromium does not exist. Run 'git submodule update --init'.") - load(configure) - runConfigure() + !exists(src/3rdparty/chromium): \ + error("Submodule qtwebengine-chromium does not exist. Run 'git submodule update --init'.") + WSPC = $$find(OUT_PWD, \\s) + !isEmpty(WSPC): \ + error("QtWebEngine cannot be built in a path that contains whitespace characters.") + load(configure) + runConfigure() } !isEmpty(skipBuildReason) { -- cgit v1.2.3 From 57f1127b8e4663e420a34e5ab5d90ca4d3665925 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 17 Jul 2017 17:32:37 +0200 Subject: Support command-line argument --force-webrtc-ip-handling-policy This command-line argument makes it possibly to block exposure of internal IP addresses when WebRTC access hasn't been granted, using --force-webrtc-ip-handling-policy=default_public_interface_only Task-number: QTBUG-57505 Change-Id: I0cddd1b20e0814811894204cb31e0c463a75f7be Reviewed-by: Kai Koehne --- src/core/web_contents_adapter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 93e8674bd..a788b9679 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -73,6 +73,7 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/favicon_status.h" #include "content/public/common/content_constants.h" +#include "content/public/common/content_switches.h" #include #include "content/public/common/page_state.h" #include "content/public/common/page_zoom.h" @@ -419,6 +420,11 @@ void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) rendererPrefs->caret_blink_interval = 0.5 * static_cast(qtCursorFlashTime) / 1000; rendererPrefs->user_agent_override = d->browserContextAdapter->httpUserAgent().toStdString(); rendererPrefs->accept_languages = d->browserContextAdapter->httpAcceptLanguageWithoutQualities().toStdString(); +#if defined(ENABLE_WEBRTC) + base::CommandLine* commandLine = base::CommandLine::ForCurrentProcess(); + if (commandLine->HasSwitch(switches::kForceWebRtcIPHandlingPolicy)) + rendererPrefs->webrtc_ip_handling_policy = commandLine->GetSwitchValueASCII(switches::kForceWebRtcIPHandlingPolicy); +#endif d->webContents->GetRenderViewHost()->SyncRendererPrefs(); // Create and attach observers to the WebContents. -- cgit v1.2.3 From 009f5ebb4bd6e50188671e0815a5dae6afe39db5 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Tue, 27 Jun 2017 12:29:17 +0200 Subject: Fix C-ABI breakage Re-export missing C memory handling functions. Task-number: QTBUG-61521 Change-Id: I8f94d93a70c81117735a9610e391a1e31c54f15a Reviewed-by: Allan Sandfeld Jensen --- src/core/api/core_api.pro | 4 +- src/core/api/qtbug-61521.cpp | 121 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/core/api/qtbug-61521.cpp diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index d3d47e03a..05166536e 100644 --- a/src/core/api/core_api.pro +++ b/src/core/api/core_api.pro @@ -50,6 +50,8 @@ SOURCES = \ qwebengineurlrequestjob.cpp \ qwebengineurlschemehandler.cpp +### Qt6 Remove this workaround unix:!isEmpty(QMAKE_LFLAGS_VERSION_SCRIPT):!static { - SOURCES += qtbug-60565.cpp + SOURCES += qtbug-60565.cpp \ + qtbug-61521.cpp } diff --git a/src/core/api/qtbug-61521.cpp b/src/core/api/qtbug-61521.cpp new file mode 100644 index 000000000..86d5998ef --- /dev/null +++ b/src/core/api/qtbug-61521.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#define SHIM_ALIAS_SYMBOL(fn) __attribute__((weak, alias(#fn))) +#define SHIM_SYMBOL_VERSION(fn) __asm__(".symver __" #fn "," #fn "@Qt_5") +#define SHIM_HIDDEN __attribute__ ((visibility ("hidden"))) + +extern "C" { + +SHIM_SYMBOL_VERSION(malloc); +void* __malloc(size_t size) + SHIM_ALIAS_SYMBOL(ShimMalloc); + +SHIM_SYMBOL_VERSION(free); +void __free(void* ptr) + SHIM_ALIAS_SYMBOL(ShimFree); + +SHIM_SYMBOL_VERSION(realloc); +void* __realloc(void* ptr, size_t size) + SHIM_ALIAS_SYMBOL(ShimRealloc); + +SHIM_SYMBOL_VERSION(calloc); +void* __calloc(size_t n, size_t size) + SHIM_ALIAS_SYMBOL(ShimCalloc); + +SHIM_SYMBOL_VERSION(cfree); +void __cfree(void* ptr) + SHIM_ALIAS_SYMBOL(ShimCFree); + +SHIM_SYMBOL_VERSION(memalign); +void* __memalign(size_t align, size_t s) + SHIM_ALIAS_SYMBOL(ShimMemalign); + +SHIM_SYMBOL_VERSION(valloc); +void* __valloc(size_t size) + SHIM_ALIAS_SYMBOL(ShimValloc); + +SHIM_SYMBOL_VERSION(pvalloc); +void* __pvalloc(size_t size) + SHIM_ALIAS_SYMBOL(ShimPvalloc); + +SHIM_SYMBOL_VERSION(posix_memalign); +int __posix_memalign(void** r, size_t a, size_t s) + SHIM_ALIAS_SYMBOL(ShimPosixMemalign); + +SHIM_HIDDEN void* ShimMalloc(size_t size) { + return malloc(size); +} + +SHIM_HIDDEN void ShimFree(void* ptr) { + free(ptr); +} + +SHIM_HIDDEN void* ShimRealloc(void* ptr, size_t size) { + return realloc(ptr,size); +} + +SHIM_HIDDEN void* ShimCalloc(size_t n, size_t size) { + return calloc(n,size); +} + +SHIM_HIDDEN void ShimCFree(void* ptr) { + cfree(ptr); +} + +SHIM_HIDDEN void* ShimMemalign(size_t align, size_t s) { + return memalign(align,s); +} + +SHIM_HIDDEN void* ShimValloc(size_t size) { + return valloc(size); +} + +SHIM_HIDDEN void* ShimPvalloc(size_t size) { + return pvalloc(size); +} + +SHIM_HIDDEN int ShimPosixMemalign(void** r, size_t a, size_t s) { + return posix_memalign(r,a,s); +} +} // extern "C" -- cgit v1.2.3 From ae71f77d5f680d8b40c9598321a687318a7ff0b2 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 18 Jul 2017 13:30:21 +0200 Subject: Remove third_party/afl from Chromium snapshot Task-number: QTBUG-61954 Change-Id: I681f7adaab1e0ef1ec162fa98c4a70569e8c3948 Reviewed-by: Allan Sandfeld Jensen --- tools/scripts/take_snapshot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/scripts/take_snapshot.py b/tools/scripts/take_snapshot.py index 7af70bf22..4a1031e80 100755 --- a/tools/scripts/take_snapshot.py +++ b/tools/scripts/take_snapshot.py @@ -146,6 +146,7 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('third_party/WebKit/ManualTests') or file_path.startswith('third_party/WebKit/PerformanceTests') or file_path.startswith('third_party/accessibility-audit') + or file_path.startswith('third_party/afl') or file_path.startswith('third_party/android_') or file_path.startswith('third_party/apache-win32') or file_path.startswith('third_party/apple_sample_code') -- cgit v1.2.3 From a71efecbcc6f714d619a922a0eaa665a3c68a3b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCri=20Valdmann?= Date: Mon, 12 Jun 2017 15:57:31 +0200 Subject: Update Simple Browser example - Accept downloads and add a downloads list. - Fix toolbar icons being pixelated on hidpi screens by - enabling attribute AA_UseHighDpiPixmaps, and - replacing the 22x22 icons with 32x32 versions. - Move favicon selection to WebView to reduce duplication. - Replace UrlLineEdit with a standard QLineEdit using a QAction for the favicon and setClearButtonEnabled(true) for the clear button. - Fix bug where the "File -> New Tab" action would create background tabs because the QAction::triggered(bool) signal was connected to the TabWidget::createTab(bool) slot with the bool argument having a completely different meaning between the two. - Make the toolbar unmovable. Nobody wants to move the toolbar. - Add tooltips to toolbar buttons. - Add tooltips to the tab bar (page titles). - Stop adding icons to menu items only to disable them right after. Task-number: QTBUG-60655 Change-Id: I10cc0fa82dbf39281bbdbbf9ef901e1b26402f80 Reviewed-by: Leena Miettinen Reviewed-by: Michal Klocek --- .../webenginewidgets/simplebrowser/browser.cpp | 34 ++--- examples/webenginewidgets/simplebrowser/browser.h | 14 +- .../simplebrowser/browserwindow.cpp | 109 ++++++--------- .../webenginewidgets/simplebrowser/browserwindow.h | 18 ++- .../simplebrowser/data/AppLogoColor.png | Bin 0 -> 6113 bytes .../webenginewidgets/simplebrowser/data/addtab.png | Bin 469 -> 0 bytes .../simplebrowser/data/closetab.png | Bin 516 -> 0 bytes .../simplebrowser/data/defaulticon.png | Bin 1473 -> 0 bytes .../simplebrowser/data/dialog-error.png | Bin 0 -> 1645 bytes .../simplebrowser/data/edit-clear.png | Bin 0 -> 1682 bytes .../simplebrowser/data/go-bottom.png | Bin 0 -> 1263 bytes .../simplebrowser/data/go-next.png | Bin 930 -> 1219 bytes .../simplebrowser/data/go-previous.png | Bin 955 -> 1200 bytes .../simplebrowser/data/process-stop.png | Bin 1272 -> 1927 bytes .../simplebrowser/data/simplebrowser.qrc | 9 +- .../simplebrowser/data/simplebrowser.svg | 24 ---- .../simplebrowser/data/text-html.png | Bin 0 -> 1759 bytes .../simplebrowser/data/view-refresh.png | Bin 1364 -> 2024 bytes .../simplebrowser/doc/images/simplebrowser.png | Bin 70625 -> 47620 bytes .../simplebrowser/doc/src/simplebrowser.qdoc | 69 +++++++--- .../simplebrowser/downloadmanagerwidget.cpp | 86 ++++++++++++ .../simplebrowser/downloadmanagerwidget.h | 73 ++++++++++ .../simplebrowser/downloadmanagerwidget.ui | 104 ++++++++++++++ .../simplebrowser/downloadwidget.cpp | 152 +++++++++++++++++++++ .../simplebrowser/downloadwidget.h | 74 ++++++++++ .../simplebrowser/downloadwidget.ui | 80 +++++++++++ examples/webenginewidgets/simplebrowser/main.cpp | 29 ++-- .../simplebrowser/simplebrowser.pro | 18 ++- .../webenginewidgets/simplebrowser/tabwidget.cpp | 52 +++---- .../webenginewidgets/simplebrowser/tabwidget.h | 6 +- .../webenginewidgets/simplebrowser/urllineedit.cpp | 95 ------------- .../webenginewidgets/simplebrowser/urllineedit.h | 70 ---------- .../simplebrowser/webpopupwindow.cpp | 35 ++--- .../simplebrowser/webpopupwindow.h | 9 +- .../webenginewidgets/simplebrowser/webview.cpp | 44 ++++-- examples/webenginewidgets/simplebrowser/webview.h | 2 + 36 files changed, 801 insertions(+), 405 deletions(-) create mode 100644 examples/webenginewidgets/simplebrowser/data/AppLogoColor.png delete mode 100644 examples/webenginewidgets/simplebrowser/data/addtab.png delete mode 100644 examples/webenginewidgets/simplebrowser/data/closetab.png delete mode 100644 examples/webenginewidgets/simplebrowser/data/defaulticon.png create mode 100644 examples/webenginewidgets/simplebrowser/data/dialog-error.png create mode 100644 examples/webenginewidgets/simplebrowser/data/edit-clear.png create mode 100644 examples/webenginewidgets/simplebrowser/data/go-bottom.png delete mode 100644 examples/webenginewidgets/simplebrowser/data/simplebrowser.svg create mode 100644 examples/webenginewidgets/simplebrowser/data/text-html.png create mode 100644 examples/webenginewidgets/simplebrowser/downloadmanagerwidget.cpp create mode 100644 examples/webenginewidgets/simplebrowser/downloadmanagerwidget.h create mode 100644 examples/webenginewidgets/simplebrowser/downloadmanagerwidget.ui create mode 100644 examples/webenginewidgets/simplebrowser/downloadwidget.cpp create mode 100644 examples/webenginewidgets/simplebrowser/downloadwidget.h create mode 100644 examples/webenginewidgets/simplebrowser/downloadwidget.ui delete mode 100644 examples/webenginewidgets/simplebrowser/urllineedit.cpp delete mode 100644 examples/webenginewidgets/simplebrowser/urllineedit.h diff --git a/examples/webenginewidgets/simplebrowser/browser.cpp b/examples/webenginewidgets/simplebrowser/browser.cpp index f1420c2a3..5eae4f3c1 100644 --- a/examples/webenginewidgets/simplebrowser/browser.cpp +++ b/examples/webenginewidgets/simplebrowser/browser.cpp @@ -40,38 +40,26 @@ #include "browser.h" #include "browserwindow.h" -#include "webview.h" -#include -Browser::Browser() -{ -} - -Browser::~Browser() -{ - qDeleteAll(m_windows); - m_windows.clear(); -} +#include -Browser &Browser::instance() +Browser::Browser() { - static Browser browser; - return browser; -} + // Quit application if the download manager window is the only remaining window + m_downloadManagerWidget.setAttribute(Qt::WA_QuitOnClose, false); -QVector Browser::windows() -{ - return m_windows; + QObject::connect( + QWebEngineProfile::defaultProfile(), &QWebEngineProfile::downloadRequested, + &m_downloadManagerWidget, &DownloadManagerWidget::downloadRequested); } -void Browser::addWindow(BrowserWindow *mainWindow) +BrowserWindow *Browser::createWindow() { - if (m_windows.contains(mainWindow)) - return; - m_windows.prepend(mainWindow); + auto mainWindow = new BrowserWindow(this); + m_windows.append(mainWindow); QObject::connect(mainWindow, &QObject::destroyed, [this, mainWindow]() { m_windows.removeOne(mainWindow); }); mainWindow->show(); + return mainWindow; } - diff --git a/examples/webenginewidgets/simplebrowser/browser.h b/examples/webenginewidgets/simplebrowser/browser.h index 0fdbd46a7..27e2aaf43 100644 --- a/examples/webenginewidgets/simplebrowser/browser.h +++ b/examples/webenginewidgets/simplebrowser/browser.h @@ -41,6 +41,8 @@ #ifndef BROWSER_H #define BROWSER_H +#include "downloadmanagerwidget.h" + #include class BrowserWindow; @@ -48,14 +50,16 @@ class BrowserWindow; class Browser { public: - ~Browser(); + Browser(); + + QVector windows() { return m_windows; } - QVector windows(); - void addWindow(BrowserWindow* window); - static Browser &instance(); + BrowserWindow *createWindow(); + + DownloadManagerWidget &downloadManagerWidget() { return m_downloadManagerWidget; } private: - Browser(); QVector m_windows; + DownloadManagerWidget m_downloadManagerWidget; }; #endif // BROWSER_H diff --git a/examples/webenginewidgets/simplebrowser/browserwindow.cpp b/examples/webenginewidgets/simplebrowser/browserwindow.cpp index 0b85e2bb0..43c25e633 100644 --- a/examples/webenginewidgets/simplebrowser/browserwindow.cpp +++ b/examples/webenginewidgets/simplebrowser/browserwindow.cpp @@ -40,12 +40,13 @@ #include "browser.h" #include "browserwindow.h" +#include "downloadmanagerwidget.h" #include "tabwidget.h" -#include "urllineedit.h" #include "webview.h" #include #include #include +#include #include #include #include @@ -54,9 +55,10 @@ #include #include #include +#include -BrowserWindow::BrowserWindow(QWidget *parent, Qt::WindowFlags flags) - : QMainWindow(parent, flags) +BrowserWindow::BrowserWindow(Browser *browser) + : m_browser(browser) , m_tabWidget(new TabWidget(this)) , m_progressBar(new QProgressBar(this)) , m_historyBackAction(nullptr) @@ -64,10 +66,11 @@ BrowserWindow::BrowserWindow(QWidget *parent, Qt::WindowFlags flags) , m_stopAction(nullptr) , m_reloadAction(nullptr) , m_stopReloadAction(nullptr) - , m_urlLineEdit(new UrlLineEdit(this)) + , m_urlLineEdit(nullptr) + , m_favAction(nullptr) { - setToolButtonStyle(Qt::ToolButtonFollowStyle); setAttribute(Qt::WA_DeleteOnClose, true); + setFocusPolicy(Qt::ClickFocus); QToolBar *toolbar = createToolBar(); addToolBar(toolbar); @@ -85,7 +88,7 @@ BrowserWindow::BrowserWindow(QWidget *parent, Qt::WindowFlags flags) m_progressBar->setMaximumHeight(1); m_progressBar->setTextVisible(false); - m_progressBar->setStyleSheet(QStringLiteral("QProgressBar {border: 0px } QProgressBar::chunk { background-color: red; }")); + m_progressBar->setStyleSheet(QStringLiteral("QProgressBar {border: 0px} QProgressBar::chunk {background-color: #da4453}")); layout->addWidget(m_progressBar); layout->addWidget(m_tabWidget); @@ -97,15 +100,14 @@ BrowserWindow::BrowserWindow(QWidget *parent, Qt::WindowFlags flags) statusBar()->showMessage(url); }); connect(m_tabWidget, &TabWidget::loadProgress, this, &BrowserWindow::handleWebViewLoadProgress); - connect(m_tabWidget, &TabWidget::urlChanged, this, &BrowserWindow::handleWebViewUrlChanged); - connect(m_tabWidget, &TabWidget::iconChanged, this, &BrowserWindow::handleWebViewIconChanged); connect(m_tabWidget, &TabWidget::webActionEnabledChanged, this, &BrowserWindow::handleWebActionEnabledChanged); - connect(m_urlLineEdit, &QLineEdit::returnPressed, this, [this]() { - m_urlLineEdit->setFavIcon(QIcon(QStringLiteral(":defaulticon.png"))); - loadPage(m_urlLineEdit->url()); + connect(m_tabWidget, &TabWidget::urlChanged, [this](const QUrl &url) { + m_urlLineEdit->setText(url.toDisplayString()); + }); + connect(m_tabWidget, &TabWidget::favIconChanged, m_favAction, &QAction::setIcon); + connect(m_urlLineEdit, &QLineEdit::returnPressed, [this]() { + m_tabWidget->setUrl(QUrl::fromUserInput(m_urlLineEdit->text())); }); - - m_urlLineEdit->setFavIcon(QIcon(QStringLiteral(":defaulticon.png"))); QAction *focusUrlLineEditAction = new QAction(this); addAction(focusUrlLineEditAction); @@ -114,14 +116,10 @@ BrowserWindow::BrowserWindow(QWidget *parent, Qt::WindowFlags flags) m_urlLineEdit->setFocus(Qt::ShortcutFocusReason); }); - handleWebViewTitleChanged(tr("Qt Simple Browser")); + handleWebViewTitleChanged(QString()); m_tabWidget->createTab(); } -BrowserWindow::~BrowserWindow() -{ -} - QSize BrowserWindow::sizeHint() const { QRect desktopRect = QApplication::desktop()->screenGeometry(); @@ -134,18 +132,16 @@ QMenu *BrowserWindow::createFileMenu(TabWidget *tabWidget) QMenu *fileMenu = new QMenu(tr("&File")); fileMenu->addAction(tr("&New Window"), this, &BrowserWindow::handleNewWindowTriggered, QKeySequence::New); - QAction *newTabAction = new QAction(QIcon(QLatin1String(":addtab.png")), tr("New &Tab"), this); + QAction *newTabAction = new QAction(tr("New &Tab"), this); newTabAction->setShortcuts(QKeySequence::AddTab); - newTabAction->setIconVisibleInMenu(false); connect(newTabAction, &QAction::triggered, tabWidget, &TabWidget::createTab); fileMenu->addAction(newTabAction); fileMenu->addAction(tr("&Open File..."), this, &BrowserWindow::handleFileOpenTriggered, QKeySequence::Open); fileMenu->addSeparator(); - QAction *closeTabAction = new QAction(QIcon(QLatin1String(":closetab.png")), tr("&Close Tab"), this); + QAction *closeTabAction = new QAction(tr("&Close Tab"), this); closeTabAction->setShortcuts(QKeySequence::Close); - closeTabAction->setIconVisibleInMenu(false); connect(closeTabAction, &QAction::triggered, [tabWidget]() { tabWidget->closeTab(tabWidget->currentIndex()); }); @@ -156,8 +152,8 @@ QMenu *BrowserWindow::createFileMenu(TabWidget *tabWidget) connect(closeAction, &QAction::triggered, this, &QWidget::close); fileMenu->addAction(closeAction); - connect(fileMenu, &QMenu::aboutToShow, [closeAction]() { - if (Browser::instance().windows().count() == 1) + connect(fileMenu, &QMenu::aboutToShow, [this, closeAction]() { + if (m_browser->windows().count() == 1) closeAction->setText(tr("&Quit")); else closeAction->setText(tr("&Close Window")); @@ -288,7 +284,7 @@ QMenu *BrowserWindow::createWindowMenu(TabWidget *tabWidget) menu->addAction(previousTabAction); menu->addSeparator(); - QVector windows = Browser::instance().windows(); + QVector windows = m_browser->windows(); int index(-1); for (auto window : windows) { QAction *action = menu->addAction(window->windowTitle(), this, &BrowserWindow::handleShowWindowTriggered); @@ -311,7 +307,7 @@ QMenu *BrowserWindow::createHelpMenu() QToolBar *BrowserWindow::createToolBar() { QToolBar *navigationBar = new QToolBar(tr("Navigation")); - navigationBar->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea); + navigationBar->setMovable(false); navigationBar->toggleViewAction()->setEnabled(false); m_historyBackAction = new QAction(this); @@ -328,6 +324,7 @@ QToolBar *BrowserWindow::createToolBar() m_historyBackAction->setShortcuts(backShortcuts); m_historyBackAction->setIconVisibleInMenu(false); m_historyBackAction->setIcon(QIcon(QStringLiteral(":go-previous.png"))); + m_historyBackAction->setToolTip(tr("Go back in history")); connect(m_historyBackAction, &QAction::triggered, [this]() { m_tabWidget->triggerWebPageAction(QWebEnginePage::Back); }); @@ -345,6 +342,7 @@ QToolBar *BrowserWindow::createToolBar() m_historyForwardAction->setShortcuts(fwdShortcuts); m_historyForwardAction->setIconVisibleInMenu(false); m_historyForwardAction->setIcon(QIcon(QStringLiteral(":go-next.png"))); + m_historyForwardAction->setToolTip(tr("Go forward in history")); connect(m_historyForwardAction, &QAction::triggered, [this]() { m_tabWidget->triggerWebPageAction(QWebEnginePage::Forward); }); @@ -355,22 +353,22 @@ QToolBar *BrowserWindow::createToolBar() m_tabWidget->triggerWebPageAction(QWebEnginePage::WebAction(m_stopReloadAction->data().toInt())); }); navigationBar->addAction(m_stopReloadAction); + + m_urlLineEdit = new QLineEdit(this); + m_favAction = new QAction(this); + m_urlLineEdit->addAction(m_favAction, QLineEdit::LeadingPosition); + m_urlLineEdit->setClearButtonEnabled(true); navigationBar->addWidget(m_urlLineEdit); - int size = m_urlLineEdit->sizeHint().height(); - navigationBar->setIconSize(QSize(size, size)); - return navigationBar; -} -void BrowserWindow::handleWebViewIconChanged(const QIcon &icon) -{ - m_urlLineEdit->setFavIcon(icon); -} + auto downloadsAction = new QAction(this); + downloadsAction->setIcon(QIcon(QStringLiteral(":go-bottom.png"))); + downloadsAction->setToolTip(tr("Show downloads")); + navigationBar->addAction(downloadsAction); + connect(downloadsAction, &QAction::triggered, [this]() { + m_browser->downloadManagerWidget().show(); + }); -void BrowserWindow::handleWebViewUrlChanged(const QUrl &url) -{ - m_urlLineEdit->setUrl(url); - if (url.isEmpty()) - m_urlLineEdit->setFocus(); + return navigationBar; } void BrowserWindow::handleWebActionEnabledChanged(QWebEnginePage::WebAction action, bool enabled) @@ -389,7 +387,7 @@ void BrowserWindow::handleWebActionEnabledChanged(QWebEnginePage::WebAction acti m_stopAction->setEnabled(enabled); break; default: - qWarning("Unhandled webActionChanged singal"); + qWarning("Unhandled webActionChanged signal"); } } @@ -403,9 +401,7 @@ void BrowserWindow::handleWebViewTitleChanged(const QString &title) void BrowserWindow::handleNewWindowTriggered() { - BrowserWindow *window = new BrowserWindow(); - Browser::instance().addWindow(window); - window->loadHomePage(); + m_browser->createWindow(); } void BrowserWindow::handleFileOpenTriggered() @@ -414,7 +410,7 @@ void BrowserWindow::handleFileOpenTriggered() tr("Web Resources (*.html *.htm *.svg *.png *.gif *.svgz);;All files (*.*)")); if (file.isEmpty()) return; - loadPage(file); + currentTab()->setUrl(file); } void BrowserWindow::handleFindActionTriggered() @@ -450,24 +446,6 @@ void BrowserWindow::closeEvent(QCloseEvent *event) deleteLater(); } -void BrowserWindow::loadHomePage() -{ - loadPage(QStringLiteral("http://www.qt.io")); -} - -void BrowserWindow::loadPage(const QString &page) -{ - loadPage(QUrl::fromUserInput(page)); -} - -void BrowserWindow::loadPage(const QUrl &url) -{ - if (url.isValid()) { - m_urlLineEdit->setUrl(url); - m_tabWidget->setUrl(url); - } -} - TabWidget *BrowserWindow::tabWidget() const { return m_tabWidget; @@ -483,23 +461,24 @@ void BrowserWindow::handleWebViewLoadProgress(int progress) static QIcon stopIcon(QStringLiteral(":process-stop.png")); static QIcon reloadIcon(QStringLiteral(":view-refresh.png")); - if (progress < 100 && progress > 0) { + if (0 < progress && progress < 100) { m_stopReloadAction->setData(QWebEnginePage::Stop); m_stopReloadAction->setIcon(stopIcon); m_stopReloadAction->setToolTip(tr("Stop loading the current page")); + m_progressBar->setValue(progress); } else { m_stopReloadAction->setData(QWebEnginePage::Reload); m_stopReloadAction->setIcon(reloadIcon); m_stopReloadAction->setToolTip(tr("Reload the current page")); + m_progressBar->setValue(0); } - m_progressBar->setValue(progress < 100 ? progress : 0); } void BrowserWindow::handleShowWindowTriggered() { if (QAction *action = qobject_cast(sender())) { int offset = action->data().toInt(); - QVector windows = Browser::instance().windows(); + QVector windows = m_browser->windows(); windows.at(offset)->activateWindow(); windows.at(offset)->currentTab()->setFocus(); } diff --git a/examples/webenginewidgets/simplebrowser/browserwindow.h b/examples/webenginewidgets/simplebrowser/browserwindow.h index 03c8d385b..745061691 100644 --- a/examples/webenginewidgets/simplebrowser/browserwindow.h +++ b/examples/webenginewidgets/simplebrowser/browserwindow.h @@ -42,14 +42,16 @@ #define BROWSERWINDOW_H #include +#include #include QT_BEGIN_NAMESPACE +class QLineEdit; class QProgressBar; QT_END_NAMESPACE +class Browser; class TabWidget; -class UrlLineEdit; class WebView; class BrowserWindow : public QMainWindow @@ -57,15 +59,11 @@ class BrowserWindow : public QMainWindow Q_OBJECT public: - BrowserWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = 0); - ~BrowserWindow(); + BrowserWindow(Browser *browser); QSize sizeHint() const override; TabWidget *tabWidget() const; WebView *currentTab() const; - - void loadPage(const QString &url); - void loadPage(const QUrl &url); - void loadHomePage(); + Browser *browser() { return m_browser; } protected: void closeEvent(QCloseEvent *event) override; @@ -77,8 +75,6 @@ private slots: void handleShowWindowTriggered(); void handleWebViewLoadProgress(int); void handleWebViewTitleChanged(const QString &title); - void handleWebViewUrlChanged(const QUrl &url); - void handleWebViewIconChanged(const QIcon &icon); void handleWebActionEnabledChanged(QWebEnginePage::WebAction action, bool enabled); private: @@ -90,6 +86,7 @@ private: QToolBar *createToolBar(); private: + Browser *m_browser; TabWidget *m_tabWidget; QProgressBar *m_progressBar; QAction *m_historyBackAction; @@ -97,7 +94,8 @@ private: QAction *m_stopAction; QAction *m_reloadAction; QAction *m_stopReloadAction; - UrlLineEdit *m_urlLineEdit; + QLineEdit *m_urlLineEdit; + QAction *m_favAction; QString m_lastSearch; }; diff --git a/examples/webenginewidgets/simplebrowser/data/AppLogoColor.png b/examples/webenginewidgets/simplebrowser/data/AppLogoColor.png new file mode 100644 index 000000000..2a4971782 Binary files /dev/null and b/examples/webenginewidgets/simplebrowser/data/AppLogoColor.png differ diff --git a/examples/webenginewidgets/simplebrowser/data/addtab.png b/examples/webenginewidgets/simplebrowser/data/addtab.png deleted file mode 100644 index 20928fb40..000000000 Binary files a/examples/webenginewidgets/simplebrowser/data/addtab.png and /dev/null differ diff --git a/examples/webenginewidgets/simplebrowser/data/closetab.png b/examples/webenginewidgets/simplebrowser/data/closetab.png deleted file mode 100644 index ab9d669ee..000000000 Binary files a/examples/webenginewidgets/simplebrowser/data/closetab.png and /dev/null differ diff --git a/examples/webenginewidgets/simplebrowser/data/defaulticon.png b/examples/webenginewidgets/simplebrowser/data/defaulticon.png deleted file mode 100644 index 01a0920c9..000000000 Binary files a/examples/webenginewidgets/simplebrowser/data/defaulticon.png and /dev/null differ diff --git a/examples/webenginewidgets/simplebrowser/data/dialog-error.png b/examples/webenginewidgets/simplebrowser/data/dialog-error.png new file mode 100644 index 000000000..cdd95bade Binary files /dev/null and b/examples/webenginewidgets/simplebrowser/data/dialog-error.png differ diff --git a/examples/webenginewidgets/simplebrowser/data/edit-clear.png b/examples/webenginewidgets/simplebrowser/data/edit-clear.png new file mode 100644 index 000000000..5542948bc Binary files /dev/null and b/examples/webenginewidgets/simplebrowser/data/edit-clear.png differ diff --git a/examples/webenginewidgets/simplebrowser/data/go-bottom.png b/examples/webenginewidgets/simplebrowser/data/go-bottom.png new file mode 100644 index 000000000..bf973fedc Binary files /dev/null and b/examples/webenginewidgets/simplebrowser/data/go-bottom.png differ diff --git a/examples/webenginewidgets/simplebrowser/data/go-next.png b/examples/webenginewidgets/simplebrowser/data/go-next.png index 6f3f65d33..a68e2db77 100644 Binary files a/examples/webenginewidgets/simplebrowser/data/go-next.png and b/examples/webenginewidgets/simplebrowser/data/go-next.png differ diff --git a/examples/webenginewidgets/simplebrowser/data/go-previous.png b/examples/webenginewidgets/simplebrowser/data/go-previous.png index 93be3d1ee..c37bc0414 100644 Binary files a/examples/webenginewidgets/simplebrowser/data/go-previous.png and b/examples/webenginewidgets/simplebrowser/data/go-previous.png differ diff --git a/examples/webenginewidgets/simplebrowser/data/process-stop.png b/examples/webenginewidgets/simplebrowser/data/process-stop.png index b68290bf1..e7a8d1722 100644 Binary files a/examples/webenginewidgets/simplebrowser/data/process-stop.png and b/examples/webenginewidgets/simplebrowser/data/process-stop.png differ diff --git a/examples/webenginewidgets/simplebrowser/data/simplebrowser.qrc b/examples/webenginewidgets/simplebrowser/data/simplebrowser.qrc index 5795063ca..ec8716721 100644 --- a/examples/webenginewidgets/simplebrowser/data/simplebrowser.qrc +++ b/examples/webenginewidgets/simplebrowser/data/simplebrowser.qrc @@ -1,12 +1,13 @@ - addtab.png - defaulticon.png - closetab.png + AppLogoColor.png + dialog-error.png + edit-clear.png + go-bottom.png go-next.png go-previous.png process-stop.png - simplebrowser.svg + text-html.png view-refresh.png diff --git a/examples/webenginewidgets/simplebrowser/data/simplebrowser.svg b/examples/webenginewidgets/simplebrowser/data/simplebrowser.svg deleted file mode 100644 index 9f39deb66..000000000 --- a/examples/webenginewidgets/simplebrowser/data/simplebrowser.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/examples/webenginewidgets/simplebrowser/data/text-html.png b/examples/webenginewidgets/simplebrowser/data/text-html.png new file mode 100644 index 000000000..a896697d7 Binary files /dev/null and b/examples/webenginewidgets/simplebrowser/data/text-html.png differ diff --git a/examples/webenginewidgets/simplebrowser/data/view-refresh.png b/examples/webenginewidgets/simplebrowser/data/view-refresh.png index cab4d02c7..606ea9eba 100644 Binary files a/examples/webenginewidgets/simplebrowser/data/view-refresh.png and b/examples/webenginewidgets/simplebrowser/data/view-refresh.png differ diff --git a/examples/webenginewidgets/simplebrowser/doc/images/simplebrowser.png b/examples/webenginewidgets/simplebrowser/doc/images/simplebrowser.png index 777309075..b09f7c853 100644 Binary files a/examples/webenginewidgets/simplebrowser/doc/images/simplebrowser.png and b/examples/webenginewidgets/simplebrowser/doc/images/simplebrowser.png differ diff --git a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc index e57ec80ec..6736f8570 100644 --- a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc +++ b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc @@ -43,6 +43,7 @@ forward in the web page browsing history. \li Multi-tab area for displaying web content within tabs. \li Status bar for displaying hovered links. + \li A simple download manager. \endlist The web content can be opened in new tabs or separate windows. HTTP and @@ -52,13 +53,13 @@ \section1 Class Hierarchy - We start with sketching a diagram of the classes that we are going to + We start with sketching a diagram of the main classes that we are going to implement: \image simplebrowser-model.png \list - \li \c{Browser} is a singleton class managing the application windows. + \li \c{Browser} is a class managing the application windows. \li \c{BrowserWindow} is a \l QMainWindow showing the menu, a navigation bar, \c {TabWidget}, and a status bar. \li \c{TabWidget} is a \l QTabWidget and contains one or multiple @@ -68,11 +69,19 @@ \li \c{WebPage} is a \l QWebEnginePage that represents website content. \endlist + Additionally, we will implement some auxiliary classes: + + \list + \li \c{WebPopupWindow} is a \l QWidget for showing popup windows. + \li \c{DownloadManagerWidget} is a \l QWidget implementing the downloads + list. + \endlist + \section1 Creating the Browser Main Window - This example supports multiple main windows that are owned by a - \c Browser singleton object. This class could also be used for further - functionality, such as downloading files, bookmarks, and history managers. + This example supports multiple main windows that are owned by a \c Browser + object. This class also owns the \c DownloadManagerWidget and could be used + for further functionality, such as bookmarks and history managers. In \c main.cpp, we create the first \c BrowserWindow instance and add it to the \c Browser object. If no arguments are passed on the command line, @@ -104,6 +113,8 @@ \quotefromfile webenginewidgets/simplebrowser/tabwidget.cpp \skipto TabWidget::createTab( \printuntil } + \skipto TabWidget::createBackgroundTab( + \printuntil } In \c TabWidget::setupView(), we make sure that the \c TabWidget always forwards the signals of the currently selected \c WebView: @@ -225,20 +236,14 @@ \section1 Opening a Web Page - This section describes the workflow for opening a new page. - When the user enters a URL in the navigation bar and presses \uicontrol Enter, - \c QLineEdit::returnPressed is emitted, which lets \c BrowserWindow - load the requested page: + This section describes the workflow for opening a new page. When the user + enters a URL in the navigation bar and presses \uicontrol Enter, the \c + QLineEdit::returnPressed signal is emitted and the new URL is then handed + over to \c TabWidget::setUrl: \quotefromfile webenginewidgets/simplebrowser/browserwindow.cpp \skipto connect(m_urlLineEdit - \printuntil }); - - The \c loadPage() method calls the \c setUrl() method of \c TabWidget: - - \skipto void BrowserWindow::loadPage(const QUrl - \printuntil } - \printline } + \printline connect The call is forwarded to the currently selected tab: @@ -249,4 +254,36 @@ The \c setUrl() method of \c WebView just forwards the \c url to the associated \c WebPage, which in turn starts the downloading of the page's content in the background. + + \section1 Managing Downloads + + Downloads are associated with a \l QWebEngineProfile. Whenever a download is + triggered on a web page the \l QWebEngineProfile::defaultProfile signal is + emitted with a \l QWebEngineDownloadItem, which in this example is forwarded + to \c DownloadManagerWidget::downloadRequested: + + \quotefromfile webenginewidgets/simplebrowser/browser.cpp + \skipto Browser::Browser + \printuntil /^\}/ + + This method prompts the user for a file name (with a pre-filled suggestion) + and starts the download (unless the user cancels the \uicontrol {Save As} + dialog): + + \quotefromfile webenginewidgets/simplebrowser/downloadmanagerwidget.cpp + \skipto DownloadManagerWidget::downloadRequested + \printuntil /^\}/ + + The \l QWebEngineDownloadItem object will periodically emit the \l + {QWebEngineDownloadItem::}{downloadProgress} signal to notify potential + observers of the download progress and the \l + {QWebEngineDownloadItem::}{stateChanged} signal when the download is + finished or when an error occurs. See \c downloadmanagerwidget.cpp for an + example of how these signals can be handled. + + \section1 Licensing + + All icons used in the example, with the exception of \c{AppLogoColor.png}, + originate from the public domain + \l{http://tango.freedesktop.org/Tango_Icon_Library}{Tango Icon Library}. */ diff --git a/examples/webenginewidgets/simplebrowser/downloadmanagerwidget.cpp b/examples/webenginewidgets/simplebrowser/downloadmanagerwidget.cpp new file mode 100644 index 000000000..5f32294e8 --- /dev/null +++ b/examples/webenginewidgets/simplebrowser/downloadmanagerwidget.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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$ +** +****************************************************************************/ + +#include "downloadmanagerwidget.h" + +#include "browser.h" +#include "browserwindow.h" +#include "downloadwidget.h" + +#include +#include + +DownloadManagerWidget::DownloadManagerWidget(QWidget *parent) + : QWidget(parent) + , m_numDownloads(0) +{ + setupUi(this); +} + +void DownloadManagerWidget::downloadRequested(QWebEngineDownloadItem *download) +{ + Q_ASSERT(download && download->state() == QWebEngineDownloadItem::DownloadRequested); + + QString path = QFileDialog::getSaveFileName(this, tr("Save as"), download->path()); + if (path.isEmpty()) + return; + + download->setPath(path); + download->accept(); + add(new DownloadWidget(download)); + + show(); +} + +void DownloadManagerWidget::add(DownloadWidget *downloadWidget) +{ + connect(downloadWidget, &DownloadWidget::removeClicked, this, &DownloadManagerWidget::remove); + m_itemsLayout->insertWidget(0, downloadWidget, 0, Qt::AlignTop); + if (m_numDownloads++ == 0) + m_zeroItemsLabel->hide(); +} + +void DownloadManagerWidget::remove(DownloadWidget *downloadWidget) +{ + m_itemsLayout->removeWidget(downloadWidget); + downloadWidget->deleteLater(); + if (--m_numDownloads == 0) + m_zeroItemsLabel->show(); +} diff --git a/examples/webenginewidgets/simplebrowser/downloadmanagerwidget.h b/examples/webenginewidgets/simplebrowser/downloadmanagerwidget.h new file mode 100644 index 000000000..597e6139a --- /dev/null +++ b/examples/webenginewidgets/simplebrowser/downloadmanagerwidget.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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$ +** +****************************************************************************/ + +#ifndef DOWNLOADMANAGERWIDGET_H +#define DOWNLOADMANAGERWIDGET_H + +#include "ui_downloadmanagerwidget.h" + +#include + +QT_BEGIN_NAMESPACE +class QWebEngineDownloadItem; +QT_END_NAMESPACE + +class DownloadWidget; + +// Displays a list of downloads. +class DownloadManagerWidget final : public QWidget, public Ui::DownloadManagerWidget +{ + Q_OBJECT +public: + explicit DownloadManagerWidget(QWidget *parent = nullptr); + + // Prompts user with a "Save As" dialog. If the user doesn't cancel it, then + // the QWebEngineDownloadItem will be accepted and the DownloadManagerWidget + // will be shown on the screen. + void downloadRequested(QWebEngineDownloadItem *webItem); + +private: + void add(DownloadWidget *downloadWidget); + void remove(DownloadWidget *downloadWidget); + + int m_numDownloads; +}; + +#endif // DOWNLOADMANAGERWIDGET_H diff --git a/examples/webenginewidgets/simplebrowser/downloadmanagerwidget.ui b/examples/webenginewidgets/simplebrowser/downloadmanagerwidget.ui new file mode 100644 index 000000000..b7544ac16 --- /dev/null +++ b/examples/webenginewidgets/simplebrowser/downloadmanagerwidget.ui @@ -0,0 +1,104 @@ + + + DownloadManagerWidget + + + + 0 + 0 + 400 + 212 + + + + Downloads + + + #DownloadManagerWidget { + background: palette(button) +} + + + + QLayout::SetNoConstraint + + + 0 + + + 0 + + + 0 + + + 0 + + + + + #m_scrollArea { + margin: 2px; + border: none; +} + + + Qt::ScrollBarAlwaysOn + + + Qt::ScrollBarAlwaysOff + + + true + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + #m_items {background: palette(mid)} + + + + 2 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 0 + 0 + + + + color: palette(shadow) + + + No downloads + + + Qt::AlignCenter + + + + + + + + + + + + diff --git a/examples/webenginewidgets/simplebrowser/downloadwidget.cpp b/examples/webenginewidgets/simplebrowser/downloadwidget.cpp new file mode 100644 index 000000000..a80366f77 --- /dev/null +++ b/examples/webenginewidgets/simplebrowser/downloadwidget.cpp @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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$ +** +****************************************************************************/ + +#include "downloadwidget.h" + +#include +#include +#include + +DownloadWidget::DownloadWidget(QWebEngineDownloadItem *download, QWidget *parent) + : QFrame(parent) + , m_download(download) + , m_timeAdded(QTime::currentTime()) +{ + setupUi(this); + m_dstName->setText(QFileInfo(m_download->path()).fileName()); + m_srcUrl->setText(m_download->url().toDisplayString()); + + connect(m_cancelButton, &QPushButton::clicked, + [this](bool) { + if (m_download->state() == QWebEngineDownloadItem::DownloadInProgress) + m_download->cancel(); + else + emit removeClicked(this); + }); + + connect(m_download, &QWebEngineDownloadItem::downloadProgress, + [this](qint64, qint64) { + updateWidget(); + }); + + connect(m_download, &QWebEngineDownloadItem::stateChanged, + [this](QWebEngineDownloadItem::DownloadState) { + updateWidget(); + }); + + updateWidget(); +} + +inline QString DownloadWidget::withUnit(qreal bytes) +{ + if (bytes < (1 << 10)) + return tr("%L1 B").arg(bytes); + else if (bytes < (1 << 20)) + return tr("%L1 KiB").arg(bytes / (1 << 10), 0, 'f', 2); + else if (bytes < (1 << 30)) + return tr("%L1 MiB").arg(bytes / (1 << 20), 0, 'f', 2); + else + return tr("%L1 GiB").arg(bytes / (1 << 30), 0, 'f', 2); +} + +void DownloadWidget::updateWidget() +{ + qreal totalBytes = m_download->totalBytes(); + qreal receivedBytes = m_download->receivedBytes(); + qreal bytesPerSecond = receivedBytes / m_timeAdded.elapsed() * 1000; + + auto state = m_download->state(); + switch (state) { + case QWebEngineDownloadItem::DownloadRequested: + Q_UNREACHABLE(); + break; + case QWebEngineDownloadItem::DownloadInProgress: + if (totalBytes >= 0) { + m_progressBar->setValue(qRound(100 * receivedBytes / totalBytes)); + m_progressBar->setDisabled(false); + m_progressBar->setFormat( + tr("%p% - %1 of %2 downloaded - %3/s") + .arg(withUnit(receivedBytes)) + .arg(withUnit(totalBytes)) + .arg(withUnit(bytesPerSecond))); + } else { + m_progressBar->setValue(0); + m_progressBar->setDisabled(false); + m_progressBar->setFormat( + tr("unknown size - %1 downloaded - %2/s") + .arg(withUnit(receivedBytes)) + .arg(withUnit(bytesPerSecond))); + } + break; + case QWebEngineDownloadItem::DownloadCompleted: + m_progressBar->setValue(100); + m_progressBar->setDisabled(true); + m_progressBar->setFormat( + tr("completed - %1 downloaded - %2/s") + .arg(withUnit(receivedBytes)) + .arg(withUnit(bytesPerSecond))); + break; + case QWebEngineDownloadItem::DownloadCancelled: + m_progressBar->setValue(0); + m_progressBar->setDisabled(true); + m_progressBar->setFormat( + tr("cancelled - %1 downloaded - %2/s") + .arg(withUnit(receivedBytes)) + .arg(withUnit(bytesPerSecond))); + break; + case QWebEngineDownloadItem::DownloadInterrupted: + m_progressBar->setValue(0); + m_progressBar->setDisabled(true); + m_progressBar->setFormat( + tr("interrupted: %1") + .arg(m_download->interruptReasonString())); + break; + } + + if (state == QWebEngineDownloadItem::DownloadInProgress) { + static QIcon cancelIcon(QStringLiteral(":process-stop.png")); + m_cancelButton->setIcon(cancelIcon); + m_cancelButton->setToolTip(tr("Stop downloading")); + } else { + static QIcon removeIcon(QStringLiteral(":edit-clear.png")); + m_cancelButton->setIcon(removeIcon); + m_cancelButton->setToolTip(tr("Remove from list")); + } +} diff --git a/examples/webenginewidgets/simplebrowser/downloadwidget.h b/examples/webenginewidgets/simplebrowser/downloadwidget.h new file mode 100644 index 000000000..e8cf42825 --- /dev/null +++ b/examples/webenginewidgets/simplebrowser/downloadwidget.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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$ +** +****************************************************************************/ + +#ifndef DOWNLOADWIDGET_H +#define DOWNLOADWIDGET_H + +#include "ui_downloadwidget.h" + +#include +#include + +QT_BEGIN_NAMESPACE +class QWebEngineDownloadItem; +QT_END_NAMESPACE + +// Displays one ongoing or finished download (QWebEngineDownloadItem). +class DownloadWidget final : public QFrame, public Ui::DownloadWidget +{ + Q_OBJECT +public: + // Precondition: The QWebEngineDownloadItem has been accepted. + explicit DownloadWidget(QWebEngineDownloadItem *download, QWidget *parent = nullptr); + +signals: + // This signal is emitted when the user indicates that they want to remove + // this download from the downloads list. + void removeClicked(DownloadWidget *self); + +private: + void updateWidget(); + QString withUnit(qreal bytes); + + QWebEngineDownloadItem *m_download; + QTime m_timeAdded; +}; + +#endif // DOWNLOADWIDGET_H diff --git a/examples/webenginewidgets/simplebrowser/downloadwidget.ui b/examples/webenginewidgets/simplebrowser/downloadwidget.ui new file mode 100644 index 000000000..ee45e0b10 --- /dev/null +++ b/examples/webenginewidgets/simplebrowser/downloadwidget.ui @@ -0,0 +1,80 @@ + + + DownloadWidget + + + #DownloadWidget { + background: palette(button); + border: 1px solid palette(dark); + margin: 0px; +} + + + + QLayout::SetMinAndMaxSize + + + + + font-weight: bold + + + + TextLabel + + + + + + + + + + QPushButton { + margin: 1px; + border: none; +} +QPushButton:pressed { + margin: none; + border: 1px solid palette(shadow); + background: palette(midlight); +} + + + false + + + + + + + + 350 + 16777215 + + + + + + + TextLabel + + + + + + + font-size: 12px + + + 24 + + + + + + + + + + diff --git a/examples/webenginewidgets/simplebrowser/main.cpp b/examples/webenginewidgets/simplebrowser/main.cpp index fa9f44c34..93dfc8a8c 100644 --- a/examples/webenginewidgets/simplebrowser/main.cpp +++ b/examples/webenginewidgets/simplebrowser/main.cpp @@ -40,38 +40,35 @@ #include "browser.h" #include "browserwindow.h" +#include "webview.h" #include #include -QString getCommandLineUrlArgument() +QUrl getCommandLineUrlArgument() { const QStringList args = QCoreApplication::arguments(); - if (args.count() > 1) { - const QString lastArg = args.last(); - const bool isValidUrl = QUrl::fromUserInput(lastArg).isValid(); - if (isValidUrl) - return lastArg; - } - return QString(); + if (args.count() > 1) + return QUrl::fromUserInput(args.last()); + return QUrl(); } int main(int argc, char **argv) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QApplication app(argc, argv); - app.setWindowIcon(QIcon(QLatin1String(":simplebrowser.svg"))); + app.setWindowIcon(QIcon(QStringLiteral(":AppLogoColor.png"))); QWebEngineSettings::defaultSettings()->setAttribute(QWebEngineSettings::PluginsEnabled, true); - BrowserWindow *window = new BrowserWindow(); - Browser::instance().addWindow(window); + QUrl url = getCommandLineUrlArgument(); + if (!url.isValid()) + url = QStringLiteral("https://www.qt.io"); - const QString url = getCommandLineUrlArgument(); - if (!url.isEmpty()) - window->loadPage(url); - else - window->loadHomePage(); + Browser browser; + BrowserWindow *window = browser.createWindow(); + window->currentTab()->setUrl(url); return app.exec(); } diff --git a/examples/webenginewidgets/simplebrowser/simplebrowser.pro b/examples/webenginewidgets/simplebrowser/simplebrowser.pro index 197d68091..8120a2852 100644 --- a/examples/webenginewidgets/simplebrowser/simplebrowser.pro +++ b/examples/webenginewidgets/simplebrowser/simplebrowser.pro @@ -6,25 +6,29 @@ CONFIG += c++11 HEADERS += \ browser.h \ browserwindow.h \ + downloadmanagerwidget.h \ + downloadwidget.h \ tabwidget.h \ - urllineedit.h \ - webview.h \ webpage.h \ - webpopupwindow.h + webpopupwindow.h \ + webview.h SOURCES += \ browser.cpp \ browserwindow.cpp \ + downloadmanagerwidget.cpp \ + downloadwidget.cpp \ main.cpp \ tabwidget.cpp \ - urllineedit.cpp \ - webview.cpp \ webpage.cpp \ - webpopupwindow.cpp + webpopupwindow.cpp \ + webview.cpp FORMS += \ certificateerrordialog.ui \ - passworddialog.ui + passworddialog.ui \ + downloadmanagerwidget.ui \ + downloadwidget.ui RESOURCES += data/simplebrowser.qrc diff --git a/examples/webenginewidgets/simplebrowser/tabwidget.cpp b/examples/webenginewidgets/simplebrowser/tabwidget.cpp index a7f855c2a..c9fb32d83 100644 --- a/examples/webenginewidgets/simplebrowser/tabwidget.cpp +++ b/examples/webenginewidgets/simplebrowser/tabwidget.cpp @@ -56,9 +56,8 @@ TabWidget::TabWidget(QWidget *parent) connect(tabBar, &QTabBar::customContextMenuRequested, this, &TabWidget::handleContextMenuRequested); connect(tabBar, &QTabBar::tabCloseRequested, this, &TabWidget::closeTab); connect(tabBar, &QTabBar::tabBarDoubleClicked, [this](int index) { - if (index != -1) - return; - createTab(); + if (index == -1) + createTab(); }); setDocumentMode(true); @@ -67,10 +66,6 @@ TabWidget::TabWidget(QWidget *parent) connect(this, &QTabWidget::currentChanged, this, &TabWidget::handleCurrentChanged); } -TabWidget::~TabWidget() -{ -} - void TabWidget::handleCurrentChanged(int index) { if (index != -1) { @@ -80,11 +75,7 @@ void TabWidget::handleCurrentChanged(int index) emit titleChanged(view->title()); emit loadProgress(view->loadProgress()); emit urlChanged(view->url()); - QIcon pageIcon = view->page()->icon(); - if (!pageIcon.isNull()) - emit iconChanged(pageIcon); - else - emit iconChanged(QIcon(QStringLiteral(":defaulticon.png"))); + emit favIconChanged(view->favIcon()); emit webActionEnabledChanged(QWebEnginePage::Back, view->isWebActionEnabled(QWebEnginePage::Back)); emit webActionEnabledChanged(QWebEnginePage::Forward, view->isWebActionEnabled(QWebEnginePage::Forward)); emit webActionEnabledChanged(QWebEnginePage::Stop, view->isWebActionEnabled(QWebEnginePage::Stop)); @@ -93,7 +84,7 @@ void TabWidget::handleCurrentChanged(int index) emit titleChanged(QString()); emit loadProgress(0); emit urlChanged(QUrl()); - emit iconChanged(QIcon(QStringLiteral(":defaulticon.png"))); + emit favIconChanged(QIcon()); emit webActionEnabledChanged(QWebEnginePage::Back, false); emit webActionEnabledChanged(QWebEnginePage::Forward, false); emit webActionEnabledChanged(QWebEnginePage::Stop, false); @@ -150,8 +141,10 @@ void TabWidget::setupView(WebView *webView) connect(webView, &QWebEngineView::titleChanged, [this, webView](const QString &title) { int index = indexOf(webView); - if (index != -1) + if (index != -1) { setTabText(index, title); + setTabToolTip(index, title); + } if (currentIndex() == index) emit titleChanged(title); }); @@ -170,26 +163,17 @@ void TabWidget::setupView(WebView *webView) if (currentIndex() == indexOf(webView)) emit linkHovered(url); }); - connect(webPage, &WebPage::iconChanged, [this, webView](const QIcon &icon) { + connect(webView, &WebView::favIconChanged, [this, webView](const QIcon &icon) { int index = indexOf(webView); - QIcon ico = icon.isNull() ? QIcon(QStringLiteral(":defaulticon.png")) : icon; - if (index != -1) - setTabIcon(index, ico); + setTabIcon(index, icon); if (currentIndex() == index) - emit iconChanged(ico); + emit favIconChanged(icon); }); connect(webView, &WebView::webActionEnabledChanged, [this, webView](QWebEnginePage::WebAction action, bool enabled) { if (currentIndex() == indexOf(webView)) emit webActionEnabledChanged(action,enabled); }); - connect(webView, &QWebEngineView::loadStarted, [this, webView]() { - int index = indexOf(webView); - if (index != -1) { - QIcon icon(QLatin1String(":view-refresh.png")); - setTabIcon(index, icon); - } - }); connect(webPage, &QWebEnginePage::windowCloseRequested, [this, webView]() { int index = indexOf(webView); if (index >= 0) @@ -197,15 +181,21 @@ void TabWidget::setupView(WebView *webView) }); } -WebView *TabWidget::createTab(bool makeCurrent) +WebView *TabWidget::createTab() +{ + WebView *webView = createBackgroundTab(); + setCurrentWidget(webView); + return webView; +} + +WebView *TabWidget::createBackgroundTab() { WebView *webView = new WebView; WebPage *webPage = new WebPage(QWebEngineProfile::defaultProfile(), webView); webView->setPage(webPage); setupView(webView); - addTab(webView, tr("(Untitled)")); - if (makeCurrent) - setCurrentWidget(webView); + int index = addTab(webView, tr("(Untitled)")); + setTabIcon(index, webView->favIcon()); return webView; } @@ -239,7 +229,7 @@ void TabWidget::closeTab(int index) void TabWidget::cloneTab(int index) { if (WebView *view = webView(index)) { - WebView *tab = createTab(false); + WebView *tab = createTab(); tab->setUrl(view->url()); } } diff --git a/examples/webenginewidgets/simplebrowser/tabwidget.h b/examples/webenginewidgets/simplebrowser/tabwidget.h index 830effa4e..e5a1671ae 100644 --- a/examples/webenginewidgets/simplebrowser/tabwidget.h +++ b/examples/webenginewidgets/simplebrowser/tabwidget.h @@ -56,7 +56,6 @@ class TabWidget : public QTabWidget public: TabWidget(QWidget *parent = nullptr); - ~TabWidget(); WebView *currentWebView() const; @@ -66,7 +65,7 @@ signals: void loadProgress(int progress); void titleChanged(const QString &title); void urlChanged(const QUrl &url); - void iconChanged(const QIcon &icon); + void favIconChanged(const QIcon &icon); void webActionEnabledChanged(QWebEnginePage::WebAction action, bool enabled); public slots: @@ -74,7 +73,8 @@ public slots: void setUrl(const QUrl &url); void triggerWebPageAction(QWebEnginePage::WebAction action); - WebView *createTab(bool makeCurrent = true); + WebView *createTab(); + WebView *createBackgroundTab(); void closeTab(int index); void nextTab(); void previousTab(); diff --git a/examples/webenginewidgets/simplebrowser/urllineedit.cpp b/examples/webenginewidgets/simplebrowser/urllineedit.cpp deleted file mode 100644 index 7e67b635a..000000000 --- a/examples/webenginewidgets/simplebrowser/urllineedit.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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$ -** -****************************************************************************/ - -#include "urllineedit.h" -#include -#include - -UrlLineEdit::UrlLineEdit(QWidget *parent) - : QLineEdit(parent) - , m_favButton(new QToolButton(this)) - , m_clearButton(new QToolButton(this)) -{ - m_clearButton->setIcon(QIcon(QStringLiteral(":closetab.png"))); - m_clearButton->setVisible(false); - m_clearButton->setCursor(Qt::ArrowCursor); - QString style(QStringLiteral("QToolButton { border: none; padding: 1px; }")); - m_clearButton->setStyleSheet(style); - m_favButton->setStyleSheet(style); - setStyleSheet(QStringLiteral("QLineEdit { padding-left: %1px; padding-right: %2px; } ") - .arg(m_clearButton->sizeHint().width()) - .arg(m_favButton->sizeHint().width())); - int minIconHeight = qMax(m_favButton->sizeHint().height(), m_clearButton->sizeHint().height()); - setMinimumSize(minimumSizeHint().width() + - m_favButton->sizeHint().width() + - m_clearButton->sizeHint().width(), - qMax(minimumSizeHint().height(), minIconHeight)); - - connect(m_clearButton, &QToolButton::clicked, this, &QLineEdit::clear); - connect(this, &QLineEdit::textChanged, [this](const QString &text) { - m_clearButton->setVisible(!text.isEmpty() && !isReadOnly()); - }); -} - -QUrl UrlLineEdit::url() const -{ - return QUrl::fromUserInput(text()); -} - -void UrlLineEdit::setUrl(const QUrl &url) -{ - setText(url.toString()); - setCursorPosition(0); -} - -void UrlLineEdit::setFavIcon(const QIcon &icon) -{ - QPixmap pixmap = icon.pixmap(16, 16); - m_favButton->setIcon(pixmap); -} - -void UrlLineEdit::resizeEvent(QResizeEvent *event) -{ - QLineEdit::resizeEvent(event); - QSize clearButtonSize = m_clearButton->sizeHint(); - m_clearButton->move(rect().right() - clearButtonSize.width(), - (rect().bottom() - clearButtonSize.height()) / 2); - m_favButton->move(rect().left(), (rect().bottom() - m_favButton->sizeHint().height()) / 2); -} diff --git a/examples/webenginewidgets/simplebrowser/urllineedit.h b/examples/webenginewidgets/simplebrowser/urllineedit.h deleted file mode 100644 index a01eb0e66..000000000 --- a/examples/webenginewidgets/simplebrowser/urllineedit.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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$ -** -****************************************************************************/ - -#ifndef URLLINEEDIT_H -#define URLLINEEDIT_H - -#include - -QT_BEGIN_NAMESPACE -class QToolButton; -QT_END_NAMESPACE - -class UrlLineEdit : public QLineEdit -{ - Q_OBJECT - -public: - UrlLineEdit(QWidget *parent = nullptr); - -public: - QUrl url() const; - void setUrl(const QUrl &url); - void setFavIcon(const QIcon &icon); - -protected: - void resizeEvent(QResizeEvent *event) override; - -private: - QToolButton *m_favButton; - QToolButton *m_clearButton; -}; - -#endif // URLLINEEDIT_H diff --git a/examples/webenginewidgets/simplebrowser/webpopupwindow.cpp b/examples/webenginewidgets/simplebrowser/webpopupwindow.cpp index 8146dcfb7..63246ac1d 100644 --- a/examples/webenginewidgets/simplebrowser/webpopupwindow.cpp +++ b/examples/webenginewidgets/simplebrowser/webpopupwindow.cpp @@ -38,15 +38,17 @@ ** ****************************************************************************/ -#include "urllineedit.h" #include "webpage.h" #include "webpopupwindow.h" #include "webview.h" +#include #include +#include #include WebPopupWindow::WebPopupWindow(QWebEngineProfile *profile) - : m_addressBar(new UrlLineEdit(this)) + : m_urlLineEdit(new QLineEdit(this)) + , m_favAction(new QAction(this)) , m_view(new WebView(this)) { setAttribute(Qt::WA_DeleteOnClose); @@ -55,31 +57,29 @@ WebPopupWindow::WebPopupWindow(QWebEngineProfile *profile) QVBoxLayout *layout = new QVBoxLayout; layout->setMargin(0); setLayout(layout); - layout->addWidget(m_addressBar); + layout->addWidget(m_urlLineEdit); layout->addWidget(m_view); m_view->setPage(new WebPage(profile, m_view)); m_view->setFocus(); - m_addressBar->setReadOnly(true); - m_addressBar->setFavIcon(QIcon(QStringLiteral(":defaulticon.png"))); + + m_urlLineEdit->setReadOnly(true); + m_urlLineEdit->addAction(m_favAction, QLineEdit::LeadingPosition); connect(m_view, &WebView::titleChanged, this, &QWidget::setWindowTitle); - connect(m_view, &WebView::urlChanged, this, &WebPopupWindow::setUrl); - connect(m_view->page(), &WebPage::iconChanged, this, &WebPopupWindow::handleIconChanged); + connect(m_view, &WebView::urlChanged, [this](const QUrl &url) { + m_urlLineEdit->setText(url.toDisplayString()); + }); + connect(m_view, &WebView::favIconChanged, m_favAction, &QAction::setIcon); connect(m_view->page(), &WebPage::geometryChangeRequested, this, &WebPopupWindow::handleGeometryChangeRequested); connect(m_view->page(), &WebPage::windowCloseRequested, this, &QWidget::close); } -QWebEngineView *WebPopupWindow::view() const +WebView *WebPopupWindow::view() const { return m_view; } -void WebPopupWindow::setUrl(const QUrl &url) -{ - m_addressBar->setUrl(url); -} - void WebPopupWindow::handleGeometryChangeRequested(const QRect &newGeometry) { m_view->setMinimumSize(newGeometry.width(), newGeometry.height()); @@ -87,12 +87,5 @@ void WebPopupWindow::handleGeometryChangeRequested(const QRect &newGeometry) // let the layout do the magic resize(0, 0); show(); -} - -void WebPopupWindow::handleIconChanged(const QIcon &icon) -{ - if (icon.isNull()) - m_addressBar->setFavIcon(QIcon(QStringLiteral(":defaulticon.png"))); - else - m_addressBar->setFavIcon(icon); + m_view->setFocus(); } diff --git a/examples/webenginewidgets/simplebrowser/webpopupwindow.h b/examples/webenginewidgets/simplebrowser/webpopupwindow.h index af97ef7fc..c737b4abc 100644 --- a/examples/webenginewidgets/simplebrowser/webpopupwindow.h +++ b/examples/webenginewidgets/simplebrowser/webpopupwindow.h @@ -44,12 +44,12 @@ #include QT_BEGIN_NAMESPACE +class QLineEdit; class QWebEngineProfile; class QWebEngineView; QT_END_NAMESPACE class WebView; -class UrlLineEdit; class WebPopupWindow : public QWidget { @@ -57,15 +57,14 @@ class WebPopupWindow : public QWidget public: WebPopupWindow(QWebEngineProfile *profile); - QWebEngineView *view() const; - void setUrl(const QUrl &url); + WebView *view() const; private slots: void handleGeometryChangeRequested(const QRect &newGeometry); - void handleIconChanged(const QIcon &icon); private: - UrlLineEdit *m_addressBar; + QLineEdit *m_urlLineEdit; + QAction *m_favAction; WebView *m_view; }; #endif // WEBPOPUPWINDOW_H diff --git a/examples/webenginewidgets/simplebrowser/webview.cpp b/examples/webenginewidgets/simplebrowser/webview.cpp index e4e7f5efa..4bd5c84ac 100644 --- a/examples/webenginewidgets/simplebrowser/webview.cpp +++ b/examples/webenginewidgets/simplebrowser/webview.cpp @@ -52,15 +52,21 @@ WebView::WebView(QWidget *parent) : QWebEngineView(parent) - , m_loadProgress(0) + , m_loadProgress(100) { + connect(this, &QWebEngineView::loadStarted, [this]() { + m_loadProgress = 0; + emit favIconChanged(favIcon()); + }); connect(this, &QWebEngineView::loadProgress, [this](int progress) { m_loadProgress = progress; }); connect(this, &QWebEngineView::loadFinished, [this](bool success) { - if (!success) { - m_loadProgress = 0; - } + m_loadProgress = success ? 100 : -1; + emit favIconChanged(favIcon()); + }); + connect(this, &QWebEngineView::iconChanged, [this](const QIcon &) { + emit favIconChanged(favIcon()); }); connect(this, &QWebEngineView::renderProcessTerminated, @@ -115,21 +121,39 @@ bool WebView::isWebActionEnabled(QWebEnginePage::WebAction webAction) const return page()->action(webAction)->isEnabled(); } +QIcon WebView::favIcon() const +{ + QIcon favIcon = icon(); + if (!favIcon.isNull()) + return favIcon; + + if (m_loadProgress < 0) { + static QIcon errorIcon(QStringLiteral(":dialog-error.png")); + return errorIcon; + } else if (m_loadProgress < 100) { + static QIcon loadingIcon(QStringLiteral(":view-refresh.png")); + return loadingIcon; + } else { + static QIcon defaultIcon(QStringLiteral(":text-html.png")); + return defaultIcon; + } +} + QWebEngineView *WebView::createWindow(QWebEnginePage::WebWindowType type) { + BrowserWindow *mainWindow = qobject_cast(window()); + if (!mainWindow) + return nullptr; + switch (type) { case QWebEnginePage::WebBrowserTab: { - BrowserWindow *mainWindow = qobject_cast(window()); return mainWindow->tabWidget()->createTab(); } case QWebEnginePage::WebBrowserBackgroundTab: { - BrowserWindow *mainWindow = qobject_cast(window()); - return mainWindow->tabWidget()->createTab(false); + return mainWindow->tabWidget()->createBackgroundTab(); } case QWebEnginePage::WebBrowserWindow: { - BrowserWindow *mainWindow = new BrowserWindow(); - Browser::instance().addWindow(mainWindow); - return mainWindow->currentTab(); + return mainWindow->browser()->createWindow()->currentTab(); } case QWebEnginePage::WebDialog: { WebPopupWindow *popup = new WebPopupWindow(page()->profile()); diff --git a/examples/webenginewidgets/simplebrowser/webview.h b/examples/webenginewidgets/simplebrowser/webview.h index f06162ea3..23a9a29ee 100644 --- a/examples/webenginewidgets/simplebrowser/webview.h +++ b/examples/webenginewidgets/simplebrowser/webview.h @@ -56,6 +56,7 @@ public: int loadProgress() const; bool isWebActionEnabled(QWebEnginePage::WebAction webAction) const; + QIcon favIcon() const; protected: void contextMenuEvent(QContextMenuEvent *event) override; @@ -63,6 +64,7 @@ protected: signals: void webActionEnabledChanged(QWebEnginePage::WebAction webAction, bool enabled); + void favIconChanged(const QIcon &icon); private: void createWebActionTrigger(QWebEnginePage *page, QWebEnginePage::WebAction); -- cgit v1.2.3 From 74f5f945ba62c839977420397fc307fe1edacbc5 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 19 Jul 2017 12:21:58 +0200 Subject: Doc: Align QtWebEngineWidgets overview with the one for the QtWebEngine module Change-Id: If4db465b9764be80df7fe953be63fc1a40b60d75 Reviewed-by: Leena Miettinen --- src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc b/src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc index 959f96b10..3da554a81 100644 --- a/src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc +++ b/src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc @@ -28,8 +28,7 @@ /*! \module QtWebEngineWidgets \title Qt WebEngine Widgets C++ Classes - \brief Provides a web browser engine as well as C++ classes to render and - interact with web content + \brief Provides C++ classes for rendering web content in a QWidget based application \ingroup modules \ingroup qtwebengine-modules \qtvariable webenginewidgets -- cgit v1.2.3 From 9f947d40ad772068b2147aff4f4374dc8c0caf30 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Fri, 14 Jul 2017 10:16:47 +0200 Subject: Speculative stabilization of imeCompositionQueryEvent widget auto test Wait for receiver object to be set after show. Task-number: QTBUG-61816 Change-Id: I2eb62775d30b0f8f9ec3e76d60a924b56c811865 Reviewed-by: Allan Sandfeld Jensen --- tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 7fbbd63d3..c9d5cda90 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -2152,14 +2152,16 @@ void tst_QWebEngineView::imeCompositionQueryEvent() QObject *input = nullptr; QFETCH(QString, receiverObjectName); - if (receiverObjectName == "focusObject") + if (receiverObjectName == "focusObject") { + QTRY_VERIFY(qApp->focusObject()); input = qApp->focusObject(); - else if (receiverObjectName == "focusProxy") + } else if (receiverObjectName == "focusProxy") { + QTRY_VERIFY(view.focusProxy()); input = view.focusProxy(); - else if (receiverObjectName == "focusWidget") + } else if (receiverObjectName == "focusWidget") { + QTRY_VERIFY(view.focusWidget()); input = view.focusWidget(); - - QVERIFY(input); + } QInputMethodQueryEvent srrndTextQuery(Qt::ImSurroundingText); QInputMethodQueryEvent cursorPosQuery(Qt::ImCursorPosition); -- cgit v1.2.3 From b5c8c48a87a19618b23d6d4fc5035915a9322117 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 20 Jul 2017 16:14:47 +0200 Subject: Fix logic to check for proxy settings The previous code tried to find out whether a user has set an application proxy by checking the type of the applicationProxy. This is wrong, because a system proxy will actually also change the applicationProxy type. Instead, we now rely on QNetworkProxyFactory::usesSystemConfiguration to decide whether to use QtNetwork's application proxy, or Chromium's logic for the system proxy. We also save the state of QNetworkProxy::useSystemConfiguration to be able to track changes. [ChangeLog][Networking] Fixed an issue where system proxy settings were not picked up correctly. Task-number: QTBUG-61910 Change-Id: I1d9af3f6006ba187266fe50c645f425a46632e41 Reviewed-by: Peter Varga --- src/core/proxy_config_service_qt.cpp | 92 +++++++++++++++++++++++------------- src/core/proxy_config_service_qt.h | 6 ++- 2 files changed, 63 insertions(+), 35 deletions(-) diff --git a/src/core/proxy_config_service_qt.cpp b/src/core/proxy_config_service_qt.cpp index b7ed83624..491131e42 100644 --- a/src/core/proxy_config_service_qt.cpp +++ b/src/core/proxy_config_service_qt.cpp @@ -36,6 +36,9 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + + +//================ Based on ChromeProxyConfigService ======================= // Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -67,11 +70,10 @@ net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qt return net::ProxyServer(proxyScheme, net::HostPortPair(qtProxy.hostName().toStdString(), qtProxy.port())); } -//================ Based on ChromeProxyConfigService ======================= - ProxyConfigServiceQt::ProxyConfigServiceQt(std::unique_ptr baseService) : m_baseService(baseService.release()), - m_registeredObserver(false) + m_registeredObserver(false), + m_usesSystemConfiguration(false) { } @@ -83,7 +85,6 @@ ProxyConfigServiceQt::~ProxyConfigServiceQt() void ProxyConfigServiceQt::AddObserver(net::ProxyConfigService::Observer *observer) { - RegisterObserver(); m_observers.AddObserver(observer); } @@ -94,28 +95,31 @@ void ProxyConfigServiceQt::RemoveObserver(net::ProxyConfigService::Observer *obs net::ProxyConfigService::ConfigAvailability ProxyConfigServiceQt::GetLatestProxyConfig(net::ProxyConfig *config) { - RegisterObserver(); - - // Ask the base service if available. - net::ProxyConfig systemConfig; - ConfigAvailability systemAvailability = net::ProxyConfigService::CONFIG_UNSET; - if (m_baseService.get()) - systemAvailability = m_baseService->GetLatestProxyConfig(&systemConfig); +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) + m_usesSystemConfiguration = QNetworkProxyFactory::usesSystemConfiguration(); +#endif + if (m_usesSystemConfiguration) { + // Use Chromium's base service to retrieve system settings + net::ProxyConfig systemConfig; + ConfigAvailability systemAvailability = net::ProxyConfigService::CONFIG_UNSET; + if (m_baseService.get()) + systemAvailability = m_baseService->GetLatestProxyConfig(&systemConfig); + *config = systemConfig; + // make sure to get updates via OnProxyConfigChanged + RegisterObserver(); + return systemAvailability; + } + // Use QNetworkProxy::applicationProxy settings const QNetworkProxy &qtProxy = QNetworkProxy::applicationProxy(); if (qtProxy == m_qtApplicationProxy && !m_qtProxyConfig.proxy_rules().empty()) { + // no changes *config = m_qtProxyConfig; return CONFIG_VALID; } + m_qtApplicationProxy = qtProxy; m_qtProxyConfig = net::ProxyConfig(); -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) - if (qtProxy.type() == QNetworkProxy::NoProxy - && QNetworkProxyFactory::usesSystemConfiguration()) { - *config = systemConfig; - return systemAvailability; - } -#endif net::ProxyConfig::ProxyRules qtRules; net::ProxyServer server = fromQNetworkProxy(qtProxy); @@ -145,31 +149,51 @@ net::ProxyConfigService::ConfigAvailability ProxyConfigServiceQt::GetLatestProxy void ProxyConfigServiceQt::OnLazyPoll() { - if (m_qtApplicationProxy != QNetworkProxy::applicationProxy()) { - net::ProxyConfig unusedConfig; - OnProxyConfigChanged(unusedConfig, CONFIG_VALID); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) + // We need to update if + // - setUseSystemConfiguration() was called in between + // - user changed application proxy + if (m_usesSystemConfiguration != QNetworkProxyFactory::usesSystemConfiguration() + || (!m_usesSystemConfiguration && m_qtApplicationProxy != QNetworkProxy::applicationProxy())) { + Update(); + } else if (m_usesSystemConfiguration) { + if (m_baseService.get()) + m_baseService->OnLazyPoll(); } - if (m_baseService.get()) - m_baseService->OnLazyPoll(); +#else + if (m_qtApplicationProxy != QNetworkProxy::applicationProxy()) + Update(); +#endif } - +// Called when the base service changed void ProxyConfigServiceQt::OnProxyConfigChanged(const net::ProxyConfig &config, ConfigAvailability availability) { - Q_UNUSED(config); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + Q_UNUSED(config); - if (m_qtApplicationProxy != QNetworkProxy::applicationProxy() - || m_qtApplicationProxy.type() == QNetworkProxy::NoProxy) { - net::ProxyConfig actual_config; - availability = GetLatestProxyConfig(&actual_config); - if (availability == CONFIG_PENDING) - return; - for (net::ProxyConfigService::Observer &observer: m_observers) - observer.OnProxyConfigChanged(actual_config, availability); - } + if (!m_usesSystemConfiguration) + return; + + Update(); +} + +// Update our observers +void ProxyConfigServiceQt::Update() +{ + net::ProxyConfig actual_config; + ConfigAvailability availability = GetLatestProxyConfig(&actual_config); + if (availability == CONFIG_PENDING) + return; + for (net::ProxyConfigService::Observer &observer: m_observers) + observer.OnProxyConfigChanged(actual_config, availability); } +// Register ourselves as observer of the base service. +// This has to be done on the IO thread, and therefore cannot be done +// in the constructor. void ProxyConfigServiceQt::RegisterObserver() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); diff --git a/src/core/proxy_config_service_qt.h b/src/core/proxy_config_service_qt.h index f2f9a2210..7be3289d0 100644 --- a/src/core/proxy_config_service_qt.h +++ b/src/core/proxy_config_service_qt.h @@ -69,13 +69,17 @@ private: void OnProxyConfigChanged(const net::ProxyConfig& config, ConfigAvailability availability) override; + // Retrieve new proxy settings and notify observers. + void Update(); + // Makes sure that the observer registration with the base service is set up. void RegisterObserver(); std::unique_ptr m_baseService; base::ObserverList m_observers; - // Keep the last QNetworkProxy::applicationProxy state around. + // Keep the last state around. + bool m_usesSystemConfiguration; QNetworkProxy m_qtApplicationProxy; net::ProxyConfig m_qtProxyConfig; -- cgit v1.2.3 From 656d3a7b7d0596d82c753a60b4e69917567b666e Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 21 Jul 2017 16:05:46 +0200 Subject: Avoid default handler in switch Change-Id: I4533e28a2c1a338abdb1d373a0a3bfe598a5edce Reviewed-by: Peter Varga --- src/core/proxy_config_service_qt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/proxy_config_service_qt.cpp b/src/core/proxy_config_service_qt.cpp index 491131e42..32f02f425 100644 --- a/src/core/proxy_config_service_qt.cpp +++ b/src/core/proxy_config_service_qt.cpp @@ -63,7 +63,7 @@ net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qt proxyScheme = net::ProxyServer::SCHEME_HTTP; break; case QNetworkProxy::NoProxy: - default: + case QNetworkProxy::DefaultProxy: proxyScheme = net::ProxyServer::SCHEME_DIRECT; break; } -- cgit v1.2.3 From 4b5029e208affc15cde07006ea91d4a28c243a57 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 27 Jul 2017 08:58:30 +0200 Subject: Doc: Add example code for using Greasemonkey attributes in scripts Task-number: QTBUG-61788 Change-Id: Ie6c29f3999ea795a37ea444f56e40ddc70ca1c03 Reviewed-by: Kai Koehne --- src/webengine/doc/src/external-resources.qdoc | 10 ++++++++++ src/webengine/doc/src/qtwebengine-overview.qdoc | 25 +++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/webengine/doc/src/external-resources.qdoc b/src/webengine/doc/src/external-resources.qdoc index a75c7aaed..6cced588c 100644 --- a/src/webengine/doc/src/external-resources.qdoc +++ b/src/webengine/doc/src/external-resources.qdoc @@ -136,3 +136,13 @@ \externalpage https://http2.akamai.com/demo \title Akamai HTTP/2 Demo */ + +/*! + \externalpage https://www.chromium.org/developers/design-documents/user-scripts + \title User Scripts +*/ + +/*! + \externalpage https://wiki.greasespot.net/Metadata_Block#.40name + \title Metadata Block +*/ diff --git a/src/webengine/doc/src/qtwebengine-overview.qdoc b/src/webengine/doc/src/qtwebengine-overview.qdoc index e180b22c0..e9ca573b7 100644 --- a/src/webengine/doc/src/qtwebengine-overview.qdoc +++ b/src/webengine/doc/src/qtwebengine-overview.qdoc @@ -181,8 +181,29 @@ script to run, the injection point, and the world where the script is run. This enables accessing the DOM to manipulate it within a world. - The following \l Greasemonkey attributes are supported since Qt 5.8: - \c @exclude, \c @include, \c @name, \c @match, and \c @run-at. + Since Qt 5.8, Qt WebEngine supports augmenting a script by using the + following \l{Metadata Block}{Greasemonkey-like attributes}: + + \list + \li \c {@exclude } + \li \c {@include } + \li \c {@match } + \li \c {@name } + \li \c {@run-at [document-start|document-end|document-idle]} + \endlist + + The attributes determine if and when a \l {User Scripts}{user script} is + run. They must be placed immediately in the beginning of the script, inside + a \c ==UserScript== comment: + + \code + // ==UserScript== + // @include http://*.qt.io/* + // @exclude http://wiki.qt.io/* + // ==/UserScript== + + window.alert("Page is from qt.io, but not wiki.qt.io"); + \endcode \section1 Managing Certificates -- cgit v1.2.3 From 4250e432fd8bd197548e119d66259cd5e9ecaf88 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 31 Jul 2017 10:34:24 +0200 Subject: Fix typo in dictionary path Change-Id: I398f88943e6f59781ad9227e2888cb25079b638c Reviewed-by: Kai Koehne --- src/webengine/doc/src/qtwebengine-features.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webengine/doc/src/qtwebengine-features.qdoc b/src/webengine/doc/src/qtwebengine-features.qdoc index b80ad6a35..30d21f2ae 100644 --- a/src/webengine/doc/src/qtwebengine-features.qdoc +++ b/src/webengine/doc/src/qtwebengine-features.qdoc @@ -296,7 +296,7 @@ When the Qt WebEngine spellchecker initializes, it will try to load the \c bdict dictionaries and to check them for consistency. First, it searches \e qtwebengine_dictionaries directories relative to the executable, - then it will look in \c QT_INSTALL_PREFIX/qtwebengines_dictionaries. + then it will look in \c QT_INSTALL_PREFIX/qtwebengine_dictionaries. Spellchecking is disabled by default and can be enabled per profile by using the QWebEngineProfile::setSpellCheckEnabled() method in widget-based -- cgit v1.2.3 From c9a624f398dafb397f75a8682145e1d412bfc100 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 27 Jul 2017 13:46:42 +0200 Subject: Fix demobrowser to not crash when switching to private browsing mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Old QWebEnginePage is destructed by the QWebEngineView::setPage() call. No need to destruct it explicitly. Task-number: QTBUG-62147 Change-Id: I8ec33d5df618f69e4acf1667490df4a67dad9a16 Reviewed-by: Jüri Valdmann Reviewed-by: Kai Koehne --- examples/webenginewidgets/demobrowser/webview.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/webenginewidgets/demobrowser/webview.cpp b/examples/webenginewidgets/demobrowser/webview.cpp index 498df74fc..ce273c0f6 100644 --- a/examples/webenginewidgets/demobrowser/webview.cpp +++ b/examples/webenginewidgets/demobrowser/webview.cpp @@ -341,8 +341,6 @@ WebView::WebView(QWidget* parent) void WebView::setPage(WebPage *_page) { - if (m_page) - m_page->deleteLater(); m_page = _page; QWebEngineView::setPage(_page); #if defined(QWEBENGINEPAGE_STATUSBARMESSAGE) -- cgit v1.2.3 From 905160596f03a4313620e5c68db5dd51d5da0f73 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Fri, 28 Jul 2017 15:08:47 +0200 Subject: Fix reorder warning in proxy_config_service_qt.cpp Task-number: QTBUG-61910 Change-Id: I894d1f180ba9952213b6f67a2445aa927dfd7e9b Reviewed-by: Kai Koehne --- src/core/proxy_config_service_qt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/proxy_config_service_qt.cpp b/src/core/proxy_config_service_qt.cpp index 32f02f425..48f3593e6 100644 --- a/src/core/proxy_config_service_qt.cpp +++ b/src/core/proxy_config_service_qt.cpp @@ -72,8 +72,8 @@ net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qt ProxyConfigServiceQt::ProxyConfigServiceQt(std::unique_ptr baseService) : m_baseService(baseService.release()), - m_registeredObserver(false), - m_usesSystemConfiguration(false) + m_usesSystemConfiguration(false), + m_registeredObserver(false) { } -- cgit v1.2.3 From bad151445176edc55fb37fbae56b3c8a1ab1feb5 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Wed, 2 Aug 2017 15:51:41 +0200 Subject: Fix simplebrowser crash on exit while downloading On webengine profile destruction all download items in progress are canceled. This triggered stateChanged of QWebEngineDownloadItem which called lambda function on already deleted object. Do not use lambda functions in this case. Change-Id: Ia1d359fe47204baa51f1380d1c3547c28550bc28 Reviewed-by: Joerg Bornemann Reviewed-by: Viktor Engelmann --- examples/webenginewidgets/simplebrowser/downloadwidget.cpp | 8 ++------ examples/webenginewidgets/simplebrowser/downloadwidget.h | 4 +++- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/examples/webenginewidgets/simplebrowser/downloadwidget.cpp b/examples/webenginewidgets/simplebrowser/downloadwidget.cpp index a80366f77..cc16d245b 100644 --- a/examples/webenginewidgets/simplebrowser/downloadwidget.cpp +++ b/examples/webenginewidgets/simplebrowser/downloadwidget.cpp @@ -62,14 +62,10 @@ DownloadWidget::DownloadWidget(QWebEngineDownloadItem *download, QWidget *parent }); connect(m_download, &QWebEngineDownloadItem::downloadProgress, - [this](qint64, qint64) { - updateWidget(); - }); + this, &DownloadWidget::updateWidget); connect(m_download, &QWebEngineDownloadItem::stateChanged, - [this](QWebEngineDownloadItem::DownloadState) { - updateWidget(); - }); + this, &DownloadWidget::updateWidget); updateWidget(); } diff --git a/examples/webenginewidgets/simplebrowser/downloadwidget.h b/examples/webenginewidgets/simplebrowser/downloadwidget.h index e8cf42825..02c42fb44 100644 --- a/examples/webenginewidgets/simplebrowser/downloadwidget.h +++ b/examples/webenginewidgets/simplebrowser/downloadwidget.h @@ -63,8 +63,10 @@ signals: // this download from the downloads list. void removeClicked(DownloadWidget *self); -private: +private slots: void updateWidget(); + +private: QString withUnit(qreal bytes); QWebEngineDownloadItem *m_download; -- cgit v1.2.3 From 6f826b2f6d9423c8a0df1ef1f64a2cf3b4651570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCri=20Valdmann?= Date: Wed, 2 Aug 2017 16:29:04 +0200 Subject: Fix signal name in simplebrowser example documentation Change-Id: Id3bf1218e43609cdb471e087e2077d4c0c0e5153 Reviewed-by: Leena Miettinen --- examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc index 6736f8570..2ca4bfc45 100644 --- a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc +++ b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc @@ -258,7 +258,7 @@ \section1 Managing Downloads Downloads are associated with a \l QWebEngineProfile. Whenever a download is - triggered on a web page the \l QWebEngineProfile::defaultProfile signal is + triggered on a web page the \l QWebEngineProfile::downloadRequested signal is emitted with a \l QWebEngineDownloadItem, which in this example is forwarded to \c DownloadManagerWidget::downloadRequested: -- cgit v1.2.3 From b238f224a7827de182e8ac77ffac31d9ae25ce57 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 3 Aug 2017 16:10:40 +0200 Subject: Doc: List some command-line arguments that are useful during debugging Task-number: QTBUG-61796 Change-Id: I76d3fec780796dd0f300c54a1bccecc50f7270e0 Reviewed-by: Allan Sandfeld Jensen --- src/webengine/doc/src/qtwebengine-debugging.qdoc | 33 +++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/webengine/doc/src/qtwebengine-debugging.qdoc b/src/webengine/doc/src/qtwebengine-debugging.qdoc index e929fabeb..5ff1c6342 100644 --- a/src/webengine/doc/src/qtwebengine-debugging.qdoc +++ b/src/webengine/doc/src/qtwebengine-debugging.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -71,4 +71,35 @@ For a detailed explanation of the capabilities of developer tools, see the \l {Chrome DevTools} page. + + \section1 Using Command-Line Arguments + + You can use the following command-line arguments while debugging to provide + input for bug reports: + + \list + \li \c {--disable-gpu} disables GPU hardware acceleration. This is + useful when diagnosing OpenGL problems. + \li \c {--disable-logging} disables console logging, which might be + useful for debug builds. + \li \c {--enable-logging --log-level=0} enables console logging and sets + the logging level to 0, which means that messages of the severity + \c info and above are recorded in the log. This is the default for + debug builds. Other possible log levels are \c 1 for warnings, \c 2 + for errors, and \c 3 for fatal errors. + \li \c {--no-sandbox} disables the sandbox for the renderer and plugin + processes. Keep in mind that disabling the sandbox might present a + security risk. + \li \c {--single-process} runs the renderer and plugins in the same + process as the browser. This is useful for getting stack traces for + renderer crashes. + \endlist + + Alternatively, the environment variable QTWEBENGINE_CHROMIUM_FLAGS can be + set. For example, the following value could be set to disable logging while + debugging an application called \e mybrowser: + + \code + QTWEBENGINE_CHROMIUM_FLAGS="--disable-logging" mybrowser + \endcode */ -- cgit v1.2.3 From 59e35e033b8c8327db5b3fdbfb5d6ecee48a4405 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 3 Aug 2017 10:40:38 +0200 Subject: Set web contents font setting to default Chromium has since version 50 overridden the global font settings with the settings of every web contents created, so we need to first set the global settings in the web contents, to still follow system defaults. Task-number: QTBUG-62146 Change-Id: If10847c81beda08ecb7bfdf7556e39b1d2989754 Reviewed-by: Joerg Bornemann --- src/core/web_contents_adapter.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index a788b9679..8273b247f 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -83,6 +83,7 @@ #include "content/public/common/web_preferences.h" #include "third_party/WebKit/public/web/WebFindOptions.h" #include "printing/features/features.h" +#include "ui/gfx/font_render_params.h" #include #include @@ -425,6 +426,15 @@ void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) if (commandLine->HasSwitch(switches::kForceWebRtcIPHandlingPolicy)) rendererPrefs->webrtc_ip_handling_policy = commandLine->GetSwitchValueASCII(switches::kForceWebRtcIPHandlingPolicy); #endif + // Set web-contents font settings to the default font settings as Chromium constantly overrides + // the global font defaults with the font settings of the latest web-contents created. + CR_DEFINE_STATIC_LOCAL(const gfx::FontRenderParams, params, (gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), NULL))); + rendererPrefs->should_antialias_text = params.antialiasing; + rendererPrefs->use_subpixel_positioning = params.subpixel_positioning; + rendererPrefs->hinting = params.hinting; + rendererPrefs->use_autohinter = params.autohinter; + rendererPrefs->use_bitmaps = params.use_bitmaps; + rendererPrefs->subpixel_rendering = params.subpixel_rendering; d->webContents->GetRenderViewHost()->SyncRendererPrefs(); // Create and attach observers to the WebContents. -- cgit v1.2.3