summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorYigit Akcay <yigit.akcay@qt.io>2023-03-23 16:12:06 +0100
committerYigit Akcay <yigit.akcay@qt.io>2023-04-05 14:19:20 +0200
commitfe9d72d931f40eafca97c1012c03e24561c973ff (patch)
tree08e36634557eadae962bb56b82137294a384879c /examples
parent88ef502099d535823156c31e77251dd2a723ad1c (diff)
Merge recipe browser, stylesheet browser and markdown editor examples
This patch merges the qtwebengine examples recipe browser, stylesheet browser and markdown editor into one single example. Pick-to: 6.5 Task-number: QTBUG-108751 Change-Id: I338707d7d3275b03bf2a2d7b65064ac91e562d7f Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'examples')
-rw-r--r--examples/webenginequick/CMakeLists.txt3
-rw-r--r--examples/webenginequick/recipebrowser/CMakeLists.txt158
-rw-r--r--examples/webenginequick/recipebrowser/doc/images/recipebrowser-demo.jpgbin33398 -> 0 bytes
-rw-r--r--examples/webenginequick/recipebrowser/doc/src/recipebrowser.qdoc209
-rw-r--r--examples/webenginequick/recipebrowser/main.cpp30
-rw-r--r--examples/webenginequick/recipebrowser/recipebrowser.pro21
-rw-r--r--examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/qt_attribution.json34
-rw-r--r--examples/webenginequick/recipebrowser/resources/pages/assets/custom.js20
-rw-r--r--examples/webenginequick/recipebrowser/resources/qml/RecipeList.qml125
-rw-r--r--examples/webenginequick/recipebrowser/resources/qml/main.qml121
-rw-r--r--examples/webenginequick/recipebrowser/resources/resources.qrc27
-rw-r--r--examples/webenginequick/webenginequick.pro3
-rw-r--r--examples/webenginewidgets/CMakeLists.txt3
-rw-r--r--examples/webenginewidgets/markdowneditor/CMakeLists.txt58
-rw-r--r--examples/webenginewidgets/markdowneditor/doc/images/markdowneditor-example.pngbin41883 -> 0 bytes
-rw-r--r--examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc159
-rw-r--r--examples/webenginewidgets/markdowneditor/document.cpp12
-rw-r--r--examples/webenginewidgets/markdowneditor/document.h26
-rw-r--r--examples/webenginewidgets/markdowneditor/main.cpp19
-rw-r--r--examples/webenginewidgets/markdowneditor/mainwindow.cpp147
-rw-r--r--examples/webenginewidgets/markdowneditor/mainwindow.h45
-rw-r--r--examples/webenginewidgets/markdowneditor/mainwindow.ui115
-rw-r--r--examples/webenginewidgets/markdowneditor/markdowneditor.pro32
-rw-r--r--examples/webenginewidgets/markdowneditor/previewpage.cpp17
-rw-r--r--examples/webenginewidgets/markdowneditor/previewpage.h19
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKDOWN-LICENSE.txt16
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKED-LICENSE.txt19
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/3rdparty/markdown.css260
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.js1514
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json34
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/default.md12
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/index.html32
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc8
-rw-r--r--examples/webenginewidgets/recipebrowser/CMakeLists.txt71
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/3rdparty/MARKDOWN-LICENSE.txt (renamed from examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/MARKDOWN-LICENSE.txt)0
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/3rdparty/MARKED-LICENSE.txt (renamed from examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/MARKED-LICENSE.txt)0
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/3rdparty/markdown.css (renamed from examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/markdown.css)0
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/3rdparty/marked.js (renamed from examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/marked.js)0
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/3rdparty/qt_attribution.json34
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/custom.css (renamed from examples/webenginequick/recipebrowser/resources/pages/assets/custom.css)2
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/custom.js13
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/burger.html (renamed from examples/webenginequick/recipebrowser/resources/pages/burger.html)27
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/cupcakes.html (renamed from examples/webenginequick/recipebrowser/resources/pages/cupcakes.html)28
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/images/burger.jpg (renamed from examples/webenginequick/recipebrowser/resources/pages/images/burger.jpg)bin48882 -> 48882 bytes
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/images/cupcakes.jpg (renamed from examples/webenginequick/recipebrowser/resources/pages/images/cupcakes.jpg)bin38653 -> 38653 bytes
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/images/pasta.jpg (renamed from examples/webenginequick/recipebrowser/resources/pages/images/pasta.jpg)bin42411 -> 42411 bytes
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/images/pizza.jpg (renamed from examples/webenginequick/recipebrowser/resources/pages/images/pizza.jpg)bin49068 -> 49068 bytes
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/images/skewers.jpg (renamed from examples/webenginequick/recipebrowser/resources/pages/images/skewers.jpg)bin49246 -> 49246 bytes
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/images/soup.jpg (renamed from examples/webenginequick/recipebrowser/resources/pages/images/soup.jpg)bin49028 -> 49028 bytes
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/images/steak.jpg (renamed from examples/webenginequick/recipebrowser/resources/pages/images/steak.jpg)bin49202 -> 49202 bytes
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/pasta.html (renamed from examples/webenginequick/recipebrowser/resources/pages/pasta.html)28
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/pizza.html (renamed from examples/webenginequick/recipebrowser/resources/pages/pizza.html)28
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/skewers.html (renamed from examples/webenginequick/recipebrowser/resources/pages/skewers.html)27
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/soup.html (renamed from examples/webenginequick/recipebrowser/resources/pages/soup.html)28
-rw-r--r--examples/webenginewidgets/recipebrowser/assets/pages/steak.html (renamed from examples/webenginequick/recipebrowser/resources/pages/steak.html)27
-rw-r--r--examples/webenginewidgets/recipebrowser/doc/images/recipebrowser.webpbin0 -> 34058 bytes
-rw-r--r--examples/webenginewidgets/recipebrowser/doc/src/recipebrowser.qdoc197
-rw-r--r--examples/webenginewidgets/recipebrowser/document.cpp48
-rw-r--r--examples/webenginewidgets/recipebrowser/document.h36
-rw-r--r--examples/webenginewidgets/recipebrowser/main.cpp (renamed from examples/webenginewidgets/stylesheetbrowser/main.cpp)4
-rw-r--r--examples/webenginewidgets/recipebrowser/mainwindow.cpp153
-rw-r--r--examples/webenginewidgets/recipebrowser/mainwindow.h (renamed from examples/webenginewidgets/stylesheetbrowser/mainwindow.h)14
-rw-r--r--examples/webenginewidgets/recipebrowser/mainwindow.ui106
-rw-r--r--examples/webenginewidgets/recipebrowser/recipebrowser.pro (renamed from examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.pro)12
-rw-r--r--examples/webenginewidgets/recipebrowser/recipebrowser.qrc15
-rw-r--r--examples/webenginewidgets/recipebrowser/stylesheetdialog.cpp (renamed from examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp)23
-rw-r--r--examples/webenginewidgets/recipebrowser/stylesheetdialog.h (renamed from examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h)2
-rw-r--r--examples/webenginewidgets/recipebrowser/stylesheetdialog.ui (renamed from examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.ui)0
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/3rdparty/COPYING1
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/3rdparty/qt_attribution.json24
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/3rdparty/view-refresh.pngbin1364 -> 0 bytes
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/CMakeLists.txt53
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/doc/images/stylesheetbrowser.pngbin45161 -> 0 bytes
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/doc/src/stylesheetbrowser.qdoc44
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp122
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/mainwindow.ui133
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.qrc5
-rw-r--r--examples/webenginewidgets/webenginewidgets.pro3
78 files changed, 872 insertions, 3734 deletions
diff --git a/examples/webenginequick/CMakeLists.txt b/examples/webenginequick/CMakeLists.txt
index ff291fdcf..52ba7cb0b 100644
--- a/examples/webenginequick/CMakeLists.txt
+++ b/examples/webenginequick/CMakeLists.txt
@@ -3,6 +3,3 @@
qt_internal_add_example(lifecycle)
qt_internal_add_example(quicknanobrowser)
-if(TARGET Qt::QuickControls2)
- qt_internal_add_example(recipebrowser)
-endif()
diff --git a/examples/webenginequick/recipebrowser/CMakeLists.txt b/examples/webenginequick/recipebrowser/CMakeLists.txt
deleted file mode 100644
index 12aa7c1d3..000000000
--- a/examples/webenginequick/recipebrowser/CMakeLists.txt
+++ /dev/null
@@ -1,158 +0,0 @@
-# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
-
-cmake_minimum_required(VERSION 3.16)
-project(recipebrowser LANGUAGES CXX)
-
-set(CMAKE_AUTOMOC ON)
-
-if(NOT DEFINED INSTALL_EXAMPLESDIR)
- set(INSTALL_EXAMPLESDIR "examples")
-endif()
-
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/webenginequick/recipebrowser")
-
-find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick QuickControls2 WebEngineQuick)
-
-qt_add_executable(recipebrowser
- main.cpp
-)
-
-set_target_properties(recipebrowser PROPERTIES
- WIN32_EXECUTABLE TRUE
- MACOSX_BUNDLE TRUE
-)
-
-target_link_libraries(recipebrowser PUBLIC
- Qt::Core
- Qt::Gui
- Qt::Qml
- Qt::Quick
- Qt::QuickControls2
- Qt::WebEngineQuick
-)
-
-# Resources:
-set_source_files_properties("resources/pages/assets/3rdparty/markdown.css"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/assets/3rdparty/marked.js"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/assets/custom.css"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/assets/custom.js"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/burger.html"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/cupcakes.html"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/images/burger.jpg"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/images/cupcakes.jpg"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/images/pasta.jpg"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/images/pizza.jpg"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/images/skewers.jpg"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/images/soup.jpg"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/images/steak.jpg"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/pasta.html"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/pizza.html"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/skewers.html"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/soup.html"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/pages/steak.html"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/qml/RecipeList.qml"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set_source_files_properties("resources/qml/main.qml"
- PROPERTIES QT_SKIP_QUICKCOMPILER 1
-)
-
-set(resources_resource_files
- "resources/pages/assets/3rdparty/markdown.css"
- "resources/pages/assets/3rdparty/marked.js"
- "resources/pages/assets/custom.css"
- "resources/pages/assets/custom.js"
- "resources/pages/burger.html"
- "resources/pages/cupcakes.html"
- "resources/pages/images/burger.jpg"
- "resources/pages/images/cupcakes.jpg"
- "resources/pages/images/pasta.jpg"
- "resources/pages/images/pizza.jpg"
- "resources/pages/images/skewers.jpg"
- "resources/pages/images/soup.jpg"
- "resources/pages/images/steak.jpg"
- "resources/pages/pasta.html"
- "resources/pages/pizza.html"
- "resources/pages/skewers.html"
- "resources/pages/soup.html"
- "resources/pages/steak.html"
- "resources/qml/main.qml"
- "resources/qml/RecipeList.qml"
-)
-
-qt_add_resources(recipebrowser "resources"
- PREFIX
- "/"
- BASE
- "resources"
- FILES
- ${resources_resource_files}
-)
-
-if(CMAKE_CROSSCOMPILING AND (LINUX OR QNX OR posix))
- target_compile_definitions(recipebrowser PUBLIC
- QTWEBENGINE_RECIPE_BROWSER_EMBEDDED
- )
-endif()
-
-install(TARGETS recipebrowser
- RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
- BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
- LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
-)
diff --git a/examples/webenginequick/recipebrowser/doc/images/recipebrowser-demo.jpg b/examples/webenginequick/recipebrowser/doc/images/recipebrowser-demo.jpg
deleted file mode 100644
index 761ad3576..000000000
--- a/examples/webenginequick/recipebrowser/doc/images/recipebrowser-demo.jpg
+++ /dev/null
Binary files differ
diff --git a/examples/webenginequick/recipebrowser/doc/src/recipebrowser.qdoc b/examples/webenginequick/recipebrowser/doc/src/recipebrowser.qdoc
deleted file mode 100644
index d2de5780c..000000000
--- a/examples/webenginequick/recipebrowser/doc/src/recipebrowser.qdoc
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
-
-/*!
- \example webenginequick/recipebrowser
- \title WebEngine Recipe Browser
- \ingroup webengine-examples
- \brief A small hybrid application based on the WebEngineView QML type and Qt Quick Controls 2.
-
- \image recipebrowser-demo.jpg
-
- \e {Recipe Browser} demonstrates how to use the \l{WebEngineView} item, \l{Qt Quick} items, and
- \l{Qt Quick Controls 2} items to develop a small hybrid web browser application.
- A \l{ListView}-based item is used to display a list of recipe names. Clicking on
- a name causes the web view to load the respective recipe page. The overall appearance
- of the application is provided by the \l{Qt Quick Controls 2} items, which have their active
- style set to the \l{Material Style}{Material} style. The web content is a mix of HTML and
- Markdown source compiled to HTML, along with CSS and JavaScript.
-
- \include examples-run.qdocinc
-
- \section1 C++ Code
-
- In \c main.cpp, we use the \l{QGuiApplication} and \l{QQmlApplicationEngine}
- classes to set up and load the main QML file. We call \l{QtWebEngineQuick::initialize} so we can use
- \l{WebEngineView} in our QML code. We set the default Qt Quick Controls 2 style
- to the Material style, so we do not have to specify it for each new item we add. Finally, we use
- a C++ define to check whether the application is compiled for an embedded platform.
- The value will be used in the main QML code to determine the window size.
-
- \quotefromfile webenginequick/recipebrowser/main.cpp
- \skipto #include
- \printuntil }
-
- \section1 QML Code
-
- In the \c main.qml file, we first create a top-level window and set a title for it. We also set
- up the size of the window depending on its primary orientation as well as the platform, so that
- the application is usable on both desktop and embedded platforms. On desktop, the size
- is constrained by a minimum of 320x480 pixels up to the maximum size that the screen supports.
- The default window size is 1024 pixels wide and 768 pixels high in landscape orientation.
- On embedded devices, the window will occupy the whole screen.
-
- \quotefromfile webenginequick/recipebrowser/resources/qml/main.qml
- \skipto ApplicationWindow
- \printuntil minimumHeight
-
- Next, we add a \l{RowLayout} item so we can divide the window into two parts: one being a
- custom \c RecipeList item containing the recipe titles, and the other being the
- \l{WebEngineView}, which shows the recipe details. The spacing is set to zero so the items are
- positioned directly next to each other.
-
- \printuntil RecipeList
- \dots 16
- \skipuntil webView.showRecipe
- \printline }
- \printuntil WebEngineView
- \dots 16
- \skipuntil busy.running = true
- \skipline }
- \skipline }
- \printline }
- \printline }
-
- The \c RecipeList item has a few \l{Layout}{attached Layout properties}, in order to scale the
- item to a maximum of one third of the layout width. We give the item focus, so that the keyboard
- can be used to navigate the recipes, in addition to using mouse and touch. We also add a handler
- for the custom \c recipeSelected signal, to tell the WebEngineView to load the URL of the
- selected recipe.
-
- \quotefromfile webenginequick/recipebrowser/resources/qml/main.qml
- \skipto RecipeList
- \printuntil }
-
- The WebEngineView has similar layout properties, to make it occupy two thirds of the layout
- width.
-
- \skipto WebEngineView
- \printuntil Layout.fillHeight
-
- We then disable the \l{WebEngineSettings::focusOnNavigationEnabled}{focusOnNavigationEnabled}
- setting to make sure that the \l{WebEngineView} does not steal focus from the \c RecipeList
- item every time its URL is changed. This allows the user to continue navigating through the
- recipes using the keyboard. We also disable the default context menu by accepting the
- ContextMenuRequest.
-
- \skipto focusOnNavigationEnabled
- \printuntil }
-
- When the application starts, instead of directly showing the \l{WebEngineView}, we show a
- placeholder \l{Rectangle} with a \l{BusyIndicator} to provide a nicer user experience while the
- application is loading.
-
- \printuntil }
- \dots 12
- \skipto Rectangle
- \printuntil }
-
- Once the first page in the view is loaded, we start a \l{Timer} that
- will hide the placeholder and show the actual page. The delay provides more time for the recipe
- images to load, so that when the view is shown, the page is completely rendered. The timer also
- shows a help \l{ToolTip} that informs the user on how to navigate the recipes.
-
- \quotefromfile webenginequick/recipebrowser/resources/qml/main.qml
- \skipto Timer {
- \printuntil }
-
- Let's see what the \c RecipeList item looks like from the inside. The root item is a
- FocusScope to allow transferring focus to the child ListView whenever the root item receives
- focus. We also declare a custom \c recipeSelected signal, which will be emitted when the current
- item of the ListView changes.
-
- \quotefromfile webenginequick/recipebrowser/resources/qml/RecipeList.qml
- \skipto FocusScope
- \printuntil recipeSelected
-
- A ColumnLayout holds a header \l{Label} above the ListView, and the ListView itself.
- Again, we set the spacing to zero and make sure the layout occupies the whole space of
- the parent item.
-
- \skipto ColumnLayout
- \printuntil anchors.fill
-
- Inside the layout there is a styled \l{ToolBar} item, with a \l{Label} inside of it serving as
- the ListView header.
-
- \skipto ToolBar
- \printuntil Label
- \printuntil }
- \printuntil }
-
- The second item inside the layout is a \l{ListView}, whose contents will fill the remaining
- space in the layout. We set \l{Item::}{clip} to true, so that the delegates that are scrolled
- up are not seen under the ToolBar item. We set \l{Item::}{focus} to true, so the ListView gains
- focus when the FocusScope does. We add a vertical scroll bar, so the user can scroll through the
- recipes if the window size is small. We also specify the recipe model to be used by the
- ListView as described later in this topic.
-
- \skipto ListView
- \printuntil model
-
- We have an \l{ItemDelegate} set as the ListView delegate, which displays the
- recipe title. The contentItem is a \l{Text} item, customized with a few properties to adjust the
- visual appearance and position of the text. We create a binding to the current delegate's model
- URL, so we can access the respective URL outside the delegate itself. We set the
- \l{ItemDelegate::}{highlighted} property to \c true whenever the item is the current one in the
- ListView to provide visual feedback. And we set the focus on the ListView whenever a delegate
- is clicked, so that keyboard navigation works in case the focus was previously in the
- WebEngineView.
-
- \skipto delegate
- \printuntil onClicked
- \printuntil }
- \printuntil }
-
- A handler is defined for the \c currentItemChanged signal to emit our own \c recipeSelected
- signal with the URL that the WebEngineView should load.
-
- \skipto onCurrentItemChanged
- \printuntil }
-
- We use a \l{ListModel} with seven \l{ListElement}s, each of which contains a recipe
- title and the URL to an HTML page contained in a resource file. The model is used to populate
- the ListView with the recipes and to show the recipe details in the WebEngineView.
-
- \skipto ListModel
- \printuntil Cupcakes
- \printuntil }
- \printuntil }
-
- We use a \l{ToolTip} item that is displayed on application startup to inform the users
- how they can navigate and view the details of each recipe. The ToolTip is shown using the
- \c showHelp method, which is invoked by the \l{Timer} in the main.qml file.
-
- \skipto ToolTip
- \printuntil help.open()
- \printuntil }
- \printuntil }
-
- An example of a recipe page can be seen below. The page uses two stylesheets and
- two JavaScript files:
- \list
- \li \l{https://bitbucket.org/kevinburke/markdowncss/src/master/}{markdown.css} is
- a markdown-friendly stylesheet created by Kevin Burke
- \li \l{https://github.com/chjj/marked}{marked.min.js} is a markdown parser and
- compiler designed for speed written by Christopher Jeffrey
- \li custom.css makes some small styling adjustments to the final recipe page
- \li custom.js is used to invoke the conversion of the recipe content (which is written in
- markdown syntax) into HTML
- \endlist
-
- The images on the pages are loaded from the compiled resource file.
-
- \quotefromfile webenginequick/recipebrowser/resources/pages/soup.html
- \printuntil </html>
-
- \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/webenginequick/recipebrowser/main.cpp b/examples/webenginequick/recipebrowser/main.cpp
deleted file mode 100644
index 076a3be9a..000000000
--- a/examples/webenginequick/recipebrowser/main.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#include <QGuiApplication>
-#include <QQmlApplicationEngine>
-#include <QQmlContext>
-#include <QQuickStyle>
-#include <QtWebEngineQuick/qtwebenginequickglobal.h>
-
-int main(int argc, char *argv[])
-{
- QCoreApplication::setOrganizationName("QtExamples");
- QtWebEngineQuick::initialize();
-
- QGuiApplication app(argc, argv);
-
- QQuickStyle::setStyle(QStringLiteral("Material"));
-
- QQmlApplicationEngine engine;
-
- bool isEmbedded = false;
-#ifdef QTWEBENGINE_RECIPE_BROWSER_EMBEDDED
- isEmbedded = true;
-#endif
- engine.rootContext()->setContextProperty(QStringLiteral("isEmbedded"), isEmbedded);
-
- engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
-
- return app.exec();
-}
diff --git a/examples/webenginequick/recipebrowser/recipebrowser.pro b/examples/webenginequick/recipebrowser/recipebrowser.pro
deleted file mode 100644
index e358d00a3..000000000
--- a/examples/webenginequick/recipebrowser/recipebrowser.pro
+++ /dev/null
@@ -1,21 +0,0 @@
-TEMPLATE = app
-
-QT += quick qml quickcontrols2 webenginequick
-
-cross_compile {
- posix|qnx|linux: DEFINES += QTWEBENGINE_RECIPE_BROWSER_EMBEDDED
-}
-
-SOURCES += main.cpp
-
-RESOURCES += resources/resources.qrc
-
-# Make sure Qt Quick compiler does not remove the source code of the .js files.
-QTQUICK_COMPILER_SKIPPED_RESOURCES = resources/resources.qrc
-
-DISTFILES += \
- resources/pages/assets/3rdparty/MARKDOWN-LICENSE.txt \
- resources/pages/assets/3rdparty/MARKED-LICENSE.txt
-
-target.path = $$[QT_INSTALL_EXAMPLES]/webenginequick/recipebrowser
-INSTALLS += target
diff --git a/examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/qt_attribution.json b/examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/qt_attribution.json
deleted file mode 100644
index 4dafa1acd..000000000
--- a/examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/qt_attribution.json
+++ /dev/null
@@ -1,34 +0,0 @@
-[
- {
- "Id": "recipebrowser-marked",
- "Name": "Marked (WebEngine RecipeBrowser example)",
- "QDocModule": "qtwebengine",
- "QtUsage": "Marked is used in the WebEngine RecipeBrowser example",
- "QtParts": [ "examples" ],
- "Files": "marked.js",
- "Description": "A full-featured markdown parser and compiler, written in JavaScript. Built for speed.",
- "Homepage": "https://github.com/chjj/marked",
- "Version": "0.4.0",
- "DownloadLocation": "https://github.com/markedjs/marked/blob/0.4.0/lib/marked.js",
- "Copyright": "Copyright (c) 2011-2018, 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.",
- "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/webenginequick/recipebrowser/resources/pages/assets/custom.js b/examples/webenginequick/recipebrowser/resources/pages/assets/custom.js
deleted file mode 100644
index 2be2cf1ec..000000000
--- a/examples/webenginequick/recipebrowser/resources/pages/assets/custom.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-marked.setOptions({
- renderer: new marked.Renderer(),
- gfm: true,
- tables: true,
- breaks: false,
- pedantic: false,
- sanitize: false,
- smartLists: true,
- smartypants: false
-});
-
-// Poor man document.ready();
-(function() {
- var placeholder = document.getElementById('placeholder');
- var content = document.getElementById('content');
- placeholder.innerHTML = marked(content.innerHTML);
-})();
diff --git a/examples/webenginequick/recipebrowser/resources/qml/RecipeList.qml b/examples/webenginequick/recipebrowser/resources/qml/RecipeList.qml
deleted file mode 100644
index bfaf59112..000000000
--- a/examples/webenginequick/recipebrowser/resources/qml/RecipeList.qml
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-import QtQuick
-import QtQuick.Controls
-import QtQuick.Controls.Material
-import QtQuick.Layouts
-
-FocusScope {
- id: root
- signal recipeSelected(url url)
-
- ColumnLayout {
- spacing: 0
- anchors.fill: parent
-
- ToolBar {
- id: headerBackground
- Layout.fillWidth: true
- implicitHeight: headerText.height + 20
-
- Label {
- id: headerText
- width: parent.width
- text: qsTr("Favorite recipes")
- padding: 10
- anchors.centerIn: parent
- }
- }
-
- ListView {
- id: listView
- Layout.fillWidth: true
- Layout.fillHeight: true
- keyNavigationWraps: true
- clip: true
- focus: true
- ScrollBar.vertical: ScrollBar { }
-
- model: recipeModel
-
- delegate: ItemDelegate {
- width: parent.width
- text: model.name
- contentItem: Text {
- text: parent.text
- font: parent.font
- color: parent.enabled ? parent.Material.primaryTextColor
- : parent.Material.hintTextColor
- elide: Text.ElideRight
- horizontalAlignment: Text.AlignLeft
- verticalAlignment: Text.AlignVCenter
- wrapMode: Text.Wrap
- }
-
- property url url: model.url
- highlighted: ListView.isCurrentItem
-
- onClicked: {
- listView.forceActiveFocus()
- listView.currentIndex = model.index
- }
- }
-
- onCurrentItemChanged: {
- root.recipeSelected(currentItem.url)
- }
-
- ListModel {
- id: recipeModel
-
- ListElement {
- name: "Pizza Diavola"
- url: "qrc:///pages/pizza.html"
- }
- ListElement {
- name: "Steak"
- url: "qrc:///pages/steak.html"
- }
- ListElement {
- name: "Burger"
- url: "qrc:///pages/burger.html"
- }
- ListElement {
- name: "Soup"
- url: "qrc:///pages/soup.html"
- }
- ListElement {
- name: "Pasta"
- url: "qrc:///pages/pasta.html"
- }
- ListElement {
- name: "Grilled Skewers"
- url: "qrc:///pages/skewers.html"
- }
- ListElement {
- name: "Cupcakes"
- url: "qrc:///pages/cupcakes.html"
- }
- }
-
- ToolTip {
- id: help
- implicitWidth: root.width - padding * 3
- y: root.y + root.height
- delay: 1000
- timeout: 5000
- text: qsTr("Use keyboard, mouse, or touch controls to navigate through the\
- recipes.")
-
- contentItem: Text {
- text: help.text
- font: help.font
- color: help.Material.primaryTextColor
- wrapMode: Text.Wrap
- }
- }
- }
- }
-
- function showHelp() {
- help.open()
- }
-}
-
diff --git a/examples/webenginequick/recipebrowser/resources/qml/main.qml b/examples/webenginequick/recipebrowser/resources/qml/main.qml
deleted file mode 100644
index 7db43c871..000000000
--- a/examples/webenginequick/recipebrowser/resources/qml/main.qml
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-import QtQml
-import QtQuick
-import QtQuick.Controls
-import QtQuick.Controls.Material
-import QtQuick.Layouts
-import QtQuick.Window
-import QtWebEngine
-
-ApplicationWindow {
- id: appWindow
- title: qsTr("Recipe Browser")
- visible: true
-
- property int shorterDesktop: 768
- property int longerDesktop: 1024
- property int shorterMin: 360
- property int longerMin: 480
- property bool isPortrait: Screen.primaryOrientation === Qt.PortraitOrientation
- width: {
- if (isEmbedded)
- return Screen.width
- var potentialWidth = shorterDesktop
- if (!isPortrait)
- potentialWidth = longerDesktop
- return potentialWidth > Screen.width ? Screen.width : potentialWidth
- }
- height: {
- if (isEmbedded)
- return Screen.height
- var potentialHeight = longerDesktop
- if (!isPortrait)
- potentialHeight = shorterDesktop
- return potentialHeight > Screen.height ? Screen.height : potentialHeight
- }
- minimumWidth: isPortrait ? shorterMin : longerMin
- minimumHeight: isPortrait ? longerMin : shorterMin
-
- RowLayout {
- id: container
- anchors.fill: parent
- spacing: 0
-
- RecipeList {
- id: recipeList
- Layout.minimumWidth: 124
- Layout.preferredWidth: parent.width / 3
- Layout.maximumWidth: 300
- Layout.fillWidth: true
- Layout.fillHeight: true
- focus: true
- activeFocusOnTab: true
- onRecipeSelected: function(url) {
- webView.showRecipe(url)
- }
- }
-
- WebEngineView {
- id: webView
- Layout.preferredWidth: 2 * parent.width / 3
- Layout.fillWidth: true
- Layout.fillHeight: true
- // Make sure focus is not taken by the web view, so user can continue navigating
- // recipes with the keyboard.
- settings.focusOnNavigationEnabled: false
-
- onContextMenuRequested: function(request) {
- request.accepted = true
- }
-
- property bool firstLoadComplete: false
- onLoadingChanged: function(loadRequest) {
- if (loadRequest.status === WebEngineView.LoadSucceededStatus
- && !firstLoadComplete) {
- // Debounce the showing of the web content, so images are more likely
- // to have loaded completely.
- showTimer.start()
- }
- }
-
- Timer {
- id: showTimer
- interval: 500
- repeat: false
- onTriggered: {
- webView.show(true)
- webView.firstLoadComplete = true
- recipeList.showHelp()
- }
- }
-
- Rectangle {
- id: webViewPlaceholder
- anchors.fill: parent
- z: 1
- color: "white"
-
- BusyIndicator {
- id: busy
- anchors.centerIn: parent
- }
- }
-
- function showRecipe(url) {
- webView.url = url
- }
-
- function show(show) {
- if (show === true) {
- busy.running = false
- webViewPlaceholder.visible = false
- } else {
- webViewPlaceholder.visible = true
- busy.running = true
- }
- }
- }
- }
-}
diff --git a/examples/webenginequick/recipebrowser/resources/resources.qrc b/examples/webenginequick/recipebrowser/resources/resources.qrc
deleted file mode 100644
index bd13dcfae..000000000
--- a/examples/webenginequick/recipebrowser/resources/resources.qrc
+++ /dev/null
@@ -1,27 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>qml/main.qml</file>
- <file>qml/RecipeList.qml</file>
-
- <file>pages/pizza.html</file>
- <file>pages/burger.html</file>
- <file>pages/steak.html</file>
- <file>pages/soup.html</file>
- <file>pages/pasta.html</file>
- <file>pages/skewers.html</file>
- <file>pages/cupcakes.html</file>
-
- <file>pages/assets/3rdparty/marked.js</file>
- <file>pages/assets/3rdparty/markdown.css</file>
- <file>pages/assets/custom.css</file>
- <file>pages/assets/custom.js</file>
-
- <file>pages/images/burger.jpg</file>
- <file>pages/images/pizza.jpg</file>
- <file>pages/images/steak.jpg</file>
- <file>pages/images/soup.jpg</file>
- <file>pages/images/pasta.jpg</file>
- <file>pages/images/skewers.jpg</file>
- <file>pages/images/cupcakes.jpg</file>
- </qresource>
-</RCC>
diff --git a/examples/webenginequick/webenginequick.pro b/examples/webenginequick/webenginequick.pro
index acf6127d6..fb44f2c54 100644
--- a/examples/webenginequick/webenginequick.pro
+++ b/examples/webenginequick/webenginequick.pro
@@ -5,6 +5,5 @@ SUBDIRS += \
qtHaveModule(quickcontrols2) {
SUBDIRS += \
- lifecycle \
- recipebrowser
+ lifecycle
}
diff --git a/examples/webenginewidgets/CMakeLists.txt b/examples/webenginewidgets/CMakeLists.txt
index c15089420..cc4a4d6c0 100644
--- a/examples/webenginewidgets/CMakeLists.txt
+++ b/examples/webenginewidgets/CMakeLists.txt
@@ -5,14 +5,13 @@ qt_internal_add_example(contentmanipulation)
qt_internal_add_example(cookiebrowser)
qt_internal_add_example(notifications)
qt_internal_add_example(simplebrowser)
-qt_internal_add_example(stylesheetbrowser)
qt_internal_add_example(push-notifications)
qt_internal_add_example(videoplayer)
if(QT_FEATURE_webengine_geolocation)
qt_internal_add_example(maps)
endif()
if(QT_FEATURE_webengine_webchannel)
- qt_internal_add_example(markdowneditor)
+ qt_internal_add_example(recipebrowser)
endif()
if(QT_FEATURE_webengine_printing_and_pdf)
qt_internal_add_example(printme)
diff --git a/examples/webenginewidgets/markdowneditor/CMakeLists.txt b/examples/webenginewidgets/markdowneditor/CMakeLists.txt
deleted file mode 100644
index 808c69521..000000000
--- a/examples/webenginewidgets/markdowneditor/CMakeLists.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
-
-cmake_minimum_required(VERSION 3.16)
-project(markdowneditor LANGUAGES CXX)
-
-set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTOUIC ON)
-
-if(NOT DEFINED INSTALL_EXAMPLESDIR)
- set(INSTALL_EXAMPLESDIR "examples")
-endif()
-
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/webenginewidgets/markdowneditor")
-
-find_package(Qt6 REQUIRED COMPONENTS Core Gui WebChannel WebEngineWidgets)
-
-qt_add_executable(markdowneditor
- document.cpp document.h
- main.cpp
- mainwindow.cpp mainwindow.h mainwindow.ui
- previewpage.cpp previewpage.h
-)
-
-set_target_properties(markdowneditor PROPERTIES
- WIN32_EXECUTABLE TRUE
- MACOSX_BUNDLE TRUE
-)
-
-target_link_libraries(markdowneditor PUBLIC
- Qt::Core
- Qt::Gui
- Qt::WebChannel
- Qt::WebEngineWidgets
-)
-
-# Resources:
-set(markdowneditor_resource_files
- "resources/3rdparty/markdown.css"
- "resources/3rdparty/marked.js"
- "resources/default.md"
- "resources/index.html"
-)
-
-qt_add_resources(markdowneditor "markdowneditor"
- PREFIX
- "/"
- BASE
- "resources"
- FILES
- ${markdowneditor_resource_files}
-)
-
-install(TARGETS markdowneditor
- RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
- BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
- LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
-)
diff --git a/examples/webenginewidgets/markdowneditor/doc/images/markdowneditor-example.png b/examples/webenginewidgets/markdowneditor/doc/images/markdowneditor-example.png
deleted file mode 100644
index 9f456c4db..000000000
--- a/examples/webenginewidgets/markdowneditor/doc/images/markdowneditor-example.png
+++ /dev/null
Binary files differ
diff --git a/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc b/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc
deleted file mode 100644
index f8c67fd63..000000000
--- a/examples/webenginewidgets/markdowneditor/doc/src/markdowneditor.qdoc
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
-
-/*!
- \example webenginewidgets/markdowneditor
- \title WebEngine Markdown Editor Example
- \ingroup webengine-widgetexamples
- \brief Demonstrates how to integrate a web engine in a hybrid desktop
- application.
-
- \image markdowneditor-example.png
-
- \e {Markdown Editor} demonstrates how to use QWebChannel and JavaScript
- libraries to provide a rich text preview tool for a custom markup language.
-
- \l{http://daringfireball.net/projects/markdown/}{Markdown} is a lightweight
- markup language with a plain text formatting syntax.
- Some services, such as \l{http://github.com}{github}, acknowledge the
- format, and render the content as rich text when viewed in a browser.
-
- The Markdown Editor main window is split into an editor and a preview area.
- The editor supports the Markdown syntax and is implemented by using
- QPlainTextEdit. The document is rendered as rich text in the preview area,
- which is implemented by using QWebEngineView. To render the text, the
- Markdown text is converted to HTML format with the help of a JavaScript
- library inside the web engine. The preview is updated from the editor
- through QWebChannel.
-
- \include examples-run.qdocinc
-
- \section1 Exposing Document Text
-
- Because we expose the current Markdown text to be rendered to the web engine
- through QWebChannel, we need to somehow make the current text available
- through the Qt metatype system. This is done by using a dedicated
- \c Document class that exposes the document text as a \c{Q_PROPERTY}:
-
- \quotefromfile webenginewidgets/markdowneditor/document.h
- \skipto class Document
- \printto #endif
-
- The \c Document class wraps a QString to be set on the C++ side with
- the \c setText() method and exposes it at runtime as a \c text property
- with a \c textChanged signal.
-
- We define the \c setText method as follows:
-
- \quotefromfile webenginewidgets/markdowneditor/document.cpp
- \skipto Document::setText
- \printuntil
-
- \section1 Previewing Text
-
- We implement our own \c PreviewPage class that publicly inherits from
- \c QWebEnginePage:
-
- \quotefromfile webenginewidgets/markdowneditor/previewpage.h
- \skipto class PreviewPage
- \printto #endif
-
- We reimplement the virtual \c acceptNavigationRequest method to
- stop the page from navigating away from the current document. Instead,
- we redirect external links to the system browser:
-
- \quotefromfile webenginewidgets/markdowneditor/previewpage.cpp
- \skipto acceptNavigationRequest
- \printuntil
-
- \section1 Creating the Main Window
-
- The \c MainWindow class inherits the QMainWindow class:
-
- \quotefromfile webenginewidgets/markdowneditor/mainwindow.h
- \skipto class MainWindow :
- \printto endif
-
- The class declares private slots that match the actions in the menu,
- as well as the \c isModified() helper method.
-
- The actual layout of the main window is specified in a \c .ui file.
- The widgets and actions are available at runtime in the \c ui member
- variable.
-
- \c m_filePath holds the file path to the currently loaded document.
- \c m_content is an instance of the \c Document class.
-
- The actual setup of the different objects is done in the \c MainWindow
- constructor:
-
- \quotefromfile webenginewidgets/markdowneditor/mainwindow.cpp
- \skipto MainWindow::MainWindow
- \printto PreviewPage
-
- The constructor first calls \c setupUi to construct the widgets and menu
- actions according to the UI file. The text editor font is set to one
- with a fixed character width, and the QWebEngineView widget is told not
- to show a context menu.
-
- \printto connect
-
- Here the constructor makes sure our custom
- \c PreviewPage is used by the QWebEngineView instance in \c{ui->preview}.
-
- \printto ui->preview
-
- Here the \c textChanged signal of the editor is connected to a lambda that
- updates the text in \c m_content. This object is then exposed to the JS side
- by \c QWebChannel under the name \c{content}.
-
- \printto connect
-
- Now we can actually load the \e index.html file from the
- resources. For more information about the file, see
- \l{Creating an Index File}.
-
- \printto defaultTextFile
-
- The menu items are connected to the corresponding member slots. The
- \uicontrol Save item is activated or deactivated depending on whether
- the user has edited the content.
-
- \printuntil }
-
- Finally, we load a default document \e default.md from the resources.
-
- \section1 Creating an Index File
-
- \quotefile webenginewidgets/markdowneditor/resources/index.html
-
- In the \e index.html, we load a custom stylesheet and two JavaScript
- libraries. \l{https://bitbucket.org/kevinburke/markdowncss/src/master/}{markdown.css} is
- a markdown-friendly stylesheet created by Kevin Burke.
- \l{https://github.com/chjj/marked}{marked.js} is a markdown parser and
- compiler designed for speed written by Christopher Jeffrey and
- \e qwebchannel.js is part of the \l{QWebChannel} module.
-
- In the \c <body> element we first define a \c placeholder element, and
- make it available as a JavaScript variable. We then define the \c updateText
- helper method that updates the content of \c placeholder with the HTML
- that the JavaScript method \c marked() returns.
-
- 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/document.cpp b/examples/webenginewidgets/markdowneditor/document.cpp
deleted file mode 100644
index 8ece76509..000000000
--- a/examples/webenginewidgets/markdowneditor/document.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#include "document.h"
-
-void Document::setText(const QString &text)
-{
- if (text == m_text)
- return;
- m_text = text;
- emit textChanged(m_text);
-}
diff --git a/examples/webenginewidgets/markdowneditor/document.h b/examples/webenginewidgets/markdowneditor/document.h
deleted file mode 100644
index f4eabbdaa..000000000
--- a/examples/webenginewidgets/markdowneditor/document.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#ifndef DOCUMENT_H
-#define DOCUMENT_H
-
-#include <QObject>
-#include <QString>
-
-class Document : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QString text MEMBER m_text NOTIFY textChanged FINAL)
-public:
- explicit Document(QObject *parent = nullptr) : QObject(parent) {}
-
- void setText(const QString &text);
-
-signals:
- void textChanged(const QString &text);
-
-private:
- QString m_text;
-};
-
-#endif // DOCUMENT_H
diff --git a/examples/webenginewidgets/markdowneditor/main.cpp b/examples/webenginewidgets/markdowneditor/main.cpp
deleted file mode 100644
index 98e76bfba..000000000
--- a/examples/webenginewidgets/markdowneditor/main.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#include "document.h"
-#include "mainwindow.h"
-
-#include <QApplication>
-#include <QFile>
-
-int main(int argc, char *argv[])
-{
- QCoreApplication::setOrganizationName("QtExamples");
- QApplication a(argc, argv);
-
- MainWindow window;
- window.show();
-
- return a.exec();
-}
diff --git a/examples/webenginewidgets/markdowneditor/mainwindow.cpp b/examples/webenginewidgets/markdowneditor/mainwindow.cpp
deleted file mode 100644
index a4ef50a31..000000000
--- a/examples/webenginewidgets/markdowneditor/mainwindow.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#include "mainwindow.h"
-#include "previewpage.h"
-#include "ui_mainwindow.h"
-
-#include <QFile>
-#include <QFileDialog>
-#include <QFontDatabase>
-#include <QMessageBox>
-#include <QStatusBar>
-#include <QTextStream>
-#include <QWebChannel>
-
-MainWindow::MainWindow(QWidget *parent) :
- QMainWindow(parent),
- ui(new Ui::MainWindow)
-{
- ui->setupUi(this);
- ui->editor->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
- ui->preview->setContextMenuPolicy(Qt::NoContextMenu);
-
- PreviewPage *page = new PreviewPage(this);
- ui->preview->setPage(page);
-
- connect(ui->editor, &QPlainTextEdit::textChanged,
- [this]() { m_content.setText(ui->editor->toPlainText()); });
-
- QWebChannel *channel = new QWebChannel(this);
- channel->registerObject(QStringLiteral("content"), &m_content);
- page->setWebChannel(channel);
-
- ui->preview->setUrl(QUrl("qrc:/index.html"));
-
- connect(ui->actionNew, &QAction::triggered, this, &MainWindow::onFileNew);
- connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::onFileOpen);
- connect(ui->actionSave, &QAction::triggered, this, &MainWindow::onFileSave);
- connect(ui->actionSaveAs, &QAction::triggered, this, &MainWindow::onFileSaveAs);
- connect(ui->actionExit, &QAction::triggered, this, &QWidget::close);
-
- connect(ui->editor->document(), &QTextDocument::modificationChanged,
- ui->actionSave, &QAction::setEnabled);
-
- QFile defaultTextFile(":/default.md");
- defaultTextFile.open(QIODevice::ReadOnly);
- ui->editor->setPlainText(defaultTextFile.readAll());
-}
-
-MainWindow::~MainWindow()
-{
- delete ui;
-}
-
-void MainWindow::openFile(const QString &path)
-{
- QFile f(path);
- if (!f.open(QIODevice::ReadOnly)) {
- QMessageBox::warning(this, windowTitle(),
- tr("Could not open file %1: %2").arg(
- QDir::toNativeSeparators(path), f.errorString()));
- return;
- }
- m_filePath = path;
- ui->editor->setPlainText(f.readAll());
- statusBar()->showMessage(tr("Opened %1").arg(QDir::toNativeSeparators(path)));
-}
-
-bool MainWindow::isModified() const
-{
- return ui->editor->document()->isModified();
-}
-
-void MainWindow::onFileNew()
-{
- if (isModified()) {
- QMessageBox::StandardButton button = QMessageBox::question(this, windowTitle(),
- tr("You have unsaved changes. Do you want to create a new document anyway?"));
- if (button != QMessageBox::Yes)
- return;
- }
-
- m_filePath.clear();
- ui->editor->setPlainText(tr("## New document"));
- ui->editor->document()->setModified(false);
-}
-
-void MainWindow::onFileOpen()
-{
- if (isModified()) {
- QMessageBox::StandardButton button = QMessageBox::question(this, windowTitle(),
- tr("You have unsaved changes. Do you want to open a new document anyway?"));
- if (button != QMessageBox::Yes)
- return;
- }
-
- QFileDialog dialog(this, tr("Open MarkDown File"));
- dialog.setMimeTypeFilters({"text/markdown"});
- dialog.setAcceptMode(QFileDialog::AcceptOpen);
- if (dialog.exec() == QDialog::Accepted)
- openFile(dialog.selectedFiles().constFirst());
-}
-
-void MainWindow::onFileSave()
-{
- if (m_filePath.isEmpty()) {
- onFileSaveAs();
- return;
- }
-
- QFile f(m_filePath);
- if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
- QMessageBox::warning(this, windowTitle(),
- tr("Could not write to file %1: %2").arg(
- QDir::toNativeSeparators(m_filePath), f.errorString()));
- return;
- }
- QTextStream str(&f);
- str << ui->editor->toPlainText();
-
- ui->editor->document()->setModified(false);
-
- statusBar()->showMessage(tr("Wrote %1").arg(QDir::toNativeSeparators(m_filePath)));
-}
-
-void MainWindow::onFileSaveAs()
-{
- QFileDialog dialog(this, tr("Save MarkDown File"));
- dialog.setMimeTypeFilters({"text/markdown"});
- dialog.setAcceptMode(QFileDialog::AcceptSave);
- dialog.setDefaultSuffix("md");
- if (dialog.exec() != QDialog::Accepted)
- return;
-
- m_filePath = dialog.selectedFiles().constFirst();
- onFileSave();
-}
-
-void MainWindow::closeEvent(QCloseEvent *e)
-{
- if (isModified()) {
- QMessageBox::StandardButton button = QMessageBox::question(this, windowTitle(),
- tr("You have unsaved changes. Do you want to exit anyway?"));
- if (button != QMessageBox::Yes)
- e->ignore();
- }
-}
diff --git a/examples/webenginewidgets/markdowneditor/mainwindow.h b/examples/webenginewidgets/markdowneditor/mainwindow.h
deleted file mode 100644
index 271664852..000000000
--- a/examples/webenginewidgets/markdowneditor/mainwindow.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
-
-#include "document.h"
-
-#include <QMainWindow>
-#include <QString>
-
-QT_BEGIN_NAMESPACE
-namespace Ui {
-class MainWindow;
-}
-QT_END_NAMESPACE
-
-class MainWindow : public QMainWindow
-{
- Q_OBJECT
-
-public:
- explicit MainWindow(QWidget *parent = nullptr);
- ~MainWindow();
-
- void openFile(const QString &path);
-
-protected:
- void closeEvent(QCloseEvent *e) override;
-
-private slots:
- void onFileNew();
- void onFileOpen();
- void onFileSave();
- void onFileSaveAs();
-
-private:
- bool isModified() const;
-
- Ui::MainWindow *ui;
- QString m_filePath;
- Document m_content;
-};
-
-#endif // MAINWINDOW_H
diff --git a/examples/webenginewidgets/markdowneditor/mainwindow.ui b/examples/webenginewidgets/markdowneditor/mainwindow.ui
deleted file mode 100644
index 36ab352b7..000000000
--- a/examples/webenginewidgets/markdowneditor/mainwindow.ui
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>800</width>
- <height>600</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>MarkDown Editor</string>
- </property>
- <widget class="QWidget" name="centralwidget">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QSplitter" name="splitter">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <widget class="QPlainTextEdit" name="editor"/>
- <widget class="QWebEngineView" name="preview" native="true"/>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QMenuBar" name="menubar">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>800</width>
- <height>26</height>
- </rect>
- </property>
- <widget class="QMenu" name="menu_File">
- <property name="title">
- <string>&amp;File</string>
- </property>
- <addaction name="actionNew"/>
- <addaction name="actionOpen"/>
- <addaction name="actionSave"/>
- <addaction name="actionSaveAs"/>
- <addaction name="separator"/>
- <addaction name="actionExit"/>
- </widget>
- <addaction name="menu_File"/>
- </widget>
- <widget class="QStatusBar" name="statusbar"/>
- <action name="actionOpen">
- <property name="text">
- <string>&amp;Open...</string>
- </property>
- <property name="toolTip">
- <string>Open document</string>
- </property>
- <property name="shortcut">
- <string>Ctrl+O</string>
- </property>
- </action>
- <action name="actionSave">
- <property name="text">
- <string>&amp;Save</string>
- </property>
- <property name="toolTip">
- <string>Save current document</string>
- </property>
- <property name="shortcut">
- <string>Ctrl+S</string>
- </property>
- </action>
- <action name="actionExit">
- <property name="text">
- <string>E&amp;xit</string>
- </property>
- <property name="toolTip">
- <string>Exit editor</string>
- </property>
- <property name="shortcut">
- <string>Ctrl+Q</string>
- </property>
- </action>
- <action name="actionSaveAs">
- <property name="text">
- <string>Save &amp;As...</string>
- </property>
- <property name="toolTip">
- <string>Save document under different name</string>
- </property>
- </action>
- <action name="actionNew">
- <property name="text">
- <string>&amp;New</string>
- </property>
- <property name="toolTip">
- <string>Create new document</string>
- </property>
- <property name="shortcut">
- <string>Ctrl+N</string>
- </property>
- </action>
- </widget>
- <customwidgets>
- <customwidget>
- <class>QWebEngineView</class>
- <extends>QWidget</extends>
- <header>qwebengineview.h</header>
- <container>1</container>
- </customwidget>
- </customwidgets>
- <resources/>
- <connections/>
-</ui>
diff --git a/examples/webenginewidgets/markdowneditor/markdowneditor.pro b/examples/webenginewidgets/markdowneditor/markdowneditor.pro
deleted file mode 100644
index 099edf4b5..000000000
--- a/examples/webenginewidgets/markdowneditor/markdowneditor.pro
+++ /dev/null
@@ -1,32 +0,0 @@
-TEMPLATE = app
-
-QT += webenginewidgets webchannel
-
-HEADERS += \
- mainwindow.h \
- previewpage.h \
- document.h
-
-SOURCES = \
- main.cpp \
- mainwindow.cpp \
- previewpage.cpp \
- document.cpp
-
-RESOURCES = \
- resources/markdowneditor.qrc
-
-# Disable Qt Quick compiler because the example doesn't use QML, but more importantly so that
-# the source code of the .js files is not removed from the embedded qrc file.
-CONFIG -= qtquickcompiler
-
-FORMS += \
- mainwindow.ui
-
-DISTFILES += \
- resources/3rdparty/MARKDOWN-LICENSE.txt \
- resources/3rdparty/MARKED-LICENSE.txt
-
-# install
-target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/markdowneditor
-INSTALLS += target
diff --git a/examples/webenginewidgets/markdowneditor/previewpage.cpp b/examples/webenginewidgets/markdowneditor/previewpage.cpp
deleted file mode 100644
index 17249fdb0..000000000
--- a/examples/webenginewidgets/markdowneditor/previewpage.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#include "previewpage.h"
-
-#include <QDesktopServices>
-
-bool PreviewPage::acceptNavigationRequest(const QUrl &url,
- QWebEnginePage::NavigationType /*type*/,
- bool /*isMainFrame*/)
-{
- // Only allow qrc:/index.html.
- if (url.scheme() == QString("qrc"))
- return true;
- QDesktopServices::openUrl(url);
- return false;
-}
diff --git a/examples/webenginewidgets/markdowneditor/previewpage.h b/examples/webenginewidgets/markdowneditor/previewpage.h
deleted file mode 100644
index 4a5d98c7c..000000000
--- a/examples/webenginewidgets/markdowneditor/previewpage.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#ifndef PREVIEWPAGE_H
-#define PREVIEWPAGE_H
-
-#include <QWebEnginePage>
-
-class PreviewPage : public QWebEnginePage
-{
- Q_OBJECT
-public:
- using QWebEnginePage::QWebEnginePage;
-
-protected:
- bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) override;
-};
-
-#endif // PREVIEWPAGE_H
diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKDOWN-LICENSE.txt b/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKDOWN-LICENSE.txt
deleted file mode 100644
index 23c52cc43..000000000
--- a/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKDOWN-LICENSE.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-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
deleted file mode 100644
index 8e3ba0e0a..000000000
--- a/examples/webenginewidgets/markdowneditor/resources/3rdparty/MARKED-LICENSE.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2011-2018, 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
deleted file mode 100644
index 24fc2ffe2..000000000
--- a/examples/webenginewidgets/markdowneditor/resources/3rdparty/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/3rdparty/marked.js b/examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.js
deleted file mode 100644
index 33c02d9cf..000000000
--- a/examples/webenginewidgets/markdowneditor/resources/3rdparty/marked.js
+++ /dev/null
@@ -1,1514 +0,0 @@
-/**
- * marked - a markdown parser
- * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
- * https://github.com/markedjs/marked
- */
-
-;(function(root) {
-'use strict';
-
-/**
- * Block-Level Grammar
- */
-
-var block = {
- newline: /^\n+/,
- code: /^( {4}[^\n]+\n*)+/,
- fences: noop,
- hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,
- heading: /^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,
- nptable: noop,
- blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
- list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
- html: '^ {0,3}(?:' // optional indentation
- + '<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
- + '|comment[^\\n]*(\\n+|$)' // (2)
- + '|<\\?[\\s\\S]*?\\?>\\n*' // (3)
- + '|<![A-Z][\\s\\S]*?>\\n*' // (4)
- + '|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>\\n*' // (5)
- + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:\\n{2,}|$)' // (6)
- + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) open tag
- + '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)' // (7) closing tag
- + ')',
- def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,
- table: noop,
- lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
- paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading| {0,3}>|<\/?(?:tag)(?: +|\n|\/?>)|<(?:script|pre|style|!--))[^\n]+)*)/,
- text: /^[^\n]+/
-};
-
-block._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/;
-block._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;
-block.def = edit(block.def)
- .replace('label', block._label)
- .replace('title', block._title)
- .getRegex();
-
-block.bullet = /(?:[*+-]|\d+\.)/;
-block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
-block.item = edit(block.item, 'gm')
- .replace(/bull/g, block.bullet)
- .getRegex();
-
-block.list = edit(block.list)
- .replace(/bull/g, block.bullet)
- .replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))')
- .replace('def', '\\n+(?=' + block.def.source + ')')
- .getRegex();
-
-block._tag = 'address|article|aside|base|basefont|blockquote|body|caption'
- + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption'
- + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe'
- + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'
- + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr'
- + '|track|ul';
-block._comment = /<!--(?!-?>)[\s\S]*?-->/;
-block.html = edit(block.html, 'i')
- .replace('comment', block._comment)
- .replace('tag', block._tag)
- .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/)
- .getRegex();
-
-block.paragraph = edit(block.paragraph)
- .replace('hr', block.hr)
- .replace('heading', block.heading)
- .replace('lheading', block.lheading)
- .replace('tag', block._tag) // pars can be interrupted by type (6) html blocks
- .getRegex();
-
-block.blockquote = edit(block.blockquote)
- .replace('paragraph', block.paragraph)
- .getRegex();
-
-/**
- * Normal Block Grammar
- */
-
-block.normal = merge({}, block);
-
-/**
- * GFM Block Grammar
- */
-
-block.gfm = merge({}, block.normal, {
- fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\n? *\1 *(?:\n+|$)/,
- paragraph: /^/,
- heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
-});
-
-block.gfm.paragraph = edit(block.paragraph)
- .replace('(?!', '(?!'
- + block.gfm.fences.source.replace('\\1', '\\2') + '|'
- + block.list.source.replace('\\1', '\\3') + '|')
- .getRegex();
-
-/**
- * GFM + Tables Block Grammar
- */
-
-block.tables = merge({}, block.gfm, {
- nptable: /^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,
- table: /^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/
-});
-
-/**
- * Pedantic grammar
- */
-
-block.pedantic = merge({}, block.normal, {
- html: edit(
- '^ *(?:comment *(?:\\n|\\s*$)'
- + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
- + '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))')
- .replace('comment', block._comment)
- .replace(/tag/g, '(?!(?:'
- + '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')
- .getRegex(),
- def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/
-});
-
-/**
- * Block Lexer
- */
-
-function Lexer(options) {
- this.tokens = [];
- this.tokens.links = {};
- this.options = options || marked.defaults;
- this.rules = block.normal;
-
- if (this.options.pedantic) {
- this.rules = block.pedantic;
- } else if (this.options.gfm) {
- if (this.options.tables) {
- this.rules = block.tables;
- } else {
- this.rules = block.gfm;
- }
- }
-}
-
-/**
- * Expose Block Rules
- */
-
-Lexer.rules = block;
-
-/**
- * Static Lex Method
- */
-
-Lexer.lex = function(src, options) {
- var lexer = new Lexer(options);
- return lexer.lex(src);
-};
-
-/**
- * Preprocessing
- */
-
-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);
-};
-
-/**
- * Lexing
- */
-
-Lexer.prototype.token = function(src, top) {
- src = src.replace(/^ +$/gm, '');
- var next,
- loose,
- cap,
- bull,
- b,
- item,
- space,
- i,
- tag,
- l,
- isordered,
- istask,
- ischecked;
-
- while (src) {
- // newline
- if (cap = this.rules.newline.exec(src)) {
- src = src.substring(cap[0].length);
- if (cap[0].length > 1) {
- this.tokens.push({
- type: 'space'
- });
- }
- }
-
- // code
- 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;
- }
-
- // fences (gfm)
- 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;
- }
-
- // heading
- 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;
- }
-
- // table no leading pipe (gfm)
- if (top && (cap = this.rules.nptable.exec(src))) {
- item = {
- type: 'table',
- header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
- align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
- cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : []
- };
-
- if (item.header.length === item.align.length) {
- src = src.substring(cap[0].length);
-
- for (i = 0; i < item.align.length; i++) {
- if (/^ *-+: *$/.test(item.align[i])) {
- item.align[i] = 'right';
- } else if (/^ *:-+: *$/.test(item.align[i])) {
- item.align[i] = 'center';
- } else if (/^ *:-+ *$/.test(item.align[i])) {
- item.align[i] = 'left';
- } else {
- item.align[i] = null;
- }
- }
-
- for (i = 0; i < item.cells.length; i++) {
- item.cells[i] = splitCells(item.cells[i], item.header.length);
- }
-
- this.tokens.push(item);
-
- continue;
- }
- }
-
- // hr
- if (cap = this.rules.hr.exec(src)) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'hr'
- });
- continue;
- }
-
- // blockquote
- if (cap = this.rules.blockquote.exec(src)) {
- src = src.substring(cap[0].length);
-
- this.tokens.push({
- type: 'blockquote_start'
- });
-
- cap = cap[0].replace(/^ *> ?/gm, '');
-
- // Pass `top` to keep the current
- // "toplevel" state. This is exactly
- // how markdown.pl works.
- this.token(cap, top);
-
- this.tokens.push({
- type: 'blockquote_end'
- });
-
- continue;
- }
-
- // list
- if (cap = this.rules.list.exec(src)) {
- src = src.substring(cap[0].length);
- bull = cap[2];
- isordered = bull.length > 1;
-
- this.tokens.push({
- type: 'list_start',
- ordered: isordered,
- start: isordered ? +bull : ''
- });
-
- // Get each top-level item.
- cap = cap[0].match(this.rules.item);
-
- next = false;
- l = cap.length;
- i = 0;
-
- for (; i < l; i++) {
- item = cap[i];
-
- // Remove the list item's bullet
- // so it is seen as the next token.
- space = item.length;
- item = item.replace(/^ *([*+-]|\d+\.) +/, '');
-
- // Outdent whatever the
- // list item contains. Hacky.
- if (~item.indexOf('\n ')) {
- space -= item.length;
- item = !this.options.pedantic
- ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
- : item.replace(/^ {1,4}/gm, '');
- }
-
- // Determine whether the next list item belongs here.
- // Backpedal if it does not belong in this list.
- if (this.options.smartLists && i !== l - 1) {
- b = block.bullet.exec(cap[i + 1])[0];
- if (bull !== b && !(bull.length > 1 && b.length > 1)) {
- src = cap.slice(i + 1).join('\n') + src;
- i = l - 1;
- }
- }
-
- // Determine whether item is loose or not.
- // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
- // for discount behavior.
- loose = next || /\n\n(?!\s*$)/.test(item);
- if (i !== l - 1) {
- next = item.charAt(item.length - 1) === '\n';
- if (!loose) loose = next;
- }
-
- // Check for task list items
- istask = /^\[[ xX]\] /.test(item);
- ischecked = undefined;
- if (istask) {
- ischecked = item[1] !== ' ';
- item = item.replace(/^\[[ xX]\] +/, '');
- }
-
- this.tokens.push({
- type: loose
- ? 'loose_item_start'
- : 'list_item_start',
- task: istask,
- checked: ischecked
- });
-
- // Recurse.
- this.token(item, false);
-
- this.tokens.push({
- type: 'list_item_end'
- });
- }
-
- this.tokens.push({
- type: 'list_end'
- });
-
- continue;
- }
-
- // html
- 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;
- }
-
- // def
- if (top && (cap = this.rules.def.exec(src))) {
- src = src.substring(cap[0].length);
- if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1);
- tag = cap[1].toLowerCase().replace(/\s+/g, ' ');
- if (!this.tokens.links[tag]) {
- this.tokens.links[tag] = {
- href: cap[2],
- title: cap[3]
- };
- }
- continue;
- }
-
- // table (gfm)
- if (top && (cap = this.rules.table.exec(src))) {
- item = {
- type: 'table',
- header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
- align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
- cells: cap[3] ? cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') : []
- };
-
- if (item.header.length === item.align.length) {
- src = src.substring(cap[0].length);
-
- for (i = 0; i < item.align.length; i++) {
- if (/^ *-+: *$/.test(item.align[i])) {
- item.align[i] = 'right';
- } else if (/^ *:-+: *$/.test(item.align[i])) {
- item.align[i] = 'center';
- } else if (/^ *:-+ *$/.test(item.align[i])) {
- item.align[i] = 'left';
- } else {
- item.align[i] = null;
- }
- }
-
- for (i = 0; i < item.cells.length; i++) {
- item.cells[i] = splitCells(
- item.cells[i].replace(/^ *\| *| *\| *$/g, ''),
- item.header.length);
- }
-
- this.tokens.push(item);
-
- continue;
- }
- }
-
- // lheading
- if (cap = this.rules.lheading.exec(src)) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'heading',
- depth: cap[2] === '=' ? 1 : 2,
- text: cap[1]
- });
- continue;
- }
-
- // top-level paragraph
- if (top && (cap = this.rules.paragraph.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'paragraph',
- text: cap[1].charAt(cap[1].length - 1) === '\n'
- ? cap[1].slice(0, -1)
- : cap[1]
- });
- continue;
- }
-
- // text
- if (cap = this.rules.text.exec(src)) {
- // Top-level should never reach here.
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'text',
- text: cap[0]
- });
- continue;
- }
-
- if (src) {
- throw new Error('Infinite loop on byte: ' + src.charCodeAt(0));
- }
- }
-
- return this.tokens;
-};
-
-/**
- * Inline-Level Grammar
- */
-
-var inline = {
- escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
- autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
- url: noop,
- tag: '^comment'
- + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
- + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
- + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
- + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
- + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>', // CDATA section
- link: /^!?\[(label)\]\(href(?:\s+(title))?\s*\)/,
- reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
- nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
- strong: /^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)|^__([^\s])__(?!_)|^\*\*([^\s])\*\*(?!\*)/,
- em: /^_([^\s][\s\S]*?[^\s_])_(?!_)|^_([^\s_][\s\S]*?[^\s])_(?!_)|^\*([^\s][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*][\s\S]*?[^\s])\*(?!\*)|^_([^\s_])_(?!_)|^\*([^\s*])\*(?!\*)/,
- code: /^(`+)\s*([\s\S]*?[^`]?)\s*\1(?!`)/,
- br: /^ {2,}\n(?!\s*$)/,
- del: noop,
- text: /^[\s\S]+?(?=[\\<!\[`*]|\b_| {2,}\n|$)/
-};
-
-inline._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
-
-inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
-inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;
-inline.autolink = edit(inline.autolink)
- .replace('scheme', inline._scheme)
- .replace('email', inline._email)
- .getRegex();
-
-inline._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;
-
-inline.tag = edit(inline.tag)
- .replace('comment', block._comment)
- .replace('attribute', inline._attribute)
- .getRegex();
-
-inline._label = /(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|[^\[\]\\])*?/;
-inline._href = /\s*(<(?:\\[<>]?|[^\s<>\\])*>|(?:\\[()]?|\([^\s\x00-\x1f()\\]*\)|[^\s\x00-\x1f()\\])*?)/;
-inline._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
-
-inline.link = edit(inline.link)
- .replace('label', inline._label)
- .replace('href', inline._href)
- .replace('title', inline._title)
- .getRegex();
-
-inline.reflink = edit(inline.reflink)
- .replace('label', inline._label)
- .getRegex();
-
-/**
- * Normal Inline Grammar
- */
-
-inline.normal = merge({}, inline);
-
-/**
- * Pedantic Inline Grammar
- */
-
-inline.pedantic = merge({}, inline.normal, {
- strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
- em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,
- link: edit(/^!?\[(label)\]\((.*?)\)/)
- .replace('label', inline._label)
- .getRegex(),
- reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/)
- .replace('label', inline._label)
- .getRegex()
-});
-
-/**
- * GFM Inline Grammar
- */
-
-inline.gfm = merge({}, inline.normal, {
- escape: edit(inline.escape).replace('])', '~|])').getRegex(),
- url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/)
- .replace('email', inline._email)
- .getRegex(),
- _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
- del: /^~~(?=\S)([\s\S]*?\S)~~/,
- text: edit(inline.text)
- .replace(']|', '~]|')
- .replace('|', '|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&\'*+/=?^_`{\\|}~-]+@|')
- .getRegex()
-});
-
-/**
- * GFM + Line Breaks Inline Grammar
- */
-
-inline.breaks = merge({}, inline.gfm, {
- br: edit(inline.br).replace('{2,}', '*').getRegex(),
- text: edit(inline.gfm.text).replace('{2,}', '*').getRegex()
-});
-
-/**
- * Inline Lexer & Compiler
- */
-
-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.pedantic) {
- this.rules = inline.pedantic;
- } else if (this.options.gfm) {
- if (this.options.breaks) {
- this.rules = inline.breaks;
- } else {
- this.rules = inline.gfm;
- }
- }
-}
-
-/**
- * Expose Inline Rules
- */
-
-InlineLexer.rules = inline;
-
-/**
- * Static Lexing/Compiling Method
- */
-
-InlineLexer.output = function(src, links, options) {
- var inline = new InlineLexer(links, options);
- return inline.output(src);
-};
-
-/**
- * Lexing/Compiling
- */
-
-InlineLexer.prototype.output = function(src) {
- var out = '',
- link,
- text,
- href,
- title,
- cap;
-
- while (src) {
- // escape
- if (cap = this.rules.escape.exec(src)) {
- src = src.substring(cap[0].length);
- out += cap[1];
- continue;
- }
-
- // autolink
- if (cap = this.rules.autolink.exec(src)) {
- src = src.substring(cap[0].length);
- if (cap[2] === '@') {
- text = escape(this.mangle(cap[1]));
- href = 'mailto:' + text;
- } else {
- text = escape(cap[1]);
- href = text;
- }
- out += this.renderer.link(href, null, text);
- continue;
- }
-
- // url (gfm)
- if (!this.inLink && (cap = this.rules.url.exec(src))) {
- cap[0] = this.rules._backpedal.exec(cap[0])[0];
- src = src.substring(cap[0].length);
- if (cap[2] === '@') {
- text = escape(cap[0]);
- href = 'mailto:' + text;
- } else {
- text = escape(cap[0]);
- if (cap[1] === 'www.') {
- href = 'http://' + text;
- } else {
- href = text;
- }
- }
- out += this.renderer.link(href, null, text);
- continue;
- }
-
- // tag
- if (cap = this.rules.tag.exec(src)) {
- if (!this.inLink && /^<a /i.test(cap[0])) {
- this.inLink = true;
- } else if (this.inLink && /^<\/a>/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;
- }
-
- // link
- if (cap = this.rules.link.exec(src)) {
- src = src.substring(cap[0].length);
- this.inLink = true;
- href = cap[2];
- if (this.options.pedantic) {
- link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
-
- if (link) {
- href = link[1];
- title = link[3];
- } else {
- title = '';
- }
- } else {
- title = cap[3] ? cap[3].slice(1, -1) : '';
- }
- href = href.trim().replace(/^<([\s\S]*)>$/, '$1');
- out += this.outputLink(cap, {
- href: InlineLexer.escapes(href),
- title: InlineLexer.escapes(title)
- });
- this.inLink = false;
- continue;
- }
-
- // reflink, nolink
- 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;
- }
-
- // strong
- if (cap = this.rules.strong.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.strong(this.output(cap[4] || cap[3] || cap[2] || cap[1]));
- continue;
- }
-
- // em
- if (cap = this.rules.em.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.em(this.output(cap[6] || cap[5] || cap[4] || cap[3] || cap[2] || cap[1]));
- continue;
- }
-
- // code
- if (cap = this.rules.code.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.codespan(escape(cap[2].trim(), true));
- continue;
- }
-
- // br
- if (cap = this.rules.br.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.br();
- continue;
- }
-
- // del (gfm)
- if (cap = this.rules.del.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.del(this.output(cap[1]));
- continue;
- }
-
- // text
- 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.escapes = function(text) {
- return text ? text.replace(InlineLexer.rules._escapes, '$1') : text;
-}
-
-/**
- * Compile Link
- */
-
-InlineLexer.prototype.outputLink = function(cap, link) {
- var href = 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]));
-};
-
-/**
- * Smartypants Transformations
- */
-
-InlineLexer.prototype.smartypants = function(text) {
- if (!this.options.smartypants) return text;
- return text
- // em-dashes
- .replace(/---/g, '\u2014')
- // en-dashes
- .replace(/--/g, '\u2013')
- // opening singles
- .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
- // closing singles & apostrophes
- .replace(/'/g, '\u2019')
- // opening doubles
- .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
- // closing doubles
- .replace(/"/g, '\u201d')
- // ellipses
- .replace(/\.{3}/g, '\u2026');
-};
-
-/**
- * Mangle Links
- */
-
-InlineLexer.prototype.mangle = function(text) {
- if (!this.options.mangle) return text;
- var out = '',
- l = text.length,
- i = 0,
- ch;
-
- for (; i < l; i++) {
- ch = text.charCodeAt(i);
- if (Math.random() > 0.5) {
- ch = 'x' + ch.toString(16);
- }
- out += '&#' + ch + ';';
- }
-
- return out;
-};
-
-/**
- * Renderer
- */
-
-function Renderer(options) {
- this.options = options || marked.defaults;
-}
-
-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 '<pre><code>'
- + (escaped ? code : escape(code, true))
- + '</code></pre>';
- }
-
- return '<pre><code class="'
- + this.options.langPrefix
- + escape(lang, true)
- + '">'
- + (escaped ? code : escape(code, true))
- + '</code></pre>\n';
-};
-
-Renderer.prototype.blockquote = function(quote) {
- return '<blockquote>\n' + quote + '</blockquote>\n';
-};
-
-Renderer.prototype.html = function(html) {
- return html;
-};
-
-Renderer.prototype.heading = function(text, level, raw) {
- if (this.options.headerIds) {
- return '<h'
- + level
- + ' id="'
- + this.options.headerPrefix
- + raw.toLowerCase().replace(/[^\w]+/g, '-')
- + '">'
- + text
- + '</h'
- + level
- + '>\n';
- }
- // ignore IDs
- return '<h' + level + '>' + text + '</h' + level + '>\n';
-};
-
-Renderer.prototype.hr = function() {
- return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
-};
-
-Renderer.prototype.list = function(body, ordered, start) {
- var type = ordered ? 'ol' : 'ul',
- startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
- return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
-};
-
-Renderer.prototype.listitem = function(text) {
- return '<li>' + text + '</li>\n';
-};
-
-Renderer.prototype.checkbox = function(checked) {
- return '<input '
- + (checked ? 'checked="" ' : '')
- + 'disabled="" type="checkbox"'
- + (this.options.xhtml ? ' /' : '')
- + '> ';
-}
-
-Renderer.prototype.paragraph = function(text) {
- return '<p>' + text + '</p>\n';
-};
-
-Renderer.prototype.table = function(header, body) {
- if (body) body = '<tbody>' + body + '</tbody>';
-
- return '<table>\n'
- + '<thead>\n'
- + header
- + '</thead>\n'
- + body
- + '</table>\n';
-};
-
-Renderer.prototype.tablerow = function(content) {
- return '<tr>\n' + content + '</tr>\n';
-};
-
-Renderer.prototype.tablecell = function(content, flags) {
- var type = flags.header ? 'th' : 'td';
- var tag = flags.align
- ? '<' + type + ' align="' + flags.align + '">'
- : '<' + type + '>';
- return tag + content + '</' + type + '>\n';
-};
-
-// span level renderer
-Renderer.prototype.strong = function(text) {
- return '<strong>' + text + '</strong>';
-};
-
-Renderer.prototype.em = function(text) {
- return '<em>' + text + '</em>';
-};
-
-Renderer.prototype.codespan = function(text) {
- return '<code>' + text + '</code>';
-};
-
-Renderer.prototype.br = function() {
- return this.options.xhtml ? '<br/>' : '<br>';
-};
-
-Renderer.prototype.del = function(text) {
- return '<del>' + text + '</del>';
-};
-
-Renderer.prototype.link = function(href, title, text) {
- if (this.options.sanitize) {
- try {
- var prot = decodeURIComponent(unescape(href))
- .replace(/[^\w:]/g, '')
- .toLowerCase();
- } catch (e) {
- return text;
- }
- if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
- return text;
- }
- }
- if (this.options.baseUrl && !originIndependentUrl.test(href)) {
- href = resolveUrl(this.options.baseUrl, href);
- }
- try {
- href = encodeURI(href).replace(/%25/g, '%');
- } catch (e) {
- return text;
- }
- var out = '<a href="' + escape(href) + '"';
- if (title) {
- out += ' title="' + title + '"';
- }
- out += '>' + text + '</a>';
- return out;
-};
-
-Renderer.prototype.image = function(href, title, text) {
- if (this.options.baseUrl && !originIndependentUrl.test(href)) {
- href = resolveUrl(this.options.baseUrl, href);
- }
- var out = '<img src="' + href + '" alt="' + text + '"';
- if (title) {
- out += ' title="' + title + '"';
- }
- out += this.options.xhtml ? '/>' : '>';
- return out;
-};
-
-Renderer.prototype.text = function(text) {
- return text;
-};
-
-/**
- * TextRenderer
- * returns only the textual part of the token
- */
-
-function TextRenderer() {}
-
-// no need for block level renderers
-
-TextRenderer.prototype.strong =
-TextRenderer.prototype.em =
-TextRenderer.prototype.codespan =
-TextRenderer.prototype.del =
-TextRenderer.prototype.text = function (text) {
- return text;
-}
-
-TextRenderer.prototype.link =
-TextRenderer.prototype.image = function(href, title, text) {
- return '' + text;
-}
-
-TextRenderer.prototype.br = function() {
- return '';
-}
-
-/**
- * Parsing & Compiling
- */
-
-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;
-}
-
-/**
- * Static Parse Method
- */
-
-Parser.parse = function(src, options) {
- var parser = new Parser(options);
- return parser.parse(src);
-};
-
-/**
- * Parse Loop
- */
-
-Parser.prototype.parse = function(src) {
- this.inline = new InlineLexer(src.links, this.options);
- // use an InlineLexer with a TextRenderer to extract pure text
- this.inlineText = new InlineLexer(
- src.links,
- merge({}, this.options, {renderer: new TextRenderer()})
- );
- this.tokens = src.reverse();
-
- var out = '';
- while (this.next()) {
- out += this.tok();
- }
-
- return out;
-};
-
-/**
- * Next Token
- */
-
-Parser.prototype.next = function() {
- return this.token = this.tokens.pop();
-};
-
-/**
- * Preview Next Token
- */
-
-Parser.prototype.peek = function() {
- return this.tokens[this.tokens.length - 1] || 0;
-};
-
-/**
- * Parse Text Tokens
- */
-
-Parser.prototype.parseText = function() {
- var body = this.token.text;
-
- while (this.peek().type === 'text') {
- body += '\n' + this.next().text;
- }
-
- return this.inline.output(body);
-};
-
-/**
- * Parse Current Token
- */
-
-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,
- unescape(this.inlineText.output(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,
- j;
-
- // header
- cell = '';
- for (i = 0; i < this.token.header.length; i++) {
- cell += this.renderer.tablecell(
- this.inline.output(this.token.header[i]),
- { header: true, align: this.token.align[i] }
- );
- }
- header += this.renderer.tablerow(cell);
-
- for (i = 0; i < this.token.cells.length; i++) {
- row = this.token.cells[i];
-
- cell = '';
- for (j = 0; j < row.length; j++) {
- cell += this.renderer.tablecell(
- this.inline.output(row[j]),
- { header: false, align: this.token.align[j] }
- );
- }
-
- body += this.renderer.tablerow(cell);
- }
- return this.renderer.table(header, body);
- }
- case 'blockquote_start': {
- body = '';
-
- while (this.next().type !== 'blockquote_end') {
- body += this.tok();
- }
-
- return this.renderer.blockquote(body);
- }
- case 'list_start': {
- body = '';
- var ordered = this.token.ordered,
- start = this.token.start;
-
- while (this.next().type !== 'list_end') {
- body += this.tok();
- }
-
- return this.renderer.list(body, ordered, start);
- }
- case 'list_item_start': {
- body = '';
-
- if (this.token.task) {
- body += this.renderer.checkbox(this.token.checked);
- }
-
- while (this.next().type !== 'list_item_end') {
- body += this.token.type === 'text'
- ? this.parseText()
- : this.tok();
- }
-
- return this.renderer.listitem(body);
- }
- case 'loose_item_start': {
- body = '';
-
- while (this.next().type !== 'list_item_end') {
- body += this.tok();
- }
-
- return this.renderer.listitem(body);
- }
- case 'html': {
- // TODO parse inline content if parameter markdown=1
- return this.renderer.html(this.token.text);
- }
- case 'paragraph': {
- return this.renderer.paragraph(this.inline.output(this.token.text));
- }
- case 'text': {
- return this.renderer.paragraph(this.parseText());
- }
- }
-};
-
-/**
- * Helpers
- */
-
-function escape(html, encode) {
- return html
- .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
- .replace(/</g, '&lt;')
- .replace(/>/g, '&gt;')
- .replace(/"/g, '&quot;')
- .replace(/'/g, '&#39;');
-}
-
-function unescape(html) {
- // explicitly match decimal, hex, and named HTML entities
- return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, 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 edit(regex, opt) {
- regex = regex.source || regex;
- opt = opt || '';
- return {
- replace: function(name, val) {
- val = val.source || val;
- val = val.replace(/(^|[^\[])\^/g, '$1');
- regex = regex.replace(name, val);
- return this;
- },
- getRegex: function() {
- return new RegExp(regex, opt);
- }
- };
-}
-
-function resolveUrl(base, href) {
- if (!baseUrls[' ' + base]) {
- // we can ignore everything in base after the last slash of its path component,
- // but we might need to add _that_
- // https://tools.ietf.org/html/rfc3986#section-3
- if (/^[^:]+:\/*[^/]*$/.test(base)) {
- baseUrls[' ' + base] = base + '/';
- } else {
- baseUrls[' ' + base] = base.replace(/[^/]*$/, '');
- }
- }
- base = baseUrls[' ' + base];
-
- if (href.slice(0, 2) === '//') {
- return base.replace(/:[\s\S]*/, ':') + href;
- } else if (href.charAt(0) === '/') {
- return base.replace(/(:\/*[^/]*)[\s\S]*/, '$1') + href;
- } else {
- return base + href;
- }
-}
-var baseUrls = {};
-var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
-
-function noop() {}
-noop.exec = noop;
-
-function merge(obj) {
- var i = 1,
- target,
- key;
-
- for (; i < arguments.length; i++) {
- target = arguments[i];
- for (key in target) {
- if (Object.prototype.hasOwnProperty.call(target, key)) {
- obj[key] = target[key];
- }
- }
- }
-
- return obj;
-}
-
-function splitCells(tableRow, count) {
- var cells = tableRow.replace(/([^\\])\|/g, '$1 |').split(/ +\| */),
- i = 0;
-
- if (cells.length > count) {
- cells.splice(count);
- } else {
- while (cells.length < count) cells.push('');
- }
-
- for (; i < cells.length; i++) {
- cells[i] = cells[i].replace(/\\\|/g, '|');
- }
- return cells;
-}
-
-/**
- * Marked
- */
-
-function marked(src, opt, callback) {
- // throw error in case of non string input
- if (typeof src === 'undefined' || src === null) {
- throw new Error('marked(): input parameter is undefined or null');
- }
- if (typeof src !== 'string') {
- throw new Error('marked(): input parameter is of type '
- + Object.prototype.toString.call(src) + ', string expected');
- }
-
- if (callback || typeof opt === 'function') {
- if (!callback) {
- callback = opt;
- opt = null;
- }
-
- opt = merge({}, marked.defaults, opt || {});
-
- var highlight = opt.highlight,
- tokens,
- pending,
- i = 0;
-
- try {
- tokens = Lexer.lex(src, opt)
- } catch (e) {
- return callback(e);
- }
-
- pending = tokens.length;
-
- var done = function(err) {
- if (err) {
- opt.highlight = highlight;
- return callback(err);
- }
-
- var out;
-
- try {
- out = Parser.parse(tokens, opt);
- } catch (e) {
- err = e;
- }
-
- opt.highlight = highlight;
-
- return err
- ? callback(err)
- : callback(null, out);
- };
-
- if (!highlight || highlight.length < 3) {
- return done();
- }
-
- delete opt.highlight;
-
- if (!pending) return done();
-
- for (; i < tokens.length; i++) {
- (function(token) {
- if (token.type !== 'code') {
- return --pending || done();
- }
- return highlight(token.text, token.lang, function(err, code) {
- if (err) return done(err);
- if (code == null || code === token.text) {
- return --pending || done();
- }
- token.text = code;
- token.escaped = true;
- --pending || done();
- });
- })(tokens[i]);
- }
-
- return;
- }
- try {
- if (opt) opt = merge({}, marked.defaults, opt);
- return Parser.parse(Lexer.lex(src, opt), opt);
- } catch (e) {
- e.message += '\nPlease report this to https://github.com/markedjs/marked.';
- if ((opt || marked.defaults).silent) {
- return '<p>An error occurred:</p><pre>'
- + escape(e.message + '', true)
- + '</pre>';
- }
- throw e;
- }
-}
-
-/**
- * Options
- */
-
-marked.options =
-marked.setOptions = function(opt) {
- merge(marked.defaults, opt);
- return marked;
-};
-
-marked.getDefaults = function () {
- return {
- baseUrl: null,
- breaks: false,
- gfm: true,
- headerIds: true,
- headerPrefix: '',
- highlight: null,
- langPrefix: 'language-',
- mangle: true,
- pedantic: false,
- renderer: new Renderer(),
- sanitize: false,
- sanitizer: null,
- silent: false,
- smartLists: false,
- smartypants: false,
- tables: true,
- xhtml: false
- };
-}
-
-marked.defaults = marked.getDefaults();
-
-/**
- * Expose
- */
-
-marked.Parser = Parser;
-marked.parser = Parser.parse;
-
-marked.Renderer = Renderer;
-marked.TextRenderer = TextRenderer;
-
-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 {
- root.marked = marked;
-}
-})(this || (typeof window !== 'undefined' ? window : global));
diff --git a/examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json b/examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json
deleted file mode 100644
index d51ac744b..000000000
--- a/examples/webenginewidgets/markdowneditor/resources/3rdparty/qt_attribution.json
+++ /dev/null
@@ -1,34 +0,0 @@
-[
- {
- "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.js",
- "Description": "A full-featured markdown parser and compiler, written in JavaScript. Built for speed.",
- "Homepage": "https://github.com/chjj/marked",
- "Version": "0.4.0",
- "DownloadLocation": "https://github.com/markedjs/marked/blob/0.4.0/lib/marked.js",
- "Copyright": "Copyright (c) 2011-2018, 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.",
- "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
deleted file mode 100644
index af835fa4d..000000000
--- a/examples/webenginewidgets/markdowneditor/resources/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](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
deleted file mode 100644
index c8e30b49b..000000000
--- a/examples/webenginewidgets/markdowneditor/resources/index.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!doctype html>
-<html lang="en">
-<meta charset="utf-8">
-<head>
- <link rel="stylesheet" type="text/css" href="3rdparty/markdown.css">
- <script src="3rdparty/marked.js"></script>
- <script src="qrc:/qtwebchannel/qwebchannel.js"></script>
-</head>
-<body>
- <div id="placeholder"></div>
- <script>
- 'use strict';
-
- var placeholder = document.getElementById('placeholder');
-
- var updateText = function(text) {
- placeholder.innerHTML = marked.parse(text);
- }
-
- new QWebChannel(qt.webChannelTransport,
- function(channel) {
- var content = channel.objects.content;
- updateText(content.text);
- content.textChanged.connect(updateText);
- }
- );
- </script>
-</body>
-</html>
-
-
-
diff --git a/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc b/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc
deleted file mode 100644
index bc738f1cf..000000000
--- a/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc
+++ /dev/null
@@ -1,8 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>default.md</file>
- <file>index.html</file>
- <file>3rdparty/markdown.css</file>
- <file>3rdparty/marked.js</file>
- </qresource>
-</RCC>
diff --git a/examples/webenginewidgets/recipebrowser/CMakeLists.txt b/examples/webenginewidgets/recipebrowser/CMakeLists.txt
new file mode 100644
index 000000000..d10409c09
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/CMakeLists.txt
@@ -0,0 +1,71 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(recipebrowser LANGUAGES CXX)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTOUIC ON)
+
+if(NOT DEFINED INSTALL_EXAMPLESDIR)
+ set(INSTALL_EXAMPLESDIR "examples")
+endif()
+
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/webenginewidgets/recipebrowser")
+
+find_package(Qt6 REQUIRED COMPONENTS Core Gui WebEngineWidgets)
+
+qt_add_executable(recipebrowser
+ main.cpp
+ mainwindow.cpp mainwindow.h mainwindow.ui
+ stylesheetdialog.cpp stylesheetdialog.h stylesheetdialog.ui
+ document.cpp document.h
+)
+
+set_target_properties(recipebrowser PROPERTIES
+ WIN32_EXECUTABLE TRUE
+ MACOSX_BUNDLE TRUE
+)
+
+target_link_libraries(recipebrowser PUBLIC
+ Qt::Core
+ Qt::Gui
+ Qt::WebEngineWidgets
+)
+
+# Resources:
+set(recipebrowser_resource_files
+ "assets/3rdparty/markdown.css"
+ "assets/3rdparty/marked.js"
+ "assets/custom.css"
+ "assets/custom.js"
+ "assets/pages/burger.html"
+ "assets/pages/cupcakes.html"
+ "assets/pages/images/burger.jpg"
+ "assets/pages/images/cupcakes.jpg"
+ "assets/pages/images/pasta.jpg"
+ "assets/pages/images/pizza.jpg"
+ "assets/pages/images/skewers.jpg"
+ "assets/pages/images/soup.jpg"
+ "assets/pages/images/steak.jpg"
+ "assets/pages/pasta.html"
+ "assets/pages/pizza.html"
+ "assets/pages/skewers.html"
+ "assets/pages/soup.html"
+ "assets/pages/steak.html"
+)
+
+qt_add_resources(recipebrowser "recipebrowser"
+ PREFIX
+ "/"
+ BASE
+ "assets"
+ FILES
+ ${recipebrowser_resource_files}
+)
+
+install(TARGETS recipebrowser
+ RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
+ LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+)
diff --git a/examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/MARKDOWN-LICENSE.txt b/examples/webenginewidgets/recipebrowser/assets/3rdparty/MARKDOWN-LICENSE.txt
index 23c52cc43..23c52cc43 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/MARKDOWN-LICENSE.txt
+++ b/examples/webenginewidgets/recipebrowser/assets/3rdparty/MARKDOWN-LICENSE.txt
diff --git a/examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/MARKED-LICENSE.txt b/examples/webenginewidgets/recipebrowser/assets/3rdparty/MARKED-LICENSE.txt
index 8e3ba0e0a..8e3ba0e0a 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/MARKED-LICENSE.txt
+++ b/examples/webenginewidgets/recipebrowser/assets/3rdparty/MARKED-LICENSE.txt
diff --git a/examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/markdown.css b/examples/webenginewidgets/recipebrowser/assets/3rdparty/markdown.css
index 24fc2ffe2..24fc2ffe2 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/markdown.css
+++ b/examples/webenginewidgets/recipebrowser/assets/3rdparty/markdown.css
diff --git a/examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/marked.js b/examples/webenginewidgets/recipebrowser/assets/3rdparty/marked.js
index 33c02d9cf..33c02d9cf 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/assets/3rdparty/marked.js
+++ b/examples/webenginewidgets/recipebrowser/assets/3rdparty/marked.js
diff --git a/examples/webenginewidgets/recipebrowser/assets/3rdparty/qt_attribution.json b/examples/webenginewidgets/recipebrowser/assets/3rdparty/qt_attribution.json
new file mode 100644
index 000000000..f8b0fd023
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/assets/3rdparty/qt_attribution.json
@@ -0,0 +1,34 @@
+[
+ {
+ "Id" : "recipebrowser-marked",
+ "Name" : "Marked (WebEngine Recipe Browser example)",
+ "QDocModule" : "qtwebengine",
+ "QtUsage" : "Marked is used in the WebEngine Recipe Browser example",
+ "QtParts" : ["examples"],
+ "Files" : "marked.js",
+ "Description" :
+ "A full-featured markdown parser and compiler, written in JavaScript. Built for speed.",
+ "Homepage" : "https://github.com/chjj/marked",
+ "Version" : "0.4.0",
+ "DownloadLocation" : "https://github.com/markedjs/marked/blob/0.4.0/lib/marked.js",
+ "Copyright" : "Copyright (c) 2011-2018, Christopher Jeffrey",
+ "License" : "MIT License",
+ "LicenseId" : "MIT",
+ "LicenseFile" : "MARKED-LICENSE.txt"
+ },
+ {
+ "Id" : "recipebrowser-markdowncss",
+ "Name" : "Markdown.css (WebEngine Recipe Browser example)",
+ "QDocModule" : "qtwebengine",
+ "QtUsage" : "markdown.css is used in the WebEngine Recipe Browser example",
+ "QtParts" : ["examples"],
+ "Files" : "markdown.css",
+ "Description" : "Markdown.css is better default styling for your Markdown files.",
+ "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/webenginequick/recipebrowser/resources/pages/assets/custom.css b/examples/webenginewidgets/recipebrowser/assets/custom.css
index 8d2f6cb0b..cc1106af3 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/assets/custom.css
+++ b/examples/webenginewidgets/recipebrowser/assets/custom.css
@@ -1,4 +1,4 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
body {
diff --git a/examples/webenginewidgets/recipebrowser/assets/custom.js b/examples/webenginewidgets/recipebrowser/assets/custom.js
new file mode 100644
index 000000000..34470164e
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/assets/custom.js
@@ -0,0 +1,13 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+marked.setOptions({
+ renderer : new marked.Renderer(),
+ gfm : true,
+ tables : true,
+ breaks : false,
+ pedantic : false,
+ sanitize : false,
+ smartLists : true,
+ smartypants : false
+});
diff --git a/examples/webenginequick/recipebrowser/resources/pages/burger.html b/examples/webenginewidgets/recipebrowser/assets/pages/burger.html
index 6651cc0f0..99497959f 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/burger.html
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/burger.html
@@ -3,8 +3,11 @@
<head>
<meta charset="utf-8">
<title>Insanity Burger</title>
- <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
- <link rel="stylesheet" type="text/css" href="assets/custom.css">
+ <link rel="stylesheet" type="text/css" href="../3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="../custom.css">
+ <script src="../3rdparty/marked.js"></script>
+ <script src="../custom.js"></script>
+ <script src="qrc:/qtwebchannel/qwebchannel.js"></script>
</head>
<body>
<div id="placeholder"></div>
@@ -68,8 +71,24 @@ give it a minute to go gorgeous and sloppy.
</div><!--End of content-->
- <script src="assets/3rdparty/marked.js"></script>
- <script src="assets/custom.js"></script>
+ <script>
+ 'use strict';
+
+ var jsContent = document.getElementById('content');
+ var placeholder = document.getElementById('placeholder');
+
+ var updateText = function(text) {
+ placeholder.innerHTML = marked.parse(text);
+ }
+
+ new QWebChannel(qt.webChannelTransport,
+ function(channel) {
+ var content = channel.objects.content;
+ content.setInitialText(jsContent.innerHTML);
+ content.textChanged.connect(updateText);
+ }
+ );
+ </script>
</body>
</html>
diff --git a/examples/webenginequick/recipebrowser/resources/pages/cupcakes.html b/examples/webenginewidgets/recipebrowser/assets/pages/cupcakes.html
index 4791c7ffa..e8e14a9b6 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/cupcakes.html
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/cupcakes.html
@@ -3,8 +3,11 @@
<head>
<meta charset="utf-8">
<title>Cupcakes</title>
- <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
- <link rel="stylesheet" type="text/css" href="assets/custom.css">
+ <link rel="stylesheet" type="text/css" href="../3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="../custom.css">
+ <script src="../3rdparty/marked.js"></script>
+ <script src="../custom.js"></script>
+ <script src="qrc:/qtwebchannel/qwebchannel.js"></script>
</head>
<body>
<div id="placeholder"></div>
@@ -46,8 +49,25 @@ Cupcakes
**Enjoy!**
</div><!--End of content-->
- <script src="assets/3rdparty/marked.js"></script>
- <script src="assets/custom.js"></script>
+
+ <script>
+ 'use strict';
+
+ var jsContent = document.getElementById('content');
+ var placeholder = document.getElementById('placeholder');
+
+ var updateText = function(text) {
+ placeholder.innerHTML = marked.parse(text);
+ }
+
+ new QWebChannel(qt.webChannelTransport,
+ function(channel) {
+ var content = channel.objects.content;
+ content.setInitialText(jsContent.innerHTML);
+ content.textChanged.connect(updateText);
+ }
+ );
+ </script>
</body>
</html>
diff --git a/examples/webenginequick/recipebrowser/resources/pages/images/burger.jpg b/examples/webenginewidgets/recipebrowser/assets/pages/images/burger.jpg
index edc0c65de..edc0c65de 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/images/burger.jpg
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/images/burger.jpg
Binary files differ
diff --git a/examples/webenginequick/recipebrowser/resources/pages/images/cupcakes.jpg b/examples/webenginewidgets/recipebrowser/assets/pages/images/cupcakes.jpg
index cce52ba23..cce52ba23 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/images/cupcakes.jpg
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/images/cupcakes.jpg
Binary files differ
diff --git a/examples/webenginequick/recipebrowser/resources/pages/images/pasta.jpg b/examples/webenginewidgets/recipebrowser/assets/pages/images/pasta.jpg
index 7ac924b79..7ac924b79 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/images/pasta.jpg
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/images/pasta.jpg
Binary files differ
diff --git a/examples/webenginequick/recipebrowser/resources/pages/images/pizza.jpg b/examples/webenginewidgets/recipebrowser/assets/pages/images/pizza.jpg
index 8d8f756af..8d8f756af 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/images/pizza.jpg
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/images/pizza.jpg
Binary files differ
diff --git a/examples/webenginequick/recipebrowser/resources/pages/images/skewers.jpg b/examples/webenginewidgets/recipebrowser/assets/pages/images/skewers.jpg
index 6bb2f1172..6bb2f1172 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/images/skewers.jpg
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/images/skewers.jpg
Binary files differ
diff --git a/examples/webenginequick/recipebrowser/resources/pages/images/soup.jpg b/examples/webenginewidgets/recipebrowser/assets/pages/images/soup.jpg
index fc9dff906..fc9dff906 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/images/soup.jpg
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/images/soup.jpg
Binary files differ
diff --git a/examples/webenginequick/recipebrowser/resources/pages/images/steak.jpg b/examples/webenginewidgets/recipebrowser/assets/pages/images/steak.jpg
index 240b72eb4..240b72eb4 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/images/steak.jpg
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/images/steak.jpg
Binary files differ
diff --git a/examples/webenginequick/recipebrowser/resources/pages/pasta.html b/examples/webenginewidgets/recipebrowser/assets/pages/pasta.html
index 41ed1a756..c2b3d840a 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/pasta.html
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/pasta.html
@@ -3,8 +3,11 @@
<head>
<meta charset="utf-8">
<title>Pasta</title>
- <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
- <link rel="stylesheet" type="text/css" href="assets/custom.css">
+ <link rel="stylesheet" type="text/css" href="../3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="../custom.css">
+ <script src="../3rdparty/marked.js"></script>
+ <script src="../custom.js"></script>
+ <script src="qrc:/qtwebchannel/qwebchannel.js"></script>
</head>
<body>
<div id="placeholder"></div>
@@ -49,8 +52,25 @@ Pasta
**Enjoy!**
</div><!--End of content-->
- <script src="assets/3rdparty/marked.js"></script>
- <script src="assets/custom.js"></script>
+
+ <script>
+ 'use strict';
+
+ var jsContent = document.getElementById('content');
+ var placeholder = document.getElementById('placeholder');
+
+ var updateText = function(text) {
+ placeholder.innerHTML = marked.parse(text);
+ }
+
+ new QWebChannel(qt.webChannelTransport,
+ function(channel) {
+ var content = channel.objects.content;
+ content.setInitialText(jsContent.innerHTML);
+ content.textChanged.connect(updateText);
+ }
+ );
+ </script>
</body>
</html>
diff --git a/examples/webenginequick/recipebrowser/resources/pages/pizza.html b/examples/webenginewidgets/recipebrowser/assets/pages/pizza.html
index 348d809e8..7e390a373 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/pizza.html
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/pizza.html
@@ -3,8 +3,11 @@
<head>
<meta charset="utf-8">
<title>Pizza Diavola</title>
- <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
- <link rel="stylesheet" type="text/css" href="assets/custom.css">
+ <link rel="stylesheet" type="text/css" href="../3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="../custom.css">
+ <script src="../3rdparty/marked.js"></script>
+ <script src="../custom.js"></script>
+ <script src="qrc:/qtwebchannel/qwebchannel.js"></script>
</head>
<body>
<div id="placeholder"></div>
@@ -40,8 +43,25 @@ Pizza Diavola
**Enjoy!**
</div><!--End of content-->
- <script src="assets/3rdparty/marked.js"></script>
- <script src="assets/custom.js"></script>
+
+ <script>
+ 'use strict';
+
+ var jsContent = document.getElementById('content');
+ var placeholder = document.getElementById('placeholder');
+
+ var updateText = function(text) {
+ placeholder.innerHTML = marked.parse(text);
+ }
+
+ new QWebChannel(qt.webChannelTransport,
+ function(channel) {
+ var content = channel.objects.content;
+ content.setInitialText(jsContent.innerHTML);
+ content.textChanged.connect(updateText);
+ }
+ );
+ </script>
</body>
</html>
diff --git a/examples/webenginequick/recipebrowser/resources/pages/skewers.html b/examples/webenginewidgets/recipebrowser/assets/pages/skewers.html
index aca4c4859..db2df5472 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/skewers.html
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/skewers.html
@@ -3,8 +3,11 @@
<head>
<meta charset="utf-8">
<title>Grilled skewers</title>
- <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
- <link rel="stylesheet" type="text/css" href="assets/custom.css">
+ <link rel="stylesheet" type="text/css" href="../3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="../custom.css">
+ <script src="../3rdparty/marked.js"></script>
+ <script src="../custom.js"></script>
+ <script src="qrc:/qtwebchannel/qwebchannel.js"></script>
</head>
<body>
<div id="placeholder"></div>
@@ -46,8 +49,24 @@ Grilled skewers
</div><!--End of content-->
- <script src="assets/3rdparty/marked.js"></script>
- <script src="assets/custom.js"></script>
+ <script>
+ 'use strict';
+
+ var jsContent = document.getElementById('content');
+ var placeholder = document.getElementById('placeholder');
+
+ var updateText = function(text) {
+ placeholder.innerHTML = marked.parse(text);
+ }
+
+ new QWebChannel(qt.webChannelTransport,
+ function(channel) {
+ var content = channel.objects.content;
+ content.setInitialText(jsContent.innerHTML);
+ content.textChanged.connect(updateText);
+ }
+ );
+ </script>
</body>
</html>
diff --git a/examples/webenginequick/recipebrowser/resources/pages/soup.html b/examples/webenginewidgets/recipebrowser/assets/pages/soup.html
index 1b7027e5d..ea51fc8a5 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/soup.html
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/soup.html
@@ -3,8 +3,11 @@
<head>
<meta charset="utf-8">
<title>Soup</title>
- <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
- <link rel="stylesheet" type="text/css" href="assets/custom.css">
+ <link rel="stylesheet" type="text/css" href="../3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="../custom.css">
+ <script src="../3rdparty/marked.js"></script>
+ <script src="../custom.js"></script>
+ <script src="qrc:/qtwebchannel/qwebchannel.js"></script>
</head>
<body>
<div id="placeholder"></div>
@@ -34,8 +37,25 @@ Soup
**Enjoy!**
</div><!--End of content-->
- <script src="assets/3rdparty/marked.js"></script>
- <script src="assets/custom.js"></script>
+
+ <script>
+ 'use strict';
+
+ var jsContent = document.getElementById('content');
+ var placeholder = document.getElementById('placeholder');
+
+ var updateText = function(text) {
+ placeholder.innerHTML = marked.parse(text);
+ }
+
+ new QWebChannel(qt.webChannelTransport,
+ function(channel) {
+ var content = channel.objects.content;
+ content.setInitialText(jsContent.innerHTML);
+ content.textChanged.connect(updateText);
+ }
+ );
+ </script>
</body>
</html>
diff --git a/examples/webenginequick/recipebrowser/resources/pages/steak.html b/examples/webenginewidgets/recipebrowser/assets/pages/steak.html
index a56313e27..26391b409 100644
--- a/examples/webenginequick/recipebrowser/resources/pages/steak.html
+++ b/examples/webenginewidgets/recipebrowser/assets/pages/steak.html
@@ -3,8 +3,11 @@
<head>
<meta charset="utf-8">
<title>Grilled steak and rice</title>
- <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
- <link rel="stylesheet" type="text/css" href="assets/custom.css">
+ <link rel="stylesheet" type="text/css" href="../3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="../custom.css">
+ <script src="../3rdparty/marked.js"></script>
+ <script src="../custom.js"></script>
+ <script src="qrc:/qtwebchannel/qwebchannel.js"></script>
</head>
<body>
<div id="placeholder"></div>
@@ -60,8 +63,24 @@ Grilled steak and rice
</div><!--End of content-->
- <script src="assets/3rdparty/marked.js"></script>
- <script src="assets/custom.js"></script>
+ <script>
+ 'use strict';
+
+ var jsContent = document.getElementById('content');
+ var placeholder = document.getElementById('placeholder');
+
+ var updateText = function(text) {
+ placeholder.innerHTML = marked.parse(text);
+ }
+
+ new QWebChannel(qt.webChannelTransport,
+ function(channel) {
+ var content = channel.objects.content;
+ content.setInitialText(jsContent.innerHTML);
+ content.textChanged.connect(updateText);
+ }
+ );
+ </script>
</body>
</html>
diff --git a/examples/webenginewidgets/recipebrowser/doc/images/recipebrowser.webp b/examples/webenginewidgets/recipebrowser/doc/images/recipebrowser.webp
new file mode 100644
index 000000000..8446bcde3
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/doc/images/recipebrowser.webp
Binary files differ
diff --git a/examples/webenginewidgets/recipebrowser/doc/src/recipebrowser.qdoc b/examples/webenginewidgets/recipebrowser/doc/src/recipebrowser.qdoc
new file mode 100644
index 000000000..4ac9973b3
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/doc/src/recipebrowser.qdoc
@@ -0,0 +1,197 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \example webenginewidgets/recipebrowser
+ \title Recipe Browser
+ \meta category {Application Examples}
+ \meta tag {widgets, webengine, webchannel, webenginescript}
+ \ingroup webengine-widgetexamples
+ \brief Injecting custom stylsheets into web pages and providing a rich text preview
+ tool for a custom markup language.
+
+ \image recipebrowser.webp
+
+ \e {Recipe Browser} is a small hybrid web browser application. It demonstrates how to
+ use the \l{Qt WebEngine Widgets C++ Classes} {Qt WebEngine C++ classes} to combine
+ C++ and JavaScript logic in the following ways.
+
+ \list
+ \li Running arbitrary JavaScript code via \c QWebEnginePage::runJavaScript() to
+ inject custom CSS stylesheets
+ \li Using QWebEngineScript and QWebEngineScriptCollection to persist the JavaScript
+ code and inject it to every page
+ \li Using QWebChannel to interact with and provide a rich text preview for a custom
+ markup language
+ \endlist
+
+ \l{http://daringfireball.net/projects/markdown/}{Markdown} is a lightweight
+ markup language with a plain text formatting syntax.
+ Some services, such as \l{http://github.com}{github}, acknowledge the
+ format, and render the content as rich text when viewed in a browser.
+
+ The Recipe Browser main window is split into a navigation on the left and
+ a preview area on the right. The preview area on the right switches to an
+ editor when the user clicks the Edit button on the top left of the main window.
+ The editor supports the Markdown syntax and is implemented by using
+ QPlainTextEdit. The document is rendered as rich text in the preview area,
+ once the user clicks the View button,to which the Edit button transforms to.
+ This rendering is implemented by using QWebEngineView. To render the text,
+ a JavaScript library inside the web engine converts the Markdown text to HTML.
+ The preview is updated from the editor through QWebChannel.
+
+ \include examples-run.qdocinc
+
+ \section1 Exposing Document Text
+
+ To render the current Markdown text it needs to be exposed to the web engine through
+ QWebChannel. To achieve this it has to be part of Qt metatype system. This is done
+ by using a dedicated \c Document class that exposes the document text as a
+ \c {Q_PROPERTY}:
+
+ \quotefromfile webenginewidgets/recipebrowser/document.h
+ \skipto class Document
+ \printto #endif
+
+ The \c Document class wraps a QString \c m_currentText to be set on the C++
+ side with the \c setText() method and exposes it at runtime as a \c text
+ property with a \c textChanged signal. We define the \c setText method as
+ follows:
+
+ \quotefromfile webenginewidgets/recipebrowser/document.cpp
+ \skipto Document::setText(const QString &text)
+ \printuntil /^\}/
+
+ Additionally, the \c Document class keeps track of the current recipe via
+ \c m_currentPage. We call the recipes pages here, because each recipe has
+ its distinct HTML document that contains the initial text content.
+ Furthermore, \c m_textCollection is a QMap<QString, QString> that contains
+ the key/value pairs \{page, text\}, so that changes made to the text content
+ of a page is persisted between navigation. Nevertheless, we do not write the
+ modified text contents to the drive, but instead we persist them between
+ application start and shutdown via QSettings.
+
+ \section1 Creating the Main Window
+
+ The \c MainWindow class inherits the QMainWindow class:
+
+ \quotefromfile webenginewidgets/recipebrowser/mainwindow.h
+ \skipto class MainWindow :
+ \printto endif
+
+ The class declares private slots that match the two buttons on the
+ top left, over the navigation list view. Additionally, helper
+ methods for custom CSS stylesheets are declared.
+
+ The actual layout of the main window is specified in a \c .ui file.
+ The widgets and actions are available at runtime in the \c ui member
+ variable.
+
+ \c m_isEditMode is a boolean that toggles between the editor and the
+ preview area.
+ \c m_content is an instance of the \c Document class.
+
+ The actual setup of the different objects is done in the \c MainWindow
+ constructor:
+
+ \quotefromfile webenginewidgets/recipebrowser/mainwindow.cpp
+ \skipto MainWindow::MainWindow
+ \printto connect
+
+ The constructor first calls \c setupUi to construct the widgets and menu
+ actions according to the UI file. The text editor font is set to one
+ with a fixed character width, and the QWebEngineView widget is told not
+ to show a context menu. Furthermore, the editor is hidden away.
+
+ \printto ui->recipes
+
+ Here the \c clicked signals of QPushButton are connected to respective functions
+ that show the stylesheets dialog or toggle between edit and view mode, that is,
+ hide and show the editor and preview area respectively.
+
+ \printto m_content.setTextEdit
+
+ Here the navigation QListWidget on the left is setup with the 7 recipes.
+ Also, the currentItemChanged signal of QListWidget is connected to a lambda
+ that loads the new, current recipe page and updates the page in \c m_content.
+
+ \printto connect
+
+ Next, the pointer to the ui editor, a QPlainTextEdit, is passed to \c m_content to ensure that
+ calls to \c Document::setInitialText() work properly.
+
+ \printto QSettings
+
+ Here the \c textChanged signal of the editor is connected to a lambda that
+ updates the text in \c m_content. This object is then exposed to the JS side
+ by \c QWebChannel under the name \c{content}.
+
+ \printto ui->recipes
+
+ By using QSettings we persist stylesheets between application runs. If there
+ should be no stylesheets configured, for example, because the user deleted all of them
+ in a previous run, we load default ones.
+
+ \printto }
+
+ Finally, we set the currently selected list item to the first contained in the
+ navigation list widget. This triggers the previously mentioned
+ QListWidget::currentItemChanged signal and navigates to the page of the list item.
+
+ \section1 Working With Stylesheets
+
+ We use JavaScript to create and append CSS elements to the documents.
+ After declaring the script source, QWebEnginePage::runJavaScript() can run it
+ immediately and apply newly created styles on the current content of the web view.
+ Encapsulating the script into a QWebEngineScript and adding it to the script collection
+ of QWebEnginePage makes its effect permanent.
+
+ \quotefromfile webenginewidgets/recipebrowser/mainwindow.cpp
+ \skipto MainWindow::insertStyleSheet
+ \printuntil /^\}/
+
+ Removing stylesheets can be done similarly:
+
+ \quotefromfile webenginewidgets/recipebrowser/mainwindow.cpp
+ \skipto MainWindow::removeStyleSheet
+ \printuntil /^\}/
+
+ \section1 Creating a recipe file
+
+ \quotefile webenginewidgets/recipebrowser/assets/pages/burger.html
+
+ All the different recipe pages are set up the same way.
+
+ In the \c <head> part they
+ include two CSS files: \c markdown.css, that styles the markdown, and
+ custom.css, that does some further styling but most importantly hides the
+ \c <div> with id \e content, as this \c <div> only contains the unmodified,
+ initial content text. Also, three JS scripts are included. \c marked.js
+ is responsible for parsing the markdown and transforming it into HTML.
+ \c custom.js does some configuration of \c marked.js, and \c qwebchannel.js
+ exposes the QWebChannel JavaScript API.
+
+ In the body there are two \c <div> elements. The \c <div> with id \e placeholder
+ gets the markdown text injected that is rendered and visible. The \c <div> with id
+ \e content is hidden by \c custom.css and only contains the original, unmodified
+ text content of the recipe.
+
+ Finally, on the bottom of each recipe HTML file is a script that is responsible for
+ the communication between the C++ and JavaScript side via QWebChannel. The original,
+ unmodified text content inside the \c <div> with id \e content is passed to the C++
+ side and a callback is setup that is invoked when the \c textChanged signal of
+ \c m_content is emitted. The callback then updates the contents of the \c <div>
+ \e placeholder with the parsed markdown.
+
+ \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/webenginewidgets/recipebrowser/document.cpp b/examples/webenginewidgets/recipebrowser/document.cpp
new file mode 100644
index 000000000..c991e14f8
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/document.cpp
@@ -0,0 +1,48 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "document.h"
+
+#include <QSettings>
+
+Document::Document(QObject *parent) : QObject(parent)
+{
+ QSettings settings;
+ settings.beginGroup("textCollection");
+ QStringList pageTexts = settings.allKeys();
+ for (const QString &name : std::as_const(pageTexts)) {
+ QString pageText = settings.value(name).value<QString>();
+ if (!pageText.isEmpty())
+ m_textCollection.insert(name, pageText);
+ }
+ settings.endGroup();
+}
+
+void Document::setTextEdit(QPlainTextEdit *textEdit)
+{
+ m_textEdit = textEdit;
+}
+
+void Document::setCurrentPage(const QString &page)
+{
+ m_currentPage = page;
+}
+
+void Document::setInitialText(const QString &text)
+{
+ m_textEdit->setPlainText(m_textCollection.value(m_currentPage, text));
+}
+
+void Document::setText(const QString &text)
+{
+ if (text == m_currentText)
+ return;
+ m_currentText = text;
+ emit textChanged(m_currentText);
+
+ QSettings settings;
+ settings.beginGroup("textCollection");
+ settings.setValue(m_currentPage, text);
+ m_textCollection.insert(m_currentPage, text);
+ settings.endGroup();
+}
diff --git a/examples/webenginewidgets/recipebrowser/document.h b/examples/webenginewidgets/recipebrowser/document.h
new file mode 100644
index 000000000..f6b537eb8
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/document.h
@@ -0,0 +1,36 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef DOCUMENT_H
+#define DOCUMENT_H
+
+#include <QObject>
+#include <QString>
+#include <QPlainTextEdit>
+
+class Document : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString text MEMBER m_currentText NOTIFY textChanged FINAL)
+public:
+ explicit Document(QObject *parent = nullptr);
+
+ void setTextEdit(QPlainTextEdit *textEdit);
+ void setCurrentPage(const QString &page);
+
+public slots:
+ void setInitialText(const QString &text);
+ void setText(const QString &text);
+
+signals:
+ void textChanged(const QString &text);
+
+private:
+ QPlainTextEdit *m_textEdit;
+
+ QString m_currentText;
+ QString m_currentPage;
+ QMap<QString, QString> m_textCollection;
+};
+
+#endif // DOCUMENT_H
diff --git a/examples/webenginewidgets/stylesheetbrowser/main.cpp b/examples/webenginewidgets/recipebrowser/main.cpp
index cf1e5f718..b0b42d16b 100644
--- a/examples/webenginewidgets/stylesheetbrowser/main.cpp
+++ b/examples/webenginewidgets/recipebrowser/main.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
@@ -12,7 +12,7 @@ int main(int argc, char *argv[])
QCoreApplication::setOrganizationName("QtExamples");
QApplication a(argc, argv);
- MainWindow w(QUrl("http://qt.io"));
+ MainWindow w;
w.show();
return a.exec();
}
diff --git a/examples/webenginewidgets/recipebrowser/mainwindow.cpp b/examples/webenginewidgets/recipebrowser/mainwindow.cpp
new file mode 100644
index 000000000..7288fe4ce
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/mainwindow.cpp
@@ -0,0 +1,153 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "mainwindow.h"
+#include "stylesheetdialog.h"
+#include "ui_mainwindow.h"
+
+#include <QWebChannel>
+
+static QMap<QString, QString> defaultStyleSheets = {
+ { "Upside down", "body { -webkit-transform: rotate(180deg); }" },
+ { "Darkmode",
+ "body { color: #FFF; background-color: #000 }"
+ "h1, h2, h3, h4, h5 { color: #FFF }" }
+};
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent), ui(new Ui::MainWindow), m_isEditMode(false)
+{
+ ui->setupUi(this);
+ ui->textEdit->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
+ ui->textEdit->hide();
+ ui->webEngineView->setContextMenuPolicy(Qt::NoContextMenu);
+
+ connect(ui->stylesheetsButton, &QPushButton::clicked, this, &MainWindow::showStyleSheetsDialog);
+ connect(ui->editViewButton, &QPushButton::clicked, this, &MainWindow::toggleEditView);
+
+ ui->recipes->insertItem(0, "Burger");
+ ui->recipes->insertItem(1, "Cupcakes");
+ ui->recipes->insertItem(2, "Pasta");
+ ui->recipes->insertItem(3, "Pizza");
+ ui->recipes->insertItem(4, "Skewers");
+ ui->recipes->insertItem(5, "Soup");
+ ui->recipes->insertItem(6, "Steak");
+ connect(ui->recipes, &QListWidget::currentItemChanged, this,
+ [this](QListWidgetItem *current, QListWidgetItem * /* previous */) {
+ const QString page = current->text().toLower();
+ const QString url = QStringLiteral("qrc:/pages/") + page + QStringLiteral(".html");
+ ui->webEngineView->setUrl(QUrl(url));
+ m_content.setCurrentPage(page);
+ });
+
+ m_content.setTextEdit(ui->textEdit);
+
+ connect(ui->textEdit, &QPlainTextEdit::textChanged, this,
+ [this]() { m_content.setText(ui->textEdit->toPlainText()); });
+
+ QWebChannel *channel = new QWebChannel(this);
+ channel->registerObject(QStringLiteral("content"), &m_content);
+ ui->webEngineView->page()->setWebChannel(channel);
+
+ QSettings settings;
+ settings.beginGroup("styleSheets");
+ QStringList styleSheets = settings.allKeys();
+ if (styleSheets.empty()) {
+ // Add back default style sheets if the user cleared them out
+ loadDefaultStyleSheets();
+ } else {
+ for (const auto &name : std::as_const(styleSheets)) {
+ StyleSheet styleSheet = settings.value(name).value<StyleSheet>();
+ if (styleSheet.second)
+ insertStyleSheet(name, styleSheet.first, false);
+ }
+ }
+ settings.endGroup();
+
+ ui->recipes->setCurrentItem(ui->recipes->item(0));
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+void MainWindow::insertStyleSheet(const QString &name, const QString &source, bool immediately)
+{
+ QWebEngineScript script;
+ QString s = QString::fromLatin1("(function() {"
+ " css = document.createElement('style');"
+ " css.type = 'text/css';"
+ " css.id = '%1';"
+ " document.head.appendChild(css);"
+ " css.innerText = '%2';"
+ "})()")
+ .arg(name, source.simplified());
+ if (immediately)
+ ui->webEngineView->page()->runJavaScript(s, QWebEngineScript::ApplicationWorld);
+
+ script.setName(name);
+ script.setSourceCode(s);
+ script.setInjectionPoint(QWebEngineScript::DocumentReady);
+ script.setRunsOnSubFrames(true);
+ script.setWorldId(QWebEngineScript::ApplicationWorld);
+ ui->webEngineView->page()->scripts().insert(script);
+}
+
+void MainWindow::removeStyleSheet(const QString &name, bool immediately)
+{
+ QString s = QString::fromLatin1("(function() {"
+ " var element = document.getElementById('%1');"
+ " element.outerHTML = '';"
+ " delete element;"
+ "})()")
+ .arg(name);
+ if (immediately)
+ ui->webEngineView->page()->runJavaScript(s, QWebEngineScript::ApplicationWorld);
+
+ const QList<QWebEngineScript> scripts = ui->webEngineView->page()->scripts().find(name);
+ if (!scripts.isEmpty())
+ ui->webEngineView->page()->scripts().remove(scripts.first());
+}
+
+bool MainWindow::hasStyleSheet(const QString &name)
+{
+ const QList<QWebEngineScript> scripts = ui->webEngineView->page()->scripts().find(name);
+ return !scripts.isEmpty();
+}
+
+void MainWindow::loadDefaultStyleSheets()
+{
+ QSettings settings;
+ settings.beginGroup("styleSheets");
+
+ for (auto it = defaultStyleSheets.constBegin(); it != defaultStyleSheets.constEnd(); ++it) {
+ settings.setValue(it.key(), QVariant::fromValue(qMakePair(it.value(), true)));
+ insertStyleSheet(it.key(), it.value(), false);
+ }
+
+ settings.endGroup();
+}
+
+void MainWindow::showStyleSheetsDialog()
+{
+ StylesheetDialog *dialog = new StylesheetDialog(this);
+ dialog->show();
+}
+
+void MainWindow::toggleEditView()
+{
+ m_isEditMode = !m_isEditMode;
+
+ if (m_isEditMode) {
+ ui->webEngineView->hide();
+ ui->textEdit->show();
+
+ ui->editViewButton->setText(QStringLiteral("View"));
+ } else {
+ ui->textEdit->hide();
+ ui->webEngineView->show();
+
+ ui->editViewButton->setText(QStringLiteral("Edit"));
+ }
+}
diff --git a/examples/webenginewidgets/stylesheetbrowser/mainwindow.h b/examples/webenginewidgets/recipebrowser/mainwindow.h
index 92d6d02fe..959c82af8 100644
--- a/examples/webenginewidgets/stylesheetbrowser/mainwindow.h
+++ b/examples/webenginewidgets/recipebrowser/mainwindow.h
@@ -1,12 +1,15 @@
-// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
+#include "document.h"
#include <QMainWindow>
#include <QSettings>
#include <QWebEngineScriptCollection>
+#include <QWebEngineView>
+#include <QPlainTextEdit>
QT_BEGIN_NAMESPACE
namespace Ui {
@@ -19,7 +22,7 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
- explicit MainWindow(const QUrl &url);
+ explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
void insertStyleSheet(const QString &name, const QString &source, bool immediately);
@@ -28,13 +31,14 @@ public:
void loadDefaultStyleSheets();
private slots:
- void urlEntered();
- void urlChanged(const QUrl &url);
void showStyleSheetsDialog();
- void reloadRequested();
+ void toggleEditView();
private:
Ui::MainWindow *ui;
+
+ bool m_isEditMode;
+ Document m_content;
};
#endif // MAINWINDOW_H
diff --git a/examples/webenginewidgets/recipebrowser/mainwindow.ui b/examples/webenginewidgets/recipebrowser/mainwindow.ui
new file mode 100644
index 000000000..b7c29f1b8
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/mainwindow.ui
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>713</width>
+ <height>455</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Recipe Browser</string>
+ </property>
+ <property name="unifiedTitleAndToolBarOnMac">
+ <bool>false</bool>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="navigation">
+ <item>
+ <layout class="QHBoxLayout" name="navigationBar">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Recipes</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="editViewButton">
+ <property name="text">
+ <string>Edit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="stylesheetsButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Stylesheets</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QListWidget" name="recipes">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QWebEngineView" name="webEngineView" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="textEdit"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <customwidgets>
+ <customwidget>
+ <class>QWebEngineView</class>
+ <extends>QWidget</extends>
+ <header>qwebengineview.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.pro b/examples/webenginewidgets/recipebrowser/recipebrowser.pro
index a9ff54400..8f8895b52 100644
--- a/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.pro
+++ b/examples/webenginewidgets/recipebrowser/recipebrowser.pro
@@ -1,22 +1,24 @@
TEMPLATE = app
-TARGET = stylesheetbrowser
+TARGET = recipebrowser
QT += webenginewidgets
HEADERS += \
mainwindow.h \
- stylesheetdialog.h
+ stylesheetdialog.h \
+ document.h
SOURCES += \
main.cpp \
mainwindow.cpp \
- stylesheetdialog.cpp
+ stylesheetdialog.cpp \
+ document.cpp
FORMS += \
mainwindow.ui \
stylesheetdialog.ui
-RESOURCES += stylesheetbrowser.qrc
+RESOURCES += recipebrowser.qrc
# install
-target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/stylesheetbrowser
+target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/recipebrowser
INSTALLS += target
diff --git a/examples/webenginewidgets/recipebrowser/recipebrowser.qrc b/examples/webenginewidgets/recipebrowser/recipebrowser.qrc
new file mode 100644
index 000000000..2dc003f30
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/recipebrowser.qrc
@@ -0,0 +1,15 @@
+<RCC>
+ <qresource prefix="/">
+ <file>assets/3rdparty/markdown.css</file>
+ <file>assets/3rdparty/marked.js</file>
+ <file>assets/custom.js</file>
+ <file>assets/custom.css</file>
+ <file>assets/pages/burger.html</file>
+ <file>assets/pages/cupcakes.html</file>
+ <file>assets/pages/pasta.html</file>
+ <file>assets/pages/pizza.html</file>
+ <file>assets/pages/skewers.html</file>
+ <file>assets/pages/soup.html</file>
+ <file>assets/pages/steak.html</file>
+ </qresource>
+</RCC>
diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp b/examples/webenginewidgets/recipebrowser/stylesheetdialog.cpp
index 30409f107..2137617c3 100644
--- a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp
+++ b/examples/webenginewidgets/recipebrowser/stylesheetdialog.cpp
@@ -1,18 +1,18 @@
-// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include "stylesheetdialog.h"
#include "ui_stylesheetdialog.h"
-StylesheetDialog::StylesheetDialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::StylesheetDialog)
+StylesheetDialog::StylesheetDialog(QWidget *parent) : QDialog(parent), ui(new Ui::StylesheetDialog)
{
ui->setupUi(this);
- connect(ui->styleSheetList, &QListWidget::currentItemChanged, this, &StylesheetDialog::currentStyleSheetChanged);
- connect(ui->styleSheetList, &QListWidget::itemClicked, this, &StylesheetDialog::listItemClicked);
+ connect(ui->styleSheetList, &QListWidget::currentItemChanged, this,
+ &StylesheetDialog::currentStyleSheetChanged);
+ connect(ui->styleSheetList, &QListWidget::itemClicked, this,
+ &StylesheetDialog::listItemClicked);
connect(ui->fileNameEdit, &QLineEdit::textChanged, this, &StylesheetDialog::fileNameChanged);
connect(ui->addButton, &QPushButton::clicked, this, &StylesheetDialog::addButtonClicked);
@@ -20,8 +20,8 @@ StylesheetDialog::StylesheetDialog(QWidget *parent) :
QSettings settings;
settings.beginGroup("styleSheets");
- for (auto name : settings.allKeys()) {
- QListWidgetItem *listItem = new QListWidgetItem(name, ui->styleSheetList);
+ for (const auto &name : settings.allKeys()) {
+ QListWidgetItem *listItem = new QListWidgetItem(name, ui->styleSheetList);
listItem->setFlags(listItem->flags() | Qt::ItemIsUserCheckable);
bool checked = settings.value(name).value<StyleSheet>().second;
listItem->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
@@ -59,9 +59,8 @@ void StylesheetDialog::listItemClicked(QListWidgetItem *item)
{
MainWindow *window = static_cast<MainWindow *>(parent());
const QString name = item->text();
- bool checkedStateChanged =
- (item->checkState() == Qt::Checked && !window->hasStyleSheet(name)) ||
- (item->checkState() == Qt::Unchecked && window->hasStyleSheet(name));
+ bool checkedStateChanged = (item->checkState() == Qt::Checked && !window->hasStyleSheet(name))
+ || (item->checkState() == Qt::Unchecked && window->hasStyleSheet(name));
if (!checkedStateChanged)
return;
@@ -96,7 +95,7 @@ void StylesheetDialog::addButtonClicked()
if (name.isEmpty() || source.isEmpty())
return;
- QListWidgetItem *listItem = new QListWidgetItem(ui->fileNameEdit->text(), ui->styleSheetList);
+ QListWidgetItem *listItem = new QListWidgetItem(ui->fileNameEdit->text(), ui->styleSheetList);
listItem->setFlags(listItem->flags() | Qt::ItemIsUserCheckable);
listItem->setCheckState(Qt::Checked);
diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h b/examples/webenginewidgets/recipebrowser/stylesheetdialog.h
index 7bebff74f..ca1b4ae99 100644
--- a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h
+++ b/examples/webenginewidgets/recipebrowser/stylesheetdialog.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef STYLESHEETDIALOG_H
diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.ui b/examples/webenginewidgets/recipebrowser/stylesheetdialog.ui
index 19db267e8..19db267e8 100644
--- a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.ui
+++ b/examples/webenginewidgets/recipebrowser/stylesheetdialog.ui
diff --git a/examples/webenginewidgets/stylesheetbrowser/3rdparty/COPYING b/examples/webenginewidgets/stylesheetbrowser/3rdparty/COPYING
deleted file mode 100644
index 220881da6..000000000
--- a/examples/webenginewidgets/stylesheetbrowser/3rdparty/COPYING
+++ /dev/null
@@ -1 +0,0 @@
-The icons in this repository are herefore released into the Public Domain.
diff --git a/examples/webenginewidgets/stylesheetbrowser/3rdparty/qt_attribution.json b/examples/webenginewidgets/stylesheetbrowser/3rdparty/qt_attribution.json
deleted file mode 100644
index f779da7e2..000000000
--- a/examples/webenginewidgets/stylesheetbrowser/3rdparty/qt_attribution.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "Id": "stylesheetbrowser-tango",
- "Name": "Tango Icon Library",
- "QDocModule": "qtwebengine",
- "QtUsage": "Used in WebEngine StyleSheet Browser example.",
-
- "QtParts": [ "examples" ],
- "Description": "Selected icons from the Tango Icon Library",
- "Homepage": "http://tango.freedesktop.org/Tango_Icon_Library",
- "Version": "0.8.90",
- "DownloadLocation": "http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz",
- "LicenseId": "urn:dje:license:public-domain",
- "License": "Public Domain",
- "LicenseFile": "COPYING",
- "Copyright": "Ulisse Perusin <uli.peru@gmail.com>
-Steven Garrity <sgarrity@silverorange.com>
-Lapo Calamandrei <calamandrei@gmail.com>
-Ryan Collier <rcollier@novell.com>
-Rodney Dawes <dobey@novell.com>
-Andreas Nilsson <nisses.mail@home.se>
-Tuomas Kuosmanen <tigert@tigert.com>
-Garrett LeSage <garrett@novell.com>
-Jakub Steiner <jimmac@novell.com>"
-}
diff --git a/examples/webenginewidgets/stylesheetbrowser/3rdparty/view-refresh.png b/examples/webenginewidgets/stylesheetbrowser/3rdparty/view-refresh.png
deleted file mode 100644
index cab4d02c7..000000000
--- a/examples/webenginewidgets/stylesheetbrowser/3rdparty/view-refresh.png
+++ /dev/null
Binary files differ
diff --git a/examples/webenginewidgets/stylesheetbrowser/CMakeLists.txt b/examples/webenginewidgets/stylesheetbrowser/CMakeLists.txt
deleted file mode 100644
index 56ecd51f3..000000000
--- a/examples/webenginewidgets/stylesheetbrowser/CMakeLists.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
-
-cmake_minimum_required(VERSION 3.16)
-project(stylesheetbrowser LANGUAGES CXX)
-
-set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTOUIC ON)
-
-if(NOT DEFINED INSTALL_EXAMPLESDIR)
- set(INSTALL_EXAMPLESDIR "examples")
-endif()
-
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/webenginewidgets/stylesheetbrowser")
-
-find_package(Qt6 REQUIRED COMPONENTS Core Gui WebEngineWidgets)
-
-qt_add_executable(stylesheetbrowser
- main.cpp
- mainwindow.cpp mainwindow.h mainwindow.ui
- stylesheetdialog.cpp stylesheetdialog.h stylesheetdialog.ui
-)
-
-set_target_properties(stylesheetbrowser PROPERTIES
- WIN32_EXECUTABLE TRUE
- MACOSX_BUNDLE TRUE
-)
-
-target_link_libraries(stylesheetbrowser PUBLIC
- Qt::Core
- Qt::Gui
- Qt::WebEngineWidgets
-)
-
-# Resources:
-set(stylesheetbrowser_resource_files
- "3rdparty/view-refresh.png"
-)
-
-qt_add_resources(stylesheetbrowser "stylesheetbrowser"
- PREFIX
- "/"
- BASE
- "3rdparty"
- FILES
- ${stylesheetbrowser_resource_files}
-)
-
-install(TARGETS stylesheetbrowser
- RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
- BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
- LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
-)
diff --git a/examples/webenginewidgets/stylesheetbrowser/doc/images/stylesheetbrowser.png b/examples/webenginewidgets/stylesheetbrowser/doc/images/stylesheetbrowser.png
deleted file mode 100644
index 32c7c43ed..000000000
--- a/examples/webenginewidgets/stylesheetbrowser/doc/images/stylesheetbrowser.png
+++ /dev/null
Binary files differ
diff --git a/examples/webenginewidgets/stylesheetbrowser/doc/src/stylesheetbrowser.qdoc b/examples/webenginewidgets/stylesheetbrowser/doc/src/stylesheetbrowser.qdoc
deleted file mode 100644
index 80f333323..000000000
--- a/examples/webenginewidgets/stylesheetbrowser/doc/src/stylesheetbrowser.qdoc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
-
-/*!
- \example webenginewidgets/stylesheetbrowser
- \title WebEngine StyleSheet Browser Example
- \ingroup webengine-widgetexamples
- \brief Demonstrates how to inject CSS into web pages using user scripts.
-
- \image stylesheetbrowser.png
-
- \e {StyleSheet Browser} demonstrates how to use the \l{Qt WebEngine Widgets C++ Classes}
- {Qt WebEngine C++ classes} to inject user stylesheets into web pages.
-
- \include examples-run.qdocinc
-
- \section1 Working With Stylesheets
-
- We use JavaScript to create and append CSS elements to the documents.
- After declaring the script source, QWebEnginePage::runJavaScript() can run it
- immediately and apply newly created styles on the current content of the web view.
- Encapsulating the script into a QWebEngineScript and adding it to the script collection
- of QWebEnginePage makes its effect permanent.
-
- \quotefromfile webenginewidgets/stylesheetbrowser/mainwindow.cpp
- \skipto MainWindow::insertStyleSheet
- \printuntil /^\}/
-
- Removing stylesheets can be done similarly:
-
- \quotefromfile webenginewidgets/stylesheetbrowser/mainwindow.cpp
- \skipto MainWindow::removeStyleSheet
- \printuntil /^\}/
-
- \section1 Files and Attributions
-
- The example uses icons from the Tango Icon Library:
-
- \table
- \row
- \li \l{stylesheetbrowser-tango}{Tango Icon Library}
- \li Public Domain
- \endtable
-*/
diff --git a/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp b/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp
deleted file mode 100644
index ab786d5c9..000000000
--- a/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#include "mainwindow.h"
-#include "stylesheetdialog.h"
-#include "ui_mainwindow.h"
-
-static QMap<QString, QString> defaultStyleSheets = {
- {"Upside down", "body { -webkit-transform: rotate(180deg); }"}
-};
-
-MainWindow::MainWindow(const QUrl &url) :
- QMainWindow(),
- ui(new Ui::MainWindow)
-{
- ui->setupUi(this);
-
- connect(ui->urlBar, &QLineEdit::returnPressed, this, &MainWindow::urlEntered);
- connect(ui->webEngineView, &QWebEngineView::urlChanged, this, &MainWindow::urlChanged);
- connect(ui->settingsButton, &QPushButton::clicked, this, &MainWindow::showStyleSheetsDialog);
- connect(ui->reloadButton, &QPushButton::clicked, this, &MainWindow::reloadRequested);
-
- QSettings settings;
- settings.beginGroup("styleSheets");
- QStringList styleSheets = settings.allKeys();
- if (styleSheets.empty()) {
- // Add back default style sheets if the user cleared them out
- loadDefaultStyleSheets();
- } else {
- for (auto name : std::as_const(styleSheets)) {
- StyleSheet styleSheet = settings.value(name).value<StyleSheet>();
- if (styleSheet.second)
- insertStyleSheet(name, styleSheet.first, false);
- }
- }
- settings.endGroup();
-
- ui->webEngineView->setUrl(url);
-}
-
-MainWindow::~MainWindow()
-{
- delete ui;
-}
-
-void MainWindow::insertStyleSheet(const QString &name, const QString &source, bool immediately)
-{
- QWebEngineScript script;
- QString s = QString::fromLatin1("(function() {"\
- " css = document.createElement('style');"\
- " css.type = 'text/css';"\
- " css.id = '%1';"\
- " document.head.appendChild(css);"\
- " css.innerText = '%2';"\
- "})()").arg(name).arg(source.simplified());
- if (immediately)
- ui->webEngineView->page()->runJavaScript(s, QWebEngineScript::ApplicationWorld);
-
- script.setName(name);
- script.setSourceCode(s);
- script.setInjectionPoint(QWebEngineScript::DocumentReady);
- script.setRunsOnSubFrames(true);
- script.setWorldId(QWebEngineScript::ApplicationWorld);
- ui->webEngineView->page()->scripts().insert(script);
-}
-
-void MainWindow::removeStyleSheet(const QString &name, bool immediately)
-{
- QString s = QString::fromLatin1("(function() {"\
- " var element = document.getElementById('%1');"\
- " element.outerHTML = '';"\
- " delete element;"\
- "})()").arg(name);
- if (immediately)
- ui->webEngineView->page()->runJavaScript(s, QWebEngineScript::ApplicationWorld);
-
- const QList<QWebEngineScript> scripts = ui->webEngineView->page()->scripts().find(name);
- if (!scripts.isEmpty())
- ui->webEngineView->page()->scripts().remove(scripts.first());
-}
-
-bool MainWindow::hasStyleSheet(const QString &name)
-{
- const QList<QWebEngineScript> scripts = ui->webEngineView->page()->scripts().find(name);
- return !scripts.isEmpty();
-}
-
-void MainWindow::loadDefaultStyleSheets()
-{
- QSettings settings;
- settings.beginGroup("styleSheets");
-
- auto it = defaultStyleSheets.constBegin();
- while (it != defaultStyleSheets.constEnd()) {
- settings.setValue(it.key(), QVariant::fromValue(qMakePair(it.value(), true)));
- insertStyleSheet(it.key(), it.value(), false);
- ++it;
- }
-
- settings.endGroup();
-}
-
-void MainWindow::urlEntered()
-{
- ui->webEngineView->setUrl(QUrl::fromUserInput(ui->urlBar->text()));
-}
-
-void MainWindow::urlChanged(const QUrl &url)
-{
- ui->urlBar->setText(url.toString());
-}
-
-void MainWindow::showStyleSheetsDialog()
-{
- StylesheetDialog *dialog = new StylesheetDialog(this);
- dialog->show();
-}
-
-void MainWindow::reloadRequested()
-{
- ui->webEngineView->reload();
-}
diff --git a/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui b/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui
deleted file mode 100644
index bc68c16bb..000000000
--- a/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui
+++ /dev/null
@@ -1,133 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>713</width>
- <height>455</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>StyleSheet Browser</string>
- </property>
- <property name="unifiedTitleAndToolBarOnMac">
- <bool>false</bool>
- </property>
- <widget class="QWidget" name="centralWidget">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QWidget" name="webContentsWidget" native="true">
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QWidget" name="urlBarWidget" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QLineEdit" name="urlBar"/>
- </item>
- <item>
- <widget class="QPushButton" name="reloadButton">
- <property name="text">
- <string/>
- </property>
- <property name="icon">
- <iconset resource="stylesheetbrowser.qrc">
- <normaloff>:/view-refresh.png</normaloff>:/view-refresh.png</iconset>
- </property>
- <property name="shortcut">
- <string>Ctrl+R</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="settingsButton">
- <property name="text">
- <string>Settings</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QWebEngineView" name="webEngineView" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="url" stdset="0">
- <url>
- <string>about:blank</string>
- </url>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QMenuBar" name="menuBar">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>713</width>
- <height>20</height>
- </rect>
- </property>
- </widget>
- </widget>
- <layoutdefault spacing="6" margin="11"/>
- <customwidgets>
- <customwidget>
- <class>QWebEngineView</class>
- <extends>QWidget</extends>
- <header location="global">QtWebEngineWidgets/QWebEngineView</header>
- </customwidget>
- </customwidgets>
- <resources>
- <include location="stylesheetbrowser.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.qrc b/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.qrc
deleted file mode 100644
index a1cebd6a7..000000000
--- a/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file alias="view-refresh.png">3rdparty/view-refresh.png</file>
- </qresource>
-</RCC>
diff --git a/examples/webenginewidgets/webenginewidgets.pro b/examples/webenginewidgets/webenginewidgets.pro
index aedd2cc62..2a24686cf 100644
--- a/examples/webenginewidgets/webenginewidgets.pro
+++ b/examples/webenginewidgets/webenginewidgets.pro
@@ -7,12 +7,11 @@ SUBDIRS += \
cookiebrowser \
notifications \
simplebrowser \
- stylesheetbrowser \
push-notifications \
videoplayer
qtConfig(webengine-geolocation): SUBDIRS += maps
-qtConfig(webengine-webchannel): SUBDIRS += markdowneditor
+qtConfig(webengine-webchannel): SUBDIRS += recipebrowser
qtConfig(webengine-printing-and-pdf) {
SUBDIRS += printme html2pdf