Sophie

Sophie

distrib > Mageia > 7 > armv7hl > media > core-updates > by-pkgid > 433eb9daba9f45efee96fd578b74d021 > files > 327

qtwebengine5-doc-5.12.6-1.mga7.noarch.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- recipebrowser.qdoc -->
  <title>WebEngine Recipe Browser | Qt WebEngine 5.12.6</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td >Qt 5.12</td><td ><a href="qtwebengine-index.html">Qt WebEngine</a></td><td ><a href="webengine-examples.html">Qt WebEngine Examples</a></td><td >WebEngine Recipe Browser</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right"><a href="qtwebengine-index.html">Qt 5.12.6 Reference Documentation</a></td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
<div class="sidebar">
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level1"><a href="#running-the-example">Running the Example</a></li>
<li class="level1"><a href="#c-code">C++ Code</a></li>
<li class="level1"><a href="#qml-code">QML Code</a></li>
<li class="level1"><a href="#files-and-attributions">Files and Attributions</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">WebEngine Recipe Browser</h1>
<span class="subtitle"></span>
<!-- $$$webengine/recipebrowser-brief -->
<p>A small hybrid application based on the <a href="qml-qtwebengine-webengineview.html">WebEngineView</a> QML type and Qt Quick Controls 2.</p>
<!-- @@@webengine/recipebrowser -->
<!-- $$$webengine/recipebrowser-description -->
<div class="descr"> <a name="details"></a>
<p class="centerAlign"><img src="images/recipebrowser-demo.jpg" alt="" /></p><p><i>Recipe Browser</i> demonstrates how to use the <a href="qml-qtwebengine-webengineview.html">WebEngineView</a> item, Qt Quick items, and Qt Quick Controls 2 items to develop a small hybrid web browser application. A 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 Qt Quick Controls 2 items, which have their active style set to the Material style. The web content is a mix of HTML and Markdown source compiled to HTML, along with CSS and JavaScript.</p>
<a name="running-the-example"></a>
<h2 id="running-the-example">Running the Example</h2>
<p>To run the example from Qt Creator, open the <b>Welcome</b> mode and select the example from <b>Examples</b>. For more information, visit Building and Running an Example.</p>
<a name="c-code"></a>
<h2 id="c-code">C++ Code</h2>
<p>In <code>main.cpp</code>, we use the QGuiApplication and QQmlApplicationEngine classes to set up and load the main QML file. We call <a href="qtwebengine.html#initialize">QtWebEngine::initialize</a> so we can use <a href="qml-qtwebengine-webengineview.html">WebEngineView</a> in our QML code. We enable high DPI screen support by setting the Qt::AA_EnableHighDpiScaling attribute. 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.</p>
<pre class="cpp">

  <span class="preprocessor">#include &lt;QGuiApplication&gt;</span>
  <span class="preprocessor">#include &lt;QQmlApplicationEngine&gt;</span>
  <span class="preprocessor">#include &lt;QQmlContext&gt;</span>
  <span class="preprocessor">#include &lt;QQuickStyle&gt;</span>
  <span class="preprocessor">#include &lt;qtwebengineglobal.h&gt;</span>

  <span class="type">int</span> main(<span class="type">int</span> argc<span class="operator">,</span> <span class="type">char</span> <span class="operator">*</span>argv<span class="operator">[</span><span class="operator">]</span>)
  {
      <span class="type">QCoreApplication</span><span class="operator">::</span>setOrganizationName(<span class="string">&quot;QtExamples&quot;</span>);
      <span class="type">QCoreApplication</span><span class="operator">::</span>setAttribute(<span class="type">Qt</span><span class="operator">::</span>AA_EnableHighDpiScaling);
      <span class="type">QGuiApplication</span> app(argc<span class="operator">,</span> argv);
      <span class="type"><a href="qtwebengine-module.html">QtWebEngine</a></span><span class="operator">::</span>initialize();

      <span class="type">QQuickStyle</span><span class="operator">::</span>setStyle(<span class="type">QStringLiteral</span>(<span class="string">&quot;Material&quot;</span>));

      <span class="type">QQmlApplicationEngine</span> engine;

      bool isEmbedded <span class="operator">=</span> <span class="keyword">false</span>;
  <span class="preprocessor">#ifdef QTWEBENGINE_RECIPE_BROWSER_EMBEDDED</span>
      isEmbedded <span class="operator">=</span> <span class="keyword">true</span>;
  <span class="preprocessor">#endif</span>
      engine<span class="operator">.</span>rootContext()<span class="operator">-</span><span class="operator">&gt;</span>setContextProperty(<span class="type">QStringLiteral</span>(<span class="string">&quot;isEmbedded&quot;</span>)<span class="operator">,</span> isEmbedded);

      engine<span class="operator">.</span>load(<span class="type">QUrl</span>(<span class="type">QStringLiteral</span>(<span class="string">&quot;qrc:/qml/main.qml&quot;</span>)));

      <span class="keyword">return</span> app<span class="operator">.</span>exec();
  }

</pre>
<a name="qml-code"></a>
<h2 id="qml-code">QML Code</h2>
<p>In the <code>main.qml</code> 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.</p>
<pre class="cpp">

  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

</pre>
<p>Next, we add a RowLayout item so we can divide the window into two parts: one being a custom <code>RecipeList</code> item containing the recipe titles, and the other being the <a href="qml-qtwebengine-webengineview.html">WebEngineView</a>, which shows the recipe details. The spacing is set to zero so the items are positioned directly next to each other.</p>
<pre class="cpp">

      RowLayout {
          id: container
          anchors.fill: parent
          spacing: 0

          RecipeList {
                  ...
              }
          }

          WebEngineView {
                  ...
          }
      }

</pre>
<p>The <code>RecipeList</code> item has a few 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 <code>recipeSelected</code> signal, to tell the <a href="qml-qtwebengine-webengineview.html">WebEngineView</a> to load the URL of the selected recipe.</p>
<pre class="cpp">

          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)
              }

</pre>
<p>The <a href="qml-qtwebengine-webengineview.html">WebEngineView</a> has similar layout properties, to make it occupy two thirds of the layout width.</p>
<pre class="cpp">

          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
                  }
              }
          }
      }
  }

</pre>
<p>We then disable the <a href="qml-qtwebengine-webenginesettings.html#focusOnNavigationEnabled-prop">focusOnNavigationEnabled</a> setting to make sure that the <a href="qml-qtwebengine-webengineview.html">WebEngineView</a> does not steal focus from the <code>RecipeList</code> 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 <a href="qml-qtwebengine-contextmenurequest.html">ContextMenuRequest</a>.</p>
<pre class="cpp">



</pre>
<p>When the application starts, instead of directly showing the <a href="qml-qtwebengine-webengineview.html">WebEngineView</a>, we show a placeholder Rectangle with a BusyIndicator to provide a nicer user experience while the application is loading. Once the first page in the view is loaded, we start a 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 ToolTip that informs the user on how to navigate the recipes.</p>
<pre class="cpp">



</pre>
<p>Let's see what the <code>RecipeList</code> 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 <code>recipeSelected</code> signal, which will be emitted when the current item of the ListView changes.</p>
<pre class="cpp">

  FocusScope {
      id: root
      signal recipeSelected(url url)

</pre>
<p>A ColumnLayout holds a header 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.</p>
<pre class="cpp">

      ColumnLayout {
          spacing: 0
          anchors.fill: parent

</pre>
<p>Inside the layout there is a styled ToolBar item, with a Label inside of it serving as the ListView header.</p>
<pre class="cpp">

          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
              }
          }

</pre>
<p>The second item inside the layout is a ListView, whose contents will fill the remaining space in the layout. We set clip to true, so that the delegates that are scrolled up are not seen under the ToolBar item. We set 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.</p>
<pre class="cpp">

          ListView {
              id: listView
              Layout.fillWidth: true
              Layout.fillHeight: true
              keyNavigationWraps: true
              clip: true
              focus: true
              ScrollBar.vertical: ScrollBar { }

              model: recipeModel

</pre>
<p>We have an ItemDelegate set as the ListView delegate, which displays the recipe title. The contentItem is a 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 highlighted property to <code>true</code> 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 <a href="qml-qtwebengine-webengineview.html">WebEngineView</a>.</p>
<pre class="cpp">

              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
                  }
              }

</pre>
<p>A handler is defined for the <code>currentItemChanged</code> signal to emit our own <code>recipeSelected</code> signal with the URL that the <a href="qml-qtwebengine-webengineview.html">WebEngineView</a> should load.</p>
<pre class="cpp">

              onCurrentItemChanged: {
                  root.recipeSelected(currentItem.url)
              }

</pre>
<p>We use a ListModel with seven ListElements, 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 <a href="qml-qtwebengine-webengineview.html">WebEngineView</a>.</p>
<pre class="cpp">

              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"
                  }
              }

</pre>
<p>We use a 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 <code>showHelp</code> method, which is invoked by the Timer in the main.qml file.</p>
<pre class="cpp">

              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()
      }
  }

</pre>
<p>An example of a recipe page can be seen below. The page uses two stylesheets and two JavaScript files:</p>
<ul>
<li><a href="http://kevinburke.bitbucket.org/markdowncss/">markdown.css</a> is a markdown-friendly stylesheet created by Kevin Burke</li>
<li><a href="https://github.com/chjj/marked">marked.min.js</a> is a markdown parser and compiler designed for speed written by Christopher Jeffrey</li>
<li>custom.css makes some small styling adjustments to the final recipe page</li>
<li>custom.js is used to invoke the conversion of the recipe content (which is written in markdown syntax) into HTML</li>
</ul>
<p>The images on the pages are loaded from the compiled resource file.</p>
<pre class="cpp">

  &lt;!doctype html&gt;
  &lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;&gt;
    &lt;title&gt;Soup&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;assets/3rdparty/markdown.css&quot;&gt;
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;assets/custom.css&quot;&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div id=&quot;placeholder&quot;&gt;&lt;/div&gt;
    &lt;div id=&quot;content&quot;&gt;

  &lt;img src=&quot;images/soup.jpg&quot; alt=&quot;Soup&quot; title=&quot;Soup&quot; /&gt;

  Soup
  =============

  ### Ingredients

  * 2 potatoes
  * 2 onions
  * 2 cloves of garlic
  * olive oil
  * 400 ml organic stock
  * 3 bunches of watercress

  ### Instructions
  * Peel and roughly chop the potatoes, onions and garlic.
  * In a large saucepan, heat a little olive oil, then sauté the potato, onion and garlic until the onions are translucent.
  * Add the stock and simmer until the potato is soft. Chop and add the watercress and simmer for a further 3 to 4 minutes.
  * Using a hand blender, liquidise the soup until smooth.
  * Serve with a swirl of crème fraîche and some Fortt’s Bath Oliver biscuits, if you like.

  **Enjoy!**

    &lt;/div&gt;&lt;!--End of content--&gt;
    &lt;script src=&quot;assets/3rdparty/marked.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;assets/custom.js&quot;&gt;&lt;/script&gt;
  &lt;/body&gt;
  &lt;/html&gt;

</pre>
<a name="files-and-attributions"></a>
<h2 id="files-and-attributions">Files and Attributions</h2>
<p>The example bundles the following code with third-party licenses:</p>
<div class="table"><table class="generic">
 <tr valign="top" class="odd"><td ><a href="qtwebengine-attribution-recipebrowser-marked.html#recipebrowser-marked">Marked</a></td><td >MIT License</td></tr>
<tr valign="top" class="even"><td ><a href="qtwebengine-attribution-recipebrowser-markdowncss.html#recipebrowser-markdowncss">Markdown.css</a></td><td >Apache License 2.0</td></tr>
</table></div>
<p>Files:</p>
<ul>
<li><a href="qtwebengine-webengine-recipebrowser-main-cpp.html">webengine/recipebrowser/main.cpp</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-recipebrowser-pro.html">webengine/recipebrowser/recipebrowser.pro</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-pages-assets-3rdparty-markdown-css.html">webengine/recipebrowser/resources/pages/assets/3rdparty/markdown.css</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-pages-assets-3rdparty-marked-js.html">webengine/recipebrowser/resources/pages/assets/3rdparty/marked.js</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-pages-assets-custom-css.html">webengine/recipebrowser/resources/pages/assets/custom.css</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-pages-assets-custom-js.html">webengine/recipebrowser/resources/pages/assets/custom.js</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-pages-burger-html.html">webengine/recipebrowser/resources/pages/burger.html</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-pages-cupcakes-html.html">webengine/recipebrowser/resources/pages/cupcakes.html</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-pages-pasta-html.html">webengine/recipebrowser/resources/pages/pasta.html</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-pages-pizza-html.html">webengine/recipebrowser/resources/pages/pizza.html</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-pages-skewers-html.html">webengine/recipebrowser/resources/pages/skewers.html</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-pages-soup-html.html">webengine/recipebrowser/resources/pages/soup.html</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-pages-steak-html.html">webengine/recipebrowser/resources/pages/steak.html</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-qml-recipelist-qml.html">webengine/recipebrowser/resources/qml/RecipeList.qml</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-qml-main-qml.html">webengine/recipebrowser/resources/qml/main.qml</a></li>
<li><a href="qtwebengine-webengine-recipebrowser-resources-resources-qrc.html">webengine/recipebrowser/resources/resources.qrc</a></li>
</ul>
<p>Images:</p>
<ul>
<li><a href="images/used-in-examples/webengine/recipebrowser/resources/pages/images/burger.jpg">webengine/recipebrowser/resources/pages/images/burger.jpg</a></li>
<li><a href="images/used-in-examples/webengine/recipebrowser/resources/pages/images/cupcakes.jpg">webengine/recipebrowser/resources/pages/images/cupcakes.jpg</a></li>
<li><a href="images/used-in-examples/webengine/recipebrowser/resources/pages/images/pasta.jpg">webengine/recipebrowser/resources/pages/images/pasta.jpg</a></li>
<li><a href="images/used-in-examples/webengine/recipebrowser/resources/pages/images/pizza.jpg">webengine/recipebrowser/resources/pages/images/pizza.jpg</a></li>
<li><a href="images/used-in-examples/webengine/recipebrowser/resources/pages/images/skewers.jpg">webengine/recipebrowser/resources/pages/images/skewers.jpg</a></li>
<li><a href="images/used-in-examples/webengine/recipebrowser/resources/pages/images/soup.jpg">webengine/recipebrowser/resources/pages/images/soup.jpg</a></li>
<li><a href="images/used-in-examples/webengine/recipebrowser/resources/pages/images/steak.jpg">webengine/recipebrowser/resources/pages/images/steak.jpg</a></li>
</ul>
</div>
<!-- @@@webengine/recipebrowser -->
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2019 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br/>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br/>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>