From 482a89fb431da3430bdfd4a1f9a93d66b8254163 Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Mon, 10 Mar 2014 16:37:18 +0100 Subject: Rename example directories to match the source install destination To match other modules example directory structures we should deploy our examples in a directory matching the module name, webengine and webenginewidgets in our case. qmake uses the relative directory of each example up to the upper "examples" directory to decide where they will be deployed when running the sources install target. Change-Id: I59ce7ff8a30f98fad20064c7eecf72b784f1d275 Reviewed-by: Pierre Rossi --- examples/examples.pro | 6 +- .../quick/quicknanobrowser/ContextMenuExtras.qml | 61 - examples/quick/quicknanobrowser/icons/go-next.png | Bin 930 -> 0 bytes .../quick/quicknanobrowser/icons/go-previous.png | Bin 955 -> 0 bytes .../quick/quicknanobrowser/icons/process-stop.png | Bin 1272 -> 0 bytes .../quick/quicknanobrowser/icons/view-refresh.png | Bin 1364 -> 0 bytes examples/quick/quicknanobrowser/main.cpp | 66 - .../quick/quicknanobrowser/quicknanobrowser.pro | 24 - examples/quick/quicknanobrowser/quickwindow.cpp | 66 - examples/quick/quicknanobrowser/quickwindow.h | 55 - examples/quick/quicknanobrowser/quickwindow.qml | 247 ---- examples/quick/quicknanobrowser/resources.qrc | 12 - examples/quick/quicknanobrowser/util.h | 73 -- .../quicknanobrowser/ContextMenuExtras.qml | 61 + .../webengine/quicknanobrowser/icons/go-next.png | Bin 0 -> 930 bytes .../quicknanobrowser/icons/go-previous.png | Bin 0 -> 955 bytes .../quicknanobrowser/icons/process-stop.png | Bin 0 -> 1272 bytes .../quicknanobrowser/icons/view-refresh.png | Bin 0 -> 1364 bytes examples/webengine/quicknanobrowser/main.cpp | 66 + .../quicknanobrowser/quicknanobrowser.pro | 24 + .../webengine/quicknanobrowser/quickwindow.cpp | 66 + examples/webengine/quicknanobrowser/quickwindow.h | 55 + .../webengine/quicknanobrowser/quickwindow.qml | 247 ++++ examples/webengine/quicknanobrowser/resources.qrc | 12 + examples/webengine/quicknanobrowser/util.h | 73 ++ examples/webenginewidgets/browser/Info_mac.plist | 43 + .../webenginewidgets/browser/addbookmarkdialog.ui | 98 ++ examples/webenginewidgets/browser/autosaver.cpp | 93 ++ examples/webenginewidgets/browser/autosaver.h | 75 ++ examples/webenginewidgets/browser/bookmarks.cpp | 986 +++++++++++++++ examples/webenginewidgets/browser/bookmarks.h | 309 +++++ examples/webenginewidgets/browser/bookmarks.ui | 106 ++ examples/webenginewidgets/browser/browser.icns | Bin 0 -> 50218 bytes examples/webenginewidgets/browser/browser.ico | Bin 0 -> 15374 bytes examples/webenginewidgets/browser/browser.pro | 103 ++ examples/webenginewidgets/browser/browser.rc | 1 + .../browser/browserapplication.cpp | 472 +++++++ .../webenginewidgets/browser/browserapplication.h | 118 ++ .../webenginewidgets/browser/browsermainwindow.cpp | 993 +++++++++++++++ .../webenginewidgets/browser/browsermainwindow.h | 171 +++ examples/webenginewidgets/browser/chasewidget.cpp | 141 +++ examples/webenginewidgets/browser/chasewidget.h | 85 ++ examples/webenginewidgets/browser/cookiejar.cpp | 737 +++++++++++ examples/webenginewidgets/browser/cookiejar.h | 203 +++ examples/webenginewidgets/browser/cookies.ui | 106 ++ .../webenginewidgets/browser/cookiesexceptions.ui | 184 +++ examples/webenginewidgets/browser/data/addtab.png | Bin 0 -> 469 bytes examples/webenginewidgets/browser/data/browser.svg | 411 +++++++ .../webenginewidgets/browser/data/closetab.png | Bin 0 -> 516 bytes examples/webenginewidgets/browser/data/data.qrc | 11 + .../browser/data/defaultbookmarks.xbel | 43 + .../webenginewidgets/browser/data/defaulticon.png | Bin 0 -> 1473 bytes examples/webenginewidgets/browser/data/history.png | Bin 0 -> 1527 bytes examples/webenginewidgets/browser/data/loading.gif | Bin 0 -> 847 bytes .../browser/doc/images/browser-demo.png | Bin 0 -> 156342 bytes .../webenginewidgets/browser/doc/src/browser.qdoc | 41 + examples/webenginewidgets/browser/downloaditem.ui | 134 ++ .../webenginewidgets/browser/downloadmanager.cpp | 580 +++++++++ .../webenginewidgets/browser/downloadmanager.h | 161 +++ examples/webenginewidgets/browser/downloads.ui | 83 ++ .../webenginewidgets/browser/edittableview.cpp | 77 ++ examples/webenginewidgets/browser/edittableview.h | 60 + examples/webenginewidgets/browser/edittreeview.cpp | 76 ++ examples/webenginewidgets/browser/edittreeview.h | 60 + examples/webenginewidgets/browser/history.cpp | 1298 ++++++++++++++++++++ examples/webenginewidgets/browser/history.h | 354 ++++++ examples/webenginewidgets/browser/history.ui | 106 ++ examples/webenginewidgets/browser/htmls/htmls.qrc | 5 + .../webenginewidgets/browser/htmls/notfound.html | 63 + examples/webenginewidgets/browser/main.cpp | 52 + examples/webenginewidgets/browser/modelmenu.cpp | 226 ++++ examples/webenginewidgets/browser/modelmenu.h | 104 ++ .../browser/networkaccessmanager.cpp | 160 +++ .../browser/networkaccessmanager.h | 75 ++ .../webenginewidgets/browser/passworddialog.ui | 111 ++ examples/webenginewidgets/browser/proxy.ui | 104 ++ .../webenginewidgets/browser/searchlineedit.cpp | 240 ++++ examples/webenginewidgets/browser/searchlineedit.h | 102 ++ examples/webenginewidgets/browser/settings.cpp | 331 +++++ examples/webenginewidgets/browser/settings.h | 73 ++ examples/webenginewidgets/browser/settings.ui | 614 +++++++++ examples/webenginewidgets/browser/squeezelabel.cpp | 60 + examples/webenginewidgets/browser/squeezelabel.h | 59 + examples/webenginewidgets/browser/tabwidget.cpp | 839 +++++++++++++ examples/webenginewidgets/browser/tabwidget.h | 223 ++++ .../webenginewidgets/browser/toolbarsearch.cpp | 166 +++ examples/webenginewidgets/browser/toolbarsearch.h | 83 ++ examples/webenginewidgets/browser/urllineedit.cpp | 342 ++++++ examples/webenginewidgets/browser/urllineedit.h | 114 ++ examples/webenginewidgets/browser/webview.cpp | 431 +++++++ examples/webenginewidgets/browser/webview.h | 121 ++ examples/webenginewidgets/browser/xbel.cpp | 282 +++++ examples/webenginewidgets/browser/xbel.h | 111 ++ .../doc/images/fancybrowser-example.png | Bin 0 -> 98031 bytes .../fancybrowser/doc/src/fancybrowser.qdoc | 140 +++ .../webenginewidgets/fancybrowser/fancybrowser.pro | 12 + .../webenginewidgets/fancybrowser/jquery.min.js | 19 + examples/webenginewidgets/fancybrowser/jquery.qrc | 5 + examples/webenginewidgets/fancybrowser/main.cpp | 55 + .../webenginewidgets/fancybrowser/mainwindow.cpp | 225 ++++ .../webenginewidgets/fancybrowser/mainwindow.h | 80 ++ examples/widgets/browser/Info_mac.plist | 43 - examples/widgets/browser/addbookmarkdialog.ui | 98 -- examples/widgets/browser/autosaver.cpp | 93 -- examples/widgets/browser/autosaver.h | 75 -- examples/widgets/browser/bookmarks.cpp | 986 --------------- examples/widgets/browser/bookmarks.h | 309 ----- examples/widgets/browser/bookmarks.ui | 106 -- examples/widgets/browser/browser.icns | Bin 50218 -> 0 bytes examples/widgets/browser/browser.ico | Bin 15374 -> 0 bytes examples/widgets/browser/browser.pro | 103 -- examples/widgets/browser/browser.rc | 1 - examples/widgets/browser/browserapplication.cpp | 472 ------- examples/widgets/browser/browserapplication.h | 118 -- examples/widgets/browser/browsermainwindow.cpp | 993 --------------- examples/widgets/browser/browsermainwindow.h | 171 --- examples/widgets/browser/chasewidget.cpp | 141 --- examples/widgets/browser/chasewidget.h | 85 -- examples/widgets/browser/cookiejar.cpp | 737 ----------- examples/widgets/browser/cookiejar.h | 203 --- examples/widgets/browser/cookies.ui | 106 -- examples/widgets/browser/cookiesexceptions.ui | 184 --- examples/widgets/browser/data/addtab.png | Bin 469 -> 0 bytes examples/widgets/browser/data/browser.svg | 411 ------- examples/widgets/browser/data/closetab.png | Bin 516 -> 0 bytes examples/widgets/browser/data/data.qrc | 11 - .../widgets/browser/data/defaultbookmarks.xbel | 43 - examples/widgets/browser/data/defaulticon.png | Bin 1473 -> 0 bytes examples/widgets/browser/data/history.png | Bin 1527 -> 0 bytes examples/widgets/browser/data/loading.gif | Bin 847 -> 0 bytes .../widgets/browser/doc/images/browser-demo.png | Bin 156342 -> 0 bytes examples/widgets/browser/doc/src/browser.qdoc | 41 - examples/widgets/browser/downloaditem.ui | 134 -- examples/widgets/browser/downloadmanager.cpp | 580 --------- examples/widgets/browser/downloadmanager.h | 161 --- examples/widgets/browser/downloads.ui | 83 -- examples/widgets/browser/edittableview.cpp | 77 -- examples/widgets/browser/edittableview.h | 60 - examples/widgets/browser/edittreeview.cpp | 76 -- examples/widgets/browser/edittreeview.h | 60 - examples/widgets/browser/history.cpp | 1298 -------------------- examples/widgets/browser/history.h | 354 ------ examples/widgets/browser/history.ui | 106 -- examples/widgets/browser/htmls/htmls.qrc | 5 - examples/widgets/browser/htmls/notfound.html | 63 - examples/widgets/browser/main.cpp | 52 - examples/widgets/browser/modelmenu.cpp | 226 ---- examples/widgets/browser/modelmenu.h | 104 -- examples/widgets/browser/networkaccessmanager.cpp | 160 --- examples/widgets/browser/networkaccessmanager.h | 75 -- examples/widgets/browser/passworddialog.ui | 111 -- examples/widgets/browser/proxy.ui | 104 -- examples/widgets/browser/searchlineedit.cpp | 240 ---- examples/widgets/browser/searchlineedit.h | 102 -- examples/widgets/browser/settings.cpp | 331 ----- examples/widgets/browser/settings.h | 73 -- examples/widgets/browser/settings.ui | 614 --------- examples/widgets/browser/squeezelabel.cpp | 60 - examples/widgets/browser/squeezelabel.h | 59 - examples/widgets/browser/tabwidget.cpp | 839 ------------- examples/widgets/browser/tabwidget.h | 223 ---- examples/widgets/browser/toolbarsearch.cpp | 166 --- examples/widgets/browser/toolbarsearch.h | 83 -- examples/widgets/browser/urllineedit.cpp | 342 ------ examples/widgets/browser/urllineedit.h | 114 -- examples/widgets/browser/webview.cpp | 431 ------- examples/widgets/browser/webview.h | 121 -- examples/widgets/browser/xbel.cpp | 282 ----- examples/widgets/browser/xbel.h | 111 -- .../doc/images/fancybrowser-example.png | Bin 98031 -> 0 bytes .../widgets/fancybrowser/doc/src/fancybrowser.qdoc | 140 --- examples/widgets/fancybrowser/fancybrowser.pro | 12 - examples/widgets/fancybrowser/jquery.min.js | 19 - examples/widgets/fancybrowser/jquery.qrc | 5 - examples/widgets/fancybrowser/main.cpp | 55 - examples/widgets/fancybrowser/mainwindow.cpp | 225 ---- examples/widgets/fancybrowser/mainwindow.h | 80 -- 177 files changed, 14753 insertions(+), 14753 deletions(-) delete mode 100644 examples/quick/quicknanobrowser/ContextMenuExtras.qml delete mode 100644 examples/quick/quicknanobrowser/icons/go-next.png delete mode 100644 examples/quick/quicknanobrowser/icons/go-previous.png delete mode 100644 examples/quick/quicknanobrowser/icons/process-stop.png delete mode 100644 examples/quick/quicknanobrowser/icons/view-refresh.png delete mode 100644 examples/quick/quicknanobrowser/main.cpp delete mode 100644 examples/quick/quicknanobrowser/quicknanobrowser.pro delete mode 100644 examples/quick/quicknanobrowser/quickwindow.cpp delete mode 100644 examples/quick/quicknanobrowser/quickwindow.h delete mode 100644 examples/quick/quicknanobrowser/quickwindow.qml delete mode 100644 examples/quick/quicknanobrowser/resources.qrc delete mode 100644 examples/quick/quicknanobrowser/util.h create mode 100644 examples/webengine/quicknanobrowser/ContextMenuExtras.qml create mode 100644 examples/webengine/quicknanobrowser/icons/go-next.png create mode 100644 examples/webengine/quicknanobrowser/icons/go-previous.png create mode 100644 examples/webengine/quicknanobrowser/icons/process-stop.png create mode 100644 examples/webengine/quicknanobrowser/icons/view-refresh.png create mode 100644 examples/webengine/quicknanobrowser/main.cpp create mode 100644 examples/webengine/quicknanobrowser/quicknanobrowser.pro create mode 100644 examples/webengine/quicknanobrowser/quickwindow.cpp create mode 100644 examples/webengine/quicknanobrowser/quickwindow.h create mode 100644 examples/webengine/quicknanobrowser/quickwindow.qml create mode 100644 examples/webengine/quicknanobrowser/resources.qrc create mode 100644 examples/webengine/quicknanobrowser/util.h create mode 100644 examples/webenginewidgets/browser/Info_mac.plist create mode 100644 examples/webenginewidgets/browser/addbookmarkdialog.ui create mode 100644 examples/webenginewidgets/browser/autosaver.cpp create mode 100644 examples/webenginewidgets/browser/autosaver.h create mode 100644 examples/webenginewidgets/browser/bookmarks.cpp create mode 100644 examples/webenginewidgets/browser/bookmarks.h create mode 100644 examples/webenginewidgets/browser/bookmarks.ui create mode 100644 examples/webenginewidgets/browser/browser.icns create mode 100644 examples/webenginewidgets/browser/browser.ico create mode 100644 examples/webenginewidgets/browser/browser.pro create mode 100644 examples/webenginewidgets/browser/browser.rc create mode 100644 examples/webenginewidgets/browser/browserapplication.cpp create mode 100644 examples/webenginewidgets/browser/browserapplication.h create mode 100644 examples/webenginewidgets/browser/browsermainwindow.cpp create mode 100644 examples/webenginewidgets/browser/browsermainwindow.h create mode 100644 examples/webenginewidgets/browser/chasewidget.cpp create mode 100644 examples/webenginewidgets/browser/chasewidget.h create mode 100644 examples/webenginewidgets/browser/cookiejar.cpp create mode 100644 examples/webenginewidgets/browser/cookiejar.h create mode 100644 examples/webenginewidgets/browser/cookies.ui create mode 100644 examples/webenginewidgets/browser/cookiesexceptions.ui create mode 100644 examples/webenginewidgets/browser/data/addtab.png create mode 100644 examples/webenginewidgets/browser/data/browser.svg create mode 100644 examples/webenginewidgets/browser/data/closetab.png create mode 100644 examples/webenginewidgets/browser/data/data.qrc create mode 100644 examples/webenginewidgets/browser/data/defaultbookmarks.xbel create mode 100644 examples/webenginewidgets/browser/data/defaulticon.png create mode 100644 examples/webenginewidgets/browser/data/history.png create mode 100644 examples/webenginewidgets/browser/data/loading.gif create mode 100644 examples/webenginewidgets/browser/doc/images/browser-demo.png create mode 100644 examples/webenginewidgets/browser/doc/src/browser.qdoc create mode 100644 examples/webenginewidgets/browser/downloaditem.ui create mode 100644 examples/webenginewidgets/browser/downloadmanager.cpp create mode 100644 examples/webenginewidgets/browser/downloadmanager.h create mode 100644 examples/webenginewidgets/browser/downloads.ui create mode 100644 examples/webenginewidgets/browser/edittableview.cpp create mode 100644 examples/webenginewidgets/browser/edittableview.h create mode 100644 examples/webenginewidgets/browser/edittreeview.cpp create mode 100644 examples/webenginewidgets/browser/edittreeview.h create mode 100644 examples/webenginewidgets/browser/history.cpp create mode 100644 examples/webenginewidgets/browser/history.h create mode 100644 examples/webenginewidgets/browser/history.ui create mode 100644 examples/webenginewidgets/browser/htmls/htmls.qrc create mode 100644 examples/webenginewidgets/browser/htmls/notfound.html create mode 100644 examples/webenginewidgets/browser/main.cpp create mode 100644 examples/webenginewidgets/browser/modelmenu.cpp create mode 100644 examples/webenginewidgets/browser/modelmenu.h create mode 100644 examples/webenginewidgets/browser/networkaccessmanager.cpp create mode 100644 examples/webenginewidgets/browser/networkaccessmanager.h create mode 100644 examples/webenginewidgets/browser/passworddialog.ui create mode 100644 examples/webenginewidgets/browser/proxy.ui create mode 100644 examples/webenginewidgets/browser/searchlineedit.cpp create mode 100644 examples/webenginewidgets/browser/searchlineedit.h create mode 100644 examples/webenginewidgets/browser/settings.cpp create mode 100644 examples/webenginewidgets/browser/settings.h create mode 100644 examples/webenginewidgets/browser/settings.ui create mode 100644 examples/webenginewidgets/browser/squeezelabel.cpp create mode 100644 examples/webenginewidgets/browser/squeezelabel.h create mode 100644 examples/webenginewidgets/browser/tabwidget.cpp create mode 100644 examples/webenginewidgets/browser/tabwidget.h create mode 100644 examples/webenginewidgets/browser/toolbarsearch.cpp create mode 100644 examples/webenginewidgets/browser/toolbarsearch.h create mode 100644 examples/webenginewidgets/browser/urllineedit.cpp create mode 100644 examples/webenginewidgets/browser/urllineedit.h create mode 100644 examples/webenginewidgets/browser/webview.cpp create mode 100644 examples/webenginewidgets/browser/webview.h create mode 100644 examples/webenginewidgets/browser/xbel.cpp create mode 100644 examples/webenginewidgets/browser/xbel.h create mode 100644 examples/webenginewidgets/fancybrowser/doc/images/fancybrowser-example.png create mode 100644 examples/webenginewidgets/fancybrowser/doc/src/fancybrowser.qdoc create mode 100644 examples/webenginewidgets/fancybrowser/fancybrowser.pro create mode 100644 examples/webenginewidgets/fancybrowser/jquery.min.js create mode 100644 examples/webenginewidgets/fancybrowser/jquery.qrc create mode 100644 examples/webenginewidgets/fancybrowser/main.cpp create mode 100644 examples/webenginewidgets/fancybrowser/mainwindow.cpp create mode 100644 examples/webenginewidgets/fancybrowser/mainwindow.h delete mode 100644 examples/widgets/browser/Info_mac.plist delete mode 100644 examples/widgets/browser/addbookmarkdialog.ui delete mode 100644 examples/widgets/browser/autosaver.cpp delete mode 100644 examples/widgets/browser/autosaver.h delete mode 100644 examples/widgets/browser/bookmarks.cpp delete mode 100644 examples/widgets/browser/bookmarks.h delete mode 100644 examples/widgets/browser/bookmarks.ui delete mode 100644 examples/widgets/browser/browser.icns delete mode 100644 examples/widgets/browser/browser.ico delete mode 100644 examples/widgets/browser/browser.pro delete mode 100644 examples/widgets/browser/browser.rc delete mode 100644 examples/widgets/browser/browserapplication.cpp delete mode 100644 examples/widgets/browser/browserapplication.h delete mode 100644 examples/widgets/browser/browsermainwindow.cpp delete mode 100644 examples/widgets/browser/browsermainwindow.h delete mode 100644 examples/widgets/browser/chasewidget.cpp delete mode 100644 examples/widgets/browser/chasewidget.h delete mode 100644 examples/widgets/browser/cookiejar.cpp delete mode 100644 examples/widgets/browser/cookiejar.h delete mode 100644 examples/widgets/browser/cookies.ui delete mode 100644 examples/widgets/browser/cookiesexceptions.ui delete mode 100644 examples/widgets/browser/data/addtab.png delete mode 100644 examples/widgets/browser/data/browser.svg delete mode 100644 examples/widgets/browser/data/closetab.png delete mode 100644 examples/widgets/browser/data/data.qrc delete mode 100644 examples/widgets/browser/data/defaultbookmarks.xbel delete mode 100644 examples/widgets/browser/data/defaulticon.png delete mode 100644 examples/widgets/browser/data/history.png delete mode 100644 examples/widgets/browser/data/loading.gif delete mode 100644 examples/widgets/browser/doc/images/browser-demo.png delete mode 100644 examples/widgets/browser/doc/src/browser.qdoc delete mode 100644 examples/widgets/browser/downloaditem.ui delete mode 100644 examples/widgets/browser/downloadmanager.cpp delete mode 100644 examples/widgets/browser/downloadmanager.h delete mode 100644 examples/widgets/browser/downloads.ui delete mode 100644 examples/widgets/browser/edittableview.cpp delete mode 100644 examples/widgets/browser/edittableview.h delete mode 100644 examples/widgets/browser/edittreeview.cpp delete mode 100644 examples/widgets/browser/edittreeview.h delete mode 100644 examples/widgets/browser/history.cpp delete mode 100644 examples/widgets/browser/history.h delete mode 100644 examples/widgets/browser/history.ui delete mode 100644 examples/widgets/browser/htmls/htmls.qrc delete mode 100644 examples/widgets/browser/htmls/notfound.html delete mode 100644 examples/widgets/browser/main.cpp delete mode 100644 examples/widgets/browser/modelmenu.cpp delete mode 100644 examples/widgets/browser/modelmenu.h delete mode 100644 examples/widgets/browser/networkaccessmanager.cpp delete mode 100644 examples/widgets/browser/networkaccessmanager.h delete mode 100644 examples/widgets/browser/passworddialog.ui delete mode 100644 examples/widgets/browser/proxy.ui delete mode 100644 examples/widgets/browser/searchlineedit.cpp delete mode 100644 examples/widgets/browser/searchlineedit.h delete mode 100644 examples/widgets/browser/settings.cpp delete mode 100644 examples/widgets/browser/settings.h delete mode 100644 examples/widgets/browser/settings.ui delete mode 100644 examples/widgets/browser/squeezelabel.cpp delete mode 100644 examples/widgets/browser/squeezelabel.h delete mode 100644 examples/widgets/browser/tabwidget.cpp delete mode 100644 examples/widgets/browser/tabwidget.h delete mode 100644 examples/widgets/browser/toolbarsearch.cpp delete mode 100644 examples/widgets/browser/toolbarsearch.h delete mode 100644 examples/widgets/browser/urllineedit.cpp delete mode 100644 examples/widgets/browser/urllineedit.h delete mode 100644 examples/widgets/browser/webview.cpp delete mode 100644 examples/widgets/browser/webview.h delete mode 100644 examples/widgets/browser/xbel.cpp delete mode 100644 examples/widgets/browser/xbel.h delete mode 100644 examples/widgets/fancybrowser/doc/images/fancybrowser-example.png delete mode 100644 examples/widgets/fancybrowser/doc/src/fancybrowser.qdoc delete mode 100644 examples/widgets/fancybrowser/fancybrowser.pro delete mode 100644 examples/widgets/fancybrowser/jquery.min.js delete mode 100644 examples/widgets/fancybrowser/jquery.qrc delete mode 100644 examples/widgets/fancybrowser/main.cpp delete mode 100644 examples/widgets/fancybrowser/mainwindow.cpp delete mode 100644 examples/widgets/fancybrowser/mainwindow.h (limited to 'examples') diff --git a/examples/examples.pro b/examples/examples.pro index 4952e0b15..7940e289d 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -1,8 +1,8 @@ TEMPLATE=subdirs -SUBDIRS += quick/quicknanobrowser +SUBDIRS += webengine/quicknanobrowser qtHaveModule(widgets) { SUBDIRS += \ - widgets/browser \ - widgets/fancybrowser + webenginewidgets/browser \ + webenginewidgets/fancybrowser } diff --git a/examples/quick/quicknanobrowser/ContextMenuExtras.qml b/examples/quick/quicknanobrowser/ContextMenuExtras.qml deleted file mode 100644 index cf54e9ba0..000000000 --- a/examples/quick/quicknanobrowser/ContextMenuExtras.qml +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.1 -import QtWebEngine.UIDelegates 1.0 - -VisualItemModel { - MenuItem { - text: "An application specific entry" - onTriggered: console.log("Application specific action triggered") - } - Menu { - title: "Extras Submenu" - MenuItem { - text: "something" - onTriggered: console.log("something triggered") - } - MenuItem { - text: "something else" - enabled: false - } - } -} - diff --git a/examples/quick/quicknanobrowser/icons/go-next.png b/examples/quick/quicknanobrowser/icons/go-next.png deleted file mode 100644 index 6f3f65d33..000000000 Binary files a/examples/quick/quicknanobrowser/icons/go-next.png and /dev/null differ diff --git a/examples/quick/quicknanobrowser/icons/go-previous.png b/examples/quick/quicknanobrowser/icons/go-previous.png deleted file mode 100644 index 93be3d1ee..000000000 Binary files a/examples/quick/quicknanobrowser/icons/go-previous.png and /dev/null differ diff --git a/examples/quick/quicknanobrowser/icons/process-stop.png b/examples/quick/quicknanobrowser/icons/process-stop.png deleted file mode 100644 index b68290bf1..000000000 Binary files a/examples/quick/quicknanobrowser/icons/process-stop.png and /dev/null differ diff --git a/examples/quick/quicknanobrowser/icons/view-refresh.png b/examples/quick/quicknanobrowser/icons/view-refresh.png deleted file mode 100644 index cab4d02c7..000000000 Binary files a/examples/quick/quicknanobrowser/icons/view-refresh.png and /dev/null differ diff --git a/examples/quick/quicknanobrowser/main.cpp b/examples/quick/quicknanobrowser/main.cpp deleted file mode 100644 index 6c2f91de6..000000000 --- a/examples/quick/quicknanobrowser/main.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "quickwindow.h" -#ifndef QT_NO_WIDGETS -#include -typedef QApplication Application; -#else -#include -typedef QGuiApplication Application; -#endif -#include - -int main(int argc, char **argv) -{ - Application app(argc, argv); - - // This is currently needed by all QtWebEngine application using the HW accelerated QQuickWebView. - // It enables sharing between the QOpenGLContext of all QQuickWindows of the application. - // We have to do so until we expose a public API for it, or chose enable it by default in Qt 5.3.0. - QOpenGLContext shareContext; - shareContext.create(); - QSGContext::setSharedOpenGLContext(&shareContext); - - ApplicationEngine appEngine; - - return app.exec(); -} diff --git a/examples/quick/quicknanobrowser/quicknanobrowser.pro b/examples/quick/quicknanobrowser/quicknanobrowser.pro deleted file mode 100644 index b07bd4e51..000000000 --- a/examples/quick/quicknanobrowser/quicknanobrowser.pro +++ /dev/null @@ -1,24 +0,0 @@ -TEMPLATE = app -TARGET = quicknanobrowser - -macx: CONFIG -= app_bundle - -HEADERS = quickwindow.h \ - util.h -SOURCES = quickwindow.cpp \ - main.cpp - -OTHER_FILES += ContextMenuExtras.qml \ - quickwindow.qml - -RESOURCES += resources.qrc - -QT += qml quick -QT_PRIVATE += quick-private gui-private core-private - -qtHaveModule(widgets) { - QT += widgets # QApplication is required to get native styling with QtQuickControls -} - -target.path = $$[QT_INSTALL_EXAMPLES]/quick/quicknanobrowser -INSTALLS += target diff --git a/examples/quick/quicknanobrowser/quickwindow.cpp b/examples/quick/quicknanobrowser/quickwindow.cpp deleted file mode 100644 index ec7b6f94a..000000000 --- a/examples/quick/quicknanobrowser/quickwindow.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "quickwindow.h" - -#include "util.h" - -#include -#include -#include -#include -#include - -class Utils : public QObject { - Q_OBJECT -public: - Utils(QObject* parent = 0) : QObject(parent) { } - Q_INVOKABLE static QUrl fromUserInput(const QString& userInput) { return urlFromUserInput(userInput); } -}; - -#include "quickwindow.moc" - -ApplicationEngine::ApplicationEngine() -{ - rootContext()->setContextProperty("utils", new Utils(this)); - load(QUrl("qrc:/quickwindow.qml")); - QMetaObject::invokeMethod(rootObjects().first(), "load", Q_ARG(QVariant, startupUrl())); -} diff --git a/examples/quick/quicknanobrowser/quickwindow.h b/examples/quick/quicknanobrowser/quickwindow.h deleted file mode 100644 index ed25a23b8..000000000 --- a/examples/quick/quicknanobrowser/quickwindow.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QUICKWINDOW_H -#define QUICKWINDOW_H - -#include - -class QWebEngineView; - -class ApplicationEngine : public QQmlApplicationEngine { - Q_OBJECT -public: - ApplicationEngine(); -}; - -#endif // QUICKWINDOW_H diff --git a/examples/quick/quicknanobrowser/quickwindow.qml b/examples/quick/quicknanobrowser/quickwindow.qml deleted file mode 100644 index 183e41f4f..000000000 --- a/examples/quick/quicknanobrowser/quickwindow.qml +++ /dev/null @@ -1,247 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.1 -import QtWebEngine 1.0 -import QtWebEngine.experimental 1.0 -import QtQuick.Controls 1.0 -import QtQuick.Controls.Styles 1.0 -import QtQuick.Layouts 1.0 -import QtQuick.Window 2.1 -import QtQuick.Controls.Private 1.0 - -ApplicationWindow { - id: browserWindow - function load(url) { currentWebView.url = url } - property Item currentWebView: tabs.currentIndex < tabs.count ? tabs.getTab(tabs.currentIndex).item : null - - property bool isFullScreen: visibility == Window.FullScreen - onIsFullScreenChanged: { - // This is for the case where the system forces us to leave fullscreen. - if (currentWebView) - currentWebView.state = isFullScreen ? "FullScreen" : "" - } - - height: 600 - width: 800 - visible: true - title: currentWebView && currentWebView.title - - // Make sure the Qt.WindowFullscreenButtonHint is set on Mac. - Component.onCompleted: flags = flags | Qt.WindowFullscreenButtonHint - - // Create a styleItem to determine the platform. - // When using style "mac", ToolButtons are not supposed to accept focus. - StyleItem { id: styleItem } - property bool platformIsMac: styleItem.style == "mac" - - - Action { - id: focus - shortcut: "Ctrl+L" - onTriggered: { - addressBar.forceActiveFocus(); - addressBar.selectAll(); - } - } - Action { - shortcut: "Ctrl+R" - onTriggered: { - if (currentWebView) - currentWebView.reload() - } - } - Action { - shortcut: "Ctrl+T" - onTriggered: { - tabs.createEmptyTab() - addressBar.forceActiveFocus(); - addressBar.selectAll(); - } - } - Action { - shortcut: "Ctrl+W" - onTriggered: { - if (tabs.count == 1) - browserWindow.close() - else - tabs.removeTab(tabs.currentIndex) - } - } - - Action { - shortcut: "Escape" - onTriggered: { - if (browserWindow.isFullScreen) - browserWindow.showNormal() - } - } - - toolBar: ToolBar { - id: navigationBar - RowLayout { - anchors.fill: parent; - ToolButton { - id: backButton - iconSource: "icons/go-previous.png" - onClicked: currentWebView.goBack() - enabled: currentWebView && currentWebView.canGoBack - activeFocusOnTab: !browserWindow.platformIsMac - } - ToolButton { - id: forwardButton - iconSource: "icons/go-next.png" - onClicked: currentWebView.goForward() - enabled: currentWebView && currentWebView.canGoForward - activeFocusOnTab: !browserWindow.platformIsMac - } - ToolButton { - id: reloadButton - iconSource: currentWebView && currentWebView.loading ? "icons/process-stop.png" : "icons/view-refresh.png" - onClicked: currentWebView && currentWebView.loading ? currentWebView.stop() : currentWebView.reload() - activeFocusOnTab: !browserWindow.platformIsMac - } - TextField { - id: addressBar - Image { - anchors.verticalCenter: addressBar.verticalCenter; - x: 5 - z: 2 - id: faviconImage - width: 16; height: 16 - source: currentWebView && currentWebView.icon - } - style: TextFieldStyle { - padding { - left: 26; - } - } - focus: true - Layout.fillWidth: true - text: currentWebView && currentWebView.url - onAccepted: currentWebView.url = utils.fromUserInput(text) - } - } - ProgressBar { - id: progressBar - height: 3 - anchors { - left: parent.left - top: parent.bottom - right: parent.right - leftMargin: -parent.leftMargin - rightMargin: -parent.rightMargin - } - style: ProgressBarStyle { - background: Item {} - } - z: -2; - minimumValue: 0 - maximumValue: 100 - value: (currentWebView && currentWebView.loadProgress < 100) ? currentWebView.loadProgress : 0 - } - } - - TabView { - id: tabs - function createEmptyTab() { - var tab = addTab("", tabComponent) - // We must do this first to make sure that tab.active gets set so that tab.item gets instantiated immediately. - tabs.currentIndex = tabs.count - 1 - tab.title = Qt.binding(function() { return tab.item.title }) - return tab - } - - anchors.fill: parent - Component.onCompleted: createEmptyTab() - - Component { - id: tabComponent - WebEngineView { - id: webEngineView - function adoptHandle(viewHandle) { experimental.adoptHandle(viewHandle) } - - focus: true - - states: [ - State { - name: "FullScreen" - PropertyChanges { - target: tabs - frameVisible: false - tabsVisible: false - } - PropertyChanges { - target: navigationBar - visible: false - } - } - ] - - experimental { - isFullScreen: webEngineView.state == "FullScreen" && browserWindow.isFullScreen - onFullScreenRequested: { - if (fullScreen) { - webEngineView.state = "FullScreen" - browserWindow.showFullScreen(); - } else { - webEngineView.state = "" - browserWindow.showNormal(); - } - } - - onNewViewRequested: { - if (request.popup) - print("Warning: Blocked a popup window.") - else if (request.destination == WebEngineView.NewViewInTab) { - var tab = tabs.createEmptyTab() - request.openIn(tab.item) - } else { - var component = Qt.createComponent("quickwindow.qml") - var window = component.createObject() - request.openIn(window.currentWebView) - } - } - extraContextMenuEntriesComponent: ContextMenuExtras {} - } - } - } - } -} diff --git a/examples/quick/quicknanobrowser/resources.qrc b/examples/quick/quicknanobrowser/resources.qrc deleted file mode 100644 index 1befb4fd1..000000000 --- a/examples/quick/quicknanobrowser/resources.qrc +++ /dev/null @@ -1,12 +0,0 @@ - - - quickwindow.qml - ContextMenuExtras.qml - - - icons/go-next.png - icons/go-previous.png - icons/process-stop.png - icons/view-refresh.png - - diff --git a/examples/quick/quicknanobrowser/util.h b/examples/quick/quicknanobrowser/util.h deleted file mode 100644 index ea0ae8b2e..000000000 --- a/examples/quick/quicknanobrowser/util.h +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef UTIL_H -#define UTIL_H - -#include -#include -#include -#include - -QUrl urlFromUserInput(const QString& userInput) -{ - QFileInfo fileInfo(userInput); - if (fileInfo.exists()) - return QUrl(fileInfo.absoluteFilePath()); - return QUrl::fromUserInput(userInput); -} - -QUrl startupUrl() -{ - QUrl ret; - QStringList args(qApp->arguments()); - args.takeFirst(); - Q_FOREACH(const QString& arg, args) { - if (arg.startsWith(QLatin1Char('-'))) - continue; - ret = urlFromUserInput(arg); - if (ret.isValid()) - return ret; - } - return QUrl(QStringLiteral("http://qt-project.org/")); -} - - -#endif // UTIL_H diff --git a/examples/webengine/quicknanobrowser/ContextMenuExtras.qml b/examples/webengine/quicknanobrowser/ContextMenuExtras.qml new file mode 100644 index 000000000..cf54e9ba0 --- /dev/null +++ b/examples/webengine/quicknanobrowser/ContextMenuExtras.qml @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtWebEngine.UIDelegates 1.0 + +VisualItemModel { + MenuItem { + text: "An application specific entry" + onTriggered: console.log("Application specific action triggered") + } + Menu { + title: "Extras Submenu" + MenuItem { + text: "something" + onTriggered: console.log("something triggered") + } + MenuItem { + text: "something else" + enabled: false + } + } +} + diff --git a/examples/webengine/quicknanobrowser/icons/go-next.png b/examples/webengine/quicknanobrowser/icons/go-next.png new file mode 100644 index 000000000..6f3f65d33 Binary files /dev/null and b/examples/webengine/quicknanobrowser/icons/go-next.png differ diff --git a/examples/webengine/quicknanobrowser/icons/go-previous.png b/examples/webengine/quicknanobrowser/icons/go-previous.png new file mode 100644 index 000000000..93be3d1ee Binary files /dev/null and b/examples/webengine/quicknanobrowser/icons/go-previous.png differ diff --git a/examples/webengine/quicknanobrowser/icons/process-stop.png b/examples/webengine/quicknanobrowser/icons/process-stop.png new file mode 100644 index 000000000..b68290bf1 Binary files /dev/null and b/examples/webengine/quicknanobrowser/icons/process-stop.png differ diff --git a/examples/webengine/quicknanobrowser/icons/view-refresh.png b/examples/webengine/quicknanobrowser/icons/view-refresh.png new file mode 100644 index 000000000..cab4d02c7 Binary files /dev/null and b/examples/webengine/quicknanobrowser/icons/view-refresh.png differ diff --git a/examples/webengine/quicknanobrowser/main.cpp b/examples/webengine/quicknanobrowser/main.cpp new file mode 100644 index 000000000..6c2f91de6 --- /dev/null +++ b/examples/webengine/quicknanobrowser/main.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "quickwindow.h" +#ifndef QT_NO_WIDGETS +#include +typedef QApplication Application; +#else +#include +typedef QGuiApplication Application; +#endif +#include + +int main(int argc, char **argv) +{ + Application app(argc, argv); + + // This is currently needed by all QtWebEngine application using the HW accelerated QQuickWebView. + // It enables sharing between the QOpenGLContext of all QQuickWindows of the application. + // We have to do so until we expose a public API for it, or chose enable it by default in Qt 5.3.0. + QOpenGLContext shareContext; + shareContext.create(); + QSGContext::setSharedOpenGLContext(&shareContext); + + ApplicationEngine appEngine; + + return app.exec(); +} diff --git a/examples/webengine/quicknanobrowser/quicknanobrowser.pro b/examples/webengine/quicknanobrowser/quicknanobrowser.pro new file mode 100644 index 000000000..0ea2e60e2 --- /dev/null +++ b/examples/webengine/quicknanobrowser/quicknanobrowser.pro @@ -0,0 +1,24 @@ +TEMPLATE = app +TARGET = quicknanobrowser + +macx: CONFIG -= app_bundle + +HEADERS = quickwindow.h \ + util.h +SOURCES = quickwindow.cpp \ + main.cpp + +OTHER_FILES += ContextMenuExtras.qml \ + quickwindow.qml + +RESOURCES += resources.qrc + +QT += qml quick +QT_PRIVATE += quick-private gui-private core-private + +qtHaveModule(widgets) { + QT += widgets # QApplication is required to get native styling with QtQuickControls +} + +target.path = $$[QT_INSTALL_EXAMPLES]/webengine/quicknanobrowser +INSTALLS += target diff --git a/examples/webengine/quicknanobrowser/quickwindow.cpp b/examples/webengine/quicknanobrowser/quickwindow.cpp new file mode 100644 index 000000000..ec7b6f94a --- /dev/null +++ b/examples/webengine/quicknanobrowser/quickwindow.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "quickwindow.h" + +#include "util.h" + +#include +#include +#include +#include +#include + +class Utils : public QObject { + Q_OBJECT +public: + Utils(QObject* parent = 0) : QObject(parent) { } + Q_INVOKABLE static QUrl fromUserInput(const QString& userInput) { return urlFromUserInput(userInput); } +}; + +#include "quickwindow.moc" + +ApplicationEngine::ApplicationEngine() +{ + rootContext()->setContextProperty("utils", new Utils(this)); + load(QUrl("qrc:/quickwindow.qml")); + QMetaObject::invokeMethod(rootObjects().first(), "load", Q_ARG(QVariant, startupUrl())); +} diff --git a/examples/webengine/quicknanobrowser/quickwindow.h b/examples/webengine/quicknanobrowser/quickwindow.h new file mode 100644 index 000000000..ed25a23b8 --- /dev/null +++ b/examples/webengine/quicknanobrowser/quickwindow.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QUICKWINDOW_H +#define QUICKWINDOW_H + +#include + +class QWebEngineView; + +class ApplicationEngine : public QQmlApplicationEngine { + Q_OBJECT +public: + ApplicationEngine(); +}; + +#endif // QUICKWINDOW_H diff --git a/examples/webengine/quicknanobrowser/quickwindow.qml b/examples/webengine/quicknanobrowser/quickwindow.qml new file mode 100644 index 000000000..183e41f4f --- /dev/null +++ b/examples/webengine/quicknanobrowser/quickwindow.qml @@ -0,0 +1,247 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtWebEngine 1.0 +import QtWebEngine.experimental 1.0 +import QtQuick.Controls 1.0 +import QtQuick.Controls.Styles 1.0 +import QtQuick.Layouts 1.0 +import QtQuick.Window 2.1 +import QtQuick.Controls.Private 1.0 + +ApplicationWindow { + id: browserWindow + function load(url) { currentWebView.url = url } + property Item currentWebView: tabs.currentIndex < tabs.count ? tabs.getTab(tabs.currentIndex).item : null + + property bool isFullScreen: visibility == Window.FullScreen + onIsFullScreenChanged: { + // This is for the case where the system forces us to leave fullscreen. + if (currentWebView) + currentWebView.state = isFullScreen ? "FullScreen" : "" + } + + height: 600 + width: 800 + visible: true + title: currentWebView && currentWebView.title + + // Make sure the Qt.WindowFullscreenButtonHint is set on Mac. + Component.onCompleted: flags = flags | Qt.WindowFullscreenButtonHint + + // Create a styleItem to determine the platform. + // When using style "mac", ToolButtons are not supposed to accept focus. + StyleItem { id: styleItem } + property bool platformIsMac: styleItem.style == "mac" + + + Action { + id: focus + shortcut: "Ctrl+L" + onTriggered: { + addressBar.forceActiveFocus(); + addressBar.selectAll(); + } + } + Action { + shortcut: "Ctrl+R" + onTriggered: { + if (currentWebView) + currentWebView.reload() + } + } + Action { + shortcut: "Ctrl+T" + onTriggered: { + tabs.createEmptyTab() + addressBar.forceActiveFocus(); + addressBar.selectAll(); + } + } + Action { + shortcut: "Ctrl+W" + onTriggered: { + if (tabs.count == 1) + browserWindow.close() + else + tabs.removeTab(tabs.currentIndex) + } + } + + Action { + shortcut: "Escape" + onTriggered: { + if (browserWindow.isFullScreen) + browserWindow.showNormal() + } + } + + toolBar: ToolBar { + id: navigationBar + RowLayout { + anchors.fill: parent; + ToolButton { + id: backButton + iconSource: "icons/go-previous.png" + onClicked: currentWebView.goBack() + enabled: currentWebView && currentWebView.canGoBack + activeFocusOnTab: !browserWindow.platformIsMac + } + ToolButton { + id: forwardButton + iconSource: "icons/go-next.png" + onClicked: currentWebView.goForward() + enabled: currentWebView && currentWebView.canGoForward + activeFocusOnTab: !browserWindow.platformIsMac + } + ToolButton { + id: reloadButton + iconSource: currentWebView && currentWebView.loading ? "icons/process-stop.png" : "icons/view-refresh.png" + onClicked: currentWebView && currentWebView.loading ? currentWebView.stop() : currentWebView.reload() + activeFocusOnTab: !browserWindow.platformIsMac + } + TextField { + id: addressBar + Image { + anchors.verticalCenter: addressBar.verticalCenter; + x: 5 + z: 2 + id: faviconImage + width: 16; height: 16 + source: currentWebView && currentWebView.icon + } + style: TextFieldStyle { + padding { + left: 26; + } + } + focus: true + Layout.fillWidth: true + text: currentWebView && currentWebView.url + onAccepted: currentWebView.url = utils.fromUserInput(text) + } + } + ProgressBar { + id: progressBar + height: 3 + anchors { + left: parent.left + top: parent.bottom + right: parent.right + leftMargin: -parent.leftMargin + rightMargin: -parent.rightMargin + } + style: ProgressBarStyle { + background: Item {} + } + z: -2; + minimumValue: 0 + maximumValue: 100 + value: (currentWebView && currentWebView.loadProgress < 100) ? currentWebView.loadProgress : 0 + } + } + + TabView { + id: tabs + function createEmptyTab() { + var tab = addTab("", tabComponent) + // We must do this first to make sure that tab.active gets set so that tab.item gets instantiated immediately. + tabs.currentIndex = tabs.count - 1 + tab.title = Qt.binding(function() { return tab.item.title }) + return tab + } + + anchors.fill: parent + Component.onCompleted: createEmptyTab() + + Component { + id: tabComponent + WebEngineView { + id: webEngineView + function adoptHandle(viewHandle) { experimental.adoptHandle(viewHandle) } + + focus: true + + states: [ + State { + name: "FullScreen" + PropertyChanges { + target: tabs + frameVisible: false + tabsVisible: false + } + PropertyChanges { + target: navigationBar + visible: false + } + } + ] + + experimental { + isFullScreen: webEngineView.state == "FullScreen" && browserWindow.isFullScreen + onFullScreenRequested: { + if (fullScreen) { + webEngineView.state = "FullScreen" + browserWindow.showFullScreen(); + } else { + webEngineView.state = "" + browserWindow.showNormal(); + } + } + + onNewViewRequested: { + if (request.popup) + print("Warning: Blocked a popup window.") + else if (request.destination == WebEngineView.NewViewInTab) { + var tab = tabs.createEmptyTab() + request.openIn(tab.item) + } else { + var component = Qt.createComponent("quickwindow.qml") + var window = component.createObject() + request.openIn(window.currentWebView) + } + } + extraContextMenuEntriesComponent: ContextMenuExtras {} + } + } + } + } +} diff --git a/examples/webengine/quicknanobrowser/resources.qrc b/examples/webengine/quicknanobrowser/resources.qrc new file mode 100644 index 000000000..1befb4fd1 --- /dev/null +++ b/examples/webengine/quicknanobrowser/resources.qrc @@ -0,0 +1,12 @@ + + + quickwindow.qml + ContextMenuExtras.qml + + + icons/go-next.png + icons/go-previous.png + icons/process-stop.png + icons/view-refresh.png + + diff --git a/examples/webengine/quicknanobrowser/util.h b/examples/webengine/quicknanobrowser/util.h new file mode 100644 index 000000000..ea0ae8b2e --- /dev/null +++ b/examples/webengine/quicknanobrowser/util.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef UTIL_H +#define UTIL_H + +#include +#include +#include +#include + +QUrl urlFromUserInput(const QString& userInput) +{ + QFileInfo fileInfo(userInput); + if (fileInfo.exists()) + return QUrl(fileInfo.absoluteFilePath()); + return QUrl::fromUserInput(userInput); +} + +QUrl startupUrl() +{ + QUrl ret; + QStringList args(qApp->arguments()); + args.takeFirst(); + Q_FOREACH(const QString& arg, args) { + if (arg.startsWith(QLatin1Char('-'))) + continue; + ret = urlFromUserInput(arg); + if (ret.isValid()) + return ret; + } + return QUrl(QStringLiteral("http://qt-project.org/")); +} + + +#endif // UTIL_H diff --git a/examples/webenginewidgets/browser/Info_mac.plist b/examples/webenginewidgets/browser/Info_mac.plist new file mode 100644 index 000000000..87435b2b6 --- /dev/null +++ b/examples/webenginewidgets/browser/Info_mac.plist @@ -0,0 +1,43 @@ + + + + + CFBundleIconFile + @ICON@ + CFBundlePackageType + APPL + CFBundleGetInfoString + Created by Qt/QMake + CFBundleIdentifier + com.trolltech.DemoBrowser + CFBundleSignature + ttxt + CFBundleExecutable + @EXECUTABLE@ + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + html + htm + shtml + xht + xhtml + + CFBundleTypeIconFile + @ICON@ + CFBundleTypeName + HTML Document + CFBundleTypeOSTypes + + HTML + + CFBundleTypeRole + Viewer + + + NOTE + DemoBrowser by Digia Plc and/or its subsidiary(-ies) + + diff --git a/examples/webenginewidgets/browser/addbookmarkdialog.ui b/examples/webenginewidgets/browser/addbookmarkdialog.ui new file mode 100644 index 000000000..3460d7bb8 --- /dev/null +++ b/examples/webenginewidgets/browser/addbookmarkdialog.ui @@ -0,0 +1,98 @@ + + AddBookmarkDialog + + + + 0 + 0 + 240 + 168 + + + + Add Bookmark + + + + + + Type a name for the bookmark, and choose where to keep it. + + + Qt::PlainText + + + true + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 2 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + false + + + + + + + + + buttonBox + accepted() + AddBookmarkDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AddBookmarkDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/examples/webenginewidgets/browser/autosaver.cpp b/examples/webenginewidgets/browser/autosaver.cpp new file mode 100644 index 000000000..a6efa4ca1 --- /dev/null +++ b/examples/webenginewidgets/browser/autosaver.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "autosaver.h" + +#include +#include +#include +#include + +#define AUTOSAVE_IN 1000 * 3 // seconds +#define MAXWAIT 1000 * 15 // seconds + +AutoSaver::AutoSaver(QObject *parent) : QObject(parent) +{ + Q_ASSERT(parent); +} + +AutoSaver::~AutoSaver() +{ + if (m_timer.isActive()) + qWarning() << "AutoSaver: still active when destroyed, changes not saved."; +} + +void AutoSaver::changeOccurred() +{ + if (m_firstChange.isNull()) + m_firstChange.start(); + + if (m_firstChange.elapsed() > MAXWAIT) { + saveIfNeccessary(); + } else { + m_timer.start(AUTOSAVE_IN, this); + } +} + +void AutoSaver::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == m_timer.timerId()) { + saveIfNeccessary(); + } else { + QObject::timerEvent(event); + } +} + +void AutoSaver::saveIfNeccessary() +{ + if (!m_timer.isActive()) + return; + m_timer.stop(); + m_firstChange = QTime(); + if (!QMetaObject::invokeMethod(parent(), "save", Qt::DirectConnection)) { + qWarning() << "AutoSaver: error invoking slot save() on parent"; + } +} diff --git a/examples/webenginewidgets/browser/autosaver.h b/examples/webenginewidgets/browser/autosaver.h new file mode 100644 index 000000000..cf499b066 --- /dev/null +++ b/examples/webenginewidgets/browser/autosaver.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef AUTOSAVER_H +#define AUTOSAVER_H + +#include +#include +#include + +/* + This class will call the save() slot on the parent object when the parent changes. + It will wait several seconds after changed() to combining multiple changes and + prevent continuous writing to disk. + */ +class AutoSaver : public QObject { + +Q_OBJECT + +public: + AutoSaver(QObject *parent); + ~AutoSaver(); + void saveIfNeccessary(); + +public slots: + void changeOccurred(); + +protected: + void timerEvent(QTimerEvent *event); + +private: + QBasicTimer m_timer; + QTime m_firstChange; + +}; + +#endif // AUTOSAVER_H diff --git a/examples/webenginewidgets/browser/bookmarks.cpp b/examples/webenginewidgets/browser/bookmarks.cpp new file mode 100644 index 000000000..adc35bd50 --- /dev/null +++ b/examples/webenginewidgets/browser/bookmarks.cpp @@ -0,0 +1,986 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "bookmarks.h" + +#include "autosaver.h" +#include "browserapplication.h" +#include "history.h" +#include "xbel.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define BOOKMARKBAR "Bookmarks Bar" +#define BOOKMARKMENU "Bookmarks Menu" + +BookmarksManager::BookmarksManager(QObject *parent) + : QObject(parent) + , m_loaded(false) + , m_saveTimer(new AutoSaver(this)) + , m_bookmarkRootNode(0) + , m_bookmarkModel(0) +{ + connect(this, SIGNAL(entryAdded(BookmarkNode*)), + m_saveTimer, SLOT(changeOccurred())); + connect(this, SIGNAL(entryRemoved(BookmarkNode*,int,BookmarkNode*)), + m_saveTimer, SLOT(changeOccurred())); + connect(this, SIGNAL(entryChanged(BookmarkNode*)), + m_saveTimer, SLOT(changeOccurred())); +} + +BookmarksManager::~BookmarksManager() +{ + m_saveTimer->saveIfNeccessary(); +} + +void BookmarksManager::changeExpanded() +{ + m_saveTimer->changeOccurred(); +} + +void BookmarksManager::load() +{ + if (m_loaded) + return; + m_loaded = true; + + QString dir = QStandardPaths::writableLocation(QStandardPaths::DataLocation); + QString bookmarkFile = dir + QLatin1String("/bookmarks.xbel"); + if (!QFile::exists(bookmarkFile)) + bookmarkFile = QLatin1String(":defaultbookmarks.xbel"); + + XbelReader reader; + m_bookmarkRootNode = reader.read(bookmarkFile); + if (reader.error() != QXmlStreamReader::NoError) { + QMessageBox::warning(0, QLatin1String("Loading Bookmark"), + tr("Error when loading bookmarks on line %1, column %2:\n" + "%3").arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString())); + } + + BookmarkNode *toolbar = 0; + BookmarkNode *menu = 0; + QList others; + for (int i = m_bookmarkRootNode->children().count() - 1; i >= 0; --i) { + BookmarkNode *node = m_bookmarkRootNode->children().at(i); + if (node->type() == BookmarkNode::Folder) { + // Automatically convert + if (node->title == tr("Toolbar Bookmarks") && !toolbar) { + node->title = tr(BOOKMARKBAR); + } + if (node->title == tr(BOOKMARKBAR) && !toolbar) { + toolbar = node; + } + + // Automatically convert + if (node->title == tr("Menu") && !menu) { + node->title = tr(BOOKMARKMENU); + } + if (node->title == tr(BOOKMARKMENU) && !menu) { + menu = node; + } + } else { + others.append(node); + } + m_bookmarkRootNode->remove(node); + } + Q_ASSERT(m_bookmarkRootNode->children().count() == 0); + if (!toolbar) { + toolbar = new BookmarkNode(BookmarkNode::Folder, m_bookmarkRootNode); + toolbar->title = tr(BOOKMARKBAR); + } else { + m_bookmarkRootNode->add(toolbar); + } + + if (!menu) { + menu = new BookmarkNode(BookmarkNode::Folder, m_bookmarkRootNode); + menu->title = tr(BOOKMARKMENU); + } else { + m_bookmarkRootNode->add(menu); + } + + for (int i = 0; i < others.count(); ++i) + menu->add(others.at(i)); +} + +void BookmarksManager::save() const +{ + if (!m_loaded) + return; + + XbelWriter writer; + QString dir = QStandardPaths::writableLocation(QStandardPaths::DataLocation); + QString bookmarkFile = dir + QLatin1String("/bookmarks.xbel"); + if (!writer.write(bookmarkFile, m_bookmarkRootNode)) + qWarning() << "BookmarkManager: error saving to" << bookmarkFile; +} + +void BookmarksManager::addBookmark(BookmarkNode *parent, BookmarkNode *node, int row) +{ + if (!m_loaded) + return; + Q_ASSERT(parent); + InsertBookmarksCommand *command = new InsertBookmarksCommand(this, parent, node, row); + m_commands.push(command); +} + +void BookmarksManager::removeBookmark(BookmarkNode *node) +{ + if (!m_loaded) + return; + + Q_ASSERT(node); + BookmarkNode *parent = node->parent(); + int row = parent->children().indexOf(node); + RemoveBookmarksCommand *command = new RemoveBookmarksCommand(this, parent, row); + m_commands.push(command); +} + +void BookmarksManager::setTitle(BookmarkNode *node, const QString &newTitle) +{ + if (!m_loaded) + return; + + Q_ASSERT(node); + ChangeBookmarkCommand *command = new ChangeBookmarkCommand(this, node, newTitle, true); + m_commands.push(command); +} + +void BookmarksManager::setUrl(BookmarkNode *node, const QString &newUrl) +{ + if (!m_loaded) + return; + + Q_ASSERT(node); + ChangeBookmarkCommand *command = new ChangeBookmarkCommand(this, node, newUrl, false); + m_commands.push(command); +} + +BookmarkNode *BookmarksManager::bookmarks() +{ + if (!m_loaded) + load(); + return m_bookmarkRootNode; +} + +BookmarkNode *BookmarksManager::menu() +{ + if (!m_loaded) + load(); + + for (int i = m_bookmarkRootNode->children().count() - 1; i >= 0; --i) { + BookmarkNode *node = m_bookmarkRootNode->children().at(i); + if (node->title == tr(BOOKMARKMENU)) + return node; + } + Q_ASSERT(false); + return 0; +} + +BookmarkNode *BookmarksManager::toolbar() +{ + if (!m_loaded) + load(); + + for (int i = m_bookmarkRootNode->children().count() - 1; i >= 0; --i) { + BookmarkNode *node = m_bookmarkRootNode->children().at(i); + if (node->title == tr(BOOKMARKBAR)) + return node; + } + Q_ASSERT(false); + return 0; +} + +BookmarksModel *BookmarksManager::bookmarksModel() +{ + if (!m_bookmarkModel) + m_bookmarkModel = new BookmarksModel(this, this); + return m_bookmarkModel; +} + +void BookmarksManager::importBookmarks() +{ + QString fileName = QFileDialog::getOpenFileName(0, tr("Open File"), + QString(), + tr("XBEL (*.xbel *.xml)")); + if (fileName.isEmpty()) + return; + + XbelReader reader; + BookmarkNode *importRootNode = reader.read(fileName); + if (reader.error() != QXmlStreamReader::NoError) { + QMessageBox::warning(0, QLatin1String("Loading Bookmark"), + tr("Error when loading bookmarks on line %1, column %2:\n" + "%3").arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString())); + } + + importRootNode->setType(BookmarkNode::Folder); + importRootNode->title = (tr("Imported %1").arg(QDate::currentDate().toString(Qt::SystemLocaleShortDate))); + addBookmark(menu(), importRootNode); +} + +void BookmarksManager::exportBookmarks() +{ + QString fileName = QFileDialog::getSaveFileName(0, tr("Save File"), + tr("%1 Bookmarks.xbel").arg(QCoreApplication::applicationName()), + tr("XBEL (*.xbel *.xml)")); + if (fileName.isEmpty()) + return; + + XbelWriter writer; + if (!writer.write(fileName, m_bookmarkRootNode)) + QMessageBox::critical(0, tr("Export error"), tr("error saving bookmarks")); +} + +RemoveBookmarksCommand::RemoveBookmarksCommand(BookmarksManager *m_bookmarkManagaer, BookmarkNode *parent, int row) + : QUndoCommand(BookmarksManager::tr("Remove Bookmark")) + , m_row(row) + , m_bookmarkManagaer(m_bookmarkManagaer) + , m_node(parent->children().value(row)) + , m_parent(parent) + , m_done(false) +{ +} + +RemoveBookmarksCommand::~RemoveBookmarksCommand() +{ + if (m_done && !m_node->parent()) { + delete m_node; + } +} + +void RemoveBookmarksCommand::undo() +{ + m_parent->add(m_node, m_row); + emit m_bookmarkManagaer->entryAdded(m_node); + m_done = false; +} + +void RemoveBookmarksCommand::redo() +{ + m_parent->remove(m_node); + emit m_bookmarkManagaer->entryRemoved(m_parent, m_row, m_node); + m_done = true; +} + +InsertBookmarksCommand::InsertBookmarksCommand(BookmarksManager *m_bookmarkManagaer, + BookmarkNode *parent, BookmarkNode *node, int row) + : RemoveBookmarksCommand(m_bookmarkManagaer, parent, row) +{ + setText(BookmarksManager::tr("Insert Bookmark")); + m_node = node; +} + +ChangeBookmarkCommand::ChangeBookmarkCommand(BookmarksManager *m_bookmarkManagaer, BookmarkNode *node, + const QString &newValue, bool title) + : QUndoCommand() + , m_bookmarkManagaer(m_bookmarkManagaer) + , m_title(title) + , m_newValue(newValue) + , m_node(node) +{ + if (m_title) { + m_oldValue = m_node->title; + setText(BookmarksManager::tr("Name Change")); + } else { + m_oldValue = m_node->url; + setText(BookmarksManager::tr("Address Change")); + } +} + +void ChangeBookmarkCommand::undo() +{ + if (m_title) + m_node->title = m_oldValue; + else + m_node->url = m_oldValue; + emit m_bookmarkManagaer->entryChanged(m_node); +} + +void ChangeBookmarkCommand::redo() +{ + if (m_title) + m_node->title = m_newValue; + else + m_node->url = m_newValue; + emit m_bookmarkManagaer->entryChanged(m_node); +} + +BookmarksModel::BookmarksModel(BookmarksManager *bookmarkManager, QObject *parent) + : QAbstractItemModel(parent) + , m_endMacro(false) + , m_bookmarksManager(bookmarkManager) +{ + connect(bookmarkManager, SIGNAL(entryAdded(BookmarkNode*)), + this, SLOT(entryAdded(BookmarkNode*))); + connect(bookmarkManager, SIGNAL(entryRemoved(BookmarkNode*,int,BookmarkNode*)), + this, SLOT(entryRemoved(BookmarkNode*,int,BookmarkNode*))); + connect(bookmarkManager, SIGNAL(entryChanged(BookmarkNode*)), + this, SLOT(entryChanged(BookmarkNode*))); +} + +QModelIndex BookmarksModel::index(BookmarkNode *node) const +{ + BookmarkNode *parent = node->parent(); + if (!parent) + return QModelIndex(); + return createIndex(parent->children().indexOf(node), 0, node); +} + +void BookmarksModel::entryAdded(BookmarkNode *item) +{ + Q_ASSERT(item && item->parent()); + int row = item->parent()->children().indexOf(item); + BookmarkNode *parent = item->parent(); + // item was already added so remove beore beginInsertRows is called + parent->remove(item); + beginInsertRows(index(parent), row, row); + parent->add(item, row); + endInsertRows(); +} + +void BookmarksModel::entryRemoved(BookmarkNode *parent, int row, BookmarkNode *item) +{ + // item was already removed, re-add so beginRemoveRows works + parent->add(item, row); + beginRemoveRows(index(parent), row, row); + parent->remove(item); + endRemoveRows(); +} + +void BookmarksModel::entryChanged(BookmarkNode *item) +{ + QModelIndex idx = index(item); + emit dataChanged(idx, idx); +} + +bool BookmarksModel::removeRows(int row, int count, const QModelIndex &parent) +{ + if (row < 0 || count <= 0 || row + count > rowCount(parent)) + return false; + + BookmarkNode *bookmarkNode = node(parent); + for (int i = row + count - 1; i >= row; --i) { + BookmarkNode *node = bookmarkNode->children().at(i); + if (node == m_bookmarksManager->menu() + || node == m_bookmarksManager->toolbar()) + continue; + + m_bookmarksManager->removeBookmark(node); + } + if (m_endMacro) { + m_bookmarksManager->undoRedoStack()->endMacro(); + m_endMacro = false; + } + return true; +} + +QVariant BookmarksModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + switch (section) { + case 0: return tr("Title"); + case 1: return tr("Address"); + } + } + return QAbstractItemModel::headerData(section, orientation, role); +} + +QVariant BookmarksModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.model() != this) + return QVariant(); + + const BookmarkNode *bookmarkNode = node(index); + switch (role) { + case Qt::EditRole: + case Qt::DisplayRole: + if (bookmarkNode->type() == BookmarkNode::Separator) { + switch (index.column()) { + case 0: return QString(50, 0xB7); + case 1: return QString(); + } + } + + switch (index.column()) { + case 0: return bookmarkNode->title; + case 1: return bookmarkNode->url; + } + break; + case BookmarksModel::UrlRole: + return QUrl(bookmarkNode->url); + break; + case BookmarksModel::UrlStringRole: + return bookmarkNode->url; + break; + case BookmarksModel::TypeRole: + return bookmarkNode->type(); + break; + case BookmarksModel::SeparatorRole: + return (bookmarkNode->type() == BookmarkNode::Separator); + break; + case Qt::DecorationRole: + if (index.column() == 0) { + if (bookmarkNode->type() == BookmarkNode::Folder) + return QApplication::style()->standardIcon(QStyle::SP_DirIcon); + return BrowserApplication::instance()->icon(bookmarkNode->url); + } + } + + return QVariant(); +} + +int BookmarksModel::columnCount(const QModelIndex &parent) const +{ + return (parent.column() > 0) ? 0 : 2; +} + +int BookmarksModel::rowCount(const QModelIndex &parent) const +{ + if (parent.column() > 0) + return 0; + + if (!parent.isValid()) + return m_bookmarksManager->bookmarks()->children().count(); + + const BookmarkNode *item = static_cast(parent.internalPointer()); + return item->children().count(); +} + +QModelIndex BookmarksModel::index(int row, int column, const QModelIndex &parent) const +{ + if (row < 0 || column < 0 || row >= rowCount(parent) || column >= columnCount(parent)) + return QModelIndex(); + + // get the parent node + BookmarkNode *parentNode = node(parent); + return createIndex(row, column, parentNode->children().at(row)); +} + +QModelIndex BookmarksModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + BookmarkNode *itemNode = node(index); + BookmarkNode *parentNode = (itemNode ? itemNode->parent() : 0); + if (!parentNode || parentNode == m_bookmarksManager->bookmarks()) + return QModelIndex(); + + // get the parent's row + BookmarkNode *grandParentNode = parentNode->parent(); + int parentRow = grandParentNode->children().indexOf(parentNode); + Q_ASSERT(parentRow >= 0); + return createIndex(parentRow, 0, parentNode); +} + +bool BookmarksModel::hasChildren(const QModelIndex &parent) const +{ + if (!parent.isValid()) + return true; + const BookmarkNode *parentNode = node(parent); + return (parentNode->type() == BookmarkNode::Folder); +} + +Qt::ItemFlags BookmarksModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::NoItemFlags; + + Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; + + BookmarkNode *bookmarkNode = node(index); + + if (bookmarkNode != m_bookmarksManager->menu() + && bookmarkNode != m_bookmarksManager->toolbar()) { + flags |= Qt::ItemIsDragEnabled; + if (bookmarkNode->type() != BookmarkNode::Separator) + flags |= Qt::ItemIsEditable; + } + if (hasChildren(index)) + flags |= Qt::ItemIsDropEnabled; + return flags; +} + +Qt::DropActions BookmarksModel::supportedDropActions () const +{ + return Qt::CopyAction | Qt::MoveAction; +} + +#define MIMETYPE QLatin1String("application/bookmarks.xbel") + +QStringList BookmarksModel::mimeTypes() const +{ + QStringList types; + types << MIMETYPE; + return types; +} + +QMimeData *BookmarksModel::mimeData(const QModelIndexList &indexes) const +{ + QMimeData *mimeData = new QMimeData(); + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + foreach (QModelIndex index, indexes) { + if (index.column() != 0 || !index.isValid()) + continue; + QByteArray encodedData; + QBuffer buffer(&encodedData); + buffer.open(QBuffer::ReadWrite); + XbelWriter writer; + const BookmarkNode *parentNode = node(index); + writer.write(&buffer, parentNode); + stream << encodedData; + } + mimeData->setData(MIMETYPE, data); + return mimeData; +} + +bool BookmarksModel::dropMimeData(const QMimeData *data, + Qt::DropAction action, int row, int column, const QModelIndex &parent) +{ + if (action == Qt::IgnoreAction) + return true; + + if (!data->hasFormat(MIMETYPE) + || column > 0) + return false; + + QByteArray ba = data->data(MIMETYPE); + QDataStream stream(&ba, QIODevice::ReadOnly); + if (stream.atEnd()) + return false; + + QUndoStack *undoStack = m_bookmarksManager->undoRedoStack(); + undoStack->beginMacro(QLatin1String("Move Bookmarks")); + + while (!stream.atEnd()) { + QByteArray encodedData; + stream >> encodedData; + QBuffer buffer(&encodedData); + buffer.open(QBuffer::ReadOnly); + + XbelReader reader; + BookmarkNode *rootNode = reader.read(&buffer); + QList children = rootNode->children(); + for (int i = 0; i < children.count(); ++i) { + BookmarkNode *bookmarkNode = children.at(i); + rootNode->remove(bookmarkNode); + row = qMax(0, row); + BookmarkNode *parentNode = node(parent); + m_bookmarksManager->addBookmark(parentNode, bookmarkNode, row); + m_endMacro = true; + } + delete rootNode; + } + return true; +} + +bool BookmarksModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid() || (flags(index) & Qt::ItemIsEditable) == 0) + return false; + + BookmarkNode *item = node(index); + + switch (role) { + case Qt::EditRole: + case Qt::DisplayRole: + if (index.column() == 0) { + m_bookmarksManager->setTitle(item, value.toString()); + break; + } + if (index.column() == 1) { + m_bookmarksManager->setUrl(item, value.toString()); + break; + } + return false; + case BookmarksModel::UrlRole: + m_bookmarksManager->setUrl(item, value.toUrl().toString()); + break; + case BookmarksModel::UrlStringRole: + m_bookmarksManager->setUrl(item, value.toString()); + break; + default: + break; + return false; + } + + return true; +} + +BookmarkNode *BookmarksModel::node(const QModelIndex &index) const +{ + BookmarkNode *itemNode = static_cast(index.internalPointer()); + if (!itemNode) + return m_bookmarksManager->bookmarks(); + return itemNode; +} + + +AddBookmarkProxyModel::AddBookmarkProxyModel(QObject *parent) + : QSortFilterProxyModel(parent) +{ +} + +int AddBookmarkProxyModel::columnCount(const QModelIndex &parent) const +{ + return qMin(1, QSortFilterProxyModel::columnCount(parent)); +} + +bool AddBookmarkProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + QModelIndex idx = sourceModel()->index(source_row, 0, source_parent); + return sourceModel()->hasChildren(idx); +} + +AddBookmarkDialog::AddBookmarkDialog(const QString &url, const QString &title, QWidget *parent, BookmarksManager *bookmarkManager) + : QDialog(parent) + , m_url(url) + , m_bookmarksManager(bookmarkManager) +{ + setWindowFlags(Qt::Sheet); + if (!m_bookmarksManager) + m_bookmarksManager = BrowserApplication::bookmarksManager(); + setupUi(this); + QTreeView *view = new QTreeView(this); + m_proxyModel = new AddBookmarkProxyModel(this); + BookmarksModel *model = m_bookmarksManager->bookmarksModel(); + m_proxyModel->setSourceModel(model); + view->setModel(m_proxyModel); + view->expandAll(); + view->header()->setStretchLastSection(true); + view->header()->hide(); + view->setItemsExpandable(false); + view->setRootIsDecorated(false); + view->setIndentation(10); + location->setModel(m_proxyModel); + view->show(); + location->setView(view); + BookmarkNode *menu = m_bookmarksManager->menu(); + QModelIndex idx = m_proxyModel->mapFromSource(model->index(menu)); + view->setCurrentIndex(idx); + location->setCurrentIndex(idx.row()); + name->setText(title); +} + +void AddBookmarkDialog::accept() +{ + QModelIndex index = location->view()->currentIndex(); + index = m_proxyModel->mapToSource(index); + if (!index.isValid()) + index = m_bookmarksManager->bookmarksModel()->index(0, 0); + BookmarkNode *parent = m_bookmarksManager->bookmarksModel()->node(index); + BookmarkNode *bookmark = new BookmarkNode(BookmarkNode::Bookmark); + bookmark->url = m_url; + bookmark->title = name->text(); + m_bookmarksManager->addBookmark(parent, bookmark); + QDialog::accept(); +} + +BookmarksMenu::BookmarksMenu(QWidget *parent) + : ModelMenu(parent) + , m_bookmarksManager(0) +{ + connect(this, SIGNAL(activated(QModelIndex)), + this, SLOT(activated(QModelIndex))); + setMaxRows(-1); + setHoverRole(BookmarksModel::UrlStringRole); + setSeparatorRole(BookmarksModel::SeparatorRole); +} + +void BookmarksMenu::activated(const QModelIndex &index) +{ + emit openUrl(index.data(BookmarksModel::UrlRole).toUrl()); +} + +bool BookmarksMenu::prePopulated() +{ + m_bookmarksManager = BrowserApplication::bookmarksManager(); + setModel(m_bookmarksManager->bookmarksModel()); + setRootIndex(m_bookmarksManager->bookmarksModel()->index(1, 0)); + // initial actions + for (int i = 0; i < m_initialActions.count(); ++i) + addAction(m_initialActions.at(i)); + if (!m_initialActions.isEmpty()) + addSeparator(); + createMenu(model()->index(0, 0), 1, this); + return true; +} + +void BookmarksMenu::setInitialActions(QList actions) +{ + m_initialActions = actions; + for (int i = 0; i < m_initialActions.count(); ++i) + addAction(m_initialActions.at(i)); +} + +BookmarksDialog::BookmarksDialog(QWidget *parent, BookmarksManager *manager) + : QDialog(parent) +{ + m_bookmarksManager = manager; + if (!m_bookmarksManager) + m_bookmarksManager = BrowserApplication::bookmarksManager(); + setupUi(this); + + tree->setUniformRowHeights(true); + tree->setSelectionBehavior(QAbstractItemView::SelectRows); + tree->setSelectionMode(QAbstractItemView::ContiguousSelection); + tree->setTextElideMode(Qt::ElideMiddle); + m_bookmarksModel = m_bookmarksManager->bookmarksModel(); + m_proxyModel = new TreeProxyModel(this); + connect(search, SIGNAL(textChanged(QString)), + m_proxyModel, SLOT(setFilterFixedString(QString))); + connect(removeButton, SIGNAL(clicked()), tree, SLOT(removeOne())); + m_proxyModel->setSourceModel(m_bookmarksModel); + tree->setModel(m_proxyModel); + tree->setDragDropMode(QAbstractItemView::InternalMove); + tree->setExpanded(m_proxyModel->index(0, 0), true); + tree->setAlternatingRowColors(true); + QFontMetrics fm(font()); + int header = fm.width(QLatin1Char('m')) * 40; + tree->header()->resizeSection(0, header); + tree->header()->setStretchLastSection(true); + connect(tree, SIGNAL(activated(QModelIndex)), + this, SLOT(open())); + tree->setContextMenuPolicy(Qt::CustomContextMenu); + connect(tree, SIGNAL(customContextMenuRequested(QPoint)), + this, SLOT(customContextMenuRequested(QPoint))); + connect(addFolderButton, SIGNAL(clicked()), + this, SLOT(newFolder())); + expandNodes(m_bookmarksManager->bookmarks()); + setAttribute(Qt::WA_DeleteOnClose); +} + +BookmarksDialog::~BookmarksDialog() +{ + if (saveExpandedNodes(tree->rootIndex())) + m_bookmarksManager->changeExpanded(); +} + +bool BookmarksDialog::saveExpandedNodes(const QModelIndex &parent) +{ + bool changed = false; + for (int i = 0; i < m_proxyModel->rowCount(parent); ++i) { + QModelIndex child = m_proxyModel->index(i, 0, parent); + QModelIndex sourceIndex = m_proxyModel->mapToSource(child); + BookmarkNode *childNode = m_bookmarksModel->node(sourceIndex); + bool wasExpanded = childNode->expanded; + if (tree->isExpanded(child)) { + childNode->expanded = true; + changed |= saveExpandedNodes(child); + } else { + childNode->expanded = false; + } + changed |= (wasExpanded != childNode->expanded); + } + return changed; +} + +void BookmarksDialog::expandNodes(BookmarkNode *node) +{ + for (int i = 0; i < node->children().count(); ++i) { + BookmarkNode *childNode = node->children()[i]; + if (childNode->expanded) { + QModelIndex idx = m_bookmarksModel->index(childNode); + idx = m_proxyModel->mapFromSource(idx); + tree->setExpanded(idx, true); + expandNodes(childNode); + } + } +} + +void BookmarksDialog::customContextMenuRequested(const QPoint &pos) +{ + QMenu menu; + QModelIndex index = tree->indexAt(pos); + index = index.sibling(index.row(), 0); + if (index.isValid() && !tree->model()->hasChildren(index)) { + menu.addAction(tr("Open"), this, SLOT(open())); + menu.addSeparator(); + } + menu.addAction(tr("Delete"), tree, SLOT(removeOne())); + menu.exec(QCursor::pos()); +} + +void BookmarksDialog::open() +{ + QModelIndex index = tree->currentIndex(); + if (!index.parent().isValid()) + return; + emit openUrl(index.sibling(index.row(), 1).data(BookmarksModel::UrlRole).toUrl()); +} + +void BookmarksDialog::newFolder() +{ + QModelIndex currentIndex = tree->currentIndex(); + QModelIndex idx = currentIndex; + if (idx.isValid() && !idx.model()->hasChildren(idx)) + idx = idx.parent(); + if (!idx.isValid()) + idx = tree->rootIndex(); + idx = m_proxyModel->mapToSource(idx); + BookmarkNode *parent = m_bookmarksManager->bookmarksModel()->node(idx); + BookmarkNode *node = new BookmarkNode(BookmarkNode::Folder); + node->title = tr("New Folder"); + m_bookmarksManager->addBookmark(parent, node, currentIndex.row() + 1); +} + +BookmarksToolBar::BookmarksToolBar(BookmarksModel *model, QWidget *parent) + : QToolBar(tr("Bookmark"), parent) + , m_bookmarksModel(model) +{ + connect(this, SIGNAL(actionTriggered(QAction*)), this, SLOT(triggered(QAction*))); + setRootIndex(model->index(0, 0)); + connect(m_bookmarksModel, SIGNAL(modelReset()), this, SLOT(build())); + connect(m_bookmarksModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(build())); + connect(m_bookmarksModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(build())); + connect(m_bookmarksModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(build())); + setAcceptDrops(true); +} + +void BookmarksToolBar::dragEnterEvent(QDragEnterEvent *event) +{ + const QMimeData *mimeData = event->mimeData(); + if (mimeData->hasUrls()) + event->acceptProposedAction(); + QToolBar::dragEnterEvent(event); +} + +void BookmarksToolBar::dropEvent(QDropEvent *event) +{ + const QMimeData *mimeData = event->mimeData(); + if (mimeData->hasUrls() && mimeData->hasText()) { + QList urls = mimeData->urls(); + QAction *action = actionAt(event->pos()); + QString dropText; + if (action) + dropText = action->text(); + int row = -1; + QModelIndex parentIndex = m_root; + for (int i = 0; i < m_bookmarksModel->rowCount(m_root); ++i) { + QModelIndex idx = m_bookmarksModel->index(i, 0, m_root); + QString title = idx.data().toString(); + if (title == dropText) { + row = i; + if (m_bookmarksModel->hasChildren(idx)) { + parentIndex = idx; + row = -1; + } + break; + } + } + BookmarkNode *bookmark = new BookmarkNode(BookmarkNode::Bookmark); + bookmark->url = urls.at(0).toString(); + bookmark->title = mimeData->text(); + + BookmarkNode *parent = m_bookmarksModel->node(parentIndex); + BookmarksManager *bookmarksManager = m_bookmarksModel->bookmarksManager(); + bookmarksManager->addBookmark(parent, bookmark, row); + event->acceptProposedAction(); + } + QToolBar::dropEvent(event); +} + + +void BookmarksToolBar::setRootIndex(const QModelIndex &index) +{ + m_root = index; + build(); +} + +QModelIndex BookmarksToolBar::rootIndex() const +{ + return m_root; +} + +void BookmarksToolBar::build() +{ + clear(); + for (int i = 0; i < m_bookmarksModel->rowCount(m_root); ++i) { + QModelIndex idx = m_bookmarksModel->index(i, 0, m_root); + if (m_bookmarksModel->hasChildren(idx)) { + QToolButton *button = new QToolButton(this); + button->setPopupMode(QToolButton::InstantPopup); + button->setArrowType(Qt::DownArrow); + button->setText(idx.data().toString()); + ModelMenu *menu = new ModelMenu(this); + connect(menu, SIGNAL(activated(QModelIndex)), + this, SLOT(activated(QModelIndex))); + menu->setModel(m_bookmarksModel); + menu->setRootIndex(idx); + menu->addAction(new QAction(menu)); + button->setMenu(menu); + button->setToolButtonStyle(Qt::ToolButtonTextOnly); + QAction *a = addWidget(button); + a->setText(idx.data().toString()); + } else { + QAction *action = addAction(idx.data().toString()); + action->setData(idx.data(BookmarksModel::UrlRole)); + } + } +} + +void BookmarksToolBar::triggered(QAction *action) +{ + QVariant v = action->data(); + if (v.canConvert()) { + emit openUrl(v.toUrl()); + } +} + +void BookmarksToolBar::activated(const QModelIndex &index) +{ + emit openUrl(index.data(BookmarksModel::UrlRole).toUrl()); +} diff --git a/examples/webenginewidgets/browser/bookmarks.h b/examples/webenginewidgets/browser/bookmarks.h new file mode 100644 index 000000000..be29666df --- /dev/null +++ b/examples/webenginewidgets/browser/bookmarks.h @@ -0,0 +1,309 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BOOKMARKS_H +#define BOOKMARKS_H + +#include +#include + +#include + +/*! + Bookmark manager, owner of the bookmarks, loads, saves and basic tasks + */ +class AutoSaver; +class BookmarkNode; +class BookmarksModel; +class BookmarksManager : public QObject +{ + Q_OBJECT + +signals: + void entryAdded(BookmarkNode *item); + void entryRemoved(BookmarkNode *parent, int row, BookmarkNode *item); + void entryChanged(BookmarkNode *item); + +public: + BookmarksManager(QObject *parent = 0); + ~BookmarksManager(); + + void addBookmark(BookmarkNode *parent, BookmarkNode *node, int row = -1); + void removeBookmark(BookmarkNode *node); + void setTitle(BookmarkNode *node, const QString &newTitle); + void setUrl(BookmarkNode *node, const QString &newUrl); + void changeExpanded(); + + BookmarkNode *bookmarks(); + BookmarkNode *menu(); + BookmarkNode *toolbar(); + + BookmarksModel *bookmarksModel(); + QUndoStack *undoRedoStack() { return &m_commands; }; + +public slots: + void importBookmarks(); + void exportBookmarks(); + +private slots: + void save() const; + +private: + void load(); + + bool m_loaded; + AutoSaver *m_saveTimer; + BookmarkNode *m_bookmarkRootNode; + BookmarksModel *m_bookmarkModel; + QUndoStack m_commands; + + friend class RemoveBookmarksCommand; + friend class ChangeBookmarkCommand; +}; + +class RemoveBookmarksCommand : public QUndoCommand +{ + +public: + RemoveBookmarksCommand(BookmarksManager *m_bookmarkManagaer, BookmarkNode *parent, int row); + ~RemoveBookmarksCommand(); + void undo(); + void redo(); + +protected: + int m_row; + BookmarksManager *m_bookmarkManagaer; + BookmarkNode *m_node; + BookmarkNode *m_parent; + bool m_done; +}; + +class InsertBookmarksCommand : public RemoveBookmarksCommand +{ + +public: + InsertBookmarksCommand(BookmarksManager *m_bookmarkManagaer, + BookmarkNode *parent, BookmarkNode *node, int row); + void undo() { RemoveBookmarksCommand::redo(); } + void redo() { RemoveBookmarksCommand::undo(); } + +}; + +class ChangeBookmarkCommand : public QUndoCommand +{ + +public: + ChangeBookmarkCommand(BookmarksManager *m_bookmarkManagaer, + BookmarkNode *node, const QString &newValue, bool title); + void undo(); + void redo(); + +private: + BookmarksManager *m_bookmarkManagaer; + bool m_title; + QString m_oldValue; + QString m_newValue; + BookmarkNode *m_node; +}; + +/*! + BookmarksModel is a QAbstractItemModel wrapper around the BookmarkManager + */ +class BookmarksModel : public QAbstractItemModel +{ + Q_OBJECT + +public slots: + void entryAdded(BookmarkNode *item); + void entryRemoved(BookmarkNode *parent, int row, BookmarkNode *item); + void entryChanged(BookmarkNode *item); + +public: + enum Roles { + TypeRole = Qt::UserRole + 1, + UrlRole = Qt::UserRole + 2, + UrlStringRole = Qt::UserRole + 3, + SeparatorRole = Qt::UserRole + 4 + }; + + BookmarksModel(BookmarksManager *bookmarkManager, QObject *parent = 0); + inline BookmarksManager *bookmarksManager() const { return m_bookmarksManager; } + + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + QModelIndex index(int, int, const QModelIndex& = QModelIndex()) const; + QModelIndex parent(const QModelIndex& index= QModelIndex()) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + Qt::DropActions supportedDropActions () const; + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + QMimeData *mimeData(const QModelIndexList &indexes) const; + QStringList mimeTypes() const; + bool dropMimeData(const QMimeData *data, + Qt::DropAction action, int row, int column, const QModelIndex &parent); + bool hasChildren(const QModelIndex &parent = QModelIndex()) const; + + BookmarkNode *node(const QModelIndex &index) const; + QModelIndex index(BookmarkNode *node) const; + +private: + + bool m_endMacro; + BookmarksManager *m_bookmarksManager; +}; + +// Menu that is dynamically populated from the bookmarks +#include "modelmenu.h" +class BookmarksMenu : public ModelMenu +{ + Q_OBJECT + +signals: + void openUrl(const QUrl &url); + +public: + BookmarksMenu(QWidget *parent = 0); + void setInitialActions(QList actions); + +protected: + bool prePopulated(); + +private slots: + void activated(const QModelIndex &index); + +private: + BookmarksManager *m_bookmarksManager; + QList m_initialActions; +}; + +/* + Proxy model that filters out the bookmarks so only the folders + are left behind. Used in the add bookmark dialog combobox. + */ +#include +class AddBookmarkProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + AddBookmarkProxyModel(QObject * parent = 0); + int columnCount(const QModelIndex & parent = QModelIndex()) const; + +protected: + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; +}; + +/*! + Add bookmark dialog + */ +#include "ui_addbookmarkdialog.h" +class AddBookmarkDialog : public QDialog, public Ui_AddBookmarkDialog +{ + Q_OBJECT + +public: + AddBookmarkDialog(const QString &url, const QString &title, QWidget *parent = 0, BookmarksManager *bookmarkManager = 0); + +private slots: + void accept(); + +private: + QString m_url; + BookmarksManager *m_bookmarksManager; + AddBookmarkProxyModel *m_proxyModel; +}; + +#include "ui_bookmarks.h" +class TreeProxyModel; +class BookmarksDialog : public QDialog, public Ui_BookmarksDialog +{ + Q_OBJECT + +signals: + void openUrl(const QUrl &url); + +public: + BookmarksDialog(QWidget *parent = 0, BookmarksManager *manager = 0); + ~BookmarksDialog(); + +private slots: + void customContextMenuRequested(const QPoint &pos); + void open(); + void newFolder(); + +private: + void expandNodes(BookmarkNode *node); + bool saveExpandedNodes(const QModelIndex &parent); + + BookmarksManager *m_bookmarksManager; + BookmarksModel *m_bookmarksModel; + TreeProxyModel *m_proxyModel; +}; + +#include +class BookmarksToolBar : public QToolBar +{ + Q_OBJECT + +signals: + void openUrl(const QUrl &url); + +public: + BookmarksToolBar(BookmarksModel *model, QWidget *parent = 0); + void setRootIndex(const QModelIndex &index); + QModelIndex rootIndex() const; + +protected: + void dragEnterEvent(QDragEnterEvent *event); + void dropEvent(QDropEvent *event); + +private slots: + void triggered(QAction *action); + void activated(const QModelIndex &index); + void build(); + +private: + BookmarksModel *m_bookmarksModel; + QPersistentModelIndex m_root; +}; + +#endif // BOOKMARKS_H diff --git a/examples/webenginewidgets/browser/bookmarks.ui b/examples/webenginewidgets/browser/bookmarks.ui new file mode 100644 index 000000000..c893e941d --- /dev/null +++ b/examples/webenginewidgets/browser/bookmarks.ui @@ -0,0 +1,106 @@ + + BookmarksDialog + + + + 0 + 0 + 758 + 450 + + + + Bookmarks + + + + + + Qt::Horizontal + + + + 252 + 20 + + + + + + + + + + + + + + + + &Remove + + + + + + + Add Folder + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + QDialogButtonBox::Ok + + + + + + + + + + SearchLineEdit + QLineEdit +
searchlineedit.h
+
+ + EditTreeView + QTreeView +
edittreeview.h
+
+
+ + + + buttonBox + accepted() + BookmarksDialog + accept() + + + 472 + 329 + + + 461 + 356 + + + + +
diff --git a/examples/webenginewidgets/browser/browser.icns b/examples/webenginewidgets/browser/browser.icns new file mode 100644 index 000000000..f591ae48a Binary files /dev/null and b/examples/webenginewidgets/browser/browser.icns differ diff --git a/examples/webenginewidgets/browser/browser.ico b/examples/webenginewidgets/browser/browser.ico new file mode 100644 index 000000000..7f9be934d Binary files /dev/null and b/examples/webenginewidgets/browser/browser.ico differ diff --git a/examples/webenginewidgets/browser/browser.pro b/examples/webenginewidgets/browser/browser.pro new file mode 100644 index 000000000..b40c745b8 --- /dev/null +++ b/examples/webenginewidgets/browser/browser.pro @@ -0,0 +1,103 @@ +TEMPLATE = app +TARGET = browser +QT += webenginewidgets network widgets printsupport + +macx: CONFIG -= app_bundle + +qtHaveModule(uitools):!embedded: QT += uitools +else: DEFINES += QT_NO_UITOOLS + +FORMS += \ + addbookmarkdialog.ui \ + bookmarks.ui \ + cookies.ui \ + cookiesexceptions.ui \ + downloaditem.ui \ + downloads.ui \ + history.ui \ + passworddialog.ui \ + proxy.ui \ + settings.ui + +HEADERS += \ + autosaver.h \ + bookmarks.h \ + browserapplication.h \ + browsermainwindow.h \ + chasewidget.h \ + downloadmanager.h \ + edittableview.h \ + edittreeview.h \ + history.h \ + modelmenu.h \ + searchlineedit.h \ + settings.h \ + squeezelabel.h \ + tabwidget.h \ + toolbarsearch.h \ + urllineedit.h \ + webview.h \ + xbel.h + +SOURCES += \ + autosaver.cpp \ + bookmarks.cpp \ + browserapplication.cpp \ + browsermainwindow.cpp \ + chasewidget.cpp \ + downloadmanager.cpp \ + edittableview.cpp \ + edittreeview.cpp \ + history.cpp \ + modelmenu.cpp \ + searchlineedit.cpp \ + settings.cpp \ + squeezelabel.cpp \ + tabwidget.cpp \ + toolbarsearch.cpp \ + urllineedit.cpp \ + webview.cpp \ + xbel.cpp \ + main.cpp + +RESOURCES += data/data.qrc htmls/htmls.qrc + +contains(DEFINES, QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) { + HEADERS += cookiejar.h networkaccessmanager.h + SOURCES += cookiejar.cpp networkaccessmanager.cpp +} + +build_all:!build_pass { + CONFIG -= build_all + CONFIG += release +} + +win32 { + RC_FILE = browser.rc +} + +mac { + ICON = browser.icns + QMAKE_INFO_PLIST = Info_mac.plist + TARGET = Browser + + # No 64-bit Flash on Mac, so build the browser 32-bit + contains(QT_CONFIG, x86) { + CONFIG -= x86_64 + CONFIG += x86 + } + contains(QT_CONFIG, ppc) { + CONFIG -= ppc64 + CONFIG += ppc + } +} + +wince*: { + DEPLOYMENT_PLUGIN += qjpeg qgif +} + +EXAMPLE_FILES = Info_mac.plist browser.icns browser.ico browser.rc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/browser +INSTALLS += target diff --git a/examples/webenginewidgets/browser/browser.rc b/examples/webenginewidgets/browser/browser.rc new file mode 100644 index 000000000..39e17e973 --- /dev/null +++ b/examples/webenginewidgets/browser/browser.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "browser.ico" diff --git a/examples/webenginewidgets/browser/browserapplication.cpp b/examples/webenginewidgets/browser/browserapplication.cpp new file mode 100644 index 000000000..da96b65b9 --- /dev/null +++ b/examples/webenginewidgets/browser/browserapplication.cpp @@ -0,0 +1,472 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "browserapplication.h" + +#include "bookmarks.h" +#include "browsermainwindow.h" +#include "cookiejar.h" +#include "downloadmanager.h" +#include "history.h" +#include "networkaccessmanager.h" +#include "tabwidget.h" +#include "webview.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +DownloadManager *BrowserApplication::s_downloadManager = 0; +HistoryManager *BrowserApplication::s_historyManager = 0; +NetworkAccessManager *BrowserApplication::s_networkAccessManager = 0; +BookmarksManager *BrowserApplication::s_bookmarksManager = 0; + +BrowserApplication::BrowserApplication(int &argc, char **argv) + : QApplication(argc, argv) + , m_localServer(0) +{ + QCoreApplication::setOrganizationName(QLatin1String("Qt")); + QCoreApplication::setApplicationName(QLatin1String("demobrowser")); + QCoreApplication::setApplicationVersion(QLatin1String("0.1")); +#ifdef Q_WS_QWS + // Use a different server name for QWS so we can run an X11 + // browser and a QWS browser in parallel on the same machine for + // debugging + QString serverName = QCoreApplication::applicationName() + QLatin1String("_qws"); +#else + QString serverName = QCoreApplication::applicationName(); +#endif + QLocalSocket socket; + socket.connectToServer(serverName); + if (socket.waitForConnected(500)) { + QTextStream stream(&socket); + QStringList args = QCoreApplication::arguments(); + if (args.count() > 1) + stream << args.last(); + else + stream << QString(); + stream.flush(); + socket.waitForBytesWritten(); + return; + } + +#if defined(Q_WS_MAC) + QApplication::setQuitOnLastWindowClosed(false); +#else + QApplication::setQuitOnLastWindowClosed(true); +#endif + + m_localServer = new QLocalServer(this); + connect(m_localServer, SIGNAL(newConnection()), + this, SLOT(newLocalSocketConnection())); + if (!m_localServer->listen(serverName)) { + if (m_localServer->serverError() == QAbstractSocket::AddressInUseError + && QFile::exists(m_localServer->serverName())) { + QFile::remove(m_localServer->serverName()); + m_localServer->listen(serverName); + } + } + +#ifndef QT_NO_OPENSSL + if (!QSslSocket::supportsSsl()) { + QMessageBox::information(0, "Demo Browser", + "This system does not support OpenSSL. SSL websites will not be available."); + } +#endif + + QDesktopServices::setUrlHandler(QLatin1String("http"), this, "openUrl"); + QString localSysName = QLocale::system().name(); + + installTranslator(QLatin1String("qt_") + localSysName); + + QSettings settings; + settings.beginGroup(QLatin1String("sessions")); + m_lastSession = settings.value(QLatin1String("lastSession")).toByteArray(); + settings.endGroup(); + +#if defined(Q_WS_MAC) + connect(this, SIGNAL(lastWindowClosed()), + this, SLOT(lastWindowClosed())); +#endif + + QTimer::singleShot(0, this, SLOT(postLaunch())); +} + +BrowserApplication::~BrowserApplication() +{ + delete s_downloadManager; + for (int i = 0; i < m_mainWindows.size(); ++i) { + BrowserMainWindow *window = m_mainWindows.at(i); + delete window; + } + delete s_networkAccessManager; + delete s_bookmarksManager; +} + +#if defined(Q_WS_MAC) +void BrowserApplication::lastWindowClosed() +{ + clean(); + BrowserMainWindow *mw = new BrowserMainWindow; + mw->slotHome(); + m_mainWindows.prepend(mw); +} +#endif + +BrowserApplication *BrowserApplication::instance() +{ + return (static_cast(QCoreApplication::instance())); +} + +#if defined(Q_WS_MAC) +#include +void BrowserApplication::quitBrowser() +{ + clean(); + int tabCount = 0; + for (int i = 0; i < m_mainWindows.count(); ++i) { + tabCount =+ m_mainWindows.at(i)->tabWidget()->count(); + } + + if (tabCount > 1) { + int ret = QMessageBox::warning(mainWindow(), QString(), + tr("There are %1 windows and %2 tabs open\n" + "Do you want to quit anyway?").arg(m_mainWindows.count()).arg(tabCount), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No); + if (ret == QMessageBox::No) + return; + } + + exit(0); +} +#endif + +/*! + Any actions that can be delayed until the window is visible + */ +void BrowserApplication::postLaunch() +{ +#if defined(QWEBENGINESETTINGS) + QString directory = QStandardPaths::writableLocation(QStandardPaths::DataLocation); + if (directory.isEmpty()) + directory = QDir::homePath() + QLatin1String("/.") + QCoreApplication::applicationName(); + QWebEngineSettings::setIconDatabasePath(directory); + QWebEngineSettings::setOfflineStoragePath(directory); +#endif + + setWindowIcon(QIcon(QLatin1String(":browser.svg"))); + + loadSettings(); + + // newMainWindow() needs to be called in main() for this to happen + if (m_mainWindows.count() > 0) { + QStringList args = QCoreApplication::arguments(); + if (args.count() > 1) + mainWindow()->loadPage(args.last()); + else + mainWindow()->slotHome(); + } + BrowserApplication::historyManager(); +} + +void BrowserApplication::loadSettings() +{ +#if defined(QWEBENGINESETTINGS) + QSettings settings; + settings.beginGroup(QLatin1String("websettings")); + + QWebEngineSettings *defaultSettings = QWebEngineSettings::globalSettings(); + QString standardFontFamily = defaultSettings->fontFamily(QWebEngineSettings::StandardFont); + int standardFontSize = defaultSettings->fontSize(QWebEngineSettings::DefaultFontSize); + QFont standardFont = QFont(standardFontFamily, standardFontSize); + standardFont = qvariant_cast(settings.value(QLatin1String("standardFont"), standardFont)); + defaultSettings->setFontFamily(QWebEngineSettings::StandardFont, standardFont.family()); + defaultSettings->setFontSize(QWebEngineSettings::DefaultFontSize, standardFont.pointSize()); + + QString fixedFontFamily = defaultSettings->fontFamily(QWebEngineSettings::FixedFont); + int fixedFontSize = defaultSettings->fontSize(QWebEngineSettings::DefaultFixedFontSize); + QFont fixedFont = QFont(fixedFontFamily, fixedFontSize); + fixedFont = qvariant_cast(settings.value(QLatin1String("fixedFont"), fixedFont)); + defaultSettings->setFontFamily(QWebEngineSettings::FixedFont, fixedFont.family()); + defaultSettings->setFontSize(QWebEngineSettings::DefaultFixedFontSize, fixedFont.pointSize()); + + defaultSettings->setAttribute(QWebEngineSettings::JavascriptEnabled, settings.value(QLatin1String("enableJavascript"), true).toBool()); + defaultSettings->setAttribute(QWebEngineSettings::PluginsEnabled, settings.value(QLatin1String("enablePlugins"), true).toBool()); + + QUrl url = settings.value(QLatin1String("userStyleSheet")).toUrl(); + defaultSettings->setUserStyleSheetUrl(url); + + defaultSettings->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, true); + + settings.endGroup(); +#endif +} + +QList BrowserApplication::mainWindows() +{ + clean(); + QList list; + for (int i = 0; i < m_mainWindows.count(); ++i) + list.append(m_mainWindows.at(i)); + return list; +} + +void BrowserApplication::clean() +{ + // cleanup any deleted main windows first + for (int i = m_mainWindows.count() - 1; i >= 0; --i) + if (m_mainWindows.at(i).isNull()) + m_mainWindows.removeAt(i); +} + +void BrowserApplication::saveSession() +{ +#if defined(QWEBENGINESETTINGS) + QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); + if (globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) + return; +#endif + + clean(); + + QSettings settings; + settings.beginGroup(QLatin1String("sessions")); + + QByteArray data; + QBuffer buffer(&data); + QDataStream stream(&buffer); + buffer.open(QIODevice::ReadWrite); + + stream << m_mainWindows.count(); + for (int i = 0; i < m_mainWindows.count(); ++i) + stream << m_mainWindows.at(i)->saveState(); + settings.setValue(QLatin1String("lastSession"), data); + settings.endGroup(); +} + +bool BrowserApplication::canRestoreSession() const +{ + return !m_lastSession.isEmpty(); +} + +void BrowserApplication::restoreLastSession() +{ + QList windows; + QBuffer buffer(&m_lastSession); + QDataStream stream(&buffer); + buffer.open(QIODevice::ReadOnly); + int windowCount; + stream >> windowCount; + for (int i = 0; i < windowCount; ++i) { + QByteArray windowState; + stream >> windowState; + windows.append(windowState); + } + for (int i = 0; i < windows.count(); ++i) { + BrowserMainWindow *newWindow = 0; + if (m_mainWindows.count() == 1 + && mainWindow()->tabWidget()->count() == 1 + && mainWindow()->currentTab()->url() == QUrl()) { + newWindow = mainWindow(); + } else { + newWindow = newMainWindow(); + } + newWindow->restoreState(windows.at(i)); + } +} + +bool BrowserApplication::isTheOnlyBrowser() const +{ + return (m_localServer != 0); +} + +void BrowserApplication::installTranslator(const QString &name) +{ + QTranslator *translator = new QTranslator(this); + translator->load(name, QLibraryInfo::location(QLibraryInfo::TranslationsPath)); + QApplication::installTranslator(translator); +} + +#if defined(Q_WS_MAC) +bool BrowserApplication::event(QEvent* event) +{ + switch (event->type()) { + case QEvent::ApplicationActivate: { + clean(); + if (!m_mainWindows.isEmpty()) { + BrowserMainWindow *mw = mainWindow(); + if (mw && !mw->isMinimized()) { + mainWindow()->show(); + } + return true; + } + } + case QEvent::FileOpen: + if (!m_mainWindows.isEmpty()) { + mainWindow()->loadPage(static_cast(event)->file()); + return true; + } + default: + break; + } + return QApplication::event(event); +} +#endif + +void BrowserApplication::openUrl(const QUrl &url) +{ + mainWindow()->loadPage(url.toString()); +} + +BrowserMainWindow *BrowserApplication::newMainWindow() +{ + BrowserMainWindow *browser = new BrowserMainWindow(); + m_mainWindows.prepend(browser); + browser->show(); + return browser; +} + +BrowserMainWindow *BrowserApplication::mainWindow() +{ + clean(); + if (m_mainWindows.isEmpty()) + newMainWindow(); + return m_mainWindows[0]; +} + +void BrowserApplication::newLocalSocketConnection() +{ + QLocalSocket *socket = m_localServer->nextPendingConnection(); + if (!socket) + return; + socket->waitForReadyRead(1000); + QTextStream stream(socket); + QString url; + stream >> url; + if (!url.isEmpty()) { + QSettings settings; + settings.beginGroup(QLatin1String("general")); + int openLinksIn = settings.value(QLatin1String("openLinksIn"), 0).toInt(); + settings.endGroup(); + if (openLinksIn == 1) + newMainWindow(); + else + mainWindow()->tabWidget()->newTab(); + openUrl(url); + } + delete socket; + mainWindow()->raise(); + mainWindow()->activateWindow(); +} + +CookieJar *BrowserApplication::cookieJar() +{ +#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) + return (CookieJar*)networkAccessManager()->cookieJar(); +#else + return 0; +#endif +} + +DownloadManager *BrowserApplication::downloadManager() +{ + if (!s_downloadManager) { + s_downloadManager = new DownloadManager(); + } + return s_downloadManager; +} + +NetworkAccessManager *BrowserApplication::networkAccessManager() +{ +#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) + if (!s_networkAccessManager) { + s_networkAccessManager = new NetworkAccessManager(); + s_networkAccessManager->setCookieJar(new CookieJar); + } + return s_networkAccessManager; +#else + return 0; +#endif +} + +HistoryManager *BrowserApplication::historyManager() +{ + if (!s_historyManager) + s_historyManager = new HistoryManager(); + return s_historyManager; +} + +BookmarksManager *BrowserApplication::bookmarksManager() +{ + if (!s_bookmarksManager) { + s_bookmarksManager = new BookmarksManager; + } + return s_bookmarksManager; +} + +QIcon BrowserApplication::icon(const QUrl &url) const +{ +#if defined(QWEBENGINESETTINGS) + QIcon icon = QWebEngineSettings::iconForUrl(url); + if (!icon.isNull()) + return icon.pixmap(16, 16); +#endif + if (m_defaultIcon.isNull()) + m_defaultIcon = QIcon(QLatin1String(":defaulticon.png")); + return m_defaultIcon.pixmap(16, 16); +} diff --git a/examples/webenginewidgets/browser/browserapplication.h b/examples/webenginewidgets/browser/browserapplication.h new file mode 100644 index 000000000..b17f1cea5 --- /dev/null +++ b/examples/webenginewidgets/browser/browserapplication.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BROWSERAPPLICATION_H +#define BROWSERAPPLICATION_H + +#include + +#include +#include + +#include + +QT_BEGIN_NAMESPACE +class QLocalServer; +QT_END_NAMESPACE + +class BookmarksManager; +class BrowserMainWindow; +class CookieJar; +class DownloadManager; +class HistoryManager; +class NetworkAccessManager; +class BrowserApplication : public QApplication +{ + Q_OBJECT + +public: + BrowserApplication(int &argc, char **argv); + ~BrowserApplication(); + static BrowserApplication *instance(); + void loadSettings(); + + bool isTheOnlyBrowser() const; + BrowserMainWindow *mainWindow(); + QList mainWindows(); + QIcon icon(const QUrl &url) const; + + void saveSession(); + bool canRestoreSession() const; + + static HistoryManager *historyManager(); + static CookieJar *cookieJar(); + static DownloadManager *downloadManager(); + static NetworkAccessManager *networkAccessManager(); + static BookmarksManager *bookmarksManager(); + +#if defined(Q_WS_MAC) + bool event(QEvent *event); +#endif + +public slots: + BrowserMainWindow *newMainWindow(); + void restoreLastSession(); +#if defined(Q_WS_MAC) + void lastWindowClosed(); + void quitBrowser(); +#endif + +private slots: + void postLaunch(); + void openUrl(const QUrl &url); + void newLocalSocketConnection(); + +private: + void clean(); + void installTranslator(const QString &name); + + static HistoryManager *s_historyManager; + static DownloadManager *s_downloadManager; + static NetworkAccessManager *s_networkAccessManager; + static BookmarksManager *s_bookmarksManager; + + QList > m_mainWindows; + QLocalServer *m_localServer; + QByteArray m_lastSession; + mutable QIcon m_defaultIcon; +}; + +#endif // BROWSERAPPLICATION_H diff --git a/examples/webenginewidgets/browser/browsermainwindow.cpp b/examples/webenginewidgets/browser/browsermainwindow.cpp new file mode 100644 index 000000000..3cee14e9e --- /dev/null +++ b/examples/webenginewidgets/browser/browsermainwindow.cpp @@ -0,0 +1,993 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "browsermainwindow.h" + +#include "autosaver.h" +#include "bookmarks.h" +#include "browserapplication.h" +#include "chasewidget.h" +#include "downloadmanager.h" +#include "history.h" +#include "settings.h" +#include "tabwidget.h" +#include "toolbarsearch.h" +#include "ui_passworddialog.h" +#include "webview.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +template +struct InvokeWrapper { + R *receiver; + void (C::*memberFun)(Arg); + void operator()(Arg result) { + (receiver->*memberFun)(result); + } +}; + +template +InvokeWrapper invoke(R *receiver, void (C::*memberFun)(Arg)) +{ + InvokeWrapper wrapper = {receiver, memberFun}; + return wrapper; +} + +BrowserMainWindow::BrowserMainWindow(QWidget *parent, Qt::WindowFlags flags) + : QMainWindow(parent, flags) + , m_tabWidget(new TabWidget(this)) + , m_autoSaver(new AutoSaver(this)) + , m_historyBack(0) + , m_historyForward(0) + , m_stop(0) + , m_reload(0) +{ + setToolButtonStyle(Qt::ToolButtonFollowStyle); + setAttribute(Qt::WA_DeleteOnClose, true); + statusBar()->setSizeGripEnabled(true); + setupMenu(); + setupToolBar(); + + QWidget *centralWidget = new QWidget(this); + BookmarksModel *boomarksModel = BrowserApplication::bookmarksManager()->bookmarksModel(); + m_bookmarksToolbar = new BookmarksToolBar(boomarksModel, this); + connect(m_bookmarksToolbar, SIGNAL(openUrl(QUrl)), + m_tabWidget, SLOT(loadUrlInCurrentTab(QUrl))); + connect(m_bookmarksToolbar->toggleViewAction(), SIGNAL(toggled(bool)), + this, SLOT(updateBookmarksToolbarActionText(bool))); + + QVBoxLayout *layout = new QVBoxLayout; + layout->setSpacing(0); + layout->setMargin(0); +#if defined(Q_WS_MAC) + layout->addWidget(m_bookmarksToolbar); + layout->addWidget(new QWidget); // <- OS X tab widget style bug +#else + addToolBarBreak(); + addToolBar(m_bookmarksToolbar); +#endif + layout->addWidget(m_tabWidget); + centralWidget->setLayout(layout); + setCentralWidget(centralWidget); + + connect(m_tabWidget, SIGNAL(loadPage(QString)), + this, SLOT(loadPage(QString))); + connect(m_tabWidget, SIGNAL(setCurrentTitle(QString)), + this, SLOT(slotUpdateWindowTitle(QString))); + connect(m_tabWidget, SIGNAL(showStatusBarMessage(QString)), + statusBar(), SLOT(showMessage(QString))); + connect(m_tabWidget, SIGNAL(linkHovered(QString)), + statusBar(), SLOT(showMessage(QString))); + connect(m_tabWidget, SIGNAL(loadProgress(int)), + this, SLOT(slotLoadProgress(int))); + connect(m_tabWidget, SIGNAL(tabsChanged()), + m_autoSaver, SLOT(changeOccurred())); + connect(m_tabWidget, SIGNAL(geometryChangeRequested(QRect)), + this, SLOT(geometryChangeRequested(QRect))); + connect(m_tabWidget, SIGNAL(printRequested(QWebEngineFrame*)), + this, SLOT(printRequested(QWebEngineFrame*))); + connect(m_tabWidget, SIGNAL(menuBarVisibilityChangeRequested(bool)), + menuBar(), SLOT(setVisible(bool))); + connect(m_tabWidget, SIGNAL(statusBarVisibilityChangeRequested(bool)), + statusBar(), SLOT(setVisible(bool))); + connect(m_tabWidget, SIGNAL(toolBarVisibilityChangeRequested(bool)), + m_navigationBar, SLOT(setVisible(bool))); + connect(m_tabWidget, SIGNAL(toolBarVisibilityChangeRequested(bool)), + m_bookmarksToolbar, SLOT(setVisible(bool))); +#if defined(Q_WS_MAC) + connect(m_tabWidget, SIGNAL(lastTabClosed()), + this, SLOT(close())); +#else + connect(m_tabWidget, SIGNAL(lastTabClosed()), + m_tabWidget, SLOT(newTab())); +#endif + + slotUpdateWindowTitle(); + loadDefaultState(); + m_tabWidget->newTab(); + + int size = m_tabWidget->lineEditStack()->sizeHint().height(); + m_navigationBar->setIconSize(QSize(size, size)); + +} + +BrowserMainWindow::~BrowserMainWindow() +{ + m_autoSaver->changeOccurred(); + m_autoSaver->saveIfNeccessary(); +} + +void BrowserMainWindow::loadDefaultState() +{ + QSettings settings; + settings.beginGroup(QLatin1String("BrowserMainWindow")); + QByteArray data = settings.value(QLatin1String("defaultState")).toByteArray(); + restoreState(data); + settings.endGroup(); +} + +QSize BrowserMainWindow::sizeHint() const +{ + QRect desktopRect = QApplication::desktop()->screenGeometry(); + QSize size = desktopRect.size() * qreal(0.9); + return size; +} + +void BrowserMainWindow::save() +{ + BrowserApplication::instance()->saveSession(); + + QSettings settings; + settings.beginGroup(QLatin1String("BrowserMainWindow")); + QByteArray data = saveState(false); + settings.setValue(QLatin1String("defaultState"), data); + settings.endGroup(); +} + +static const qint32 BrowserMainWindowMagic = 0xba; + +QByteArray BrowserMainWindow::saveState(bool withTabs) const +{ + int version = 2; + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + + stream << qint32(BrowserMainWindowMagic); + stream << qint32(version); + + stream << size(); + stream << !m_navigationBar->isHidden(); + stream << !m_bookmarksToolbar->isHidden(); + stream << !statusBar()->isHidden(); + if (withTabs) + stream << tabWidget()->saveState(); + else + stream << QByteArray(); + return data; +} + +bool BrowserMainWindow::restoreState(const QByteArray &state) +{ + int version = 2; + QByteArray sd = state; + QDataStream stream(&sd, QIODevice::ReadOnly); + if (stream.atEnd()) + return false; + + qint32 marker; + qint32 v; + stream >> marker; + stream >> v; + if (marker != BrowserMainWindowMagic || v != version) + return false; + + QSize size; + bool showToolbar; + bool showBookmarksBar; + bool showStatusbar; + QByteArray tabState; + + stream >> size; + stream >> showToolbar; + stream >> showBookmarksBar; + stream >> showStatusbar; + stream >> tabState; + + resize(size); + + m_navigationBar->setVisible(showToolbar); + updateToolbarActionText(showToolbar); + + m_bookmarksToolbar->setVisible(showBookmarksBar); + updateBookmarksToolbarActionText(showBookmarksBar); + + statusBar()->setVisible(showStatusbar); + updateStatusbarActionText(showStatusbar); + + if (!tabWidget()->restoreState(tabState)) + return false; + + return true; +} + +void BrowserMainWindow::setupMenu() +{ + new QShortcut(QKeySequence(Qt::Key_F6), this, SLOT(slotSwapFocus())); + + // File + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + + fileMenu->addAction(tr("&New Window"), this, SLOT(slotFileNew()), QKeySequence::New); + fileMenu->addAction(m_tabWidget->newTabAction()); + fileMenu->addAction(tr("&Open File..."), this, SLOT(slotFileOpen()), QKeySequence::Open); + fileMenu->addAction(tr("Open &Location..."), this, + SLOT(slotSelectLineEdit()), QKeySequence(Qt::ControlModifier + Qt::Key_L)); + fileMenu->addSeparator(); + fileMenu->addAction(m_tabWidget->closeTabAction()); + fileMenu->addSeparator(); +#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) + fileMenu->addAction(tr("&Save As..."), this, + SLOT(slotFileSaveAs()), QKeySequence(QKeySequence::Save)); + fileMenu->addSeparator(); +#endif + BookmarksManager *bookmarksManager = BrowserApplication::bookmarksManager(); + fileMenu->addAction(tr("&Import Bookmarks..."), bookmarksManager, SLOT(importBookmarks())); + fileMenu->addAction(tr("&Export Bookmarks..."), bookmarksManager, SLOT(exportBookmarks())); + fileMenu->addSeparator(); +#if defined(QWEBENGINEPAGE_PRINT) + fileMenu->addAction(tr("P&rint Preview..."), this, SLOT(slotFilePrintPreview())); + fileMenu->addAction(tr("&Print..."), this, SLOT(slotFilePrint()), QKeySequence::Print); + fileMenu->addSeparator(); +#endif +#if defined(QWEBENGINESETTINGS) + QAction *action = fileMenu->addAction(tr("Private &Browsing..."), this, SLOT(slotPrivateBrowsing())); + action->setCheckable(true); + fileMenu->addSeparator(); +#endif + +#if defined(Q_WS_MAC) + fileMenu->addAction(tr("&Quit"), BrowserApplication::instance(), SLOT(quitBrowser()), QKeySequence(Qt::CTRL | Qt::Key_Q)); +#else + fileMenu->addAction(tr("&Quit"), this, SLOT(close()), QKeySequence(Qt::CTRL | Qt::Key_Q)); +#endif + + // Edit + QMenu *editMenu = menuBar()->addMenu(tr("&Edit")); + QAction *m_undo = editMenu->addAction(tr("&Undo")); + m_undo->setShortcuts(QKeySequence::Undo); + m_tabWidget->addWebAction(m_undo, QWebEnginePage::Undo); + QAction *m_redo = editMenu->addAction(tr("&Redo")); + m_redo->setShortcuts(QKeySequence::Redo); + m_tabWidget->addWebAction(m_redo, QWebEnginePage::Redo); + editMenu->addSeparator(); + QAction *m_cut = editMenu->addAction(tr("Cu&t")); + m_cut->setShortcuts(QKeySequence::Cut); + m_tabWidget->addWebAction(m_cut, QWebEnginePage::Cut); + QAction *m_copy = editMenu->addAction(tr("&Copy")); + m_copy->setShortcuts(QKeySequence::Copy); + m_tabWidget->addWebAction(m_copy, QWebEnginePage::Copy); + QAction *m_paste = editMenu->addAction(tr("&Paste")); + m_paste->setShortcuts(QKeySequence::Paste); + m_tabWidget->addWebAction(m_paste, QWebEnginePage::Paste); + editMenu->addSeparator(); + + QAction *m_find = editMenu->addAction(tr("&Find")); + m_find->setShortcuts(QKeySequence::Find); + connect(m_find, SIGNAL(triggered()), this, SLOT(slotEditFind())); + new QShortcut(QKeySequence(Qt::Key_Slash), this, SLOT(slotEditFind())); + + QAction *m_findNext = editMenu->addAction(tr("&Find Next")); + m_findNext->setShortcuts(QKeySequence::FindNext); + connect(m_findNext, SIGNAL(triggered()), this, SLOT(slotEditFindNext())); + + QAction *m_findPrevious = editMenu->addAction(tr("&Find Previous")); + m_findPrevious->setShortcuts(QKeySequence::FindPrevious); + connect(m_findPrevious, SIGNAL(triggered()), this, SLOT(slotEditFindPrevious())); + editMenu->addSeparator(); + + editMenu->addAction(tr("&Preferences"), this, SLOT(slotPreferences()), tr("Ctrl+,")); + + // View + QMenu *viewMenu = menuBar()->addMenu(tr("&View")); + + m_viewBookmarkBar = new QAction(this); + updateBookmarksToolbarActionText(true); + m_viewBookmarkBar->setShortcut(tr("Shift+Ctrl+B")); + connect(m_viewBookmarkBar, SIGNAL(triggered()), this, SLOT(slotViewBookmarksBar())); + viewMenu->addAction(m_viewBookmarkBar); + + m_viewToolbar = new QAction(this); + updateToolbarActionText(true); + m_viewToolbar->setShortcut(tr("Ctrl+|")); + connect(m_viewToolbar, SIGNAL(triggered()), this, SLOT(slotViewToolbar())); + viewMenu->addAction(m_viewToolbar); + + m_viewStatusbar = new QAction(this); + updateStatusbarActionText(true); + m_viewStatusbar->setShortcut(tr("Ctrl+/")); + connect(m_viewStatusbar, SIGNAL(triggered()), this, SLOT(slotViewStatusbar())); + viewMenu->addAction(m_viewStatusbar); + + viewMenu->addSeparator(); + + m_stop = viewMenu->addAction(tr("&Stop")); + QList shortcuts; + shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_Period)); + shortcuts.append(Qt::Key_Escape); + m_stop->setShortcuts(shortcuts); + m_tabWidget->addWebAction(m_stop, QWebEnginePage::Stop); + + m_reload = viewMenu->addAction(tr("Reload Page")); + m_reload->setShortcuts(QKeySequence::Refresh); + m_tabWidget->addWebAction(m_reload, QWebEnginePage::Reload); + + viewMenu->addAction(tr("Zoom &In"), this, SLOT(slotViewZoomIn()), QKeySequence(Qt::CTRL | Qt::Key_Plus)); + viewMenu->addAction(tr("Zoom &Out"), this, SLOT(slotViewZoomOut()), QKeySequence(Qt::CTRL | Qt::Key_Minus)); + viewMenu->addAction(tr("Reset &Zoom"), this, SLOT(slotViewResetZoom()), QKeySequence(Qt::CTRL | Qt::Key_0)); +#if defined(QWEBENGINESETTINGS) + QAction *zoomTextOnlyAction = viewMenu->addAction(tr("Zoom &Text Only")); + connect(zoomTextOnlyAction, SIGNAL(toggled(bool)), this, SLOT(slotViewZoomTextOnly(bool))); + zoomTextOnlyAction->setCheckable(true); + zoomTextOnlyAction->setChecked(false); +#endif + + viewMenu->addSeparator(); + viewMenu->addAction(tr("Page S&ource"), this, SLOT(slotViewPageSource()), tr("Ctrl+Alt+U")); + QAction *a = viewMenu->addAction(tr("&Full Screen"), this, SLOT(slotViewFullScreen(bool)), Qt::Key_F11); + a->setCheckable(true); + + // History + HistoryMenu *historyMenu = new HistoryMenu(this); + connect(historyMenu, SIGNAL(openUrl(QUrl)), + m_tabWidget, SLOT(loadUrlInCurrentTab(QUrl))); + connect(historyMenu, SIGNAL(hovered(QString)), this, + SLOT(slotUpdateStatusbar(QString))); + historyMenu->setTitle(tr("Hi&story")); + menuBar()->addMenu(historyMenu); + QList historyActions; + + m_historyBack = new QAction(tr("Back"), this); + m_tabWidget->addWebAction(m_historyBack, QWebEnginePage::Back); + m_historyBack->setShortcuts(QKeySequence::Back); + m_historyBack->setIconVisibleInMenu(false); + historyActions.append(m_historyBack); + + m_historyForward = new QAction(tr("Forward"), this); + m_tabWidget->addWebAction(m_historyForward, QWebEnginePage::Forward); + m_historyForward->setShortcuts(QKeySequence::Forward); + m_historyForward->setIconVisibleInMenu(false); + historyActions.append(m_historyForward); + + QAction *m_historyHome = new QAction(tr("Home"), this); + connect(m_historyHome, SIGNAL(triggered()), this, SLOT(slotHome())); + m_historyHome->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_H)); + historyActions.append(m_historyHome); + +#if defined(QWEBENGINEHISTORY_RESTORESESSION) + m_restoreLastSession = new QAction(tr("Restore Last Session"), this); + connect(m_restoreLastSession, SIGNAL(triggered()), BrowserApplication::instance(), SLOT(restoreLastSession())); + m_restoreLastSession->setEnabled(BrowserApplication::instance()->canRestoreSession()); + historyActions.append(m_tabWidget->recentlyClosedTabsAction()); + historyActions.append(m_restoreLastSession); +#endif + + historyMenu->setInitialActions(historyActions); + + // Bookmarks + BookmarksMenu *bookmarksMenu = new BookmarksMenu(this); + connect(bookmarksMenu, SIGNAL(openUrl(QUrl)), + m_tabWidget, SLOT(loadUrlInCurrentTab(QUrl))); + connect(bookmarksMenu, SIGNAL(hovered(QString)), + this, SLOT(slotUpdateStatusbar(QString))); + bookmarksMenu->setTitle(tr("&Bookmarks")); + menuBar()->addMenu(bookmarksMenu); + + QList bookmarksActions; + + QAction *showAllBookmarksAction = new QAction(tr("Show All Bookmarks"), this); + connect(showAllBookmarksAction, SIGNAL(triggered()), this, SLOT(slotShowBookmarksDialog())); + m_addBookmark = new QAction(QIcon(QLatin1String(":addbookmark.png")), tr("Add Bookmark..."), this); + m_addBookmark->setIconVisibleInMenu(false); + + connect(m_addBookmark, SIGNAL(triggered()), this, SLOT(slotAddBookmark())); + m_addBookmark->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_D)); + + bookmarksActions.append(showAllBookmarksAction); + bookmarksActions.append(m_addBookmark); + bookmarksMenu->setInitialActions(bookmarksActions); + + // Window + m_windowMenu = menuBar()->addMenu(tr("&Window")); + connect(m_windowMenu, SIGNAL(aboutToShow()), + this, SLOT(slotAboutToShowWindowMenu())); + slotAboutToShowWindowMenu(); + + QMenu *toolsMenu = menuBar()->addMenu(tr("&Tools")); + toolsMenu->addAction(tr("Web &Search"), this, SLOT(slotWebSearch()), QKeySequence(tr("Ctrl+K", "Web Search"))); +#if defined(QWEBENGINEINSPECTOR) + a = toolsMenu->addAction(tr("Enable Web &Inspector"), this, SLOT(slotToggleInspector(bool))); + a->setCheckable(true); +#endif + + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt())); + helpMenu->addAction(tr("About &Demo Browser"), this, SLOT(slotAboutApplication())); +} + +void BrowserMainWindow::setupToolBar() +{ + setUnifiedTitleAndToolBarOnMac(true); + m_navigationBar = addToolBar(tr("Navigation")); + connect(m_navigationBar->toggleViewAction(), SIGNAL(toggled(bool)), + this, SLOT(updateToolbarActionText(bool))); + + m_historyBack->setIcon(style()->standardIcon(QStyle::SP_ArrowBack, 0, this)); + m_historyBackMenu = new QMenu(this); + m_historyBack->setMenu(m_historyBackMenu); + connect(m_historyBackMenu, SIGNAL(aboutToShow()), + this, SLOT(slotAboutToShowBackMenu())); + connect(m_historyBackMenu, SIGNAL(triggered(QAction*)), + this, SLOT(slotOpenActionUrl(QAction*))); + m_navigationBar->addAction(m_historyBack); + + m_historyForward->setIcon(style()->standardIcon(QStyle::SP_ArrowForward, 0, this)); + m_historyForwardMenu = new QMenu(this); + connect(m_historyForwardMenu, SIGNAL(aboutToShow()), + this, SLOT(slotAboutToShowForwardMenu())); + connect(m_historyForwardMenu, SIGNAL(triggered(QAction*)), + this, SLOT(slotOpenActionUrl(QAction*))); + m_historyForward->setMenu(m_historyForwardMenu); + m_navigationBar->addAction(m_historyForward); + + m_stopReload = new QAction(this); + m_reloadIcon = style()->standardIcon(QStyle::SP_BrowserReload); + m_stopReload->setIcon(m_reloadIcon); + + m_navigationBar->addAction(m_stopReload); + + m_navigationBar->addWidget(m_tabWidget->lineEditStack()); + + m_toolbarSearch = new ToolbarSearch(m_navigationBar); + m_navigationBar->addWidget(m_toolbarSearch); + connect(m_toolbarSearch, SIGNAL(search(QUrl)), SLOT(loadUrl(QUrl))); + + m_chaseWidget = new ChaseWidget(this); + m_navigationBar->addWidget(m_chaseWidget); +} + +void BrowserMainWindow::slotShowBookmarksDialog() +{ + BookmarksDialog *dialog = new BookmarksDialog(this); + connect(dialog, SIGNAL(openUrl(QUrl)), + m_tabWidget, SLOT(loadUrlInCurrentTab(QUrl))); + dialog->show(); +} + +void BrowserMainWindow::slotAddBookmark() +{ + WebView *webView = currentTab(); + QString url = webView->url().toString(); + QString title = webView->title(); + AddBookmarkDialog dialog(url, title); + dialog.exec(); +} + +void BrowserMainWindow::slotViewToolbar() +{ + if (m_navigationBar->isVisible()) { + updateToolbarActionText(false); + m_navigationBar->close(); + } else { + updateToolbarActionText(true); + m_navigationBar->show(); + } + m_autoSaver->changeOccurred(); +} + +void BrowserMainWindow::slotViewBookmarksBar() +{ + if (m_bookmarksToolbar->isVisible()) { + updateBookmarksToolbarActionText(false); + m_bookmarksToolbar->close(); + } else { + updateBookmarksToolbarActionText(true); + m_bookmarksToolbar->show(); + } + m_autoSaver->changeOccurred(); +} + +void BrowserMainWindow::updateStatusbarActionText(bool visible) +{ + m_viewStatusbar->setText(!visible ? tr("Show Status Bar") : tr("Hide Status Bar")); +} + +void BrowserMainWindow::handleFindTextResult(bool found) +{ + if (!found) + slotUpdateStatusbar(tr("\"%1\" not found.").arg(m_lastSearch)); +} + +void BrowserMainWindow::updateToolbarActionText(bool visible) +{ + m_viewToolbar->setText(!visible ? tr("Show Toolbar") : tr("Hide Toolbar")); +} + +void BrowserMainWindow::updateBookmarksToolbarActionText(bool visible) +{ + m_viewBookmarkBar->setText(!visible ? tr("Show Bookmarks bar") : tr("Hide Bookmarks bar")); +} + +void BrowserMainWindow::slotViewStatusbar() +{ + if (statusBar()->isVisible()) { + updateStatusbarActionText(false); + statusBar()->close(); + } else { + updateStatusbarActionText(true); + statusBar()->show(); + } + m_autoSaver->changeOccurred(); +} + +void BrowserMainWindow::loadUrl(const QUrl &url) +{ + if (!currentTab() || !url.isValid()) + return; + + m_tabWidget->currentLineEdit()->setText(QString::fromUtf8(url.toEncoded())); + m_tabWidget->loadUrlInCurrentTab(url); +} + +void BrowserMainWindow::slotDownloadManager() +{ + BrowserApplication::downloadManager()->show(); +} + +void BrowserMainWindow::slotSelectLineEdit() +{ + m_tabWidget->currentLineEdit()->selectAll(); + m_tabWidget->currentLineEdit()->setFocus(); +} + +void BrowserMainWindow::slotFileSaveAs() +{ + BrowserApplication::downloadManager()->download(currentTab()->url(), true); +} + +void BrowserMainWindow::slotPreferences() +{ + SettingsDialog *s = new SettingsDialog(this); + s->show(); +} + +void BrowserMainWindow::slotUpdateStatusbar(const QString &string) +{ + statusBar()->showMessage(string, 2000); +} + +void BrowserMainWindow::slotUpdateWindowTitle(const QString &title) +{ + if (title.isEmpty()) { + setWindowTitle(tr("Qt Demo Browser")); + } else { +#if defined(Q_WS_MAC) + setWindowTitle(title); +#else + setWindowTitle(tr("%1 - Qt Demo Browser", "Page title and Browser name").arg(title)); +#endif + } +} + +void BrowserMainWindow::slotAboutApplication() +{ + QMessageBox::about(this, tr("About"), tr( + "Version %1" + "

This demo demonstrates Qt's " + "webkit facilities in action, providing an example " + "browser for you to experiment with.

" + "

QtWebKit is based on the Open Source WebKit Project developed at http://webkit.org/." + ).arg(QCoreApplication::applicationVersion())); +} + +void BrowserMainWindow::slotFileNew() +{ + BrowserApplication::instance()->newMainWindow(); + BrowserMainWindow *mw = BrowserApplication::instance()->mainWindow(); + mw->slotHome(); +} + +void BrowserMainWindow::slotFileOpen() +{ + QString file = QFileDialog::getOpenFileName(this, tr("Open Web Resource"), QString(), + tr("Web Resources (*.html *.htm *.svg *.png *.gif *.svgz);;All files (*.*)")); + + if (file.isEmpty()) + return; + + loadPage(file); +} + +void BrowserMainWindow::slotFilePrintPreview() +{ +#ifndef QT_NO_PRINTPREVIEWDIALOG + if (!currentTab()) + return; + QPrintPreviewDialog *dialog = new QPrintPreviewDialog(this); + connect(dialog, SIGNAL(paintRequested(QPrinter*)), + currentTab(), SLOT(print(QPrinter*))); + dialog->exec(); +#endif +} + +void BrowserMainWindow::slotFilePrint() +{ +#if defined(QWEBENGINEPAGE_PRINT) + if (!currentTab()) + return; + printRequested(currentTab()->page()->mainFrame()); +#endif +} + +void BrowserMainWindow::printRequested(QWebEngineFrame *frame) +{ +#if defined(QWEBENGINEPAGE_PRINT) +#ifndef QT_NO_PRINTDIALOG + QPrinter printer; + QPrintDialog *dialog = new QPrintDialog(&printer, this); + dialog->setWindowTitle(tr("Print Document")); + if (dialog->exec() != QDialog::Accepted) + return; + frame->print(&printer); +#endif +#endif +} + +void BrowserMainWindow::slotPrivateBrowsing() +{ +#if defined(QWEBENGINESETTINGS) + QWebEngineSettings *settings = QWebEngineSettings::globalSettings(); + bool pb = settings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled); + if (!pb) { + QString title = tr("Are you sure you want to turn on private browsing?"); + QString text = tr("%1

When private browsing in turned on," + " webpages are not added to the history," + " items are automatically removed from the Downloads window," \ + " new cookies are not stored, current cookies can't be accessed," \ + " site icons wont be stored, session wont be saved, " \ + " and searches are not added to the pop-up menu in the Google search box." \ + " Until you close the window, you can still click the Back and Forward buttons" \ + " to return to the webpages you have opened.").arg(title); + + QMessageBox::StandardButton button = QMessageBox::question(this, QString(), text, + QMessageBox::Ok | QMessageBox::Cancel, + QMessageBox::Ok); + if (button == QMessageBox::Ok) { + settings->setAttribute(QWebEngineSettings::PrivateBrowsingEnabled, true); + } + } else { + settings->setAttribute(QWebEngineSettings::PrivateBrowsingEnabled, false); + + QList windows = BrowserApplication::instance()->mainWindows(); + for (int i = 0; i < windows.count(); ++i) { + BrowserMainWindow *window = windows.at(i); + window->m_lastSearch = QString::null; + window->tabWidget()->clear(); + } + } +#endif +} + +void BrowserMainWindow::closeEvent(QCloseEvent *event) +{ + if (m_tabWidget->count() > 1) { + int ret = QMessageBox::warning(this, QString(), + tr("Are you sure you want to close the window?" + " There are %1 tabs open").arg(m_tabWidget->count()), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No); + if (ret == QMessageBox::No) { + event->ignore(); + return; + } + } + event->accept(); + deleteLater(); +} + +void BrowserMainWindow::slotEditFind() +{ + if (!currentTab()) + return; + bool ok; + QString search = QInputDialog::getText(this, tr("Find"), + tr("Text:"), QLineEdit::Normal, + m_lastSearch, &ok); + if (ok && !search.isEmpty()) { + m_lastSearch = search; + currentTab()->findText(m_lastSearch, 0, invoke(this, &BrowserMainWindow::handleFindTextResult)); + } +} + +void BrowserMainWindow::slotEditFindNext() +{ + if (!currentTab() && !m_lastSearch.isEmpty()) + return; + currentTab()->findText(m_lastSearch); +} + +void BrowserMainWindow::slotEditFindPrevious() +{ + if (!currentTab() && !m_lastSearch.isEmpty()) + return; + currentTab()->findText(m_lastSearch, QWebEnginePage::FindBackward); +} + +void BrowserMainWindow::slotViewZoomIn() +{ + if (!currentTab()) + return; + currentTab()->setZoomFactor(currentTab()->zoomFactor() + 0.1); +} + +void BrowserMainWindow::slotViewZoomOut() +{ + if (!currentTab()) + return; + currentTab()->setZoomFactor(currentTab()->zoomFactor() - 0.1); +} + +void BrowserMainWindow::slotViewResetZoom() +{ + if (!currentTab()) + return; + currentTab()->setZoomFactor(1.0); +} + +void BrowserMainWindow::slotViewZoomTextOnly(bool enable) +{ +#if defined(QWEBENGINESETTINGS) + if (!currentTab()) + return; + currentTab()->page()->settings()->setAttribute(QWebEngineSettings::ZoomTextOnly, enable); +#endif +} + +void BrowserMainWindow::slotViewFullScreen(bool makeFullScreen) +{ + if (makeFullScreen) { + showFullScreen(); + } else { + if (isMinimized()) + showMinimized(); + else if (isMaximized()) + showMaximized(); + else showNormal(); + } +} + +void BrowserMainWindow::slotViewPageSource() +{ + if (!currentTab()) + return; + + QPlainTextEdit *view = new QPlainTextEdit; + view->setWindowTitle(tr("Page Source of %1").arg(currentTab()->title())); + view->setMinimumWidth(640); + view->setAttribute(Qt::WA_DeleteOnClose); + view->show(); + + currentTab()->page()->toHtml(invoke(view, &QPlainTextEdit::setPlainText)); +} + +void BrowserMainWindow::slotHome() +{ + QSettings settings; + settings.beginGroup(QLatin1String("MainWindow")); + QString home = settings.value(QLatin1String("home"), QLatin1String("http://qt-project.org/")).toString(); + loadPage(home); +} + +void BrowserMainWindow::slotWebSearch() +{ + m_toolbarSearch->lineEdit()->selectAll(); + m_toolbarSearch->lineEdit()->setFocus(); +} + +void BrowserMainWindow::slotToggleInspector(bool enable) +{ +#if defined(QWEBENGINEINSPECTOR) + QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::DeveloperExtrasEnabled, enable); + if (enable) { + int result = QMessageBox::question(this, tr("Web Inspector"), + tr("The web inspector will only work correctly for pages that were loaded after enabling.\n" + "Do you want to reload all pages?"), + QMessageBox::Yes | QMessageBox::No); + if (result == QMessageBox::Yes) { + m_tabWidget->reloadAllTabs(); + } + } +#endif +} + +void BrowserMainWindow::slotSwapFocus() +{ + if (currentTab()->hasFocus()) + m_tabWidget->currentLineEdit()->setFocus(); + else + currentTab()->setFocus(); +} + +void BrowserMainWindow::loadPage(const QString &page) +{ + QUrl url = QUrl::fromUserInput(page); + loadUrl(url); +} + +TabWidget *BrowserMainWindow::tabWidget() const +{ + return m_tabWidget; +} + +WebView *BrowserMainWindow::currentTab() const +{ + return m_tabWidget->currentWebView(); +} + +void BrowserMainWindow::slotLoadProgress(int progress) +{ + if (progress < 100 && progress > 0) { + m_chaseWidget->setAnimated(true); + disconnect(m_stopReload, SIGNAL(triggered()), m_reload, SLOT(trigger())); + if (m_stopIcon.isNull()) + m_stopIcon = style()->standardIcon(QStyle::SP_BrowserStop); + m_stopReload->setIcon(m_stopIcon); + connect(m_stopReload, SIGNAL(triggered()), m_stop, SLOT(trigger())); + m_stopReload->setToolTip(tr("Stop loading the current page")); + } else { + m_chaseWidget->setAnimated(false); + disconnect(m_stopReload, SIGNAL(triggered()), m_stop, SLOT(trigger())); + m_stopReload->setIcon(m_reloadIcon); + connect(m_stopReload, SIGNAL(triggered()), m_reload, SLOT(trigger())); + m_stopReload->setToolTip(tr("Reload the current page")); + } +} + +void BrowserMainWindow::slotAboutToShowBackMenu() +{ + m_historyBackMenu->clear(); + if (!currentTab()) + return; + QWebEngineHistory *history = currentTab()->history(); + int historyCount = history->count(); + for (int i = history->backItems(historyCount).count() - 1; i >= 0; --i) { + QWebEngineHistoryItem item = history->backItems(history->count()).at(i); + QAction *action = new QAction(this); + action->setData(-1*(historyCount-i-1)); + QIcon icon = BrowserApplication::instance()->icon(item.url()); + action->setIcon(icon); + action->setText(item.title()); + m_historyBackMenu->addAction(action); + } +} + +void BrowserMainWindow::slotAboutToShowForwardMenu() +{ + m_historyForwardMenu->clear(); + if (!currentTab()) + return; + QWebEngineHistory *history = currentTab()->history(); + int historyCount = history->count(); + for (int i = 0; i < history->forwardItems(history->count()).count(); ++i) { + QWebEngineHistoryItem item = history->forwardItems(historyCount).at(i); + QAction *action = new QAction(this); + action->setData(historyCount-i); + QIcon icon = BrowserApplication::instance()->icon(item.url()); + action->setIcon(icon); + action->setText(item.title()); + m_historyForwardMenu->addAction(action); + } +} + +void BrowserMainWindow::slotAboutToShowWindowMenu() +{ + m_windowMenu->clear(); + m_windowMenu->addAction(m_tabWidget->nextTabAction()); + m_windowMenu->addAction(m_tabWidget->previousTabAction()); + m_windowMenu->addSeparator(); +#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) + m_windowMenu->addAction(tr("Downloads"), this, SLOT(slotDownloadManager()), QKeySequence(tr("Alt+Ctrl+L", "Download Manager"))); + m_windowMenu->addSeparator(); +#endif + + QList windows = BrowserApplication::instance()->mainWindows(); + for (int i = 0; i < windows.count(); ++i) { + BrowserMainWindow *window = windows.at(i); + QAction *action = m_windowMenu->addAction(window->windowTitle(), this, SLOT(slotShowWindow())); + action->setData(i); + action->setCheckable(true); + if (window == this) + action->setChecked(true); + } +} + +void BrowserMainWindow::slotShowWindow() +{ + if (QAction *action = qobject_cast(sender())) { + QVariant v = action->data(); + if (v.canConvert()) { + int offset = qvariant_cast(v); + QList windows = BrowserApplication::instance()->mainWindows(); + windows.at(offset)->activateWindow(); + windows.at(offset)->currentTab()->setFocus(); + } + } +} + +void BrowserMainWindow::slotOpenActionUrl(QAction *action) +{ + int offset = action->data().toInt(); + QWebEngineHistory *history = currentTab()->history(); + if (offset < 0) + history->goToItem(history->backItems(-1*offset).first()); // back + else if (offset > 0) + history->goToItem(history->forwardItems(history->count() - offset + 1).back()); // forward +} + +void BrowserMainWindow::geometryChangeRequested(const QRect &geometry) +{ + setGeometry(geometry); +} diff --git a/examples/webenginewidgets/browser/browsermainwindow.h b/examples/webenginewidgets/browser/browsermainwindow.h new file mode 100644 index 000000000..3c3df9117 --- /dev/null +++ b/examples/webenginewidgets/browser/browsermainwindow.h @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BROWSERMAINWINDOW_H +#define BROWSERMAINWINDOW_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QWebEngineFrame; +QT_END_NAMESPACE + +class AutoSaver; +class BookmarksToolBar; +class ChaseWidget; +class TabWidget; +class ToolbarSearch; +class WebView; + +/*! + The MainWindow of the Browser Application. + + Handles the tab widget and all the actions + */ +class BrowserMainWindow : public QMainWindow { + Q_OBJECT + +public: + BrowserMainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0); + ~BrowserMainWindow(); + QSize sizeHint() const; + +public: + TabWidget *tabWidget() const; + WebView *currentTab() const; + QByteArray saveState(bool withTabs = true) const; + bool restoreState(const QByteArray &state); + +public slots: + void loadPage(const QString &url); + void slotHome(); + +protected: + void closeEvent(QCloseEvent *event); + +private slots: + void save(); + + void slotLoadProgress(int); + void slotUpdateStatusbar(const QString &string); + void slotUpdateWindowTitle(const QString &title = QString()); + + void loadUrl(const QUrl &url); + void slotPreferences(); + + void slotFileNew(); + void slotFileOpen(); + void slotFilePrintPreview(); + void slotFilePrint(); + void slotPrivateBrowsing(); + void slotFileSaveAs(); + void slotEditFind(); + void slotEditFindNext(); + void slotEditFindPrevious(); + void slotShowBookmarksDialog(); + void slotAddBookmark(); + void slotViewZoomIn(); + void slotViewZoomOut(); + void slotViewResetZoom(); + void slotViewZoomTextOnly(bool enable); + void slotViewToolbar(); + void slotViewBookmarksBar(); + void slotViewStatusbar(); + void slotViewPageSource(); + void slotViewFullScreen(bool enable); + + void slotWebSearch(); + void slotToggleInspector(bool enable); + void slotAboutApplication(); + void slotDownloadManager(); + void slotSelectLineEdit(); + + void slotAboutToShowBackMenu(); + void slotAboutToShowForwardMenu(); + void slotAboutToShowWindowMenu(); + void slotOpenActionUrl(QAction *action); + void slotShowWindow(); + void slotSwapFocus(); + + void printRequested(QWebEngineFrame *frame); + void geometryChangeRequested(const QRect &geometry); + void updateToolbarActionText(bool visible); + void updateBookmarksToolbarActionText(bool visible); + +private: + void loadDefaultState(); + void setupMenu(); + void setupToolBar(); + void updateStatusbarActionText(bool visible); + void handleFindTextResult(bool found); + +private: + QToolBar *m_navigationBar; + ToolbarSearch *m_toolbarSearch; + BookmarksToolBar *m_bookmarksToolbar; + ChaseWidget *m_chaseWidget; + TabWidget *m_tabWidget; + AutoSaver *m_autoSaver; + + QAction *m_historyBack; + QMenu *m_historyBackMenu; + QAction *m_historyForward; + QMenu *m_historyForwardMenu; + QMenu *m_windowMenu; + + QAction *m_stop; + QAction *m_reload; + QAction *m_stopReload; + QAction *m_viewToolbar; + QAction *m_viewBookmarkBar; + QAction *m_viewStatusbar; + QAction *m_restoreLastSession; + QAction *m_addBookmark; + + QIcon m_reloadIcon; + QIcon m_stopIcon; + + QString m_lastSearch; +}; + +#endif // BROWSERMAINWINDOW_H diff --git a/examples/webenginewidgets/browser/chasewidget.cpp b/examples/webenginewidgets/browser/chasewidget.cpp new file mode 100644 index 000000000..c34dde739 --- /dev/null +++ b/examples/webenginewidgets/browser/chasewidget.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "chasewidget.h" + +#include + +#include +#include +#include +#include +#include + +ChaseWidget::ChaseWidget(QWidget *parent, QPixmap pixmap, bool pixmapEnabled) + : QWidget(parent) + , m_segment(0) + , m_delay(100) + , m_step(40) + , m_timerId(-1) + , m_animated(false) + , m_pixmap(pixmap) + , m_pixmapEnabled(pixmapEnabled) +{ +} + +void ChaseWidget::setAnimated(bool value) +{ + if (m_animated == value) + return; + m_animated = value; + if (m_timerId != -1) { + killTimer(m_timerId); + m_timerId = -1; + } + if (m_animated) { + m_segment = 0; + m_timerId = startTimer(m_delay); + } + update(); +} + +void ChaseWidget::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + QPainter p(this); + if (m_pixmapEnabled && !m_pixmap.isNull()) { + p.drawPixmap(0, 0, m_pixmap); + return; + } + + const int extent = qMin(width() - 8, height() - 8); + const int displ = extent / 4; + const int ext = extent / 4 - 1; + + p.setRenderHint(QPainter::Antialiasing, true); + + if (m_animated) + p.setPen(Qt::gray); + else + p.setPen(QPen(palette().dark().color())); + + p.translate(width() / 2, height() / 2); // center + + for (int segment = 0; segment < segmentCount(); ++segment) { + p.rotate(QApplication::isRightToLeft() ? m_step : -m_step); + if (m_animated) + p.setBrush(colorForSegment(segment)); + else + p.setBrush(palette().background()); + p.drawEllipse(QRect(displ, -ext / 2, ext, ext)); + } +} + +QSize ChaseWidget::sizeHint() const +{ + return QSize(32, 32); +} + +void ChaseWidget::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == m_timerId) { + ++m_segment; + update(); + } + QWidget::timerEvent(event); +} + +QColor ChaseWidget::colorForSegment(int seg) const +{ + int index = ((seg + m_segment) % segmentCount()); + int comp = qMax(0, 255 - (index * (255 / segmentCount()))); + return QColor(comp, comp, comp, 255); +} + +int ChaseWidget::segmentCount() const +{ + return 360 / m_step; +} + +void ChaseWidget::setPixmapEnabled(bool enable) +{ + m_pixmapEnabled = enable; +} diff --git a/examples/webenginewidgets/browser/chasewidget.h b/examples/webenginewidgets/browser/chasewidget.h new file mode 100644 index 000000000..2c57d08ac --- /dev/null +++ b/examples/webenginewidgets/browser/chasewidget.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CHASEWIDGET_H +#define CHASEWIDGET_H + +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QHideEvent; +class QShowEvent; +class QPaintEvent; +class QTimerEvent; +QT_END_NAMESPACE + +class ChaseWidget : public QWidget +{ + Q_OBJECT +public: + ChaseWidget(QWidget *parent = 0, QPixmap pixmap = QPixmap(), bool pixmapEnabled = false); + + void setAnimated(bool value); + void setPixmapEnabled(bool enable); + QSize sizeHint() const; + +protected: + void paintEvent(QPaintEvent *event); + void timerEvent(QTimerEvent *event); + +private: + int segmentCount() const; + QColor colorForSegment(int segment) const; + + int m_segment; + int m_delay; + int m_step; + int m_timerId; + bool m_animated; + QPixmap m_pixmap; + bool m_pixmapEnabled; +}; + +#endif diff --git a/examples/webenginewidgets/browser/cookiejar.cpp b/examples/webenginewidgets/browser/cookiejar.cpp new file mode 100644 index 000000000..0b94d9903 --- /dev/null +++ b/examples/webenginewidgets/browser/cookiejar.cpp @@ -0,0 +1,737 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "cookiejar.h" + +#include "autosaver.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +static const unsigned int JAR_VERSION = 23; + +QT_BEGIN_NAMESPACE +QDataStream &operator<<(QDataStream &stream, const QList &list) +{ + stream << JAR_VERSION; + stream << quint32(list.size()); + for (int i = 0; i < list.size(); ++i) + stream << list.at(i).toRawForm(); + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QList &list) +{ + list.clear(); + + quint32 version; + stream >> version; + + if (version != JAR_VERSION) + return stream; + + quint32 count; + stream >> count; + for (quint32 i = 0; i < count; ++i) + { + QByteArray value; + stream >> value; + QList newCookies = QNetworkCookie::parseCookies(value); + if (newCookies.count() == 0 && value.length() != 0) { + qWarning() << "CookieJar: Unable to parse saved cookie:" << value; + } + for (int j = 0; j < newCookies.count(); ++j) + list.append(newCookies.at(j)); + if (stream.atEnd()) + break; + } + return stream; +} +QT_END_NAMESPACE + +CookieJar::CookieJar(QObject *parent) + : QNetworkCookieJar(parent) + , m_loaded(false) + , m_saveTimer(new AutoSaver(this)) + , m_acceptCookies(AcceptOnlyFromSitesNavigatedTo) +{ +} + +CookieJar::~CookieJar() +{ + if (m_keepCookies == KeepUntilExit) + clear(); + m_saveTimer->saveIfNeccessary(); +} + +void CookieJar::clear() +{ + setAllCookies(QList()); + m_saveTimer->changeOccurred(); + emit cookiesChanged(); +} + +void CookieJar::load() +{ + if (m_loaded) + return; + // load cookies and exceptions + qRegisterMetaTypeStreamOperators >("QList"); + QSettings cookieSettings(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1String("/cookies.ini"), QSettings::IniFormat); + setAllCookies(qvariant_cast >(cookieSettings.value(QLatin1String("cookies")))); + cookieSettings.beginGroup(QLatin1String("Exceptions")); + m_exceptions_block = cookieSettings.value(QLatin1String("block")).toStringList(); + m_exceptions_allow = cookieSettings.value(QLatin1String("allow")).toStringList(); + m_exceptions_allowForSession = cookieSettings.value(QLatin1String("allowForSession")).toStringList(); + qSort(m_exceptions_block.begin(), m_exceptions_block.end()); + qSort(m_exceptions_allow.begin(), m_exceptions_allow.end()); + qSort(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end()); + + loadSettings(); +} + +void CookieJar::loadSettings() +{ + QSettings settings; + settings.beginGroup(QLatin1String("cookies")); + QByteArray value = settings.value(QLatin1String("acceptCookies"), + QLatin1String("AcceptOnlyFromSitesNavigatedTo")).toByteArray(); + QMetaEnum acceptPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("AcceptPolicy")); + m_acceptCookies = acceptPolicyEnum.keyToValue(value) == -1 ? + AcceptOnlyFromSitesNavigatedTo : + static_cast(acceptPolicyEnum.keyToValue(value)); + + value = settings.value(QLatin1String("keepCookiesUntil"), QLatin1String("KeepUntilExpire")).toByteArray(); + QMetaEnum keepPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("KeepPolicy")); + m_keepCookies = keepPolicyEnum.keyToValue(value) == -1 ? + KeepUntilExpire : + static_cast(keepPolicyEnum.keyToValue(value)); + + if (m_keepCookies == KeepUntilExit) + setAllCookies(QList()); + + m_loaded = true; + emit cookiesChanged(); +} + +void CookieJar::save() +{ + if (!m_loaded) + return; + purgeOldCookies(); + QString directory = QStandardPaths::writableLocation(QStandardPaths::DataLocation); + if (directory.isEmpty()) + directory = QDir::homePath() + QLatin1String("/.") + QCoreApplication::applicationName(); + if (!QFile::exists(directory)) { + QDir dir; + dir.mkpath(directory); + } + QSettings cookieSettings(directory + QLatin1String("/cookies.ini"), QSettings::IniFormat); + QList cookies = allCookies(); + for (int i = cookies.count() - 1; i >= 0; --i) { + if (cookies.at(i).isSessionCookie()) + cookies.removeAt(i); + } + cookieSettings.setValue(QLatin1String("cookies"), QVariant::fromValue >(cookies)); + cookieSettings.beginGroup(QLatin1String("Exceptions")); + cookieSettings.setValue(QLatin1String("block"), m_exceptions_block); + cookieSettings.setValue(QLatin1String("allow"), m_exceptions_allow); + cookieSettings.setValue(QLatin1String("allowForSession"), m_exceptions_allowForSession); + + // save cookie settings + QSettings settings; + settings.beginGroup(QLatin1String("cookies")); + QMetaEnum acceptPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("AcceptPolicy")); + settings.setValue(QLatin1String("acceptCookies"), QLatin1String(acceptPolicyEnum.valueToKey(m_acceptCookies))); + + QMetaEnum keepPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("KeepPolicy")); + settings.setValue(QLatin1String("keepCookiesUntil"), QLatin1String(keepPolicyEnum.valueToKey(m_keepCookies))); +} + +void CookieJar::purgeOldCookies() +{ + QList cookies = allCookies(); + if (cookies.isEmpty()) + return; + int oldCount = cookies.count(); + QDateTime now = QDateTime::currentDateTime(); + for (int i = cookies.count() - 1; i >= 0; --i) { + if (!cookies.at(i).isSessionCookie() && cookies.at(i).expirationDate() < now) + cookies.removeAt(i); + } + if (oldCount == cookies.count()) + return; + setAllCookies(cookies); + emit cookiesChanged(); +} + +QList CookieJar::cookiesForUrl(const QUrl &url) const +{ + CookieJar *that = const_cast(this); + if (!m_loaded) + that->load(); + + QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); + if (globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) { + QList noCookies; + return noCookies; + } + + return QNetworkCookieJar::cookiesForUrl(url); +} + +bool CookieJar::setCookiesFromUrl(const QList &cookieList, const QUrl &url) +{ + if (!m_loaded) + load(); + + QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); + if (globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) + return false; + + QString host = url.host(); + bool eBlock = qBinaryFind(m_exceptions_block.begin(), m_exceptions_block.end(), host) != m_exceptions_block.end(); + bool eAllow = qBinaryFind(m_exceptions_allow.begin(), m_exceptions_allow.end(), host) != m_exceptions_allow.end(); + bool eAllowSession = qBinaryFind(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end(), host) != m_exceptions_allowForSession.end(); + + bool addedCookies = false; + // pass exceptions + bool acceptInitially = (m_acceptCookies != AcceptNever); + if ((acceptInitially && !eBlock) + || (!acceptInitially && (eAllow || eAllowSession))) { + // pass url domain == cookie domain + QDateTime soon = QDateTime::currentDateTime(); + soon = soon.addDays(90); + foreach (QNetworkCookie cookie, cookieList) { + QList lst; + if (m_keepCookies == KeepUntilTimeLimit + && !cookie.isSessionCookie() + && cookie.expirationDate() > soon) { + cookie.setExpirationDate(soon); + } + lst += cookie; + if (QNetworkCookieJar::setCookiesFromUrl(lst, url)) { + addedCookies = true; + } else { + // finally force it in if wanted + if (m_acceptCookies == AcceptAlways) { + QList cookies = allCookies(); + cookies += cookie; + setAllCookies(cookies); + addedCookies = true; + } +#if 0 + else + qWarning() << "setCookiesFromUrl failed" << url << cookieList.value(0).toRawForm(); +#endif + } + } + } + + if (addedCookies) { + m_saveTimer->changeOccurred(); + emit cookiesChanged(); + } + return addedCookies; +} + +CookieJar::AcceptPolicy CookieJar::acceptPolicy() const +{ + if (!m_loaded) + (const_cast(this))->load(); + return m_acceptCookies; +} + +void CookieJar::setAcceptPolicy(AcceptPolicy policy) +{ + if (!m_loaded) + load(); + if (policy == m_acceptCookies) + return; + m_acceptCookies = policy; + m_saveTimer->changeOccurred(); +} + +CookieJar::KeepPolicy CookieJar::keepPolicy() const +{ + if (!m_loaded) + (const_cast(this))->load(); + return m_keepCookies; +} + +void CookieJar::setKeepPolicy(KeepPolicy policy) +{ + if (!m_loaded) + load(); + if (policy == m_keepCookies) + return; + m_keepCookies = policy; + m_saveTimer->changeOccurred(); +} + +QStringList CookieJar::blockedCookies() const +{ + if (!m_loaded) + (const_cast(this))->load(); + return m_exceptions_block; +} + +QStringList CookieJar::allowedCookies() const +{ + if (!m_loaded) + (const_cast(this))->load(); + return m_exceptions_allow; +} + +QStringList CookieJar::allowForSessionCookies() const +{ + if (!m_loaded) + (const_cast(this))->load(); + return m_exceptions_allowForSession; +} + +void CookieJar::setBlockedCookies(const QStringList &list) +{ + if (!m_loaded) + load(); + m_exceptions_block = list; + qSort(m_exceptions_block.begin(), m_exceptions_block.end()); + m_saveTimer->changeOccurred(); +} + +void CookieJar::setAllowedCookies(const QStringList &list) +{ + if (!m_loaded) + load(); + m_exceptions_allow = list; + qSort(m_exceptions_allow.begin(), m_exceptions_allow.end()); + m_saveTimer->changeOccurred(); +} + +void CookieJar::setAllowForSessionCookies(const QStringList &list) +{ + if (!m_loaded) + load(); + m_exceptions_allowForSession = list; + qSort(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end()); + m_saveTimer->changeOccurred(); +} + +CookieModel::CookieModel(CookieJar *cookieJar, QObject *parent) + : QAbstractTableModel(parent) + , m_cookieJar(cookieJar) +{ + connect(m_cookieJar, SIGNAL(cookiesChanged()), this, SLOT(cookiesChanged())); + m_cookieJar->load(); +} + +QVariant CookieModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role == Qt::SizeHintRole) { + QFont font; + font.setPointSize(10); + QFontMetrics fm(font); + int height = fm.height() + fm.height()/3; + int width = fm.width(headerData(section, orientation, Qt::DisplayRole).toString()); + return QSize(width, height); + } + + if (orientation == Qt::Horizontal) { + if (role != Qt::DisplayRole) + return QVariant(); + + switch (section) { + case 0: + return tr("Website"); + case 1: + return tr("Name"); + case 2: + return tr("Path"); + case 3: + return tr("Secure"); + case 4: + return tr("Expires"); + case 5: + return tr("Contents"); + default: + return QVariant(); + } + } + return QAbstractTableModel::headerData(section, orientation, role); +} + +QVariant CookieModel::data(const QModelIndex &index, int role) const +{ + QList lst; + if (m_cookieJar) + lst = m_cookieJar->allCookies(); + if (index.row() < 0 || index.row() >= lst.size()) + return QVariant(); + + switch (role) { + case Qt::DisplayRole: + case Qt::EditRole: { + QNetworkCookie cookie = lst.at(index.row()); + switch (index.column()) { + case 0: + return cookie.domain(); + case 1: + return cookie.name(); + case 2: + return cookie.path(); + case 3: + return cookie.isSecure(); + case 4: + return cookie.expirationDate(); + case 5: + return cookie.value(); + } + } + case Qt::FontRole:{ + QFont font; + font.setPointSize(10); + return font; + } + } + + return QVariant(); +} + +int CookieModel::columnCount(const QModelIndex &parent) const +{ + return (parent.isValid()) ? 0 : 6; +} + +int CookieModel::rowCount(const QModelIndex &parent) const +{ + return (parent.isValid() || !m_cookieJar) ? 0 : m_cookieJar->allCookies().count(); +} + +bool CookieModel::removeRows(int row, int count, const QModelIndex &parent) +{ + if (parent.isValid() || !m_cookieJar) + return false; + int lastRow = row + count - 1; + beginRemoveRows(parent, row, lastRow); + QList lst = m_cookieJar->allCookies(); + for (int i = lastRow; i >= row; --i) { + lst.removeAt(i); + } + m_cookieJar->setAllCookies(lst); + endRemoveRows(); + return true; +} + +void CookieModel::cookiesChanged() +{ + beginResetModel(); + endResetModel(); +} + +CookiesDialog::CookiesDialog(CookieJar *cookieJar, QWidget *parent) : QDialog(parent) +{ + setupUi(this); + setWindowFlags(Qt::Sheet); + CookieModel *model = new CookieModel(cookieJar, this); + m_proxyModel = new QSortFilterProxyModel(this); + connect(search, SIGNAL(textChanged(QString)), + m_proxyModel, SLOT(setFilterFixedString(QString))); + connect(removeButton, SIGNAL(clicked()), cookiesTable, SLOT(removeOne())); + connect(removeAllButton, SIGNAL(clicked()), cookiesTable, SLOT(removeAll())); + m_proxyModel->setSourceModel(model); + cookiesTable->verticalHeader()->hide(); + cookiesTable->setSelectionBehavior(QAbstractItemView::SelectRows); + cookiesTable->setModel(m_proxyModel); + cookiesTable->setAlternatingRowColors(true); + cookiesTable->setTextElideMode(Qt::ElideMiddle); + cookiesTable->setShowGrid(false); + cookiesTable->setSortingEnabled(true); + QFont f = font(); + f.setPointSize(10); + QFontMetrics fm(f); + int height = fm.height() + fm.height()/3; + cookiesTable->verticalHeader()->setDefaultSectionSize(height); + cookiesTable->verticalHeader()->setMinimumSectionSize(-1); + for (int i = 0; i < model->columnCount(); ++i){ + int header = cookiesTable->horizontalHeader()->sectionSizeHint(i); + switch (i) { + case 0: + header = fm.width(QLatin1String("averagehost.domain.com")); + break; + case 1: + header = fm.width(QLatin1String("_session_id")); + break; + case 4: + header = fm.width(QDateTime::currentDateTime().toString(Qt::LocalDate)); + break; + } + int buffer = fm.width(QLatin1String("xx")); + header += buffer; + cookiesTable->horizontalHeader()->resizeSection(i, header); + } + cookiesTable->horizontalHeader()->setStretchLastSection(true); +} + + + +CookieExceptionsModel::CookieExceptionsModel(CookieJar *cookiejar, QObject *parent) + : QAbstractTableModel(parent) + , m_cookieJar(cookiejar) +{ + m_allowedCookies = m_cookieJar->allowedCookies(); + m_blockedCookies = m_cookieJar->blockedCookies(); + m_sessionCookies = m_cookieJar->allowForSessionCookies(); +} + +QVariant CookieExceptionsModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role == Qt::SizeHintRole) { + QFont font; + font.setPointSize(10); + QFontMetrics fm(font); + int height = fm.height() + fm.height()/3; + int width = fm.width(headerData(section, orientation, Qt::DisplayRole).toString()); + return QSize(width, height); + } + + if (orientation == Qt::Horizontal + && role == Qt::DisplayRole) { + switch (section) { + case 0: + return tr("Website"); + case 1: + return tr("Status"); + } + } + return QAbstractTableModel::headerData(section, orientation, role); +} + +QVariant CookieExceptionsModel::data(const QModelIndex &index, int role) const +{ + if (index.row() < 0 || index.row() >= rowCount()) + return QVariant(); + + switch (role) { + case Qt::DisplayRole: + case Qt::EditRole: { + int row = index.row(); + if (row < m_allowedCookies.count()) { + switch (index.column()) { + case 0: + return m_allowedCookies.at(row); + case 1: + return tr("Allow"); + } + } + row = row - m_allowedCookies.count(); + if (row < m_blockedCookies.count()) { + switch (index.column()) { + case 0: + return m_blockedCookies.at(row); + case 1: + return tr("Block"); + } + } + row = row - m_blockedCookies.count(); + if (row < m_sessionCookies.count()) { + switch (index.column()) { + case 0: + return m_sessionCookies.at(row); + case 1: + return tr("Allow For Session"); + } + } + } + case Qt::FontRole:{ + QFont font; + font.setPointSize(10); + return font; + } + } + return QVariant(); +} + +int CookieExceptionsModel::columnCount(const QModelIndex &parent) const +{ + return (parent.isValid()) ? 0 : 2; +} + +int CookieExceptionsModel::rowCount(const QModelIndex &parent) const +{ + return (parent.isValid() || !m_cookieJar) ? 0 : m_allowedCookies.count() + m_blockedCookies.count() + m_sessionCookies.count(); +} + +bool CookieExceptionsModel::removeRows(int row, int count, const QModelIndex &parent) +{ + if (parent.isValid() || !m_cookieJar) + return false; + + int lastRow = row + count - 1; + beginRemoveRows(parent, row, lastRow); + for (int i = lastRow; i >= row; --i) { + if (i < m_allowedCookies.count()) { + m_allowedCookies.removeAt(row); + continue; + } + i = i - m_allowedCookies.count(); + if (i < m_blockedCookies.count()) { + m_blockedCookies.removeAt(row); + continue; + } + i = i - m_blockedCookies.count(); + if (i < m_sessionCookies.count()) { + m_sessionCookies.removeAt(row); + continue; + } + } + m_cookieJar->setAllowedCookies(m_allowedCookies); + m_cookieJar->setBlockedCookies(m_blockedCookies); + m_cookieJar->setAllowForSessionCookies(m_sessionCookies); + endRemoveRows(); + return true; +} + +CookiesExceptionsDialog::CookiesExceptionsDialog(CookieJar *cookieJar, QWidget *parent) + : QDialog(parent) + , m_cookieJar(cookieJar) +{ + setupUi(this); + setWindowFlags(Qt::Sheet); + connect(removeButton, SIGNAL(clicked()), exceptionTable, SLOT(removeOne())); + connect(removeAllButton, SIGNAL(clicked()), exceptionTable, SLOT(removeAll())); + exceptionTable->verticalHeader()->hide(); + exceptionTable->setSelectionBehavior(QAbstractItemView::SelectRows); + exceptionTable->setAlternatingRowColors(true); + exceptionTable->setTextElideMode(Qt::ElideMiddle); + exceptionTable->setShowGrid(false); + exceptionTable->setSortingEnabled(true); + m_exceptionsModel = new CookieExceptionsModel(cookieJar, this); + m_proxyModel = new QSortFilterProxyModel(this); + m_proxyModel->setSourceModel(m_exceptionsModel); + connect(search, SIGNAL(textChanged(QString)), + m_proxyModel, SLOT(setFilterFixedString(QString))); + exceptionTable->setModel(m_proxyModel); + + CookieModel *cookieModel = new CookieModel(cookieJar, this); + domainLineEdit->setCompleter(new QCompleter(cookieModel, domainLineEdit)); + + connect(domainLineEdit, SIGNAL(textChanged(QString)), + this, SLOT(textChanged(QString))); + connect(blockButton, SIGNAL(clicked()), this, SLOT(block())); + connect(allowButton, SIGNAL(clicked()), this, SLOT(allow())); + connect(allowForSessionButton, SIGNAL(clicked()), this, SLOT(allowForSession())); + + QFont f = font(); + f.setPointSize(10); + QFontMetrics fm(f); + int height = fm.height() + fm.height()/3; + exceptionTable->verticalHeader()->setDefaultSectionSize(height); + exceptionTable->verticalHeader()->setMinimumSectionSize(-1); + for (int i = 0; i < m_exceptionsModel->columnCount(); ++i){ + int header = exceptionTable->horizontalHeader()->sectionSizeHint(i); + switch (i) { + case 0: + header = fm.width(QLatin1String("averagebiglonghost.domain.com")); + break; + case 1: + header = fm.width(QLatin1String("Allow For Session")); + break; + } + int buffer = fm.width(QLatin1String("xx")); + header += buffer; + exceptionTable->horizontalHeader()->resizeSection(i, header); + } +} + +void CookiesExceptionsDialog::textChanged(const QString &text) +{ + bool enabled = !text.isEmpty(); + blockButton->setEnabled(enabled); + allowButton->setEnabled(enabled); + allowForSessionButton->setEnabled(enabled); +} + +void CookiesExceptionsDialog::block() +{ + if (domainLineEdit->text().isEmpty()) + return; + m_exceptionsModel->m_blockedCookies.append(domainLineEdit->text()); + m_cookieJar->setBlockedCookies(m_exceptionsModel->m_blockedCookies); + m_exceptionsModel->beginResetModel(); + m_exceptionsModel->endResetModel(); +} + +void CookiesExceptionsDialog::allow() +{ + if (domainLineEdit->text().isEmpty()) + return; + m_exceptionsModel->m_allowedCookies.append(domainLineEdit->text()); + m_cookieJar->setAllowedCookies(m_exceptionsModel->m_allowedCookies); + m_exceptionsModel->beginResetModel(); + m_exceptionsModel->endResetModel(); +} + +void CookiesExceptionsDialog::allowForSession() +{ + if (domainLineEdit->text().isEmpty()) + return; + m_exceptionsModel->m_sessionCookies.append(domainLineEdit->text()); + m_cookieJar->setAllowForSessionCookies(m_exceptionsModel->m_sessionCookies); + m_exceptionsModel->beginResetModel(); + m_exceptionsModel->endResetModel(); +} diff --git a/examples/webenginewidgets/browser/cookiejar.h b/examples/webenginewidgets/browser/cookiejar.h new file mode 100644 index 000000000..1cc7800e1 --- /dev/null +++ b/examples/webenginewidgets/browser/cookiejar.h @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef COOKIEJAR_H +#define COOKIEJAR_H + +#include + +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE +class QSortFilterProxyModel; +class QKeyEvent; +QT_END_NAMESPACE + +class AutoSaver; + +class CookieJar : public QNetworkCookieJar +{ + friend class CookieModel; + Q_OBJECT + Q_PROPERTY(AcceptPolicy acceptPolicy READ acceptPolicy WRITE setAcceptPolicy) + Q_PROPERTY(KeepPolicy keepPolicy READ keepPolicy WRITE setKeepPolicy) + Q_PROPERTY(QStringList blockedCookies READ blockedCookies WRITE setBlockedCookies) + Q_PROPERTY(QStringList allowedCookies READ allowedCookies WRITE setAllowedCookies) + Q_PROPERTY(QStringList allowForSessionCookies READ allowForSessionCookies WRITE setAllowForSessionCookies) + Q_ENUMS(KeepPolicy) + Q_ENUMS(AcceptPolicy) + +signals: + void cookiesChanged(); + +public: + enum AcceptPolicy { + AcceptAlways, + AcceptNever, + AcceptOnlyFromSitesNavigatedTo + }; + + enum KeepPolicy { + KeepUntilExpire, + KeepUntilExit, + KeepUntilTimeLimit + }; + + CookieJar(QObject *parent = 0); + ~CookieJar(); + + QList cookiesForUrl(const QUrl &url) const; + bool setCookiesFromUrl(const QList &cookieList, const QUrl &url); + + AcceptPolicy acceptPolicy() const; + void setAcceptPolicy(AcceptPolicy policy); + + KeepPolicy keepPolicy() const; + void setKeepPolicy(KeepPolicy policy); + + QStringList blockedCookies() const; + QStringList allowedCookies() const; + QStringList allowForSessionCookies() const; + + void setBlockedCookies(const QStringList &list); + void setAllowedCookies(const QStringList &list); + void setAllowForSessionCookies(const QStringList &list); + +public slots: + void clear(); + void loadSettings(); + +private slots: + void save(); + +private: + void purgeOldCookies(); + void load(); + bool m_loaded; + AutoSaver *m_saveTimer; + + AcceptPolicy m_acceptCookies; + KeepPolicy m_keepCookies; + + QStringList m_exceptions_block; + QStringList m_exceptions_allow; + QStringList m_exceptions_allowForSession; +}; + +class CookieModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + CookieModel(CookieJar *jar, QObject *parent = 0); + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + +private slots: + void cookiesChanged(); + +private: + CookieJar *m_cookieJar; +}; + +#include "ui_cookies.h" +#include "ui_cookiesexceptions.h" + +class CookiesDialog : public QDialog, public Ui_CookiesDialog +{ + Q_OBJECT + +public: + CookiesDialog(CookieJar *cookieJar, QWidget *parent = 0); + +private: + QSortFilterProxyModel *m_proxyModel; +}; + +class CookieExceptionsModel : public QAbstractTableModel +{ + Q_OBJECT + friend class CookiesExceptionsDialog; + +public: + CookieExceptionsModel(CookieJar *cookieJar, QObject *parent = 0); + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + +private: + CookieJar *m_cookieJar; + + // Domains we allow, Domains we block, Domains we allow for this session + QStringList m_allowedCookies; + QStringList m_blockedCookies; + QStringList m_sessionCookies; +}; + +class CookiesExceptionsDialog : public QDialog, public Ui_CookiesExceptionsDialog +{ + Q_OBJECT + +public: + CookiesExceptionsDialog(CookieJar *cookieJar, QWidget *parent = 0); + +private slots: + void block(); + void allow(); + void allowForSession(); + void textChanged(const QString &text); + +private: + CookieExceptionsModel *m_exceptionsModel; + QSortFilterProxyModel *m_proxyModel; + CookieJar *m_cookieJar; +}; + +#endif // COOKIEJAR_H diff --git a/examples/webenginewidgets/browser/cookies.ui b/examples/webenginewidgets/browser/cookies.ui new file mode 100644 index 000000000..c4bccc548 --- /dev/null +++ b/examples/webenginewidgets/browser/cookies.ui @@ -0,0 +1,106 @@ + + CookiesDialog + + + + 0 + 0 + 550 + 370 + + + + Cookies + + + + + + Qt::Horizontal + + + + 252 + 20 + + + + + + + + + + + + + + + + &Remove + + + + + + + Remove &All Cookies + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + QDialogButtonBox::Ok + + + + + + + + + + SearchLineEdit + QLineEdit +

searchlineedit.h
+ + + EditTableView + QTableView +
edittableview.h
+
+ + + + + buttonBox + accepted() + CookiesDialog + accept() + + + 472 + 329 + + + 461 + 356 + + + + + diff --git a/examples/webenginewidgets/browser/cookiesexceptions.ui b/examples/webenginewidgets/browser/cookiesexceptions.ui new file mode 100644 index 000000000..3d9ef6241 --- /dev/null +++ b/examples/webenginewidgets/browser/cookiesexceptions.ui @@ -0,0 +1,184 @@ + + CookiesExceptionsDialog + + + + 0 + 0 + 466 + 446 + + + + Cookie Exceptions + + + + + + New Exception + + + + + + + + Domain: + + + + + + + + + + + + + + Qt::Horizontal + + + + 81 + 25 + + + + + + + + false + + + Block + + + + + + + false + + + Allow For Session + + + + + + + false + + + Allow + + + + + + + + + + + + Exceptions + + + + + + Qt::Horizontal + + + + 252 + 20 + + + + + + + + + + + + + + &Remove + + + + + + + Remove &All + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + SearchLineEdit + QLineEdit +
searchlineedit.h
+
+ + EditTableView + QTableView +
edittableview.h
+
+
+ + + + buttonBox + accepted() + CookiesExceptionsDialog + accept() + + + 381 + 428 + + + 336 + 443 + + + + +
diff --git a/examples/webenginewidgets/browser/data/addtab.png b/examples/webenginewidgets/browser/data/addtab.png new file mode 100644 index 000000000..20928fb40 Binary files /dev/null and b/examples/webenginewidgets/browser/data/addtab.png differ diff --git a/examples/webenginewidgets/browser/data/browser.svg b/examples/webenginewidgets/browser/data/browser.svg new file mode 100644 index 000000000..8795187b1 --- /dev/null +++ b/examples/webenginewidgets/browser/data/browser.svg @@ -0,0 +1,411 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Qt Browser + + + Jens Bache-Wiig + + + + + Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/webenginewidgets/browser/data/closetab.png b/examples/webenginewidgets/browser/data/closetab.png new file mode 100644 index 000000000..ab9d669ee Binary files /dev/null and b/examples/webenginewidgets/browser/data/closetab.png differ diff --git a/examples/webenginewidgets/browser/data/data.qrc b/examples/webenginewidgets/browser/data/data.qrc new file mode 100644 index 000000000..c7d0294c1 --- /dev/null +++ b/examples/webenginewidgets/browser/data/data.qrc @@ -0,0 +1,11 @@ + + + addtab.png + closetab.png + history.png + browser.svg + defaultbookmarks.xbel + loading.gif + defaulticon.png + + diff --git a/examples/webenginewidgets/browser/data/defaultbookmarks.xbel b/examples/webenginewidgets/browser/data/defaultbookmarks.xbel new file mode 100644 index 000000000..7a95e36b3 --- /dev/null +++ b/examples/webenginewidgets/browser/data/defaultbookmarks.xbel @@ -0,0 +1,43 @@ + + + + + Bookmarks Bar + + Qt Home Page + + + WebKit.org + + + Qt Documentation + + + Qt Quarterly + + + Qt Blog + + + Qt Centre + + + Qt-Apps.org + + + Online Communities + + + xkcd + + + Twitter + + + + Bookmarks Menu + + reddit.com: what's new online! + + + diff --git a/examples/webenginewidgets/browser/data/defaulticon.png b/examples/webenginewidgets/browser/data/defaulticon.png new file mode 100644 index 000000000..01a0920c9 Binary files /dev/null and b/examples/webenginewidgets/browser/data/defaulticon.png differ diff --git a/examples/webenginewidgets/browser/data/history.png b/examples/webenginewidgets/browser/data/history.png new file mode 100644 index 000000000..552a1cbd8 Binary files /dev/null and b/examples/webenginewidgets/browser/data/history.png differ diff --git a/examples/webenginewidgets/browser/data/loading.gif b/examples/webenginewidgets/browser/data/loading.gif new file mode 100644 index 000000000..c1545eb0e Binary files /dev/null and b/examples/webenginewidgets/browser/data/loading.gif differ diff --git a/examples/webenginewidgets/browser/doc/images/browser-demo.png b/examples/webenginewidgets/browser/doc/images/browser-demo.png new file mode 100644 index 000000000..09d065095 Binary files /dev/null and b/examples/webenginewidgets/browser/doc/images/browser-demo.png differ diff --git a/examples/webenginewidgets/browser/doc/src/browser.qdoc b/examples/webenginewidgets/browser/doc/src/browser.qdoc new file mode 100644 index 000000000..4e53de38f --- /dev/null +++ b/examples/webenginewidgets/browser/doc/src/browser.qdoc @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example webkitwidgets/browser + \title Tab Browser + \brief Demonstrates a complete web browsing experience + \ingroup webkit-widgetexamples + + The Tab Browser example shows \l{Qt WebKit} module in action, + providing a little Web browser application with support for tabs. + + \image browser-demo.png + + This browser is the foundation for the \l{Arora Browser}, a simple cross-platform + Web browser. +*/ diff --git a/examples/webenginewidgets/browser/downloaditem.ui b/examples/webenginewidgets/browser/downloaditem.ui new file mode 100644 index 000000000..4a0a0fd9a --- /dev/null +++ b/examples/webenginewidgets/browser/downloaditem.ui @@ -0,0 +1,134 @@ + + DownloadItem + + + + 0 + 0 + 423 + 110 + + + + Form + + + + 0 + + + + + + 0 + 0 + + + + Ico + + + + + + + + + + 0 + 0 + + + + Filename + + + + + + + 0 + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Qt::Vertical + + + + 17 + 1 + + + + + + + + false + + + Try Again + + + + + + + Stop + + + + + + + Open + + + + + + + Qt::Vertical + + + + 17 + 5 + + + + + + + + + + + SqueezeLabel + QWidget +
squeezelabel.h
+
+
+ + +
diff --git a/examples/webenginewidgets/browser/downloadmanager.cpp b/examples/webenginewidgets/browser/downloadmanager.cpp new file mode 100644 index 000000000..6f4c6c8ad --- /dev/null +++ b/examples/webenginewidgets/browser/downloadmanager.cpp @@ -0,0 +1,580 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "downloadmanager.h" + +#include "autosaver.h" +#include "browserapplication.h" +#include "networkaccessmanager.h" + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include + +/*! + DownloadItem is a widget that is displayed in the download manager list. + It moves the data from the QNetworkReply into the QFile as well + as update the information/progressbar and report errors. + */ +DownloadItem::DownloadItem(QNetworkReply *reply, bool requestFileName, QWidget *parent) + : QWidget(parent) + , m_reply(reply) + , m_requestFileName(requestFileName) + , m_bytesReceived(0) +{ + setupUi(this); + QPalette p = downloadInfoLabel->palette(); + p.setColor(QPalette::Text, Qt::darkGray); + downloadInfoLabel->setPalette(p); + progressBar->setMaximum(0); + tryAgainButton->hide(); + connect(stopButton, SIGNAL(clicked()), this, SLOT(stop())); + connect(openButton, SIGNAL(clicked()), this, SLOT(open())); + connect(tryAgainButton, SIGNAL(clicked()), this, SLOT(tryAgain())); + + init(); +} + +void DownloadItem::init() +{ + if (!m_reply) + return; + + // attach to the m_reply + m_url = m_reply->url(); + m_reply->setParent(this); + connect(m_reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead())); + connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(error(QNetworkReply::NetworkError))); + connect(m_reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(downloadProgress(qint64,qint64))); + connect(m_reply, SIGNAL(metaDataChanged()), + this, SLOT(metaDataChanged())); + connect(m_reply, SIGNAL(finished()), + this, SLOT(finished())); + + // reset info + downloadInfoLabel->clear(); + progressBar->setValue(0); + getFileName(); + + // start timer for the download estimation + m_downloadTime.start(); + + if (m_reply->error() != QNetworkReply::NoError) { + error(m_reply->error()); + finished(); + } +} + +void DownloadItem::getFileName() +{ + QSettings settings; + settings.beginGroup(QLatin1String("downloadmanager")); + QString defaultLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); + QString downloadDirectory = settings.value(QLatin1String("downloadDirectory"), defaultLocation).toString(); + if (!downloadDirectory.isEmpty()) + downloadDirectory += QLatin1Char('/'); + + QString defaultFileName = saveFileName(downloadDirectory); + QString fileName = defaultFileName; + if (m_requestFileName) { + fileName = QFileDialog::getSaveFileName(this, tr("Save File"), defaultFileName); + if (fileName.isEmpty()) { + m_reply->close(); + fileNameLabel->setText(tr("Download canceled: %1").arg(QFileInfo(defaultFileName).fileName())); + return; + } + } + m_output.setFileName(fileName); + fileNameLabel->setText(QFileInfo(m_output.fileName()).fileName()); + if (m_requestFileName) + downloadReadyRead(); +} + +QString DownloadItem::saveFileName(const QString &directory) const +{ + // Move this function into QNetworkReply to also get file name sent from the server + QString path = m_url.path(); + QFileInfo info(path); + QString baseName = info.completeBaseName(); + QString endName = info.suffix(); + + if (baseName.isEmpty()) { + baseName = QLatin1String("unnamed_download"); + qDebug() << "DownloadManager:: downloading unknown file:" << m_url; + } + QString name = directory + baseName + QLatin1Char('.') + endName; + if (QFile::exists(name)) { + // already exists, don't overwrite + int i = 1; + do { + name = directory + baseName + QLatin1Char('-') + QString::number(i++) + QLatin1Char('.') + endName; + } while (QFile::exists(name)); + } + return name; +} + + +void DownloadItem::stop() +{ + setUpdatesEnabled(false); + stopButton->setEnabled(false); + stopButton->hide(); + tryAgainButton->setEnabled(true); + tryAgainButton->show(); + setUpdatesEnabled(true); + m_reply->abort(); +} + +void DownloadItem::open() +{ + QFileInfo info(m_output); + QUrl url = QUrl::fromLocalFile(info.absolutePath()); + QDesktopServices::openUrl(url); +} + +void DownloadItem::tryAgain() +{ + if (!tryAgainButton->isEnabled()) + return; + + tryAgainButton->setEnabled(false); + tryAgainButton->setVisible(false); + stopButton->setEnabled(true); + stopButton->setVisible(true); + progressBar->setVisible(true); + + QNetworkReply *r = BrowserApplication::networkAccessManager()->get(QNetworkRequest(m_url)); + if (m_reply) + m_reply->deleteLater(); + if (m_output.exists()) + m_output.remove(); + m_reply = r; + init(); + emit statusChanged(); +} + +void DownloadItem::downloadReadyRead() +{ + if (m_requestFileName && m_output.fileName().isEmpty()) + return; + if (!m_output.isOpen()) { + // in case someone else has already put a file there + if (!m_requestFileName) + getFileName(); + if (!m_output.open(QIODevice::WriteOnly)) { + downloadInfoLabel->setText(tr("Error opening save file: %1") + .arg(m_output.errorString())); + stopButton->click(); + emit statusChanged(); + return; + } + emit statusChanged(); + } + if (-1 == m_output.write(m_reply->readAll())) { + downloadInfoLabel->setText(tr("Error saving: %1") + .arg(m_output.errorString())); + stopButton->click(); + } +} + +void DownloadItem::error(QNetworkReply::NetworkError) +{ + qDebug() << "DownloadItem::error" << m_reply->errorString() << m_url; + downloadInfoLabel->setText(tr("Network Error: %1").arg(m_reply->errorString())); + tryAgainButton->setEnabled(true); + tryAgainButton->setVisible(true); +} + +void DownloadItem::metaDataChanged() +{ + qDebug() << "DownloadItem::metaDataChanged: not handled."; +} + +void DownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + m_bytesReceived = bytesReceived; + if (bytesTotal == -1) { + progressBar->setValue(0); + progressBar->setMaximum(0); + } else { + progressBar->setValue(bytesReceived); + progressBar->setMaximum(bytesTotal); + } + updateInfoLabel(); +} + +void DownloadItem::updateInfoLabel() +{ + if (m_reply->error() == QNetworkReply::NoError) + return; + + qint64 bytesTotal = progressBar->maximum(); + bool running = !downloadedSuccessfully(); + + // update info label + double speed = m_bytesReceived * 1000.0 / m_downloadTime.elapsed(); + double timeRemaining = ((double)(bytesTotal - m_bytesReceived)) / speed; + QString timeRemainingString = tr("seconds"); + if (timeRemaining > 60) { + timeRemaining = timeRemaining / 60; + timeRemainingString = tr("minutes"); + } + timeRemaining = floor(timeRemaining); + + // When downloading the eta should never be 0 + if (timeRemaining == 0) + timeRemaining = 1; + + QString info; + if (running) { + QString remaining; + if (bytesTotal != 0) + remaining = tr("- %4 %5 remaining") + .arg(timeRemaining) + .arg(timeRemainingString); + info = tr("%1 of %2 (%3/sec) %4") + .arg(dataString(m_bytesReceived)) + .arg(bytesTotal == 0 ? tr("?") : dataString(bytesTotal)) + .arg(dataString((int)speed)) + .arg(remaining); + } else { + if (m_bytesReceived == bytesTotal) + info = dataString(m_output.size()); + else + info = tr("%1 of %2 - Stopped") + .arg(dataString(m_bytesReceived)) + .arg(dataString(bytesTotal)); + } + downloadInfoLabel->setText(info); +} + +QString DownloadItem::dataString(int size) const +{ + QString unit; + if (size < 1024) { + unit = tr("bytes"); + } else if (size < 1024*1024) { + size /= 1024; + unit = tr("kB"); + } else { + size /= 1024*1024; + unit = tr("MB"); + } + return QString(QLatin1String("%1 %2")).arg(size).arg(unit); +} + +bool DownloadItem::downloading() const +{ + return (progressBar->isVisible()); +} + +bool DownloadItem::downloadedSuccessfully() const +{ + return (stopButton->isHidden() && tryAgainButton->isHidden()); +} + +void DownloadItem::finished() +{ + progressBar->hide(); + stopButton->setEnabled(false); + stopButton->hide(); + m_output.close(); + updateInfoLabel(); + emit statusChanged(); +} + +/*! + DownloadManager is a Dialog that contains a list of DownloadItems + + It is a basic download manager. It only downloads the file, doesn't do BitTorrent, + extract zipped files or anything fancy. + */ +DownloadManager::DownloadManager(QWidget *parent) + : QDialog(parent) + , m_autoSaver(new AutoSaver(this)) + , m_manager(BrowserApplication::networkAccessManager()) + , m_iconProvider(0) + , m_removePolicy(Never) +{ + setupUi(this); + downloadsView->setShowGrid(false); + downloadsView->verticalHeader()->hide(); + downloadsView->horizontalHeader()->hide(); + downloadsView->setAlternatingRowColors(true); + downloadsView->horizontalHeader()->setStretchLastSection(true); + m_model = new DownloadModel(this); + downloadsView->setModel(m_model); + connect(cleanupButton, SIGNAL(clicked()), this, SLOT(cleanup())); + load(); +} + +DownloadManager::~DownloadManager() +{ + m_autoSaver->changeOccurred(); + m_autoSaver->saveIfNeccessary(); + if (m_iconProvider) + delete m_iconProvider; +} + +int DownloadManager::activeDownloads() const +{ + int count = 0; + for (int i = 0; i < m_downloads.count(); ++i) { + if (m_downloads.at(i)->stopButton->isEnabled()) + ++count; + } + return count; +} + +void DownloadManager::download(const QNetworkRequest &request, bool requestFileName) +{ + if (request.url().isEmpty()) + return; + handleUnsupportedContent(m_manager->get(request), requestFileName); +} + +void DownloadManager::handleUnsupportedContent(QNetworkReply *reply, bool requestFileName) +{ + if (!reply || reply->url().isEmpty()) + return; + QVariant header = reply->header(QNetworkRequest::ContentLengthHeader); + bool ok; + int size = header.toInt(&ok); + if (ok && size == 0) + return; + + qDebug() << "DownloadManager::handleUnsupportedContent" << reply->url() << "requestFileName" << requestFileName; + DownloadItem *item = new DownloadItem(reply, requestFileName, this); + addItem(item); +} + +void DownloadManager::addItem(DownloadItem *item) +{ + connect(item, SIGNAL(statusChanged()), this, SLOT(updateRow())); + int row = m_downloads.count(); + m_model->beginInsertRows(QModelIndex(), row, row); + m_downloads.append(item); + m_model->endInsertRows(); + updateItemCount(); + if (row == 0) + show(); + downloadsView->setIndexWidget(m_model->index(row, 0), item); + QIcon icon = style()->standardIcon(QStyle::SP_FileIcon); + item->fileIcon->setPixmap(icon.pixmap(48, 48)); + downloadsView->setRowHeight(row, item->sizeHint().height()); +} + +void DownloadManager::updateRow() +{ + DownloadItem *item = qobject_cast(sender()); + int row = m_downloads.indexOf(item); + if (-1 == row) + return; + if (!m_iconProvider) + m_iconProvider = new QFileIconProvider(); + QIcon icon = m_iconProvider->icon(item->m_output.fileName()); + if (icon.isNull()) + icon = style()->standardIcon(QStyle::SP_FileIcon); + item->fileIcon->setPixmap(icon.pixmap(48, 48)); + downloadsView->setRowHeight(row, item->minimumSizeHint().height()); + + bool remove = false; +#if defined(QWEBENGINESETTINGS) + QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); + if (!item->downloading() + && globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) + remove = true; +#endif + + if (item->downloadedSuccessfully() + && removePolicy() == DownloadManager::SuccessFullDownload) { + remove = true; + } + if (remove) + m_model->removeRow(row); + + cleanupButton->setEnabled(m_downloads.count() - activeDownloads() > 0); +} + +DownloadManager::RemovePolicy DownloadManager::removePolicy() const +{ + return m_removePolicy; +} + +void DownloadManager::setRemovePolicy(RemovePolicy policy) +{ + if (policy == m_removePolicy) + return; + m_removePolicy = policy; + m_autoSaver->changeOccurred(); +} + +void DownloadManager::save() const +{ + QSettings settings; + settings.beginGroup(QLatin1String("downloadmanager")); + QMetaEnum removePolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("RemovePolicy")); + settings.setValue(QLatin1String("removeDownloadsPolicy"), QLatin1String(removePolicyEnum.valueToKey(m_removePolicy))); + settings.setValue(QLatin1String("size"), size()); + if (m_removePolicy == Exit) + return; + + for (int i = 0; i < m_downloads.count(); ++i) { + QString key = QString(QLatin1String("download_%1_")).arg(i); + settings.setValue(key + QLatin1String("url"), m_downloads[i]->m_url); + settings.setValue(key + QLatin1String("location"), QFileInfo(m_downloads[i]->m_output).filePath()); + settings.setValue(key + QLatin1String("done"), m_downloads[i]->downloadedSuccessfully()); + } + int i = m_downloads.count(); + QString key = QString(QLatin1String("download_%1_")).arg(i); + while (settings.contains(key + QLatin1String("url"))) { + settings.remove(key + QLatin1String("url")); + settings.remove(key + QLatin1String("location")); + settings.remove(key + QLatin1String("done")); + key = QString(QLatin1String("download_%1_")).arg(++i); + } +} + +void DownloadManager::load() +{ + QSettings settings; + settings.beginGroup(QLatin1String("downloadmanager")); + QSize size = settings.value(QLatin1String("size")).toSize(); + if (size.isValid()) + resize(size); + QByteArray value = settings.value(QLatin1String("removeDownloadsPolicy"), QLatin1String("Never")).toByteArray(); + QMetaEnum removePolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("RemovePolicy")); + m_removePolicy = removePolicyEnum.keyToValue(value) == -1 ? + Never : + static_cast(removePolicyEnum.keyToValue(value)); + + int i = 0; + QString key = QString(QLatin1String("download_%1_")).arg(i); + while (settings.contains(key + QLatin1String("url"))) { + QUrl url = settings.value(key + QLatin1String("url")).toUrl(); + QString fileName = settings.value(key + QLatin1String("location")).toString(); + bool done = settings.value(key + QLatin1String("done"), true).toBool(); + if (!url.isEmpty() && !fileName.isEmpty()) { + DownloadItem *item = new DownloadItem(0, this); + item->m_output.setFileName(fileName); + item->fileNameLabel->setText(QFileInfo(item->m_output.fileName()).fileName()); + item->m_url = url; + item->stopButton->setVisible(false); + item->stopButton->setEnabled(false); + item->tryAgainButton->setVisible(!done); + item->tryAgainButton->setEnabled(!done); + item->progressBar->setVisible(!done); + addItem(item); + } + key = QString(QLatin1String("download_%1_")).arg(++i); + } + cleanupButton->setEnabled(m_downloads.count() - activeDownloads() > 0); +} + +void DownloadManager::cleanup() +{ + if (m_downloads.isEmpty()) + return; + m_model->removeRows(0, m_downloads.count()); + updateItemCount(); + if (m_downloads.isEmpty() && m_iconProvider) { + delete m_iconProvider; + m_iconProvider = 0; + } + m_autoSaver->changeOccurred(); +} + +void DownloadManager::updateItemCount() +{ + int count = m_downloads.count(); + itemCount->setText(count == 1 ? tr("1 Download") : tr("%1 Downloads").arg(count)); +} + +DownloadModel::DownloadModel(DownloadManager *downloadManager, QObject *parent) + : QAbstractListModel(parent) + , m_downloadManager(downloadManager) +{ +} + +QVariant DownloadModel::data(const QModelIndex &index, int role) const +{ + if (index.row() < 0 || index.row() >= rowCount(index.parent())) + return QVariant(); + if (role == Qt::ToolTipRole) + if (!m_downloadManager->m_downloads.at(index.row())->downloadedSuccessfully()) + return m_downloadManager->m_downloads.at(index.row())->downloadInfoLabel->text(); + return QVariant(); +} + +int DownloadModel::rowCount(const QModelIndex &parent) const +{ + return (parent.isValid()) ? 0 : m_downloadManager->m_downloads.count(); +} + +bool DownloadModel::removeRows(int row, int count, const QModelIndex &parent) +{ + if (parent.isValid()) + return false; + + int lastRow = row + count - 1; + for (int i = lastRow; i >= row; --i) { + if (m_downloadManager->m_downloads.at(i)->downloadedSuccessfully() + || m_downloadManager->m_downloads.at(i)->tryAgainButton->isEnabled()) { + beginRemoveRows(parent, i, i); + m_downloadManager->m_downloads.takeAt(i)->deleteLater(); + endRemoveRows(); + } + } + m_downloadManager->m_autoSaver->changeOccurred(); + return true; +} diff --git a/examples/webenginewidgets/browser/downloadmanager.h b/examples/webenginewidgets/browser/downloadmanager.h new file mode 100644 index 000000000..072e99efd --- /dev/null +++ b/examples/webenginewidgets/browser/downloadmanager.h @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DOWNLOADMANAGER_H +#define DOWNLOADMANAGER_H + +#include "ui_downloads.h" +#include "ui_downloaditem.h" + +#include + +#include +#include + +class DownloadItem : public QWidget, public Ui_DownloadItem +{ + Q_OBJECT + +signals: + void statusChanged(); + +public: + DownloadItem(QNetworkReply *reply = 0, bool requestFileName = false, QWidget *parent = 0); + bool downloading() const; + bool downloadedSuccessfully() const; + + QUrl m_url; + + QFile m_output; + QNetworkReply *m_reply; + +private slots: + void stop(); + void tryAgain(); + void open(); + + void downloadReadyRead(); + void error(QNetworkReply::NetworkError code); + void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); + void metaDataChanged(); + void finished(); + +private: + void getFileName(); + void init(); + void updateInfoLabel(); + QString dataString(int size) const; + + QString saveFileName(const QString &directory) const; + + bool m_requestFileName; + qint64 m_bytesReceived; + QTime m_downloadTime; +}; + +class AutoSaver; +class DownloadModel; +QT_BEGIN_NAMESPACE +class QFileIconProvider; +QT_END_NAMESPACE + +class DownloadManager : public QDialog, public Ui_DownloadDialog +{ + Q_OBJECT + Q_PROPERTY(RemovePolicy removePolicy READ removePolicy WRITE setRemovePolicy) + Q_ENUMS(RemovePolicy) + +public: + enum RemovePolicy { + Never, + Exit, + SuccessFullDownload + }; + + DownloadManager(QWidget *parent = 0); + ~DownloadManager(); + int activeDownloads() const; + + RemovePolicy removePolicy() const; + void setRemovePolicy(RemovePolicy policy); + +public slots: + void download(const QNetworkRequest &request, bool requestFileName = false); + inline void download(const QUrl &url, bool requestFileName = false) + { download(QNetworkRequest(url), requestFileName); } + void handleUnsupportedContent(QNetworkReply *reply, bool requestFileName = false); + void cleanup(); + +private slots: + void save() const; + void updateRow(); + +private: + void addItem(DownloadItem *item); + void updateItemCount(); + void load(); + + AutoSaver *m_autoSaver; + DownloadModel *m_model; + QNetworkAccessManager *m_manager; + QFileIconProvider *m_iconProvider; + QList m_downloads; + RemovePolicy m_removePolicy; + friend class DownloadModel; +}; + +class DownloadModel : public QAbstractListModel +{ + friend class DownloadManager; + Q_OBJECT + +public: + DownloadModel(DownloadManager *downloadManager, QObject *parent = 0); + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + +private: + DownloadManager *m_downloadManager; + +}; + +#endif // DOWNLOADMANAGER_H diff --git a/examples/webenginewidgets/browser/downloads.ui b/examples/webenginewidgets/browser/downloads.ui new file mode 100644 index 000000000..a2e256935 --- /dev/null +++ b/examples/webenginewidgets/browser/downloads.ui @@ -0,0 +1,83 @@ + + DownloadDialog + + + + 0 + 0 + 332 + 252 + + + + Downloads + + + + 0 + + + 0 + + + + + + + + + + false + + + Clean up + + + + + + + Qt::Horizontal + + + + 58 + 24 + + + + + + + + + + 0 Items + + + + + + + Qt::Horizontal + + + + 148 + 20 + + + + + + + + + EditTableView + QTableView +
edittableview.h
+
+
+ + +
diff --git a/examples/webenginewidgets/browser/edittableview.cpp b/examples/webenginewidgets/browser/edittableview.cpp new file mode 100644 index 000000000..71d9b5706 --- /dev/null +++ b/examples/webenginewidgets/browser/edittableview.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "edittableview.h" +#include + +EditTableView::EditTableView(QWidget *parent) + : QTableView(parent) +{ +} + +void EditTableView::keyPressEvent(QKeyEvent *event) +{ + if ((event->key() == Qt::Key_Delete + || event->key() == Qt::Key_Backspace) + && model()) { + removeOne(); + } else { + QAbstractItemView::keyPressEvent(event); + } +} + +void EditTableView::removeOne() +{ + if (!model() || !selectionModel()) + return; + int row = currentIndex().row(); + model()->removeRow(row, rootIndex()); + QModelIndex idx = model()->index(row, 0, rootIndex()); + if (!idx.isValid()) + idx = model()->index(row - 1, 0, rootIndex()); + selectionModel()->select(idx, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); +} + +void EditTableView::removeAll() +{ + if (model()) + model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex()); +} diff --git a/examples/webenginewidgets/browser/edittableview.h b/examples/webenginewidgets/browser/edittableview.h new file mode 100644 index 000000000..1c865ad42 --- /dev/null +++ b/examples/webenginewidgets/browser/edittableview.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EDITTABLEVIEW_H +#define EDITTABLEVIEW_H + +#include + +class EditTableView : public QTableView +{ + Q_OBJECT + +public: + EditTableView(QWidget *parent = 0); + void keyPressEvent(QKeyEvent *event); + +public slots: + void removeOne(); + void removeAll(); +}; + +#endif // EDITTABLEVIEW_H diff --git a/examples/webenginewidgets/browser/edittreeview.cpp b/examples/webenginewidgets/browser/edittreeview.cpp new file mode 100644 index 000000000..5b8007856 --- /dev/null +++ b/examples/webenginewidgets/browser/edittreeview.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "edittreeview.h" + +#include + +EditTreeView::EditTreeView(QWidget *parent) + : QTreeView(parent) +{ +} + +void EditTreeView::keyPressEvent(QKeyEvent *event) +{ + if ((event->key() == Qt::Key_Delete + || event->key() == Qt::Key_Backspace) + && model()) { + removeOne(); + } else { + QAbstractItemView::keyPressEvent(event); + } +} + +void EditTreeView::removeOne() +{ + if (!model()) + return; + QModelIndex ci = currentIndex(); + int row = ci.row(); + model()->removeRow(row, ci.parent()); +} + +void EditTreeView::removeAll() +{ + if (!model()) + return; + model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex()); +} diff --git a/examples/webenginewidgets/browser/edittreeview.h b/examples/webenginewidgets/browser/edittreeview.h new file mode 100644 index 000000000..4159812a6 --- /dev/null +++ b/examples/webenginewidgets/browser/edittreeview.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EDITTREEVIEW_H +#define EDITTREEVIEW_H + +#include + +class EditTreeView : public QTreeView +{ + Q_OBJECT + +public: + EditTreeView(QWidget *parent = 0); + void keyPressEvent(QKeyEvent *event); + +public slots: + void removeOne(); + void removeAll(); +}; + +#endif // EDITTREEVIEW_H diff --git a/examples/webenginewidgets/browser/history.cpp b/examples/webenginewidgets/browser/history.cpp new file mode 100644 index 000000000..9d599f876 --- /dev/null +++ b/examples/webenginewidgets/browser/history.cpp @@ -0,0 +1,1298 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "history.h" + +#include "autosaver.h" +#include "browserapplication.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +static const unsigned int HISTORY_VERSION = 23; + +HistoryManager::HistoryManager(QObject *parent) + : +#if defined(QWEBENGINEHISTORYINTERFACE) + QWebEngineHistoryInterface(parent), +#endif + m_saveTimer(new AutoSaver(this)) + , m_historyLimit(30) + , m_historyModel(0) + , m_historyFilterModel(0) + , m_historyTreeModel(0) +{ + m_expiredTimer.setSingleShot(true); + connect(&m_expiredTimer, SIGNAL(timeout()), + this, SLOT(checkForExpired())); + connect(this, SIGNAL(entryAdded(HistoryItem)), + m_saveTimer, SLOT(changeOccurred())); + connect(this, SIGNAL(entryRemoved(HistoryItem)), + m_saveTimer, SLOT(changeOccurred())); + load(); + + m_historyModel = new HistoryModel(this, this); + m_historyFilterModel = new HistoryFilterModel(m_historyModel, this); + m_historyTreeModel = new HistoryTreeModel(m_historyFilterModel, this); + +#if defined(QWEBENGINEHISTORYINTERFACE) + // QWebEngineHistoryInterface will delete the history manager + QWebEngineHistoryInterface::setDefaultInterface(this); +#endif +} + +HistoryManager::~HistoryManager() +{ + m_saveTimer->saveIfNeccessary(); +} + +QList HistoryManager::history() const +{ + return m_history; +} + +bool HistoryManager::historyContains(const QString &url) const +{ + return m_historyFilterModel->historyContains(url); +} + +void HistoryManager::addHistoryEntry(const QString &url) +{ + QUrl cleanUrl(url); + cleanUrl.setPassword(QString()); + cleanUrl.setHost(cleanUrl.host().toLower()); + HistoryItem item(cleanUrl.toString(), QDateTime::currentDateTime()); + addHistoryItem(item); +} + +void HistoryManager::setHistory(const QList &history, bool loadedAndSorted) +{ + m_history = history; + + // verify that it is sorted by date + if (!loadedAndSorted) + qSort(m_history.begin(), m_history.end()); + + checkForExpired(); + + if (loadedAndSorted) { + m_lastSavedUrl = m_history.value(0).url; + } else { + m_lastSavedUrl = QString(); + m_saveTimer->changeOccurred(); + } + emit historyReset(); +} + +HistoryModel *HistoryManager::historyModel() const +{ + return m_historyModel; +} + +HistoryFilterModel *HistoryManager::historyFilterModel() const +{ + return m_historyFilterModel; +} + +HistoryTreeModel *HistoryManager::historyTreeModel() const +{ + return m_historyTreeModel; +} + +void HistoryManager::checkForExpired() +{ + if (m_historyLimit < 0 || m_history.isEmpty()) + return; + + QDateTime now = QDateTime::currentDateTime(); + int nextTimeout = 0; + + while (!m_history.isEmpty()) { + QDateTime checkForExpired = m_history.last().dateTime; + checkForExpired.setDate(checkForExpired.date().addDays(m_historyLimit)); + if (now.daysTo(checkForExpired) > 7) { + // check at most in a week to prevent int overflows on the timer + nextTimeout = 7 * 86400; + } else { + nextTimeout = now.secsTo(checkForExpired); + } + if (nextTimeout > 0) + break; + HistoryItem item = m_history.takeLast(); + // remove from saved file also + m_lastSavedUrl = QString(); + emit entryRemoved(item); + } + + if (nextTimeout > 0) + m_expiredTimer.start(nextTimeout * 1000); +} + +void HistoryManager::addHistoryItem(const HistoryItem &item) +{ +#if defined(QWEBENGINESETTINGS) + QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); + if (globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) + return; +#endif + + m_history.prepend(item); + emit entryAdded(item); + if (m_history.count() == 1) + checkForExpired(); +} + +void HistoryManager::updateHistoryItem(const QUrl &url, const QString &title) +{ + for (int i = 0; i < m_history.count(); ++i) { + if (url == m_history.at(i).url) { + m_history[i].title = title; + m_saveTimer->changeOccurred(); + if (m_lastSavedUrl.isEmpty()) + m_lastSavedUrl = m_history.at(i).url; + emit entryUpdated(i); + break; + } + } +} + +int HistoryManager::historyLimit() const +{ + return m_historyLimit; +} + +void HistoryManager::setHistoryLimit(int limit) +{ + if (m_historyLimit == limit) + return; + m_historyLimit = limit; + checkForExpired(); + m_saveTimer->changeOccurred(); +} + +void HistoryManager::clear() +{ + m_history.clear(); + m_lastSavedUrl = QString(); + m_saveTimer->changeOccurred(); + m_saveTimer->saveIfNeccessary(); + historyReset(); +} + +void HistoryManager::loadSettings() +{ + // load settings + QSettings settings; + settings.beginGroup(QLatin1String("history")); + m_historyLimit = settings.value(QLatin1String("historyLimit"), 30).toInt(); +} + +void HistoryManager::load() +{ + loadSettings(); + + QFile historyFile(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + + QLatin1String("/history")); + if (!historyFile.exists()) + return; + if (!historyFile.open(QFile::ReadOnly)) { + qWarning() << "Unable to open history file" << historyFile.fileName(); + return; + } + + QList list; + QDataStream in(&historyFile); + // Double check that the history file is sorted as it is read in + bool needToSort = false; + HistoryItem lastInsertedItem; + QByteArray data; + QDataStream stream; + QBuffer buffer; + stream.setDevice(&buffer); + while (!historyFile.atEnd()) { + in >> data; + buffer.close(); + buffer.setBuffer(&data); + buffer.open(QIODevice::ReadOnly); + quint32 ver; + stream >> ver; + if (ver != HISTORY_VERSION) + continue; + HistoryItem item; + stream >> item.url; + stream >> item.dateTime; + stream >> item.title; + + if (!item.dateTime.isValid()) + continue; + + if (item == lastInsertedItem) { + if (lastInsertedItem.title.isEmpty() && !list.isEmpty()) + list[0].title = item.title; + continue; + } + + if (!needToSort && !list.isEmpty() && lastInsertedItem < item) + needToSort = true; + + list.prepend(item); + lastInsertedItem = item; + } + if (needToSort) + qSort(list.begin(), list.end()); + + setHistory(list, true); + + // If we had to sort re-write the whole history sorted + if (needToSort) { + m_lastSavedUrl = QString(); + m_saveTimer->changeOccurred(); + } +} + +void HistoryManager::save() +{ + QSettings settings; + settings.beginGroup(QLatin1String("history")); + settings.setValue(QLatin1String("historyLimit"), m_historyLimit); + + bool saveAll = m_lastSavedUrl.isEmpty(); + int first = m_history.count() - 1; + if (!saveAll) { + // find the first one to save + for (int i = 0; i < m_history.count(); ++i) { + if (m_history.at(i).url == m_lastSavedUrl) { + first = i - 1; + break; + } + } + } + if (first == m_history.count() - 1) + saveAll = true; + + QString directory = QStandardPaths::writableLocation(QStandardPaths::DataLocation); + if (directory.isEmpty()) + directory = QDir::homePath() + QLatin1String("/.") + QCoreApplication::applicationName(); + if (!QFile::exists(directory)) { + QDir dir; + dir.mkpath(directory); + } + + QFile historyFile(directory + QLatin1String("/history")); + // When saving everything use a temporary file to prevent possible data loss. + QTemporaryFile tempFile; + tempFile.setAutoRemove(false); + bool open = false; + if (saveAll) { + open = tempFile.open(); + } else { + open = historyFile.open(QFile::Append); + } + + if (!open) { + qWarning() << "Unable to open history file for saving" + << (saveAll ? tempFile.fileName() : historyFile.fileName()); + return; + } + + QDataStream out(saveAll ? &tempFile : &historyFile); + for (int i = first; i >= 0; --i) { + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + HistoryItem item = m_history.at(i); + stream << HISTORY_VERSION << item.url << item.dateTime << item.title; + out << data; + } + tempFile.close(); + + if (saveAll) { + if (historyFile.exists() && !historyFile.remove()) + qWarning() << "History: error removing old history." << historyFile.errorString(); + if (!tempFile.rename(historyFile.fileName())) + qWarning() << "History: error moving new history over old." << tempFile.errorString() << historyFile.fileName(); + } + m_lastSavedUrl = m_history.value(0).url; +} + +HistoryModel::HistoryModel(HistoryManager *history, QObject *parent) + : QAbstractTableModel(parent) + , m_history(history) +{ + Q_ASSERT(m_history); + connect(m_history, SIGNAL(historyReset()), + this, SLOT(historyReset())); + connect(m_history, SIGNAL(entryRemoved(HistoryItem)), + this, SLOT(historyReset())); + + connect(m_history, SIGNAL(entryAdded(HistoryItem)), + this, SLOT(entryAdded())); + connect(m_history, SIGNAL(entryUpdated(int)), + this, SLOT(entryUpdated(int))); +} + +void HistoryModel::historyReset() +{ + beginResetModel(); + endResetModel(); +} + +void HistoryModel::entryAdded() +{ + beginInsertRows(QModelIndex(), 0, 0); + endInsertRows(); +} + +void HistoryModel::entryUpdated(int offset) +{ + QModelIndex idx = index(offset, 0); + emit dataChanged(idx, idx); +} + +QVariant HistoryModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal + && role == Qt::DisplayRole) { + switch (section) { + case 0: return tr("Title"); + case 1: return tr("Address"); + } + } + return QAbstractTableModel::headerData(section, orientation, role); +} + +QVariant HistoryModel::data(const QModelIndex &index, int role) const +{ + QList lst = m_history->history(); + if (index.row() < 0 || index.row() >= lst.size()) + return QVariant(); + + const HistoryItem &item = lst.at(index.row()); + switch (role) { + case DateTimeRole: + return item.dateTime; + case DateRole: + return item.dateTime.date(); + case UrlRole: + return QUrl(item.url); + case UrlStringRole: + return item.url; + case Qt::DisplayRole: + case Qt::EditRole: { + switch (index.column()) { + case 0: + // when there is no title try to generate one from the url + if (item.title.isEmpty()) { + QString page = QFileInfo(QUrl(item.url).path()).fileName(); + if (!page.isEmpty()) + return page; + return item.url; + } + return item.title; + case 1: + return item.url; + } + } + case Qt::DecorationRole: + if (index.column() == 0) { + return BrowserApplication::instance()->icon(item.url); + } + } + return QVariant(); +} + +int HistoryModel::columnCount(const QModelIndex &parent) const +{ + return (parent.isValid()) ? 0 : 2; +} + +int HistoryModel::rowCount(const QModelIndex &parent) const +{ + return (parent.isValid()) ? 0 : m_history->history().count(); +} + +bool HistoryModel::removeRows(int row, int count, const QModelIndex &parent) +{ + if (parent.isValid()) + return false; + int lastRow = row + count - 1; + beginRemoveRows(parent, row, lastRow); + QList lst = m_history->history(); + for (int i = lastRow; i >= row; --i) + lst.removeAt(i); + disconnect(m_history, SIGNAL(historyReset()), this, SLOT(historyReset())); + m_history->setHistory(lst); + connect(m_history, SIGNAL(historyReset()), this, SLOT(historyReset())); + endRemoveRows(); + return true; +} + +#define MOVEDROWS 15 + +/* + Maps the first bunch of items of the source model to the root +*/ +HistoryMenuModel::HistoryMenuModel(HistoryTreeModel *sourceModel, QObject *parent) + : QAbstractProxyModel(parent) + , m_treeModel(sourceModel) +{ + setSourceModel(sourceModel); +} + +int HistoryMenuModel::bumpedRows() const +{ + QModelIndex first = m_treeModel->index(0, 0); + if (!first.isValid()) + return 0; + return qMin(m_treeModel->rowCount(first), MOVEDROWS); +} + +int HistoryMenuModel::columnCount(const QModelIndex &parent) const +{ + return m_treeModel->columnCount(mapToSource(parent)); +} + +int HistoryMenuModel::rowCount(const QModelIndex &parent) const +{ + if (parent.column() > 0) + return 0; + + if (!parent.isValid()) { + int folders = sourceModel()->rowCount(); + int bumpedItems = bumpedRows(); + if (bumpedItems <= MOVEDROWS + && bumpedItems == sourceModel()->rowCount(sourceModel()->index(0, 0))) + --folders; + return bumpedItems + folders; + } + + if (parent.internalId() == quintptr(-1)) { + if (parent.row() < bumpedRows()) + return 0; + } + + QModelIndex idx = mapToSource(parent); + int defaultCount = sourceModel()->rowCount(idx); + if (idx == sourceModel()->index(0, 0)) + return defaultCount - bumpedRows(); + return defaultCount; +} + +QModelIndex HistoryMenuModel::mapFromSource(const QModelIndex &sourceIndex) const +{ + // currently not used or autotested + Q_ASSERT(false); + int sr = m_treeModel->mapToSource(sourceIndex).row(); + return createIndex(sourceIndex.row(), sourceIndex.column(), sr); +} + +QModelIndex HistoryMenuModel::mapToSource(const QModelIndex &proxyIndex) const +{ + if (!proxyIndex.isValid()) + return QModelIndex(); + + if (proxyIndex.internalId() == quintptr(-1)) { + int bumpedItems = bumpedRows(); + if (proxyIndex.row() < bumpedItems) + return m_treeModel->index(proxyIndex.row(), proxyIndex.column(), m_treeModel->index(0, 0)); + if (bumpedItems <= MOVEDROWS && bumpedItems == sourceModel()->rowCount(m_treeModel->index(0, 0))) + --bumpedItems; + return m_treeModel->index(proxyIndex.row() - bumpedItems, proxyIndex.column()); + } + + QModelIndex historyIndex = m_treeModel->sourceModel()->index(proxyIndex.internalId(), proxyIndex.column()); + QModelIndex treeIndex = m_treeModel->mapFromSource(historyIndex); + return treeIndex; +} + +QModelIndex HistoryMenuModel::index(int row, int column, const QModelIndex &parent) const +{ + if (row < 0 + || column < 0 || column >= columnCount(parent) + || parent.column() > 0) + return QModelIndex(); + if (!parent.isValid()) + return createIndex(row, column, quintptr(-1)); + + QModelIndex treeIndexParent = mapToSource(parent); + + int bumpedItems = 0; + if (treeIndexParent == m_treeModel->index(0, 0)) + bumpedItems = bumpedRows(); + QModelIndex treeIndex = m_treeModel->index(row + bumpedItems, column, treeIndexParent); + QModelIndex historyIndex = m_treeModel->mapToSource(treeIndex); + int historyRow = historyIndex.row(); + if (historyRow == -1) + historyRow = treeIndex.row(); + return createIndex(row, column, historyRow); +} + +QModelIndex HistoryMenuModel::parent(const QModelIndex &index) const +{ + int offset = index.internalId(); + if (offset == -1 || !index.isValid()) + return QModelIndex(); + + QModelIndex historyIndex = m_treeModel->sourceModel()->index(index.internalId(), 0); + QModelIndex treeIndex = m_treeModel->mapFromSource(historyIndex); + QModelIndex treeIndexParent = treeIndex.parent(); + + int sr = m_treeModel->mapToSource(treeIndexParent).row(); + int bumpedItems = bumpedRows(); + if (bumpedItems <= MOVEDROWS && bumpedItems == sourceModel()->rowCount(sourceModel()->index(0, 0))) + --bumpedItems; + return createIndex(bumpedItems + treeIndexParent.row(), treeIndexParent.column(), sr); +} + + +HistoryMenu::HistoryMenu(QWidget *parent) + : ModelMenu(parent) + , m_history(0) +{ + connect(this, SIGNAL(activated(QModelIndex)), + this, SLOT(activated(QModelIndex))); + setHoverRole(HistoryModel::UrlStringRole); +} + +void HistoryMenu::activated(const QModelIndex &index) +{ + emit openUrl(index.data(HistoryModel::UrlRole).toUrl()); +} + +bool HistoryMenu::prePopulated() +{ + if (!m_history) { + m_history = BrowserApplication::historyManager(); + m_historyMenuModel = new HistoryMenuModel(m_history->historyTreeModel(), this); + setModel(m_historyMenuModel); + } + // initial actions + for (int i = 0; i < m_initialActions.count(); ++i) + addAction(m_initialActions.at(i)); + if (!m_initialActions.isEmpty()) + addSeparator(); + setFirstSeparator(m_historyMenuModel->bumpedRows()); + + return false; +} + +void HistoryMenu::postPopulated() +{ + if (m_history->history().count() > 0) + addSeparator(); + + QAction *showAllAction = new QAction(tr("Show All History"), this); + connect(showAllAction, SIGNAL(triggered()), this, SLOT(showHistoryDialog())); + addAction(showAllAction); + + QAction *clearAction = new QAction(tr("Clear History"), this); + connect(clearAction, SIGNAL(triggered()), m_history, SLOT(clear())); + addAction(clearAction); +} + +void HistoryMenu::showHistoryDialog() +{ + HistoryDialog *dialog = new HistoryDialog(this); + connect(dialog, SIGNAL(openUrl(QUrl)), + this, SIGNAL(openUrl(QUrl))); + dialog->show(); +} + +void HistoryMenu::setInitialActions(QList actions) +{ + m_initialActions = actions; + for (int i = 0; i < m_initialActions.count(); ++i) + addAction(m_initialActions.at(i)); +} + +TreeProxyModel::TreeProxyModel(QObject *parent) : QSortFilterProxyModel(parent) +{ + setSortRole(HistoryModel::DateTimeRole); + setFilterCaseSensitivity(Qt::CaseInsensitive); +} + +bool TreeProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + if (!source_parent.isValid()) + return true; + return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); +} + +HistoryDialog::HistoryDialog(QWidget *parent, HistoryManager *setHistory) : QDialog(parent) +{ + HistoryManager *history = setHistory; + if (!history) + history = BrowserApplication::historyManager(); + setupUi(this); + tree->setUniformRowHeights(true); + tree->setSelectionBehavior(QAbstractItemView::SelectRows); + tree->setTextElideMode(Qt::ElideMiddle); + QAbstractItemModel *model = history->historyTreeModel(); + TreeProxyModel *proxyModel = new TreeProxyModel(this); + connect(search, SIGNAL(textChanged(QString)), + proxyModel, SLOT(setFilterFixedString(QString))); + connect(removeButton, SIGNAL(clicked()), tree, SLOT(removeOne())); + connect(removeAllButton, SIGNAL(clicked()), history, SLOT(clear())); + proxyModel->setSourceModel(model); + tree->setModel(proxyModel); + tree->setExpanded(proxyModel->index(0, 0), true); + tree->setAlternatingRowColors(true); + QFontMetrics fm(font()); + int header = fm.width(QLatin1Char('m')) * 40; + tree->header()->resizeSection(0, header); + tree->header()->setStretchLastSection(true); + connect(tree, SIGNAL(activated(QModelIndex)), + this, SLOT(open())); + tree->setContextMenuPolicy(Qt::CustomContextMenu); + connect(tree, SIGNAL(customContextMenuRequested(QPoint)), + this, SLOT(customContextMenuRequested(QPoint))); +} + +void HistoryDialog::customContextMenuRequested(const QPoint &pos) +{ + QMenu menu; + QModelIndex index = tree->indexAt(pos); + index = index.sibling(index.row(), 0); + if (index.isValid() && !tree->model()->hasChildren(index)) { + menu.addAction(tr("Open"), this, SLOT(open())); + menu.addSeparator(); + menu.addAction(tr("Copy"), this, SLOT(copy())); + } + menu.addAction(tr("Delete"), tree, SLOT(removeOne())); + menu.exec(QCursor::pos()); +} + +void HistoryDialog::open() +{ + QModelIndex index = tree->currentIndex(); + if (!index.parent().isValid()) + return; + emit openUrl(index.data(HistoryModel::UrlRole).toUrl()); +} + +void HistoryDialog::copy() +{ + QModelIndex index = tree->currentIndex(); + if (!index.parent().isValid()) + return; + QString url = index.data(HistoryModel::UrlStringRole).toString(); + + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(url); +} + +HistoryFilterModel::HistoryFilterModel(QAbstractItemModel *sourceModel, QObject *parent) + : QAbstractProxyModel(parent), + m_loaded(false) +{ + setSourceModel(sourceModel); +} + +int HistoryFilterModel::historyLocation(const QString &url) const +{ + load(); + if (!m_historyHash.contains(url)) + return 0; + return sourceModel()->rowCount() - m_historyHash.value(url); +} + +QVariant HistoryFilterModel::data(const QModelIndex &index, int role) const +{ + return QAbstractProxyModel::data(index, role); +} + +void HistoryFilterModel::setSourceModel(QAbstractItemModel *newSourceModel) +{ + if (sourceModel()) { + disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset())); + disconnect(sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(dataChanged(QModelIndex,QModelIndex))); + disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(sourceRowsInserted(QModelIndex,int,int))); + disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); + } + + QAbstractProxyModel::setSourceModel(newSourceModel); + + if (sourceModel()) { + m_loaded = false; + connect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset())); + connect(sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(sourceDataChanged(QModelIndex,QModelIndex))); + connect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(sourceRowsInserted(QModelIndex,int,int))); + connect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); + } +} + +void HistoryFilterModel::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + emit dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight)); +} + +QVariant HistoryFilterModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + return sourceModel()->headerData(section, orientation, role); +} + +void HistoryFilterModel::sourceReset() +{ + m_loaded = false; + beginResetModel(); + endResetModel(); +} + +int HistoryFilterModel::rowCount(const QModelIndex &parent) const +{ + load(); + if (parent.isValid()) + return 0; + return m_historyHash.count(); +} + +int HistoryFilterModel::columnCount(const QModelIndex &parent) const +{ + return (parent.isValid()) ? 0 : 2; +} + +QModelIndex HistoryFilterModel::mapToSource(const QModelIndex &proxyIndex) const +{ + load(); + int sourceRow = sourceModel()->rowCount() - proxyIndex.internalId(); + return sourceModel()->index(sourceRow, proxyIndex.column()); +} + +QModelIndex HistoryFilterModel::mapFromSource(const QModelIndex &sourceIndex) const +{ + load(); + QString url = sourceIndex.data(HistoryModel::UrlStringRole).toString(); + if (!m_historyHash.contains(url)) + return QModelIndex(); + + // This can be done in a binary search, but we can't use qBinary find + // because it can't take: qBinaryFind(m_sourceRow.end(), m_sourceRow.begin(), v); + // so if this is a performance bottlneck then convert to binary search, until then + // the cleaner/easier to read code wins the day. + int realRow = -1; + int sourceModelRow = sourceModel()->rowCount() - sourceIndex.row(); + + for (int i = 0; i < m_sourceRow.count(); ++i) { + if (m_sourceRow.at(i) == sourceModelRow) { + realRow = i; + break; + } + } + if (realRow == -1) + return QModelIndex(); + + return createIndex(realRow, sourceIndex.column(), sourceModel()->rowCount() - sourceIndex.row()); +} + +QModelIndex HistoryFilterModel::index(int row, int column, const QModelIndex &parent) const +{ + load(); + if (row < 0 || row >= rowCount(parent) + || column < 0 || column >= columnCount(parent)) + return QModelIndex(); + + return createIndex(row, column, m_sourceRow[row]); +} + +QModelIndex HistoryFilterModel::parent(const QModelIndex &) const +{ + return QModelIndex(); +} + +void HistoryFilterModel::load() const +{ + if (m_loaded) + return; + m_sourceRow.clear(); + m_historyHash.clear(); + m_historyHash.reserve(sourceModel()->rowCount()); + for (int i = 0; i < sourceModel()->rowCount(); ++i) { + QModelIndex idx = sourceModel()->index(i, 0); + QString url = idx.data(HistoryModel::UrlStringRole).toString(); + if (!m_historyHash.contains(url)) { + m_sourceRow.append(sourceModel()->rowCount() - i); + m_historyHash[url] = sourceModel()->rowCount() - i; + } + } + m_loaded = true; +} + +void HistoryFilterModel::sourceRowsInserted(const QModelIndex &parent, int start, int end) +{ + Q_ASSERT(start == end && start == 0); + Q_UNUSED(end); + if (!m_loaded) + return; + QModelIndex idx = sourceModel()->index(start, 0, parent); + QString url = idx.data(HistoryModel::UrlStringRole).toString(); + if (m_historyHash.contains(url)) { + int sourceRow = sourceModel()->rowCount() - m_historyHash[url]; + int realRow = mapFromSource(sourceModel()->index(sourceRow, 0)).row(); + beginRemoveRows(QModelIndex(), realRow, realRow); + m_sourceRow.removeAt(realRow); + m_historyHash.remove(url); + endRemoveRows(); + } + beginInsertRows(QModelIndex(), 0, 0); + m_historyHash.insert(url, sourceModel()->rowCount() - start); + m_sourceRow.insert(0, sourceModel()->rowCount()); + endInsertRows(); +} + +void HistoryFilterModel::sourceRowsRemoved(const QModelIndex &, int start, int end) +{ + Q_UNUSED(start); + Q_UNUSED(end); + sourceReset(); +} + +/* + Removing a continuous block of rows will remove filtered rows too as this is + the users intention. +*/ +bool HistoryFilterModel::removeRows(int row, int count, const QModelIndex &parent) +{ + if (row < 0 || count <= 0 || row + count > rowCount(parent) || parent.isValid()) + return false; + int lastRow = row + count - 1; + disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); + beginRemoveRows(parent, row, lastRow); + int oldCount = rowCount(); + int start = sourceModel()->rowCount() - m_sourceRow.value(row); + int end = sourceModel()->rowCount() - m_sourceRow.value(lastRow); + sourceModel()->removeRows(start, end - start + 1); + endRemoveRows(); + connect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); + m_loaded = false; + if (oldCount - count != rowCount()) { + beginResetModel(); + endResetModel(); + } + return true; +} + +HistoryCompletionModel::HistoryCompletionModel(QObject *parent) + : QAbstractProxyModel(parent) +{ +} + +QVariant HistoryCompletionModel::data(const QModelIndex &index, int role) const +{ + if (sourceModel() + && (role == Qt::EditRole || role == Qt::DisplayRole) + && index.isValid()) { + QModelIndex idx = mapToSource(index); + idx = idx.sibling(idx.row(), 1); + QString urlString = idx.data(HistoryModel::UrlStringRole).toString(); + if (index.row() % 2) { + QUrl url = urlString; + QString s = url.toString(QUrl::RemoveScheme + | QUrl::RemoveUserInfo + | QUrl::StripTrailingSlash); + return s.mid(2); // strip // from the front + } + return urlString; + } + return QAbstractProxyModel::data(index, role); +} + +int HistoryCompletionModel::rowCount(const QModelIndex &parent) const +{ + return (parent.isValid() || !sourceModel()) ? 0 : sourceModel()->rowCount(parent) * 2; +} + +int HistoryCompletionModel::columnCount(const QModelIndex &parent) const +{ + return (parent.isValid()) ? 0 : 1; +} + +QModelIndex HistoryCompletionModel::mapFromSource(const QModelIndex &sourceIndex) const +{ + int row = sourceIndex.row() * 2; + return index(row, sourceIndex.column()); +} + +QModelIndex HistoryCompletionModel::mapToSource(const QModelIndex &proxyIndex) const +{ + if (!sourceModel()) + return QModelIndex(); + int row = proxyIndex.row() / 2; + return sourceModel()->index(row, proxyIndex.column()); +} + +QModelIndex HistoryCompletionModel::index(int row, int column, const QModelIndex &parent) const +{ + if (row < 0 || row >= rowCount(parent) + || column < 0 || column >= columnCount(parent)) + return QModelIndex(); + return createIndex(row, column); +} + +QModelIndex HistoryCompletionModel::parent(const QModelIndex &) const +{ + return QModelIndex(); +} + +void HistoryCompletionModel::setSourceModel(QAbstractItemModel *newSourceModel) +{ + if (sourceModel()) { + disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset())); + disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(sourceReset())); + disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(sourceReset())); + } + + QAbstractProxyModel::setSourceModel(newSourceModel); + + if (newSourceModel) { + connect(newSourceModel, SIGNAL(modelReset()), this, SLOT(sourceReset())); + connect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(sourceReset())); + connect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(sourceReset())); + } + + beginResetModel(); + endResetModel(); +} + +void HistoryCompletionModel::sourceReset() +{ + beginResetModel(); + endResetModel(); +} + +HistoryTreeModel::HistoryTreeModel(QAbstractItemModel *sourceModel, QObject *parent) + : QAbstractProxyModel(parent) +{ + setSourceModel(sourceModel); +} + +QVariant HistoryTreeModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + return sourceModel()->headerData(section, orientation, role); +} + +QVariant HistoryTreeModel::data(const QModelIndex &index, int role) const +{ + if ((role == Qt::EditRole || role == Qt::DisplayRole)) { + int start = index.internalId(); + if (start == 0) { + int offset = sourceDateRow(index.row()); + if (index.column() == 0) { + QModelIndex idx = sourceModel()->index(offset, 0); + QDate date = idx.data(HistoryModel::DateRole).toDate(); + if (date == QDate::currentDate()) + return tr("Earlier Today"); + return date.toString(QLatin1String("dddd, MMMM d, yyyy")); + } + if (index.column() == 1) { + return tr("%1 items").arg(rowCount(index.sibling(index.row(), 0))); + } + } + } + if (role == Qt::DecorationRole && index.column() == 0 && !index.parent().isValid()) + return QIcon(QLatin1String(":history.png")); + if (role == HistoryModel::DateRole && index.column() == 0 && index.internalId() == 0) { + int offset = sourceDateRow(index.row()); + QModelIndex idx = sourceModel()->index(offset, 0); + return idx.data(HistoryModel::DateRole); + } + + return QAbstractProxyModel::data(index, role); +} + +int HistoryTreeModel::columnCount(const QModelIndex &parent) const +{ + return sourceModel()->columnCount(mapToSource(parent)); +} + +int HistoryTreeModel::rowCount(const QModelIndex &parent) const +{ + if ( parent.internalId() != 0 + || parent.column() > 0 + || !sourceModel()) + return 0; + + // row count OF dates + if (!parent.isValid()) { + if (!m_sourceRowCache.isEmpty()) + return m_sourceRowCache.count(); + QDate currentDate; + int rows = 0; + int totalRows = sourceModel()->rowCount(); + + for (int i = 0; i < totalRows; ++i) { + QDate rowDate = sourceModel()->index(i, 0).data(HistoryModel::DateRole).toDate(); + if (rowDate != currentDate) { + m_sourceRowCache.append(i); + currentDate = rowDate; + ++rows; + } + } + Q_ASSERT(m_sourceRowCache.count() == rows); + return rows; + } + + // row count FOR a date + int start = sourceDateRow(parent.row()); + int end = sourceDateRow(parent.row() + 1); + return (end - start); +} + +// Translate the top level date row into the offset where that date starts +int HistoryTreeModel::sourceDateRow(int row) const +{ + if (row <= 0) + return 0; + + if (m_sourceRowCache.isEmpty()) + rowCount(QModelIndex()); + + if (row >= m_sourceRowCache.count()) { + if (!sourceModel()) + return 0; + return sourceModel()->rowCount(); + } + return m_sourceRowCache.at(row); +} + +QModelIndex HistoryTreeModel::mapToSource(const QModelIndex &proxyIndex) const +{ + int offset = proxyIndex.internalId(); + if (offset == 0) + return QModelIndex(); + int startDateRow = sourceDateRow(offset - 1); + return sourceModel()->index(startDateRow + proxyIndex.row(), proxyIndex.column()); +} + +QModelIndex HistoryTreeModel::index(int row, int column, const QModelIndex &parent) const +{ + if (row < 0 + || column < 0 || column >= columnCount(parent) + || parent.column() > 0) + return QModelIndex(); + + if (!parent.isValid()) + return createIndex(row, column); + return createIndex(row, column, parent.row() + 1); +} + +QModelIndex HistoryTreeModel::parent(const QModelIndex &index) const +{ + int offset = index.internalId(); + if (offset == 0 || !index.isValid()) + return QModelIndex(); + return createIndex(offset - 1, 0); +} + +bool HistoryTreeModel::hasChildren(const QModelIndex &parent) const +{ + QModelIndex grandparent = parent.parent(); + if (!grandparent.isValid()) + return true; + return false; +} + +Qt::ItemFlags HistoryTreeModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::NoItemFlags; + return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled; +} + +bool HistoryTreeModel::removeRows(int row, int count, const QModelIndex &parent) +{ + if (row < 0 || count <= 0 || row + count > rowCount(parent)) + return false; + + if (parent.isValid()) { + // removing pages + int offset = sourceDateRow(parent.row()); + return sourceModel()->removeRows(offset + row, count); + } else { + // removing whole dates + for (int i = row + count - 1; i >= row; --i) { + QModelIndex dateParent = index(i, 0); + int offset = sourceDateRow(dateParent.row()); + if (!sourceModel()->removeRows(offset, rowCount(dateParent))) + return false; + } + } + return true; +} + +void HistoryTreeModel::setSourceModel(QAbstractItemModel *newSourceModel) +{ + if (sourceModel()) { + disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset())); + disconnect(sourceModel(), SIGNAL(layoutChanged()), this, SLOT(sourceReset())); + disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(sourceRowsInserted(QModelIndex,int,int))); + disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); + } + + QAbstractProxyModel::setSourceModel(newSourceModel); + + if (newSourceModel) { + connect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset())); + connect(sourceModel(), SIGNAL(layoutChanged()), this, SLOT(sourceReset())); + connect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(sourceRowsInserted(QModelIndex,int,int))); + connect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); + } + + beginResetModel(); + endResetModel(); +} + +void HistoryTreeModel::sourceReset() +{ + beginResetModel(); + m_sourceRowCache.clear(); + endResetModel(); +} + +void HistoryTreeModel::sourceRowsInserted(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent); // Avoid warnings when compiling release + Q_ASSERT(!parent.isValid()); + if (start != 0 || start != end) { + beginResetModel(); + m_sourceRowCache.clear(); + endResetModel(); + return; + } + + m_sourceRowCache.clear(); + QModelIndex treeIndex = mapFromSource(sourceModel()->index(start, 0)); + QModelIndex treeParent = treeIndex.parent(); + if (rowCount(treeParent) == 1) { + beginInsertRows(QModelIndex(), 0, 0); + endInsertRows(); + } else { + beginInsertRows(treeParent, treeIndex.row(), treeIndex.row()); + endInsertRows(); + } +} + +QModelIndex HistoryTreeModel::mapFromSource(const QModelIndex &sourceIndex) const +{ + if (!sourceIndex.isValid()) + return QModelIndex(); + + if (m_sourceRowCache.isEmpty()) + rowCount(QModelIndex()); + + QList::iterator it; + it = qLowerBound(m_sourceRowCache.begin(), m_sourceRowCache.end(), sourceIndex.row()); + if (*it != sourceIndex.row()) + --it; + int dateRow = qMax(0, it - m_sourceRowCache.begin()); + int row = sourceIndex.row() - m_sourceRowCache.at(dateRow); + return createIndex(row, sourceIndex.column(), dateRow + 1); +} + +void HistoryTreeModel::sourceRowsRemoved(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent); // Avoid warnings when compiling release + Q_ASSERT(!parent.isValid()); + if (m_sourceRowCache.isEmpty()) + return; + for (int i = end; i >= start;) { + QList::iterator it; + it = qLowerBound(m_sourceRowCache.begin(), m_sourceRowCache.end(), i); + // playing it safe + if (it == m_sourceRowCache.end()) { + beginResetModel(); + m_sourceRowCache.clear(); + endResetModel(); + return; + } + + if (*it != i) + --it; + int row = qMax(0, it - m_sourceRowCache.begin()); + int offset = m_sourceRowCache[row]; + QModelIndex dateParent = index(row, 0); + // If we can remove all the rows in the date do that and skip over them + int rc = rowCount(dateParent); + if (i - rc + 1 == offset && start <= i - rc + 1) { + beginRemoveRows(QModelIndex(), row, row); + m_sourceRowCache.removeAt(row); + i -= rc + 1; + } else { + beginRemoveRows(dateParent, i - offset, i - offset); + ++row; + --i; + } + for (int j = row; j < m_sourceRowCache.count(); ++j) + --m_sourceRowCache[j]; + endRemoveRows(); + } +} diff --git a/examples/webenginewidgets/browser/history.h b/examples/webenginewidgets/browser/history.h new file mode 100644 index 000000000..4006f3415 --- /dev/null +++ b/examples/webenginewidgets/browser/history.h @@ -0,0 +1,354 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef HISTORY_H +#define HISTORY_H + +#include "modelmenu.h" + +#include +#include +#include +#include +#include + +#include + +#include + +class HistoryItem +{ +public: + HistoryItem() {} + HistoryItem(const QString &u, + const QDateTime &d = QDateTime(), const QString &t = QString()) + : title(t), url(u), dateTime(d) {} + + inline bool operator==(const HistoryItem &other) const + { return other.title == title + && other.url == url && other.dateTime == dateTime; } + + // history is sorted in reverse + inline bool operator <(const HistoryItem &other) const + { return dateTime > other.dateTime; } + + QString title; + QString url; + QDateTime dateTime; +}; + +class AutoSaver; +class HistoryModel; +class HistoryFilterModel; +class HistoryTreeModel; +class HistoryManager +#if defined(QWEBENGINEHISTORYINTERFACE) + : public QWebEngineHistoryInterface +#else + : public QObject +#endif +{ + Q_OBJECT + Q_PROPERTY(int historyLimit READ historyLimit WRITE setHistoryLimit) + +signals: + void historyReset(); + void entryAdded(const HistoryItem &item); + void entryRemoved(const HistoryItem &item); + void entryUpdated(int offset); + +public: + HistoryManager(QObject *parent = 0); + ~HistoryManager(); + + bool historyContains(const QString &url) const; + void addHistoryEntry(const QString &url); + + void updateHistoryItem(const QUrl &url, const QString &title); + + int historyLimit() const; + void setHistoryLimit(int limit); + + QList history() const; + void setHistory(const QList &history, bool loadedAndSorted = false); + + // History manager keeps around these models for use by the completer and other classes + HistoryModel *historyModel() const; + HistoryFilterModel *historyFilterModel() const; + HistoryTreeModel *historyTreeModel() const; + +public slots: + void clear(); + void loadSettings(); + +private slots: + void save(); + void checkForExpired(); + +protected: + void addHistoryItem(const HistoryItem &item); + +private: + void load(); + + AutoSaver *m_saveTimer; + int m_historyLimit; + QTimer m_expiredTimer; + QList m_history; + QString m_lastSavedUrl; + + HistoryModel *m_historyModel; + HistoryFilterModel *m_historyFilterModel; + HistoryTreeModel *m_historyTreeModel; +}; + +class HistoryModel : public QAbstractTableModel +{ + Q_OBJECT + +public slots: + void historyReset(); + void entryAdded(); + void entryUpdated(int offset); + +public: + enum Roles { + DateRole = Qt::UserRole + 1, + DateTimeRole = Qt::UserRole + 2, + UrlRole = Qt::UserRole + 3, + UrlStringRole = Qt::UserRole + 4 + }; + + HistoryModel(HistoryManager *history, QObject *parent = 0); + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + +private: + HistoryManager *m_history; +}; + +/*! + Proxy model that will remove any duplicate entries. + Both m_sourceRow and m_historyHash store their offsets not from + the front of the list, but as offsets from the back. + */ +class HistoryFilterModel : public QAbstractProxyModel +{ + Q_OBJECT + +public: + HistoryFilterModel(QAbstractItemModel *sourceModel, QObject *parent = 0); + + inline bool historyContains(const QString &url) const + { load(); return m_historyHash.contains(url); } + int historyLocation(const QString &url) const; + + QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; + QModelIndex mapToSource(const QModelIndex &proxyIndex) const; + void setSourceModel(QAbstractItemModel *sourceModel); + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QModelIndex index(int, int, const QModelIndex& = QModelIndex()) const; + QModelIndex parent(const QModelIndex& index= QModelIndex()) const; + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + +private slots: + void sourceReset(); + void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void sourceRowsInserted(const QModelIndex &parent, int start, int end); + void sourceRowsRemoved(const QModelIndex &, int, int); + +private: + void load() const; + + mutable QList m_sourceRow; + mutable QHash m_historyHash; + mutable bool m_loaded; +}; + +/* + The history menu + - Removes the first twenty entries and puts them as children of the top level. + - If there are less then twenty entries then the first folder is also removed. + + The mapping is done by knowing that HistoryTreeModel is over a table + We store that row offset in our index's private data. +*/ +class HistoryMenuModel : public QAbstractProxyModel +{ + Q_OBJECT + +public: + HistoryMenuModel(HistoryTreeModel *sourceModel, QObject *parent = 0); + int columnCount(const QModelIndex &parent) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + QModelIndex mapFromSource(const QModelIndex & sourceIndex) const; + QModelIndex mapToSource(const QModelIndex & proxyIndex) const; + QModelIndex index(int, int, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index = QModelIndex()) const; + + int bumpedRows() const; + +private: + HistoryTreeModel *m_treeModel; +}; + +// Menu that is dynamically populated from the history +class HistoryMenu : public ModelMenu +{ + Q_OBJECT + +signals: + void openUrl(const QUrl &url); + +public: + HistoryMenu(QWidget *parent = 0); + void setInitialActions(QList actions); + +protected: + bool prePopulated(); + void postPopulated(); + +private slots: + void activated(const QModelIndex &index); + void showHistoryDialog(); + +private: + HistoryManager *m_history; + HistoryMenuModel *m_historyMenuModel; + QList m_initialActions; +}; + +// proxy model for the history model that +// exposes each url http://www.foo.com and it url starting at the host www.foo.com +class HistoryCompletionModel : public QAbstractProxyModel +{ + Q_OBJECT + +public: + HistoryCompletionModel(QObject *parent = 0); + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; + QModelIndex mapToSource(const QModelIndex &proxyIndex) const; + QModelIndex index(int, int, const QModelIndex& = QModelIndex()) const; + QModelIndex parent(const QModelIndex& index= QModelIndex()) const; + void setSourceModel(QAbstractItemModel *sourceModel); + +private slots: + void sourceReset(); + +}; + +// proxy model for the history model that converts the list +// into a tree, one top level node per day. +// Used in the HistoryDialog. +class HistoryTreeModel : public QAbstractProxyModel +{ + Q_OBJECT + +public: + HistoryTreeModel(QAbstractItemModel *sourceModel, QObject *parent = 0); + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + int columnCount(const QModelIndex &parent) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; + QModelIndex mapToSource(const QModelIndex &proxyIndex) const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index= QModelIndex()) const; + bool hasChildren(const QModelIndex &parent = QModelIndex()) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + void setSourceModel(QAbstractItemModel *sourceModel); + +private slots: + void sourceReset(); + void sourceRowsInserted(const QModelIndex &parent, int start, int end); + void sourceRowsRemoved(const QModelIndex &parent, int start, int end); + +private: + int sourceDateRow(int row) const; + mutable QList m_sourceRowCache; + +}; + +// A modified QSortFilterProxyModel that always accepts the root nodes in the tree +// so filtering is only done on the children. +// Used in the HistoryDialog +class TreeProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + TreeProxyModel(QObject *parent = 0); + +protected: + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; +}; + +#include "ui_history.h" + +class HistoryDialog : public QDialog, public Ui_HistoryDialog +{ + Q_OBJECT + +signals: + void openUrl(const QUrl &url); + +public: + HistoryDialog(QWidget *parent = 0, HistoryManager *history = 0); + +private slots: + void customContextMenuRequested(const QPoint &pos); + void open(); + void copy(); + +}; + +#endif // HISTORY_H diff --git a/examples/webenginewidgets/browser/history.ui b/examples/webenginewidgets/browser/history.ui new file mode 100644 index 000000000..0944940e7 --- /dev/null +++ b/examples/webenginewidgets/browser/history.ui @@ -0,0 +1,106 @@ + + HistoryDialog + + + + 0 + 0 + 758 + 450 + + + + History + + + + + + Qt::Horizontal + + + + 252 + 20 + + + + + + + + + + + + + + + + &Remove + + + + + + + Remove &All + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + QDialogButtonBox::Ok + + + + + + + + + + SearchLineEdit + QLineEdit +
searchlineedit.h
+
+ + EditTreeView + QTreeView +
edittreeview.h
+
+
+ + + + buttonBox + accepted() + HistoryDialog + accept() + + + 472 + 329 + + + 461 + 356 + + + + +
diff --git a/examples/webenginewidgets/browser/htmls/htmls.qrc b/examples/webenginewidgets/browser/htmls/htmls.qrc new file mode 100644 index 000000000..03b256ccb --- /dev/null +++ b/examples/webenginewidgets/browser/htmls/htmls.qrc @@ -0,0 +1,5 @@ + + + notfound.html + + diff --git a/examples/webenginewidgets/browser/htmls/notfound.html b/examples/webenginewidgets/browser/htmls/notfound.html new file mode 100644 index 000000000..e89845aa6 --- /dev/null +++ b/examples/webenginewidgets/browser/htmls/notfound.html @@ -0,0 +1,63 @@ + + +%1 + + + +
+ +

%2

+

When connecting to: %3.

+
    +
  • Check the address for errors such as ww.example.com + instead of www.example.com
  • +
  • If the address is correct, try checking the network + connection.
  • +
  • If your computer or network is protected by a firewall or + proxy, make sure that the browser demo is permitted to access + the network.
  • +
+

+
+ + diff --git a/examples/webenginewidgets/browser/main.cpp b/examples/webenginewidgets/browser/main.cpp new file mode 100644 index 000000000..9baf01f42 --- /dev/null +++ b/examples/webenginewidgets/browser/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "browserapplication.h" + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(data); + BrowserApplication application(argc, argv); + if (!application.isTheOnlyBrowser()) + return 0; + application.newMainWindow(); + return application.exec(); +} diff --git a/examples/webenginewidgets/browser/modelmenu.cpp b/examples/webenginewidgets/browser/modelmenu.cpp new file mode 100644 index 000000000..56453b080 --- /dev/null +++ b/examples/webenginewidgets/browser/modelmenu.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "modelmenu.h" + +#include +#include + +ModelMenu::ModelMenu(QWidget * parent) + : QMenu(parent) + , m_maxRows(7) + , m_firstSeparator(-1) + , m_maxWidth(-1) + , m_hoverRole(0) + , m_separatorRole(0) + , m_model(0) +{ + connect(this, SIGNAL(aboutToShow()), this, SLOT(aboutToShow())); +} + +bool ModelMenu::prePopulated() +{ + return false; +} + +void ModelMenu::postPopulated() +{ +} + +void ModelMenu::setModel(QAbstractItemModel *model) +{ + m_model = model; +} + +QAbstractItemModel *ModelMenu::model() const +{ + return m_model; +} + +void ModelMenu::setMaxRows(int max) +{ + m_maxRows = max; +} + +int ModelMenu::maxRows() const +{ + return m_maxRows; +} + +void ModelMenu::setFirstSeparator(int offset) +{ + m_firstSeparator = offset; +} + +int ModelMenu::firstSeparator() const +{ + return m_firstSeparator; +} + +void ModelMenu::setRootIndex(const QModelIndex &index) +{ + m_root = index; +} + +QModelIndex ModelMenu::rootIndex() const +{ + return m_root; +} + +void ModelMenu::setHoverRole(int role) +{ + m_hoverRole = role; +} + +int ModelMenu::hoverRole() const +{ + return m_hoverRole; +} + +void ModelMenu::setSeparatorRole(int role) +{ + m_separatorRole = role; +} + +int ModelMenu::separatorRole() const +{ + return m_separatorRole; +} + +Q_DECLARE_METATYPE(QModelIndex) +void ModelMenu::aboutToShow() +{ + if (QMenu *menu = qobject_cast(sender())) { + QVariant v = menu->menuAction()->data(); + if (v.canConvert()) { + QModelIndex idx = qvariant_cast(v); + createMenu(idx, -1, menu, menu); + disconnect(menu, SIGNAL(aboutToShow()), this, SLOT(aboutToShow())); + return; + } + } + + clear(); + if (prePopulated()) + addSeparator(); + int max = m_maxRows; + if (max != -1) + max += m_firstSeparator; + createMenu(m_root, max, this, this); + postPopulated(); +} + +void ModelMenu::createMenu(const QModelIndex &parent, int max, QMenu *parentMenu, QMenu *menu) +{ + if (!menu) { + QString title = parent.data().toString(); + menu = new QMenu(title, this); + QIcon icon = qvariant_cast(parent.data(Qt::DecorationRole)); + menu->setIcon(icon); + parentMenu->addMenu(menu); + QVariant v; + v.setValue(parent); + menu->menuAction()->setData(v); + connect(menu, SIGNAL(aboutToShow()), this, SLOT(aboutToShow())); + return; + } + + int end = m_model->rowCount(parent); + if (max != -1) + end = qMin(max, end); + + connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(triggered(QAction*))); + connect(menu, SIGNAL(hovered(QAction*)), this, SLOT(hovered(QAction*))); + + for (int i = 0; i < end; ++i) { + QModelIndex idx = m_model->index(i, 0, parent); + if (m_model->hasChildren(idx)) { + createMenu(idx, -1, menu); + } else { + if (m_separatorRole != 0 + && idx.data(m_separatorRole).toBool()) + addSeparator(); + else + menu->addAction(makeAction(idx)); + } + if (menu == this && i == m_firstSeparator - 1) + addSeparator(); + } +} + +QAction *ModelMenu::makeAction(const QModelIndex &index) +{ + QIcon icon = qvariant_cast(index.data(Qt::DecorationRole)); + QAction *action = makeAction(icon, index.data().toString(), this); + QVariant v; + v.setValue(index); + action->setData(v); + return action; +} + +QAction *ModelMenu::makeAction(const QIcon &icon, const QString &text, QObject *parent) +{ + QFontMetrics fm(font()); + if (-1 == m_maxWidth) + m_maxWidth = fm.width(QLatin1Char('m')) * 30; + QString smallText = fm.elidedText(text, Qt::ElideMiddle, m_maxWidth); + return new QAction(icon, smallText, parent); +} + +void ModelMenu::triggered(QAction *action) +{ + QVariant v = action->data(); + if (v.canConvert()) { + QModelIndex idx = qvariant_cast(v); + emit activated(idx); + } +} + +void ModelMenu::hovered(QAction *action) +{ + QVariant v = action->data(); + if (v.canConvert()) { + QModelIndex idx = qvariant_cast(v); + QString hoveredString = idx.data(m_hoverRole).toString(); + if (!hoveredString.isEmpty()) + emit hovered(hoveredString); + } +} diff --git a/examples/webenginewidgets/browser/modelmenu.h b/examples/webenginewidgets/browser/modelmenu.h new file mode 100644 index 000000000..4045a7758 --- /dev/null +++ b/examples/webenginewidgets/browser/modelmenu.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MODELMENU_H +#define MODELMENU_H + +#include +#include + +// A QMenu that is dynamically populated from a QAbstractItemModel +class ModelMenu : public QMenu +{ + Q_OBJECT + +signals: + void activated(const QModelIndex &index); + void hovered(const QString &text); + +public: + ModelMenu(QWidget *parent = 0); + + void setModel(QAbstractItemModel *model); + QAbstractItemModel *model() const; + + void setMaxRows(int max); + int maxRows() const; + + void setFirstSeparator(int offset); + int firstSeparator() const; + + void setRootIndex(const QModelIndex &index); + QModelIndex rootIndex() const; + + void setHoverRole(int role); + int hoverRole() const; + + void setSeparatorRole(int role); + int separatorRole() const; + + QAction *makeAction(const QIcon &icon, const QString &text, QObject *parent); + +protected: + // add any actions before the tree, return true if any actions are added. + virtual bool prePopulated(); + // add any actions after the tree + virtual void postPopulated(); + // put all of the children of parent into menu up to max + void createMenu(const QModelIndex &parent, int max, QMenu *parentMenu = 0, QMenu *menu = 0); + +private slots: + void aboutToShow(); + void triggered(QAction *action); + void hovered(QAction *action); + +private: + QAction *makeAction(const QModelIndex &index); + int m_maxRows; + int m_firstSeparator; + int m_maxWidth; + int m_hoverRole; + int m_separatorRole; + QAbstractItemModel *m_model; + QPersistentModelIndex m_root; +}; + +#endif // MODELMENU_H diff --git a/examples/webenginewidgets/browser/networkaccessmanager.cpp b/examples/webenginewidgets/browser/networkaccessmanager.cpp new file mode 100644 index 000000000..a7127ade6 --- /dev/null +++ b/examples/webenginewidgets/browser/networkaccessmanager.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "networkaccessmanager.h" + +#include "browserapplication.h" +#include "browsermainwindow.h" + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +NetworkAccessManager::NetworkAccessManager(QObject *parent) + : QNetworkAccessManager(parent), + requestFinishedCount(0), requestFinishedFromCacheCount(0), requestFinishedPipelinedCount(0), + requestFinishedSecureCount(0), requestFinishedDownloadBufferCount(0) +{ + connect(this, SIGNAL(finished(QNetworkReply*)), + SLOT(requestFinished(QNetworkReply*))); +#ifndef QT_NO_OPENSSL + connect(this, SIGNAL(sslErrors(QNetworkReply*,QList)), + SLOT(sslErrors(QNetworkReply*,QList))); +#endif + loadSettings(); + + QNetworkDiskCache *diskCache = new QNetworkDiskCache(this); + QString location = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); + diskCache->setCacheDirectory(location); + setCache(diskCache); +} + +QNetworkReply* NetworkAccessManager::createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData) +{ + QNetworkRequest request = req; // copy so we can modify + // this is a temporary hack until we properly use the pipelining flags from QtWebkit + // pipeline everything! :) + request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + return QNetworkAccessManager::createRequest(op, request, outgoingData); +} + +void NetworkAccessManager::requestFinished(QNetworkReply *reply) +{ + requestFinishedCount++; + + if (reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool() == true) + requestFinishedFromCacheCount++; + + if (reply->attribute(QNetworkRequest::HttpPipeliningWasUsedAttribute).toBool() == true) + requestFinishedPipelinedCount++; + + if (reply->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool() == true) + requestFinishedSecureCount++; + + if (reply->attribute(QNetworkRequest::DownloadBufferAttribute).isValid() == true) + requestFinishedDownloadBufferCount++; + + if (requestFinishedCount % 10) + return; + +#ifdef QT_DEBUG + double pctCached = (double(requestFinishedFromCacheCount) * 100.0/ double(requestFinishedCount)); + double pctPipelined = (double(requestFinishedPipelinedCount) * 100.0/ double(requestFinishedCount)); + double pctSecure = (double(requestFinishedSecureCount) * 100.0/ double(requestFinishedCount)); + double pctDownloadBuffer = (double(requestFinishedDownloadBufferCount) * 100.0/ double(requestFinishedCount)); + + qDebug("STATS [%lli requests total] [%3.2f%% from cache] [%3.2f%% pipelined] [%3.2f%% SSL/TLS] [%3.2f%% Zerocopy]", requestFinishedCount, pctCached, pctPipelined, pctSecure, pctDownloadBuffer); +#endif +} + +void NetworkAccessManager::loadSettings() +{ + QSettings settings; + settings.beginGroup(QLatin1String("proxy")); + QNetworkProxy proxy; + if (settings.value(QLatin1String("enabled"), false).toBool()) { + if (settings.value(QLatin1String("type"), 0).toInt() == 0) + proxy = QNetworkProxy::Socks5Proxy; + else + proxy = QNetworkProxy::HttpProxy; + proxy.setHostName(settings.value(QLatin1String("hostName")).toString()); + proxy.setPort(settings.value(QLatin1String("port"), 1080).toInt()); + proxy.setUser(settings.value(QLatin1String("userName")).toString()); + proxy.setPassword(settings.value(QLatin1String("password")).toString()); + } + setProxy(proxy); +} + +#ifndef QT_NO_OPENSSL +void NetworkAccessManager::sslErrors(QNetworkReply *reply, const QList &error) +{ + // check if SSL certificate has been trusted already + QString replyHost = reply->url().host() + QString(":%1").arg(reply->url().port()); + if (! sslTrustedHostList.contains(replyHost)) { + BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow(); + + QStringList errorStrings; + for (int i = 0; i < error.count(); ++i) + errorStrings += error.at(i).errorString(); + QString errors = errorStrings.join(QLatin1String("\n")); + int ret = QMessageBox::warning(mainWindow, QCoreApplication::applicationName(), + tr("SSL Errors:\n\n%1\n\n%2\n\n" + "Do you want to ignore these errors for this host?").arg(reply->url().toString()).arg(errors), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No); + if (ret == QMessageBox::Yes) { + reply->ignoreSslErrors(); + sslTrustedHostList.append(replyHost); + } + } +} +#endif diff --git a/examples/webenginewidgets/browser/networkaccessmanager.h b/examples/webenginewidgets/browser/networkaccessmanager.h new file mode 100644 index 000000000..54c24f86e --- /dev/null +++ b/examples/webenginewidgets/browser/networkaccessmanager.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NETWORKACCESSMANAGER_H +#define NETWORKACCESSMANAGER_H + +#include +#include + +class NetworkAccessManager : public QNetworkAccessManager +{ + Q_OBJECT + +public: + NetworkAccessManager(QObject *parent = 0); + + virtual QNetworkReply* createRequest ( Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0 ); + +private: + QList sslTrustedHostList; + qint64 requestFinishedCount; + qint64 requestFinishedFromCacheCount; + qint64 requestFinishedPipelinedCount; + qint64 requestFinishedSecureCount; + qint64 requestFinishedDownloadBufferCount; + +public slots: + void loadSettings(); + void requestFinished(QNetworkReply *reply); + +private slots: +#ifndef QT_NO_OPENSSL + void sslErrors(QNetworkReply *reply, const QList &error); +#endif +}; + +#endif // NETWORKACCESSMANAGER_H diff --git a/examples/webenginewidgets/browser/passworddialog.ui b/examples/webenginewidgets/browser/passworddialog.ui new file mode 100644 index 000000000..7c1665867 --- /dev/null +++ b/examples/webenginewidgets/browser/passworddialog.ui @@ -0,0 +1,111 @@ + + PasswordDialog + + + + 0 + 0 + 399 + 148 + + + + Authentication Required + + + + + + + + DUMMY ICON + + + + + + + + 0 + 0 + + + + INTRO TEXT DUMMY + + + + + + + + + Username: + + + + + + + + + + Password: + + + + + + + QLineEdit::Password + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + PasswordDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + PasswordDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/examples/webenginewidgets/browser/proxy.ui b/examples/webenginewidgets/browser/proxy.ui new file mode 100644 index 000000000..62a8be627 --- /dev/null +++ b/examples/webenginewidgets/browser/proxy.ui @@ -0,0 +1,104 @@ + + ProxyDialog + + + + 0 + 0 + 369 + 144 + + + + Proxy Authentication + + + + + + ICON + + + + + + + Connect to proxy + + + true + + + + + + + Username: + + + + + + + + + + Password: + + + + + + + QLineEdit::Password + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + ProxyDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + ProxyDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/examples/webenginewidgets/browser/searchlineedit.cpp b/examples/webenginewidgets/browser/searchlineedit.cpp new file mode 100644 index 000000000..0d387da4b --- /dev/null +++ b/examples/webenginewidgets/browser/searchlineedit.cpp @@ -0,0 +1,240 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "searchlineedit.h" + +#include +#include +#include +#include +#include + +ClearButton::ClearButton(QWidget *parent) + : QAbstractButton(parent) +{ +#ifndef QT_NO_CURSOR + setCursor(Qt::ArrowCursor); +#endif // QT_NO_CURSOR + setToolTip(tr("Clear")); + setVisible(false); + setFocusPolicy(Qt::NoFocus); +} + +void ClearButton::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + QPainter painter(this); + int height = this->height(); + + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setBrush(isDown() + ? palette().color(QPalette::Dark) + : palette().color(QPalette::Mid)); + painter.setPen(painter.brush().color()); + int size = width(); + int offset = size / 5; + int radius = size - offset * 2; + painter.drawEllipse(offset, offset, radius, radius); + + painter.setPen(palette().color(QPalette::Base)); + int border = offset * 2; + painter.drawLine(border, border, width() - border, height - border); + painter.drawLine(border, height - border, width() - border, border); +} + +void ClearButton::textChanged(const QString &text) +{ + setVisible(!text.isEmpty()); +} + +/* + Search icon on the left hand side of the search widget + When a menu is set a down arrow appears + */ +class SearchButton : public QAbstractButton { +public: + SearchButton(QWidget *parent = 0); + void paintEvent(QPaintEvent *event); + QMenu *m_menu; + +protected: + void mousePressEvent(QMouseEvent *event); +}; + +SearchButton::SearchButton(QWidget *parent) + : QAbstractButton(parent), + m_menu(0) +{ + setObjectName(QLatin1String("SearchButton")); +#ifndef QT_NO_CURSOR + setCursor(Qt::ArrowCursor); +#endif //QT_NO_CURSOR + setFocusPolicy(Qt::NoFocus); +} + +void SearchButton::mousePressEvent(QMouseEvent *event) +{ + if (m_menu && event->button() == Qt::LeftButton) { + QWidget *p = parentWidget(); + if (p) { + QPoint r = p->mapToGlobal(QPoint(0, p->height())); + m_menu->exec(QPoint(r.x() + height() / 2, r.y())); + } + event->accept(); + } + QAbstractButton::mousePressEvent(event); +} + +void SearchButton::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + QPainterPath myPath; + + int radius = (height() / 5) * 2; + QRect circle(height() / 3 - 1, height() / 4, radius, radius); + myPath.addEllipse(circle); + + myPath.arcMoveTo(circle, 300); + QPointF c = myPath.currentPosition(); + int diff = height() / 7; + myPath.lineTo(qMin(width() - 2, (int)c.x() + diff), c.y() + diff); + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setPen(QPen(Qt::darkGray, 2)); + painter.drawPath(myPath); + + if (m_menu) { + QPainterPath dropPath; + dropPath.arcMoveTo(circle, 320); + QPointF c = dropPath.currentPosition(); + c = QPointF(c.x() + 3.5, c.y() + 0.5); + dropPath.moveTo(c); + dropPath.lineTo(c.x() + 4, c.y()); + dropPath.lineTo(c.x() + 2, c.y() + 2); + dropPath.closeSubpath(); + painter.setPen(Qt::darkGray); + painter.setBrush(Qt::darkGray); + painter.setRenderHint(QPainter::Antialiasing, false); + painter.drawPath(dropPath); + } + painter.end(); +} + +/* + SearchLineEdit is an enhanced QLineEdit + - A Search icon on the left with optional menu + - When there is no text and doesn't have focus an "inactive text" is displayed + - When there is text a clear button is displayed on the right hand side + */ +SearchLineEdit::SearchLineEdit(QWidget *parent) : ExLineEdit(parent), + m_searchButton(new SearchButton(this)) +{ + connect(lineEdit(), SIGNAL(textChanged(QString)), + this, SIGNAL(textChanged(QString))); + setLeftWidget(m_searchButton); + m_inactiveText = tr("Search"); + + QSizePolicy policy = sizePolicy(); + setSizePolicy(QSizePolicy::Preferred, policy.verticalPolicy()); +} + +void SearchLineEdit::paintEvent(QPaintEvent *event) +{ + if (lineEdit()->text().isEmpty() && !hasFocus() && !m_inactiveText.isEmpty()) { + ExLineEdit::paintEvent(event); + QStyleOptionFrameV2 panel; + initStyleOption(&panel); + QRect r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this); + QFontMetrics fm = fontMetrics(); + int horizontalMargin = lineEdit()->x(); + QRect lineRect(horizontalMargin + r.x(), r.y() + (r.height() - fm.height() + 1) / 2, + r.width() - 2 * horizontalMargin, fm.height()); + QPainter painter(this); + painter.setPen(palette().brush(QPalette::Disabled, QPalette::Text).color()); + painter.drawText(lineRect, Qt::AlignLeft|Qt::AlignVCenter, m_inactiveText); + } else { + ExLineEdit::paintEvent(event); + } +} + +void SearchLineEdit::resizeEvent(QResizeEvent *event) +{ + updateGeometries(); + ExLineEdit::resizeEvent(event); +} + +void SearchLineEdit::updateGeometries() +{ + int menuHeight = height(); + int menuWidth = menuHeight + 1; + if (!m_searchButton->m_menu) + menuWidth = (menuHeight / 5) * 4; + m_searchButton->resize(QSize(menuWidth, menuHeight)); +} + +QString SearchLineEdit::inactiveText() const +{ + return m_inactiveText; +} + +void SearchLineEdit::setInactiveText(const QString &text) +{ + m_inactiveText = text; +} + +void SearchLineEdit::setMenu(QMenu *menu) +{ + if (m_searchButton->m_menu) + m_searchButton->m_menu->deleteLater(); + m_searchButton->m_menu = menu; + updateGeometries(); +} + +QMenu *SearchLineEdit::menu() const +{ + if (!m_searchButton->m_menu) { + m_searchButton->m_menu = new QMenu(m_searchButton); + if (isVisible()) + (const_cast(this))->updateGeometries(); + } + return m_searchButton->m_menu; +} diff --git a/examples/webenginewidgets/browser/searchlineedit.h b/examples/webenginewidgets/browser/searchlineedit.h new file mode 100644 index 000000000..e01fcbff2 --- /dev/null +++ b/examples/webenginewidgets/browser/searchlineedit.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SEARCHLINEEDIT_H +#define SEARCHLINEEDIT_H + +#include "urllineedit.h" + +#include +#include + +QT_BEGIN_NAMESPACE +class QMenu; +QT_END_NAMESPACE + +class SearchButton; + +/* + Clear button on the right hand side of the search widget. + Hidden by default + "A circle with an X in it" + */ +class ClearButton : public QAbstractButton +{ + Q_OBJECT + +public: + ClearButton(QWidget *parent = 0); + void paintEvent(QPaintEvent *event); + +public slots: + void textChanged(const QString &text); +}; + + +class SearchLineEdit : public ExLineEdit +{ + Q_OBJECT + Q_PROPERTY(QString inactiveText READ inactiveText WRITE setInactiveText) + +signals: + void textChanged(const QString &text); + +public: + SearchLineEdit(QWidget *parent = 0); + + QString inactiveText() const; + void setInactiveText(const QString &text); + + QMenu *menu() const; + void setMenu(QMenu *menu); + +protected: + void resizeEvent(QResizeEvent *event); + void paintEvent(QPaintEvent *event); + +private: + void updateGeometries(); + + SearchButton *m_searchButton; + QString m_inactiveText; +}; + +#endif // SEARCHLINEEDIT_H diff --git a/examples/webenginewidgets/browser/settings.cpp b/examples/webenginewidgets/browser/settings.cpp new file mode 100644 index 000000000..6838c19aa --- /dev/null +++ b/examples/webenginewidgets/browser/settings.cpp @@ -0,0 +1,331 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "settings.h" + +#include "browserapplication.h" +#include "browsermainwindow.h" +#include "cookiejar.h" +#include "history.h" +#include "networkaccessmanager.h" +#include "webview.h" + +#include +#include +#include + +SettingsDialog::SettingsDialog(QWidget *parent) + : QDialog(parent) +{ + setupUi(this); + connect(exceptionsButton, SIGNAL(clicked()), this, SLOT(showExceptions())); + connect(setHomeToCurrentPageButton, SIGNAL(clicked()), this, SLOT(setHomeToCurrentPage())); + connect(cookiesButton, SIGNAL(clicked()), this, SLOT(showCookies())); + connect(standardFontButton, SIGNAL(clicked()), this, SLOT(chooseFont())); + connect(fixedFontButton, SIGNAL(clicked()), this, SLOT(chooseFixedFont())); + + loadDefaults(); + loadFromSettings(); +} + +void SettingsDialog::loadDefaults() +{ +#if defined(QWEBENGINESETTINGS) + QWebEngineSettings *defaultSettings = QWebEngineSettings::globalSettings(); + QString standardFontFamily = defaultSettings->fontFamily(QWebEngineSettings::StandardFont); + int standardFontSize = defaultSettings->fontSize(QWebEngineSettings::DefaultFontSize); + standardFont = QFont(standardFontFamily, standardFontSize); + standardLabel->setText(QString(QLatin1String("%1 %2")).arg(standardFont.family()).arg(standardFont.pointSize())); + + QString fixedFontFamily = defaultSettings->fontFamily(QWebEngineSettings::FixedFont); + int fixedFontSize = defaultSettings->fontSize(QWebEngineSettings::DefaultFixedFontSize); + fixedFont = QFont(fixedFontFamily, fixedFontSize); + fixedLabel->setText(QString(QLatin1String("%1 %2")).arg(fixedFont.family()).arg(fixedFont.pointSize())); + + downloadsLocation->setText(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); + + enableJavascript->setChecked(defaultSettings->testAttribute(QWebEngineSettings::JavascriptEnabled)); + enablePlugins->setChecked(defaultSettings->testAttribute(QWebEngineSettings::PluginsEnabled)); +#endif +} + +void SettingsDialog::loadFromSettings() +{ +#if defined(QWEBENGINESETTINGS) + QSettings settings; + settings.beginGroup(QLatin1String("MainWindow")); + QString defaultHome = QLatin1String("http://qt-project.org/"); + homeLineEdit->setText(settings.value(QLatin1String("home"), defaultHome).toString()); + settings.endGroup(); + + settings.beginGroup(QLatin1String("history")); + int historyExpire = settings.value(QLatin1String("historyExpire")).toInt(); + int idx = 0; + switch (historyExpire) { + case 1: idx = 0; break; + case 7: idx = 1; break; + case 14: idx = 2; break; + case 30: idx = 3; break; + case 365: idx = 4; break; + case -1: idx = 5; break; + default: + idx = 5; + } + expireHistory->setCurrentIndex(idx); + settings.endGroup(); + + settings.beginGroup(QLatin1String("downloadmanager")); + QString downloadDirectory = settings.value(QLatin1String("downloadDirectory"), downloadsLocation->text()).toString(); + downloadsLocation->setText(downloadDirectory); + settings.endGroup(); + + settings.beginGroup(QLatin1String("general")); + openLinksIn->setCurrentIndex(settings.value(QLatin1String("openLinksIn"), openLinksIn->currentIndex()).toInt()); + + settings.endGroup(); + + // Appearance + settings.beginGroup(QLatin1String("websettings")); + fixedFont = qvariant_cast(settings.value(QLatin1String("fixedFont"), fixedFont)); + standardFont = qvariant_cast(settings.value(QLatin1String("standardFont"), standardFont)); + + standardLabel->setText(QString(QLatin1String("%1 %2")).arg(standardFont.family()).arg(standardFont.pointSize())); + fixedLabel->setText(QString(QLatin1String("%1 %2")).arg(fixedFont.family()).arg(fixedFont.pointSize())); + + enableJavascript->setChecked(settings.value(QLatin1String("enableJavascript"), enableJavascript->isChecked()).toBool()); + enablePlugins->setChecked(settings.value(QLatin1String("enablePlugins"), enablePlugins->isChecked()).toBool()); + userStyleSheet->setText(settings.value(QLatin1String("userStyleSheet")).toUrl().toString()); + settings.endGroup(); + + // Privacy + settings.beginGroup(QLatin1String("cookies")); + + QByteArray value = settings.value(QLatin1String("acceptCookies"), QLatin1String("AcceptOnlyFromSitesNavigatedTo")).toByteArray(); + QMetaEnum acceptPolicyEnum = CookieJar::staticMetaObject.enumerator(CookieJar::staticMetaObject.indexOfEnumerator("AcceptPolicy")); + CookieJar::AcceptPolicy acceptCookies = acceptPolicyEnum.keyToValue(value) == -1 ? + CookieJar::AcceptOnlyFromSitesNavigatedTo : + static_cast(acceptPolicyEnum.keyToValue(value)); + switch (acceptCookies) { + case CookieJar::AcceptAlways: + acceptCombo->setCurrentIndex(0); + break; + case CookieJar::AcceptNever: + acceptCombo->setCurrentIndex(1); + break; + case CookieJar::AcceptOnlyFromSitesNavigatedTo: + acceptCombo->setCurrentIndex(2); + break; + } + + value = settings.value(QLatin1String("keepCookiesUntil"), QLatin1String("Expire")).toByteArray(); + QMetaEnum keepPolicyEnum = CookieJar::staticMetaObject.enumerator(CookieJar::staticMetaObject.indexOfEnumerator("KeepPolicy")); + CookieJar::KeepPolicy keepCookies = keepPolicyEnum.keyToValue(value) == -1 ? + CookieJar::KeepUntilExpire : + static_cast(keepPolicyEnum.keyToValue(value)); + switch (keepCookies) { + case CookieJar::KeepUntilExpire: + keepUntilCombo->setCurrentIndex(0); + break; + case CookieJar::KeepUntilExit: + keepUntilCombo->setCurrentIndex(1); + break; + case CookieJar::KeepUntilTimeLimit: + keepUntilCombo->setCurrentIndex(2); + break; + } + settings.endGroup(); + + + // Proxy + settings.beginGroup(QLatin1String("proxy")); + proxySupport->setChecked(settings.value(QLatin1String("enabled"), false).toBool()); + proxyType->setCurrentIndex(settings.value(QLatin1String("type"), 0).toInt()); + proxyHostName->setText(settings.value(QLatin1String("hostName")).toString()); + proxyPort->setValue(settings.value(QLatin1String("port"), 1080).toInt()); + proxyUserName->setText(settings.value(QLatin1String("userName")).toString()); + proxyPassword->setText(settings.value(QLatin1String("password")).toString()); + settings.endGroup(); +#endif +} + +void SettingsDialog::saveToSettings() +{ +#if defined(QWEBENGINESETTINGS) + QSettings settings; + settings.beginGroup(QLatin1String("MainWindow")); + settings.setValue(QLatin1String("home"), homeLineEdit->text()); + settings.endGroup(); + + settings.beginGroup(QLatin1String("general")); + settings.setValue(QLatin1String("openLinksIn"), openLinksIn->currentIndex()); + settings.endGroup(); + + settings.beginGroup(QLatin1String("history")); + int historyExpire = expireHistory->currentIndex(); + int idx = -1; + switch (historyExpire) { + case 0: idx = 1; break; + case 1: idx = 7; break; + case 2: idx = 14; break; + case 3: idx = 30; break; + case 4: idx = 365; break; + case 5: idx = -1; break; + } + settings.setValue(QLatin1String("historyExpire"), idx); + settings.endGroup(); + + // Appearance + settings.beginGroup(QLatin1String("websettings")); + settings.setValue(QLatin1String("fixedFont"), fixedFont); + settings.setValue(QLatin1String("standardFont"), standardFont); + settings.setValue(QLatin1String("enableJavascript"), enableJavascript->isChecked()); + settings.setValue(QLatin1String("enablePlugins"), enablePlugins->isChecked()); + QString userStyleSheetString = userStyleSheet->text(); + if (QFile::exists(userStyleSheetString)) + settings.setValue(QLatin1String("userStyleSheet"), QUrl::fromLocalFile(userStyleSheetString)); + else + settings.setValue(QLatin1String("userStyleSheet"), QUrl(userStyleSheetString)); + settings.endGroup(); + + //Privacy + settings.beginGroup(QLatin1String("cookies")); + + CookieJar::KeepPolicy keepCookies; + switch (acceptCombo->currentIndex()) { + default: + case 0: + keepCookies = CookieJar::KeepUntilExpire; + break; + case 1: + keepCookies = CookieJar::KeepUntilExit; + break; + case 2: + keepCookies = CookieJar::KeepUntilTimeLimit; + break; + } + QMetaEnum acceptPolicyEnum = CookieJar::staticMetaObject.enumerator(CookieJar::staticMetaObject.indexOfEnumerator("AcceptPolicy")); + settings.setValue(QLatin1String("acceptCookies"), QLatin1String(acceptPolicyEnum.valueToKey(keepCookies))); + + CookieJar::KeepPolicy keepPolicy; + switch (keepUntilCombo->currentIndex()) { + default: + case 0: + keepPolicy = CookieJar::KeepUntilExpire; + break; + case 1: + keepPolicy = CookieJar::KeepUntilExit; + break; + case 2: + keepPolicy = CookieJar::KeepUntilTimeLimit; + break; + } + + QMetaEnum keepPolicyEnum = CookieJar::staticMetaObject.enumerator(CookieJar::staticMetaObject.indexOfEnumerator("KeepPolicy")); + settings.setValue(QLatin1String("keepCookiesUntil"), QLatin1String(keepPolicyEnum.valueToKey(keepPolicy))); + + settings.endGroup(); + + // proxy + settings.beginGroup(QLatin1String("proxy")); + settings.setValue(QLatin1String("enabled"), proxySupport->isChecked()); + settings.setValue(QLatin1String("type"), proxyType->currentIndex()); + settings.setValue(QLatin1String("hostName"), proxyHostName->text()); + settings.setValue(QLatin1String("port"), proxyPort->text()); + settings.setValue(QLatin1String("userName"), proxyUserName->text()); + settings.setValue(QLatin1String("password"), proxyPassword->text()); + settings.endGroup(); + + BrowserApplication::instance()->loadSettings(); + BrowserApplication::networkAccessManager()->loadSettings(); + BrowserApplication::cookieJar()->loadSettings(); + BrowserApplication::historyManager()->loadSettings(); +#endif +} + +void SettingsDialog::accept() +{ + saveToSettings(); + QDialog::accept(); +} + +void SettingsDialog::showCookies() +{ +#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) + CookiesDialog *dialog = new CookiesDialog(BrowserApplication::cookieJar(), this); + dialog->exec(); +#endif +} + +void SettingsDialog::showExceptions() +{ +#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) + CookiesExceptionsDialog *dialog = new CookiesExceptionsDialog(BrowserApplication::cookieJar(), this); + dialog->exec(); +#endif +} + +void SettingsDialog::chooseFont() +{ + bool ok; + QFont font = QFontDialog::getFont(&ok, standardFont, this); + if ( ok ) { + standardFont = font; + standardLabel->setText(QString(QLatin1String("%1 %2")).arg(font.family()).arg(font.pointSize())); + } +} + +void SettingsDialog::chooseFixedFont() +{ + bool ok; + QFont font = QFontDialog::getFont(&ok, fixedFont, this); + if ( ok ) { + fixedFont = font; + fixedLabel->setText(QString(QLatin1String("%1 %2")).arg(font.family()).arg(font.pointSize())); + } +} + +void SettingsDialog::setHomeToCurrentPage() +{ + BrowserMainWindow *mw = static_cast(parent()); + WebView *webView = mw->currentTab(); + if (webView) + homeLineEdit->setText(webView->url().toString()); +} diff --git a/examples/webenginewidgets/browser/settings.h b/examples/webenginewidgets/browser/settings.h new file mode 100644 index 000000000..0858e0023 --- /dev/null +++ b/examples/webenginewidgets/browser/settings.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SETTINGS_H +#define SETTINGS_H + +#include +#include "ui_settings.h" + +class SettingsDialog : public QDialog, public Ui_Settings +{ + Q_OBJECT + +public: + SettingsDialog(QWidget *parent = 0); + void accept(); + +private slots: + void loadDefaults(); + void loadFromSettings(); + void saveToSettings(); + + void setHomeToCurrentPage(); + void showCookies(); + void showExceptions(); + + void chooseFont(); + void chooseFixedFont(); + +private: + QFont standardFont; + QFont fixedFont; +}; + +#endif // SETTINGS_H diff --git a/examples/webenginewidgets/browser/settings.ui b/examples/webenginewidgets/browser/settings.ui new file mode 100644 index 000000000..3491ce0b0 --- /dev/null +++ b/examples/webenginewidgets/browser/settings.ui @@ -0,0 +1,614 @@ + + Settings + + + + 0 + 0 + 657 + 322 + + + + Settings + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + 0 + + + + + 0 + 0 + 627 + 243 + + + + General + + + + + + Home: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Set to current page + + + + + + + Qt::Horizontal + + + + 280 + 18 + + + + + + + + Remove history items: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + After one day + + + + + After one week + + + + + After two weeks + + + + + After one month + + + + + After one year + + + + + Manually + + + + + + + + Save downloads to: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Open links from applications: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + In a tab in the current window + + + + + In a new window + + + + + + + + Qt::Vertical + + + + 391 + 262 + + + + + + + + + + 0 + 0 + 627 + 243 + + + + Appearance + + + + + + Standard font: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + Times 16 + + + Qt::AlignCenter + + + + + + + Select... + + + + + + + Fixed-width font: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + QFrame::StyledPanel + + + Courier 13 + + + Qt::AlignCenter + + + + + + + Select... + + + + + + + Qt::Vertical + + + + 20 + 93 + + + + + + + + + + 0 + 0 + 627 + 243 + + + + Privacy + + + + + + Web Content + + + + + + Enable Plugins + + + true + + + + + + + Enable Javascript + + + true + + + + + + + + + + Cookies + + + + + + Accept Cookies: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + Always + + + + + Never + + + + + Only from sites you navigate to + + + + + + + + Exceptions... + + + + + + + Keep until: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + They expire + + + + + I exit the application + + + + + At most 90 days + + + + + + + + Cookies... + + + + + + + + + + Qt::Vertical + + + + 371 + 177 + + + + + + + + + + 0 + 0 + 627 + 243 + + + + Proxy + + + + + + Enable proxy + + + true + + + + + + Type: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + Socks5 + + + + + Http + + + + + + + + Host: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Port: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 10000 + + + 1080 + + + + + + + Qt::Horizontal + + + + 293 + 20 + + + + + + + + User Name: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Password: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + QLineEdit::Password + + + + + + + Qt::Vertical + + + + 20 + 8 + + + + + + + + + + + + Advanced + + + + + + Style Sheet: + + + + + + + + + + Qt::Vertical + + + + 20 + 176 + + + + + + + + + + + + + + buttonBox + accepted() + Settings + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Settings + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/examples/webenginewidgets/browser/squeezelabel.cpp b/examples/webenginewidgets/browser/squeezelabel.cpp new file mode 100644 index 000000000..c40fe97da --- /dev/null +++ b/examples/webenginewidgets/browser/squeezelabel.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "squeezelabel.h" + +SqueezeLabel::SqueezeLabel(QWidget *parent) : QLabel(parent) +{ +} + +void SqueezeLabel::paintEvent(QPaintEvent *event) +{ + QFontMetrics fm = fontMetrics(); + if (fm.width(text()) > contentsRect().width()) { + QString elided = fm.elidedText(text(), Qt::ElideMiddle, width()); + QString oldText = text(); + setText(elided); + QLabel::paintEvent(event); + setText(oldText); + } else { + QLabel::paintEvent(event); + } +} diff --git a/examples/webenginewidgets/browser/squeezelabel.h b/examples/webenginewidgets/browser/squeezelabel.h new file mode 100644 index 000000000..6df84179a --- /dev/null +++ b/examples/webenginewidgets/browser/squeezelabel.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SQUEEZELABEL_H +#define SQUEEZELABEL_H + +#include + +class SqueezeLabel : public QLabel +{ + Q_OBJECT + +public: + SqueezeLabel(QWidget *parent = 0); + +protected: + void paintEvent(QPaintEvent *event); + +}; + +#endif // SQUEEZELABEL_H diff --git a/examples/webenginewidgets/browser/tabwidget.cpp b/examples/webenginewidgets/browser/tabwidget.cpp new file mode 100644 index 000000000..3c71b2d53 --- /dev/null +++ b/examples/webenginewidgets/browser/tabwidget.cpp @@ -0,0 +1,839 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tabwidget.h" + +#include "browserapplication.h" +#include "browsermainwindow.h" +#include "history.h" +#include "urllineedit.h" +#include "webview.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +TabBar::TabBar(QWidget *parent) + : QTabBar(parent) +{ + setContextMenuPolicy(Qt::CustomContextMenu); + setAcceptDrops(true); + connect(this, SIGNAL(customContextMenuRequested(QPoint)), + this, SLOT(contextMenuRequested(QPoint))); + + QString ctrl = QLatin1String("Ctrl+%1"); + for (int i = 1; i <= 10; ++i) { + int key = i; + if (key == 10) + key = 0; + QShortcut *shortCut = new QShortcut(ctrl.arg(key), this); + m_tabShortcuts.append(shortCut); + connect(shortCut, SIGNAL(activated()), this, SLOT(selectTabAction())); + } + setTabsClosable(true); + connect(this, SIGNAL(tabCloseRequested(int)), + this, SIGNAL(closeTab(int))); + setSelectionBehaviorOnRemove(QTabBar::SelectPreviousTab); + setMovable(true); +} + +void TabBar::selectTabAction() +{ + if (QShortcut *shortCut = qobject_cast(sender())) { + int index = m_tabShortcuts.indexOf(shortCut); + if (index == 0) + index = 10; + setCurrentIndex(index); + } +} + +void TabBar::contextMenuRequested(const QPoint &position) +{ + QMenu menu; + menu.addAction(tr("New &Tab"), this, SIGNAL(newTab()), QKeySequence::AddTab); + int index = tabAt(position); + if (-1 != index) { + QAction *action = menu.addAction(tr("Clone Tab"), + this, SLOT(cloneTab())); + action->setData(index); + + menu.addSeparator(); + + action = menu.addAction(tr("&Close Tab"), + this, SLOT(closeTab()), QKeySequence::Close); + action->setData(index); + + action = menu.addAction(tr("Close &Other Tabs"), + this, SLOT(closeOtherTabs())); + action->setData(index); + + menu.addSeparator(); + + action = menu.addAction(tr("Reload Tab"), + this, SLOT(reloadTab()), QKeySequence::Refresh); + action->setData(index); + } else { + menu.addSeparator(); + } + menu.addAction(tr("Reload All Tabs"), this, SIGNAL(reloadAllTabs())); + menu.exec(QCursor::pos()); +} + +void TabBar::cloneTab() +{ + if (QAction *action = qobject_cast(sender())) { + int index = action->data().toInt(); + emit cloneTab(index); + } +} + +void TabBar::closeTab() +{ + if (QAction *action = qobject_cast(sender())) { + int index = action->data().toInt(); + emit closeTab(index); + } +} + +void TabBar::closeOtherTabs() +{ + if (QAction *action = qobject_cast(sender())) { + int index = action->data().toInt(); + emit closeOtherTabs(index); + } +} + +void TabBar::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) + m_dragStartPos = event->pos(); + QTabBar::mousePressEvent(event); +} + +void TabBar::mouseMoveEvent(QMouseEvent *event) +{ + if (event->buttons() == Qt::LeftButton) { + int diffX = event->pos().x() - m_dragStartPos.x(); + int diffY = event->pos().y() - m_dragStartPos.y(); + if ((event->pos() - m_dragStartPos).manhattanLength() > QApplication::startDragDistance() + && diffX < 3 && diffX > -3 + && diffY < -10) { + QDrag *drag = new QDrag(this); + QMimeData *mimeData = new QMimeData; + QList urls; + int index = tabAt(event->pos()); + QUrl url = tabData(index).toUrl(); + urls.append(url); + mimeData->setUrls(urls); + mimeData->setText(tabText(index)); + mimeData->setData(QLatin1String("action"), "tab-reordering"); + drag->setMimeData(mimeData); + drag->exec(); + } + } + QTabBar::mouseMoveEvent(event); +} + +// When index is -1 index chooses the current tab +void TabWidget::reloadTab(int index) +{ + if (index < 0) + index = currentIndex(); + if (index < 0 || index >= count()) + return; + + QWidget *widget = this->widget(index); + if (WebView *tab = qobject_cast(widget)) + tab->reload(); +} + +void TabBar::reloadTab() +{ + if (QAction *action = qobject_cast(sender())) { + int index = action->data().toInt(); + emit reloadTab(index); + } +} + +TabWidget::TabWidget(QWidget *parent) + : QTabWidget(parent) + , m_recentlyClosedTabsAction(0) + , m_newTabAction(0) + , m_closeTabAction(0) + , m_nextTabAction(0) + , m_previousTabAction(0) + , m_recentlyClosedTabsMenu(0) + , m_lineEditCompleter(0) + , m_lineEdits(0) + , m_tabBar(new TabBar(this)) +{ + setElideMode(Qt::ElideRight); + + connect(m_tabBar, SIGNAL(newTab()), this, SLOT(newTab())); + connect(m_tabBar, SIGNAL(closeTab(int)), this, SLOT(closeTab(int))); + connect(m_tabBar, SIGNAL(cloneTab(int)), this, SLOT(cloneTab(int))); + connect(m_tabBar, SIGNAL(closeOtherTabs(int)), this, SLOT(closeOtherTabs(int))); + connect(m_tabBar, SIGNAL(reloadTab(int)), this, SLOT(reloadTab(int))); + connect(m_tabBar, SIGNAL(reloadAllTabs()), this, SLOT(reloadAllTabs())); + connect(m_tabBar, SIGNAL(tabMoved(int,int)), this, SLOT(moveTab(int,int))); + setTabBar(m_tabBar); + setDocumentMode(true); + + // Actions + m_newTabAction = new QAction(QIcon(QLatin1String(":addtab.png")), tr("New &Tab"), this); + m_newTabAction->setShortcuts(QKeySequence::AddTab); + m_newTabAction->setIconVisibleInMenu(false); + connect(m_newTabAction, SIGNAL(triggered()), this, SLOT(newTab())); + + m_closeTabAction = new QAction(QIcon(QLatin1String(":closetab.png")), tr("&Close Tab"), this); + m_closeTabAction->setShortcuts(QKeySequence::Close); + m_closeTabAction->setIconVisibleInMenu(false); + connect(m_closeTabAction, SIGNAL(triggered()), this, SLOT(closeTab())); + + m_nextTabAction = new QAction(tr("Show Next Tab"), this); + QList shortcuts; + shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_BraceRight)); + shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_PageDown)); + shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_BracketRight)); + shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_Less)); + m_nextTabAction->setShortcuts(shortcuts); + connect(m_nextTabAction, SIGNAL(triggered()), this, SLOT(nextTab())); + + m_previousTabAction = new QAction(tr("Show Previous Tab"), this); + shortcuts.clear(); + shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_BraceLeft)); + shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_PageUp)); + shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_BracketLeft)); + shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_Greater)); + m_previousTabAction->setShortcuts(shortcuts); + connect(m_previousTabAction, SIGNAL(triggered()), this, SLOT(previousTab())); + + m_recentlyClosedTabsMenu = new QMenu(this); + connect(m_recentlyClosedTabsMenu, SIGNAL(aboutToShow()), + this, SLOT(aboutToShowRecentTabsMenu())); + connect(m_recentlyClosedTabsMenu, SIGNAL(triggered(QAction*)), + this, SLOT(aboutToShowRecentTriggeredAction(QAction*))); + m_recentlyClosedTabsAction = new QAction(tr("Recently Closed Tabs"), this); + m_recentlyClosedTabsAction->setMenu(m_recentlyClosedTabsMenu); + m_recentlyClosedTabsAction->setEnabled(false); + + connect(this, SIGNAL(currentChanged(int)), + this, SLOT(currentChanged(int))); + + m_lineEdits = new QStackedWidget(this); +} + +void TabWidget::clear() +{ + // clear the recently closed tabs + m_recentlyClosedTabs.clear(); + // clear the line edit history + for (int i = 0; i < m_lineEdits->count(); ++i) { + QLineEdit *qLineEdit = lineEdit(i); + qLineEdit->setText(qLineEdit->text()); + } +} + +void TabWidget::moveTab(int fromIndex, int toIndex) +{ + QWidget *lineEdit = m_lineEdits->widget(fromIndex); + m_lineEdits->removeWidget(lineEdit); + m_lineEdits->insertWidget(toIndex, lineEdit); +} + +void TabWidget::addWebAction(QAction *action, QWebEnginePage::WebAction webAction) +{ + if (!action) + return; + m_actions.append(new WebActionMapper(action, webAction, this)); +} + +void TabWidget::currentChanged(int index) +{ + WebView *webView = this->webView(index); + if (!webView) + return; + + Q_ASSERT(m_lineEdits->count() == count()); + + WebView *oldWebView = this->webView(m_lineEdits->currentIndex()); + if (oldWebView) { + disconnect(oldWebView, SIGNAL(statusBarMessage(QString)), + this, SIGNAL(showStatusBarMessage(QString))); + disconnect(oldWebView->page(), SIGNAL(linkHovered(QString,QString,QString)), + this, SIGNAL(linkHovered(QString))); + disconnect(oldWebView, SIGNAL(loadProgress(int)), + this, SIGNAL(loadProgress(int))); + } + + connect(webView, SIGNAL(statusBarMessage(QString)), + this, SIGNAL(showStatusBarMessage(QString))); + connect(webView->page(), SIGNAL(linkHovered(QString,QString,QString)), + this, SIGNAL(linkHovered(QString))); + connect(webView, SIGNAL(loadProgress(int)), + this, SIGNAL(loadProgress(int))); + + for (int i = 0; i < m_actions.count(); ++i) { + WebActionMapper *mapper = m_actions[i]; + mapper->updateCurrent(webView->page()); + } + emit setCurrentTitle(webView->title()); + m_lineEdits->setCurrentIndex(index); + emit loadProgress(webView->progress()); + emit showStatusBarMessage(webView->lastStatusBarText()); + if (webView->url().isEmpty()) + m_lineEdits->currentWidget()->setFocus(); + else + webView->setFocus(); +} + +QAction *TabWidget::newTabAction() const +{ + return m_newTabAction; +} + +QAction *TabWidget::closeTabAction() const +{ + return m_closeTabAction; +} + +QAction *TabWidget::recentlyClosedTabsAction() const +{ + return m_recentlyClosedTabsAction; +} + +QAction *TabWidget::nextTabAction() const +{ + return m_nextTabAction; +} + +QAction *TabWidget::previousTabAction() const +{ + return m_previousTabAction; +} + +QWidget *TabWidget::lineEditStack() const +{ + return m_lineEdits; +} + +QLineEdit *TabWidget::currentLineEdit() const +{ + return lineEdit(m_lineEdits->currentIndex()); +} + +WebView *TabWidget::currentWebView() const +{ + return webView(currentIndex()); +} + +QLineEdit *TabWidget::lineEdit(int index) const +{ + UrlLineEdit *urlLineEdit = qobject_cast(m_lineEdits->widget(index)); + if (urlLineEdit) + return urlLineEdit->lineEdit(); + return 0; +} + +WebView *TabWidget::webView(int index) const +{ + QWidget *widget = this->widget(index); + if (WebView *webView = qobject_cast(widget)) { + return webView; + } else { + // optimization to delay creating the first webview + if (count() == 1) { + TabWidget *that = const_cast(this); + that->setUpdatesEnabled(false); + that->newTab(); + that->closeTab(0); + that->setUpdatesEnabled(true); + return currentWebView(); + } + } + return 0; +} + +int TabWidget::webViewIndex(WebView *webView) const +{ + int index = indexOf(webView); + return index; +} + +WebView *TabWidget::newTab(bool makeCurrent) +{ + // line edit + UrlLineEdit *urlLineEdit = new UrlLineEdit; + QLineEdit *lineEdit = urlLineEdit->lineEdit(); + if (!m_lineEditCompleter && count() > 0) { + HistoryCompletionModel *completionModel = new HistoryCompletionModel(this); + completionModel->setSourceModel(BrowserApplication::historyManager()->historyFilterModel()); + m_lineEditCompleter = new QCompleter(completionModel, this); + // Should this be in Qt by default? + QAbstractItemView *popup = m_lineEditCompleter->popup(); + QListView *listView = qobject_cast(popup); + if (listView) + listView->setUniformItemSizes(true); + } + lineEdit->setCompleter(m_lineEditCompleter); + connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(lineEditReturnPressed())); + m_lineEdits->addWidget(urlLineEdit); + m_lineEdits->setSizePolicy(lineEdit->sizePolicy()); + + // optimization to delay creating the more expensive WebView, history, etc + if (count() == 0) { + QWidget *emptyWidget = new QWidget; + QPalette p = emptyWidget->palette(); + p.setColor(QPalette::Window, palette().color(QPalette::Base)); + emptyWidget->setPalette(p); + emptyWidget->setAutoFillBackground(true); + disconnect(this, SIGNAL(currentChanged(int)), + this, SLOT(currentChanged(int))); + addTab(emptyWidget, tr("(Untitled)")); + connect(this, SIGNAL(currentChanged(int)), + this, SLOT(currentChanged(int))); + return 0; + } + + // webview + WebView *webView = new WebView; + urlLineEdit->setWebView(webView); + connect(webView, SIGNAL(loadStarted()), + this, SLOT(webViewLoadStarted())); + connect(webView, SIGNAL(loadFinished(bool)), + this, SLOT(webViewIconChanged())); + connect(webView, SIGNAL(iconChanged()), + this, SLOT(webViewIconChanged())); + connect(webView, SIGNAL(titleChanged(QString)), + this, SLOT(webViewTitleChanged(QString))); + connect(webView, SIGNAL(urlChanged(QUrl)), + this, SLOT(webViewUrlChanged(QUrl))); + connect(webView->page(), SIGNAL(windowCloseRequested()), + this, SLOT(windowCloseRequested())); + connect(webView->page(), SIGNAL(geometryChangeRequested(QRect)), + this, SIGNAL(geometryChangeRequested(QRect))); + connect(webView->page(), SIGNAL(printRequested(QWebEngineFrame*)), + this, SIGNAL(printRequested(QWebEngineFrame*))); + connect(webView->page(), SIGNAL(menuBarVisibilityChangeRequested(bool)), + this, SIGNAL(menuBarVisibilityChangeRequested(bool))); + connect(webView->page(), SIGNAL(statusBarVisibilityChangeRequested(bool)), + this, SIGNAL(statusBarVisibilityChangeRequested(bool))); + connect(webView->page(), SIGNAL(toolBarVisibilityChangeRequested(bool)), + this, SIGNAL(toolBarVisibilityChangeRequested(bool))); + addTab(webView, tr("(Untitled)")); + if (makeCurrent) + setCurrentWidget(webView); + + // webview actions + for (int i = 0; i < m_actions.count(); ++i) { + WebActionMapper *mapper = m_actions[i]; + mapper->addChild(webView->page()->action(mapper->webAction())); + } + + if (count() == 1) + currentChanged(currentIndex()); + emit tabsChanged(); + return webView; +} + +void TabWidget::reloadAllTabs() +{ + for (int i = 0; i < count(); ++i) { + QWidget *tabWidget = widget(i); + if (WebView *tab = qobject_cast(tabWidget)) { + tab->reload(); + } + } +} + +void TabWidget::lineEditReturnPressed() +{ + if (QLineEdit *lineEdit = qobject_cast(sender())) { + emit loadPage(lineEdit->text()); + if (m_lineEdits->currentWidget() == lineEdit) + currentWebView()->setFocus(); + } +} + +void TabWidget::windowCloseRequested() +{ + WebPage *webPage = qobject_cast(sender()); + WebView *webView = qobject_cast(webPage->view()); + int index = webViewIndex(webView); + if (index >= 0) { + if (count() == 1) + webView->webPage()->mainWindow()->close(); + else + closeTab(index); + } +} + +void TabWidget::closeOtherTabs(int index) +{ + if (-1 == index) + return; + for (int i = count() - 1; i > index; --i) + closeTab(i); + for (int i = index - 1; i >= 0; --i) + closeTab(i); +} + +// When index is -1 index chooses the current tab +void TabWidget::cloneTab(int index) +{ + if (index < 0) + index = currentIndex(); + if (index < 0 || index >= count()) + return; + WebView *tab = newTab(false); + tab->setUrl(webView(index)->url()); +} + +// When index is -1 index chooses the current tab +void TabWidget::closeTab(int index) +{ + if (index < 0) + index = currentIndex(); + if (index < 0 || index >= count()) + return; + + bool hasFocus = false; + if (WebView *tab = webView(index)) { +#if defined(QWEBENGINEPAGE_ISMODIFIED) + if (tab->isModified()) { + QMessageBox closeConfirmation(tab); + closeConfirmation.setWindowFlags(Qt::Sheet); + closeConfirmation.setWindowTitle(tr("Do you really want to close this page?")); + closeConfirmation.setInformativeText(tr("You have modified this page and when closing it you would lose the modification.\n" + "Do you really want to close this page?\n")); + closeConfirmation.setIcon(QMessageBox::Question); + closeConfirmation.addButton(QMessageBox::Yes); + closeConfirmation.addButton(QMessageBox::No); + closeConfirmation.setEscapeButton(QMessageBox::No); + if (closeConfirmation.exec() == QMessageBox::No) + return; + } +#endif + hasFocus = tab->hasFocus(); + +#if defined(QWEBENGINESETTINGS) + QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); + if (!globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) +#endif + { + m_recentlyClosedTabsAction->setEnabled(true); + m_recentlyClosedTabs.prepend(tab->url()); + if (m_recentlyClosedTabs.size() >= TabWidget::m_recentlyClosedTabsSize) + m_recentlyClosedTabs.removeLast(); + } + } + QWidget *lineEdit = m_lineEdits->widget(index); + m_lineEdits->removeWidget(lineEdit); + lineEdit->deleteLater(); + QWidget *webView = widget(index); + removeTab(index); + webView->deleteLater(); + emit tabsChanged(); + if (hasFocus && count() > 0) + currentWebView()->setFocus(); + if (count() == 0) + emit lastTabClosed(); +} + +void TabWidget::webViewLoadStarted() +{ + WebView *webView = qobject_cast(sender()); + int index = webViewIndex(webView); + if (-1 != index) { + QIcon icon(QLatin1String(":loading.gif")); + setTabIcon(index, icon); + } +} + +void TabWidget::webViewIconChanged() +{ + WebView *webView = qobject_cast(sender()); + int index = webViewIndex(webView); + if (-1 != index) { + QIcon icon = BrowserApplication::instance()->icon(webView->url()); + setTabIcon(index, icon); + } +} + +void TabWidget::webViewTitleChanged(const QString &title) +{ + WebView *webView = qobject_cast(sender()); + int index = webViewIndex(webView); + if (-1 != index) { + setTabText(index, title); + } + if (currentIndex() == index) + emit setCurrentTitle(title); + BrowserApplication::historyManager()->updateHistoryItem(webView->url(), title); +} + +void TabWidget::webViewUrlChanged(const QUrl &url) +{ + WebView *webView = qobject_cast(sender()); + int index = webViewIndex(webView); + if (-1 != index) { + m_tabBar->setTabData(index, url); + } + emit tabsChanged(); +} + +void TabWidget::aboutToShowRecentTabsMenu() +{ + m_recentlyClosedTabsMenu->clear(); + for (int i = 0; i < m_recentlyClosedTabs.count(); ++i) { + QAction *action = new QAction(m_recentlyClosedTabsMenu); + action->setData(m_recentlyClosedTabs.at(i)); + QIcon icon = BrowserApplication::instance()->icon(m_recentlyClosedTabs.at(i)); + action->setIcon(icon); + action->setText(m_recentlyClosedTabs.at(i).toString()); + m_recentlyClosedTabsMenu->addAction(action); + } +} + +void TabWidget::aboutToShowRecentTriggeredAction(QAction *action) +{ + QUrl url = action->data().toUrl(); + loadUrlInCurrentTab(url); +} + +void TabWidget::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (!childAt(event->pos()) + // Remove the line below when QTabWidget does not have a one pixel frame + && event->pos().y() < (tabBar()->y() + tabBar()->height())) { + newTab(); + return; + } + QTabWidget::mouseDoubleClickEvent(event); +} + +void TabWidget::contextMenuEvent(QContextMenuEvent *event) +{ + if (!childAt(event->pos())) { + m_tabBar->contextMenuRequested(event->pos()); + return; + } + QTabWidget::contextMenuEvent(event); +} + +void TabWidget::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::MidButton && !childAt(event->pos()) + // Remove the line below when QTabWidget does not have a one pixel frame + && event->pos().y() < (tabBar()->y() + tabBar()->height())) { + QUrl url(QApplication::clipboard()->text(QClipboard::Selection)); + if (!url.isEmpty() && url.isValid() && !url.scheme().isEmpty()) { + WebView *webView = newTab(); + webView->setUrl(url); + } + } +} + +void TabWidget::loadUrlInCurrentTab(const QUrl &url) +{ + WebView *webView = currentWebView(); + if (webView) { + webView->loadUrl(url); + webView->setFocus(); + } +} + +void TabWidget::nextTab() +{ + int next = currentIndex() + 1; + if (next == count()) + next = 0; + setCurrentIndex(next); +} + +void TabWidget::previousTab() +{ + int next = currentIndex() - 1; + if (next < 0) + next = count() - 1; + setCurrentIndex(next); +} + +static const qint32 TabWidgetMagic = 0xaa; + +QByteArray TabWidget::saveState() const +{ + int version = 1; + QByteArray data; + QDataStream stream(&data, QIODevice::WriteOnly); + + stream << qint32(TabWidgetMagic); + stream << qint32(version); + + QStringList tabs; + for (int i = 0; i < count(); ++i) { + if (WebView *tab = qobject_cast(widget(i))) { + tabs.append(tab->url().toString()); + } else { + tabs.append(QString::null); + } + } + stream << tabs; + stream << currentIndex(); + return data; +} + +bool TabWidget::restoreState(const QByteArray &state) +{ + int version = 1; + QByteArray sd = state; + QDataStream stream(&sd, QIODevice::ReadOnly); + if (stream.atEnd()) + return false; + + qint32 marker; + qint32 v; + stream >> marker; + stream >> v; + if (marker != TabWidgetMagic || v != version) + return false; + + QStringList openTabs; + stream >> openTabs; + + for (int i = 0; i < openTabs.count(); ++i) { + if (i != 0) + newTab(); + loadPage(openTabs.at(i)); + } + + int currentTab; + stream >> currentTab; + setCurrentIndex(currentTab); + + return true; +} + +WebActionMapper::WebActionMapper(QAction *root, QWebEnginePage::WebAction webAction, QObject *parent) + : QObject(parent) + , m_currentParent(0) + , m_root(root) + , m_webAction(webAction) +{ + if (!m_root) + return; + connect(m_root, SIGNAL(triggered()), this, SLOT(rootTriggered())); + connect(root, SIGNAL(destroyed(QObject*)), this, SLOT(rootDestroyed())); + root->setEnabled(false); +} + +void WebActionMapper::rootDestroyed() +{ + m_root = 0; +} + +void WebActionMapper::currentDestroyed() +{ + updateCurrent(0); +} + +void WebActionMapper::addChild(QAction *action) +{ + if (!action) + return; + connect(action, SIGNAL(changed()), this, SLOT(childChanged())); +} + +QWebEnginePage::WebAction WebActionMapper::webAction() const +{ + return m_webAction; +} + +void WebActionMapper::rootTriggered() +{ + if (m_currentParent) { + QAction *gotoAction = m_currentParent->action(m_webAction); + gotoAction->trigger(); + } +} + +void WebActionMapper::childChanged() +{ + if (QAction *source = qobject_cast(sender())) { + if (m_root + && m_currentParent + && source->parent() == m_currentParent) { + m_root->setChecked(source->isChecked()); + m_root->setEnabled(source->isEnabled()); + } + } +} + +void WebActionMapper::updateCurrent(QWebEnginePage *currentParent) +{ + if (m_currentParent) + disconnect(m_currentParent, SIGNAL(destroyed(QObject*)), + this, SLOT(currentDestroyed())); + + m_currentParent = currentParent; + if (!m_root) + return; + if (!m_currentParent) { + m_root->setEnabled(false); + m_root->setChecked(false); + return; + } + QAction *source = m_currentParent->action(m_webAction); + m_root->setChecked(source->isChecked()); + m_root->setEnabled(source->isEnabled()); + connect(m_currentParent, SIGNAL(destroyed(QObject*)), + this, SLOT(currentDestroyed())); +} diff --git a/examples/webenginewidgets/browser/tabwidget.h b/examples/webenginewidgets/browser/tabwidget.h new file mode 100644 index 000000000..e5e1cb606 --- /dev/null +++ b/examples/webenginewidgets/browser/tabwidget.h @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TABWIDGET_H +#define TABWIDGET_H + +#include + +#include +/* + Tab bar with a few more features such as a context menu and shortcuts + */ +class TabBar : public QTabBar +{ + Q_OBJECT + +signals: + void newTab(); + void cloneTab(int index); + void closeTab(int index); + void closeOtherTabs(int index); + void reloadTab(int index); + void reloadAllTabs(); + void tabMoveRequested(int fromIndex, int toIndex); + +public: + TabBar(QWidget *parent = 0); + +protected: + void mousePressEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event); + +private slots: + void selectTabAction(); + void cloneTab(); + void closeTab(); + void closeOtherTabs(); + void reloadTab(); + void contextMenuRequested(const QPoint &position); + +private: + QList m_tabShortcuts; + friend class TabWidget; + + QPoint m_dragStartPos; + int m_dragCurrentIndex; +}; + +#include + +QT_BEGIN_NAMESPACE +class QAction; +QT_END_NAMESPACE +class WebView; +/*! + A proxy object that connects a single browser action + to one child webpage action at a time. + + Example usage: used to keep the main window stop action in sync with + the current tabs webview's stop action. + */ +class WebActionMapper : public QObject +{ + Q_OBJECT + +public: + WebActionMapper(QAction *root, QWebEnginePage::WebAction webAction, QObject *parent); + QWebEnginePage::WebAction webAction() const; + void addChild(QAction *action); + void updateCurrent(QWebEnginePage *currentParent); + +private slots: + void rootTriggered(); + void childChanged(); + void rootDestroyed(); + void currentDestroyed(); + +private: + QWebEnginePage *m_currentParent; + QAction *m_root; + QWebEnginePage::WebAction m_webAction; +}; + +#include +#include +QT_BEGIN_NAMESPACE +class QCompleter; +class QLineEdit; +class QMenu; +class QStackedWidget; +QT_END_NAMESPACE +/*! + TabWidget that contains WebViews and a stack widget of associated line edits. + + Connects up the current tab's signals to this class's signal and uses WebActionMapper + to proxy the actions. + */ +class TabWidget : public QTabWidget +{ + Q_OBJECT + +signals: + // tab widget signals + void loadPage(const QString &url); + void tabsChanged(); + void lastTabClosed(); + + // current tab signals + void setCurrentTitle(const QString &url); + void showStatusBarMessage(const QString &message); + void linkHovered(const QString &link); + void loadProgress(int progress); + void geometryChangeRequested(const QRect &geometry); + void menuBarVisibilityChangeRequested(bool visible); + void statusBarVisibilityChangeRequested(bool visible); + void toolBarVisibilityChangeRequested(bool visible); + void printRequested(QWebEngineFrame *frame); + +public: + TabWidget(QWidget *parent = 0); + void clear(); + void addWebAction(QAction *action, QWebEnginePage::WebAction webAction); + + QAction *newTabAction() const; + QAction *closeTabAction() const; + QAction *recentlyClosedTabsAction() const; + QAction *nextTabAction() const; + QAction *previousTabAction() const; + + QWidget *lineEditStack() const; + QLineEdit *currentLineEdit() const; + WebView *currentWebView() const; + WebView *webView(int index) const; + QLineEdit *lineEdit(int index) const; + int webViewIndex(WebView *webView) const; + + QByteArray saveState() const; + bool restoreState(const QByteArray &state); + +protected: + void mouseDoubleClickEvent(QMouseEvent *event); + void contextMenuEvent(QContextMenuEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +public slots: + void loadUrlInCurrentTab(const QUrl &url); + WebView *newTab(bool makeCurrent = true); + void cloneTab(int index = -1); + void closeTab(int index = -1); + void closeOtherTabs(int index); + void reloadTab(int index = -1); + void reloadAllTabs(); + void nextTab(); + void previousTab(); + +private slots: + void currentChanged(int index); + void aboutToShowRecentTabsMenu(); + void aboutToShowRecentTriggeredAction(QAction *action); + void webViewLoadStarted(); + void webViewIconChanged(); + void webViewTitleChanged(const QString &title); + void webViewUrlChanged(const QUrl &url); + void lineEditReturnPressed(); + void windowCloseRequested(); + void moveTab(int fromIndex, int toIndex); + +private: + QAction *m_recentlyClosedTabsAction; + QAction *m_newTabAction; + QAction *m_closeTabAction; + QAction *m_nextTabAction; + QAction *m_previousTabAction; + + QMenu *m_recentlyClosedTabsMenu; + static const int m_recentlyClosedTabsSize = 10; + QList m_recentlyClosedTabs; + QList m_actions; + + QCompleter *m_lineEditCompleter; + QStackedWidget *m_lineEdits; + TabBar *m_tabBar; +}; + +#endif // TABWIDGET_H diff --git a/examples/webenginewidgets/browser/toolbarsearch.cpp b/examples/webenginewidgets/browser/toolbarsearch.cpp new file mode 100644 index 000000000..d6d1ec1da --- /dev/null +++ b/examples/webenginewidgets/browser/toolbarsearch.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "toolbarsearch.h" +#include "autosaver.h" + +#include +#include +#include + +#include +#include +#include + +#include + +/* + ToolbarSearch is a very basic search widget that also contains a small history. + Searches are turned into urls that use Google to perform search + */ +ToolbarSearch::ToolbarSearch(QWidget *parent) + : SearchLineEdit(parent) + , m_autosaver(new AutoSaver(this)) + , m_maxSavedSearches(10) + , m_stringListModel(new QStringListModel(this)) +{ + QMenu *m = menu(); + connect(m, SIGNAL(aboutToShow()), this, SLOT(aboutToShowMenu())); + connect(m, SIGNAL(triggered(QAction*)), this, SLOT(triggeredMenuAction(QAction*))); + + QCompleter *completer = new QCompleter(m_stringListModel, this); + completer->setCompletionMode(QCompleter::InlineCompletion); + lineEdit()->setCompleter(completer); + + connect(lineEdit(), SIGNAL(returnPressed()), SLOT(searchNow())); + setInactiveText(tr("Google")); + load(); +} + +ToolbarSearch::~ToolbarSearch() +{ + m_autosaver->saveIfNeccessary(); +} + +void ToolbarSearch::save() +{ + QSettings settings; + settings.beginGroup(QLatin1String("toolbarsearch")); + settings.setValue(QLatin1String("recentSearches"), m_stringListModel->stringList()); + settings.setValue(QLatin1String("maximumSaved"), m_maxSavedSearches); + settings.endGroup(); +} + +void ToolbarSearch::load() +{ + QSettings settings; + settings.beginGroup(QLatin1String("toolbarsearch")); + QStringList list = settings.value(QLatin1String("recentSearches")).toStringList(); + m_maxSavedSearches = settings.value(QLatin1String("maximumSaved"), m_maxSavedSearches).toInt(); + m_stringListModel->setStringList(list); + settings.endGroup(); +} + +void ToolbarSearch::searchNow() +{ + QString searchText = lineEdit()->text(); + QStringList newList = m_stringListModel->stringList(); + if (newList.contains(searchText)) + newList.removeAt(newList.indexOf(searchText)); + newList.prepend(searchText); + if (newList.size() >= m_maxSavedSearches) + newList.removeLast(); + +#if defined(QWEBENGINESETTINGS) + QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); + if (!globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) +#endif + { + m_stringListModel->setStringList(newList); + m_autosaver->changeOccurred(); + } + + QUrl url(QLatin1String("http://www.google.com/search")); + QUrlQuery urlQuery; + urlQuery.addQueryItem(QLatin1String("q"), searchText); + urlQuery.addQueryItem(QLatin1String("ie"), QLatin1String("UTF-8")); + urlQuery.addQueryItem(QLatin1String("oe"), QLatin1String("UTF-8")); + urlQuery.addQueryItem(QLatin1String("client"), QLatin1String("qtdemobrowser")); + url.setQuery(urlQuery); + emit search(url); +} + +void ToolbarSearch::aboutToShowMenu() +{ + lineEdit()->selectAll(); + QMenu *m = menu(); + m->clear(); + QStringList list = m_stringListModel->stringList(); + if (list.isEmpty()) { + m->addAction(tr("No Recent Searches")); + return; + } + + QAction *recent = m->addAction(tr("Recent Searches")); + recent->setEnabled(false); + for (int i = 0; i < list.count(); ++i) { + QString text = list.at(i); + m->addAction(text)->setData(text); + } + m->addSeparator(); + m->addAction(tr("Clear Recent Searches"), this, SLOT(clear())); +} + +void ToolbarSearch::triggeredMenuAction(QAction *action) +{ + QVariant v = action->data(); + if (v.canConvert()) { + QString text = v.toString(); + lineEdit()->setText(text); + searchNow(); + } +} + +void ToolbarSearch::clear() +{ + m_stringListModel->setStringList(QStringList()); + m_autosaver->changeOccurred();; +} diff --git a/examples/webenginewidgets/browser/toolbarsearch.h b/examples/webenginewidgets/browser/toolbarsearch.h new file mode 100644 index 000000000..1189785db --- /dev/null +++ b/examples/webenginewidgets/browser/toolbarsearch.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TOOLBARSEARCH_H +#define TOOLBARSEARCH_H + +#include "searchlineedit.h" + +QT_BEGIN_NAMESPACE +class QUrl; +class QAction; +class QStringListModel; +QT_END_NAMESPACE + +class AutoSaver; + +class ToolbarSearch : public SearchLineEdit +{ + Q_OBJECT + +signals: + void search(const QUrl &url); + +public: + ToolbarSearch(QWidget *parent = 0); + ~ToolbarSearch(); + +public slots: + void clear(); + void searchNow(); + +private slots: + void save(); + void aboutToShowMenu(); + void triggeredMenuAction(QAction *action); + +private: + void load(); + + AutoSaver *m_autosaver; + int m_maxSavedSearches; + QStringListModel *m_stringListModel; +}; + +#endif // TOOLBARSEARCH_H diff --git a/examples/webenginewidgets/browser/urllineedit.cpp b/examples/webenginewidgets/browser/urllineedit.cpp new file mode 100644 index 000000000..47828d95f --- /dev/null +++ b/examples/webenginewidgets/browser/urllineedit.cpp @@ -0,0 +1,342 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "urllineedit.h" + +#include "browserapplication.h" +#include "searchlineedit.h" +#include "webview.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +ExLineEdit::ExLineEdit(QWidget *parent) + : QWidget(parent) + , m_leftWidget(0) + , m_lineEdit(new QLineEdit(this)) + , m_clearButton(0) +{ + setFocusPolicy(m_lineEdit->focusPolicy()); + setAttribute(Qt::WA_InputMethodEnabled); + setSizePolicy(m_lineEdit->sizePolicy()); + setBackgroundRole(m_lineEdit->backgroundRole()); + setMouseTracking(true); + setAcceptDrops(true); + setAttribute(Qt::WA_MacShowFocusRect, true); + QPalette p = m_lineEdit->palette(); + setPalette(p); + + // line edit + m_lineEdit->setFrame(false); + m_lineEdit->setFocusProxy(this); + m_lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false); + QPalette clearPalette = m_lineEdit->palette(); + clearPalette.setBrush(QPalette::Base, QBrush(Qt::transparent)); + m_lineEdit->setPalette(clearPalette); + + // clearButton + m_clearButton = new ClearButton(this); + connect(m_clearButton, SIGNAL(clicked()), + m_lineEdit, SLOT(clear())); + connect(m_lineEdit, SIGNAL(textChanged(QString)), + m_clearButton, SLOT(textChanged(QString))); +} + +void ExLineEdit::setLeftWidget(QWidget *widget) +{ + m_leftWidget = widget; +} + +QWidget *ExLineEdit::leftWidget() const +{ + return m_leftWidget; +} + +void ExLineEdit::resizeEvent(QResizeEvent *event) +{ + Q_ASSERT(m_leftWidget); + updateGeometries(); + QWidget::resizeEvent(event); +} + +void ExLineEdit::updateGeometries() +{ + QStyleOptionFrameV2 panel; + initStyleOption(&panel); + QRect rect = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this); + + int height = rect.height(); + int width = rect.width(); + + int m_leftWidgetHeight = m_leftWidget->height(); + m_leftWidget->setGeometry(rect.x() + 2, rect.y() + (height - m_leftWidgetHeight)/2, + m_leftWidget->width(), m_leftWidget->height()); + + int clearButtonWidth = this->height(); + m_lineEdit->setGeometry(m_leftWidget->x() + m_leftWidget->width(), 0, + width - clearButtonWidth - m_leftWidget->width(), this->height()); + + m_clearButton->setGeometry(this->width() - clearButtonWidth, 0, + clearButtonWidth, this->height()); +} + +void ExLineEdit::initStyleOption(QStyleOptionFrameV2 *option) const +{ + option->initFrom(this); + option->rect = contentsRect(); + option->lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, option, this); + option->midLineWidth = 0; + option->state |= QStyle::State_Sunken; + if (m_lineEdit->isReadOnly()) + option->state |= QStyle::State_ReadOnly; +#ifdef QT_KEYPAD_NAVIGATION + if (hasEditFocus()) + option->state |= QStyle::State_HasEditFocus; +#endif + option->features = QStyleOptionFrameV2::None; +} + +QSize ExLineEdit::sizeHint() const +{ + m_lineEdit->setFrame(true); + QSize size = m_lineEdit->sizeHint(); + m_lineEdit->setFrame(false); + return size; +} + +void ExLineEdit::focusInEvent(QFocusEvent *event) +{ + m_lineEdit->event(event); + QWidget::focusInEvent(event); +} + +void ExLineEdit::focusOutEvent(QFocusEvent *event) +{ + m_lineEdit->event(event); + + if (m_lineEdit->completer()) { + connect(m_lineEdit->completer(), SIGNAL(activated(QString)), + m_lineEdit, SLOT(setText(QString))); + connect(m_lineEdit->completer(), SIGNAL(highlighted(QString)), + m_lineEdit, SLOT(_q_completionHighlighted(QString))); + } + QWidget::focusOutEvent(event); +} + +void ExLineEdit::keyPressEvent(QKeyEvent *event) +{ + m_lineEdit->event(event); +} + +bool ExLineEdit::event(QEvent *event) +{ + if (event->type() == QEvent::ShortcutOverride) + return m_lineEdit->event(event); + return QWidget::event(event); +} + +void ExLineEdit::paintEvent(QPaintEvent *) +{ + QPainter p(this); + QStyleOptionFrameV2 panel; + initStyleOption(&panel); + style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, &p, this); +} + +QVariant ExLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const +{ + return m_lineEdit->inputMethodQuery(property); +} + +void ExLineEdit::inputMethodEvent(QInputMethodEvent *e) +{ + m_lineEdit->event(e); +} + + +class UrlIconLabel : public QLabel +{ + +public: + UrlIconLabel(QWidget *parent); + + WebView *m_webView; + +protected: + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + +private: + QPoint m_dragStartPos; + +}; + +UrlIconLabel::UrlIconLabel(QWidget *parent) + : QLabel(parent) + , m_webView(0) +{ + setMinimumWidth(16); + setMinimumHeight(16); +} + +void UrlIconLabel::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) + m_dragStartPos = event->pos(); + QLabel::mousePressEvent(event); +} + +void UrlIconLabel::mouseMoveEvent(QMouseEvent *event) +{ + if (event->buttons() == Qt::LeftButton + && (event->pos() - m_dragStartPos).manhattanLength() > QApplication::startDragDistance() + && m_webView) { + QDrag *drag = new QDrag(this); + QMimeData *mimeData = new QMimeData; + mimeData->setText(QString::fromUtf8(m_webView->url().toEncoded())); + QList urls; + urls.append(m_webView->url()); + mimeData->setUrls(urls); + drag->setMimeData(mimeData); + drag->exec(); + } +} + +UrlLineEdit::UrlLineEdit(QWidget *parent) + : ExLineEdit(parent) + , m_webView(0) + , m_iconLabel(0) +{ + // icon + m_iconLabel = new UrlIconLabel(this); + m_iconLabel->resize(16, 16); + setLeftWidget(m_iconLabel); + m_defaultBaseColor = palette().color(QPalette::Base); + + webViewIconChanged(); +} + +void UrlLineEdit::setWebView(WebView *webView) +{ + Q_ASSERT(!m_webView); + m_webView = webView; + m_iconLabel->m_webView = webView; + connect(webView, SIGNAL(urlChanged(QUrl)), + this, SLOT(webViewUrlChanged(QUrl))); + connect(webView, SIGNAL(loadFinished(bool)), + this, SLOT(webViewIconChanged())); + connect(webView, SIGNAL(iconChanged()), + this, SLOT(webViewIconChanged())); + connect(webView, SIGNAL(loadProgress(int)), + this, SLOT(update())); +} + +void UrlLineEdit::webViewUrlChanged(const QUrl &url) +{ + m_lineEdit->setText(QString::fromUtf8(url.toEncoded())); + m_lineEdit->setCursorPosition(0); +} + +void UrlLineEdit::webViewIconChanged() +{ + QUrl url = (m_webView) ? m_webView->url() : QUrl(); + QIcon icon = BrowserApplication::instance()->icon(url); + QPixmap pixmap(icon.pixmap(16, 16)); + m_iconLabel->setPixmap(pixmap); +} + +QLinearGradient UrlLineEdit::generateGradient(const QColor &color) const +{ + QLinearGradient gradient(0, 0, 0, height()); + gradient.setColorAt(0, m_defaultBaseColor); + gradient.setColorAt(0.15, color.lighter(120)); + gradient.setColorAt(0.5, color); + gradient.setColorAt(0.85, color.lighter(120)); + gradient.setColorAt(1, m_defaultBaseColor); + return gradient; +} + +void UrlLineEdit::focusOutEvent(QFocusEvent *event) +{ + if (m_lineEdit->text().isEmpty() && m_webView) + m_lineEdit->setText(QString::fromUtf8(m_webView->url().toEncoded())); + ExLineEdit::focusOutEvent(event); +} + +void UrlLineEdit::paintEvent(QPaintEvent *event) +{ + QPalette p = palette(); + if (m_webView && m_webView->url().scheme() == QLatin1String("https")) { + QColor lightYellow(248, 248, 210); + p.setBrush(QPalette::Base, generateGradient(lightYellow)); + } else { + p.setBrush(QPalette::Base, m_defaultBaseColor); + } + setPalette(p); + ExLineEdit::paintEvent(event); + + QPainter painter(this); + QStyleOptionFrameV2 panel; + initStyleOption(&panel); + QRect backgroundRect = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this); + if (m_webView && !hasFocus()) { + int progress = m_webView->progress(); + QColor loadingColor = QColor(116, 192, 250); + painter.setBrush(generateGradient(loadingColor)); + painter.setPen(Qt::transparent); + int mid = backgroundRect.width() / 100 * progress; + QRect progressRect(backgroundRect.x(), backgroundRect.y(), mid, backgroundRect.height()); + painter.drawRect(progressRect); + } +} diff --git a/examples/webenginewidgets/browser/urllineedit.h b/examples/webenginewidgets/browser/urllineedit.h new file mode 100644 index 000000000..c30f40b57 --- /dev/null +++ b/examples/webenginewidgets/browser/urllineedit.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef URLLINEEDIT_H +#define URLLINEEDIT_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QLineEdit; +QT_END_NAMESPACE + +class ClearButton; +class ExLineEdit : public QWidget +{ + Q_OBJECT + +public: + ExLineEdit(QWidget *parent = 0); + + inline QLineEdit *lineEdit() const { return m_lineEdit; } + + void setLeftWidget(QWidget *widget); + QWidget *leftWidget() const; + + QSize sizeHint() const; + + QVariant inputMethodQuery(Qt::InputMethodQuery property) const; +protected: + void focusInEvent(QFocusEvent *event); + void focusOutEvent(QFocusEvent *event); + void keyPressEvent(QKeyEvent *event); + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *event); + void inputMethodEvent(QInputMethodEvent *e); + bool event(QEvent *event); + +protected: + void updateGeometries(); + void initStyleOption(QStyleOptionFrameV2 *option) const; + + QWidget *m_leftWidget; + QLineEdit *m_lineEdit; + ClearButton *m_clearButton; +}; + +class UrlIconLabel; +class WebView; +class UrlLineEdit : public ExLineEdit +{ + Q_OBJECT + +public: + UrlLineEdit(QWidget *parent = 0); + void setWebView(WebView *webView); + +protected: + void paintEvent(QPaintEvent *event); + void focusOutEvent(QFocusEvent *event); + +private slots: + void webViewUrlChanged(const QUrl &url); + void webViewIconChanged(); + +private: + QLinearGradient generateGradient(const QColor &color) const; + WebView *m_webView; + UrlIconLabel *m_iconLabel; + QColor m_defaultBaseColor; + +}; + + +#endif // URLLINEEDIT_H diff --git a/examples/webenginewidgets/browser/webview.cpp b/examples/webenginewidgets/browser/webview.cpp new file mode 100644 index 000000000..193cb4797 --- /dev/null +++ b/examples/webenginewidgets/browser/webview.cpp @@ -0,0 +1,431 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "browserapplication.h" +#include "browsermainwindow.h" +#include "cookiejar.h" +#include "downloadmanager.h" +#include "networkaccessmanager.h" +#include "ui_passworddialog.h" +#include "ui_proxy.h" +#include "tabwidget.h" +#include "webview.h" + +#include +#include +#include +#include +#include + +#include + +#ifndef QT_NO_UITOOLS +#include +#endif //QT_NO_UITOOLS + +#include +#include + +WebPage::WebPage(QObject *parent) + : QWebEnginePage(parent) + , m_keyboardModifiers(Qt::NoModifier) + , m_pressedButtons(Qt::NoButton) + , m_openInNewTab(false) +{ +#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) + setNetworkAccessManager(BrowserApplication::networkAccessManager()); +#endif + connect(this, SIGNAL(unsupportedContent(QNetworkReply*)), + this, SLOT(handleUnsupportedContent(QNetworkReply*))); + connect(this, SIGNAL(authenticationRequired(const QUrl &, QAuthenticator*)), + SLOT(authenticationRequired(const QUrl &, QAuthenticator*))); + connect(this, SIGNAL(proxyAuthenticationRequired(const QUrl &, QAuthenticator *, const QString &)), + SLOT(proxyAuthenticationRequired(const QUrl &, QAuthenticator *, const QString &))); +} + +BrowserMainWindow *WebPage::mainWindow() +{ + QObject *w = this->parent(); + while (w) { + if (BrowserMainWindow *mw = qobject_cast(w)) + return mw; + w = w->parent(); + } + return BrowserApplication::instance()->mainWindow(); +} + +bool WebPage::acceptNavigationRequest(QWebEngineFrame *frame, const QNetworkRequest &request, NavigationType type) +{ +#if defined(QWEBENGINEPAGE_ACCEPTNAVIGATIONREQUEST) + // ctrl open in new tab + // ctrl-shift open in new tab and select + // ctrl-alt open in new window + if (type == QWebEnginePage::NavigationTypeLinkClicked + && (m_keyboardModifiers & Qt::ControlModifier + || m_pressedButtons == Qt::MidButton)) { + bool newWindow = (m_keyboardModifiers & Qt::AltModifier); + WebView *webView; + if (newWindow) { + BrowserApplication::instance()->newMainWindow(); + BrowserMainWindow *newMainWindow = BrowserApplication::instance()->mainWindow(); + webView = newMainWindow->currentTab(); + newMainWindow->raise(); + newMainWindow->activateWindow(); + webView->setFocus(); + } else { + bool selectNewTab = (m_keyboardModifiers & Qt::ShiftModifier); + webView = mainWindow()->tabWidget()->newTab(selectNewTab); + } + webView->load(request); + m_keyboardModifiers = Qt::NoModifier; + m_pressedButtons = Qt::NoButton; + return false; + } + m_loadingUrl = request.url(); + emit loadingUrl(m_loadingUrl); +#endif + return QWebEnginePage::acceptNavigationRequest(frame, request, type); +} + +class PopupWindow : public QWidget { + Q_OBJECT +public: + PopupWindow() + : m_addressBar(new QLineEdit(this)) + , m_view(new WebView(this)) + { + QVBoxLayout *layout = new QVBoxLayout; + layout->setMargin(0); + setLayout(layout); + layout->addWidget(m_addressBar); + layout->addWidget(m_view); + m_view->setFocus(); + + connect(m_view, &WebView::titleChanged, this, &QWidget::setWindowTitle); + connect(m_view, &WebView::urlChanged, this, &PopupWindow::setUrl); + connect(page(), &WebPage::geometryChangeRequested, this, &PopupWindow::adjustGeometry); + connect(page(), &WebPage::windowCloseRequested, this, &QWidget::close); + } + + QWebEnginePage* page() const { return m_view->page(); } + +private Q_SLOTS: + void setUrl(const QUrl &url) + { + m_addressBar->setText(url.toString()); + } + + void adjustGeometry(const QRect &newGeometry) + { + const int x1 = frameGeometry().left() - geometry().left(); + const int y1 = frameGeometry().top() - geometry().top(); + const int x2 = frameGeometry().right() - geometry().right(); + const int y2 = frameGeometry().bottom() - geometry().bottom(); + + setGeometry(newGeometry.adjusted(x1, y1 - m_addressBar->height(), x2, y2)); + } + +private: + QLineEdit *m_addressBar; + WebView *m_view; + +}; + +#include "webview.moc" + +QWebEnginePage *WebPage::createWindow(QWebEnginePage::WebWindowType type) +{ + if (m_keyboardModifiers & Qt::ControlModifier || m_pressedButtons == Qt::MidButton) + m_openInNewTab = true; + if (m_openInNewTab) { + m_openInNewTab = false; + return mainWindow()->tabWidget()->newTab()->page(); + } + if (type == QWebEnginePage::WebBrowserWindow) { + BrowserApplication::instance()->newMainWindow(); + BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow(); + return mainWindow->currentTab()->page(); + } else { + PopupWindow *popup = new PopupWindow; + popup->setAttribute(Qt::WA_DeleteOnClose); + popup->show(); + return popup->page(); + } +} + +#if !defined(QT_NO_UITOOLS) +QObject *WebPage::createPlugin(const QString &classId, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) +{ + Q_UNUSED(url); + Q_UNUSED(paramNames); + Q_UNUSED(paramValues); + QUiLoader loader; + return loader.createWidget(classId, view()); +} +#endif // !defined(QT_NO_UITOOLS) + +void WebPage::handleUnsupportedContent(QNetworkReply *reply) +{ +#if defined(QWEBENGINEPAGE_UNSUPPORTEDCONTENT) + QString errorString = reply->errorString(); + + if (m_loadingUrl != reply->url()) { + // sub resource of this page + qWarning() << "Resource" << reply->url().toEncoded() << "has unknown Content-Type, will be ignored."; + reply->deleteLater(); + return; + } + + if (reply->error() == QNetworkReply::NoError && !reply->header(QNetworkRequest::ContentTypeHeader).isValid()) { + errorString = "Unknown Content-Type"; + } + + QFile file(QLatin1String(":/notfound.html")); + bool isOpened = file.open(QIODevice::ReadOnly); + Q_ASSERT(isOpened); + Q_UNUSED(isOpened) + + QString title = tr("Error loading page: %1").arg(reply->url().toString()); + QString html = QString(QLatin1String(file.readAll())) + .arg(title) + .arg(errorString) + .arg(reply->url().toString()); + + QBuffer imageBuffer; + imageBuffer.open(QBuffer::ReadWrite); + QIcon icon = view()->style()->standardIcon(QStyle::SP_MessageBoxWarning, 0, view()); + QPixmap pixmap = icon.pixmap(QSize(32,32)); + if (pixmap.save(&imageBuffer, "PNG")) { + html.replace(QLatin1String("IMAGE_BINARY_DATA_HERE"), + QString(QLatin1String(imageBuffer.buffer().toBase64()))); + } + + QList frames; + frames.append(mainFrame()); + while (!frames.isEmpty()) { + QWebEngineFrame *frame = frames.takeFirst(); + if (frame->url() == reply->url()) { + frame->setHtml(html, reply->url()); + return; + } + QList children = frame->childFrames(); + foreach (QWebEngineFrame *frame, children) + frames.append(frame); + } + if (m_loadingUrl == reply->url()) { + mainFrame()->setHtml(html, reply->url()); + } +#endif +} + +void WebPage::authenticationRequired(const QUrl &requestUrl, QAuthenticator *auth) +{ + BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow(); + + QDialog dialog(mainWindow); + dialog.setWindowFlags(Qt::Sheet); + + Ui::PasswordDialog passwordDialog; + passwordDialog.setupUi(&dialog); + + passwordDialog.iconLabel->setText(QString()); + passwordDialog.iconLabel->setPixmap(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, 0, mainWindow).pixmap(32, 32)); + + QString introMessage = tr("Enter username and password for \"%1\" at %2"); + introMessage = introMessage.arg(auth->realm()).arg(requestUrl.toString().toHtmlEscaped()); + passwordDialog.introLabel->setText(introMessage); + passwordDialog.introLabel->setWordWrap(true); + + if (dialog.exec() == QDialog::Accepted) { + auth->setUser(passwordDialog.userNameLineEdit->text()); + auth->setPassword(passwordDialog.passwordLineEdit->text()); + } +} + +void WebPage::proxyAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth, const QString &proxyHost) +{ + BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow(); + + QDialog dialog(mainWindow); + dialog.setWindowFlags(Qt::Sheet); + + Ui::ProxyDialog proxyDialog; + proxyDialog.setupUi(&dialog); + + proxyDialog.iconLabel->setText(QString()); + proxyDialog.iconLabel->setPixmap(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, 0, mainWindow).pixmap(32, 32)); + + QString introMessage = tr("Connect to proxy \"%1\" using:"); + introMessage = introMessage.arg(proxyHost.toHtmlEscaped()); + proxyDialog.introLabel->setText(introMessage); + proxyDialog.introLabel->setWordWrap(true); + + if (dialog.exec() == QDialog::Accepted) { + auth->setUser(proxyDialog.userNameLineEdit->text()); + auth->setPassword(proxyDialog.passwordLineEdit->text()); + } +} + +WebView::WebView(QWidget* parent) + : QWebEngineView(parent) + , m_progress(0) + , m_page(new WebPage(this)) +{ + setPage(m_page); + connect(page(), SIGNAL(statusBarMessage(QString)), + SLOT(setStatusBarText(QString))); + connect(this, SIGNAL(loadProgress(int)), + this, SLOT(setProgress(int))); + connect(this, SIGNAL(loadFinished(bool)), + this, SLOT(loadFinished())); + connect(page(), SIGNAL(loadingUrl(QUrl)), + this, SIGNAL(urlChanged(QUrl))); + connect(page(), SIGNAL(downloadRequested(QNetworkRequest)), + this, SLOT(downloadRequested(QNetworkRequest))); +#if defined(QWEBENGINEPAGE_UNSUPPORTEDCONTENT) + page()->setForwardUnsupportedContent(true); +#endif + +} + +void WebView::contextMenuEvent(QContextMenuEvent *event) +{ +#if defined(QWEBENGINEPAGE_HITTESTCONTENT) + QWebEngineHitTestResult r = page()->hitTestContent(event->pos()); + if (!r.linkUrl().isEmpty()) { + QMenu menu(this); + menu.addAction(pageAction(QWebEnginePage::OpenLinkInNewWindow)); + menu.addAction(tr("Open in New Tab"), this, SLOT(openLinkInNewTab())); + menu.addSeparator(); + menu.addAction(pageAction(QWebEnginePage::DownloadLinkToDisk)); + // Add link to bookmarks... + menu.addSeparator(); + menu.addAction(pageAction(QWebEnginePage::CopyLinkToClipboard)); + if (page()->settings()->testAttribute(QWebEngineSettings::DeveloperExtrasEnabled)) + menu.addAction(pageAction(QWebEnginePage::InspectElement)); + menu.exec(mapToGlobal(event->pos())); + return; + } +#endif + QWebEngineView::contextMenuEvent(event); +} + +void WebView::wheelEvent(QWheelEvent *event) +{ +#if defined(QWEBENGINEPAGE_SETTEXTSIZEMULTIPLIER) + if (QApplication::keyboardModifiers() & Qt::ControlModifier) { + int numDegrees = event->delta() / 8; + int numSteps = numDegrees / 15; + setTextSizeMultiplier(textSizeMultiplier() + numSteps * 0.1); + event->accept(); + return; + } +#endif + QWebEngineView::wheelEvent(event); +} + +void WebView::openLinkInNewTab() +{ + m_page->m_openInNewTab = true; + pageAction(QWebEnginePage::OpenLinkInNewWindow)->trigger(); +} + +void WebView::setProgress(int progress) +{ + m_progress = progress; +} + +void WebView::loadFinished() +{ + if (100 != m_progress) { + qWarning() << "Received finished signal while progress is still:" << progress() + << "Url:" << url(); + } + m_progress = 0; +} + +void WebView::loadUrl(const QUrl &url) +{ + m_initialUrl = url; + load(url); +} + +QString WebView::lastStatusBarText() const +{ + return m_statusBarText; +} + +QUrl WebView::url() const +{ + QUrl url = QWebEngineView::url(); + if (!url.isEmpty()) + return url; + + return m_initialUrl; +} + +void WebView::mousePressEvent(QMouseEvent *event) +{ + m_page->m_pressedButtons = event->buttons(); + m_page->m_keyboardModifiers = event->modifiers(); + QWebEngineView::mousePressEvent(event); +} + +void WebView::mouseReleaseEvent(QMouseEvent *event) +{ + QWebEngineView::mouseReleaseEvent(event); + if (!event->isAccepted() && (m_page->m_pressedButtons & Qt::MidButton)) { + QUrl url(QApplication::clipboard()->text(QClipboard::Selection)); + if (!url.isEmpty() && url.isValid() && !url.scheme().isEmpty()) { + setUrl(url); + } + } +} + +void WebView::setStatusBarText(const QString &string) +{ + m_statusBarText = string; +} + +void WebView::downloadRequested(const QNetworkRequest &request) +{ + BrowserApplication::downloadManager()->download(request); +} diff --git a/examples/webenginewidgets/browser/webview.h b/examples/webenginewidgets/browser/webview.h new file mode 100644 index 000000000..2d3ec50cc --- /dev/null +++ b/examples/webenginewidgets/browser/webview.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WEBVIEW_H +#define WEBVIEW_H + +#include + +QT_BEGIN_NAMESPACE +class QAuthenticator; +class QMouseEvent; +class QNetworkProxy; +class QNetworkReply; +class QSslError; +QT_END_NAMESPACE + +class BrowserMainWindow; +class WebPage : public QWebEnginePage { + Q_OBJECT + +signals: + void loadingUrl(const QUrl &url); + +public: + WebPage(QObject *parent = 0); + BrowserMainWindow *mainWindow(); + +protected: + bool acceptNavigationRequest(QWebEngineFrame *frame, const QNetworkRequest &request, NavigationType type); + QWebEnginePage *createWindow(QWebEnginePage::WebWindowType type); +#if !defined(QT_NO_UITOOLS) + QObject *createPlugin(const QString &classId, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues); +#endif + +private slots: + void handleUnsupportedContent(QNetworkReply *reply); + void authenticationRequired(const QUrl &requestUrl, QAuthenticator *auth); + void proxyAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth, const QString &proxyHost); + +private: + friend class WebView; + + // set the webview mousepressedevent + Qt::KeyboardModifiers m_keyboardModifiers; + Qt::MouseButtons m_pressedButtons; + bool m_openInNewTab; + QUrl m_loadingUrl; +}; + +class WebView : public QWebEngineView { + Q_OBJECT + +public: + WebView(QWidget *parent = 0); + WebPage *webPage() const { return m_page; } + + void loadUrl(const QUrl &url); + QUrl url() const; + + QString lastStatusBarText() const; + inline int progress() const { return m_progress; } + +protected: + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void contextMenuEvent(QContextMenuEvent *event); + void wheelEvent(QWheelEvent *event); + +private slots: + void setProgress(int progress); + void loadFinished(); + void setStatusBarText(const QString &string); + void downloadRequested(const QNetworkRequest &request); + void openLinkInNewTab(); + +private: + QString m_statusBarText; + QUrl m_initialUrl; + int m_progress; + WebPage *m_page; +}; + +#endif diff --git a/examples/webenginewidgets/browser/xbel.cpp b/examples/webenginewidgets/browser/xbel.cpp new file mode 100644 index 000000000..ae84a6a37 --- /dev/null +++ b/examples/webenginewidgets/browser/xbel.cpp @@ -0,0 +1,282 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "xbel.h" + +#include + +BookmarkNode::BookmarkNode(BookmarkNode::Type type, BookmarkNode *parent) : + expanded(false) + , m_parent(parent) + , m_type(type) +{ + if (parent) + parent->add(this); +} + +BookmarkNode::~BookmarkNode() +{ + if (m_parent) + m_parent->remove(this); + qDeleteAll(m_children); + m_parent = 0; + m_type = BookmarkNode::Root; +} + +bool BookmarkNode::operator==(const BookmarkNode &other) +{ + if (url != other.url + || title != other.title + || desc != other.desc + || expanded != other.expanded + || m_type != other.m_type + || m_children.count() != other.m_children.count()) + return false; + + for (int i = 0; i < m_children.count(); ++i) + if (!((*(m_children[i])) == (*(other.m_children[i])))) + return false; + return true; +} + +BookmarkNode::Type BookmarkNode::type() const +{ + return m_type; +} + +void BookmarkNode::setType(Type type) +{ + m_type = type; +} + +QList BookmarkNode::children() const +{ + return m_children; +} + +BookmarkNode *BookmarkNode::parent() const +{ + return m_parent; +} + +void BookmarkNode::add(BookmarkNode *child, int offset) +{ + Q_ASSERT(child->m_type != Root); + if (child->m_parent) + child->m_parent->remove(child); + child->m_parent = this; + if (-1 == offset) + offset = m_children.size(); + m_children.insert(offset, child); +} + +void BookmarkNode::remove(BookmarkNode *child) +{ + child->m_parent = 0; + m_children.removeAll(child); +} + + +XbelReader::XbelReader() +{ +} + +BookmarkNode *XbelReader::read(const QString &fileName) +{ + QFile file(fileName); + if (!file.exists()) { + return new BookmarkNode(BookmarkNode::Root); + } + file.open(QFile::ReadOnly); + return read(&file); +} + +BookmarkNode *XbelReader::read(QIODevice *device) +{ + BookmarkNode *root = new BookmarkNode(BookmarkNode::Root); + setDevice(device); + if (readNextStartElement()) { + QString version = attributes().value(QLatin1String("version")).toString(); + if (name() == QLatin1String("xbel") + && (version.isEmpty() || version == QLatin1String("1.0"))) { + readXBEL(root); + } else { + raiseError(QObject::tr("The file is not an XBEL version 1.0 file.")); + } + } + return root; +} + +void XbelReader::readXBEL(BookmarkNode *parent) +{ + Q_ASSERT(isStartElement() && name() == QLatin1String("xbel")); + + while (readNextStartElement()) { + if (name() == QLatin1String("folder")) + readFolder(parent); + else if (name() == QLatin1String("bookmark")) + readBookmarkNode(parent); + else if (name() == QLatin1String("separator")) + readSeparator(parent); + else + skipCurrentElement(); + } +} + +void XbelReader::readFolder(BookmarkNode *parent) +{ + Q_ASSERT(isStartElement() && name() == QLatin1String("folder")); + + BookmarkNode *folder = new BookmarkNode(BookmarkNode::Folder, parent); + folder->expanded = (attributes().value(QLatin1String("folded")) == QLatin1String("no")); + + while (readNextStartElement()) { + if (name() == QLatin1String("title")) + readTitle(folder); + else if (name() == QLatin1String("desc")) + readDescription(folder); + else if (name() == QLatin1String("folder")) + readFolder(folder); + else if (name() == QLatin1String("bookmark")) + readBookmarkNode(folder); + else if (name() == QLatin1String("separator")) + readSeparator(folder); + else + skipCurrentElement(); + } +} + +void XbelReader::readTitle(BookmarkNode *parent) +{ + Q_ASSERT(isStartElement() && name() == QLatin1String("title")); + parent->title = readElementText(); +} + +void XbelReader::readDescription(BookmarkNode *parent) +{ + Q_ASSERT(isStartElement() && name() == QLatin1String("desc")); + parent->desc = readElementText(); +} + +void XbelReader::readSeparator(BookmarkNode *parent) +{ + new BookmarkNode(BookmarkNode::Separator, parent); + // empty elements have a start and end element + readNext(); +} + +void XbelReader::readBookmarkNode(BookmarkNode *parent) +{ + Q_ASSERT(isStartElement() && name() == QLatin1String("bookmark")); + BookmarkNode *bookmark = new BookmarkNode(BookmarkNode::Bookmark, parent); + bookmark->url = attributes().value(QLatin1String("href")).toString(); + while (readNextStartElement()) { + if (name() == QLatin1String("title")) + readTitle(bookmark); + else if (name() == QLatin1String("desc")) + readDescription(bookmark); + else + skipCurrentElement(); + } + if (bookmark->title.isEmpty()) + bookmark->title = QObject::tr("Unknown title"); +} + + +XbelWriter::XbelWriter() +{ + setAutoFormatting(true); +} + +bool XbelWriter::write(const QString &fileName, const BookmarkNode *root) +{ + QFile file(fileName); + if (!root || !file.open(QFile::WriteOnly)) + return false; + return write(&file, root); +} + +bool XbelWriter::write(QIODevice *device, const BookmarkNode *root) +{ + setDevice(device); + + writeStartDocument(); + writeDTD(QLatin1String("")); + writeStartElement(QLatin1String("xbel")); + writeAttribute(QLatin1String("version"), QLatin1String("1.0")); + if (root->type() == BookmarkNode::Root) { + for (int i = 0; i < root->children().count(); ++i) + writeItem(root->children().at(i)); + } else { + writeItem(root); + } + + writeEndDocument(); + return true; +} + +void XbelWriter::writeItem(const BookmarkNode *parent) +{ + switch (parent->type()) { + case BookmarkNode::Folder: + writeStartElement(QLatin1String("folder")); + writeAttribute(QLatin1String("folded"), parent->expanded ? QLatin1String("no") : QLatin1String("yes")); + writeTextElement(QLatin1String("title"), parent->title); + for (int i = 0; i < parent->children().count(); ++i) + writeItem(parent->children().at(i)); + writeEndElement(); + break; + case BookmarkNode::Bookmark: + writeStartElement(QLatin1String("bookmark")); + if (!parent->url.isEmpty()) + writeAttribute(QLatin1String("href"), parent->url); + writeTextElement(QLatin1String("title"), parent->title); + if (!parent->desc.isEmpty()) + writeAttribute(QLatin1String("desc"), parent->desc); + writeEndElement(); + break; + case BookmarkNode::Separator: + writeEmptyElement(QLatin1String("separator")); + break; + default: + break; + } +} diff --git a/examples/webenginewidgets/browser/xbel.h b/examples/webenginewidgets/browser/xbel.h new file mode 100644 index 000000000..8ee9558ef --- /dev/null +++ b/examples/webenginewidgets/browser/xbel.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef XBEL_H +#define XBEL_H + +#include +#include + +class BookmarkNode +{ +public: + enum Type { + Root, + Folder, + Bookmark, + Separator + }; + + BookmarkNode(Type type = Root, BookmarkNode *parent = 0); + ~BookmarkNode(); + bool operator==(const BookmarkNode &other); + + Type type() const; + void setType(Type type); + QList children() const; + BookmarkNode *parent() const; + + void add(BookmarkNode *child, int offset = -1); + void remove(BookmarkNode *child); + + QString url; + QString title; + QString desc; + bool expanded; + +private: + BookmarkNode *m_parent; + Type m_type; + QList m_children; + +}; + +class XbelReader : public QXmlStreamReader +{ +public: + XbelReader(); + BookmarkNode *read(const QString &fileName); + BookmarkNode *read(QIODevice *device); + +private: + void readXBEL(BookmarkNode *parent); + void readTitle(BookmarkNode *parent); + void readDescription(BookmarkNode *parent); + void readSeparator(BookmarkNode *parent); + void readFolder(BookmarkNode *parent); + void readBookmarkNode(BookmarkNode *parent); +}; + +#include + +class XbelWriter : public QXmlStreamWriter +{ +public: + XbelWriter(); + bool write(const QString &fileName, const BookmarkNode *root); + bool write(QIODevice *device, const BookmarkNode *root); + +private: + void writeItem(const BookmarkNode *parent); +}; + +#endif // XBEL_H diff --git a/examples/webenginewidgets/fancybrowser/doc/images/fancybrowser-example.png b/examples/webenginewidgets/fancybrowser/doc/images/fancybrowser-example.png new file mode 100644 index 000000000..717ac9ddc Binary files /dev/null and b/examples/webenginewidgets/fancybrowser/doc/images/fancybrowser-example.png differ diff --git a/examples/webenginewidgets/fancybrowser/doc/src/fancybrowser.qdoc b/examples/webenginewidgets/fancybrowser/doc/src/fancybrowser.qdoc new file mode 100644 index 000000000..c1de06332 --- /dev/null +++ b/examples/webenginewidgets/fancybrowser/doc/src/fancybrowser.qdoc @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example webengine/fancybrowser + \title Fancy Browser Example + \brief Demonstrates how to use browse web and manipulate content + \ingroup webengine-widgetexamples + + \brief The Fancy Browser example shows how to use JQuery with QtWebEngine to + create a web browser with special effects and content + manipulation. + + \image fancybrowser-example.png + + The application makes use of QWebEnginePage::evaluateJavaScript to + evaluate the jQuery JavaScript code. A QMainWindow with a QWebEngineView + as central widget builds up the browser itself. + + \section1 MainWindow Class Definition + + The \c MainWindow class inherits QMainWindow. It implements a number of + slots to perform actions on both the application and on the web content. + + \snippet webenginewidgets/fancybrowser/mainwindow.h 1 + + We also declare a QString that contains the jQuery, a QWebView + that displays the web content, and a QLineEdit that acts as the + address bar. + + \section1 MainWindow Class Implementation + + We start by implementing the constructor. + + \snippet webenginewidgets/fancybrowser/mainwindow.cpp 1 + + The first part of the constructor sets the value of \c progress to + 0. This value will be used later in the code to visualize the + loading of a webpage. + + Next, the jQuery library is loaded using a QFile and reading the file + content. The jQuery library is a JavaScript library that provides different + functions for manipulating HTML. + + \snippet webenginewidgets/fancybrowser/mainwindow.cpp 2 + + The second part of the constructor creates a QWebView and connects + slots to the views signals. Furthermore, we create a QLineEdit as + the browsers address bar. We then set the horizontal QSizePolicy + to fill the available area in the browser at all times. We add the + QLineEdit to a QToolbar together with a set of navigation actions + from QWebView::pageAction. + + \snippet webenginewidgets/fancybrowser/mainwindow.cpp 3 + + The third and last part of the constructor implements two QMenus and assigns + a set of actions to them. The last line sets the QWebView as the central + widget in the QMainWindow. + + \snippet webenginewidgets/fancybrowser/mainwindow.cpp 4 + + When the page is loaded, \c adjustLocation() updates the address + bar; \c adjustLocation() is triggered by the \c loadFinished() + signal in QWebView. In \c changeLocation() we create a QUrl + object, and then use it to load the page into the QWebView. When + the new web page has finished loading, \c adjustLocation() will be + run once more to update the address bar. + + \snippet webenginewidgets/fancybrowser/mainwindow.cpp 5 + + \c adjustTitle() sets the window title and displays the loading + progress. This slot is triggered by the \c titleChanged() signal + in QWebView. + + \snippet webenginewidgets/fancybrowser/mainwindow.cpp 6 + + When a web page has loaded, \c finishLoading() is triggered by the + \c loadFinished() signal in QWebView. \c finishLoading() then updates the + progress in the title bar and calls \c evaluateJavaScript() + to evaluate the jQuery library. This evaluates the JavaScript against the + current web page. What that means is that the JavaScript can be viewed as + part of the content loaded into the QWebView, and therefore needs to be + loaded every time a new page is loaded. Once the jQuery library is loaded, + we can start executing the different jQuery functions in the browser. + + The rotateImages() function is then called explicitely to make sure + that the images of the newly loaded page respect the state of the toggle + action. + + \snippet webenginewidgets/fancybrowser/mainwindow.cpp 7 + + The first jQuery-based function, \c highlightAllLinks(), is designed to + highlight all links in the current webpage. The JavaScript code looks + for web elements named \e {a}, which is the tag for a hyperlink. + For each such element, the background color is set to be yellow by + using CSS. + + \snippet webenginewidgets/fancybrowser/mainwindow.cpp 8 + + The \c rotateImages() function rotates the images on the current + web page. This JavaScript code relies on CSS transforms and + looks up all \e {img} elements and rotates the images 180 degrees + and then back again. + + \snippet webenginewidgets/fancybrowser/mainwindow.cpp 9 + + The remaining four methods remove different elements from the current web + page. \c removeGifImages() removes all GIF images on the page by looking up + the \e {src} attribute of all the elements on the web page. Any element with + a \e {gif} file as its source is removed. \c removeInlineFrames() removes all + \e {iframe} or inline elements. \c removeObjectElements() removes all + \e {object} elements, and \c removeEmbeddedElements() removes any elements + such as plugins embedded on the page using the \e {embed} tag. + +*/ + diff --git a/examples/webenginewidgets/fancybrowser/fancybrowser.pro b/examples/webenginewidgets/fancybrowser/fancybrowser.pro new file mode 100644 index 000000000..c530f74b8 --- /dev/null +++ b/examples/webenginewidgets/fancybrowser/fancybrowser.pro @@ -0,0 +1,12 @@ +QT += webenginewidgets + +macx: CONFIG -= app_bundle + +HEADERS = mainwindow.h +SOURCES = main.cpp \ + mainwindow.cpp +RESOURCES = jquery.qrc + +# install +#target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/fancybrowser +#INSTALLS += target diff --git a/examples/webenginewidgets/fancybrowser/jquery.min.js b/examples/webenginewidgets/fancybrowser/jquery.min.js new file mode 100644 index 000000000..b1ae21d8b --- /dev/null +++ b/examples/webenginewidgets/fancybrowser/jquery.min.js @@ -0,0 +1,19 @@ +/* + * jQuery JavaScript Library v1.3.2 + * http://jquery.com/ + * + * Copyright (c) 2009 John Resig + * Dual licensed under the MIT and GPL licenses. + * http://docs.jquery.com/License + * + * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) + * Revision: 6246 + */ +(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
"]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
","
"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); +/* + * Sizzle CSS Selector Engine - v0.9.3 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/examples/webenginewidgets/fancybrowser/jquery.qrc b/examples/webenginewidgets/fancybrowser/jquery.qrc new file mode 100644 index 000000000..1022d682f --- /dev/null +++ b/examples/webenginewidgets/fancybrowser/jquery.qrc @@ -0,0 +1,5 @@ + + + jquery.min.js + + diff --git a/examples/webenginewidgets/fancybrowser/main.cpp b/examples/webenginewidgets/fancybrowser/main.cpp new file mode 100644 index 000000000..451f247f3 --- /dev/null +++ b/examples/webenginewidgets/fancybrowser/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "mainwindow.h" + +int main(int argc, char * argv[]) +{ + QApplication app(argc, argv); + QUrl url; + if (argc > 1) + url = QUrl::fromUserInput(argv[1]); + else + url = QUrl("http://www.google.com/ncr"); + MainWindow *browser = new MainWindow(url); + browser->show(); + return app.exec(); +} diff --git a/examples/webenginewidgets/fancybrowser/mainwindow.cpp b/examples/webenginewidgets/fancybrowser/mainwindow.cpp new file mode 100644 index 000000000..3366d2006 --- /dev/null +++ b/examples/webenginewidgets/fancybrowser/mainwindow.cpp @@ -0,0 +1,225 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include "mainwindow.h" + +template +struct InvokeWrapper { + R *receiver; + void (C::*memberFun)(Arg); + void operator()(Arg result) { + (receiver->*memberFun)(result); + } +}; + +template +InvokeWrapper invoke(R *receiver, void (C::*memberFun)(Arg)) +{ + InvokeWrapper wrapper = {receiver, memberFun}; + return wrapper; +} + +//! [1] + +MainWindow::MainWindow(const QUrl& url) +{ + progress = 0; + + QFile file; + file.setFileName(":/jquery.min.js"); + file.open(QIODevice::ReadOnly); + jQuery = file.readAll(); + jQuery.append("\nvar qt = { 'jQuery': jQuery.noConflict(true) };"); + file.close(); + +//! [1] + view = new QWebEngineView(this); + view->load(url); + connect(view, SIGNAL(loadFinished(bool)), SLOT(adjustLocation())); + connect(view, SIGNAL(titleChanged(QString)), SLOT(adjustTitle())); + connect(view, SIGNAL(loadProgress(int)), SLOT(setProgress(int))); + connect(view, SIGNAL(loadFinished(bool)), SLOT(finishLoading(bool))); + + locationEdit = new QLineEdit(this); + locationEdit->setSizePolicy(QSizePolicy::Expanding, locationEdit->sizePolicy().verticalPolicy()); + connect(locationEdit, SIGNAL(returnPressed()), SLOT(changeLocation())); + + QToolBar *toolBar = addToolBar(tr("Navigation")); + toolBar->addAction(view->pageAction(QWebEnginePage::Back)); + toolBar->addAction(view->pageAction(QWebEnginePage::Forward)); + toolBar->addAction(view->pageAction(QWebEnginePage::Reload)); + toolBar->addAction(view->pageAction(QWebEnginePage::Stop)); + toolBar->addWidget(locationEdit); +//! [1] + + QMenu *viewMenu = menuBar()->addMenu(tr("&View")); + QAction* viewSourceAction = new QAction("Page Source", this); + connect(viewSourceAction, SIGNAL(triggered()), SLOT(viewSource())); + viewMenu->addAction(viewSourceAction); + +//! [3] + QMenu *effectMenu = menuBar()->addMenu(tr("&Effect")); + effectMenu->addAction("Highlight all links", this, SLOT(highlightAllLinks())); + + rotateAction = new QAction(this); + rotateAction->setIcon(style()->standardIcon(QStyle::SP_FileDialogDetailedView)); + rotateAction->setCheckable(true); + rotateAction->setText(tr("Turn images upside down")); + connect(rotateAction, SIGNAL(toggled(bool)), this, SLOT(rotateImages(bool))); + effectMenu->addAction(rotateAction); + + QMenu *toolsMenu = menuBar()->addMenu(tr("&Tools")); + toolsMenu->addAction(tr("Remove GIF images"), this, SLOT(removeGifImages())); + toolsMenu->addAction(tr("Remove all inline frames"), this, SLOT(removeInlineFrames())); + toolsMenu->addAction(tr("Remove all object elements"), this, SLOT(removeObjectElements())); + toolsMenu->addAction(tr("Remove all embedded elements"), this, SLOT(removeEmbeddedElements())); + + setCentralWidget(view); + setUnifiedTitleAndToolBarOnMac(true); +} +//! [3] + +void MainWindow::viewSource() +{ + QTextEdit* textEdit = new QTextEdit(NULL); + textEdit->setAttribute(Qt::WA_DeleteOnClose); + textEdit->adjustSize(); + textEdit->move(this->geometry().center() - textEdit->rect().center()); + textEdit->show(); + + view->page()->toHtml(invoke(textEdit, &QTextEdit::setPlainText)); +} + +//! [4] +void MainWindow::adjustLocation() +{ + locationEdit->setText(view->url().toString()); +} + +void MainWindow::changeLocation() +{ + QUrl url = QUrl::fromUserInput(locationEdit->text()); + view->load(url); + view->setFocus(); +} +//! [4] + +//! [5] +void MainWindow::adjustTitle() +{ + if (progress <= 0 || progress >= 100) + setWindowTitle(view->title()); + else + setWindowTitle(QString("%1 (%2%)").arg(view->title()).arg(progress)); +} + +void MainWindow::setProgress(int p) +{ + progress = p; + adjustTitle(); +} +//! [5] + +//! [6] +void MainWindow::finishLoading(bool) +{ + progress = 100; + adjustTitle(); + view->page()->runJavaScript(jQuery); + + rotateImages(rotateAction->isChecked()); +} +//! [6] + +//! [7] +void MainWindow::highlightAllLinks() +{ + // We append '; undefined' after the jQuery call here to prevent a possible recursion loop and crash caused by + // the way the elements returned by the each iterator elements reference each other, which causes problems upon + // converting them to QVariants. + QString code = "qt.jQuery('a').each( function () { qt.jQuery(this).css('background-color', 'yellow') } ); undefined"; + view->page()->runJavaScript(code); +} +//! [7] + +//! [8] +void MainWindow::rotateImages(bool invert) +{ + QString code; + + // We append '; undefined' after each of the jQuery calls here to prevent a possible recursion loop and crash caused by + // the way the elements returned by the each iterator elements reference each other, which causes problems upon + // converting them to QVariants. + if (invert) + code = "qt.jQuery('img').each( function () { qt.jQuery(this).css('-webkit-transition', '-webkit-transform 2s'); qt.jQuery(this).css('-webkit-transform', 'rotate(180deg)') } ); undefined"; + else + code = "qt.jQuery('img').each( function () { qt.jQuery(this).css('-webkit-transition', '-webkit-transform 2s'); qt.jQuery(this).css('-webkit-transform', 'rotate(0deg)') } ); undefined"; + view->page()->runJavaScript(code); +} +//! [8] + +//! [9] +void MainWindow::removeGifImages() +{ + QString code = "qt.jQuery('[src*=gif]').remove()"; + view->page()->runJavaScript(code); +} + +void MainWindow::removeInlineFrames() +{ + QString code = "qt.jQuery('iframe').remove()"; + view->page()->runJavaScript(code); +} + +void MainWindow::removeObjectElements() +{ + QString code = "qt.jQuery('object').remove()"; + view->page()->runJavaScript(code); +} + +void MainWindow::removeEmbeddedElements() +{ + QString code = "qt.jQuery('embed').remove()"; + view->page()->runJavaScript(code); +} +//! [9] + diff --git a/examples/webenginewidgets/fancybrowser/mainwindow.h b/examples/webenginewidgets/fancybrowser/mainwindow.h new file mode 100644 index 000000000..5f33bdf96 --- /dev/null +++ b/examples/webenginewidgets/fancybrowser/mainwindow.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +QT_BEGIN_NAMESPACE +class QWebEngineView; +class QLineEdit; +QT_END_NAMESPACE + +//! [1] +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(const QUrl& url); + +protected slots: + + void adjustLocation(); + void changeLocation(); + void adjustTitle(); + void setProgress(int p); + void finishLoading(bool); + + void viewSource(); + + void highlightAllLinks(); + void rotateImages(bool invert); + void removeGifImages(); + void removeInlineFrames(); + void removeObjectElements(); + void removeEmbeddedElements(); + +private: + QString jQuery; + QWebEngineView *view; + QLineEdit *locationEdit; + QAction *rotateAction; + int progress; +//! [1] +}; diff --git a/examples/widgets/browser/Info_mac.plist b/examples/widgets/browser/Info_mac.plist deleted file mode 100644 index 87435b2b6..000000000 --- a/examples/widgets/browser/Info_mac.plist +++ /dev/null @@ -1,43 +0,0 @@ - - - - - CFBundleIconFile - @ICON@ - CFBundlePackageType - APPL - CFBundleGetInfoString - Created by Qt/QMake - CFBundleIdentifier - com.trolltech.DemoBrowser - CFBundleSignature - ttxt - CFBundleExecutable - @EXECUTABLE@ - CFBundleDocumentTypes - - - CFBundleTypeExtensions - - html - htm - shtml - xht - xhtml - - CFBundleTypeIconFile - @ICON@ - CFBundleTypeName - HTML Document - CFBundleTypeOSTypes - - HTML - - CFBundleTypeRole - Viewer - - - NOTE - DemoBrowser by Digia Plc and/or its subsidiary(-ies) - - diff --git a/examples/widgets/browser/addbookmarkdialog.ui b/examples/widgets/browser/addbookmarkdialog.ui deleted file mode 100644 index 3460d7bb8..000000000 --- a/examples/widgets/browser/addbookmarkdialog.ui +++ /dev/null @@ -1,98 +0,0 @@ - - AddBookmarkDialog - - - - 0 - 0 - 240 - 168 - - - - Add Bookmark - - - - - - Type a name for the bookmark, and choose where to keep it. - - - Qt::PlainText - - - true - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 2 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - false - - - - - - - - - buttonBox - accepted() - AddBookmarkDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - AddBookmarkDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/examples/widgets/browser/autosaver.cpp b/examples/widgets/browser/autosaver.cpp deleted file mode 100644 index a6efa4ca1..000000000 --- a/examples/widgets/browser/autosaver.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "autosaver.h" - -#include -#include -#include -#include - -#define AUTOSAVE_IN 1000 * 3 // seconds -#define MAXWAIT 1000 * 15 // seconds - -AutoSaver::AutoSaver(QObject *parent) : QObject(parent) -{ - Q_ASSERT(parent); -} - -AutoSaver::~AutoSaver() -{ - if (m_timer.isActive()) - qWarning() << "AutoSaver: still active when destroyed, changes not saved."; -} - -void AutoSaver::changeOccurred() -{ - if (m_firstChange.isNull()) - m_firstChange.start(); - - if (m_firstChange.elapsed() > MAXWAIT) { - saveIfNeccessary(); - } else { - m_timer.start(AUTOSAVE_IN, this); - } -} - -void AutoSaver::timerEvent(QTimerEvent *event) -{ - if (event->timerId() == m_timer.timerId()) { - saveIfNeccessary(); - } else { - QObject::timerEvent(event); - } -} - -void AutoSaver::saveIfNeccessary() -{ - if (!m_timer.isActive()) - return; - m_timer.stop(); - m_firstChange = QTime(); - if (!QMetaObject::invokeMethod(parent(), "save", Qt::DirectConnection)) { - qWarning() << "AutoSaver: error invoking slot save() on parent"; - } -} diff --git a/examples/widgets/browser/autosaver.h b/examples/widgets/browser/autosaver.h deleted file mode 100644 index cf499b066..000000000 --- a/examples/widgets/browser/autosaver.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef AUTOSAVER_H -#define AUTOSAVER_H - -#include -#include -#include - -/* - This class will call the save() slot on the parent object when the parent changes. - It will wait several seconds after changed() to combining multiple changes and - prevent continuous writing to disk. - */ -class AutoSaver : public QObject { - -Q_OBJECT - -public: - AutoSaver(QObject *parent); - ~AutoSaver(); - void saveIfNeccessary(); - -public slots: - void changeOccurred(); - -protected: - void timerEvent(QTimerEvent *event); - -private: - QBasicTimer m_timer; - QTime m_firstChange; - -}; - -#endif // AUTOSAVER_H diff --git a/examples/widgets/browser/bookmarks.cpp b/examples/widgets/browser/bookmarks.cpp deleted file mode 100644 index adc35bd50..000000000 --- a/examples/widgets/browser/bookmarks.cpp +++ /dev/null @@ -1,986 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "bookmarks.h" - -#include "autosaver.h" -#include "browserapplication.h" -#include "history.h" -#include "xbel.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#define BOOKMARKBAR "Bookmarks Bar" -#define BOOKMARKMENU "Bookmarks Menu" - -BookmarksManager::BookmarksManager(QObject *parent) - : QObject(parent) - , m_loaded(false) - , m_saveTimer(new AutoSaver(this)) - , m_bookmarkRootNode(0) - , m_bookmarkModel(0) -{ - connect(this, SIGNAL(entryAdded(BookmarkNode*)), - m_saveTimer, SLOT(changeOccurred())); - connect(this, SIGNAL(entryRemoved(BookmarkNode*,int,BookmarkNode*)), - m_saveTimer, SLOT(changeOccurred())); - connect(this, SIGNAL(entryChanged(BookmarkNode*)), - m_saveTimer, SLOT(changeOccurred())); -} - -BookmarksManager::~BookmarksManager() -{ - m_saveTimer->saveIfNeccessary(); -} - -void BookmarksManager::changeExpanded() -{ - m_saveTimer->changeOccurred(); -} - -void BookmarksManager::load() -{ - if (m_loaded) - return; - m_loaded = true; - - QString dir = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - QString bookmarkFile = dir + QLatin1String("/bookmarks.xbel"); - if (!QFile::exists(bookmarkFile)) - bookmarkFile = QLatin1String(":defaultbookmarks.xbel"); - - XbelReader reader; - m_bookmarkRootNode = reader.read(bookmarkFile); - if (reader.error() != QXmlStreamReader::NoError) { - QMessageBox::warning(0, QLatin1String("Loading Bookmark"), - tr("Error when loading bookmarks on line %1, column %2:\n" - "%3").arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString())); - } - - BookmarkNode *toolbar = 0; - BookmarkNode *menu = 0; - QList others; - for (int i = m_bookmarkRootNode->children().count() - 1; i >= 0; --i) { - BookmarkNode *node = m_bookmarkRootNode->children().at(i); - if (node->type() == BookmarkNode::Folder) { - // Automatically convert - if (node->title == tr("Toolbar Bookmarks") && !toolbar) { - node->title = tr(BOOKMARKBAR); - } - if (node->title == tr(BOOKMARKBAR) && !toolbar) { - toolbar = node; - } - - // Automatically convert - if (node->title == tr("Menu") && !menu) { - node->title = tr(BOOKMARKMENU); - } - if (node->title == tr(BOOKMARKMENU) && !menu) { - menu = node; - } - } else { - others.append(node); - } - m_bookmarkRootNode->remove(node); - } - Q_ASSERT(m_bookmarkRootNode->children().count() == 0); - if (!toolbar) { - toolbar = new BookmarkNode(BookmarkNode::Folder, m_bookmarkRootNode); - toolbar->title = tr(BOOKMARKBAR); - } else { - m_bookmarkRootNode->add(toolbar); - } - - if (!menu) { - menu = new BookmarkNode(BookmarkNode::Folder, m_bookmarkRootNode); - menu->title = tr(BOOKMARKMENU); - } else { - m_bookmarkRootNode->add(menu); - } - - for (int i = 0; i < others.count(); ++i) - menu->add(others.at(i)); -} - -void BookmarksManager::save() const -{ - if (!m_loaded) - return; - - XbelWriter writer; - QString dir = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - QString bookmarkFile = dir + QLatin1String("/bookmarks.xbel"); - if (!writer.write(bookmarkFile, m_bookmarkRootNode)) - qWarning() << "BookmarkManager: error saving to" << bookmarkFile; -} - -void BookmarksManager::addBookmark(BookmarkNode *parent, BookmarkNode *node, int row) -{ - if (!m_loaded) - return; - Q_ASSERT(parent); - InsertBookmarksCommand *command = new InsertBookmarksCommand(this, parent, node, row); - m_commands.push(command); -} - -void BookmarksManager::removeBookmark(BookmarkNode *node) -{ - if (!m_loaded) - return; - - Q_ASSERT(node); - BookmarkNode *parent = node->parent(); - int row = parent->children().indexOf(node); - RemoveBookmarksCommand *command = new RemoveBookmarksCommand(this, parent, row); - m_commands.push(command); -} - -void BookmarksManager::setTitle(BookmarkNode *node, const QString &newTitle) -{ - if (!m_loaded) - return; - - Q_ASSERT(node); - ChangeBookmarkCommand *command = new ChangeBookmarkCommand(this, node, newTitle, true); - m_commands.push(command); -} - -void BookmarksManager::setUrl(BookmarkNode *node, const QString &newUrl) -{ - if (!m_loaded) - return; - - Q_ASSERT(node); - ChangeBookmarkCommand *command = new ChangeBookmarkCommand(this, node, newUrl, false); - m_commands.push(command); -} - -BookmarkNode *BookmarksManager::bookmarks() -{ - if (!m_loaded) - load(); - return m_bookmarkRootNode; -} - -BookmarkNode *BookmarksManager::menu() -{ - if (!m_loaded) - load(); - - for (int i = m_bookmarkRootNode->children().count() - 1; i >= 0; --i) { - BookmarkNode *node = m_bookmarkRootNode->children().at(i); - if (node->title == tr(BOOKMARKMENU)) - return node; - } - Q_ASSERT(false); - return 0; -} - -BookmarkNode *BookmarksManager::toolbar() -{ - if (!m_loaded) - load(); - - for (int i = m_bookmarkRootNode->children().count() - 1; i >= 0; --i) { - BookmarkNode *node = m_bookmarkRootNode->children().at(i); - if (node->title == tr(BOOKMARKBAR)) - return node; - } - Q_ASSERT(false); - return 0; -} - -BookmarksModel *BookmarksManager::bookmarksModel() -{ - if (!m_bookmarkModel) - m_bookmarkModel = new BookmarksModel(this, this); - return m_bookmarkModel; -} - -void BookmarksManager::importBookmarks() -{ - QString fileName = QFileDialog::getOpenFileName(0, tr("Open File"), - QString(), - tr("XBEL (*.xbel *.xml)")); - if (fileName.isEmpty()) - return; - - XbelReader reader; - BookmarkNode *importRootNode = reader.read(fileName); - if (reader.error() != QXmlStreamReader::NoError) { - QMessageBox::warning(0, QLatin1String("Loading Bookmark"), - tr("Error when loading bookmarks on line %1, column %2:\n" - "%3").arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString())); - } - - importRootNode->setType(BookmarkNode::Folder); - importRootNode->title = (tr("Imported %1").arg(QDate::currentDate().toString(Qt::SystemLocaleShortDate))); - addBookmark(menu(), importRootNode); -} - -void BookmarksManager::exportBookmarks() -{ - QString fileName = QFileDialog::getSaveFileName(0, tr("Save File"), - tr("%1 Bookmarks.xbel").arg(QCoreApplication::applicationName()), - tr("XBEL (*.xbel *.xml)")); - if (fileName.isEmpty()) - return; - - XbelWriter writer; - if (!writer.write(fileName, m_bookmarkRootNode)) - QMessageBox::critical(0, tr("Export error"), tr("error saving bookmarks")); -} - -RemoveBookmarksCommand::RemoveBookmarksCommand(BookmarksManager *m_bookmarkManagaer, BookmarkNode *parent, int row) - : QUndoCommand(BookmarksManager::tr("Remove Bookmark")) - , m_row(row) - , m_bookmarkManagaer(m_bookmarkManagaer) - , m_node(parent->children().value(row)) - , m_parent(parent) - , m_done(false) -{ -} - -RemoveBookmarksCommand::~RemoveBookmarksCommand() -{ - if (m_done && !m_node->parent()) { - delete m_node; - } -} - -void RemoveBookmarksCommand::undo() -{ - m_parent->add(m_node, m_row); - emit m_bookmarkManagaer->entryAdded(m_node); - m_done = false; -} - -void RemoveBookmarksCommand::redo() -{ - m_parent->remove(m_node); - emit m_bookmarkManagaer->entryRemoved(m_parent, m_row, m_node); - m_done = true; -} - -InsertBookmarksCommand::InsertBookmarksCommand(BookmarksManager *m_bookmarkManagaer, - BookmarkNode *parent, BookmarkNode *node, int row) - : RemoveBookmarksCommand(m_bookmarkManagaer, parent, row) -{ - setText(BookmarksManager::tr("Insert Bookmark")); - m_node = node; -} - -ChangeBookmarkCommand::ChangeBookmarkCommand(BookmarksManager *m_bookmarkManagaer, BookmarkNode *node, - const QString &newValue, bool title) - : QUndoCommand() - , m_bookmarkManagaer(m_bookmarkManagaer) - , m_title(title) - , m_newValue(newValue) - , m_node(node) -{ - if (m_title) { - m_oldValue = m_node->title; - setText(BookmarksManager::tr("Name Change")); - } else { - m_oldValue = m_node->url; - setText(BookmarksManager::tr("Address Change")); - } -} - -void ChangeBookmarkCommand::undo() -{ - if (m_title) - m_node->title = m_oldValue; - else - m_node->url = m_oldValue; - emit m_bookmarkManagaer->entryChanged(m_node); -} - -void ChangeBookmarkCommand::redo() -{ - if (m_title) - m_node->title = m_newValue; - else - m_node->url = m_newValue; - emit m_bookmarkManagaer->entryChanged(m_node); -} - -BookmarksModel::BookmarksModel(BookmarksManager *bookmarkManager, QObject *parent) - : QAbstractItemModel(parent) - , m_endMacro(false) - , m_bookmarksManager(bookmarkManager) -{ - connect(bookmarkManager, SIGNAL(entryAdded(BookmarkNode*)), - this, SLOT(entryAdded(BookmarkNode*))); - connect(bookmarkManager, SIGNAL(entryRemoved(BookmarkNode*,int,BookmarkNode*)), - this, SLOT(entryRemoved(BookmarkNode*,int,BookmarkNode*))); - connect(bookmarkManager, SIGNAL(entryChanged(BookmarkNode*)), - this, SLOT(entryChanged(BookmarkNode*))); -} - -QModelIndex BookmarksModel::index(BookmarkNode *node) const -{ - BookmarkNode *parent = node->parent(); - if (!parent) - return QModelIndex(); - return createIndex(parent->children().indexOf(node), 0, node); -} - -void BookmarksModel::entryAdded(BookmarkNode *item) -{ - Q_ASSERT(item && item->parent()); - int row = item->parent()->children().indexOf(item); - BookmarkNode *parent = item->parent(); - // item was already added so remove beore beginInsertRows is called - parent->remove(item); - beginInsertRows(index(parent), row, row); - parent->add(item, row); - endInsertRows(); -} - -void BookmarksModel::entryRemoved(BookmarkNode *parent, int row, BookmarkNode *item) -{ - // item was already removed, re-add so beginRemoveRows works - parent->add(item, row); - beginRemoveRows(index(parent), row, row); - parent->remove(item); - endRemoveRows(); -} - -void BookmarksModel::entryChanged(BookmarkNode *item) -{ - QModelIndex idx = index(item); - emit dataChanged(idx, idx); -} - -bool BookmarksModel::removeRows(int row, int count, const QModelIndex &parent) -{ - if (row < 0 || count <= 0 || row + count > rowCount(parent)) - return false; - - BookmarkNode *bookmarkNode = node(parent); - for (int i = row + count - 1; i >= row; --i) { - BookmarkNode *node = bookmarkNode->children().at(i); - if (node == m_bookmarksManager->menu() - || node == m_bookmarksManager->toolbar()) - continue; - - m_bookmarksManager->removeBookmark(node); - } - if (m_endMacro) { - m_bookmarksManager->undoRedoStack()->endMacro(); - m_endMacro = false; - } - return true; -} - -QVariant BookmarksModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { - switch (section) { - case 0: return tr("Title"); - case 1: return tr("Address"); - } - } - return QAbstractItemModel::headerData(section, orientation, role); -} - -QVariant BookmarksModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || index.model() != this) - return QVariant(); - - const BookmarkNode *bookmarkNode = node(index); - switch (role) { - case Qt::EditRole: - case Qt::DisplayRole: - if (bookmarkNode->type() == BookmarkNode::Separator) { - switch (index.column()) { - case 0: return QString(50, 0xB7); - case 1: return QString(); - } - } - - switch (index.column()) { - case 0: return bookmarkNode->title; - case 1: return bookmarkNode->url; - } - break; - case BookmarksModel::UrlRole: - return QUrl(bookmarkNode->url); - break; - case BookmarksModel::UrlStringRole: - return bookmarkNode->url; - break; - case BookmarksModel::TypeRole: - return bookmarkNode->type(); - break; - case BookmarksModel::SeparatorRole: - return (bookmarkNode->type() == BookmarkNode::Separator); - break; - case Qt::DecorationRole: - if (index.column() == 0) { - if (bookmarkNode->type() == BookmarkNode::Folder) - return QApplication::style()->standardIcon(QStyle::SP_DirIcon); - return BrowserApplication::instance()->icon(bookmarkNode->url); - } - } - - return QVariant(); -} - -int BookmarksModel::columnCount(const QModelIndex &parent) const -{ - return (parent.column() > 0) ? 0 : 2; -} - -int BookmarksModel::rowCount(const QModelIndex &parent) const -{ - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) - return m_bookmarksManager->bookmarks()->children().count(); - - const BookmarkNode *item = static_cast(parent.internalPointer()); - return item->children().count(); -} - -QModelIndex BookmarksModel::index(int row, int column, const QModelIndex &parent) const -{ - if (row < 0 || column < 0 || row >= rowCount(parent) || column >= columnCount(parent)) - return QModelIndex(); - - // get the parent node - BookmarkNode *parentNode = node(parent); - return createIndex(row, column, parentNode->children().at(row)); -} - -QModelIndex BookmarksModel::parent(const QModelIndex &index) const -{ - if (!index.isValid()) - return QModelIndex(); - - BookmarkNode *itemNode = node(index); - BookmarkNode *parentNode = (itemNode ? itemNode->parent() : 0); - if (!parentNode || parentNode == m_bookmarksManager->bookmarks()) - return QModelIndex(); - - // get the parent's row - BookmarkNode *grandParentNode = parentNode->parent(); - int parentRow = grandParentNode->children().indexOf(parentNode); - Q_ASSERT(parentRow >= 0); - return createIndex(parentRow, 0, parentNode); -} - -bool BookmarksModel::hasChildren(const QModelIndex &parent) const -{ - if (!parent.isValid()) - return true; - const BookmarkNode *parentNode = node(parent); - return (parentNode->type() == BookmarkNode::Folder); -} - -Qt::ItemFlags BookmarksModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return Qt::NoItemFlags; - - Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; - - BookmarkNode *bookmarkNode = node(index); - - if (bookmarkNode != m_bookmarksManager->menu() - && bookmarkNode != m_bookmarksManager->toolbar()) { - flags |= Qt::ItemIsDragEnabled; - if (bookmarkNode->type() != BookmarkNode::Separator) - flags |= Qt::ItemIsEditable; - } - if (hasChildren(index)) - flags |= Qt::ItemIsDropEnabled; - return flags; -} - -Qt::DropActions BookmarksModel::supportedDropActions () const -{ - return Qt::CopyAction | Qt::MoveAction; -} - -#define MIMETYPE QLatin1String("application/bookmarks.xbel") - -QStringList BookmarksModel::mimeTypes() const -{ - QStringList types; - types << MIMETYPE; - return types; -} - -QMimeData *BookmarksModel::mimeData(const QModelIndexList &indexes) const -{ - QMimeData *mimeData = new QMimeData(); - QByteArray data; - QDataStream stream(&data, QIODevice::WriteOnly); - foreach (QModelIndex index, indexes) { - if (index.column() != 0 || !index.isValid()) - continue; - QByteArray encodedData; - QBuffer buffer(&encodedData); - buffer.open(QBuffer::ReadWrite); - XbelWriter writer; - const BookmarkNode *parentNode = node(index); - writer.write(&buffer, parentNode); - stream << encodedData; - } - mimeData->setData(MIMETYPE, data); - return mimeData; -} - -bool BookmarksModel::dropMimeData(const QMimeData *data, - Qt::DropAction action, int row, int column, const QModelIndex &parent) -{ - if (action == Qt::IgnoreAction) - return true; - - if (!data->hasFormat(MIMETYPE) - || column > 0) - return false; - - QByteArray ba = data->data(MIMETYPE); - QDataStream stream(&ba, QIODevice::ReadOnly); - if (stream.atEnd()) - return false; - - QUndoStack *undoStack = m_bookmarksManager->undoRedoStack(); - undoStack->beginMacro(QLatin1String("Move Bookmarks")); - - while (!stream.atEnd()) { - QByteArray encodedData; - stream >> encodedData; - QBuffer buffer(&encodedData); - buffer.open(QBuffer::ReadOnly); - - XbelReader reader; - BookmarkNode *rootNode = reader.read(&buffer); - QList children = rootNode->children(); - for (int i = 0; i < children.count(); ++i) { - BookmarkNode *bookmarkNode = children.at(i); - rootNode->remove(bookmarkNode); - row = qMax(0, row); - BookmarkNode *parentNode = node(parent); - m_bookmarksManager->addBookmark(parentNode, bookmarkNode, row); - m_endMacro = true; - } - delete rootNode; - } - return true; -} - -bool BookmarksModel::setData(const QModelIndex &index, const QVariant &value, int role) -{ - if (!index.isValid() || (flags(index) & Qt::ItemIsEditable) == 0) - return false; - - BookmarkNode *item = node(index); - - switch (role) { - case Qt::EditRole: - case Qt::DisplayRole: - if (index.column() == 0) { - m_bookmarksManager->setTitle(item, value.toString()); - break; - } - if (index.column() == 1) { - m_bookmarksManager->setUrl(item, value.toString()); - break; - } - return false; - case BookmarksModel::UrlRole: - m_bookmarksManager->setUrl(item, value.toUrl().toString()); - break; - case BookmarksModel::UrlStringRole: - m_bookmarksManager->setUrl(item, value.toString()); - break; - default: - break; - return false; - } - - return true; -} - -BookmarkNode *BookmarksModel::node(const QModelIndex &index) const -{ - BookmarkNode *itemNode = static_cast(index.internalPointer()); - if (!itemNode) - return m_bookmarksManager->bookmarks(); - return itemNode; -} - - -AddBookmarkProxyModel::AddBookmarkProxyModel(QObject *parent) - : QSortFilterProxyModel(parent) -{ -} - -int AddBookmarkProxyModel::columnCount(const QModelIndex &parent) const -{ - return qMin(1, QSortFilterProxyModel::columnCount(parent)); -} - -bool AddBookmarkProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const -{ - QModelIndex idx = sourceModel()->index(source_row, 0, source_parent); - return sourceModel()->hasChildren(idx); -} - -AddBookmarkDialog::AddBookmarkDialog(const QString &url, const QString &title, QWidget *parent, BookmarksManager *bookmarkManager) - : QDialog(parent) - , m_url(url) - , m_bookmarksManager(bookmarkManager) -{ - setWindowFlags(Qt::Sheet); - if (!m_bookmarksManager) - m_bookmarksManager = BrowserApplication::bookmarksManager(); - setupUi(this); - QTreeView *view = new QTreeView(this); - m_proxyModel = new AddBookmarkProxyModel(this); - BookmarksModel *model = m_bookmarksManager->bookmarksModel(); - m_proxyModel->setSourceModel(model); - view->setModel(m_proxyModel); - view->expandAll(); - view->header()->setStretchLastSection(true); - view->header()->hide(); - view->setItemsExpandable(false); - view->setRootIsDecorated(false); - view->setIndentation(10); - location->setModel(m_proxyModel); - view->show(); - location->setView(view); - BookmarkNode *menu = m_bookmarksManager->menu(); - QModelIndex idx = m_proxyModel->mapFromSource(model->index(menu)); - view->setCurrentIndex(idx); - location->setCurrentIndex(idx.row()); - name->setText(title); -} - -void AddBookmarkDialog::accept() -{ - QModelIndex index = location->view()->currentIndex(); - index = m_proxyModel->mapToSource(index); - if (!index.isValid()) - index = m_bookmarksManager->bookmarksModel()->index(0, 0); - BookmarkNode *parent = m_bookmarksManager->bookmarksModel()->node(index); - BookmarkNode *bookmark = new BookmarkNode(BookmarkNode::Bookmark); - bookmark->url = m_url; - bookmark->title = name->text(); - m_bookmarksManager->addBookmark(parent, bookmark); - QDialog::accept(); -} - -BookmarksMenu::BookmarksMenu(QWidget *parent) - : ModelMenu(parent) - , m_bookmarksManager(0) -{ - connect(this, SIGNAL(activated(QModelIndex)), - this, SLOT(activated(QModelIndex))); - setMaxRows(-1); - setHoverRole(BookmarksModel::UrlStringRole); - setSeparatorRole(BookmarksModel::SeparatorRole); -} - -void BookmarksMenu::activated(const QModelIndex &index) -{ - emit openUrl(index.data(BookmarksModel::UrlRole).toUrl()); -} - -bool BookmarksMenu::prePopulated() -{ - m_bookmarksManager = BrowserApplication::bookmarksManager(); - setModel(m_bookmarksManager->bookmarksModel()); - setRootIndex(m_bookmarksManager->bookmarksModel()->index(1, 0)); - // initial actions - for (int i = 0; i < m_initialActions.count(); ++i) - addAction(m_initialActions.at(i)); - if (!m_initialActions.isEmpty()) - addSeparator(); - createMenu(model()->index(0, 0), 1, this); - return true; -} - -void BookmarksMenu::setInitialActions(QList actions) -{ - m_initialActions = actions; - for (int i = 0; i < m_initialActions.count(); ++i) - addAction(m_initialActions.at(i)); -} - -BookmarksDialog::BookmarksDialog(QWidget *parent, BookmarksManager *manager) - : QDialog(parent) -{ - m_bookmarksManager = manager; - if (!m_bookmarksManager) - m_bookmarksManager = BrowserApplication::bookmarksManager(); - setupUi(this); - - tree->setUniformRowHeights(true); - tree->setSelectionBehavior(QAbstractItemView::SelectRows); - tree->setSelectionMode(QAbstractItemView::ContiguousSelection); - tree->setTextElideMode(Qt::ElideMiddle); - m_bookmarksModel = m_bookmarksManager->bookmarksModel(); - m_proxyModel = new TreeProxyModel(this); - connect(search, SIGNAL(textChanged(QString)), - m_proxyModel, SLOT(setFilterFixedString(QString))); - connect(removeButton, SIGNAL(clicked()), tree, SLOT(removeOne())); - m_proxyModel->setSourceModel(m_bookmarksModel); - tree->setModel(m_proxyModel); - tree->setDragDropMode(QAbstractItemView::InternalMove); - tree->setExpanded(m_proxyModel->index(0, 0), true); - tree->setAlternatingRowColors(true); - QFontMetrics fm(font()); - int header = fm.width(QLatin1Char('m')) * 40; - tree->header()->resizeSection(0, header); - tree->header()->setStretchLastSection(true); - connect(tree, SIGNAL(activated(QModelIndex)), - this, SLOT(open())); - tree->setContextMenuPolicy(Qt::CustomContextMenu); - connect(tree, SIGNAL(customContextMenuRequested(QPoint)), - this, SLOT(customContextMenuRequested(QPoint))); - connect(addFolderButton, SIGNAL(clicked()), - this, SLOT(newFolder())); - expandNodes(m_bookmarksManager->bookmarks()); - setAttribute(Qt::WA_DeleteOnClose); -} - -BookmarksDialog::~BookmarksDialog() -{ - if (saveExpandedNodes(tree->rootIndex())) - m_bookmarksManager->changeExpanded(); -} - -bool BookmarksDialog::saveExpandedNodes(const QModelIndex &parent) -{ - bool changed = false; - for (int i = 0; i < m_proxyModel->rowCount(parent); ++i) { - QModelIndex child = m_proxyModel->index(i, 0, parent); - QModelIndex sourceIndex = m_proxyModel->mapToSource(child); - BookmarkNode *childNode = m_bookmarksModel->node(sourceIndex); - bool wasExpanded = childNode->expanded; - if (tree->isExpanded(child)) { - childNode->expanded = true; - changed |= saveExpandedNodes(child); - } else { - childNode->expanded = false; - } - changed |= (wasExpanded != childNode->expanded); - } - return changed; -} - -void BookmarksDialog::expandNodes(BookmarkNode *node) -{ - for (int i = 0; i < node->children().count(); ++i) { - BookmarkNode *childNode = node->children()[i]; - if (childNode->expanded) { - QModelIndex idx = m_bookmarksModel->index(childNode); - idx = m_proxyModel->mapFromSource(idx); - tree->setExpanded(idx, true); - expandNodes(childNode); - } - } -} - -void BookmarksDialog::customContextMenuRequested(const QPoint &pos) -{ - QMenu menu; - QModelIndex index = tree->indexAt(pos); - index = index.sibling(index.row(), 0); - if (index.isValid() && !tree->model()->hasChildren(index)) { - menu.addAction(tr("Open"), this, SLOT(open())); - menu.addSeparator(); - } - menu.addAction(tr("Delete"), tree, SLOT(removeOne())); - menu.exec(QCursor::pos()); -} - -void BookmarksDialog::open() -{ - QModelIndex index = tree->currentIndex(); - if (!index.parent().isValid()) - return; - emit openUrl(index.sibling(index.row(), 1).data(BookmarksModel::UrlRole).toUrl()); -} - -void BookmarksDialog::newFolder() -{ - QModelIndex currentIndex = tree->currentIndex(); - QModelIndex idx = currentIndex; - if (idx.isValid() && !idx.model()->hasChildren(idx)) - idx = idx.parent(); - if (!idx.isValid()) - idx = tree->rootIndex(); - idx = m_proxyModel->mapToSource(idx); - BookmarkNode *parent = m_bookmarksManager->bookmarksModel()->node(idx); - BookmarkNode *node = new BookmarkNode(BookmarkNode::Folder); - node->title = tr("New Folder"); - m_bookmarksManager->addBookmark(parent, node, currentIndex.row() + 1); -} - -BookmarksToolBar::BookmarksToolBar(BookmarksModel *model, QWidget *parent) - : QToolBar(tr("Bookmark"), parent) - , m_bookmarksModel(model) -{ - connect(this, SIGNAL(actionTriggered(QAction*)), this, SLOT(triggered(QAction*))); - setRootIndex(model->index(0, 0)); - connect(m_bookmarksModel, SIGNAL(modelReset()), this, SLOT(build())); - connect(m_bookmarksModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(build())); - connect(m_bookmarksModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(build())); - connect(m_bookmarksModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(build())); - setAcceptDrops(true); -} - -void BookmarksToolBar::dragEnterEvent(QDragEnterEvent *event) -{ - const QMimeData *mimeData = event->mimeData(); - if (mimeData->hasUrls()) - event->acceptProposedAction(); - QToolBar::dragEnterEvent(event); -} - -void BookmarksToolBar::dropEvent(QDropEvent *event) -{ - const QMimeData *mimeData = event->mimeData(); - if (mimeData->hasUrls() && mimeData->hasText()) { - QList urls = mimeData->urls(); - QAction *action = actionAt(event->pos()); - QString dropText; - if (action) - dropText = action->text(); - int row = -1; - QModelIndex parentIndex = m_root; - for (int i = 0; i < m_bookmarksModel->rowCount(m_root); ++i) { - QModelIndex idx = m_bookmarksModel->index(i, 0, m_root); - QString title = idx.data().toString(); - if (title == dropText) { - row = i; - if (m_bookmarksModel->hasChildren(idx)) { - parentIndex = idx; - row = -1; - } - break; - } - } - BookmarkNode *bookmark = new BookmarkNode(BookmarkNode::Bookmark); - bookmark->url = urls.at(0).toString(); - bookmark->title = mimeData->text(); - - BookmarkNode *parent = m_bookmarksModel->node(parentIndex); - BookmarksManager *bookmarksManager = m_bookmarksModel->bookmarksManager(); - bookmarksManager->addBookmark(parent, bookmark, row); - event->acceptProposedAction(); - } - QToolBar::dropEvent(event); -} - - -void BookmarksToolBar::setRootIndex(const QModelIndex &index) -{ - m_root = index; - build(); -} - -QModelIndex BookmarksToolBar::rootIndex() const -{ - return m_root; -} - -void BookmarksToolBar::build() -{ - clear(); - for (int i = 0; i < m_bookmarksModel->rowCount(m_root); ++i) { - QModelIndex idx = m_bookmarksModel->index(i, 0, m_root); - if (m_bookmarksModel->hasChildren(idx)) { - QToolButton *button = new QToolButton(this); - button->setPopupMode(QToolButton::InstantPopup); - button->setArrowType(Qt::DownArrow); - button->setText(idx.data().toString()); - ModelMenu *menu = new ModelMenu(this); - connect(menu, SIGNAL(activated(QModelIndex)), - this, SLOT(activated(QModelIndex))); - menu->setModel(m_bookmarksModel); - menu->setRootIndex(idx); - menu->addAction(new QAction(menu)); - button->setMenu(menu); - button->setToolButtonStyle(Qt::ToolButtonTextOnly); - QAction *a = addWidget(button); - a->setText(idx.data().toString()); - } else { - QAction *action = addAction(idx.data().toString()); - action->setData(idx.data(BookmarksModel::UrlRole)); - } - } -} - -void BookmarksToolBar::triggered(QAction *action) -{ - QVariant v = action->data(); - if (v.canConvert()) { - emit openUrl(v.toUrl()); - } -} - -void BookmarksToolBar::activated(const QModelIndex &index) -{ - emit openUrl(index.data(BookmarksModel::UrlRole).toUrl()); -} diff --git a/examples/widgets/browser/bookmarks.h b/examples/widgets/browser/bookmarks.h deleted file mode 100644 index be29666df..000000000 --- a/examples/widgets/browser/bookmarks.h +++ /dev/null @@ -1,309 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BOOKMARKS_H -#define BOOKMARKS_H - -#include -#include - -#include - -/*! - Bookmark manager, owner of the bookmarks, loads, saves and basic tasks - */ -class AutoSaver; -class BookmarkNode; -class BookmarksModel; -class BookmarksManager : public QObject -{ - Q_OBJECT - -signals: - void entryAdded(BookmarkNode *item); - void entryRemoved(BookmarkNode *parent, int row, BookmarkNode *item); - void entryChanged(BookmarkNode *item); - -public: - BookmarksManager(QObject *parent = 0); - ~BookmarksManager(); - - void addBookmark(BookmarkNode *parent, BookmarkNode *node, int row = -1); - void removeBookmark(BookmarkNode *node); - void setTitle(BookmarkNode *node, const QString &newTitle); - void setUrl(BookmarkNode *node, const QString &newUrl); - void changeExpanded(); - - BookmarkNode *bookmarks(); - BookmarkNode *menu(); - BookmarkNode *toolbar(); - - BookmarksModel *bookmarksModel(); - QUndoStack *undoRedoStack() { return &m_commands; }; - -public slots: - void importBookmarks(); - void exportBookmarks(); - -private slots: - void save() const; - -private: - void load(); - - bool m_loaded; - AutoSaver *m_saveTimer; - BookmarkNode *m_bookmarkRootNode; - BookmarksModel *m_bookmarkModel; - QUndoStack m_commands; - - friend class RemoveBookmarksCommand; - friend class ChangeBookmarkCommand; -}; - -class RemoveBookmarksCommand : public QUndoCommand -{ - -public: - RemoveBookmarksCommand(BookmarksManager *m_bookmarkManagaer, BookmarkNode *parent, int row); - ~RemoveBookmarksCommand(); - void undo(); - void redo(); - -protected: - int m_row; - BookmarksManager *m_bookmarkManagaer; - BookmarkNode *m_node; - BookmarkNode *m_parent; - bool m_done; -}; - -class InsertBookmarksCommand : public RemoveBookmarksCommand -{ - -public: - InsertBookmarksCommand(BookmarksManager *m_bookmarkManagaer, - BookmarkNode *parent, BookmarkNode *node, int row); - void undo() { RemoveBookmarksCommand::redo(); } - void redo() { RemoveBookmarksCommand::undo(); } - -}; - -class ChangeBookmarkCommand : public QUndoCommand -{ - -public: - ChangeBookmarkCommand(BookmarksManager *m_bookmarkManagaer, - BookmarkNode *node, const QString &newValue, bool title); - void undo(); - void redo(); - -private: - BookmarksManager *m_bookmarkManagaer; - bool m_title; - QString m_oldValue; - QString m_newValue; - BookmarkNode *m_node; -}; - -/*! - BookmarksModel is a QAbstractItemModel wrapper around the BookmarkManager - */ -class BookmarksModel : public QAbstractItemModel -{ - Q_OBJECT - -public slots: - void entryAdded(BookmarkNode *item); - void entryRemoved(BookmarkNode *parent, int row, BookmarkNode *item); - void entryChanged(BookmarkNode *item); - -public: - enum Roles { - TypeRole = Qt::UserRole + 1, - UrlRole = Qt::UserRole + 2, - UrlStringRole = Qt::UserRole + 3, - SeparatorRole = Qt::UserRole + 4 - }; - - BookmarksModel(BookmarksManager *bookmarkManager, QObject *parent = 0); - inline BookmarksManager *bookmarksManager() const { return m_bookmarksManager; } - - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - QModelIndex index(int, int, const QModelIndex& = QModelIndex()) const; - QModelIndex parent(const QModelIndex& index= QModelIndex()) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - Qt::DropActions supportedDropActions () const; - bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); - bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - QMimeData *mimeData(const QModelIndexList &indexes) const; - QStringList mimeTypes() const; - bool dropMimeData(const QMimeData *data, - Qt::DropAction action, int row, int column, const QModelIndex &parent); - bool hasChildren(const QModelIndex &parent = QModelIndex()) const; - - BookmarkNode *node(const QModelIndex &index) const; - QModelIndex index(BookmarkNode *node) const; - -private: - - bool m_endMacro; - BookmarksManager *m_bookmarksManager; -}; - -// Menu that is dynamically populated from the bookmarks -#include "modelmenu.h" -class BookmarksMenu : public ModelMenu -{ - Q_OBJECT - -signals: - void openUrl(const QUrl &url); - -public: - BookmarksMenu(QWidget *parent = 0); - void setInitialActions(QList actions); - -protected: - bool prePopulated(); - -private slots: - void activated(const QModelIndex &index); - -private: - BookmarksManager *m_bookmarksManager; - QList m_initialActions; -}; - -/* - Proxy model that filters out the bookmarks so only the folders - are left behind. Used in the add bookmark dialog combobox. - */ -#include -class AddBookmarkProxyModel : public QSortFilterProxyModel -{ - Q_OBJECT -public: - AddBookmarkProxyModel(QObject * parent = 0); - int columnCount(const QModelIndex & parent = QModelIndex()) const; - -protected: - bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; -}; - -/*! - Add bookmark dialog - */ -#include "ui_addbookmarkdialog.h" -class AddBookmarkDialog : public QDialog, public Ui_AddBookmarkDialog -{ - Q_OBJECT - -public: - AddBookmarkDialog(const QString &url, const QString &title, QWidget *parent = 0, BookmarksManager *bookmarkManager = 0); - -private slots: - void accept(); - -private: - QString m_url; - BookmarksManager *m_bookmarksManager; - AddBookmarkProxyModel *m_proxyModel; -}; - -#include "ui_bookmarks.h" -class TreeProxyModel; -class BookmarksDialog : public QDialog, public Ui_BookmarksDialog -{ - Q_OBJECT - -signals: - void openUrl(const QUrl &url); - -public: - BookmarksDialog(QWidget *parent = 0, BookmarksManager *manager = 0); - ~BookmarksDialog(); - -private slots: - void customContextMenuRequested(const QPoint &pos); - void open(); - void newFolder(); - -private: - void expandNodes(BookmarkNode *node); - bool saveExpandedNodes(const QModelIndex &parent); - - BookmarksManager *m_bookmarksManager; - BookmarksModel *m_bookmarksModel; - TreeProxyModel *m_proxyModel; -}; - -#include -class BookmarksToolBar : public QToolBar -{ - Q_OBJECT - -signals: - void openUrl(const QUrl &url); - -public: - BookmarksToolBar(BookmarksModel *model, QWidget *parent = 0); - void setRootIndex(const QModelIndex &index); - QModelIndex rootIndex() const; - -protected: - void dragEnterEvent(QDragEnterEvent *event); - void dropEvent(QDropEvent *event); - -private slots: - void triggered(QAction *action); - void activated(const QModelIndex &index); - void build(); - -private: - BookmarksModel *m_bookmarksModel; - QPersistentModelIndex m_root; -}; - -#endif // BOOKMARKS_H diff --git a/examples/widgets/browser/bookmarks.ui b/examples/widgets/browser/bookmarks.ui deleted file mode 100644 index c893e941d..000000000 --- a/examples/widgets/browser/bookmarks.ui +++ /dev/null @@ -1,106 +0,0 @@ - - BookmarksDialog - - - - 0 - 0 - 758 - 450 - - - - Bookmarks - - - - - - Qt::Horizontal - - - - 252 - 20 - - - - - - - - - - - - - - - - &Remove - - - - - - - Add Folder - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - QDialogButtonBox::Ok - - - - - - - - - - SearchLineEdit - QLineEdit -
searchlineedit.h
-
- - EditTreeView - QTreeView -
edittreeview.h
-
-
- - - - buttonBox - accepted() - BookmarksDialog - accept() - - - 472 - 329 - - - 461 - 356 - - - - -
diff --git a/examples/widgets/browser/browser.icns b/examples/widgets/browser/browser.icns deleted file mode 100644 index f591ae48a..000000000 Binary files a/examples/widgets/browser/browser.icns and /dev/null differ diff --git a/examples/widgets/browser/browser.ico b/examples/widgets/browser/browser.ico deleted file mode 100644 index 7f9be934d..000000000 Binary files a/examples/widgets/browser/browser.ico and /dev/null differ diff --git a/examples/widgets/browser/browser.pro b/examples/widgets/browser/browser.pro deleted file mode 100644 index 050e9fa83..000000000 --- a/examples/widgets/browser/browser.pro +++ /dev/null @@ -1,103 +0,0 @@ -TEMPLATE = app -TARGET = browser -QT += webenginewidgets network widgets printsupport - -macx: CONFIG -= app_bundle - -qtHaveModule(uitools):!embedded: QT += uitools -else: DEFINES += QT_NO_UITOOLS - -FORMS += \ - addbookmarkdialog.ui \ - bookmarks.ui \ - cookies.ui \ - cookiesexceptions.ui \ - downloaditem.ui \ - downloads.ui \ - history.ui \ - passworddialog.ui \ - proxy.ui \ - settings.ui - -HEADERS += \ - autosaver.h \ - bookmarks.h \ - browserapplication.h \ - browsermainwindow.h \ - chasewidget.h \ - downloadmanager.h \ - edittableview.h \ - edittreeview.h \ - history.h \ - modelmenu.h \ - searchlineedit.h \ - settings.h \ - squeezelabel.h \ - tabwidget.h \ - toolbarsearch.h \ - urllineedit.h \ - webview.h \ - xbel.h - -SOURCES += \ - autosaver.cpp \ - bookmarks.cpp \ - browserapplication.cpp \ - browsermainwindow.cpp \ - chasewidget.cpp \ - downloadmanager.cpp \ - edittableview.cpp \ - edittreeview.cpp \ - history.cpp \ - modelmenu.cpp \ - searchlineedit.cpp \ - settings.cpp \ - squeezelabel.cpp \ - tabwidget.cpp \ - toolbarsearch.cpp \ - urllineedit.cpp \ - webview.cpp \ - xbel.cpp \ - main.cpp - -RESOURCES += data/data.qrc htmls/htmls.qrc - -contains(DEFINES, QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) { - HEADERS += cookiejar.h networkaccessmanager.h - SOURCES += cookiejar.cpp networkaccessmanager.cpp -} - -build_all:!build_pass { - CONFIG -= build_all - CONFIG += release -} - -win32 { - RC_FILE = browser.rc -} - -mac { - ICON = browser.icns - QMAKE_INFO_PLIST = Info_mac.plist - TARGET = Browser - - # No 64-bit Flash on Mac, so build the browser 32-bit - contains(QT_CONFIG, x86) { - CONFIG -= x86_64 - CONFIG += x86 - } - contains(QT_CONFIG, ppc) { - CONFIG -= ppc64 - CONFIG += ppc - } -} - -wince*: { - DEPLOYMENT_PLUGIN += qjpeg qgif -} - -EXAMPLE_FILES = Info_mac.plist browser.icns browser.ico browser.rc - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/browser -INSTALLS += target diff --git a/examples/widgets/browser/browser.rc b/examples/widgets/browser/browser.rc deleted file mode 100644 index 39e17e973..000000000 --- a/examples/widgets/browser/browser.rc +++ /dev/null @@ -1 +0,0 @@ -IDI_ICON1 ICON DISCARDABLE "browser.ico" diff --git a/examples/widgets/browser/browserapplication.cpp b/examples/widgets/browser/browserapplication.cpp deleted file mode 100644 index da96b65b9..000000000 --- a/examples/widgets/browser/browserapplication.cpp +++ /dev/null @@ -1,472 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "browserapplication.h" - -#include "bookmarks.h" -#include "browsermainwindow.h" -#include "cookiejar.h" -#include "downloadmanager.h" -#include "history.h" -#include "networkaccessmanager.h" -#include "tabwidget.h" -#include "webview.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include - -DownloadManager *BrowserApplication::s_downloadManager = 0; -HistoryManager *BrowserApplication::s_historyManager = 0; -NetworkAccessManager *BrowserApplication::s_networkAccessManager = 0; -BookmarksManager *BrowserApplication::s_bookmarksManager = 0; - -BrowserApplication::BrowserApplication(int &argc, char **argv) - : QApplication(argc, argv) - , m_localServer(0) -{ - QCoreApplication::setOrganizationName(QLatin1String("Qt")); - QCoreApplication::setApplicationName(QLatin1String("demobrowser")); - QCoreApplication::setApplicationVersion(QLatin1String("0.1")); -#ifdef Q_WS_QWS - // Use a different server name for QWS so we can run an X11 - // browser and a QWS browser in parallel on the same machine for - // debugging - QString serverName = QCoreApplication::applicationName() + QLatin1String("_qws"); -#else - QString serverName = QCoreApplication::applicationName(); -#endif - QLocalSocket socket; - socket.connectToServer(serverName); - if (socket.waitForConnected(500)) { - QTextStream stream(&socket); - QStringList args = QCoreApplication::arguments(); - if (args.count() > 1) - stream << args.last(); - else - stream << QString(); - stream.flush(); - socket.waitForBytesWritten(); - return; - } - -#if defined(Q_WS_MAC) - QApplication::setQuitOnLastWindowClosed(false); -#else - QApplication::setQuitOnLastWindowClosed(true); -#endif - - m_localServer = new QLocalServer(this); - connect(m_localServer, SIGNAL(newConnection()), - this, SLOT(newLocalSocketConnection())); - if (!m_localServer->listen(serverName)) { - if (m_localServer->serverError() == QAbstractSocket::AddressInUseError - && QFile::exists(m_localServer->serverName())) { - QFile::remove(m_localServer->serverName()); - m_localServer->listen(serverName); - } - } - -#ifndef QT_NO_OPENSSL - if (!QSslSocket::supportsSsl()) { - QMessageBox::information(0, "Demo Browser", - "This system does not support OpenSSL. SSL websites will not be available."); - } -#endif - - QDesktopServices::setUrlHandler(QLatin1String("http"), this, "openUrl"); - QString localSysName = QLocale::system().name(); - - installTranslator(QLatin1String("qt_") + localSysName); - - QSettings settings; - settings.beginGroup(QLatin1String("sessions")); - m_lastSession = settings.value(QLatin1String("lastSession")).toByteArray(); - settings.endGroup(); - -#if defined(Q_WS_MAC) - connect(this, SIGNAL(lastWindowClosed()), - this, SLOT(lastWindowClosed())); -#endif - - QTimer::singleShot(0, this, SLOT(postLaunch())); -} - -BrowserApplication::~BrowserApplication() -{ - delete s_downloadManager; - for (int i = 0; i < m_mainWindows.size(); ++i) { - BrowserMainWindow *window = m_mainWindows.at(i); - delete window; - } - delete s_networkAccessManager; - delete s_bookmarksManager; -} - -#if defined(Q_WS_MAC) -void BrowserApplication::lastWindowClosed() -{ - clean(); - BrowserMainWindow *mw = new BrowserMainWindow; - mw->slotHome(); - m_mainWindows.prepend(mw); -} -#endif - -BrowserApplication *BrowserApplication::instance() -{ - return (static_cast(QCoreApplication::instance())); -} - -#if defined(Q_WS_MAC) -#include -void BrowserApplication::quitBrowser() -{ - clean(); - int tabCount = 0; - for (int i = 0; i < m_mainWindows.count(); ++i) { - tabCount =+ m_mainWindows.at(i)->tabWidget()->count(); - } - - if (tabCount > 1) { - int ret = QMessageBox::warning(mainWindow(), QString(), - tr("There are %1 windows and %2 tabs open\n" - "Do you want to quit anyway?").arg(m_mainWindows.count()).arg(tabCount), - QMessageBox::Yes | QMessageBox::No, - QMessageBox::No); - if (ret == QMessageBox::No) - return; - } - - exit(0); -} -#endif - -/*! - Any actions that can be delayed until the window is visible - */ -void BrowserApplication::postLaunch() -{ -#if defined(QWEBENGINESETTINGS) - QString directory = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - if (directory.isEmpty()) - directory = QDir::homePath() + QLatin1String("/.") + QCoreApplication::applicationName(); - QWebEngineSettings::setIconDatabasePath(directory); - QWebEngineSettings::setOfflineStoragePath(directory); -#endif - - setWindowIcon(QIcon(QLatin1String(":browser.svg"))); - - loadSettings(); - - // newMainWindow() needs to be called in main() for this to happen - if (m_mainWindows.count() > 0) { - QStringList args = QCoreApplication::arguments(); - if (args.count() > 1) - mainWindow()->loadPage(args.last()); - else - mainWindow()->slotHome(); - } - BrowserApplication::historyManager(); -} - -void BrowserApplication::loadSettings() -{ -#if defined(QWEBENGINESETTINGS) - QSettings settings; - settings.beginGroup(QLatin1String("websettings")); - - QWebEngineSettings *defaultSettings = QWebEngineSettings::globalSettings(); - QString standardFontFamily = defaultSettings->fontFamily(QWebEngineSettings::StandardFont); - int standardFontSize = defaultSettings->fontSize(QWebEngineSettings::DefaultFontSize); - QFont standardFont = QFont(standardFontFamily, standardFontSize); - standardFont = qvariant_cast(settings.value(QLatin1String("standardFont"), standardFont)); - defaultSettings->setFontFamily(QWebEngineSettings::StandardFont, standardFont.family()); - defaultSettings->setFontSize(QWebEngineSettings::DefaultFontSize, standardFont.pointSize()); - - QString fixedFontFamily = defaultSettings->fontFamily(QWebEngineSettings::FixedFont); - int fixedFontSize = defaultSettings->fontSize(QWebEngineSettings::DefaultFixedFontSize); - QFont fixedFont = QFont(fixedFontFamily, fixedFontSize); - fixedFont = qvariant_cast(settings.value(QLatin1String("fixedFont"), fixedFont)); - defaultSettings->setFontFamily(QWebEngineSettings::FixedFont, fixedFont.family()); - defaultSettings->setFontSize(QWebEngineSettings::DefaultFixedFontSize, fixedFont.pointSize()); - - defaultSettings->setAttribute(QWebEngineSettings::JavascriptEnabled, settings.value(QLatin1String("enableJavascript"), true).toBool()); - defaultSettings->setAttribute(QWebEngineSettings::PluginsEnabled, settings.value(QLatin1String("enablePlugins"), true).toBool()); - - QUrl url = settings.value(QLatin1String("userStyleSheet")).toUrl(); - defaultSettings->setUserStyleSheetUrl(url); - - defaultSettings->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, true); - - settings.endGroup(); -#endif -} - -QList BrowserApplication::mainWindows() -{ - clean(); - QList list; - for (int i = 0; i < m_mainWindows.count(); ++i) - list.append(m_mainWindows.at(i)); - return list; -} - -void BrowserApplication::clean() -{ - // cleanup any deleted main windows first - for (int i = m_mainWindows.count() - 1; i >= 0; --i) - if (m_mainWindows.at(i).isNull()) - m_mainWindows.removeAt(i); -} - -void BrowserApplication::saveSession() -{ -#if defined(QWEBENGINESETTINGS) - QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); - if (globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) - return; -#endif - - clean(); - - QSettings settings; - settings.beginGroup(QLatin1String("sessions")); - - QByteArray data; - QBuffer buffer(&data); - QDataStream stream(&buffer); - buffer.open(QIODevice::ReadWrite); - - stream << m_mainWindows.count(); - for (int i = 0; i < m_mainWindows.count(); ++i) - stream << m_mainWindows.at(i)->saveState(); - settings.setValue(QLatin1String("lastSession"), data); - settings.endGroup(); -} - -bool BrowserApplication::canRestoreSession() const -{ - return !m_lastSession.isEmpty(); -} - -void BrowserApplication::restoreLastSession() -{ - QList windows; - QBuffer buffer(&m_lastSession); - QDataStream stream(&buffer); - buffer.open(QIODevice::ReadOnly); - int windowCount; - stream >> windowCount; - for (int i = 0; i < windowCount; ++i) { - QByteArray windowState; - stream >> windowState; - windows.append(windowState); - } - for (int i = 0; i < windows.count(); ++i) { - BrowserMainWindow *newWindow = 0; - if (m_mainWindows.count() == 1 - && mainWindow()->tabWidget()->count() == 1 - && mainWindow()->currentTab()->url() == QUrl()) { - newWindow = mainWindow(); - } else { - newWindow = newMainWindow(); - } - newWindow->restoreState(windows.at(i)); - } -} - -bool BrowserApplication::isTheOnlyBrowser() const -{ - return (m_localServer != 0); -} - -void BrowserApplication::installTranslator(const QString &name) -{ - QTranslator *translator = new QTranslator(this); - translator->load(name, QLibraryInfo::location(QLibraryInfo::TranslationsPath)); - QApplication::installTranslator(translator); -} - -#if defined(Q_WS_MAC) -bool BrowserApplication::event(QEvent* event) -{ - switch (event->type()) { - case QEvent::ApplicationActivate: { - clean(); - if (!m_mainWindows.isEmpty()) { - BrowserMainWindow *mw = mainWindow(); - if (mw && !mw->isMinimized()) { - mainWindow()->show(); - } - return true; - } - } - case QEvent::FileOpen: - if (!m_mainWindows.isEmpty()) { - mainWindow()->loadPage(static_cast(event)->file()); - return true; - } - default: - break; - } - return QApplication::event(event); -} -#endif - -void BrowserApplication::openUrl(const QUrl &url) -{ - mainWindow()->loadPage(url.toString()); -} - -BrowserMainWindow *BrowserApplication::newMainWindow() -{ - BrowserMainWindow *browser = new BrowserMainWindow(); - m_mainWindows.prepend(browser); - browser->show(); - return browser; -} - -BrowserMainWindow *BrowserApplication::mainWindow() -{ - clean(); - if (m_mainWindows.isEmpty()) - newMainWindow(); - return m_mainWindows[0]; -} - -void BrowserApplication::newLocalSocketConnection() -{ - QLocalSocket *socket = m_localServer->nextPendingConnection(); - if (!socket) - return; - socket->waitForReadyRead(1000); - QTextStream stream(socket); - QString url; - stream >> url; - if (!url.isEmpty()) { - QSettings settings; - settings.beginGroup(QLatin1String("general")); - int openLinksIn = settings.value(QLatin1String("openLinksIn"), 0).toInt(); - settings.endGroup(); - if (openLinksIn == 1) - newMainWindow(); - else - mainWindow()->tabWidget()->newTab(); - openUrl(url); - } - delete socket; - mainWindow()->raise(); - mainWindow()->activateWindow(); -} - -CookieJar *BrowserApplication::cookieJar() -{ -#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) - return (CookieJar*)networkAccessManager()->cookieJar(); -#else - return 0; -#endif -} - -DownloadManager *BrowserApplication::downloadManager() -{ - if (!s_downloadManager) { - s_downloadManager = new DownloadManager(); - } - return s_downloadManager; -} - -NetworkAccessManager *BrowserApplication::networkAccessManager() -{ -#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) - if (!s_networkAccessManager) { - s_networkAccessManager = new NetworkAccessManager(); - s_networkAccessManager->setCookieJar(new CookieJar); - } - return s_networkAccessManager; -#else - return 0; -#endif -} - -HistoryManager *BrowserApplication::historyManager() -{ - if (!s_historyManager) - s_historyManager = new HistoryManager(); - return s_historyManager; -} - -BookmarksManager *BrowserApplication::bookmarksManager() -{ - if (!s_bookmarksManager) { - s_bookmarksManager = new BookmarksManager; - } - return s_bookmarksManager; -} - -QIcon BrowserApplication::icon(const QUrl &url) const -{ -#if defined(QWEBENGINESETTINGS) - QIcon icon = QWebEngineSettings::iconForUrl(url); - if (!icon.isNull()) - return icon.pixmap(16, 16); -#endif - if (m_defaultIcon.isNull()) - m_defaultIcon = QIcon(QLatin1String(":defaulticon.png")); - return m_defaultIcon.pixmap(16, 16); -} diff --git a/examples/widgets/browser/browserapplication.h b/examples/widgets/browser/browserapplication.h deleted file mode 100644 index b17f1cea5..000000000 --- a/examples/widgets/browser/browserapplication.h +++ /dev/null @@ -1,118 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BROWSERAPPLICATION_H -#define BROWSERAPPLICATION_H - -#include - -#include -#include - -#include - -QT_BEGIN_NAMESPACE -class QLocalServer; -QT_END_NAMESPACE - -class BookmarksManager; -class BrowserMainWindow; -class CookieJar; -class DownloadManager; -class HistoryManager; -class NetworkAccessManager; -class BrowserApplication : public QApplication -{ - Q_OBJECT - -public: - BrowserApplication(int &argc, char **argv); - ~BrowserApplication(); - static BrowserApplication *instance(); - void loadSettings(); - - bool isTheOnlyBrowser() const; - BrowserMainWindow *mainWindow(); - QList mainWindows(); - QIcon icon(const QUrl &url) const; - - void saveSession(); - bool canRestoreSession() const; - - static HistoryManager *historyManager(); - static CookieJar *cookieJar(); - static DownloadManager *downloadManager(); - static NetworkAccessManager *networkAccessManager(); - static BookmarksManager *bookmarksManager(); - -#if defined(Q_WS_MAC) - bool event(QEvent *event); -#endif - -public slots: - BrowserMainWindow *newMainWindow(); - void restoreLastSession(); -#if defined(Q_WS_MAC) - void lastWindowClosed(); - void quitBrowser(); -#endif - -private slots: - void postLaunch(); - void openUrl(const QUrl &url); - void newLocalSocketConnection(); - -private: - void clean(); - void installTranslator(const QString &name); - - static HistoryManager *s_historyManager; - static DownloadManager *s_downloadManager; - static NetworkAccessManager *s_networkAccessManager; - static BookmarksManager *s_bookmarksManager; - - QList > m_mainWindows; - QLocalServer *m_localServer; - QByteArray m_lastSession; - mutable QIcon m_defaultIcon; -}; - -#endif // BROWSERAPPLICATION_H diff --git a/examples/widgets/browser/browsermainwindow.cpp b/examples/widgets/browser/browsermainwindow.cpp deleted file mode 100644 index 3cee14e9e..000000000 --- a/examples/widgets/browser/browsermainwindow.cpp +++ /dev/null @@ -1,993 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "browsermainwindow.h" - -#include "autosaver.h" -#include "bookmarks.h" -#include "browserapplication.h" -#include "chasewidget.h" -#include "downloadmanager.h" -#include "history.h" -#include "settings.h" -#include "tabwidget.h" -#include "toolbarsearch.h" -#include "ui_passworddialog.h" -#include "webview.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -template -struct InvokeWrapper { - R *receiver; - void (C::*memberFun)(Arg); - void operator()(Arg result) { - (receiver->*memberFun)(result); - } -}; - -template -InvokeWrapper invoke(R *receiver, void (C::*memberFun)(Arg)) -{ - InvokeWrapper wrapper = {receiver, memberFun}; - return wrapper; -} - -BrowserMainWindow::BrowserMainWindow(QWidget *parent, Qt::WindowFlags flags) - : QMainWindow(parent, flags) - , m_tabWidget(new TabWidget(this)) - , m_autoSaver(new AutoSaver(this)) - , m_historyBack(0) - , m_historyForward(0) - , m_stop(0) - , m_reload(0) -{ - setToolButtonStyle(Qt::ToolButtonFollowStyle); - setAttribute(Qt::WA_DeleteOnClose, true); - statusBar()->setSizeGripEnabled(true); - setupMenu(); - setupToolBar(); - - QWidget *centralWidget = new QWidget(this); - BookmarksModel *boomarksModel = BrowserApplication::bookmarksManager()->bookmarksModel(); - m_bookmarksToolbar = new BookmarksToolBar(boomarksModel, this); - connect(m_bookmarksToolbar, SIGNAL(openUrl(QUrl)), - m_tabWidget, SLOT(loadUrlInCurrentTab(QUrl))); - connect(m_bookmarksToolbar->toggleViewAction(), SIGNAL(toggled(bool)), - this, SLOT(updateBookmarksToolbarActionText(bool))); - - QVBoxLayout *layout = new QVBoxLayout; - layout->setSpacing(0); - layout->setMargin(0); -#if defined(Q_WS_MAC) - layout->addWidget(m_bookmarksToolbar); - layout->addWidget(new QWidget); // <- OS X tab widget style bug -#else - addToolBarBreak(); - addToolBar(m_bookmarksToolbar); -#endif - layout->addWidget(m_tabWidget); - centralWidget->setLayout(layout); - setCentralWidget(centralWidget); - - connect(m_tabWidget, SIGNAL(loadPage(QString)), - this, SLOT(loadPage(QString))); - connect(m_tabWidget, SIGNAL(setCurrentTitle(QString)), - this, SLOT(slotUpdateWindowTitle(QString))); - connect(m_tabWidget, SIGNAL(showStatusBarMessage(QString)), - statusBar(), SLOT(showMessage(QString))); - connect(m_tabWidget, SIGNAL(linkHovered(QString)), - statusBar(), SLOT(showMessage(QString))); - connect(m_tabWidget, SIGNAL(loadProgress(int)), - this, SLOT(slotLoadProgress(int))); - connect(m_tabWidget, SIGNAL(tabsChanged()), - m_autoSaver, SLOT(changeOccurred())); - connect(m_tabWidget, SIGNAL(geometryChangeRequested(QRect)), - this, SLOT(geometryChangeRequested(QRect))); - connect(m_tabWidget, SIGNAL(printRequested(QWebEngineFrame*)), - this, SLOT(printRequested(QWebEngineFrame*))); - connect(m_tabWidget, SIGNAL(menuBarVisibilityChangeRequested(bool)), - menuBar(), SLOT(setVisible(bool))); - connect(m_tabWidget, SIGNAL(statusBarVisibilityChangeRequested(bool)), - statusBar(), SLOT(setVisible(bool))); - connect(m_tabWidget, SIGNAL(toolBarVisibilityChangeRequested(bool)), - m_navigationBar, SLOT(setVisible(bool))); - connect(m_tabWidget, SIGNAL(toolBarVisibilityChangeRequested(bool)), - m_bookmarksToolbar, SLOT(setVisible(bool))); -#if defined(Q_WS_MAC) - connect(m_tabWidget, SIGNAL(lastTabClosed()), - this, SLOT(close())); -#else - connect(m_tabWidget, SIGNAL(lastTabClosed()), - m_tabWidget, SLOT(newTab())); -#endif - - slotUpdateWindowTitle(); - loadDefaultState(); - m_tabWidget->newTab(); - - int size = m_tabWidget->lineEditStack()->sizeHint().height(); - m_navigationBar->setIconSize(QSize(size, size)); - -} - -BrowserMainWindow::~BrowserMainWindow() -{ - m_autoSaver->changeOccurred(); - m_autoSaver->saveIfNeccessary(); -} - -void BrowserMainWindow::loadDefaultState() -{ - QSettings settings; - settings.beginGroup(QLatin1String("BrowserMainWindow")); - QByteArray data = settings.value(QLatin1String("defaultState")).toByteArray(); - restoreState(data); - settings.endGroup(); -} - -QSize BrowserMainWindow::sizeHint() const -{ - QRect desktopRect = QApplication::desktop()->screenGeometry(); - QSize size = desktopRect.size() * qreal(0.9); - return size; -} - -void BrowserMainWindow::save() -{ - BrowserApplication::instance()->saveSession(); - - QSettings settings; - settings.beginGroup(QLatin1String("BrowserMainWindow")); - QByteArray data = saveState(false); - settings.setValue(QLatin1String("defaultState"), data); - settings.endGroup(); -} - -static const qint32 BrowserMainWindowMagic = 0xba; - -QByteArray BrowserMainWindow::saveState(bool withTabs) const -{ - int version = 2; - QByteArray data; - QDataStream stream(&data, QIODevice::WriteOnly); - - stream << qint32(BrowserMainWindowMagic); - stream << qint32(version); - - stream << size(); - stream << !m_navigationBar->isHidden(); - stream << !m_bookmarksToolbar->isHidden(); - stream << !statusBar()->isHidden(); - if (withTabs) - stream << tabWidget()->saveState(); - else - stream << QByteArray(); - return data; -} - -bool BrowserMainWindow::restoreState(const QByteArray &state) -{ - int version = 2; - QByteArray sd = state; - QDataStream stream(&sd, QIODevice::ReadOnly); - if (stream.atEnd()) - return false; - - qint32 marker; - qint32 v; - stream >> marker; - stream >> v; - if (marker != BrowserMainWindowMagic || v != version) - return false; - - QSize size; - bool showToolbar; - bool showBookmarksBar; - bool showStatusbar; - QByteArray tabState; - - stream >> size; - stream >> showToolbar; - stream >> showBookmarksBar; - stream >> showStatusbar; - stream >> tabState; - - resize(size); - - m_navigationBar->setVisible(showToolbar); - updateToolbarActionText(showToolbar); - - m_bookmarksToolbar->setVisible(showBookmarksBar); - updateBookmarksToolbarActionText(showBookmarksBar); - - statusBar()->setVisible(showStatusbar); - updateStatusbarActionText(showStatusbar); - - if (!tabWidget()->restoreState(tabState)) - return false; - - return true; -} - -void BrowserMainWindow::setupMenu() -{ - new QShortcut(QKeySequence(Qt::Key_F6), this, SLOT(slotSwapFocus())); - - // File - QMenu *fileMenu = menuBar()->addMenu(tr("&File")); - - fileMenu->addAction(tr("&New Window"), this, SLOT(slotFileNew()), QKeySequence::New); - fileMenu->addAction(m_tabWidget->newTabAction()); - fileMenu->addAction(tr("&Open File..."), this, SLOT(slotFileOpen()), QKeySequence::Open); - fileMenu->addAction(tr("Open &Location..."), this, - SLOT(slotSelectLineEdit()), QKeySequence(Qt::ControlModifier + Qt::Key_L)); - fileMenu->addSeparator(); - fileMenu->addAction(m_tabWidget->closeTabAction()); - fileMenu->addSeparator(); -#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) - fileMenu->addAction(tr("&Save As..."), this, - SLOT(slotFileSaveAs()), QKeySequence(QKeySequence::Save)); - fileMenu->addSeparator(); -#endif - BookmarksManager *bookmarksManager = BrowserApplication::bookmarksManager(); - fileMenu->addAction(tr("&Import Bookmarks..."), bookmarksManager, SLOT(importBookmarks())); - fileMenu->addAction(tr("&Export Bookmarks..."), bookmarksManager, SLOT(exportBookmarks())); - fileMenu->addSeparator(); -#if defined(QWEBENGINEPAGE_PRINT) - fileMenu->addAction(tr("P&rint Preview..."), this, SLOT(slotFilePrintPreview())); - fileMenu->addAction(tr("&Print..."), this, SLOT(slotFilePrint()), QKeySequence::Print); - fileMenu->addSeparator(); -#endif -#if defined(QWEBENGINESETTINGS) - QAction *action = fileMenu->addAction(tr("Private &Browsing..."), this, SLOT(slotPrivateBrowsing())); - action->setCheckable(true); - fileMenu->addSeparator(); -#endif - -#if defined(Q_WS_MAC) - fileMenu->addAction(tr("&Quit"), BrowserApplication::instance(), SLOT(quitBrowser()), QKeySequence(Qt::CTRL | Qt::Key_Q)); -#else - fileMenu->addAction(tr("&Quit"), this, SLOT(close()), QKeySequence(Qt::CTRL | Qt::Key_Q)); -#endif - - // Edit - QMenu *editMenu = menuBar()->addMenu(tr("&Edit")); - QAction *m_undo = editMenu->addAction(tr("&Undo")); - m_undo->setShortcuts(QKeySequence::Undo); - m_tabWidget->addWebAction(m_undo, QWebEnginePage::Undo); - QAction *m_redo = editMenu->addAction(tr("&Redo")); - m_redo->setShortcuts(QKeySequence::Redo); - m_tabWidget->addWebAction(m_redo, QWebEnginePage::Redo); - editMenu->addSeparator(); - QAction *m_cut = editMenu->addAction(tr("Cu&t")); - m_cut->setShortcuts(QKeySequence::Cut); - m_tabWidget->addWebAction(m_cut, QWebEnginePage::Cut); - QAction *m_copy = editMenu->addAction(tr("&Copy")); - m_copy->setShortcuts(QKeySequence::Copy); - m_tabWidget->addWebAction(m_copy, QWebEnginePage::Copy); - QAction *m_paste = editMenu->addAction(tr("&Paste")); - m_paste->setShortcuts(QKeySequence::Paste); - m_tabWidget->addWebAction(m_paste, QWebEnginePage::Paste); - editMenu->addSeparator(); - - QAction *m_find = editMenu->addAction(tr("&Find")); - m_find->setShortcuts(QKeySequence::Find); - connect(m_find, SIGNAL(triggered()), this, SLOT(slotEditFind())); - new QShortcut(QKeySequence(Qt::Key_Slash), this, SLOT(slotEditFind())); - - QAction *m_findNext = editMenu->addAction(tr("&Find Next")); - m_findNext->setShortcuts(QKeySequence::FindNext); - connect(m_findNext, SIGNAL(triggered()), this, SLOT(slotEditFindNext())); - - QAction *m_findPrevious = editMenu->addAction(tr("&Find Previous")); - m_findPrevious->setShortcuts(QKeySequence::FindPrevious); - connect(m_findPrevious, SIGNAL(triggered()), this, SLOT(slotEditFindPrevious())); - editMenu->addSeparator(); - - editMenu->addAction(tr("&Preferences"), this, SLOT(slotPreferences()), tr("Ctrl+,")); - - // View - QMenu *viewMenu = menuBar()->addMenu(tr("&View")); - - m_viewBookmarkBar = new QAction(this); - updateBookmarksToolbarActionText(true); - m_viewBookmarkBar->setShortcut(tr("Shift+Ctrl+B")); - connect(m_viewBookmarkBar, SIGNAL(triggered()), this, SLOT(slotViewBookmarksBar())); - viewMenu->addAction(m_viewBookmarkBar); - - m_viewToolbar = new QAction(this); - updateToolbarActionText(true); - m_viewToolbar->setShortcut(tr("Ctrl+|")); - connect(m_viewToolbar, SIGNAL(triggered()), this, SLOT(slotViewToolbar())); - viewMenu->addAction(m_viewToolbar); - - m_viewStatusbar = new QAction(this); - updateStatusbarActionText(true); - m_viewStatusbar->setShortcut(tr("Ctrl+/")); - connect(m_viewStatusbar, SIGNAL(triggered()), this, SLOT(slotViewStatusbar())); - viewMenu->addAction(m_viewStatusbar); - - viewMenu->addSeparator(); - - m_stop = viewMenu->addAction(tr("&Stop")); - QList shortcuts; - shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_Period)); - shortcuts.append(Qt::Key_Escape); - m_stop->setShortcuts(shortcuts); - m_tabWidget->addWebAction(m_stop, QWebEnginePage::Stop); - - m_reload = viewMenu->addAction(tr("Reload Page")); - m_reload->setShortcuts(QKeySequence::Refresh); - m_tabWidget->addWebAction(m_reload, QWebEnginePage::Reload); - - viewMenu->addAction(tr("Zoom &In"), this, SLOT(slotViewZoomIn()), QKeySequence(Qt::CTRL | Qt::Key_Plus)); - viewMenu->addAction(tr("Zoom &Out"), this, SLOT(slotViewZoomOut()), QKeySequence(Qt::CTRL | Qt::Key_Minus)); - viewMenu->addAction(tr("Reset &Zoom"), this, SLOT(slotViewResetZoom()), QKeySequence(Qt::CTRL | Qt::Key_0)); -#if defined(QWEBENGINESETTINGS) - QAction *zoomTextOnlyAction = viewMenu->addAction(tr("Zoom &Text Only")); - connect(zoomTextOnlyAction, SIGNAL(toggled(bool)), this, SLOT(slotViewZoomTextOnly(bool))); - zoomTextOnlyAction->setCheckable(true); - zoomTextOnlyAction->setChecked(false); -#endif - - viewMenu->addSeparator(); - viewMenu->addAction(tr("Page S&ource"), this, SLOT(slotViewPageSource()), tr("Ctrl+Alt+U")); - QAction *a = viewMenu->addAction(tr("&Full Screen"), this, SLOT(slotViewFullScreen(bool)), Qt::Key_F11); - a->setCheckable(true); - - // History - HistoryMenu *historyMenu = new HistoryMenu(this); - connect(historyMenu, SIGNAL(openUrl(QUrl)), - m_tabWidget, SLOT(loadUrlInCurrentTab(QUrl))); - connect(historyMenu, SIGNAL(hovered(QString)), this, - SLOT(slotUpdateStatusbar(QString))); - historyMenu->setTitle(tr("Hi&story")); - menuBar()->addMenu(historyMenu); - QList historyActions; - - m_historyBack = new QAction(tr("Back"), this); - m_tabWidget->addWebAction(m_historyBack, QWebEnginePage::Back); - m_historyBack->setShortcuts(QKeySequence::Back); - m_historyBack->setIconVisibleInMenu(false); - historyActions.append(m_historyBack); - - m_historyForward = new QAction(tr("Forward"), this); - m_tabWidget->addWebAction(m_historyForward, QWebEnginePage::Forward); - m_historyForward->setShortcuts(QKeySequence::Forward); - m_historyForward->setIconVisibleInMenu(false); - historyActions.append(m_historyForward); - - QAction *m_historyHome = new QAction(tr("Home"), this); - connect(m_historyHome, SIGNAL(triggered()), this, SLOT(slotHome())); - m_historyHome->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_H)); - historyActions.append(m_historyHome); - -#if defined(QWEBENGINEHISTORY_RESTORESESSION) - m_restoreLastSession = new QAction(tr("Restore Last Session"), this); - connect(m_restoreLastSession, SIGNAL(triggered()), BrowserApplication::instance(), SLOT(restoreLastSession())); - m_restoreLastSession->setEnabled(BrowserApplication::instance()->canRestoreSession()); - historyActions.append(m_tabWidget->recentlyClosedTabsAction()); - historyActions.append(m_restoreLastSession); -#endif - - historyMenu->setInitialActions(historyActions); - - // Bookmarks - BookmarksMenu *bookmarksMenu = new BookmarksMenu(this); - connect(bookmarksMenu, SIGNAL(openUrl(QUrl)), - m_tabWidget, SLOT(loadUrlInCurrentTab(QUrl))); - connect(bookmarksMenu, SIGNAL(hovered(QString)), - this, SLOT(slotUpdateStatusbar(QString))); - bookmarksMenu->setTitle(tr("&Bookmarks")); - menuBar()->addMenu(bookmarksMenu); - - QList bookmarksActions; - - QAction *showAllBookmarksAction = new QAction(tr("Show All Bookmarks"), this); - connect(showAllBookmarksAction, SIGNAL(triggered()), this, SLOT(slotShowBookmarksDialog())); - m_addBookmark = new QAction(QIcon(QLatin1String(":addbookmark.png")), tr("Add Bookmark..."), this); - m_addBookmark->setIconVisibleInMenu(false); - - connect(m_addBookmark, SIGNAL(triggered()), this, SLOT(slotAddBookmark())); - m_addBookmark->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_D)); - - bookmarksActions.append(showAllBookmarksAction); - bookmarksActions.append(m_addBookmark); - bookmarksMenu->setInitialActions(bookmarksActions); - - // Window - m_windowMenu = menuBar()->addMenu(tr("&Window")); - connect(m_windowMenu, SIGNAL(aboutToShow()), - this, SLOT(slotAboutToShowWindowMenu())); - slotAboutToShowWindowMenu(); - - QMenu *toolsMenu = menuBar()->addMenu(tr("&Tools")); - toolsMenu->addAction(tr("Web &Search"), this, SLOT(slotWebSearch()), QKeySequence(tr("Ctrl+K", "Web Search"))); -#if defined(QWEBENGINEINSPECTOR) - a = toolsMenu->addAction(tr("Enable Web &Inspector"), this, SLOT(slotToggleInspector(bool))); - a->setCheckable(true); -#endif - - QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); - helpMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt())); - helpMenu->addAction(tr("About &Demo Browser"), this, SLOT(slotAboutApplication())); -} - -void BrowserMainWindow::setupToolBar() -{ - setUnifiedTitleAndToolBarOnMac(true); - m_navigationBar = addToolBar(tr("Navigation")); - connect(m_navigationBar->toggleViewAction(), SIGNAL(toggled(bool)), - this, SLOT(updateToolbarActionText(bool))); - - m_historyBack->setIcon(style()->standardIcon(QStyle::SP_ArrowBack, 0, this)); - m_historyBackMenu = new QMenu(this); - m_historyBack->setMenu(m_historyBackMenu); - connect(m_historyBackMenu, SIGNAL(aboutToShow()), - this, SLOT(slotAboutToShowBackMenu())); - connect(m_historyBackMenu, SIGNAL(triggered(QAction*)), - this, SLOT(slotOpenActionUrl(QAction*))); - m_navigationBar->addAction(m_historyBack); - - m_historyForward->setIcon(style()->standardIcon(QStyle::SP_ArrowForward, 0, this)); - m_historyForwardMenu = new QMenu(this); - connect(m_historyForwardMenu, SIGNAL(aboutToShow()), - this, SLOT(slotAboutToShowForwardMenu())); - connect(m_historyForwardMenu, SIGNAL(triggered(QAction*)), - this, SLOT(slotOpenActionUrl(QAction*))); - m_historyForward->setMenu(m_historyForwardMenu); - m_navigationBar->addAction(m_historyForward); - - m_stopReload = new QAction(this); - m_reloadIcon = style()->standardIcon(QStyle::SP_BrowserReload); - m_stopReload->setIcon(m_reloadIcon); - - m_navigationBar->addAction(m_stopReload); - - m_navigationBar->addWidget(m_tabWidget->lineEditStack()); - - m_toolbarSearch = new ToolbarSearch(m_navigationBar); - m_navigationBar->addWidget(m_toolbarSearch); - connect(m_toolbarSearch, SIGNAL(search(QUrl)), SLOT(loadUrl(QUrl))); - - m_chaseWidget = new ChaseWidget(this); - m_navigationBar->addWidget(m_chaseWidget); -} - -void BrowserMainWindow::slotShowBookmarksDialog() -{ - BookmarksDialog *dialog = new BookmarksDialog(this); - connect(dialog, SIGNAL(openUrl(QUrl)), - m_tabWidget, SLOT(loadUrlInCurrentTab(QUrl))); - dialog->show(); -} - -void BrowserMainWindow::slotAddBookmark() -{ - WebView *webView = currentTab(); - QString url = webView->url().toString(); - QString title = webView->title(); - AddBookmarkDialog dialog(url, title); - dialog.exec(); -} - -void BrowserMainWindow::slotViewToolbar() -{ - if (m_navigationBar->isVisible()) { - updateToolbarActionText(false); - m_navigationBar->close(); - } else { - updateToolbarActionText(true); - m_navigationBar->show(); - } - m_autoSaver->changeOccurred(); -} - -void BrowserMainWindow::slotViewBookmarksBar() -{ - if (m_bookmarksToolbar->isVisible()) { - updateBookmarksToolbarActionText(false); - m_bookmarksToolbar->close(); - } else { - updateBookmarksToolbarActionText(true); - m_bookmarksToolbar->show(); - } - m_autoSaver->changeOccurred(); -} - -void BrowserMainWindow::updateStatusbarActionText(bool visible) -{ - m_viewStatusbar->setText(!visible ? tr("Show Status Bar") : tr("Hide Status Bar")); -} - -void BrowserMainWindow::handleFindTextResult(bool found) -{ - if (!found) - slotUpdateStatusbar(tr("\"%1\" not found.").arg(m_lastSearch)); -} - -void BrowserMainWindow::updateToolbarActionText(bool visible) -{ - m_viewToolbar->setText(!visible ? tr("Show Toolbar") : tr("Hide Toolbar")); -} - -void BrowserMainWindow::updateBookmarksToolbarActionText(bool visible) -{ - m_viewBookmarkBar->setText(!visible ? tr("Show Bookmarks bar") : tr("Hide Bookmarks bar")); -} - -void BrowserMainWindow::slotViewStatusbar() -{ - if (statusBar()->isVisible()) { - updateStatusbarActionText(false); - statusBar()->close(); - } else { - updateStatusbarActionText(true); - statusBar()->show(); - } - m_autoSaver->changeOccurred(); -} - -void BrowserMainWindow::loadUrl(const QUrl &url) -{ - if (!currentTab() || !url.isValid()) - return; - - m_tabWidget->currentLineEdit()->setText(QString::fromUtf8(url.toEncoded())); - m_tabWidget->loadUrlInCurrentTab(url); -} - -void BrowserMainWindow::slotDownloadManager() -{ - BrowserApplication::downloadManager()->show(); -} - -void BrowserMainWindow::slotSelectLineEdit() -{ - m_tabWidget->currentLineEdit()->selectAll(); - m_tabWidget->currentLineEdit()->setFocus(); -} - -void BrowserMainWindow::slotFileSaveAs() -{ - BrowserApplication::downloadManager()->download(currentTab()->url(), true); -} - -void BrowserMainWindow::slotPreferences() -{ - SettingsDialog *s = new SettingsDialog(this); - s->show(); -} - -void BrowserMainWindow::slotUpdateStatusbar(const QString &string) -{ - statusBar()->showMessage(string, 2000); -} - -void BrowserMainWindow::slotUpdateWindowTitle(const QString &title) -{ - if (title.isEmpty()) { - setWindowTitle(tr("Qt Demo Browser")); - } else { -#if defined(Q_WS_MAC) - setWindowTitle(title); -#else - setWindowTitle(tr("%1 - Qt Demo Browser", "Page title and Browser name").arg(title)); -#endif - } -} - -void BrowserMainWindow::slotAboutApplication() -{ - QMessageBox::about(this, tr("About"), tr( - "Version %1" - "

This demo demonstrates Qt's " - "webkit facilities in action, providing an example " - "browser for you to experiment with.

" - "

QtWebKit is based on the Open Source WebKit Project developed at http://webkit.org/." - ).arg(QCoreApplication::applicationVersion())); -} - -void BrowserMainWindow::slotFileNew() -{ - BrowserApplication::instance()->newMainWindow(); - BrowserMainWindow *mw = BrowserApplication::instance()->mainWindow(); - mw->slotHome(); -} - -void BrowserMainWindow::slotFileOpen() -{ - QString file = QFileDialog::getOpenFileName(this, tr("Open Web Resource"), QString(), - tr("Web Resources (*.html *.htm *.svg *.png *.gif *.svgz);;All files (*.*)")); - - if (file.isEmpty()) - return; - - loadPage(file); -} - -void BrowserMainWindow::slotFilePrintPreview() -{ -#ifndef QT_NO_PRINTPREVIEWDIALOG - if (!currentTab()) - return; - QPrintPreviewDialog *dialog = new QPrintPreviewDialog(this); - connect(dialog, SIGNAL(paintRequested(QPrinter*)), - currentTab(), SLOT(print(QPrinter*))); - dialog->exec(); -#endif -} - -void BrowserMainWindow::slotFilePrint() -{ -#if defined(QWEBENGINEPAGE_PRINT) - if (!currentTab()) - return; - printRequested(currentTab()->page()->mainFrame()); -#endif -} - -void BrowserMainWindow::printRequested(QWebEngineFrame *frame) -{ -#if defined(QWEBENGINEPAGE_PRINT) -#ifndef QT_NO_PRINTDIALOG - QPrinter printer; - QPrintDialog *dialog = new QPrintDialog(&printer, this); - dialog->setWindowTitle(tr("Print Document")); - if (dialog->exec() != QDialog::Accepted) - return; - frame->print(&printer); -#endif -#endif -} - -void BrowserMainWindow::slotPrivateBrowsing() -{ -#if defined(QWEBENGINESETTINGS) - QWebEngineSettings *settings = QWebEngineSettings::globalSettings(); - bool pb = settings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled); - if (!pb) { - QString title = tr("Are you sure you want to turn on private browsing?"); - QString text = tr("%1

When private browsing in turned on," - " webpages are not added to the history," - " items are automatically removed from the Downloads window," \ - " new cookies are not stored, current cookies can't be accessed," \ - " site icons wont be stored, session wont be saved, " \ - " and searches are not added to the pop-up menu in the Google search box." \ - " Until you close the window, you can still click the Back and Forward buttons" \ - " to return to the webpages you have opened.").arg(title); - - QMessageBox::StandardButton button = QMessageBox::question(this, QString(), text, - QMessageBox::Ok | QMessageBox::Cancel, - QMessageBox::Ok); - if (button == QMessageBox::Ok) { - settings->setAttribute(QWebEngineSettings::PrivateBrowsingEnabled, true); - } - } else { - settings->setAttribute(QWebEngineSettings::PrivateBrowsingEnabled, false); - - QList windows = BrowserApplication::instance()->mainWindows(); - for (int i = 0; i < windows.count(); ++i) { - BrowserMainWindow *window = windows.at(i); - window->m_lastSearch = QString::null; - window->tabWidget()->clear(); - } - } -#endif -} - -void BrowserMainWindow::closeEvent(QCloseEvent *event) -{ - if (m_tabWidget->count() > 1) { - int ret = QMessageBox::warning(this, QString(), - tr("Are you sure you want to close the window?" - " There are %1 tabs open").arg(m_tabWidget->count()), - QMessageBox::Yes | QMessageBox::No, - QMessageBox::No); - if (ret == QMessageBox::No) { - event->ignore(); - return; - } - } - event->accept(); - deleteLater(); -} - -void BrowserMainWindow::slotEditFind() -{ - if (!currentTab()) - return; - bool ok; - QString search = QInputDialog::getText(this, tr("Find"), - tr("Text:"), QLineEdit::Normal, - m_lastSearch, &ok); - if (ok && !search.isEmpty()) { - m_lastSearch = search; - currentTab()->findText(m_lastSearch, 0, invoke(this, &BrowserMainWindow::handleFindTextResult)); - } -} - -void BrowserMainWindow::slotEditFindNext() -{ - if (!currentTab() && !m_lastSearch.isEmpty()) - return; - currentTab()->findText(m_lastSearch); -} - -void BrowserMainWindow::slotEditFindPrevious() -{ - if (!currentTab() && !m_lastSearch.isEmpty()) - return; - currentTab()->findText(m_lastSearch, QWebEnginePage::FindBackward); -} - -void BrowserMainWindow::slotViewZoomIn() -{ - if (!currentTab()) - return; - currentTab()->setZoomFactor(currentTab()->zoomFactor() + 0.1); -} - -void BrowserMainWindow::slotViewZoomOut() -{ - if (!currentTab()) - return; - currentTab()->setZoomFactor(currentTab()->zoomFactor() - 0.1); -} - -void BrowserMainWindow::slotViewResetZoom() -{ - if (!currentTab()) - return; - currentTab()->setZoomFactor(1.0); -} - -void BrowserMainWindow::slotViewZoomTextOnly(bool enable) -{ -#if defined(QWEBENGINESETTINGS) - if (!currentTab()) - return; - currentTab()->page()->settings()->setAttribute(QWebEngineSettings::ZoomTextOnly, enable); -#endif -} - -void BrowserMainWindow::slotViewFullScreen(bool makeFullScreen) -{ - if (makeFullScreen) { - showFullScreen(); - } else { - if (isMinimized()) - showMinimized(); - else if (isMaximized()) - showMaximized(); - else showNormal(); - } -} - -void BrowserMainWindow::slotViewPageSource() -{ - if (!currentTab()) - return; - - QPlainTextEdit *view = new QPlainTextEdit; - view->setWindowTitle(tr("Page Source of %1").arg(currentTab()->title())); - view->setMinimumWidth(640); - view->setAttribute(Qt::WA_DeleteOnClose); - view->show(); - - currentTab()->page()->toHtml(invoke(view, &QPlainTextEdit::setPlainText)); -} - -void BrowserMainWindow::slotHome() -{ - QSettings settings; - settings.beginGroup(QLatin1String("MainWindow")); - QString home = settings.value(QLatin1String("home"), QLatin1String("http://qt-project.org/")).toString(); - loadPage(home); -} - -void BrowserMainWindow::slotWebSearch() -{ - m_toolbarSearch->lineEdit()->selectAll(); - m_toolbarSearch->lineEdit()->setFocus(); -} - -void BrowserMainWindow::slotToggleInspector(bool enable) -{ -#if defined(QWEBENGINEINSPECTOR) - QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::DeveloperExtrasEnabled, enable); - if (enable) { - int result = QMessageBox::question(this, tr("Web Inspector"), - tr("The web inspector will only work correctly for pages that were loaded after enabling.\n" - "Do you want to reload all pages?"), - QMessageBox::Yes | QMessageBox::No); - if (result == QMessageBox::Yes) { - m_tabWidget->reloadAllTabs(); - } - } -#endif -} - -void BrowserMainWindow::slotSwapFocus() -{ - if (currentTab()->hasFocus()) - m_tabWidget->currentLineEdit()->setFocus(); - else - currentTab()->setFocus(); -} - -void BrowserMainWindow::loadPage(const QString &page) -{ - QUrl url = QUrl::fromUserInput(page); - loadUrl(url); -} - -TabWidget *BrowserMainWindow::tabWidget() const -{ - return m_tabWidget; -} - -WebView *BrowserMainWindow::currentTab() const -{ - return m_tabWidget->currentWebView(); -} - -void BrowserMainWindow::slotLoadProgress(int progress) -{ - if (progress < 100 && progress > 0) { - m_chaseWidget->setAnimated(true); - disconnect(m_stopReload, SIGNAL(triggered()), m_reload, SLOT(trigger())); - if (m_stopIcon.isNull()) - m_stopIcon = style()->standardIcon(QStyle::SP_BrowserStop); - m_stopReload->setIcon(m_stopIcon); - connect(m_stopReload, SIGNAL(triggered()), m_stop, SLOT(trigger())); - m_stopReload->setToolTip(tr("Stop loading the current page")); - } else { - m_chaseWidget->setAnimated(false); - disconnect(m_stopReload, SIGNAL(triggered()), m_stop, SLOT(trigger())); - m_stopReload->setIcon(m_reloadIcon); - connect(m_stopReload, SIGNAL(triggered()), m_reload, SLOT(trigger())); - m_stopReload->setToolTip(tr("Reload the current page")); - } -} - -void BrowserMainWindow::slotAboutToShowBackMenu() -{ - m_historyBackMenu->clear(); - if (!currentTab()) - return; - QWebEngineHistory *history = currentTab()->history(); - int historyCount = history->count(); - for (int i = history->backItems(historyCount).count() - 1; i >= 0; --i) { - QWebEngineHistoryItem item = history->backItems(history->count()).at(i); - QAction *action = new QAction(this); - action->setData(-1*(historyCount-i-1)); - QIcon icon = BrowserApplication::instance()->icon(item.url()); - action->setIcon(icon); - action->setText(item.title()); - m_historyBackMenu->addAction(action); - } -} - -void BrowserMainWindow::slotAboutToShowForwardMenu() -{ - m_historyForwardMenu->clear(); - if (!currentTab()) - return; - QWebEngineHistory *history = currentTab()->history(); - int historyCount = history->count(); - for (int i = 0; i < history->forwardItems(history->count()).count(); ++i) { - QWebEngineHistoryItem item = history->forwardItems(historyCount).at(i); - QAction *action = new QAction(this); - action->setData(historyCount-i); - QIcon icon = BrowserApplication::instance()->icon(item.url()); - action->setIcon(icon); - action->setText(item.title()); - m_historyForwardMenu->addAction(action); - } -} - -void BrowserMainWindow::slotAboutToShowWindowMenu() -{ - m_windowMenu->clear(); - m_windowMenu->addAction(m_tabWidget->nextTabAction()); - m_windowMenu->addAction(m_tabWidget->previousTabAction()); - m_windowMenu->addSeparator(); -#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) - m_windowMenu->addAction(tr("Downloads"), this, SLOT(slotDownloadManager()), QKeySequence(tr("Alt+Ctrl+L", "Download Manager"))); - m_windowMenu->addSeparator(); -#endif - - QList windows = BrowserApplication::instance()->mainWindows(); - for (int i = 0; i < windows.count(); ++i) { - BrowserMainWindow *window = windows.at(i); - QAction *action = m_windowMenu->addAction(window->windowTitle(), this, SLOT(slotShowWindow())); - action->setData(i); - action->setCheckable(true); - if (window == this) - action->setChecked(true); - } -} - -void BrowserMainWindow::slotShowWindow() -{ - if (QAction *action = qobject_cast(sender())) { - QVariant v = action->data(); - if (v.canConvert()) { - int offset = qvariant_cast(v); - QList windows = BrowserApplication::instance()->mainWindows(); - windows.at(offset)->activateWindow(); - windows.at(offset)->currentTab()->setFocus(); - } - } -} - -void BrowserMainWindow::slotOpenActionUrl(QAction *action) -{ - int offset = action->data().toInt(); - QWebEngineHistory *history = currentTab()->history(); - if (offset < 0) - history->goToItem(history->backItems(-1*offset).first()); // back - else if (offset > 0) - history->goToItem(history->forwardItems(history->count() - offset + 1).back()); // forward -} - -void BrowserMainWindow::geometryChangeRequested(const QRect &geometry) -{ - setGeometry(geometry); -} diff --git a/examples/widgets/browser/browsermainwindow.h b/examples/widgets/browser/browsermainwindow.h deleted file mode 100644 index 3c3df9117..000000000 --- a/examples/widgets/browser/browsermainwindow.h +++ /dev/null @@ -1,171 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BROWSERMAINWINDOW_H -#define BROWSERMAINWINDOW_H - -#include -#include -#include - -QT_BEGIN_NAMESPACE -class QWebEngineFrame; -QT_END_NAMESPACE - -class AutoSaver; -class BookmarksToolBar; -class ChaseWidget; -class TabWidget; -class ToolbarSearch; -class WebView; - -/*! - The MainWindow of the Browser Application. - - Handles the tab widget and all the actions - */ -class BrowserMainWindow : public QMainWindow { - Q_OBJECT - -public: - BrowserMainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0); - ~BrowserMainWindow(); - QSize sizeHint() const; - -public: - TabWidget *tabWidget() const; - WebView *currentTab() const; - QByteArray saveState(bool withTabs = true) const; - bool restoreState(const QByteArray &state); - -public slots: - void loadPage(const QString &url); - void slotHome(); - -protected: - void closeEvent(QCloseEvent *event); - -private slots: - void save(); - - void slotLoadProgress(int); - void slotUpdateStatusbar(const QString &string); - void slotUpdateWindowTitle(const QString &title = QString()); - - void loadUrl(const QUrl &url); - void slotPreferences(); - - void slotFileNew(); - void slotFileOpen(); - void slotFilePrintPreview(); - void slotFilePrint(); - void slotPrivateBrowsing(); - void slotFileSaveAs(); - void slotEditFind(); - void slotEditFindNext(); - void slotEditFindPrevious(); - void slotShowBookmarksDialog(); - void slotAddBookmark(); - void slotViewZoomIn(); - void slotViewZoomOut(); - void slotViewResetZoom(); - void slotViewZoomTextOnly(bool enable); - void slotViewToolbar(); - void slotViewBookmarksBar(); - void slotViewStatusbar(); - void slotViewPageSource(); - void slotViewFullScreen(bool enable); - - void slotWebSearch(); - void slotToggleInspector(bool enable); - void slotAboutApplication(); - void slotDownloadManager(); - void slotSelectLineEdit(); - - void slotAboutToShowBackMenu(); - void slotAboutToShowForwardMenu(); - void slotAboutToShowWindowMenu(); - void slotOpenActionUrl(QAction *action); - void slotShowWindow(); - void slotSwapFocus(); - - void printRequested(QWebEngineFrame *frame); - void geometryChangeRequested(const QRect &geometry); - void updateToolbarActionText(bool visible); - void updateBookmarksToolbarActionText(bool visible); - -private: - void loadDefaultState(); - void setupMenu(); - void setupToolBar(); - void updateStatusbarActionText(bool visible); - void handleFindTextResult(bool found); - -private: - QToolBar *m_navigationBar; - ToolbarSearch *m_toolbarSearch; - BookmarksToolBar *m_bookmarksToolbar; - ChaseWidget *m_chaseWidget; - TabWidget *m_tabWidget; - AutoSaver *m_autoSaver; - - QAction *m_historyBack; - QMenu *m_historyBackMenu; - QAction *m_historyForward; - QMenu *m_historyForwardMenu; - QMenu *m_windowMenu; - - QAction *m_stop; - QAction *m_reload; - QAction *m_stopReload; - QAction *m_viewToolbar; - QAction *m_viewBookmarkBar; - QAction *m_viewStatusbar; - QAction *m_restoreLastSession; - QAction *m_addBookmark; - - QIcon m_reloadIcon; - QIcon m_stopIcon; - - QString m_lastSearch; -}; - -#endif // BROWSERMAINWINDOW_H diff --git a/examples/widgets/browser/chasewidget.cpp b/examples/widgets/browser/chasewidget.cpp deleted file mode 100644 index c34dde739..000000000 --- a/examples/widgets/browser/chasewidget.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "chasewidget.h" - -#include - -#include -#include -#include -#include -#include - -ChaseWidget::ChaseWidget(QWidget *parent, QPixmap pixmap, bool pixmapEnabled) - : QWidget(parent) - , m_segment(0) - , m_delay(100) - , m_step(40) - , m_timerId(-1) - , m_animated(false) - , m_pixmap(pixmap) - , m_pixmapEnabled(pixmapEnabled) -{ -} - -void ChaseWidget::setAnimated(bool value) -{ - if (m_animated == value) - return; - m_animated = value; - if (m_timerId != -1) { - killTimer(m_timerId); - m_timerId = -1; - } - if (m_animated) { - m_segment = 0; - m_timerId = startTimer(m_delay); - } - update(); -} - -void ChaseWidget::paintEvent(QPaintEvent *event) -{ - Q_UNUSED(event); - QPainter p(this); - if (m_pixmapEnabled && !m_pixmap.isNull()) { - p.drawPixmap(0, 0, m_pixmap); - return; - } - - const int extent = qMin(width() - 8, height() - 8); - const int displ = extent / 4; - const int ext = extent / 4 - 1; - - p.setRenderHint(QPainter::Antialiasing, true); - - if (m_animated) - p.setPen(Qt::gray); - else - p.setPen(QPen(palette().dark().color())); - - p.translate(width() / 2, height() / 2); // center - - for (int segment = 0; segment < segmentCount(); ++segment) { - p.rotate(QApplication::isRightToLeft() ? m_step : -m_step); - if (m_animated) - p.setBrush(colorForSegment(segment)); - else - p.setBrush(palette().background()); - p.drawEllipse(QRect(displ, -ext / 2, ext, ext)); - } -} - -QSize ChaseWidget::sizeHint() const -{ - return QSize(32, 32); -} - -void ChaseWidget::timerEvent(QTimerEvent *event) -{ - if (event->timerId() == m_timerId) { - ++m_segment; - update(); - } - QWidget::timerEvent(event); -} - -QColor ChaseWidget::colorForSegment(int seg) const -{ - int index = ((seg + m_segment) % segmentCount()); - int comp = qMax(0, 255 - (index * (255 / segmentCount()))); - return QColor(comp, comp, comp, 255); -} - -int ChaseWidget::segmentCount() const -{ - return 360 / m_step; -} - -void ChaseWidget::setPixmapEnabled(bool enable) -{ - m_pixmapEnabled = enable; -} diff --git a/examples/widgets/browser/chasewidget.h b/examples/widgets/browser/chasewidget.h deleted file mode 100644 index 2c57d08ac..000000000 --- a/examples/widgets/browser/chasewidget.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CHASEWIDGET_H -#define CHASEWIDGET_H - -#include - -#include -#include -#include - -QT_BEGIN_NAMESPACE -class QHideEvent; -class QShowEvent; -class QPaintEvent; -class QTimerEvent; -QT_END_NAMESPACE - -class ChaseWidget : public QWidget -{ - Q_OBJECT -public: - ChaseWidget(QWidget *parent = 0, QPixmap pixmap = QPixmap(), bool pixmapEnabled = false); - - void setAnimated(bool value); - void setPixmapEnabled(bool enable); - QSize sizeHint() const; - -protected: - void paintEvent(QPaintEvent *event); - void timerEvent(QTimerEvent *event); - -private: - int segmentCount() const; - QColor colorForSegment(int segment) const; - - int m_segment; - int m_delay; - int m_step; - int m_timerId; - bool m_animated; - QPixmap m_pixmap; - bool m_pixmapEnabled; -}; - -#endif diff --git a/examples/widgets/browser/cookiejar.cpp b/examples/widgets/browser/cookiejar.cpp deleted file mode 100644 index 0b94d9903..000000000 --- a/examples/widgets/browser/cookiejar.cpp +++ /dev/null @@ -1,737 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "cookiejar.h" - -#include "autosaver.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -static const unsigned int JAR_VERSION = 23; - -QT_BEGIN_NAMESPACE -QDataStream &operator<<(QDataStream &stream, const QList &list) -{ - stream << JAR_VERSION; - stream << quint32(list.size()); - for (int i = 0; i < list.size(); ++i) - stream << list.at(i).toRawForm(); - return stream; -} - -QDataStream &operator>>(QDataStream &stream, QList &list) -{ - list.clear(); - - quint32 version; - stream >> version; - - if (version != JAR_VERSION) - return stream; - - quint32 count; - stream >> count; - for (quint32 i = 0; i < count; ++i) - { - QByteArray value; - stream >> value; - QList newCookies = QNetworkCookie::parseCookies(value); - if (newCookies.count() == 0 && value.length() != 0) { - qWarning() << "CookieJar: Unable to parse saved cookie:" << value; - } - for (int j = 0; j < newCookies.count(); ++j) - list.append(newCookies.at(j)); - if (stream.atEnd()) - break; - } - return stream; -} -QT_END_NAMESPACE - -CookieJar::CookieJar(QObject *parent) - : QNetworkCookieJar(parent) - , m_loaded(false) - , m_saveTimer(new AutoSaver(this)) - , m_acceptCookies(AcceptOnlyFromSitesNavigatedTo) -{ -} - -CookieJar::~CookieJar() -{ - if (m_keepCookies == KeepUntilExit) - clear(); - m_saveTimer->saveIfNeccessary(); -} - -void CookieJar::clear() -{ - setAllCookies(QList()); - m_saveTimer->changeOccurred(); - emit cookiesChanged(); -} - -void CookieJar::load() -{ - if (m_loaded) - return; - // load cookies and exceptions - qRegisterMetaTypeStreamOperators >("QList"); - QSettings cookieSettings(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1String("/cookies.ini"), QSettings::IniFormat); - setAllCookies(qvariant_cast >(cookieSettings.value(QLatin1String("cookies")))); - cookieSettings.beginGroup(QLatin1String("Exceptions")); - m_exceptions_block = cookieSettings.value(QLatin1String("block")).toStringList(); - m_exceptions_allow = cookieSettings.value(QLatin1String("allow")).toStringList(); - m_exceptions_allowForSession = cookieSettings.value(QLatin1String("allowForSession")).toStringList(); - qSort(m_exceptions_block.begin(), m_exceptions_block.end()); - qSort(m_exceptions_allow.begin(), m_exceptions_allow.end()); - qSort(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end()); - - loadSettings(); -} - -void CookieJar::loadSettings() -{ - QSettings settings; - settings.beginGroup(QLatin1String("cookies")); - QByteArray value = settings.value(QLatin1String("acceptCookies"), - QLatin1String("AcceptOnlyFromSitesNavigatedTo")).toByteArray(); - QMetaEnum acceptPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("AcceptPolicy")); - m_acceptCookies = acceptPolicyEnum.keyToValue(value) == -1 ? - AcceptOnlyFromSitesNavigatedTo : - static_cast(acceptPolicyEnum.keyToValue(value)); - - value = settings.value(QLatin1String("keepCookiesUntil"), QLatin1String("KeepUntilExpire")).toByteArray(); - QMetaEnum keepPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("KeepPolicy")); - m_keepCookies = keepPolicyEnum.keyToValue(value) == -1 ? - KeepUntilExpire : - static_cast(keepPolicyEnum.keyToValue(value)); - - if (m_keepCookies == KeepUntilExit) - setAllCookies(QList()); - - m_loaded = true; - emit cookiesChanged(); -} - -void CookieJar::save() -{ - if (!m_loaded) - return; - purgeOldCookies(); - QString directory = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - if (directory.isEmpty()) - directory = QDir::homePath() + QLatin1String("/.") + QCoreApplication::applicationName(); - if (!QFile::exists(directory)) { - QDir dir; - dir.mkpath(directory); - } - QSettings cookieSettings(directory + QLatin1String("/cookies.ini"), QSettings::IniFormat); - QList cookies = allCookies(); - for (int i = cookies.count() - 1; i >= 0; --i) { - if (cookies.at(i).isSessionCookie()) - cookies.removeAt(i); - } - cookieSettings.setValue(QLatin1String("cookies"), QVariant::fromValue >(cookies)); - cookieSettings.beginGroup(QLatin1String("Exceptions")); - cookieSettings.setValue(QLatin1String("block"), m_exceptions_block); - cookieSettings.setValue(QLatin1String("allow"), m_exceptions_allow); - cookieSettings.setValue(QLatin1String("allowForSession"), m_exceptions_allowForSession); - - // save cookie settings - QSettings settings; - settings.beginGroup(QLatin1String("cookies")); - QMetaEnum acceptPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("AcceptPolicy")); - settings.setValue(QLatin1String("acceptCookies"), QLatin1String(acceptPolicyEnum.valueToKey(m_acceptCookies))); - - QMetaEnum keepPolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("KeepPolicy")); - settings.setValue(QLatin1String("keepCookiesUntil"), QLatin1String(keepPolicyEnum.valueToKey(m_keepCookies))); -} - -void CookieJar::purgeOldCookies() -{ - QList cookies = allCookies(); - if (cookies.isEmpty()) - return; - int oldCount = cookies.count(); - QDateTime now = QDateTime::currentDateTime(); - for (int i = cookies.count() - 1; i >= 0; --i) { - if (!cookies.at(i).isSessionCookie() && cookies.at(i).expirationDate() < now) - cookies.removeAt(i); - } - if (oldCount == cookies.count()) - return; - setAllCookies(cookies); - emit cookiesChanged(); -} - -QList CookieJar::cookiesForUrl(const QUrl &url) const -{ - CookieJar *that = const_cast(this); - if (!m_loaded) - that->load(); - - QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); - if (globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) { - QList noCookies; - return noCookies; - } - - return QNetworkCookieJar::cookiesForUrl(url); -} - -bool CookieJar::setCookiesFromUrl(const QList &cookieList, const QUrl &url) -{ - if (!m_loaded) - load(); - - QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); - if (globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) - return false; - - QString host = url.host(); - bool eBlock = qBinaryFind(m_exceptions_block.begin(), m_exceptions_block.end(), host) != m_exceptions_block.end(); - bool eAllow = qBinaryFind(m_exceptions_allow.begin(), m_exceptions_allow.end(), host) != m_exceptions_allow.end(); - bool eAllowSession = qBinaryFind(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end(), host) != m_exceptions_allowForSession.end(); - - bool addedCookies = false; - // pass exceptions - bool acceptInitially = (m_acceptCookies != AcceptNever); - if ((acceptInitially && !eBlock) - || (!acceptInitially && (eAllow || eAllowSession))) { - // pass url domain == cookie domain - QDateTime soon = QDateTime::currentDateTime(); - soon = soon.addDays(90); - foreach (QNetworkCookie cookie, cookieList) { - QList lst; - if (m_keepCookies == KeepUntilTimeLimit - && !cookie.isSessionCookie() - && cookie.expirationDate() > soon) { - cookie.setExpirationDate(soon); - } - lst += cookie; - if (QNetworkCookieJar::setCookiesFromUrl(lst, url)) { - addedCookies = true; - } else { - // finally force it in if wanted - if (m_acceptCookies == AcceptAlways) { - QList cookies = allCookies(); - cookies += cookie; - setAllCookies(cookies); - addedCookies = true; - } -#if 0 - else - qWarning() << "setCookiesFromUrl failed" << url << cookieList.value(0).toRawForm(); -#endif - } - } - } - - if (addedCookies) { - m_saveTimer->changeOccurred(); - emit cookiesChanged(); - } - return addedCookies; -} - -CookieJar::AcceptPolicy CookieJar::acceptPolicy() const -{ - if (!m_loaded) - (const_cast(this))->load(); - return m_acceptCookies; -} - -void CookieJar::setAcceptPolicy(AcceptPolicy policy) -{ - if (!m_loaded) - load(); - if (policy == m_acceptCookies) - return; - m_acceptCookies = policy; - m_saveTimer->changeOccurred(); -} - -CookieJar::KeepPolicy CookieJar::keepPolicy() const -{ - if (!m_loaded) - (const_cast(this))->load(); - return m_keepCookies; -} - -void CookieJar::setKeepPolicy(KeepPolicy policy) -{ - if (!m_loaded) - load(); - if (policy == m_keepCookies) - return; - m_keepCookies = policy; - m_saveTimer->changeOccurred(); -} - -QStringList CookieJar::blockedCookies() const -{ - if (!m_loaded) - (const_cast(this))->load(); - return m_exceptions_block; -} - -QStringList CookieJar::allowedCookies() const -{ - if (!m_loaded) - (const_cast(this))->load(); - return m_exceptions_allow; -} - -QStringList CookieJar::allowForSessionCookies() const -{ - if (!m_loaded) - (const_cast(this))->load(); - return m_exceptions_allowForSession; -} - -void CookieJar::setBlockedCookies(const QStringList &list) -{ - if (!m_loaded) - load(); - m_exceptions_block = list; - qSort(m_exceptions_block.begin(), m_exceptions_block.end()); - m_saveTimer->changeOccurred(); -} - -void CookieJar::setAllowedCookies(const QStringList &list) -{ - if (!m_loaded) - load(); - m_exceptions_allow = list; - qSort(m_exceptions_allow.begin(), m_exceptions_allow.end()); - m_saveTimer->changeOccurred(); -} - -void CookieJar::setAllowForSessionCookies(const QStringList &list) -{ - if (!m_loaded) - load(); - m_exceptions_allowForSession = list; - qSort(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end()); - m_saveTimer->changeOccurred(); -} - -CookieModel::CookieModel(CookieJar *cookieJar, QObject *parent) - : QAbstractTableModel(parent) - , m_cookieJar(cookieJar) -{ - connect(m_cookieJar, SIGNAL(cookiesChanged()), this, SLOT(cookiesChanged())); - m_cookieJar->load(); -} - -QVariant CookieModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (role == Qt::SizeHintRole) { - QFont font; - font.setPointSize(10); - QFontMetrics fm(font); - int height = fm.height() + fm.height()/3; - int width = fm.width(headerData(section, orientation, Qt::DisplayRole).toString()); - return QSize(width, height); - } - - if (orientation == Qt::Horizontal) { - if (role != Qt::DisplayRole) - return QVariant(); - - switch (section) { - case 0: - return tr("Website"); - case 1: - return tr("Name"); - case 2: - return tr("Path"); - case 3: - return tr("Secure"); - case 4: - return tr("Expires"); - case 5: - return tr("Contents"); - default: - return QVariant(); - } - } - return QAbstractTableModel::headerData(section, orientation, role); -} - -QVariant CookieModel::data(const QModelIndex &index, int role) const -{ - QList lst; - if (m_cookieJar) - lst = m_cookieJar->allCookies(); - if (index.row() < 0 || index.row() >= lst.size()) - return QVariant(); - - switch (role) { - case Qt::DisplayRole: - case Qt::EditRole: { - QNetworkCookie cookie = lst.at(index.row()); - switch (index.column()) { - case 0: - return cookie.domain(); - case 1: - return cookie.name(); - case 2: - return cookie.path(); - case 3: - return cookie.isSecure(); - case 4: - return cookie.expirationDate(); - case 5: - return cookie.value(); - } - } - case Qt::FontRole:{ - QFont font; - font.setPointSize(10); - return font; - } - } - - return QVariant(); -} - -int CookieModel::columnCount(const QModelIndex &parent) const -{ - return (parent.isValid()) ? 0 : 6; -} - -int CookieModel::rowCount(const QModelIndex &parent) const -{ - return (parent.isValid() || !m_cookieJar) ? 0 : m_cookieJar->allCookies().count(); -} - -bool CookieModel::removeRows(int row, int count, const QModelIndex &parent) -{ - if (parent.isValid() || !m_cookieJar) - return false; - int lastRow = row + count - 1; - beginRemoveRows(parent, row, lastRow); - QList lst = m_cookieJar->allCookies(); - for (int i = lastRow; i >= row; --i) { - lst.removeAt(i); - } - m_cookieJar->setAllCookies(lst); - endRemoveRows(); - return true; -} - -void CookieModel::cookiesChanged() -{ - beginResetModel(); - endResetModel(); -} - -CookiesDialog::CookiesDialog(CookieJar *cookieJar, QWidget *parent) : QDialog(parent) -{ - setupUi(this); - setWindowFlags(Qt::Sheet); - CookieModel *model = new CookieModel(cookieJar, this); - m_proxyModel = new QSortFilterProxyModel(this); - connect(search, SIGNAL(textChanged(QString)), - m_proxyModel, SLOT(setFilterFixedString(QString))); - connect(removeButton, SIGNAL(clicked()), cookiesTable, SLOT(removeOne())); - connect(removeAllButton, SIGNAL(clicked()), cookiesTable, SLOT(removeAll())); - m_proxyModel->setSourceModel(model); - cookiesTable->verticalHeader()->hide(); - cookiesTable->setSelectionBehavior(QAbstractItemView::SelectRows); - cookiesTable->setModel(m_proxyModel); - cookiesTable->setAlternatingRowColors(true); - cookiesTable->setTextElideMode(Qt::ElideMiddle); - cookiesTable->setShowGrid(false); - cookiesTable->setSortingEnabled(true); - QFont f = font(); - f.setPointSize(10); - QFontMetrics fm(f); - int height = fm.height() + fm.height()/3; - cookiesTable->verticalHeader()->setDefaultSectionSize(height); - cookiesTable->verticalHeader()->setMinimumSectionSize(-1); - for (int i = 0; i < model->columnCount(); ++i){ - int header = cookiesTable->horizontalHeader()->sectionSizeHint(i); - switch (i) { - case 0: - header = fm.width(QLatin1String("averagehost.domain.com")); - break; - case 1: - header = fm.width(QLatin1String("_session_id")); - break; - case 4: - header = fm.width(QDateTime::currentDateTime().toString(Qt::LocalDate)); - break; - } - int buffer = fm.width(QLatin1String("xx")); - header += buffer; - cookiesTable->horizontalHeader()->resizeSection(i, header); - } - cookiesTable->horizontalHeader()->setStretchLastSection(true); -} - - - -CookieExceptionsModel::CookieExceptionsModel(CookieJar *cookiejar, QObject *parent) - : QAbstractTableModel(parent) - , m_cookieJar(cookiejar) -{ - m_allowedCookies = m_cookieJar->allowedCookies(); - m_blockedCookies = m_cookieJar->blockedCookies(); - m_sessionCookies = m_cookieJar->allowForSessionCookies(); -} - -QVariant CookieExceptionsModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (role == Qt::SizeHintRole) { - QFont font; - font.setPointSize(10); - QFontMetrics fm(font); - int height = fm.height() + fm.height()/3; - int width = fm.width(headerData(section, orientation, Qt::DisplayRole).toString()); - return QSize(width, height); - } - - if (orientation == Qt::Horizontal - && role == Qt::DisplayRole) { - switch (section) { - case 0: - return tr("Website"); - case 1: - return tr("Status"); - } - } - return QAbstractTableModel::headerData(section, orientation, role); -} - -QVariant CookieExceptionsModel::data(const QModelIndex &index, int role) const -{ - if (index.row() < 0 || index.row() >= rowCount()) - return QVariant(); - - switch (role) { - case Qt::DisplayRole: - case Qt::EditRole: { - int row = index.row(); - if (row < m_allowedCookies.count()) { - switch (index.column()) { - case 0: - return m_allowedCookies.at(row); - case 1: - return tr("Allow"); - } - } - row = row - m_allowedCookies.count(); - if (row < m_blockedCookies.count()) { - switch (index.column()) { - case 0: - return m_blockedCookies.at(row); - case 1: - return tr("Block"); - } - } - row = row - m_blockedCookies.count(); - if (row < m_sessionCookies.count()) { - switch (index.column()) { - case 0: - return m_sessionCookies.at(row); - case 1: - return tr("Allow For Session"); - } - } - } - case Qt::FontRole:{ - QFont font; - font.setPointSize(10); - return font; - } - } - return QVariant(); -} - -int CookieExceptionsModel::columnCount(const QModelIndex &parent) const -{ - return (parent.isValid()) ? 0 : 2; -} - -int CookieExceptionsModel::rowCount(const QModelIndex &parent) const -{ - return (parent.isValid() || !m_cookieJar) ? 0 : m_allowedCookies.count() + m_blockedCookies.count() + m_sessionCookies.count(); -} - -bool CookieExceptionsModel::removeRows(int row, int count, const QModelIndex &parent) -{ - if (parent.isValid() || !m_cookieJar) - return false; - - int lastRow = row + count - 1; - beginRemoveRows(parent, row, lastRow); - for (int i = lastRow; i >= row; --i) { - if (i < m_allowedCookies.count()) { - m_allowedCookies.removeAt(row); - continue; - } - i = i - m_allowedCookies.count(); - if (i < m_blockedCookies.count()) { - m_blockedCookies.removeAt(row); - continue; - } - i = i - m_blockedCookies.count(); - if (i < m_sessionCookies.count()) { - m_sessionCookies.removeAt(row); - continue; - } - } - m_cookieJar->setAllowedCookies(m_allowedCookies); - m_cookieJar->setBlockedCookies(m_blockedCookies); - m_cookieJar->setAllowForSessionCookies(m_sessionCookies); - endRemoveRows(); - return true; -} - -CookiesExceptionsDialog::CookiesExceptionsDialog(CookieJar *cookieJar, QWidget *parent) - : QDialog(parent) - , m_cookieJar(cookieJar) -{ - setupUi(this); - setWindowFlags(Qt::Sheet); - connect(removeButton, SIGNAL(clicked()), exceptionTable, SLOT(removeOne())); - connect(removeAllButton, SIGNAL(clicked()), exceptionTable, SLOT(removeAll())); - exceptionTable->verticalHeader()->hide(); - exceptionTable->setSelectionBehavior(QAbstractItemView::SelectRows); - exceptionTable->setAlternatingRowColors(true); - exceptionTable->setTextElideMode(Qt::ElideMiddle); - exceptionTable->setShowGrid(false); - exceptionTable->setSortingEnabled(true); - m_exceptionsModel = new CookieExceptionsModel(cookieJar, this); - m_proxyModel = new QSortFilterProxyModel(this); - m_proxyModel->setSourceModel(m_exceptionsModel); - connect(search, SIGNAL(textChanged(QString)), - m_proxyModel, SLOT(setFilterFixedString(QString))); - exceptionTable->setModel(m_proxyModel); - - CookieModel *cookieModel = new CookieModel(cookieJar, this); - domainLineEdit->setCompleter(new QCompleter(cookieModel, domainLineEdit)); - - connect(domainLineEdit, SIGNAL(textChanged(QString)), - this, SLOT(textChanged(QString))); - connect(blockButton, SIGNAL(clicked()), this, SLOT(block())); - connect(allowButton, SIGNAL(clicked()), this, SLOT(allow())); - connect(allowForSessionButton, SIGNAL(clicked()), this, SLOT(allowForSession())); - - QFont f = font(); - f.setPointSize(10); - QFontMetrics fm(f); - int height = fm.height() + fm.height()/3; - exceptionTable->verticalHeader()->setDefaultSectionSize(height); - exceptionTable->verticalHeader()->setMinimumSectionSize(-1); - for (int i = 0; i < m_exceptionsModel->columnCount(); ++i){ - int header = exceptionTable->horizontalHeader()->sectionSizeHint(i); - switch (i) { - case 0: - header = fm.width(QLatin1String("averagebiglonghost.domain.com")); - break; - case 1: - header = fm.width(QLatin1String("Allow For Session")); - break; - } - int buffer = fm.width(QLatin1String("xx")); - header += buffer; - exceptionTable->horizontalHeader()->resizeSection(i, header); - } -} - -void CookiesExceptionsDialog::textChanged(const QString &text) -{ - bool enabled = !text.isEmpty(); - blockButton->setEnabled(enabled); - allowButton->setEnabled(enabled); - allowForSessionButton->setEnabled(enabled); -} - -void CookiesExceptionsDialog::block() -{ - if (domainLineEdit->text().isEmpty()) - return; - m_exceptionsModel->m_blockedCookies.append(domainLineEdit->text()); - m_cookieJar->setBlockedCookies(m_exceptionsModel->m_blockedCookies); - m_exceptionsModel->beginResetModel(); - m_exceptionsModel->endResetModel(); -} - -void CookiesExceptionsDialog::allow() -{ - if (domainLineEdit->text().isEmpty()) - return; - m_exceptionsModel->m_allowedCookies.append(domainLineEdit->text()); - m_cookieJar->setAllowedCookies(m_exceptionsModel->m_allowedCookies); - m_exceptionsModel->beginResetModel(); - m_exceptionsModel->endResetModel(); -} - -void CookiesExceptionsDialog::allowForSession() -{ - if (domainLineEdit->text().isEmpty()) - return; - m_exceptionsModel->m_sessionCookies.append(domainLineEdit->text()); - m_cookieJar->setAllowForSessionCookies(m_exceptionsModel->m_sessionCookies); - m_exceptionsModel->beginResetModel(); - m_exceptionsModel->endResetModel(); -} diff --git a/examples/widgets/browser/cookiejar.h b/examples/widgets/browser/cookiejar.h deleted file mode 100644 index 1cc7800e1..000000000 --- a/examples/widgets/browser/cookiejar.h +++ /dev/null @@ -1,203 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef COOKIEJAR_H -#define COOKIEJAR_H - -#include - -#include -#include - -#include -#include - -QT_BEGIN_NAMESPACE -class QSortFilterProxyModel; -class QKeyEvent; -QT_END_NAMESPACE - -class AutoSaver; - -class CookieJar : public QNetworkCookieJar -{ - friend class CookieModel; - Q_OBJECT - Q_PROPERTY(AcceptPolicy acceptPolicy READ acceptPolicy WRITE setAcceptPolicy) - Q_PROPERTY(KeepPolicy keepPolicy READ keepPolicy WRITE setKeepPolicy) - Q_PROPERTY(QStringList blockedCookies READ blockedCookies WRITE setBlockedCookies) - Q_PROPERTY(QStringList allowedCookies READ allowedCookies WRITE setAllowedCookies) - Q_PROPERTY(QStringList allowForSessionCookies READ allowForSessionCookies WRITE setAllowForSessionCookies) - Q_ENUMS(KeepPolicy) - Q_ENUMS(AcceptPolicy) - -signals: - void cookiesChanged(); - -public: - enum AcceptPolicy { - AcceptAlways, - AcceptNever, - AcceptOnlyFromSitesNavigatedTo - }; - - enum KeepPolicy { - KeepUntilExpire, - KeepUntilExit, - KeepUntilTimeLimit - }; - - CookieJar(QObject *parent = 0); - ~CookieJar(); - - QList cookiesForUrl(const QUrl &url) const; - bool setCookiesFromUrl(const QList &cookieList, const QUrl &url); - - AcceptPolicy acceptPolicy() const; - void setAcceptPolicy(AcceptPolicy policy); - - KeepPolicy keepPolicy() const; - void setKeepPolicy(KeepPolicy policy); - - QStringList blockedCookies() const; - QStringList allowedCookies() const; - QStringList allowForSessionCookies() const; - - void setBlockedCookies(const QStringList &list); - void setAllowedCookies(const QStringList &list); - void setAllowForSessionCookies(const QStringList &list); - -public slots: - void clear(); - void loadSettings(); - -private slots: - void save(); - -private: - void purgeOldCookies(); - void load(); - bool m_loaded; - AutoSaver *m_saveTimer; - - AcceptPolicy m_acceptCookies; - KeepPolicy m_keepCookies; - - QStringList m_exceptions_block; - QStringList m_exceptions_allow; - QStringList m_exceptions_allowForSession; -}; - -class CookieModel : public QAbstractTableModel -{ - Q_OBJECT - -public: - CookieModel(CookieJar *jar, QObject *parent = 0); - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); - -private slots: - void cookiesChanged(); - -private: - CookieJar *m_cookieJar; -}; - -#include "ui_cookies.h" -#include "ui_cookiesexceptions.h" - -class CookiesDialog : public QDialog, public Ui_CookiesDialog -{ - Q_OBJECT - -public: - CookiesDialog(CookieJar *cookieJar, QWidget *parent = 0); - -private: - QSortFilterProxyModel *m_proxyModel; -}; - -class CookieExceptionsModel : public QAbstractTableModel -{ - Q_OBJECT - friend class CookiesExceptionsDialog; - -public: - CookieExceptionsModel(CookieJar *cookieJar, QObject *parent = 0); - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); - -private: - CookieJar *m_cookieJar; - - // Domains we allow, Domains we block, Domains we allow for this session - QStringList m_allowedCookies; - QStringList m_blockedCookies; - QStringList m_sessionCookies; -}; - -class CookiesExceptionsDialog : public QDialog, public Ui_CookiesExceptionsDialog -{ - Q_OBJECT - -public: - CookiesExceptionsDialog(CookieJar *cookieJar, QWidget *parent = 0); - -private slots: - void block(); - void allow(); - void allowForSession(); - void textChanged(const QString &text); - -private: - CookieExceptionsModel *m_exceptionsModel; - QSortFilterProxyModel *m_proxyModel; - CookieJar *m_cookieJar; -}; - -#endif // COOKIEJAR_H diff --git a/examples/widgets/browser/cookies.ui b/examples/widgets/browser/cookies.ui deleted file mode 100644 index c4bccc548..000000000 --- a/examples/widgets/browser/cookies.ui +++ /dev/null @@ -1,106 +0,0 @@ - - CookiesDialog - - - - 0 - 0 - 550 - 370 - - - - Cookies - - - - - - Qt::Horizontal - - - - 252 - 20 - - - - - - - - - - - - - - - - &Remove - - - - - - - Remove &All Cookies - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - QDialogButtonBox::Ok - - - - - - - - - - SearchLineEdit - QLineEdit -

searchlineedit.h
- - - EditTableView - QTableView -
edittableview.h
-
- - - - - buttonBox - accepted() - CookiesDialog - accept() - - - 472 - 329 - - - 461 - 356 - - - - - diff --git a/examples/widgets/browser/cookiesexceptions.ui b/examples/widgets/browser/cookiesexceptions.ui deleted file mode 100644 index 3d9ef6241..000000000 --- a/examples/widgets/browser/cookiesexceptions.ui +++ /dev/null @@ -1,184 +0,0 @@ - - CookiesExceptionsDialog - - - - 0 - 0 - 466 - 446 - - - - Cookie Exceptions - - - - - - New Exception - - - - - - - - Domain: - - - - - - - - - - - - - - Qt::Horizontal - - - - 81 - 25 - - - - - - - - false - - - Block - - - - - - - false - - - Allow For Session - - - - - - - false - - - Allow - - - - - - - - - - - - Exceptions - - - - - - Qt::Horizontal - - - - 252 - 20 - - - - - - - - - - - - - - &Remove - - - - - - - Remove &All - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Ok - - - - - - - - SearchLineEdit - QLineEdit -
searchlineedit.h
-
- - EditTableView - QTableView -
edittableview.h
-
-
- - - - buttonBox - accepted() - CookiesExceptionsDialog - accept() - - - 381 - 428 - - - 336 - 443 - - - - -
diff --git a/examples/widgets/browser/data/addtab.png b/examples/widgets/browser/data/addtab.png deleted file mode 100644 index 20928fb40..000000000 Binary files a/examples/widgets/browser/data/addtab.png and /dev/null differ diff --git a/examples/widgets/browser/data/browser.svg b/examples/widgets/browser/data/browser.svg deleted file mode 100644 index 8795187b1..000000000 --- a/examples/widgets/browser/data/browser.svg +++ /dev/null @@ -1,411 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - Qt Browser - - - Jens Bache-Wiig - - - - - Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/widgets/browser/data/closetab.png b/examples/widgets/browser/data/closetab.png deleted file mode 100644 index ab9d669ee..000000000 Binary files a/examples/widgets/browser/data/closetab.png and /dev/null differ diff --git a/examples/widgets/browser/data/data.qrc b/examples/widgets/browser/data/data.qrc deleted file mode 100644 index c7d0294c1..000000000 --- a/examples/widgets/browser/data/data.qrc +++ /dev/null @@ -1,11 +0,0 @@ - - - addtab.png - closetab.png - history.png - browser.svg - defaultbookmarks.xbel - loading.gif - defaulticon.png - - diff --git a/examples/widgets/browser/data/defaultbookmarks.xbel b/examples/widgets/browser/data/defaultbookmarks.xbel deleted file mode 100644 index 7a95e36b3..000000000 --- a/examples/widgets/browser/data/defaultbookmarks.xbel +++ /dev/null @@ -1,43 +0,0 @@ - - - - - Bookmarks Bar - - Qt Home Page - - - WebKit.org - - - Qt Documentation - - - Qt Quarterly - - - Qt Blog - - - Qt Centre - - - Qt-Apps.org - - - Online Communities - - - xkcd - - - Twitter - - - - Bookmarks Menu - - reddit.com: what's new online! - - - diff --git a/examples/widgets/browser/data/defaulticon.png b/examples/widgets/browser/data/defaulticon.png deleted file mode 100644 index 01a0920c9..000000000 Binary files a/examples/widgets/browser/data/defaulticon.png and /dev/null differ diff --git a/examples/widgets/browser/data/history.png b/examples/widgets/browser/data/history.png deleted file mode 100644 index 552a1cbd8..000000000 Binary files a/examples/widgets/browser/data/history.png and /dev/null differ diff --git a/examples/widgets/browser/data/loading.gif b/examples/widgets/browser/data/loading.gif deleted file mode 100644 index c1545eb0e..000000000 Binary files a/examples/widgets/browser/data/loading.gif and /dev/null differ diff --git a/examples/widgets/browser/doc/images/browser-demo.png b/examples/widgets/browser/doc/images/browser-demo.png deleted file mode 100644 index 09d065095..000000000 Binary files a/examples/widgets/browser/doc/images/browser-demo.png and /dev/null differ diff --git a/examples/widgets/browser/doc/src/browser.qdoc b/examples/widgets/browser/doc/src/browser.qdoc deleted file mode 100644 index 4e53de38f..000000000 --- a/examples/widgets/browser/doc/src/browser.qdoc +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example webkitwidgets/browser - \title Tab Browser - \brief Demonstrates a complete web browsing experience - \ingroup webkit-widgetexamples - - The Tab Browser example shows \l{Qt WebKit} module in action, - providing a little Web browser application with support for tabs. - - \image browser-demo.png - - This browser is the foundation for the \l{Arora Browser}, a simple cross-platform - Web browser. -*/ diff --git a/examples/widgets/browser/downloaditem.ui b/examples/widgets/browser/downloaditem.ui deleted file mode 100644 index 4a0a0fd9a..000000000 --- a/examples/widgets/browser/downloaditem.ui +++ /dev/null @@ -1,134 +0,0 @@ - - DownloadItem - - - - 0 - 0 - 423 - 110 - - - - Form - - - - 0 - - - - - - 0 - 0 - - - - Ico - - - - - - - - - - 0 - 0 - - - - Filename - - - - - - - 0 - - - - - - - - 0 - 0 - - - - - - - - - - - - - - - Qt::Vertical - - - - 17 - 1 - - - - - - - - false - - - Try Again - - - - - - - Stop - - - - - - - Open - - - - - - - Qt::Vertical - - - - 17 - 5 - - - - - - - - - - - SqueezeLabel - QWidget -
squeezelabel.h
-
-
- - -
diff --git a/examples/widgets/browser/downloadmanager.cpp b/examples/widgets/browser/downloadmanager.cpp deleted file mode 100644 index 6f4c6c8ad..000000000 --- a/examples/widgets/browser/downloadmanager.cpp +++ /dev/null @@ -1,580 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "downloadmanager.h" - -#include "autosaver.h" -#include "browserapplication.h" -#include "networkaccessmanager.h" - -#include - -#include -#include - -#include -#include -#include -#include - -#include - -#include - -/*! - DownloadItem is a widget that is displayed in the download manager list. - It moves the data from the QNetworkReply into the QFile as well - as update the information/progressbar and report errors. - */ -DownloadItem::DownloadItem(QNetworkReply *reply, bool requestFileName, QWidget *parent) - : QWidget(parent) - , m_reply(reply) - , m_requestFileName(requestFileName) - , m_bytesReceived(0) -{ - setupUi(this); - QPalette p = downloadInfoLabel->palette(); - p.setColor(QPalette::Text, Qt::darkGray); - downloadInfoLabel->setPalette(p); - progressBar->setMaximum(0); - tryAgainButton->hide(); - connect(stopButton, SIGNAL(clicked()), this, SLOT(stop())); - connect(openButton, SIGNAL(clicked()), this, SLOT(open())); - connect(tryAgainButton, SIGNAL(clicked()), this, SLOT(tryAgain())); - - init(); -} - -void DownloadItem::init() -{ - if (!m_reply) - return; - - // attach to the m_reply - m_url = m_reply->url(); - m_reply->setParent(this); - connect(m_reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead())); - connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), - this, SLOT(error(QNetworkReply::NetworkError))); - connect(m_reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(downloadProgress(qint64,qint64))); - connect(m_reply, SIGNAL(metaDataChanged()), - this, SLOT(metaDataChanged())); - connect(m_reply, SIGNAL(finished()), - this, SLOT(finished())); - - // reset info - downloadInfoLabel->clear(); - progressBar->setValue(0); - getFileName(); - - // start timer for the download estimation - m_downloadTime.start(); - - if (m_reply->error() != QNetworkReply::NoError) { - error(m_reply->error()); - finished(); - } -} - -void DownloadItem::getFileName() -{ - QSettings settings; - settings.beginGroup(QLatin1String("downloadmanager")); - QString defaultLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); - QString downloadDirectory = settings.value(QLatin1String("downloadDirectory"), defaultLocation).toString(); - if (!downloadDirectory.isEmpty()) - downloadDirectory += QLatin1Char('/'); - - QString defaultFileName = saveFileName(downloadDirectory); - QString fileName = defaultFileName; - if (m_requestFileName) { - fileName = QFileDialog::getSaveFileName(this, tr("Save File"), defaultFileName); - if (fileName.isEmpty()) { - m_reply->close(); - fileNameLabel->setText(tr("Download canceled: %1").arg(QFileInfo(defaultFileName).fileName())); - return; - } - } - m_output.setFileName(fileName); - fileNameLabel->setText(QFileInfo(m_output.fileName()).fileName()); - if (m_requestFileName) - downloadReadyRead(); -} - -QString DownloadItem::saveFileName(const QString &directory) const -{ - // Move this function into QNetworkReply to also get file name sent from the server - QString path = m_url.path(); - QFileInfo info(path); - QString baseName = info.completeBaseName(); - QString endName = info.suffix(); - - if (baseName.isEmpty()) { - baseName = QLatin1String("unnamed_download"); - qDebug() << "DownloadManager:: downloading unknown file:" << m_url; - } - QString name = directory + baseName + QLatin1Char('.') + endName; - if (QFile::exists(name)) { - // already exists, don't overwrite - int i = 1; - do { - name = directory + baseName + QLatin1Char('-') + QString::number(i++) + QLatin1Char('.') + endName; - } while (QFile::exists(name)); - } - return name; -} - - -void DownloadItem::stop() -{ - setUpdatesEnabled(false); - stopButton->setEnabled(false); - stopButton->hide(); - tryAgainButton->setEnabled(true); - tryAgainButton->show(); - setUpdatesEnabled(true); - m_reply->abort(); -} - -void DownloadItem::open() -{ - QFileInfo info(m_output); - QUrl url = QUrl::fromLocalFile(info.absolutePath()); - QDesktopServices::openUrl(url); -} - -void DownloadItem::tryAgain() -{ - if (!tryAgainButton->isEnabled()) - return; - - tryAgainButton->setEnabled(false); - tryAgainButton->setVisible(false); - stopButton->setEnabled(true); - stopButton->setVisible(true); - progressBar->setVisible(true); - - QNetworkReply *r = BrowserApplication::networkAccessManager()->get(QNetworkRequest(m_url)); - if (m_reply) - m_reply->deleteLater(); - if (m_output.exists()) - m_output.remove(); - m_reply = r; - init(); - emit statusChanged(); -} - -void DownloadItem::downloadReadyRead() -{ - if (m_requestFileName && m_output.fileName().isEmpty()) - return; - if (!m_output.isOpen()) { - // in case someone else has already put a file there - if (!m_requestFileName) - getFileName(); - if (!m_output.open(QIODevice::WriteOnly)) { - downloadInfoLabel->setText(tr("Error opening save file: %1") - .arg(m_output.errorString())); - stopButton->click(); - emit statusChanged(); - return; - } - emit statusChanged(); - } - if (-1 == m_output.write(m_reply->readAll())) { - downloadInfoLabel->setText(tr("Error saving: %1") - .arg(m_output.errorString())); - stopButton->click(); - } -} - -void DownloadItem::error(QNetworkReply::NetworkError) -{ - qDebug() << "DownloadItem::error" << m_reply->errorString() << m_url; - downloadInfoLabel->setText(tr("Network Error: %1").arg(m_reply->errorString())); - tryAgainButton->setEnabled(true); - tryAgainButton->setVisible(true); -} - -void DownloadItem::metaDataChanged() -{ - qDebug() << "DownloadItem::metaDataChanged: not handled."; -} - -void DownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) -{ - m_bytesReceived = bytesReceived; - if (bytesTotal == -1) { - progressBar->setValue(0); - progressBar->setMaximum(0); - } else { - progressBar->setValue(bytesReceived); - progressBar->setMaximum(bytesTotal); - } - updateInfoLabel(); -} - -void DownloadItem::updateInfoLabel() -{ - if (m_reply->error() == QNetworkReply::NoError) - return; - - qint64 bytesTotal = progressBar->maximum(); - bool running = !downloadedSuccessfully(); - - // update info label - double speed = m_bytesReceived * 1000.0 / m_downloadTime.elapsed(); - double timeRemaining = ((double)(bytesTotal - m_bytesReceived)) / speed; - QString timeRemainingString = tr("seconds"); - if (timeRemaining > 60) { - timeRemaining = timeRemaining / 60; - timeRemainingString = tr("minutes"); - } - timeRemaining = floor(timeRemaining); - - // When downloading the eta should never be 0 - if (timeRemaining == 0) - timeRemaining = 1; - - QString info; - if (running) { - QString remaining; - if (bytesTotal != 0) - remaining = tr("- %4 %5 remaining") - .arg(timeRemaining) - .arg(timeRemainingString); - info = tr("%1 of %2 (%3/sec) %4") - .arg(dataString(m_bytesReceived)) - .arg(bytesTotal == 0 ? tr("?") : dataString(bytesTotal)) - .arg(dataString((int)speed)) - .arg(remaining); - } else { - if (m_bytesReceived == bytesTotal) - info = dataString(m_output.size()); - else - info = tr("%1 of %2 - Stopped") - .arg(dataString(m_bytesReceived)) - .arg(dataString(bytesTotal)); - } - downloadInfoLabel->setText(info); -} - -QString DownloadItem::dataString(int size) const -{ - QString unit; - if (size < 1024) { - unit = tr("bytes"); - } else if (size < 1024*1024) { - size /= 1024; - unit = tr("kB"); - } else { - size /= 1024*1024; - unit = tr("MB"); - } - return QString(QLatin1String("%1 %2")).arg(size).arg(unit); -} - -bool DownloadItem::downloading() const -{ - return (progressBar->isVisible()); -} - -bool DownloadItem::downloadedSuccessfully() const -{ - return (stopButton->isHidden() && tryAgainButton->isHidden()); -} - -void DownloadItem::finished() -{ - progressBar->hide(); - stopButton->setEnabled(false); - stopButton->hide(); - m_output.close(); - updateInfoLabel(); - emit statusChanged(); -} - -/*! - DownloadManager is a Dialog that contains a list of DownloadItems - - It is a basic download manager. It only downloads the file, doesn't do BitTorrent, - extract zipped files or anything fancy. - */ -DownloadManager::DownloadManager(QWidget *parent) - : QDialog(parent) - , m_autoSaver(new AutoSaver(this)) - , m_manager(BrowserApplication::networkAccessManager()) - , m_iconProvider(0) - , m_removePolicy(Never) -{ - setupUi(this); - downloadsView->setShowGrid(false); - downloadsView->verticalHeader()->hide(); - downloadsView->horizontalHeader()->hide(); - downloadsView->setAlternatingRowColors(true); - downloadsView->horizontalHeader()->setStretchLastSection(true); - m_model = new DownloadModel(this); - downloadsView->setModel(m_model); - connect(cleanupButton, SIGNAL(clicked()), this, SLOT(cleanup())); - load(); -} - -DownloadManager::~DownloadManager() -{ - m_autoSaver->changeOccurred(); - m_autoSaver->saveIfNeccessary(); - if (m_iconProvider) - delete m_iconProvider; -} - -int DownloadManager::activeDownloads() const -{ - int count = 0; - for (int i = 0; i < m_downloads.count(); ++i) { - if (m_downloads.at(i)->stopButton->isEnabled()) - ++count; - } - return count; -} - -void DownloadManager::download(const QNetworkRequest &request, bool requestFileName) -{ - if (request.url().isEmpty()) - return; - handleUnsupportedContent(m_manager->get(request), requestFileName); -} - -void DownloadManager::handleUnsupportedContent(QNetworkReply *reply, bool requestFileName) -{ - if (!reply || reply->url().isEmpty()) - return; - QVariant header = reply->header(QNetworkRequest::ContentLengthHeader); - bool ok; - int size = header.toInt(&ok); - if (ok && size == 0) - return; - - qDebug() << "DownloadManager::handleUnsupportedContent" << reply->url() << "requestFileName" << requestFileName; - DownloadItem *item = new DownloadItem(reply, requestFileName, this); - addItem(item); -} - -void DownloadManager::addItem(DownloadItem *item) -{ - connect(item, SIGNAL(statusChanged()), this, SLOT(updateRow())); - int row = m_downloads.count(); - m_model->beginInsertRows(QModelIndex(), row, row); - m_downloads.append(item); - m_model->endInsertRows(); - updateItemCount(); - if (row == 0) - show(); - downloadsView->setIndexWidget(m_model->index(row, 0), item); - QIcon icon = style()->standardIcon(QStyle::SP_FileIcon); - item->fileIcon->setPixmap(icon.pixmap(48, 48)); - downloadsView->setRowHeight(row, item->sizeHint().height()); -} - -void DownloadManager::updateRow() -{ - DownloadItem *item = qobject_cast(sender()); - int row = m_downloads.indexOf(item); - if (-1 == row) - return; - if (!m_iconProvider) - m_iconProvider = new QFileIconProvider(); - QIcon icon = m_iconProvider->icon(item->m_output.fileName()); - if (icon.isNull()) - icon = style()->standardIcon(QStyle::SP_FileIcon); - item->fileIcon->setPixmap(icon.pixmap(48, 48)); - downloadsView->setRowHeight(row, item->minimumSizeHint().height()); - - bool remove = false; -#if defined(QWEBENGINESETTINGS) - QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); - if (!item->downloading() - && globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) - remove = true; -#endif - - if (item->downloadedSuccessfully() - && removePolicy() == DownloadManager::SuccessFullDownload) { - remove = true; - } - if (remove) - m_model->removeRow(row); - - cleanupButton->setEnabled(m_downloads.count() - activeDownloads() > 0); -} - -DownloadManager::RemovePolicy DownloadManager::removePolicy() const -{ - return m_removePolicy; -} - -void DownloadManager::setRemovePolicy(RemovePolicy policy) -{ - if (policy == m_removePolicy) - return; - m_removePolicy = policy; - m_autoSaver->changeOccurred(); -} - -void DownloadManager::save() const -{ - QSettings settings; - settings.beginGroup(QLatin1String("downloadmanager")); - QMetaEnum removePolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("RemovePolicy")); - settings.setValue(QLatin1String("removeDownloadsPolicy"), QLatin1String(removePolicyEnum.valueToKey(m_removePolicy))); - settings.setValue(QLatin1String("size"), size()); - if (m_removePolicy == Exit) - return; - - for (int i = 0; i < m_downloads.count(); ++i) { - QString key = QString(QLatin1String("download_%1_")).arg(i); - settings.setValue(key + QLatin1String("url"), m_downloads[i]->m_url); - settings.setValue(key + QLatin1String("location"), QFileInfo(m_downloads[i]->m_output).filePath()); - settings.setValue(key + QLatin1String("done"), m_downloads[i]->downloadedSuccessfully()); - } - int i = m_downloads.count(); - QString key = QString(QLatin1String("download_%1_")).arg(i); - while (settings.contains(key + QLatin1String("url"))) { - settings.remove(key + QLatin1String("url")); - settings.remove(key + QLatin1String("location")); - settings.remove(key + QLatin1String("done")); - key = QString(QLatin1String("download_%1_")).arg(++i); - } -} - -void DownloadManager::load() -{ - QSettings settings; - settings.beginGroup(QLatin1String("downloadmanager")); - QSize size = settings.value(QLatin1String("size")).toSize(); - if (size.isValid()) - resize(size); - QByteArray value = settings.value(QLatin1String("removeDownloadsPolicy"), QLatin1String("Never")).toByteArray(); - QMetaEnum removePolicyEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("RemovePolicy")); - m_removePolicy = removePolicyEnum.keyToValue(value) == -1 ? - Never : - static_cast(removePolicyEnum.keyToValue(value)); - - int i = 0; - QString key = QString(QLatin1String("download_%1_")).arg(i); - while (settings.contains(key + QLatin1String("url"))) { - QUrl url = settings.value(key + QLatin1String("url")).toUrl(); - QString fileName = settings.value(key + QLatin1String("location")).toString(); - bool done = settings.value(key + QLatin1String("done"), true).toBool(); - if (!url.isEmpty() && !fileName.isEmpty()) { - DownloadItem *item = new DownloadItem(0, this); - item->m_output.setFileName(fileName); - item->fileNameLabel->setText(QFileInfo(item->m_output.fileName()).fileName()); - item->m_url = url; - item->stopButton->setVisible(false); - item->stopButton->setEnabled(false); - item->tryAgainButton->setVisible(!done); - item->tryAgainButton->setEnabled(!done); - item->progressBar->setVisible(!done); - addItem(item); - } - key = QString(QLatin1String("download_%1_")).arg(++i); - } - cleanupButton->setEnabled(m_downloads.count() - activeDownloads() > 0); -} - -void DownloadManager::cleanup() -{ - if (m_downloads.isEmpty()) - return; - m_model->removeRows(0, m_downloads.count()); - updateItemCount(); - if (m_downloads.isEmpty() && m_iconProvider) { - delete m_iconProvider; - m_iconProvider = 0; - } - m_autoSaver->changeOccurred(); -} - -void DownloadManager::updateItemCount() -{ - int count = m_downloads.count(); - itemCount->setText(count == 1 ? tr("1 Download") : tr("%1 Downloads").arg(count)); -} - -DownloadModel::DownloadModel(DownloadManager *downloadManager, QObject *parent) - : QAbstractListModel(parent) - , m_downloadManager(downloadManager) -{ -} - -QVariant DownloadModel::data(const QModelIndex &index, int role) const -{ - if (index.row() < 0 || index.row() >= rowCount(index.parent())) - return QVariant(); - if (role == Qt::ToolTipRole) - if (!m_downloadManager->m_downloads.at(index.row())->downloadedSuccessfully()) - return m_downloadManager->m_downloads.at(index.row())->downloadInfoLabel->text(); - return QVariant(); -} - -int DownloadModel::rowCount(const QModelIndex &parent) const -{ - return (parent.isValid()) ? 0 : m_downloadManager->m_downloads.count(); -} - -bool DownloadModel::removeRows(int row, int count, const QModelIndex &parent) -{ - if (parent.isValid()) - return false; - - int lastRow = row + count - 1; - for (int i = lastRow; i >= row; --i) { - if (m_downloadManager->m_downloads.at(i)->downloadedSuccessfully() - || m_downloadManager->m_downloads.at(i)->tryAgainButton->isEnabled()) { - beginRemoveRows(parent, i, i); - m_downloadManager->m_downloads.takeAt(i)->deleteLater(); - endRemoveRows(); - } - } - m_downloadManager->m_autoSaver->changeOccurred(); - return true; -} diff --git a/examples/widgets/browser/downloadmanager.h b/examples/widgets/browser/downloadmanager.h deleted file mode 100644 index 072e99efd..000000000 --- a/examples/widgets/browser/downloadmanager.h +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef DOWNLOADMANAGER_H -#define DOWNLOADMANAGER_H - -#include "ui_downloads.h" -#include "ui_downloaditem.h" - -#include - -#include -#include - -class DownloadItem : public QWidget, public Ui_DownloadItem -{ - Q_OBJECT - -signals: - void statusChanged(); - -public: - DownloadItem(QNetworkReply *reply = 0, bool requestFileName = false, QWidget *parent = 0); - bool downloading() const; - bool downloadedSuccessfully() const; - - QUrl m_url; - - QFile m_output; - QNetworkReply *m_reply; - -private slots: - void stop(); - void tryAgain(); - void open(); - - void downloadReadyRead(); - void error(QNetworkReply::NetworkError code); - void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); - void metaDataChanged(); - void finished(); - -private: - void getFileName(); - void init(); - void updateInfoLabel(); - QString dataString(int size) const; - - QString saveFileName(const QString &directory) const; - - bool m_requestFileName; - qint64 m_bytesReceived; - QTime m_downloadTime; -}; - -class AutoSaver; -class DownloadModel; -QT_BEGIN_NAMESPACE -class QFileIconProvider; -QT_END_NAMESPACE - -class DownloadManager : public QDialog, public Ui_DownloadDialog -{ - Q_OBJECT - Q_PROPERTY(RemovePolicy removePolicy READ removePolicy WRITE setRemovePolicy) - Q_ENUMS(RemovePolicy) - -public: - enum RemovePolicy { - Never, - Exit, - SuccessFullDownload - }; - - DownloadManager(QWidget *parent = 0); - ~DownloadManager(); - int activeDownloads() const; - - RemovePolicy removePolicy() const; - void setRemovePolicy(RemovePolicy policy); - -public slots: - void download(const QNetworkRequest &request, bool requestFileName = false); - inline void download(const QUrl &url, bool requestFileName = false) - { download(QNetworkRequest(url), requestFileName); } - void handleUnsupportedContent(QNetworkReply *reply, bool requestFileName = false); - void cleanup(); - -private slots: - void save() const; - void updateRow(); - -private: - void addItem(DownloadItem *item); - void updateItemCount(); - void load(); - - AutoSaver *m_autoSaver; - DownloadModel *m_model; - QNetworkAccessManager *m_manager; - QFileIconProvider *m_iconProvider; - QList m_downloads; - RemovePolicy m_removePolicy; - friend class DownloadModel; -}; - -class DownloadModel : public QAbstractListModel -{ - friend class DownloadManager; - Q_OBJECT - -public: - DownloadModel(DownloadManager *downloadManager, QObject *parent = 0); - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); - -private: - DownloadManager *m_downloadManager; - -}; - -#endif // DOWNLOADMANAGER_H diff --git a/examples/widgets/browser/downloads.ui b/examples/widgets/browser/downloads.ui deleted file mode 100644 index a2e256935..000000000 --- a/examples/widgets/browser/downloads.ui +++ /dev/null @@ -1,83 +0,0 @@ - - DownloadDialog - - - - 0 - 0 - 332 - 252 - - - - Downloads - - - - 0 - - - 0 - - - - - - - - - - false - - - Clean up - - - - - - - Qt::Horizontal - - - - 58 - 24 - - - - - - - - - - 0 Items - - - - - - - Qt::Horizontal - - - - 148 - 20 - - - - - - - - - EditTableView - QTableView -
edittableview.h
-
-
- - -
diff --git a/examples/widgets/browser/edittableview.cpp b/examples/widgets/browser/edittableview.cpp deleted file mode 100644 index 71d9b5706..000000000 --- a/examples/widgets/browser/edittableview.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "edittableview.h" -#include - -EditTableView::EditTableView(QWidget *parent) - : QTableView(parent) -{ -} - -void EditTableView::keyPressEvent(QKeyEvent *event) -{ - if ((event->key() == Qt::Key_Delete - || event->key() == Qt::Key_Backspace) - && model()) { - removeOne(); - } else { - QAbstractItemView::keyPressEvent(event); - } -} - -void EditTableView::removeOne() -{ - if (!model() || !selectionModel()) - return; - int row = currentIndex().row(); - model()->removeRow(row, rootIndex()); - QModelIndex idx = model()->index(row, 0, rootIndex()); - if (!idx.isValid()) - idx = model()->index(row - 1, 0, rootIndex()); - selectionModel()->select(idx, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); -} - -void EditTableView::removeAll() -{ - if (model()) - model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex()); -} diff --git a/examples/widgets/browser/edittableview.h b/examples/widgets/browser/edittableview.h deleted file mode 100644 index 1c865ad42..000000000 --- a/examples/widgets/browser/edittableview.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef EDITTABLEVIEW_H -#define EDITTABLEVIEW_H - -#include - -class EditTableView : public QTableView -{ - Q_OBJECT - -public: - EditTableView(QWidget *parent = 0); - void keyPressEvent(QKeyEvent *event); - -public slots: - void removeOne(); - void removeAll(); -}; - -#endif // EDITTABLEVIEW_H diff --git a/examples/widgets/browser/edittreeview.cpp b/examples/widgets/browser/edittreeview.cpp deleted file mode 100644 index 5b8007856..000000000 --- a/examples/widgets/browser/edittreeview.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "edittreeview.h" - -#include - -EditTreeView::EditTreeView(QWidget *parent) - : QTreeView(parent) -{ -} - -void EditTreeView::keyPressEvent(QKeyEvent *event) -{ - if ((event->key() == Qt::Key_Delete - || event->key() == Qt::Key_Backspace) - && model()) { - removeOne(); - } else { - QAbstractItemView::keyPressEvent(event); - } -} - -void EditTreeView::removeOne() -{ - if (!model()) - return; - QModelIndex ci = currentIndex(); - int row = ci.row(); - model()->removeRow(row, ci.parent()); -} - -void EditTreeView::removeAll() -{ - if (!model()) - return; - model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex()); -} diff --git a/examples/widgets/browser/edittreeview.h b/examples/widgets/browser/edittreeview.h deleted file mode 100644 index 4159812a6..000000000 --- a/examples/widgets/browser/edittreeview.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef EDITTREEVIEW_H -#define EDITTREEVIEW_H - -#include - -class EditTreeView : public QTreeView -{ - Q_OBJECT - -public: - EditTreeView(QWidget *parent = 0); - void keyPressEvent(QKeyEvent *event); - -public slots: - void removeOne(); - void removeAll(); -}; - -#endif // EDITTREEVIEW_H diff --git a/examples/widgets/browser/history.cpp b/examples/widgets/browser/history.cpp deleted file mode 100644 index 9d599f876..000000000 --- a/examples/widgets/browser/history.cpp +++ /dev/null @@ -1,1298 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "history.h" - -#include "autosaver.h" -#include "browserapplication.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include - -static const unsigned int HISTORY_VERSION = 23; - -HistoryManager::HistoryManager(QObject *parent) - : -#if defined(QWEBENGINEHISTORYINTERFACE) - QWebEngineHistoryInterface(parent), -#endif - m_saveTimer(new AutoSaver(this)) - , m_historyLimit(30) - , m_historyModel(0) - , m_historyFilterModel(0) - , m_historyTreeModel(0) -{ - m_expiredTimer.setSingleShot(true); - connect(&m_expiredTimer, SIGNAL(timeout()), - this, SLOT(checkForExpired())); - connect(this, SIGNAL(entryAdded(HistoryItem)), - m_saveTimer, SLOT(changeOccurred())); - connect(this, SIGNAL(entryRemoved(HistoryItem)), - m_saveTimer, SLOT(changeOccurred())); - load(); - - m_historyModel = new HistoryModel(this, this); - m_historyFilterModel = new HistoryFilterModel(m_historyModel, this); - m_historyTreeModel = new HistoryTreeModel(m_historyFilterModel, this); - -#if defined(QWEBENGINEHISTORYINTERFACE) - // QWebEngineHistoryInterface will delete the history manager - QWebEngineHistoryInterface::setDefaultInterface(this); -#endif -} - -HistoryManager::~HistoryManager() -{ - m_saveTimer->saveIfNeccessary(); -} - -QList HistoryManager::history() const -{ - return m_history; -} - -bool HistoryManager::historyContains(const QString &url) const -{ - return m_historyFilterModel->historyContains(url); -} - -void HistoryManager::addHistoryEntry(const QString &url) -{ - QUrl cleanUrl(url); - cleanUrl.setPassword(QString()); - cleanUrl.setHost(cleanUrl.host().toLower()); - HistoryItem item(cleanUrl.toString(), QDateTime::currentDateTime()); - addHistoryItem(item); -} - -void HistoryManager::setHistory(const QList &history, bool loadedAndSorted) -{ - m_history = history; - - // verify that it is sorted by date - if (!loadedAndSorted) - qSort(m_history.begin(), m_history.end()); - - checkForExpired(); - - if (loadedAndSorted) { - m_lastSavedUrl = m_history.value(0).url; - } else { - m_lastSavedUrl = QString(); - m_saveTimer->changeOccurred(); - } - emit historyReset(); -} - -HistoryModel *HistoryManager::historyModel() const -{ - return m_historyModel; -} - -HistoryFilterModel *HistoryManager::historyFilterModel() const -{ - return m_historyFilterModel; -} - -HistoryTreeModel *HistoryManager::historyTreeModel() const -{ - return m_historyTreeModel; -} - -void HistoryManager::checkForExpired() -{ - if (m_historyLimit < 0 || m_history.isEmpty()) - return; - - QDateTime now = QDateTime::currentDateTime(); - int nextTimeout = 0; - - while (!m_history.isEmpty()) { - QDateTime checkForExpired = m_history.last().dateTime; - checkForExpired.setDate(checkForExpired.date().addDays(m_historyLimit)); - if (now.daysTo(checkForExpired) > 7) { - // check at most in a week to prevent int overflows on the timer - nextTimeout = 7 * 86400; - } else { - nextTimeout = now.secsTo(checkForExpired); - } - if (nextTimeout > 0) - break; - HistoryItem item = m_history.takeLast(); - // remove from saved file also - m_lastSavedUrl = QString(); - emit entryRemoved(item); - } - - if (nextTimeout > 0) - m_expiredTimer.start(nextTimeout * 1000); -} - -void HistoryManager::addHistoryItem(const HistoryItem &item) -{ -#if defined(QWEBENGINESETTINGS) - QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); - if (globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) - return; -#endif - - m_history.prepend(item); - emit entryAdded(item); - if (m_history.count() == 1) - checkForExpired(); -} - -void HistoryManager::updateHistoryItem(const QUrl &url, const QString &title) -{ - for (int i = 0; i < m_history.count(); ++i) { - if (url == m_history.at(i).url) { - m_history[i].title = title; - m_saveTimer->changeOccurred(); - if (m_lastSavedUrl.isEmpty()) - m_lastSavedUrl = m_history.at(i).url; - emit entryUpdated(i); - break; - } - } -} - -int HistoryManager::historyLimit() const -{ - return m_historyLimit; -} - -void HistoryManager::setHistoryLimit(int limit) -{ - if (m_historyLimit == limit) - return; - m_historyLimit = limit; - checkForExpired(); - m_saveTimer->changeOccurred(); -} - -void HistoryManager::clear() -{ - m_history.clear(); - m_lastSavedUrl = QString(); - m_saveTimer->changeOccurred(); - m_saveTimer->saveIfNeccessary(); - historyReset(); -} - -void HistoryManager::loadSettings() -{ - // load settings - QSettings settings; - settings.beginGroup(QLatin1String("history")); - m_historyLimit = settings.value(QLatin1String("historyLimit"), 30).toInt(); -} - -void HistoryManager::load() -{ - loadSettings(); - - QFile historyFile(QStandardPaths::writableLocation(QStandardPaths::DataLocation) - + QLatin1String("/history")); - if (!historyFile.exists()) - return; - if (!historyFile.open(QFile::ReadOnly)) { - qWarning() << "Unable to open history file" << historyFile.fileName(); - return; - } - - QList list; - QDataStream in(&historyFile); - // Double check that the history file is sorted as it is read in - bool needToSort = false; - HistoryItem lastInsertedItem; - QByteArray data; - QDataStream stream; - QBuffer buffer; - stream.setDevice(&buffer); - while (!historyFile.atEnd()) { - in >> data; - buffer.close(); - buffer.setBuffer(&data); - buffer.open(QIODevice::ReadOnly); - quint32 ver; - stream >> ver; - if (ver != HISTORY_VERSION) - continue; - HistoryItem item; - stream >> item.url; - stream >> item.dateTime; - stream >> item.title; - - if (!item.dateTime.isValid()) - continue; - - if (item == lastInsertedItem) { - if (lastInsertedItem.title.isEmpty() && !list.isEmpty()) - list[0].title = item.title; - continue; - } - - if (!needToSort && !list.isEmpty() && lastInsertedItem < item) - needToSort = true; - - list.prepend(item); - lastInsertedItem = item; - } - if (needToSort) - qSort(list.begin(), list.end()); - - setHistory(list, true); - - // If we had to sort re-write the whole history sorted - if (needToSort) { - m_lastSavedUrl = QString(); - m_saveTimer->changeOccurred(); - } -} - -void HistoryManager::save() -{ - QSettings settings; - settings.beginGroup(QLatin1String("history")); - settings.setValue(QLatin1String("historyLimit"), m_historyLimit); - - bool saveAll = m_lastSavedUrl.isEmpty(); - int first = m_history.count() - 1; - if (!saveAll) { - // find the first one to save - for (int i = 0; i < m_history.count(); ++i) { - if (m_history.at(i).url == m_lastSavedUrl) { - first = i - 1; - break; - } - } - } - if (first == m_history.count() - 1) - saveAll = true; - - QString directory = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - if (directory.isEmpty()) - directory = QDir::homePath() + QLatin1String("/.") + QCoreApplication::applicationName(); - if (!QFile::exists(directory)) { - QDir dir; - dir.mkpath(directory); - } - - QFile historyFile(directory + QLatin1String("/history")); - // When saving everything use a temporary file to prevent possible data loss. - QTemporaryFile tempFile; - tempFile.setAutoRemove(false); - bool open = false; - if (saveAll) { - open = tempFile.open(); - } else { - open = historyFile.open(QFile::Append); - } - - if (!open) { - qWarning() << "Unable to open history file for saving" - << (saveAll ? tempFile.fileName() : historyFile.fileName()); - return; - } - - QDataStream out(saveAll ? &tempFile : &historyFile); - for (int i = first; i >= 0; --i) { - QByteArray data; - QDataStream stream(&data, QIODevice::WriteOnly); - HistoryItem item = m_history.at(i); - stream << HISTORY_VERSION << item.url << item.dateTime << item.title; - out << data; - } - tempFile.close(); - - if (saveAll) { - if (historyFile.exists() && !historyFile.remove()) - qWarning() << "History: error removing old history." << historyFile.errorString(); - if (!tempFile.rename(historyFile.fileName())) - qWarning() << "History: error moving new history over old." << tempFile.errorString() << historyFile.fileName(); - } - m_lastSavedUrl = m_history.value(0).url; -} - -HistoryModel::HistoryModel(HistoryManager *history, QObject *parent) - : QAbstractTableModel(parent) - , m_history(history) -{ - Q_ASSERT(m_history); - connect(m_history, SIGNAL(historyReset()), - this, SLOT(historyReset())); - connect(m_history, SIGNAL(entryRemoved(HistoryItem)), - this, SLOT(historyReset())); - - connect(m_history, SIGNAL(entryAdded(HistoryItem)), - this, SLOT(entryAdded())); - connect(m_history, SIGNAL(entryUpdated(int)), - this, SLOT(entryUpdated(int))); -} - -void HistoryModel::historyReset() -{ - beginResetModel(); - endResetModel(); -} - -void HistoryModel::entryAdded() -{ - beginInsertRows(QModelIndex(), 0, 0); - endInsertRows(); -} - -void HistoryModel::entryUpdated(int offset) -{ - QModelIndex idx = index(offset, 0); - emit dataChanged(idx, idx); -} - -QVariant HistoryModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal - && role == Qt::DisplayRole) { - switch (section) { - case 0: return tr("Title"); - case 1: return tr("Address"); - } - } - return QAbstractTableModel::headerData(section, orientation, role); -} - -QVariant HistoryModel::data(const QModelIndex &index, int role) const -{ - QList lst = m_history->history(); - if (index.row() < 0 || index.row() >= lst.size()) - return QVariant(); - - const HistoryItem &item = lst.at(index.row()); - switch (role) { - case DateTimeRole: - return item.dateTime; - case DateRole: - return item.dateTime.date(); - case UrlRole: - return QUrl(item.url); - case UrlStringRole: - return item.url; - case Qt::DisplayRole: - case Qt::EditRole: { - switch (index.column()) { - case 0: - // when there is no title try to generate one from the url - if (item.title.isEmpty()) { - QString page = QFileInfo(QUrl(item.url).path()).fileName(); - if (!page.isEmpty()) - return page; - return item.url; - } - return item.title; - case 1: - return item.url; - } - } - case Qt::DecorationRole: - if (index.column() == 0) { - return BrowserApplication::instance()->icon(item.url); - } - } - return QVariant(); -} - -int HistoryModel::columnCount(const QModelIndex &parent) const -{ - return (parent.isValid()) ? 0 : 2; -} - -int HistoryModel::rowCount(const QModelIndex &parent) const -{ - return (parent.isValid()) ? 0 : m_history->history().count(); -} - -bool HistoryModel::removeRows(int row, int count, const QModelIndex &parent) -{ - if (parent.isValid()) - return false; - int lastRow = row + count - 1; - beginRemoveRows(parent, row, lastRow); - QList lst = m_history->history(); - for (int i = lastRow; i >= row; --i) - lst.removeAt(i); - disconnect(m_history, SIGNAL(historyReset()), this, SLOT(historyReset())); - m_history->setHistory(lst); - connect(m_history, SIGNAL(historyReset()), this, SLOT(historyReset())); - endRemoveRows(); - return true; -} - -#define MOVEDROWS 15 - -/* - Maps the first bunch of items of the source model to the root -*/ -HistoryMenuModel::HistoryMenuModel(HistoryTreeModel *sourceModel, QObject *parent) - : QAbstractProxyModel(parent) - , m_treeModel(sourceModel) -{ - setSourceModel(sourceModel); -} - -int HistoryMenuModel::bumpedRows() const -{ - QModelIndex first = m_treeModel->index(0, 0); - if (!first.isValid()) - return 0; - return qMin(m_treeModel->rowCount(first), MOVEDROWS); -} - -int HistoryMenuModel::columnCount(const QModelIndex &parent) const -{ - return m_treeModel->columnCount(mapToSource(parent)); -} - -int HistoryMenuModel::rowCount(const QModelIndex &parent) const -{ - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) { - int folders = sourceModel()->rowCount(); - int bumpedItems = bumpedRows(); - if (bumpedItems <= MOVEDROWS - && bumpedItems == sourceModel()->rowCount(sourceModel()->index(0, 0))) - --folders; - return bumpedItems + folders; - } - - if (parent.internalId() == quintptr(-1)) { - if (parent.row() < bumpedRows()) - return 0; - } - - QModelIndex idx = mapToSource(parent); - int defaultCount = sourceModel()->rowCount(idx); - if (idx == sourceModel()->index(0, 0)) - return defaultCount - bumpedRows(); - return defaultCount; -} - -QModelIndex HistoryMenuModel::mapFromSource(const QModelIndex &sourceIndex) const -{ - // currently not used or autotested - Q_ASSERT(false); - int sr = m_treeModel->mapToSource(sourceIndex).row(); - return createIndex(sourceIndex.row(), sourceIndex.column(), sr); -} - -QModelIndex HistoryMenuModel::mapToSource(const QModelIndex &proxyIndex) const -{ - if (!proxyIndex.isValid()) - return QModelIndex(); - - if (proxyIndex.internalId() == quintptr(-1)) { - int bumpedItems = bumpedRows(); - if (proxyIndex.row() < bumpedItems) - return m_treeModel->index(proxyIndex.row(), proxyIndex.column(), m_treeModel->index(0, 0)); - if (bumpedItems <= MOVEDROWS && bumpedItems == sourceModel()->rowCount(m_treeModel->index(0, 0))) - --bumpedItems; - return m_treeModel->index(proxyIndex.row() - bumpedItems, proxyIndex.column()); - } - - QModelIndex historyIndex = m_treeModel->sourceModel()->index(proxyIndex.internalId(), proxyIndex.column()); - QModelIndex treeIndex = m_treeModel->mapFromSource(historyIndex); - return treeIndex; -} - -QModelIndex HistoryMenuModel::index(int row, int column, const QModelIndex &parent) const -{ - if (row < 0 - || column < 0 || column >= columnCount(parent) - || parent.column() > 0) - return QModelIndex(); - if (!parent.isValid()) - return createIndex(row, column, quintptr(-1)); - - QModelIndex treeIndexParent = mapToSource(parent); - - int bumpedItems = 0; - if (treeIndexParent == m_treeModel->index(0, 0)) - bumpedItems = bumpedRows(); - QModelIndex treeIndex = m_treeModel->index(row + bumpedItems, column, treeIndexParent); - QModelIndex historyIndex = m_treeModel->mapToSource(treeIndex); - int historyRow = historyIndex.row(); - if (historyRow == -1) - historyRow = treeIndex.row(); - return createIndex(row, column, historyRow); -} - -QModelIndex HistoryMenuModel::parent(const QModelIndex &index) const -{ - int offset = index.internalId(); - if (offset == -1 || !index.isValid()) - return QModelIndex(); - - QModelIndex historyIndex = m_treeModel->sourceModel()->index(index.internalId(), 0); - QModelIndex treeIndex = m_treeModel->mapFromSource(historyIndex); - QModelIndex treeIndexParent = treeIndex.parent(); - - int sr = m_treeModel->mapToSource(treeIndexParent).row(); - int bumpedItems = bumpedRows(); - if (bumpedItems <= MOVEDROWS && bumpedItems == sourceModel()->rowCount(sourceModel()->index(0, 0))) - --bumpedItems; - return createIndex(bumpedItems + treeIndexParent.row(), treeIndexParent.column(), sr); -} - - -HistoryMenu::HistoryMenu(QWidget *parent) - : ModelMenu(parent) - , m_history(0) -{ - connect(this, SIGNAL(activated(QModelIndex)), - this, SLOT(activated(QModelIndex))); - setHoverRole(HistoryModel::UrlStringRole); -} - -void HistoryMenu::activated(const QModelIndex &index) -{ - emit openUrl(index.data(HistoryModel::UrlRole).toUrl()); -} - -bool HistoryMenu::prePopulated() -{ - if (!m_history) { - m_history = BrowserApplication::historyManager(); - m_historyMenuModel = new HistoryMenuModel(m_history->historyTreeModel(), this); - setModel(m_historyMenuModel); - } - // initial actions - for (int i = 0; i < m_initialActions.count(); ++i) - addAction(m_initialActions.at(i)); - if (!m_initialActions.isEmpty()) - addSeparator(); - setFirstSeparator(m_historyMenuModel->bumpedRows()); - - return false; -} - -void HistoryMenu::postPopulated() -{ - if (m_history->history().count() > 0) - addSeparator(); - - QAction *showAllAction = new QAction(tr("Show All History"), this); - connect(showAllAction, SIGNAL(triggered()), this, SLOT(showHistoryDialog())); - addAction(showAllAction); - - QAction *clearAction = new QAction(tr("Clear History"), this); - connect(clearAction, SIGNAL(triggered()), m_history, SLOT(clear())); - addAction(clearAction); -} - -void HistoryMenu::showHistoryDialog() -{ - HistoryDialog *dialog = new HistoryDialog(this); - connect(dialog, SIGNAL(openUrl(QUrl)), - this, SIGNAL(openUrl(QUrl))); - dialog->show(); -} - -void HistoryMenu::setInitialActions(QList actions) -{ - m_initialActions = actions; - for (int i = 0; i < m_initialActions.count(); ++i) - addAction(m_initialActions.at(i)); -} - -TreeProxyModel::TreeProxyModel(QObject *parent) : QSortFilterProxyModel(parent) -{ - setSortRole(HistoryModel::DateTimeRole); - setFilterCaseSensitivity(Qt::CaseInsensitive); -} - -bool TreeProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const -{ - if (!source_parent.isValid()) - return true; - return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); -} - -HistoryDialog::HistoryDialog(QWidget *parent, HistoryManager *setHistory) : QDialog(parent) -{ - HistoryManager *history = setHistory; - if (!history) - history = BrowserApplication::historyManager(); - setupUi(this); - tree->setUniformRowHeights(true); - tree->setSelectionBehavior(QAbstractItemView::SelectRows); - tree->setTextElideMode(Qt::ElideMiddle); - QAbstractItemModel *model = history->historyTreeModel(); - TreeProxyModel *proxyModel = new TreeProxyModel(this); - connect(search, SIGNAL(textChanged(QString)), - proxyModel, SLOT(setFilterFixedString(QString))); - connect(removeButton, SIGNAL(clicked()), tree, SLOT(removeOne())); - connect(removeAllButton, SIGNAL(clicked()), history, SLOT(clear())); - proxyModel->setSourceModel(model); - tree->setModel(proxyModel); - tree->setExpanded(proxyModel->index(0, 0), true); - tree->setAlternatingRowColors(true); - QFontMetrics fm(font()); - int header = fm.width(QLatin1Char('m')) * 40; - tree->header()->resizeSection(0, header); - tree->header()->setStretchLastSection(true); - connect(tree, SIGNAL(activated(QModelIndex)), - this, SLOT(open())); - tree->setContextMenuPolicy(Qt::CustomContextMenu); - connect(tree, SIGNAL(customContextMenuRequested(QPoint)), - this, SLOT(customContextMenuRequested(QPoint))); -} - -void HistoryDialog::customContextMenuRequested(const QPoint &pos) -{ - QMenu menu; - QModelIndex index = tree->indexAt(pos); - index = index.sibling(index.row(), 0); - if (index.isValid() && !tree->model()->hasChildren(index)) { - menu.addAction(tr("Open"), this, SLOT(open())); - menu.addSeparator(); - menu.addAction(tr("Copy"), this, SLOT(copy())); - } - menu.addAction(tr("Delete"), tree, SLOT(removeOne())); - menu.exec(QCursor::pos()); -} - -void HistoryDialog::open() -{ - QModelIndex index = tree->currentIndex(); - if (!index.parent().isValid()) - return; - emit openUrl(index.data(HistoryModel::UrlRole).toUrl()); -} - -void HistoryDialog::copy() -{ - QModelIndex index = tree->currentIndex(); - if (!index.parent().isValid()) - return; - QString url = index.data(HistoryModel::UrlStringRole).toString(); - - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(url); -} - -HistoryFilterModel::HistoryFilterModel(QAbstractItemModel *sourceModel, QObject *parent) - : QAbstractProxyModel(parent), - m_loaded(false) -{ - setSourceModel(sourceModel); -} - -int HistoryFilterModel::historyLocation(const QString &url) const -{ - load(); - if (!m_historyHash.contains(url)) - return 0; - return sourceModel()->rowCount() - m_historyHash.value(url); -} - -QVariant HistoryFilterModel::data(const QModelIndex &index, int role) const -{ - return QAbstractProxyModel::data(index, role); -} - -void HistoryFilterModel::setSourceModel(QAbstractItemModel *newSourceModel) -{ - if (sourceModel()) { - disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset())); - disconnect(sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(dataChanged(QModelIndex,QModelIndex))); - disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(sourceRowsInserted(QModelIndex,int,int))); - disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); - } - - QAbstractProxyModel::setSourceModel(newSourceModel); - - if (sourceModel()) { - m_loaded = false; - connect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset())); - connect(sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(sourceDataChanged(QModelIndex,QModelIndex))); - connect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(sourceRowsInserted(QModelIndex,int,int))); - connect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); - } -} - -void HistoryFilterModel::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) -{ - emit dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight)); -} - -QVariant HistoryFilterModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - return sourceModel()->headerData(section, orientation, role); -} - -void HistoryFilterModel::sourceReset() -{ - m_loaded = false; - beginResetModel(); - endResetModel(); -} - -int HistoryFilterModel::rowCount(const QModelIndex &parent) const -{ - load(); - if (parent.isValid()) - return 0; - return m_historyHash.count(); -} - -int HistoryFilterModel::columnCount(const QModelIndex &parent) const -{ - return (parent.isValid()) ? 0 : 2; -} - -QModelIndex HistoryFilterModel::mapToSource(const QModelIndex &proxyIndex) const -{ - load(); - int sourceRow = sourceModel()->rowCount() - proxyIndex.internalId(); - return sourceModel()->index(sourceRow, proxyIndex.column()); -} - -QModelIndex HistoryFilterModel::mapFromSource(const QModelIndex &sourceIndex) const -{ - load(); - QString url = sourceIndex.data(HistoryModel::UrlStringRole).toString(); - if (!m_historyHash.contains(url)) - return QModelIndex(); - - // This can be done in a binary search, but we can't use qBinary find - // because it can't take: qBinaryFind(m_sourceRow.end(), m_sourceRow.begin(), v); - // so if this is a performance bottlneck then convert to binary search, until then - // the cleaner/easier to read code wins the day. - int realRow = -1; - int sourceModelRow = sourceModel()->rowCount() - sourceIndex.row(); - - for (int i = 0; i < m_sourceRow.count(); ++i) { - if (m_sourceRow.at(i) == sourceModelRow) { - realRow = i; - break; - } - } - if (realRow == -1) - return QModelIndex(); - - return createIndex(realRow, sourceIndex.column(), sourceModel()->rowCount() - sourceIndex.row()); -} - -QModelIndex HistoryFilterModel::index(int row, int column, const QModelIndex &parent) const -{ - load(); - if (row < 0 || row >= rowCount(parent) - || column < 0 || column >= columnCount(parent)) - return QModelIndex(); - - return createIndex(row, column, m_sourceRow[row]); -} - -QModelIndex HistoryFilterModel::parent(const QModelIndex &) const -{ - return QModelIndex(); -} - -void HistoryFilterModel::load() const -{ - if (m_loaded) - return; - m_sourceRow.clear(); - m_historyHash.clear(); - m_historyHash.reserve(sourceModel()->rowCount()); - for (int i = 0; i < sourceModel()->rowCount(); ++i) { - QModelIndex idx = sourceModel()->index(i, 0); - QString url = idx.data(HistoryModel::UrlStringRole).toString(); - if (!m_historyHash.contains(url)) { - m_sourceRow.append(sourceModel()->rowCount() - i); - m_historyHash[url] = sourceModel()->rowCount() - i; - } - } - m_loaded = true; -} - -void HistoryFilterModel::sourceRowsInserted(const QModelIndex &parent, int start, int end) -{ - Q_ASSERT(start == end && start == 0); - Q_UNUSED(end); - if (!m_loaded) - return; - QModelIndex idx = sourceModel()->index(start, 0, parent); - QString url = idx.data(HistoryModel::UrlStringRole).toString(); - if (m_historyHash.contains(url)) { - int sourceRow = sourceModel()->rowCount() - m_historyHash[url]; - int realRow = mapFromSource(sourceModel()->index(sourceRow, 0)).row(); - beginRemoveRows(QModelIndex(), realRow, realRow); - m_sourceRow.removeAt(realRow); - m_historyHash.remove(url); - endRemoveRows(); - } - beginInsertRows(QModelIndex(), 0, 0); - m_historyHash.insert(url, sourceModel()->rowCount() - start); - m_sourceRow.insert(0, sourceModel()->rowCount()); - endInsertRows(); -} - -void HistoryFilterModel::sourceRowsRemoved(const QModelIndex &, int start, int end) -{ - Q_UNUSED(start); - Q_UNUSED(end); - sourceReset(); -} - -/* - Removing a continuous block of rows will remove filtered rows too as this is - the users intention. -*/ -bool HistoryFilterModel::removeRows(int row, int count, const QModelIndex &parent) -{ - if (row < 0 || count <= 0 || row + count > rowCount(parent) || parent.isValid()) - return false; - int lastRow = row + count - 1; - disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); - beginRemoveRows(parent, row, lastRow); - int oldCount = rowCount(); - int start = sourceModel()->rowCount() - m_sourceRow.value(row); - int end = sourceModel()->rowCount() - m_sourceRow.value(lastRow); - sourceModel()->removeRows(start, end - start + 1); - endRemoveRows(); - connect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); - m_loaded = false; - if (oldCount - count != rowCount()) { - beginResetModel(); - endResetModel(); - } - return true; -} - -HistoryCompletionModel::HistoryCompletionModel(QObject *parent) - : QAbstractProxyModel(parent) -{ -} - -QVariant HistoryCompletionModel::data(const QModelIndex &index, int role) const -{ - if (sourceModel() - && (role == Qt::EditRole || role == Qt::DisplayRole) - && index.isValid()) { - QModelIndex idx = mapToSource(index); - idx = idx.sibling(idx.row(), 1); - QString urlString = idx.data(HistoryModel::UrlStringRole).toString(); - if (index.row() % 2) { - QUrl url = urlString; - QString s = url.toString(QUrl::RemoveScheme - | QUrl::RemoveUserInfo - | QUrl::StripTrailingSlash); - return s.mid(2); // strip // from the front - } - return urlString; - } - return QAbstractProxyModel::data(index, role); -} - -int HistoryCompletionModel::rowCount(const QModelIndex &parent) const -{ - return (parent.isValid() || !sourceModel()) ? 0 : sourceModel()->rowCount(parent) * 2; -} - -int HistoryCompletionModel::columnCount(const QModelIndex &parent) const -{ - return (parent.isValid()) ? 0 : 1; -} - -QModelIndex HistoryCompletionModel::mapFromSource(const QModelIndex &sourceIndex) const -{ - int row = sourceIndex.row() * 2; - return index(row, sourceIndex.column()); -} - -QModelIndex HistoryCompletionModel::mapToSource(const QModelIndex &proxyIndex) const -{ - if (!sourceModel()) - return QModelIndex(); - int row = proxyIndex.row() / 2; - return sourceModel()->index(row, proxyIndex.column()); -} - -QModelIndex HistoryCompletionModel::index(int row, int column, const QModelIndex &parent) const -{ - if (row < 0 || row >= rowCount(parent) - || column < 0 || column >= columnCount(parent)) - return QModelIndex(); - return createIndex(row, column); -} - -QModelIndex HistoryCompletionModel::parent(const QModelIndex &) const -{ - return QModelIndex(); -} - -void HistoryCompletionModel::setSourceModel(QAbstractItemModel *newSourceModel) -{ - if (sourceModel()) { - disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset())); - disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(sourceReset())); - disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(sourceReset())); - } - - QAbstractProxyModel::setSourceModel(newSourceModel); - - if (newSourceModel) { - connect(newSourceModel, SIGNAL(modelReset()), this, SLOT(sourceReset())); - connect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(sourceReset())); - connect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(sourceReset())); - } - - beginResetModel(); - endResetModel(); -} - -void HistoryCompletionModel::sourceReset() -{ - beginResetModel(); - endResetModel(); -} - -HistoryTreeModel::HistoryTreeModel(QAbstractItemModel *sourceModel, QObject *parent) - : QAbstractProxyModel(parent) -{ - setSourceModel(sourceModel); -} - -QVariant HistoryTreeModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - return sourceModel()->headerData(section, orientation, role); -} - -QVariant HistoryTreeModel::data(const QModelIndex &index, int role) const -{ - if ((role == Qt::EditRole || role == Qt::DisplayRole)) { - int start = index.internalId(); - if (start == 0) { - int offset = sourceDateRow(index.row()); - if (index.column() == 0) { - QModelIndex idx = sourceModel()->index(offset, 0); - QDate date = idx.data(HistoryModel::DateRole).toDate(); - if (date == QDate::currentDate()) - return tr("Earlier Today"); - return date.toString(QLatin1String("dddd, MMMM d, yyyy")); - } - if (index.column() == 1) { - return tr("%1 items").arg(rowCount(index.sibling(index.row(), 0))); - } - } - } - if (role == Qt::DecorationRole && index.column() == 0 && !index.parent().isValid()) - return QIcon(QLatin1String(":history.png")); - if (role == HistoryModel::DateRole && index.column() == 0 && index.internalId() == 0) { - int offset = sourceDateRow(index.row()); - QModelIndex idx = sourceModel()->index(offset, 0); - return idx.data(HistoryModel::DateRole); - } - - return QAbstractProxyModel::data(index, role); -} - -int HistoryTreeModel::columnCount(const QModelIndex &parent) const -{ - return sourceModel()->columnCount(mapToSource(parent)); -} - -int HistoryTreeModel::rowCount(const QModelIndex &parent) const -{ - if ( parent.internalId() != 0 - || parent.column() > 0 - || !sourceModel()) - return 0; - - // row count OF dates - if (!parent.isValid()) { - if (!m_sourceRowCache.isEmpty()) - return m_sourceRowCache.count(); - QDate currentDate; - int rows = 0; - int totalRows = sourceModel()->rowCount(); - - for (int i = 0; i < totalRows; ++i) { - QDate rowDate = sourceModel()->index(i, 0).data(HistoryModel::DateRole).toDate(); - if (rowDate != currentDate) { - m_sourceRowCache.append(i); - currentDate = rowDate; - ++rows; - } - } - Q_ASSERT(m_sourceRowCache.count() == rows); - return rows; - } - - // row count FOR a date - int start = sourceDateRow(parent.row()); - int end = sourceDateRow(parent.row() + 1); - return (end - start); -} - -// Translate the top level date row into the offset where that date starts -int HistoryTreeModel::sourceDateRow(int row) const -{ - if (row <= 0) - return 0; - - if (m_sourceRowCache.isEmpty()) - rowCount(QModelIndex()); - - if (row >= m_sourceRowCache.count()) { - if (!sourceModel()) - return 0; - return sourceModel()->rowCount(); - } - return m_sourceRowCache.at(row); -} - -QModelIndex HistoryTreeModel::mapToSource(const QModelIndex &proxyIndex) const -{ - int offset = proxyIndex.internalId(); - if (offset == 0) - return QModelIndex(); - int startDateRow = sourceDateRow(offset - 1); - return sourceModel()->index(startDateRow + proxyIndex.row(), proxyIndex.column()); -} - -QModelIndex HistoryTreeModel::index(int row, int column, const QModelIndex &parent) const -{ - if (row < 0 - || column < 0 || column >= columnCount(parent) - || parent.column() > 0) - return QModelIndex(); - - if (!parent.isValid()) - return createIndex(row, column); - return createIndex(row, column, parent.row() + 1); -} - -QModelIndex HistoryTreeModel::parent(const QModelIndex &index) const -{ - int offset = index.internalId(); - if (offset == 0 || !index.isValid()) - return QModelIndex(); - return createIndex(offset - 1, 0); -} - -bool HistoryTreeModel::hasChildren(const QModelIndex &parent) const -{ - QModelIndex grandparent = parent.parent(); - if (!grandparent.isValid()) - return true; - return false; -} - -Qt::ItemFlags HistoryTreeModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return Qt::NoItemFlags; - return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled; -} - -bool HistoryTreeModel::removeRows(int row, int count, const QModelIndex &parent) -{ - if (row < 0 || count <= 0 || row + count > rowCount(parent)) - return false; - - if (parent.isValid()) { - // removing pages - int offset = sourceDateRow(parent.row()); - return sourceModel()->removeRows(offset + row, count); - } else { - // removing whole dates - for (int i = row + count - 1; i >= row; --i) { - QModelIndex dateParent = index(i, 0); - int offset = sourceDateRow(dateParent.row()); - if (!sourceModel()->removeRows(offset, rowCount(dateParent))) - return false; - } - } - return true; -} - -void HistoryTreeModel::setSourceModel(QAbstractItemModel *newSourceModel) -{ - if (sourceModel()) { - disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset())); - disconnect(sourceModel(), SIGNAL(layoutChanged()), this, SLOT(sourceReset())); - disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(sourceRowsInserted(QModelIndex,int,int))); - disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); - } - - QAbstractProxyModel::setSourceModel(newSourceModel); - - if (newSourceModel) { - connect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset())); - connect(sourceModel(), SIGNAL(layoutChanged()), this, SLOT(sourceReset())); - connect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(sourceRowsInserted(QModelIndex,int,int))); - connect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); - } - - beginResetModel(); - endResetModel(); -} - -void HistoryTreeModel::sourceReset() -{ - beginResetModel(); - m_sourceRowCache.clear(); - endResetModel(); -} - -void HistoryTreeModel::sourceRowsInserted(const QModelIndex &parent, int start, int end) -{ - Q_UNUSED(parent); // Avoid warnings when compiling release - Q_ASSERT(!parent.isValid()); - if (start != 0 || start != end) { - beginResetModel(); - m_sourceRowCache.clear(); - endResetModel(); - return; - } - - m_sourceRowCache.clear(); - QModelIndex treeIndex = mapFromSource(sourceModel()->index(start, 0)); - QModelIndex treeParent = treeIndex.parent(); - if (rowCount(treeParent) == 1) { - beginInsertRows(QModelIndex(), 0, 0); - endInsertRows(); - } else { - beginInsertRows(treeParent, treeIndex.row(), treeIndex.row()); - endInsertRows(); - } -} - -QModelIndex HistoryTreeModel::mapFromSource(const QModelIndex &sourceIndex) const -{ - if (!sourceIndex.isValid()) - return QModelIndex(); - - if (m_sourceRowCache.isEmpty()) - rowCount(QModelIndex()); - - QList::iterator it; - it = qLowerBound(m_sourceRowCache.begin(), m_sourceRowCache.end(), sourceIndex.row()); - if (*it != sourceIndex.row()) - --it; - int dateRow = qMax(0, it - m_sourceRowCache.begin()); - int row = sourceIndex.row() - m_sourceRowCache.at(dateRow); - return createIndex(row, sourceIndex.column(), dateRow + 1); -} - -void HistoryTreeModel::sourceRowsRemoved(const QModelIndex &parent, int start, int end) -{ - Q_UNUSED(parent); // Avoid warnings when compiling release - Q_ASSERT(!parent.isValid()); - if (m_sourceRowCache.isEmpty()) - return; - for (int i = end; i >= start;) { - QList::iterator it; - it = qLowerBound(m_sourceRowCache.begin(), m_sourceRowCache.end(), i); - // playing it safe - if (it == m_sourceRowCache.end()) { - beginResetModel(); - m_sourceRowCache.clear(); - endResetModel(); - return; - } - - if (*it != i) - --it; - int row = qMax(0, it - m_sourceRowCache.begin()); - int offset = m_sourceRowCache[row]; - QModelIndex dateParent = index(row, 0); - // If we can remove all the rows in the date do that and skip over them - int rc = rowCount(dateParent); - if (i - rc + 1 == offset && start <= i - rc + 1) { - beginRemoveRows(QModelIndex(), row, row); - m_sourceRowCache.removeAt(row); - i -= rc + 1; - } else { - beginRemoveRows(dateParent, i - offset, i - offset); - ++row; - --i; - } - for (int j = row; j < m_sourceRowCache.count(); ++j) - --m_sourceRowCache[j]; - endRemoveRows(); - } -} diff --git a/examples/widgets/browser/history.h b/examples/widgets/browser/history.h deleted file mode 100644 index 4006f3415..000000000 --- a/examples/widgets/browser/history.h +++ /dev/null @@ -1,354 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef HISTORY_H -#define HISTORY_H - -#include "modelmenu.h" - -#include -#include -#include -#include -#include - -#include - -#include - -class HistoryItem -{ -public: - HistoryItem() {} - HistoryItem(const QString &u, - const QDateTime &d = QDateTime(), const QString &t = QString()) - : title(t), url(u), dateTime(d) {} - - inline bool operator==(const HistoryItem &other) const - { return other.title == title - && other.url == url && other.dateTime == dateTime; } - - // history is sorted in reverse - inline bool operator <(const HistoryItem &other) const - { return dateTime > other.dateTime; } - - QString title; - QString url; - QDateTime dateTime; -}; - -class AutoSaver; -class HistoryModel; -class HistoryFilterModel; -class HistoryTreeModel; -class HistoryManager -#if defined(QWEBENGINEHISTORYINTERFACE) - : public QWebEngineHistoryInterface -#else - : public QObject -#endif -{ - Q_OBJECT - Q_PROPERTY(int historyLimit READ historyLimit WRITE setHistoryLimit) - -signals: - void historyReset(); - void entryAdded(const HistoryItem &item); - void entryRemoved(const HistoryItem &item); - void entryUpdated(int offset); - -public: - HistoryManager(QObject *parent = 0); - ~HistoryManager(); - - bool historyContains(const QString &url) const; - void addHistoryEntry(const QString &url); - - void updateHistoryItem(const QUrl &url, const QString &title); - - int historyLimit() const; - void setHistoryLimit(int limit); - - QList history() const; - void setHistory(const QList &history, bool loadedAndSorted = false); - - // History manager keeps around these models for use by the completer and other classes - HistoryModel *historyModel() const; - HistoryFilterModel *historyFilterModel() const; - HistoryTreeModel *historyTreeModel() const; - -public slots: - void clear(); - void loadSettings(); - -private slots: - void save(); - void checkForExpired(); - -protected: - void addHistoryItem(const HistoryItem &item); - -private: - void load(); - - AutoSaver *m_saveTimer; - int m_historyLimit; - QTimer m_expiredTimer; - QList m_history; - QString m_lastSavedUrl; - - HistoryModel *m_historyModel; - HistoryFilterModel *m_historyFilterModel; - HistoryTreeModel *m_historyTreeModel; -}; - -class HistoryModel : public QAbstractTableModel -{ - Q_OBJECT - -public slots: - void historyReset(); - void entryAdded(); - void entryUpdated(int offset); - -public: - enum Roles { - DateRole = Qt::UserRole + 1, - DateTimeRole = Qt::UserRole + 2, - UrlRole = Qt::UserRole + 3, - UrlStringRole = Qt::UserRole + 4 - }; - - HistoryModel(HistoryManager *history, QObject *parent = 0); - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); - -private: - HistoryManager *m_history; -}; - -/*! - Proxy model that will remove any duplicate entries. - Both m_sourceRow and m_historyHash store their offsets not from - the front of the list, but as offsets from the back. - */ -class HistoryFilterModel : public QAbstractProxyModel -{ - Q_OBJECT - -public: - HistoryFilterModel(QAbstractItemModel *sourceModel, QObject *parent = 0); - - inline bool historyContains(const QString &url) const - { load(); return m_historyHash.contains(url); } - int historyLocation(const QString &url) const; - - QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; - QModelIndex mapToSource(const QModelIndex &proxyIndex) const; - void setSourceModel(QAbstractItemModel *sourceModel); - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - QModelIndex index(int, int, const QModelIndex& = QModelIndex()) const; - QModelIndex parent(const QModelIndex& index= QModelIndex()) const; - bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - -private slots: - void sourceReset(); - void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - void sourceRowsInserted(const QModelIndex &parent, int start, int end); - void sourceRowsRemoved(const QModelIndex &, int, int); - -private: - void load() const; - - mutable QList m_sourceRow; - mutable QHash m_historyHash; - mutable bool m_loaded; -}; - -/* - The history menu - - Removes the first twenty entries and puts them as children of the top level. - - If there are less then twenty entries then the first folder is also removed. - - The mapping is done by knowing that HistoryTreeModel is over a table - We store that row offset in our index's private data. -*/ -class HistoryMenuModel : public QAbstractProxyModel -{ - Q_OBJECT - -public: - HistoryMenuModel(HistoryTreeModel *sourceModel, QObject *parent = 0); - int columnCount(const QModelIndex &parent) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - QModelIndex mapFromSource(const QModelIndex & sourceIndex) const; - QModelIndex mapToSource(const QModelIndex & proxyIndex) const; - QModelIndex index(int, int, const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &index = QModelIndex()) const; - - int bumpedRows() const; - -private: - HistoryTreeModel *m_treeModel; -}; - -// Menu that is dynamically populated from the history -class HistoryMenu : public ModelMenu -{ - Q_OBJECT - -signals: - void openUrl(const QUrl &url); - -public: - HistoryMenu(QWidget *parent = 0); - void setInitialActions(QList actions); - -protected: - bool prePopulated(); - void postPopulated(); - -private slots: - void activated(const QModelIndex &index); - void showHistoryDialog(); - -private: - HistoryManager *m_history; - HistoryMenuModel *m_historyMenuModel; - QList m_initialActions; -}; - -// proxy model for the history model that -// exposes each url http://www.foo.com and it url starting at the host www.foo.com -class HistoryCompletionModel : public QAbstractProxyModel -{ - Q_OBJECT - -public: - HistoryCompletionModel(QObject *parent = 0); - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; - QModelIndex mapToSource(const QModelIndex &proxyIndex) const; - QModelIndex index(int, int, const QModelIndex& = QModelIndex()) const; - QModelIndex parent(const QModelIndex& index= QModelIndex()) const; - void setSourceModel(QAbstractItemModel *sourceModel); - -private slots: - void sourceReset(); - -}; - -// proxy model for the history model that converts the list -// into a tree, one top level node per day. -// Used in the HistoryDialog. -class HistoryTreeModel : public QAbstractProxyModel -{ - Q_OBJECT - -public: - HistoryTreeModel(QAbstractItemModel *sourceModel, QObject *parent = 0); - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - int columnCount(const QModelIndex &parent) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; - QModelIndex mapToSource(const QModelIndex &proxyIndex) const; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &index= QModelIndex()) const; - bool hasChildren(const QModelIndex &parent = QModelIndex()) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - - void setSourceModel(QAbstractItemModel *sourceModel); - -private slots: - void sourceReset(); - void sourceRowsInserted(const QModelIndex &parent, int start, int end); - void sourceRowsRemoved(const QModelIndex &parent, int start, int end); - -private: - int sourceDateRow(int row) const; - mutable QList m_sourceRowCache; - -}; - -// A modified QSortFilterProxyModel that always accepts the root nodes in the tree -// so filtering is only done on the children. -// Used in the HistoryDialog -class TreeProxyModel : public QSortFilterProxyModel -{ - Q_OBJECT - -public: - TreeProxyModel(QObject *parent = 0); - -protected: - bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; -}; - -#include "ui_history.h" - -class HistoryDialog : public QDialog, public Ui_HistoryDialog -{ - Q_OBJECT - -signals: - void openUrl(const QUrl &url); - -public: - HistoryDialog(QWidget *parent = 0, HistoryManager *history = 0); - -private slots: - void customContextMenuRequested(const QPoint &pos); - void open(); - void copy(); - -}; - -#endif // HISTORY_H diff --git a/examples/widgets/browser/history.ui b/examples/widgets/browser/history.ui deleted file mode 100644 index 0944940e7..000000000 --- a/examples/widgets/browser/history.ui +++ /dev/null @@ -1,106 +0,0 @@ - - HistoryDialog - - - - 0 - 0 - 758 - 450 - - - - History - - - - - - Qt::Horizontal - - - - 252 - 20 - - - - - - - - - - - - - - - - &Remove - - - - - - - Remove &All - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - QDialogButtonBox::Ok - - - - - - - - - - SearchLineEdit - QLineEdit -
searchlineedit.h
-
- - EditTreeView - QTreeView -
edittreeview.h
-
-
- - - - buttonBox - accepted() - HistoryDialog - accept() - - - 472 - 329 - - - 461 - 356 - - - - -
diff --git a/examples/widgets/browser/htmls/htmls.qrc b/examples/widgets/browser/htmls/htmls.qrc deleted file mode 100644 index 03b256ccb..000000000 --- a/examples/widgets/browser/htmls/htmls.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - notfound.html - - diff --git a/examples/widgets/browser/htmls/notfound.html b/examples/widgets/browser/htmls/notfound.html deleted file mode 100644 index e89845aa6..000000000 --- a/examples/widgets/browser/htmls/notfound.html +++ /dev/null @@ -1,63 +0,0 @@ - - -%1 - - - -
- -

%2

-

When connecting to: %3.

-
    -
  • Check the address for errors such as ww.example.com - instead of www.example.com
  • -
  • If the address is correct, try checking the network - connection.
  • -
  • If your computer or network is protected by a firewall or - proxy, make sure that the browser demo is permitted to access - the network.
  • -
-

-
- - diff --git a/examples/widgets/browser/main.cpp b/examples/widgets/browser/main.cpp deleted file mode 100644 index 9baf01f42..000000000 --- a/examples/widgets/browser/main.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "browserapplication.h" - -int main(int argc, char **argv) -{ - Q_INIT_RESOURCE(data); - BrowserApplication application(argc, argv); - if (!application.isTheOnlyBrowser()) - return 0; - application.newMainWindow(); - return application.exec(); -} diff --git a/examples/widgets/browser/modelmenu.cpp b/examples/widgets/browser/modelmenu.cpp deleted file mode 100644 index 56453b080..000000000 --- a/examples/widgets/browser/modelmenu.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "modelmenu.h" - -#include -#include - -ModelMenu::ModelMenu(QWidget * parent) - : QMenu(parent) - , m_maxRows(7) - , m_firstSeparator(-1) - , m_maxWidth(-1) - , m_hoverRole(0) - , m_separatorRole(0) - , m_model(0) -{ - connect(this, SIGNAL(aboutToShow()), this, SLOT(aboutToShow())); -} - -bool ModelMenu::prePopulated() -{ - return false; -} - -void ModelMenu::postPopulated() -{ -} - -void ModelMenu::setModel(QAbstractItemModel *model) -{ - m_model = model; -} - -QAbstractItemModel *ModelMenu::model() const -{ - return m_model; -} - -void ModelMenu::setMaxRows(int max) -{ - m_maxRows = max; -} - -int ModelMenu::maxRows() const -{ - return m_maxRows; -} - -void ModelMenu::setFirstSeparator(int offset) -{ - m_firstSeparator = offset; -} - -int ModelMenu::firstSeparator() const -{ - return m_firstSeparator; -} - -void ModelMenu::setRootIndex(const QModelIndex &index) -{ - m_root = index; -} - -QModelIndex ModelMenu::rootIndex() const -{ - return m_root; -} - -void ModelMenu::setHoverRole(int role) -{ - m_hoverRole = role; -} - -int ModelMenu::hoverRole() const -{ - return m_hoverRole; -} - -void ModelMenu::setSeparatorRole(int role) -{ - m_separatorRole = role; -} - -int ModelMenu::separatorRole() const -{ - return m_separatorRole; -} - -Q_DECLARE_METATYPE(QModelIndex) -void ModelMenu::aboutToShow() -{ - if (QMenu *menu = qobject_cast(sender())) { - QVariant v = menu->menuAction()->data(); - if (v.canConvert()) { - QModelIndex idx = qvariant_cast(v); - createMenu(idx, -1, menu, menu); - disconnect(menu, SIGNAL(aboutToShow()), this, SLOT(aboutToShow())); - return; - } - } - - clear(); - if (prePopulated()) - addSeparator(); - int max = m_maxRows; - if (max != -1) - max += m_firstSeparator; - createMenu(m_root, max, this, this); - postPopulated(); -} - -void ModelMenu::createMenu(const QModelIndex &parent, int max, QMenu *parentMenu, QMenu *menu) -{ - if (!menu) { - QString title = parent.data().toString(); - menu = new QMenu(title, this); - QIcon icon = qvariant_cast(parent.data(Qt::DecorationRole)); - menu->setIcon(icon); - parentMenu->addMenu(menu); - QVariant v; - v.setValue(parent); - menu->menuAction()->setData(v); - connect(menu, SIGNAL(aboutToShow()), this, SLOT(aboutToShow())); - return; - } - - int end = m_model->rowCount(parent); - if (max != -1) - end = qMin(max, end); - - connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(triggered(QAction*))); - connect(menu, SIGNAL(hovered(QAction*)), this, SLOT(hovered(QAction*))); - - for (int i = 0; i < end; ++i) { - QModelIndex idx = m_model->index(i, 0, parent); - if (m_model->hasChildren(idx)) { - createMenu(idx, -1, menu); - } else { - if (m_separatorRole != 0 - && idx.data(m_separatorRole).toBool()) - addSeparator(); - else - menu->addAction(makeAction(idx)); - } - if (menu == this && i == m_firstSeparator - 1) - addSeparator(); - } -} - -QAction *ModelMenu::makeAction(const QModelIndex &index) -{ - QIcon icon = qvariant_cast(index.data(Qt::DecorationRole)); - QAction *action = makeAction(icon, index.data().toString(), this); - QVariant v; - v.setValue(index); - action->setData(v); - return action; -} - -QAction *ModelMenu::makeAction(const QIcon &icon, const QString &text, QObject *parent) -{ - QFontMetrics fm(font()); - if (-1 == m_maxWidth) - m_maxWidth = fm.width(QLatin1Char('m')) * 30; - QString smallText = fm.elidedText(text, Qt::ElideMiddle, m_maxWidth); - return new QAction(icon, smallText, parent); -} - -void ModelMenu::triggered(QAction *action) -{ - QVariant v = action->data(); - if (v.canConvert()) { - QModelIndex idx = qvariant_cast(v); - emit activated(idx); - } -} - -void ModelMenu::hovered(QAction *action) -{ - QVariant v = action->data(); - if (v.canConvert()) { - QModelIndex idx = qvariant_cast(v); - QString hoveredString = idx.data(m_hoverRole).toString(); - if (!hoveredString.isEmpty()) - emit hovered(hoveredString); - } -} diff --git a/examples/widgets/browser/modelmenu.h b/examples/widgets/browser/modelmenu.h deleted file mode 100644 index 4045a7758..000000000 --- a/examples/widgets/browser/modelmenu.h +++ /dev/null @@ -1,104 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MODELMENU_H -#define MODELMENU_H - -#include -#include - -// A QMenu that is dynamically populated from a QAbstractItemModel -class ModelMenu : public QMenu -{ - Q_OBJECT - -signals: - void activated(const QModelIndex &index); - void hovered(const QString &text); - -public: - ModelMenu(QWidget *parent = 0); - - void setModel(QAbstractItemModel *model); - QAbstractItemModel *model() const; - - void setMaxRows(int max); - int maxRows() const; - - void setFirstSeparator(int offset); - int firstSeparator() const; - - void setRootIndex(const QModelIndex &index); - QModelIndex rootIndex() const; - - void setHoverRole(int role); - int hoverRole() const; - - void setSeparatorRole(int role); - int separatorRole() const; - - QAction *makeAction(const QIcon &icon, const QString &text, QObject *parent); - -protected: - // add any actions before the tree, return true if any actions are added. - virtual bool prePopulated(); - // add any actions after the tree - virtual void postPopulated(); - // put all of the children of parent into menu up to max - void createMenu(const QModelIndex &parent, int max, QMenu *parentMenu = 0, QMenu *menu = 0); - -private slots: - void aboutToShow(); - void triggered(QAction *action); - void hovered(QAction *action); - -private: - QAction *makeAction(const QModelIndex &index); - int m_maxRows; - int m_firstSeparator; - int m_maxWidth; - int m_hoverRole; - int m_separatorRole; - QAbstractItemModel *m_model; - QPersistentModelIndex m_root; -}; - -#endif // MODELMENU_H diff --git a/examples/widgets/browser/networkaccessmanager.cpp b/examples/widgets/browser/networkaccessmanager.cpp deleted file mode 100644 index a7127ade6..000000000 --- a/examples/widgets/browser/networkaccessmanager.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "networkaccessmanager.h" - -#include "browserapplication.h" -#include "browsermainwindow.h" - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -NetworkAccessManager::NetworkAccessManager(QObject *parent) - : QNetworkAccessManager(parent), - requestFinishedCount(0), requestFinishedFromCacheCount(0), requestFinishedPipelinedCount(0), - requestFinishedSecureCount(0), requestFinishedDownloadBufferCount(0) -{ - connect(this, SIGNAL(finished(QNetworkReply*)), - SLOT(requestFinished(QNetworkReply*))); -#ifndef QT_NO_OPENSSL - connect(this, SIGNAL(sslErrors(QNetworkReply*,QList)), - SLOT(sslErrors(QNetworkReply*,QList))); -#endif - loadSettings(); - - QNetworkDiskCache *diskCache = new QNetworkDiskCache(this); - QString location = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); - diskCache->setCacheDirectory(location); - setCache(diskCache); -} - -QNetworkReply* NetworkAccessManager::createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData) -{ - QNetworkRequest request = req; // copy so we can modify - // this is a temporary hack until we properly use the pipelining flags from QtWebkit - // pipeline everything! :) - request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); - return QNetworkAccessManager::createRequest(op, request, outgoingData); -} - -void NetworkAccessManager::requestFinished(QNetworkReply *reply) -{ - requestFinishedCount++; - - if (reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool() == true) - requestFinishedFromCacheCount++; - - if (reply->attribute(QNetworkRequest::HttpPipeliningWasUsedAttribute).toBool() == true) - requestFinishedPipelinedCount++; - - if (reply->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool() == true) - requestFinishedSecureCount++; - - if (reply->attribute(QNetworkRequest::DownloadBufferAttribute).isValid() == true) - requestFinishedDownloadBufferCount++; - - if (requestFinishedCount % 10) - return; - -#ifdef QT_DEBUG - double pctCached = (double(requestFinishedFromCacheCount) * 100.0/ double(requestFinishedCount)); - double pctPipelined = (double(requestFinishedPipelinedCount) * 100.0/ double(requestFinishedCount)); - double pctSecure = (double(requestFinishedSecureCount) * 100.0/ double(requestFinishedCount)); - double pctDownloadBuffer = (double(requestFinishedDownloadBufferCount) * 100.0/ double(requestFinishedCount)); - - qDebug("STATS [%lli requests total] [%3.2f%% from cache] [%3.2f%% pipelined] [%3.2f%% SSL/TLS] [%3.2f%% Zerocopy]", requestFinishedCount, pctCached, pctPipelined, pctSecure, pctDownloadBuffer); -#endif -} - -void NetworkAccessManager::loadSettings() -{ - QSettings settings; - settings.beginGroup(QLatin1String("proxy")); - QNetworkProxy proxy; - if (settings.value(QLatin1String("enabled"), false).toBool()) { - if (settings.value(QLatin1String("type"), 0).toInt() == 0) - proxy = QNetworkProxy::Socks5Proxy; - else - proxy = QNetworkProxy::HttpProxy; - proxy.setHostName(settings.value(QLatin1String("hostName")).toString()); - proxy.setPort(settings.value(QLatin1String("port"), 1080).toInt()); - proxy.setUser(settings.value(QLatin1String("userName")).toString()); - proxy.setPassword(settings.value(QLatin1String("password")).toString()); - } - setProxy(proxy); -} - -#ifndef QT_NO_OPENSSL -void NetworkAccessManager::sslErrors(QNetworkReply *reply, const QList &error) -{ - // check if SSL certificate has been trusted already - QString replyHost = reply->url().host() + QString(":%1").arg(reply->url().port()); - if (! sslTrustedHostList.contains(replyHost)) { - BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow(); - - QStringList errorStrings; - for (int i = 0; i < error.count(); ++i) - errorStrings += error.at(i).errorString(); - QString errors = errorStrings.join(QLatin1String("\n")); - int ret = QMessageBox::warning(mainWindow, QCoreApplication::applicationName(), - tr("SSL Errors:\n\n%1\n\n%2\n\n" - "Do you want to ignore these errors for this host?").arg(reply->url().toString()).arg(errors), - QMessageBox::Yes | QMessageBox::No, - QMessageBox::No); - if (ret == QMessageBox::Yes) { - reply->ignoreSslErrors(); - sslTrustedHostList.append(replyHost); - } - } -} -#endif diff --git a/examples/widgets/browser/networkaccessmanager.h b/examples/widgets/browser/networkaccessmanager.h deleted file mode 100644 index 54c24f86e..000000000 --- a/examples/widgets/browser/networkaccessmanager.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef NETWORKACCESSMANAGER_H -#define NETWORKACCESSMANAGER_H - -#include -#include - -class NetworkAccessManager : public QNetworkAccessManager -{ - Q_OBJECT - -public: - NetworkAccessManager(QObject *parent = 0); - - virtual QNetworkReply* createRequest ( Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0 ); - -private: - QList sslTrustedHostList; - qint64 requestFinishedCount; - qint64 requestFinishedFromCacheCount; - qint64 requestFinishedPipelinedCount; - qint64 requestFinishedSecureCount; - qint64 requestFinishedDownloadBufferCount; - -public slots: - void loadSettings(); - void requestFinished(QNetworkReply *reply); - -private slots: -#ifndef QT_NO_OPENSSL - void sslErrors(QNetworkReply *reply, const QList &error); -#endif -}; - -#endif // NETWORKACCESSMANAGER_H diff --git a/examples/widgets/browser/passworddialog.ui b/examples/widgets/browser/passworddialog.ui deleted file mode 100644 index 7c1665867..000000000 --- a/examples/widgets/browser/passworddialog.ui +++ /dev/null @@ -1,111 +0,0 @@ - - PasswordDialog - - - - 0 - 0 - 399 - 148 - - - - Authentication Required - - - - - - - - DUMMY ICON - - - - - - - - 0 - 0 - - - - INTRO TEXT DUMMY - - - - - - - - - Username: - - - - - - - - - - Password: - - - - - - - QLineEdit::Password - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - PasswordDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - PasswordDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/examples/widgets/browser/proxy.ui b/examples/widgets/browser/proxy.ui deleted file mode 100644 index 62a8be627..000000000 --- a/examples/widgets/browser/proxy.ui +++ /dev/null @@ -1,104 +0,0 @@ - - ProxyDialog - - - - 0 - 0 - 369 - 144 - - - - Proxy Authentication - - - - - - ICON - - - - - - - Connect to proxy - - - true - - - - - - - Username: - - - - - - - - - - Password: - - - - - - - QLineEdit::Password - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - ProxyDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - ProxyDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/examples/widgets/browser/searchlineedit.cpp b/examples/widgets/browser/searchlineedit.cpp deleted file mode 100644 index 0d387da4b..000000000 --- a/examples/widgets/browser/searchlineedit.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "searchlineedit.h" - -#include -#include -#include -#include -#include - -ClearButton::ClearButton(QWidget *parent) - : QAbstractButton(parent) -{ -#ifndef QT_NO_CURSOR - setCursor(Qt::ArrowCursor); -#endif // QT_NO_CURSOR - setToolTip(tr("Clear")); - setVisible(false); - setFocusPolicy(Qt::NoFocus); -} - -void ClearButton::paintEvent(QPaintEvent *event) -{ - Q_UNUSED(event); - QPainter painter(this); - int height = this->height(); - - painter.setRenderHint(QPainter::Antialiasing, true); - painter.setBrush(isDown() - ? palette().color(QPalette::Dark) - : palette().color(QPalette::Mid)); - painter.setPen(painter.brush().color()); - int size = width(); - int offset = size / 5; - int radius = size - offset * 2; - painter.drawEllipse(offset, offset, radius, radius); - - painter.setPen(palette().color(QPalette::Base)); - int border = offset * 2; - painter.drawLine(border, border, width() - border, height - border); - painter.drawLine(border, height - border, width() - border, border); -} - -void ClearButton::textChanged(const QString &text) -{ - setVisible(!text.isEmpty()); -} - -/* - Search icon on the left hand side of the search widget - When a menu is set a down arrow appears - */ -class SearchButton : public QAbstractButton { -public: - SearchButton(QWidget *parent = 0); - void paintEvent(QPaintEvent *event); - QMenu *m_menu; - -protected: - void mousePressEvent(QMouseEvent *event); -}; - -SearchButton::SearchButton(QWidget *parent) - : QAbstractButton(parent), - m_menu(0) -{ - setObjectName(QLatin1String("SearchButton")); -#ifndef QT_NO_CURSOR - setCursor(Qt::ArrowCursor); -#endif //QT_NO_CURSOR - setFocusPolicy(Qt::NoFocus); -} - -void SearchButton::mousePressEvent(QMouseEvent *event) -{ - if (m_menu && event->button() == Qt::LeftButton) { - QWidget *p = parentWidget(); - if (p) { - QPoint r = p->mapToGlobal(QPoint(0, p->height())); - m_menu->exec(QPoint(r.x() + height() / 2, r.y())); - } - event->accept(); - } - QAbstractButton::mousePressEvent(event); -} - -void SearchButton::paintEvent(QPaintEvent *event) -{ - Q_UNUSED(event); - QPainterPath myPath; - - int radius = (height() / 5) * 2; - QRect circle(height() / 3 - 1, height() / 4, radius, radius); - myPath.addEllipse(circle); - - myPath.arcMoveTo(circle, 300); - QPointF c = myPath.currentPosition(); - int diff = height() / 7; - myPath.lineTo(qMin(width() - 2, (int)c.x() + diff), c.y() + diff); - - QPainter painter(this); - painter.setRenderHint(QPainter::Antialiasing, true); - painter.setPen(QPen(Qt::darkGray, 2)); - painter.drawPath(myPath); - - if (m_menu) { - QPainterPath dropPath; - dropPath.arcMoveTo(circle, 320); - QPointF c = dropPath.currentPosition(); - c = QPointF(c.x() + 3.5, c.y() + 0.5); - dropPath.moveTo(c); - dropPath.lineTo(c.x() + 4, c.y()); - dropPath.lineTo(c.x() + 2, c.y() + 2); - dropPath.closeSubpath(); - painter.setPen(Qt::darkGray); - painter.setBrush(Qt::darkGray); - painter.setRenderHint(QPainter::Antialiasing, false); - painter.drawPath(dropPath); - } - painter.end(); -} - -/* - SearchLineEdit is an enhanced QLineEdit - - A Search icon on the left with optional menu - - When there is no text and doesn't have focus an "inactive text" is displayed - - When there is text a clear button is displayed on the right hand side - */ -SearchLineEdit::SearchLineEdit(QWidget *parent) : ExLineEdit(parent), - m_searchButton(new SearchButton(this)) -{ - connect(lineEdit(), SIGNAL(textChanged(QString)), - this, SIGNAL(textChanged(QString))); - setLeftWidget(m_searchButton); - m_inactiveText = tr("Search"); - - QSizePolicy policy = sizePolicy(); - setSizePolicy(QSizePolicy::Preferred, policy.verticalPolicy()); -} - -void SearchLineEdit::paintEvent(QPaintEvent *event) -{ - if (lineEdit()->text().isEmpty() && !hasFocus() && !m_inactiveText.isEmpty()) { - ExLineEdit::paintEvent(event); - QStyleOptionFrameV2 panel; - initStyleOption(&panel); - QRect r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this); - QFontMetrics fm = fontMetrics(); - int horizontalMargin = lineEdit()->x(); - QRect lineRect(horizontalMargin + r.x(), r.y() + (r.height() - fm.height() + 1) / 2, - r.width() - 2 * horizontalMargin, fm.height()); - QPainter painter(this); - painter.setPen(palette().brush(QPalette::Disabled, QPalette::Text).color()); - painter.drawText(lineRect, Qt::AlignLeft|Qt::AlignVCenter, m_inactiveText); - } else { - ExLineEdit::paintEvent(event); - } -} - -void SearchLineEdit::resizeEvent(QResizeEvent *event) -{ - updateGeometries(); - ExLineEdit::resizeEvent(event); -} - -void SearchLineEdit::updateGeometries() -{ - int menuHeight = height(); - int menuWidth = menuHeight + 1; - if (!m_searchButton->m_menu) - menuWidth = (menuHeight / 5) * 4; - m_searchButton->resize(QSize(menuWidth, menuHeight)); -} - -QString SearchLineEdit::inactiveText() const -{ - return m_inactiveText; -} - -void SearchLineEdit::setInactiveText(const QString &text) -{ - m_inactiveText = text; -} - -void SearchLineEdit::setMenu(QMenu *menu) -{ - if (m_searchButton->m_menu) - m_searchButton->m_menu->deleteLater(); - m_searchButton->m_menu = menu; - updateGeometries(); -} - -QMenu *SearchLineEdit::menu() const -{ - if (!m_searchButton->m_menu) { - m_searchButton->m_menu = new QMenu(m_searchButton); - if (isVisible()) - (const_cast(this))->updateGeometries(); - } - return m_searchButton->m_menu; -} diff --git a/examples/widgets/browser/searchlineedit.h b/examples/widgets/browser/searchlineedit.h deleted file mode 100644 index e01fcbff2..000000000 --- a/examples/widgets/browser/searchlineedit.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SEARCHLINEEDIT_H -#define SEARCHLINEEDIT_H - -#include "urllineedit.h" - -#include -#include - -QT_BEGIN_NAMESPACE -class QMenu; -QT_END_NAMESPACE - -class SearchButton; - -/* - Clear button on the right hand side of the search widget. - Hidden by default - "A circle with an X in it" - */ -class ClearButton : public QAbstractButton -{ - Q_OBJECT - -public: - ClearButton(QWidget *parent = 0); - void paintEvent(QPaintEvent *event); - -public slots: - void textChanged(const QString &text); -}; - - -class SearchLineEdit : public ExLineEdit -{ - Q_OBJECT - Q_PROPERTY(QString inactiveText READ inactiveText WRITE setInactiveText) - -signals: - void textChanged(const QString &text); - -public: - SearchLineEdit(QWidget *parent = 0); - - QString inactiveText() const; - void setInactiveText(const QString &text); - - QMenu *menu() const; - void setMenu(QMenu *menu); - -protected: - void resizeEvent(QResizeEvent *event); - void paintEvent(QPaintEvent *event); - -private: - void updateGeometries(); - - SearchButton *m_searchButton; - QString m_inactiveText; -}; - -#endif // SEARCHLINEEDIT_H diff --git a/examples/widgets/browser/settings.cpp b/examples/widgets/browser/settings.cpp deleted file mode 100644 index 6838c19aa..000000000 --- a/examples/widgets/browser/settings.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "settings.h" - -#include "browserapplication.h" -#include "browsermainwindow.h" -#include "cookiejar.h" -#include "history.h" -#include "networkaccessmanager.h" -#include "webview.h" - -#include -#include -#include - -SettingsDialog::SettingsDialog(QWidget *parent) - : QDialog(parent) -{ - setupUi(this); - connect(exceptionsButton, SIGNAL(clicked()), this, SLOT(showExceptions())); - connect(setHomeToCurrentPageButton, SIGNAL(clicked()), this, SLOT(setHomeToCurrentPage())); - connect(cookiesButton, SIGNAL(clicked()), this, SLOT(showCookies())); - connect(standardFontButton, SIGNAL(clicked()), this, SLOT(chooseFont())); - connect(fixedFontButton, SIGNAL(clicked()), this, SLOT(chooseFixedFont())); - - loadDefaults(); - loadFromSettings(); -} - -void SettingsDialog::loadDefaults() -{ -#if defined(QWEBENGINESETTINGS) - QWebEngineSettings *defaultSettings = QWebEngineSettings::globalSettings(); - QString standardFontFamily = defaultSettings->fontFamily(QWebEngineSettings::StandardFont); - int standardFontSize = defaultSettings->fontSize(QWebEngineSettings::DefaultFontSize); - standardFont = QFont(standardFontFamily, standardFontSize); - standardLabel->setText(QString(QLatin1String("%1 %2")).arg(standardFont.family()).arg(standardFont.pointSize())); - - QString fixedFontFamily = defaultSettings->fontFamily(QWebEngineSettings::FixedFont); - int fixedFontSize = defaultSettings->fontSize(QWebEngineSettings::DefaultFixedFontSize); - fixedFont = QFont(fixedFontFamily, fixedFontSize); - fixedLabel->setText(QString(QLatin1String("%1 %2")).arg(fixedFont.family()).arg(fixedFont.pointSize())); - - downloadsLocation->setText(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); - - enableJavascript->setChecked(defaultSettings->testAttribute(QWebEngineSettings::JavascriptEnabled)); - enablePlugins->setChecked(defaultSettings->testAttribute(QWebEngineSettings::PluginsEnabled)); -#endif -} - -void SettingsDialog::loadFromSettings() -{ -#if defined(QWEBENGINESETTINGS) - QSettings settings; - settings.beginGroup(QLatin1String("MainWindow")); - QString defaultHome = QLatin1String("http://qt-project.org/"); - homeLineEdit->setText(settings.value(QLatin1String("home"), defaultHome).toString()); - settings.endGroup(); - - settings.beginGroup(QLatin1String("history")); - int historyExpire = settings.value(QLatin1String("historyExpire")).toInt(); - int idx = 0; - switch (historyExpire) { - case 1: idx = 0; break; - case 7: idx = 1; break; - case 14: idx = 2; break; - case 30: idx = 3; break; - case 365: idx = 4; break; - case -1: idx = 5; break; - default: - idx = 5; - } - expireHistory->setCurrentIndex(idx); - settings.endGroup(); - - settings.beginGroup(QLatin1String("downloadmanager")); - QString downloadDirectory = settings.value(QLatin1String("downloadDirectory"), downloadsLocation->text()).toString(); - downloadsLocation->setText(downloadDirectory); - settings.endGroup(); - - settings.beginGroup(QLatin1String("general")); - openLinksIn->setCurrentIndex(settings.value(QLatin1String("openLinksIn"), openLinksIn->currentIndex()).toInt()); - - settings.endGroup(); - - // Appearance - settings.beginGroup(QLatin1String("websettings")); - fixedFont = qvariant_cast(settings.value(QLatin1String("fixedFont"), fixedFont)); - standardFont = qvariant_cast(settings.value(QLatin1String("standardFont"), standardFont)); - - standardLabel->setText(QString(QLatin1String("%1 %2")).arg(standardFont.family()).arg(standardFont.pointSize())); - fixedLabel->setText(QString(QLatin1String("%1 %2")).arg(fixedFont.family()).arg(fixedFont.pointSize())); - - enableJavascript->setChecked(settings.value(QLatin1String("enableJavascript"), enableJavascript->isChecked()).toBool()); - enablePlugins->setChecked(settings.value(QLatin1String("enablePlugins"), enablePlugins->isChecked()).toBool()); - userStyleSheet->setText(settings.value(QLatin1String("userStyleSheet")).toUrl().toString()); - settings.endGroup(); - - // Privacy - settings.beginGroup(QLatin1String("cookies")); - - QByteArray value = settings.value(QLatin1String("acceptCookies"), QLatin1String("AcceptOnlyFromSitesNavigatedTo")).toByteArray(); - QMetaEnum acceptPolicyEnum = CookieJar::staticMetaObject.enumerator(CookieJar::staticMetaObject.indexOfEnumerator("AcceptPolicy")); - CookieJar::AcceptPolicy acceptCookies = acceptPolicyEnum.keyToValue(value) == -1 ? - CookieJar::AcceptOnlyFromSitesNavigatedTo : - static_cast(acceptPolicyEnum.keyToValue(value)); - switch (acceptCookies) { - case CookieJar::AcceptAlways: - acceptCombo->setCurrentIndex(0); - break; - case CookieJar::AcceptNever: - acceptCombo->setCurrentIndex(1); - break; - case CookieJar::AcceptOnlyFromSitesNavigatedTo: - acceptCombo->setCurrentIndex(2); - break; - } - - value = settings.value(QLatin1String("keepCookiesUntil"), QLatin1String("Expire")).toByteArray(); - QMetaEnum keepPolicyEnum = CookieJar::staticMetaObject.enumerator(CookieJar::staticMetaObject.indexOfEnumerator("KeepPolicy")); - CookieJar::KeepPolicy keepCookies = keepPolicyEnum.keyToValue(value) == -1 ? - CookieJar::KeepUntilExpire : - static_cast(keepPolicyEnum.keyToValue(value)); - switch (keepCookies) { - case CookieJar::KeepUntilExpire: - keepUntilCombo->setCurrentIndex(0); - break; - case CookieJar::KeepUntilExit: - keepUntilCombo->setCurrentIndex(1); - break; - case CookieJar::KeepUntilTimeLimit: - keepUntilCombo->setCurrentIndex(2); - break; - } - settings.endGroup(); - - - // Proxy - settings.beginGroup(QLatin1String("proxy")); - proxySupport->setChecked(settings.value(QLatin1String("enabled"), false).toBool()); - proxyType->setCurrentIndex(settings.value(QLatin1String("type"), 0).toInt()); - proxyHostName->setText(settings.value(QLatin1String("hostName")).toString()); - proxyPort->setValue(settings.value(QLatin1String("port"), 1080).toInt()); - proxyUserName->setText(settings.value(QLatin1String("userName")).toString()); - proxyPassword->setText(settings.value(QLatin1String("password")).toString()); - settings.endGroup(); -#endif -} - -void SettingsDialog::saveToSettings() -{ -#if defined(QWEBENGINESETTINGS) - QSettings settings; - settings.beginGroup(QLatin1String("MainWindow")); - settings.setValue(QLatin1String("home"), homeLineEdit->text()); - settings.endGroup(); - - settings.beginGroup(QLatin1String("general")); - settings.setValue(QLatin1String("openLinksIn"), openLinksIn->currentIndex()); - settings.endGroup(); - - settings.beginGroup(QLatin1String("history")); - int historyExpire = expireHistory->currentIndex(); - int idx = -1; - switch (historyExpire) { - case 0: idx = 1; break; - case 1: idx = 7; break; - case 2: idx = 14; break; - case 3: idx = 30; break; - case 4: idx = 365; break; - case 5: idx = -1; break; - } - settings.setValue(QLatin1String("historyExpire"), idx); - settings.endGroup(); - - // Appearance - settings.beginGroup(QLatin1String("websettings")); - settings.setValue(QLatin1String("fixedFont"), fixedFont); - settings.setValue(QLatin1String("standardFont"), standardFont); - settings.setValue(QLatin1String("enableJavascript"), enableJavascript->isChecked()); - settings.setValue(QLatin1String("enablePlugins"), enablePlugins->isChecked()); - QString userStyleSheetString = userStyleSheet->text(); - if (QFile::exists(userStyleSheetString)) - settings.setValue(QLatin1String("userStyleSheet"), QUrl::fromLocalFile(userStyleSheetString)); - else - settings.setValue(QLatin1String("userStyleSheet"), QUrl(userStyleSheetString)); - settings.endGroup(); - - //Privacy - settings.beginGroup(QLatin1String("cookies")); - - CookieJar::KeepPolicy keepCookies; - switch (acceptCombo->currentIndex()) { - default: - case 0: - keepCookies = CookieJar::KeepUntilExpire; - break; - case 1: - keepCookies = CookieJar::KeepUntilExit; - break; - case 2: - keepCookies = CookieJar::KeepUntilTimeLimit; - break; - } - QMetaEnum acceptPolicyEnum = CookieJar::staticMetaObject.enumerator(CookieJar::staticMetaObject.indexOfEnumerator("AcceptPolicy")); - settings.setValue(QLatin1String("acceptCookies"), QLatin1String(acceptPolicyEnum.valueToKey(keepCookies))); - - CookieJar::KeepPolicy keepPolicy; - switch (keepUntilCombo->currentIndex()) { - default: - case 0: - keepPolicy = CookieJar::KeepUntilExpire; - break; - case 1: - keepPolicy = CookieJar::KeepUntilExit; - break; - case 2: - keepPolicy = CookieJar::KeepUntilTimeLimit; - break; - } - - QMetaEnum keepPolicyEnum = CookieJar::staticMetaObject.enumerator(CookieJar::staticMetaObject.indexOfEnumerator("KeepPolicy")); - settings.setValue(QLatin1String("keepCookiesUntil"), QLatin1String(keepPolicyEnum.valueToKey(keepPolicy))); - - settings.endGroup(); - - // proxy - settings.beginGroup(QLatin1String("proxy")); - settings.setValue(QLatin1String("enabled"), proxySupport->isChecked()); - settings.setValue(QLatin1String("type"), proxyType->currentIndex()); - settings.setValue(QLatin1String("hostName"), proxyHostName->text()); - settings.setValue(QLatin1String("port"), proxyPort->text()); - settings.setValue(QLatin1String("userName"), proxyUserName->text()); - settings.setValue(QLatin1String("password"), proxyPassword->text()); - settings.endGroup(); - - BrowserApplication::instance()->loadSettings(); - BrowserApplication::networkAccessManager()->loadSettings(); - BrowserApplication::cookieJar()->loadSettings(); - BrowserApplication::historyManager()->loadSettings(); -#endif -} - -void SettingsDialog::accept() -{ - saveToSettings(); - QDialog::accept(); -} - -void SettingsDialog::showCookies() -{ -#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) - CookiesDialog *dialog = new CookiesDialog(BrowserApplication::cookieJar(), this); - dialog->exec(); -#endif -} - -void SettingsDialog::showExceptions() -{ -#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) - CookiesExceptionsDialog *dialog = new CookiesExceptionsDialog(BrowserApplication::cookieJar(), this); - dialog->exec(); -#endif -} - -void SettingsDialog::chooseFont() -{ - bool ok; - QFont font = QFontDialog::getFont(&ok, standardFont, this); - if ( ok ) { - standardFont = font; - standardLabel->setText(QString(QLatin1String("%1 %2")).arg(font.family()).arg(font.pointSize())); - } -} - -void SettingsDialog::chooseFixedFont() -{ - bool ok; - QFont font = QFontDialog::getFont(&ok, fixedFont, this); - if ( ok ) { - fixedFont = font; - fixedLabel->setText(QString(QLatin1String("%1 %2")).arg(font.family()).arg(font.pointSize())); - } -} - -void SettingsDialog::setHomeToCurrentPage() -{ - BrowserMainWindow *mw = static_cast(parent()); - WebView *webView = mw->currentTab(); - if (webView) - homeLineEdit->setText(webView->url().toString()); -} diff --git a/examples/widgets/browser/settings.h b/examples/widgets/browser/settings.h deleted file mode 100644 index 0858e0023..000000000 --- a/examples/widgets/browser/settings.h +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SETTINGS_H -#define SETTINGS_H - -#include -#include "ui_settings.h" - -class SettingsDialog : public QDialog, public Ui_Settings -{ - Q_OBJECT - -public: - SettingsDialog(QWidget *parent = 0); - void accept(); - -private slots: - void loadDefaults(); - void loadFromSettings(); - void saveToSettings(); - - void setHomeToCurrentPage(); - void showCookies(); - void showExceptions(); - - void chooseFont(); - void chooseFixedFont(); - -private: - QFont standardFont; - QFont fixedFont; -}; - -#endif // SETTINGS_H diff --git a/examples/widgets/browser/settings.ui b/examples/widgets/browser/settings.ui deleted file mode 100644 index 3491ce0b0..000000000 --- a/examples/widgets/browser/settings.ui +++ /dev/null @@ -1,614 +0,0 @@ - - Settings - - - - 0 - 0 - 657 - 322 - - - - Settings - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - 0 - - - - - 0 - 0 - 627 - 243 - - - - General - - - - - - Home: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Set to current page - - - - - - - Qt::Horizontal - - - - 280 - 18 - - - - - - - - Remove history items: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - After one day - - - - - After one week - - - - - After two weeks - - - - - After one month - - - - - After one year - - - - - Manually - - - - - - - - Save downloads to: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Open links from applications: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - In a tab in the current window - - - - - In a new window - - - - - - - - Qt::Vertical - - - - 391 - 262 - - - - - - - - - - 0 - 0 - 627 - 243 - - - - Appearance - - - - - - Standard font: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - Times 16 - - - Qt::AlignCenter - - - - - - - Select... - - - - - - - Fixed-width font: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - QFrame::StyledPanel - - - Courier 13 - - - Qt::AlignCenter - - - - - - - Select... - - - - - - - Qt::Vertical - - - - 20 - 93 - - - - - - - - - - 0 - 0 - 627 - 243 - - - - Privacy - - - - - - Web Content - - - - - - Enable Plugins - - - true - - - - - - - Enable Javascript - - - true - - - - - - - - - - Cookies - - - - - - Accept Cookies: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - Always - - - - - Never - - - - - Only from sites you navigate to - - - - - - - - Exceptions... - - - - - - - Keep until: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - They expire - - - - - I exit the application - - - - - At most 90 days - - - - - - - - Cookies... - - - - - - - - - - Qt::Vertical - - - - 371 - 177 - - - - - - - - - - 0 - 0 - 627 - 243 - - - - Proxy - - - - - - Enable proxy - - - true - - - - - - Type: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - Socks5 - - - - - Http - - - - - - - - Host: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Port: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 10000 - - - 1080 - - - - - - - Qt::Horizontal - - - - 293 - 20 - - - - - - - - User Name: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Password: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - QLineEdit::Password - - - - - - - Qt::Vertical - - - - 20 - 8 - - - - - - - - - - - - Advanced - - - - - - Style Sheet: - - - - - - - - - - Qt::Vertical - - - - 20 - 176 - - - - - - - - - - - - - - buttonBox - accepted() - Settings - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Settings - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/examples/widgets/browser/squeezelabel.cpp b/examples/widgets/browser/squeezelabel.cpp deleted file mode 100644 index c40fe97da..000000000 --- a/examples/widgets/browser/squeezelabel.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "squeezelabel.h" - -SqueezeLabel::SqueezeLabel(QWidget *parent) : QLabel(parent) -{ -} - -void SqueezeLabel::paintEvent(QPaintEvent *event) -{ - QFontMetrics fm = fontMetrics(); - if (fm.width(text()) > contentsRect().width()) { - QString elided = fm.elidedText(text(), Qt::ElideMiddle, width()); - QString oldText = text(); - setText(elided); - QLabel::paintEvent(event); - setText(oldText); - } else { - QLabel::paintEvent(event); - } -} diff --git a/examples/widgets/browser/squeezelabel.h b/examples/widgets/browser/squeezelabel.h deleted file mode 100644 index 6df84179a..000000000 --- a/examples/widgets/browser/squeezelabel.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SQUEEZELABEL_H -#define SQUEEZELABEL_H - -#include - -class SqueezeLabel : public QLabel -{ - Q_OBJECT - -public: - SqueezeLabel(QWidget *parent = 0); - -protected: - void paintEvent(QPaintEvent *event); - -}; - -#endif // SQUEEZELABEL_H diff --git a/examples/widgets/browser/tabwidget.cpp b/examples/widgets/browser/tabwidget.cpp deleted file mode 100644 index 3c71b2d53..000000000 --- a/examples/widgets/browser/tabwidget.cpp +++ /dev/null @@ -1,839 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "tabwidget.h" - -#include "browserapplication.h" -#include "browsermainwindow.h" -#include "history.h" -#include "urllineedit.h" -#include "webview.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -TabBar::TabBar(QWidget *parent) - : QTabBar(parent) -{ - setContextMenuPolicy(Qt::CustomContextMenu); - setAcceptDrops(true); - connect(this, SIGNAL(customContextMenuRequested(QPoint)), - this, SLOT(contextMenuRequested(QPoint))); - - QString ctrl = QLatin1String("Ctrl+%1"); - for (int i = 1; i <= 10; ++i) { - int key = i; - if (key == 10) - key = 0; - QShortcut *shortCut = new QShortcut(ctrl.arg(key), this); - m_tabShortcuts.append(shortCut); - connect(shortCut, SIGNAL(activated()), this, SLOT(selectTabAction())); - } - setTabsClosable(true); - connect(this, SIGNAL(tabCloseRequested(int)), - this, SIGNAL(closeTab(int))); - setSelectionBehaviorOnRemove(QTabBar::SelectPreviousTab); - setMovable(true); -} - -void TabBar::selectTabAction() -{ - if (QShortcut *shortCut = qobject_cast(sender())) { - int index = m_tabShortcuts.indexOf(shortCut); - if (index == 0) - index = 10; - setCurrentIndex(index); - } -} - -void TabBar::contextMenuRequested(const QPoint &position) -{ - QMenu menu; - menu.addAction(tr("New &Tab"), this, SIGNAL(newTab()), QKeySequence::AddTab); - int index = tabAt(position); - if (-1 != index) { - QAction *action = menu.addAction(tr("Clone Tab"), - this, SLOT(cloneTab())); - action->setData(index); - - menu.addSeparator(); - - action = menu.addAction(tr("&Close Tab"), - this, SLOT(closeTab()), QKeySequence::Close); - action->setData(index); - - action = menu.addAction(tr("Close &Other Tabs"), - this, SLOT(closeOtherTabs())); - action->setData(index); - - menu.addSeparator(); - - action = menu.addAction(tr("Reload Tab"), - this, SLOT(reloadTab()), QKeySequence::Refresh); - action->setData(index); - } else { - menu.addSeparator(); - } - menu.addAction(tr("Reload All Tabs"), this, SIGNAL(reloadAllTabs())); - menu.exec(QCursor::pos()); -} - -void TabBar::cloneTab() -{ - if (QAction *action = qobject_cast(sender())) { - int index = action->data().toInt(); - emit cloneTab(index); - } -} - -void TabBar::closeTab() -{ - if (QAction *action = qobject_cast(sender())) { - int index = action->data().toInt(); - emit closeTab(index); - } -} - -void TabBar::closeOtherTabs() -{ - if (QAction *action = qobject_cast(sender())) { - int index = action->data().toInt(); - emit closeOtherTabs(index); - } -} - -void TabBar::mousePressEvent(QMouseEvent *event) -{ - if (event->button() == Qt::LeftButton) - m_dragStartPos = event->pos(); - QTabBar::mousePressEvent(event); -} - -void TabBar::mouseMoveEvent(QMouseEvent *event) -{ - if (event->buttons() == Qt::LeftButton) { - int diffX = event->pos().x() - m_dragStartPos.x(); - int diffY = event->pos().y() - m_dragStartPos.y(); - if ((event->pos() - m_dragStartPos).manhattanLength() > QApplication::startDragDistance() - && diffX < 3 && diffX > -3 - && diffY < -10) { - QDrag *drag = new QDrag(this); - QMimeData *mimeData = new QMimeData; - QList urls; - int index = tabAt(event->pos()); - QUrl url = tabData(index).toUrl(); - urls.append(url); - mimeData->setUrls(urls); - mimeData->setText(tabText(index)); - mimeData->setData(QLatin1String("action"), "tab-reordering"); - drag->setMimeData(mimeData); - drag->exec(); - } - } - QTabBar::mouseMoveEvent(event); -} - -// When index is -1 index chooses the current tab -void TabWidget::reloadTab(int index) -{ - if (index < 0) - index = currentIndex(); - if (index < 0 || index >= count()) - return; - - QWidget *widget = this->widget(index); - if (WebView *tab = qobject_cast(widget)) - tab->reload(); -} - -void TabBar::reloadTab() -{ - if (QAction *action = qobject_cast(sender())) { - int index = action->data().toInt(); - emit reloadTab(index); - } -} - -TabWidget::TabWidget(QWidget *parent) - : QTabWidget(parent) - , m_recentlyClosedTabsAction(0) - , m_newTabAction(0) - , m_closeTabAction(0) - , m_nextTabAction(0) - , m_previousTabAction(0) - , m_recentlyClosedTabsMenu(0) - , m_lineEditCompleter(0) - , m_lineEdits(0) - , m_tabBar(new TabBar(this)) -{ - setElideMode(Qt::ElideRight); - - connect(m_tabBar, SIGNAL(newTab()), this, SLOT(newTab())); - connect(m_tabBar, SIGNAL(closeTab(int)), this, SLOT(closeTab(int))); - connect(m_tabBar, SIGNAL(cloneTab(int)), this, SLOT(cloneTab(int))); - connect(m_tabBar, SIGNAL(closeOtherTabs(int)), this, SLOT(closeOtherTabs(int))); - connect(m_tabBar, SIGNAL(reloadTab(int)), this, SLOT(reloadTab(int))); - connect(m_tabBar, SIGNAL(reloadAllTabs()), this, SLOT(reloadAllTabs())); - connect(m_tabBar, SIGNAL(tabMoved(int,int)), this, SLOT(moveTab(int,int))); - setTabBar(m_tabBar); - setDocumentMode(true); - - // Actions - m_newTabAction = new QAction(QIcon(QLatin1String(":addtab.png")), tr("New &Tab"), this); - m_newTabAction->setShortcuts(QKeySequence::AddTab); - m_newTabAction->setIconVisibleInMenu(false); - connect(m_newTabAction, SIGNAL(triggered()), this, SLOT(newTab())); - - m_closeTabAction = new QAction(QIcon(QLatin1String(":closetab.png")), tr("&Close Tab"), this); - m_closeTabAction->setShortcuts(QKeySequence::Close); - m_closeTabAction->setIconVisibleInMenu(false); - connect(m_closeTabAction, SIGNAL(triggered()), this, SLOT(closeTab())); - - m_nextTabAction = new QAction(tr("Show Next Tab"), this); - QList shortcuts; - shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_BraceRight)); - shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_PageDown)); - shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_BracketRight)); - shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_Less)); - m_nextTabAction->setShortcuts(shortcuts); - connect(m_nextTabAction, SIGNAL(triggered()), this, SLOT(nextTab())); - - m_previousTabAction = new QAction(tr("Show Previous Tab"), this); - shortcuts.clear(); - shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_BraceLeft)); - shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_PageUp)); - shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_BracketLeft)); - shortcuts.append(QKeySequence(Qt::CTRL | Qt::Key_Greater)); - m_previousTabAction->setShortcuts(shortcuts); - connect(m_previousTabAction, SIGNAL(triggered()), this, SLOT(previousTab())); - - m_recentlyClosedTabsMenu = new QMenu(this); - connect(m_recentlyClosedTabsMenu, SIGNAL(aboutToShow()), - this, SLOT(aboutToShowRecentTabsMenu())); - connect(m_recentlyClosedTabsMenu, SIGNAL(triggered(QAction*)), - this, SLOT(aboutToShowRecentTriggeredAction(QAction*))); - m_recentlyClosedTabsAction = new QAction(tr("Recently Closed Tabs"), this); - m_recentlyClosedTabsAction->setMenu(m_recentlyClosedTabsMenu); - m_recentlyClosedTabsAction->setEnabled(false); - - connect(this, SIGNAL(currentChanged(int)), - this, SLOT(currentChanged(int))); - - m_lineEdits = new QStackedWidget(this); -} - -void TabWidget::clear() -{ - // clear the recently closed tabs - m_recentlyClosedTabs.clear(); - // clear the line edit history - for (int i = 0; i < m_lineEdits->count(); ++i) { - QLineEdit *qLineEdit = lineEdit(i); - qLineEdit->setText(qLineEdit->text()); - } -} - -void TabWidget::moveTab(int fromIndex, int toIndex) -{ - QWidget *lineEdit = m_lineEdits->widget(fromIndex); - m_lineEdits->removeWidget(lineEdit); - m_lineEdits->insertWidget(toIndex, lineEdit); -} - -void TabWidget::addWebAction(QAction *action, QWebEnginePage::WebAction webAction) -{ - if (!action) - return; - m_actions.append(new WebActionMapper(action, webAction, this)); -} - -void TabWidget::currentChanged(int index) -{ - WebView *webView = this->webView(index); - if (!webView) - return; - - Q_ASSERT(m_lineEdits->count() == count()); - - WebView *oldWebView = this->webView(m_lineEdits->currentIndex()); - if (oldWebView) { - disconnect(oldWebView, SIGNAL(statusBarMessage(QString)), - this, SIGNAL(showStatusBarMessage(QString))); - disconnect(oldWebView->page(), SIGNAL(linkHovered(QString,QString,QString)), - this, SIGNAL(linkHovered(QString))); - disconnect(oldWebView, SIGNAL(loadProgress(int)), - this, SIGNAL(loadProgress(int))); - } - - connect(webView, SIGNAL(statusBarMessage(QString)), - this, SIGNAL(showStatusBarMessage(QString))); - connect(webView->page(), SIGNAL(linkHovered(QString,QString,QString)), - this, SIGNAL(linkHovered(QString))); - connect(webView, SIGNAL(loadProgress(int)), - this, SIGNAL(loadProgress(int))); - - for (int i = 0; i < m_actions.count(); ++i) { - WebActionMapper *mapper = m_actions[i]; - mapper->updateCurrent(webView->page()); - } - emit setCurrentTitle(webView->title()); - m_lineEdits->setCurrentIndex(index); - emit loadProgress(webView->progress()); - emit showStatusBarMessage(webView->lastStatusBarText()); - if (webView->url().isEmpty()) - m_lineEdits->currentWidget()->setFocus(); - else - webView->setFocus(); -} - -QAction *TabWidget::newTabAction() const -{ - return m_newTabAction; -} - -QAction *TabWidget::closeTabAction() const -{ - return m_closeTabAction; -} - -QAction *TabWidget::recentlyClosedTabsAction() const -{ - return m_recentlyClosedTabsAction; -} - -QAction *TabWidget::nextTabAction() const -{ - return m_nextTabAction; -} - -QAction *TabWidget::previousTabAction() const -{ - return m_previousTabAction; -} - -QWidget *TabWidget::lineEditStack() const -{ - return m_lineEdits; -} - -QLineEdit *TabWidget::currentLineEdit() const -{ - return lineEdit(m_lineEdits->currentIndex()); -} - -WebView *TabWidget::currentWebView() const -{ - return webView(currentIndex()); -} - -QLineEdit *TabWidget::lineEdit(int index) const -{ - UrlLineEdit *urlLineEdit = qobject_cast(m_lineEdits->widget(index)); - if (urlLineEdit) - return urlLineEdit->lineEdit(); - return 0; -} - -WebView *TabWidget::webView(int index) const -{ - QWidget *widget = this->widget(index); - if (WebView *webView = qobject_cast(widget)) { - return webView; - } else { - // optimization to delay creating the first webview - if (count() == 1) { - TabWidget *that = const_cast(this); - that->setUpdatesEnabled(false); - that->newTab(); - that->closeTab(0); - that->setUpdatesEnabled(true); - return currentWebView(); - } - } - return 0; -} - -int TabWidget::webViewIndex(WebView *webView) const -{ - int index = indexOf(webView); - return index; -} - -WebView *TabWidget::newTab(bool makeCurrent) -{ - // line edit - UrlLineEdit *urlLineEdit = new UrlLineEdit; - QLineEdit *lineEdit = urlLineEdit->lineEdit(); - if (!m_lineEditCompleter && count() > 0) { - HistoryCompletionModel *completionModel = new HistoryCompletionModel(this); - completionModel->setSourceModel(BrowserApplication::historyManager()->historyFilterModel()); - m_lineEditCompleter = new QCompleter(completionModel, this); - // Should this be in Qt by default? - QAbstractItemView *popup = m_lineEditCompleter->popup(); - QListView *listView = qobject_cast(popup); - if (listView) - listView->setUniformItemSizes(true); - } - lineEdit->setCompleter(m_lineEditCompleter); - connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(lineEditReturnPressed())); - m_lineEdits->addWidget(urlLineEdit); - m_lineEdits->setSizePolicy(lineEdit->sizePolicy()); - - // optimization to delay creating the more expensive WebView, history, etc - if (count() == 0) { - QWidget *emptyWidget = new QWidget; - QPalette p = emptyWidget->palette(); - p.setColor(QPalette::Window, palette().color(QPalette::Base)); - emptyWidget->setPalette(p); - emptyWidget->setAutoFillBackground(true); - disconnect(this, SIGNAL(currentChanged(int)), - this, SLOT(currentChanged(int))); - addTab(emptyWidget, tr("(Untitled)")); - connect(this, SIGNAL(currentChanged(int)), - this, SLOT(currentChanged(int))); - return 0; - } - - // webview - WebView *webView = new WebView; - urlLineEdit->setWebView(webView); - connect(webView, SIGNAL(loadStarted()), - this, SLOT(webViewLoadStarted())); - connect(webView, SIGNAL(loadFinished(bool)), - this, SLOT(webViewIconChanged())); - connect(webView, SIGNAL(iconChanged()), - this, SLOT(webViewIconChanged())); - connect(webView, SIGNAL(titleChanged(QString)), - this, SLOT(webViewTitleChanged(QString))); - connect(webView, SIGNAL(urlChanged(QUrl)), - this, SLOT(webViewUrlChanged(QUrl))); - connect(webView->page(), SIGNAL(windowCloseRequested()), - this, SLOT(windowCloseRequested())); - connect(webView->page(), SIGNAL(geometryChangeRequested(QRect)), - this, SIGNAL(geometryChangeRequested(QRect))); - connect(webView->page(), SIGNAL(printRequested(QWebEngineFrame*)), - this, SIGNAL(printRequested(QWebEngineFrame*))); - connect(webView->page(), SIGNAL(menuBarVisibilityChangeRequested(bool)), - this, SIGNAL(menuBarVisibilityChangeRequested(bool))); - connect(webView->page(), SIGNAL(statusBarVisibilityChangeRequested(bool)), - this, SIGNAL(statusBarVisibilityChangeRequested(bool))); - connect(webView->page(), SIGNAL(toolBarVisibilityChangeRequested(bool)), - this, SIGNAL(toolBarVisibilityChangeRequested(bool))); - addTab(webView, tr("(Untitled)")); - if (makeCurrent) - setCurrentWidget(webView); - - // webview actions - for (int i = 0; i < m_actions.count(); ++i) { - WebActionMapper *mapper = m_actions[i]; - mapper->addChild(webView->page()->action(mapper->webAction())); - } - - if (count() == 1) - currentChanged(currentIndex()); - emit tabsChanged(); - return webView; -} - -void TabWidget::reloadAllTabs() -{ - for (int i = 0; i < count(); ++i) { - QWidget *tabWidget = widget(i); - if (WebView *tab = qobject_cast(tabWidget)) { - tab->reload(); - } - } -} - -void TabWidget::lineEditReturnPressed() -{ - if (QLineEdit *lineEdit = qobject_cast(sender())) { - emit loadPage(lineEdit->text()); - if (m_lineEdits->currentWidget() == lineEdit) - currentWebView()->setFocus(); - } -} - -void TabWidget::windowCloseRequested() -{ - WebPage *webPage = qobject_cast(sender()); - WebView *webView = qobject_cast(webPage->view()); - int index = webViewIndex(webView); - if (index >= 0) { - if (count() == 1) - webView->webPage()->mainWindow()->close(); - else - closeTab(index); - } -} - -void TabWidget::closeOtherTabs(int index) -{ - if (-1 == index) - return; - for (int i = count() - 1; i > index; --i) - closeTab(i); - for (int i = index - 1; i >= 0; --i) - closeTab(i); -} - -// When index is -1 index chooses the current tab -void TabWidget::cloneTab(int index) -{ - if (index < 0) - index = currentIndex(); - if (index < 0 || index >= count()) - return; - WebView *tab = newTab(false); - tab->setUrl(webView(index)->url()); -} - -// When index is -1 index chooses the current tab -void TabWidget::closeTab(int index) -{ - if (index < 0) - index = currentIndex(); - if (index < 0 || index >= count()) - return; - - bool hasFocus = false; - if (WebView *tab = webView(index)) { -#if defined(QWEBENGINEPAGE_ISMODIFIED) - if (tab->isModified()) { - QMessageBox closeConfirmation(tab); - closeConfirmation.setWindowFlags(Qt::Sheet); - closeConfirmation.setWindowTitle(tr("Do you really want to close this page?")); - closeConfirmation.setInformativeText(tr("You have modified this page and when closing it you would lose the modification.\n" - "Do you really want to close this page?\n")); - closeConfirmation.setIcon(QMessageBox::Question); - closeConfirmation.addButton(QMessageBox::Yes); - closeConfirmation.addButton(QMessageBox::No); - closeConfirmation.setEscapeButton(QMessageBox::No); - if (closeConfirmation.exec() == QMessageBox::No) - return; - } -#endif - hasFocus = tab->hasFocus(); - -#if defined(QWEBENGINESETTINGS) - QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); - if (!globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) -#endif - { - m_recentlyClosedTabsAction->setEnabled(true); - m_recentlyClosedTabs.prepend(tab->url()); - if (m_recentlyClosedTabs.size() >= TabWidget::m_recentlyClosedTabsSize) - m_recentlyClosedTabs.removeLast(); - } - } - QWidget *lineEdit = m_lineEdits->widget(index); - m_lineEdits->removeWidget(lineEdit); - lineEdit->deleteLater(); - QWidget *webView = widget(index); - removeTab(index); - webView->deleteLater(); - emit tabsChanged(); - if (hasFocus && count() > 0) - currentWebView()->setFocus(); - if (count() == 0) - emit lastTabClosed(); -} - -void TabWidget::webViewLoadStarted() -{ - WebView *webView = qobject_cast(sender()); - int index = webViewIndex(webView); - if (-1 != index) { - QIcon icon(QLatin1String(":loading.gif")); - setTabIcon(index, icon); - } -} - -void TabWidget::webViewIconChanged() -{ - WebView *webView = qobject_cast(sender()); - int index = webViewIndex(webView); - if (-1 != index) { - QIcon icon = BrowserApplication::instance()->icon(webView->url()); - setTabIcon(index, icon); - } -} - -void TabWidget::webViewTitleChanged(const QString &title) -{ - WebView *webView = qobject_cast(sender()); - int index = webViewIndex(webView); - if (-1 != index) { - setTabText(index, title); - } - if (currentIndex() == index) - emit setCurrentTitle(title); - BrowserApplication::historyManager()->updateHistoryItem(webView->url(), title); -} - -void TabWidget::webViewUrlChanged(const QUrl &url) -{ - WebView *webView = qobject_cast(sender()); - int index = webViewIndex(webView); - if (-1 != index) { - m_tabBar->setTabData(index, url); - } - emit tabsChanged(); -} - -void TabWidget::aboutToShowRecentTabsMenu() -{ - m_recentlyClosedTabsMenu->clear(); - for (int i = 0; i < m_recentlyClosedTabs.count(); ++i) { - QAction *action = new QAction(m_recentlyClosedTabsMenu); - action->setData(m_recentlyClosedTabs.at(i)); - QIcon icon = BrowserApplication::instance()->icon(m_recentlyClosedTabs.at(i)); - action->setIcon(icon); - action->setText(m_recentlyClosedTabs.at(i).toString()); - m_recentlyClosedTabsMenu->addAction(action); - } -} - -void TabWidget::aboutToShowRecentTriggeredAction(QAction *action) -{ - QUrl url = action->data().toUrl(); - loadUrlInCurrentTab(url); -} - -void TabWidget::mouseDoubleClickEvent(QMouseEvent *event) -{ - if (!childAt(event->pos()) - // Remove the line below when QTabWidget does not have a one pixel frame - && event->pos().y() < (tabBar()->y() + tabBar()->height())) { - newTab(); - return; - } - QTabWidget::mouseDoubleClickEvent(event); -} - -void TabWidget::contextMenuEvent(QContextMenuEvent *event) -{ - if (!childAt(event->pos())) { - m_tabBar->contextMenuRequested(event->pos()); - return; - } - QTabWidget::contextMenuEvent(event); -} - -void TabWidget::mouseReleaseEvent(QMouseEvent *event) -{ - if (event->button() == Qt::MidButton && !childAt(event->pos()) - // Remove the line below when QTabWidget does not have a one pixel frame - && event->pos().y() < (tabBar()->y() + tabBar()->height())) { - QUrl url(QApplication::clipboard()->text(QClipboard::Selection)); - if (!url.isEmpty() && url.isValid() && !url.scheme().isEmpty()) { - WebView *webView = newTab(); - webView->setUrl(url); - } - } -} - -void TabWidget::loadUrlInCurrentTab(const QUrl &url) -{ - WebView *webView = currentWebView(); - if (webView) { - webView->loadUrl(url); - webView->setFocus(); - } -} - -void TabWidget::nextTab() -{ - int next = currentIndex() + 1; - if (next == count()) - next = 0; - setCurrentIndex(next); -} - -void TabWidget::previousTab() -{ - int next = currentIndex() - 1; - if (next < 0) - next = count() - 1; - setCurrentIndex(next); -} - -static const qint32 TabWidgetMagic = 0xaa; - -QByteArray TabWidget::saveState() const -{ - int version = 1; - QByteArray data; - QDataStream stream(&data, QIODevice::WriteOnly); - - stream << qint32(TabWidgetMagic); - stream << qint32(version); - - QStringList tabs; - for (int i = 0; i < count(); ++i) { - if (WebView *tab = qobject_cast(widget(i))) { - tabs.append(tab->url().toString()); - } else { - tabs.append(QString::null); - } - } - stream << tabs; - stream << currentIndex(); - return data; -} - -bool TabWidget::restoreState(const QByteArray &state) -{ - int version = 1; - QByteArray sd = state; - QDataStream stream(&sd, QIODevice::ReadOnly); - if (stream.atEnd()) - return false; - - qint32 marker; - qint32 v; - stream >> marker; - stream >> v; - if (marker != TabWidgetMagic || v != version) - return false; - - QStringList openTabs; - stream >> openTabs; - - for (int i = 0; i < openTabs.count(); ++i) { - if (i != 0) - newTab(); - loadPage(openTabs.at(i)); - } - - int currentTab; - stream >> currentTab; - setCurrentIndex(currentTab); - - return true; -} - -WebActionMapper::WebActionMapper(QAction *root, QWebEnginePage::WebAction webAction, QObject *parent) - : QObject(parent) - , m_currentParent(0) - , m_root(root) - , m_webAction(webAction) -{ - if (!m_root) - return; - connect(m_root, SIGNAL(triggered()), this, SLOT(rootTriggered())); - connect(root, SIGNAL(destroyed(QObject*)), this, SLOT(rootDestroyed())); - root->setEnabled(false); -} - -void WebActionMapper::rootDestroyed() -{ - m_root = 0; -} - -void WebActionMapper::currentDestroyed() -{ - updateCurrent(0); -} - -void WebActionMapper::addChild(QAction *action) -{ - if (!action) - return; - connect(action, SIGNAL(changed()), this, SLOT(childChanged())); -} - -QWebEnginePage::WebAction WebActionMapper::webAction() const -{ - return m_webAction; -} - -void WebActionMapper::rootTriggered() -{ - if (m_currentParent) { - QAction *gotoAction = m_currentParent->action(m_webAction); - gotoAction->trigger(); - } -} - -void WebActionMapper::childChanged() -{ - if (QAction *source = qobject_cast(sender())) { - if (m_root - && m_currentParent - && source->parent() == m_currentParent) { - m_root->setChecked(source->isChecked()); - m_root->setEnabled(source->isEnabled()); - } - } -} - -void WebActionMapper::updateCurrent(QWebEnginePage *currentParent) -{ - if (m_currentParent) - disconnect(m_currentParent, SIGNAL(destroyed(QObject*)), - this, SLOT(currentDestroyed())); - - m_currentParent = currentParent; - if (!m_root) - return; - if (!m_currentParent) { - m_root->setEnabled(false); - m_root->setChecked(false); - return; - } - QAction *source = m_currentParent->action(m_webAction); - m_root->setChecked(source->isChecked()); - m_root->setEnabled(source->isEnabled()); - connect(m_currentParent, SIGNAL(destroyed(QObject*)), - this, SLOT(currentDestroyed())); -} diff --git a/examples/widgets/browser/tabwidget.h b/examples/widgets/browser/tabwidget.h deleted file mode 100644 index e5e1cb606..000000000 --- a/examples/widgets/browser/tabwidget.h +++ /dev/null @@ -1,223 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TABWIDGET_H -#define TABWIDGET_H - -#include - -#include -/* - Tab bar with a few more features such as a context menu and shortcuts - */ -class TabBar : public QTabBar -{ - Q_OBJECT - -signals: - void newTab(); - void cloneTab(int index); - void closeTab(int index); - void closeOtherTabs(int index); - void reloadTab(int index); - void reloadAllTabs(); - void tabMoveRequested(int fromIndex, int toIndex); - -public: - TabBar(QWidget *parent = 0); - -protected: - void mousePressEvent(QMouseEvent* event); - void mouseMoveEvent(QMouseEvent* event); - -private slots: - void selectTabAction(); - void cloneTab(); - void closeTab(); - void closeOtherTabs(); - void reloadTab(); - void contextMenuRequested(const QPoint &position); - -private: - QList m_tabShortcuts; - friend class TabWidget; - - QPoint m_dragStartPos; - int m_dragCurrentIndex; -}; - -#include - -QT_BEGIN_NAMESPACE -class QAction; -QT_END_NAMESPACE -class WebView; -/*! - A proxy object that connects a single browser action - to one child webpage action at a time. - - Example usage: used to keep the main window stop action in sync with - the current tabs webview's stop action. - */ -class WebActionMapper : public QObject -{ - Q_OBJECT - -public: - WebActionMapper(QAction *root, QWebEnginePage::WebAction webAction, QObject *parent); - QWebEnginePage::WebAction webAction() const; - void addChild(QAction *action); - void updateCurrent(QWebEnginePage *currentParent); - -private slots: - void rootTriggered(); - void childChanged(); - void rootDestroyed(); - void currentDestroyed(); - -private: - QWebEnginePage *m_currentParent; - QAction *m_root; - QWebEnginePage::WebAction m_webAction; -}; - -#include -#include -QT_BEGIN_NAMESPACE -class QCompleter; -class QLineEdit; -class QMenu; -class QStackedWidget; -QT_END_NAMESPACE -/*! - TabWidget that contains WebViews and a stack widget of associated line edits. - - Connects up the current tab's signals to this class's signal and uses WebActionMapper - to proxy the actions. - */ -class TabWidget : public QTabWidget -{ - Q_OBJECT - -signals: - // tab widget signals - void loadPage(const QString &url); - void tabsChanged(); - void lastTabClosed(); - - // current tab signals - void setCurrentTitle(const QString &url); - void showStatusBarMessage(const QString &message); - void linkHovered(const QString &link); - void loadProgress(int progress); - void geometryChangeRequested(const QRect &geometry); - void menuBarVisibilityChangeRequested(bool visible); - void statusBarVisibilityChangeRequested(bool visible); - void toolBarVisibilityChangeRequested(bool visible); - void printRequested(QWebEngineFrame *frame); - -public: - TabWidget(QWidget *parent = 0); - void clear(); - void addWebAction(QAction *action, QWebEnginePage::WebAction webAction); - - QAction *newTabAction() const; - QAction *closeTabAction() const; - QAction *recentlyClosedTabsAction() const; - QAction *nextTabAction() const; - QAction *previousTabAction() const; - - QWidget *lineEditStack() const; - QLineEdit *currentLineEdit() const; - WebView *currentWebView() const; - WebView *webView(int index) const; - QLineEdit *lineEdit(int index) const; - int webViewIndex(WebView *webView) const; - - QByteArray saveState() const; - bool restoreState(const QByteArray &state); - -protected: - void mouseDoubleClickEvent(QMouseEvent *event); - void contextMenuEvent(QContextMenuEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - -public slots: - void loadUrlInCurrentTab(const QUrl &url); - WebView *newTab(bool makeCurrent = true); - void cloneTab(int index = -1); - void closeTab(int index = -1); - void closeOtherTabs(int index); - void reloadTab(int index = -1); - void reloadAllTabs(); - void nextTab(); - void previousTab(); - -private slots: - void currentChanged(int index); - void aboutToShowRecentTabsMenu(); - void aboutToShowRecentTriggeredAction(QAction *action); - void webViewLoadStarted(); - void webViewIconChanged(); - void webViewTitleChanged(const QString &title); - void webViewUrlChanged(const QUrl &url); - void lineEditReturnPressed(); - void windowCloseRequested(); - void moveTab(int fromIndex, int toIndex); - -private: - QAction *m_recentlyClosedTabsAction; - QAction *m_newTabAction; - QAction *m_closeTabAction; - QAction *m_nextTabAction; - QAction *m_previousTabAction; - - QMenu *m_recentlyClosedTabsMenu; - static const int m_recentlyClosedTabsSize = 10; - QList m_recentlyClosedTabs; - QList m_actions; - - QCompleter *m_lineEditCompleter; - QStackedWidget *m_lineEdits; - TabBar *m_tabBar; -}; - -#endif // TABWIDGET_H diff --git a/examples/widgets/browser/toolbarsearch.cpp b/examples/widgets/browser/toolbarsearch.cpp deleted file mode 100644 index d6d1ec1da..000000000 --- a/examples/widgets/browser/toolbarsearch.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "toolbarsearch.h" -#include "autosaver.h" - -#include -#include -#include - -#include -#include -#include - -#include - -/* - ToolbarSearch is a very basic search widget that also contains a small history. - Searches are turned into urls that use Google to perform search - */ -ToolbarSearch::ToolbarSearch(QWidget *parent) - : SearchLineEdit(parent) - , m_autosaver(new AutoSaver(this)) - , m_maxSavedSearches(10) - , m_stringListModel(new QStringListModel(this)) -{ - QMenu *m = menu(); - connect(m, SIGNAL(aboutToShow()), this, SLOT(aboutToShowMenu())); - connect(m, SIGNAL(triggered(QAction*)), this, SLOT(triggeredMenuAction(QAction*))); - - QCompleter *completer = new QCompleter(m_stringListModel, this); - completer->setCompletionMode(QCompleter::InlineCompletion); - lineEdit()->setCompleter(completer); - - connect(lineEdit(), SIGNAL(returnPressed()), SLOT(searchNow())); - setInactiveText(tr("Google")); - load(); -} - -ToolbarSearch::~ToolbarSearch() -{ - m_autosaver->saveIfNeccessary(); -} - -void ToolbarSearch::save() -{ - QSettings settings; - settings.beginGroup(QLatin1String("toolbarsearch")); - settings.setValue(QLatin1String("recentSearches"), m_stringListModel->stringList()); - settings.setValue(QLatin1String("maximumSaved"), m_maxSavedSearches); - settings.endGroup(); -} - -void ToolbarSearch::load() -{ - QSettings settings; - settings.beginGroup(QLatin1String("toolbarsearch")); - QStringList list = settings.value(QLatin1String("recentSearches")).toStringList(); - m_maxSavedSearches = settings.value(QLatin1String("maximumSaved"), m_maxSavedSearches).toInt(); - m_stringListModel->setStringList(list); - settings.endGroup(); -} - -void ToolbarSearch::searchNow() -{ - QString searchText = lineEdit()->text(); - QStringList newList = m_stringListModel->stringList(); - if (newList.contains(searchText)) - newList.removeAt(newList.indexOf(searchText)); - newList.prepend(searchText); - if (newList.size() >= m_maxSavedSearches) - newList.removeLast(); - -#if defined(QWEBENGINESETTINGS) - QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); - if (!globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) -#endif - { - m_stringListModel->setStringList(newList); - m_autosaver->changeOccurred(); - } - - QUrl url(QLatin1String("http://www.google.com/search")); - QUrlQuery urlQuery; - urlQuery.addQueryItem(QLatin1String("q"), searchText); - urlQuery.addQueryItem(QLatin1String("ie"), QLatin1String("UTF-8")); - urlQuery.addQueryItem(QLatin1String("oe"), QLatin1String("UTF-8")); - urlQuery.addQueryItem(QLatin1String("client"), QLatin1String("qtdemobrowser")); - url.setQuery(urlQuery); - emit search(url); -} - -void ToolbarSearch::aboutToShowMenu() -{ - lineEdit()->selectAll(); - QMenu *m = menu(); - m->clear(); - QStringList list = m_stringListModel->stringList(); - if (list.isEmpty()) { - m->addAction(tr("No Recent Searches")); - return; - } - - QAction *recent = m->addAction(tr("Recent Searches")); - recent->setEnabled(false); - for (int i = 0; i < list.count(); ++i) { - QString text = list.at(i); - m->addAction(text)->setData(text); - } - m->addSeparator(); - m->addAction(tr("Clear Recent Searches"), this, SLOT(clear())); -} - -void ToolbarSearch::triggeredMenuAction(QAction *action) -{ - QVariant v = action->data(); - if (v.canConvert()) { - QString text = v.toString(); - lineEdit()->setText(text); - searchNow(); - } -} - -void ToolbarSearch::clear() -{ - m_stringListModel->setStringList(QStringList()); - m_autosaver->changeOccurred();; -} diff --git a/examples/widgets/browser/toolbarsearch.h b/examples/widgets/browser/toolbarsearch.h deleted file mode 100644 index 1189785db..000000000 --- a/examples/widgets/browser/toolbarsearch.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TOOLBARSEARCH_H -#define TOOLBARSEARCH_H - -#include "searchlineedit.h" - -QT_BEGIN_NAMESPACE -class QUrl; -class QAction; -class QStringListModel; -QT_END_NAMESPACE - -class AutoSaver; - -class ToolbarSearch : public SearchLineEdit -{ - Q_OBJECT - -signals: - void search(const QUrl &url); - -public: - ToolbarSearch(QWidget *parent = 0); - ~ToolbarSearch(); - -public slots: - void clear(); - void searchNow(); - -private slots: - void save(); - void aboutToShowMenu(); - void triggeredMenuAction(QAction *action); - -private: - void load(); - - AutoSaver *m_autosaver; - int m_maxSavedSearches; - QStringListModel *m_stringListModel; -}; - -#endif // TOOLBARSEARCH_H diff --git a/examples/widgets/browser/urllineedit.cpp b/examples/widgets/browser/urllineedit.cpp deleted file mode 100644 index 47828d95f..000000000 --- a/examples/widgets/browser/urllineedit.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "urllineedit.h" - -#include "browserapplication.h" -#include "searchlineedit.h" -#include "webview.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -ExLineEdit::ExLineEdit(QWidget *parent) - : QWidget(parent) - , m_leftWidget(0) - , m_lineEdit(new QLineEdit(this)) - , m_clearButton(0) -{ - setFocusPolicy(m_lineEdit->focusPolicy()); - setAttribute(Qt::WA_InputMethodEnabled); - setSizePolicy(m_lineEdit->sizePolicy()); - setBackgroundRole(m_lineEdit->backgroundRole()); - setMouseTracking(true); - setAcceptDrops(true); - setAttribute(Qt::WA_MacShowFocusRect, true); - QPalette p = m_lineEdit->palette(); - setPalette(p); - - // line edit - m_lineEdit->setFrame(false); - m_lineEdit->setFocusProxy(this); - m_lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false); - QPalette clearPalette = m_lineEdit->palette(); - clearPalette.setBrush(QPalette::Base, QBrush(Qt::transparent)); - m_lineEdit->setPalette(clearPalette); - - // clearButton - m_clearButton = new ClearButton(this); - connect(m_clearButton, SIGNAL(clicked()), - m_lineEdit, SLOT(clear())); - connect(m_lineEdit, SIGNAL(textChanged(QString)), - m_clearButton, SLOT(textChanged(QString))); -} - -void ExLineEdit::setLeftWidget(QWidget *widget) -{ - m_leftWidget = widget; -} - -QWidget *ExLineEdit::leftWidget() const -{ - return m_leftWidget; -} - -void ExLineEdit::resizeEvent(QResizeEvent *event) -{ - Q_ASSERT(m_leftWidget); - updateGeometries(); - QWidget::resizeEvent(event); -} - -void ExLineEdit::updateGeometries() -{ - QStyleOptionFrameV2 panel; - initStyleOption(&panel); - QRect rect = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this); - - int height = rect.height(); - int width = rect.width(); - - int m_leftWidgetHeight = m_leftWidget->height(); - m_leftWidget->setGeometry(rect.x() + 2, rect.y() + (height - m_leftWidgetHeight)/2, - m_leftWidget->width(), m_leftWidget->height()); - - int clearButtonWidth = this->height(); - m_lineEdit->setGeometry(m_leftWidget->x() + m_leftWidget->width(), 0, - width - clearButtonWidth - m_leftWidget->width(), this->height()); - - m_clearButton->setGeometry(this->width() - clearButtonWidth, 0, - clearButtonWidth, this->height()); -} - -void ExLineEdit::initStyleOption(QStyleOptionFrameV2 *option) const -{ - option->initFrom(this); - option->rect = contentsRect(); - option->lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, option, this); - option->midLineWidth = 0; - option->state |= QStyle::State_Sunken; - if (m_lineEdit->isReadOnly()) - option->state |= QStyle::State_ReadOnly; -#ifdef QT_KEYPAD_NAVIGATION - if (hasEditFocus()) - option->state |= QStyle::State_HasEditFocus; -#endif - option->features = QStyleOptionFrameV2::None; -} - -QSize ExLineEdit::sizeHint() const -{ - m_lineEdit->setFrame(true); - QSize size = m_lineEdit->sizeHint(); - m_lineEdit->setFrame(false); - return size; -} - -void ExLineEdit::focusInEvent(QFocusEvent *event) -{ - m_lineEdit->event(event); - QWidget::focusInEvent(event); -} - -void ExLineEdit::focusOutEvent(QFocusEvent *event) -{ - m_lineEdit->event(event); - - if (m_lineEdit->completer()) { - connect(m_lineEdit->completer(), SIGNAL(activated(QString)), - m_lineEdit, SLOT(setText(QString))); - connect(m_lineEdit->completer(), SIGNAL(highlighted(QString)), - m_lineEdit, SLOT(_q_completionHighlighted(QString))); - } - QWidget::focusOutEvent(event); -} - -void ExLineEdit::keyPressEvent(QKeyEvent *event) -{ - m_lineEdit->event(event); -} - -bool ExLineEdit::event(QEvent *event) -{ - if (event->type() == QEvent::ShortcutOverride) - return m_lineEdit->event(event); - return QWidget::event(event); -} - -void ExLineEdit::paintEvent(QPaintEvent *) -{ - QPainter p(this); - QStyleOptionFrameV2 panel; - initStyleOption(&panel); - style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, &p, this); -} - -QVariant ExLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const -{ - return m_lineEdit->inputMethodQuery(property); -} - -void ExLineEdit::inputMethodEvent(QInputMethodEvent *e) -{ - m_lineEdit->event(e); -} - - -class UrlIconLabel : public QLabel -{ - -public: - UrlIconLabel(QWidget *parent); - - WebView *m_webView; - -protected: - void mousePressEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - -private: - QPoint m_dragStartPos; - -}; - -UrlIconLabel::UrlIconLabel(QWidget *parent) - : QLabel(parent) - , m_webView(0) -{ - setMinimumWidth(16); - setMinimumHeight(16); -} - -void UrlIconLabel::mousePressEvent(QMouseEvent *event) -{ - if (event->button() == Qt::LeftButton) - m_dragStartPos = event->pos(); - QLabel::mousePressEvent(event); -} - -void UrlIconLabel::mouseMoveEvent(QMouseEvent *event) -{ - if (event->buttons() == Qt::LeftButton - && (event->pos() - m_dragStartPos).manhattanLength() > QApplication::startDragDistance() - && m_webView) { - QDrag *drag = new QDrag(this); - QMimeData *mimeData = new QMimeData; - mimeData->setText(QString::fromUtf8(m_webView->url().toEncoded())); - QList urls; - urls.append(m_webView->url()); - mimeData->setUrls(urls); - drag->setMimeData(mimeData); - drag->exec(); - } -} - -UrlLineEdit::UrlLineEdit(QWidget *parent) - : ExLineEdit(parent) - , m_webView(0) - , m_iconLabel(0) -{ - // icon - m_iconLabel = new UrlIconLabel(this); - m_iconLabel->resize(16, 16); - setLeftWidget(m_iconLabel); - m_defaultBaseColor = palette().color(QPalette::Base); - - webViewIconChanged(); -} - -void UrlLineEdit::setWebView(WebView *webView) -{ - Q_ASSERT(!m_webView); - m_webView = webView; - m_iconLabel->m_webView = webView; - connect(webView, SIGNAL(urlChanged(QUrl)), - this, SLOT(webViewUrlChanged(QUrl))); - connect(webView, SIGNAL(loadFinished(bool)), - this, SLOT(webViewIconChanged())); - connect(webView, SIGNAL(iconChanged()), - this, SLOT(webViewIconChanged())); - connect(webView, SIGNAL(loadProgress(int)), - this, SLOT(update())); -} - -void UrlLineEdit::webViewUrlChanged(const QUrl &url) -{ - m_lineEdit->setText(QString::fromUtf8(url.toEncoded())); - m_lineEdit->setCursorPosition(0); -} - -void UrlLineEdit::webViewIconChanged() -{ - QUrl url = (m_webView) ? m_webView->url() : QUrl(); - QIcon icon = BrowserApplication::instance()->icon(url); - QPixmap pixmap(icon.pixmap(16, 16)); - m_iconLabel->setPixmap(pixmap); -} - -QLinearGradient UrlLineEdit::generateGradient(const QColor &color) const -{ - QLinearGradient gradient(0, 0, 0, height()); - gradient.setColorAt(0, m_defaultBaseColor); - gradient.setColorAt(0.15, color.lighter(120)); - gradient.setColorAt(0.5, color); - gradient.setColorAt(0.85, color.lighter(120)); - gradient.setColorAt(1, m_defaultBaseColor); - return gradient; -} - -void UrlLineEdit::focusOutEvent(QFocusEvent *event) -{ - if (m_lineEdit->text().isEmpty() && m_webView) - m_lineEdit->setText(QString::fromUtf8(m_webView->url().toEncoded())); - ExLineEdit::focusOutEvent(event); -} - -void UrlLineEdit::paintEvent(QPaintEvent *event) -{ - QPalette p = palette(); - if (m_webView && m_webView->url().scheme() == QLatin1String("https")) { - QColor lightYellow(248, 248, 210); - p.setBrush(QPalette::Base, generateGradient(lightYellow)); - } else { - p.setBrush(QPalette::Base, m_defaultBaseColor); - } - setPalette(p); - ExLineEdit::paintEvent(event); - - QPainter painter(this); - QStyleOptionFrameV2 panel; - initStyleOption(&panel); - QRect backgroundRect = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this); - if (m_webView && !hasFocus()) { - int progress = m_webView->progress(); - QColor loadingColor = QColor(116, 192, 250); - painter.setBrush(generateGradient(loadingColor)); - painter.setPen(Qt::transparent); - int mid = backgroundRect.width() / 100 * progress; - QRect progressRect(backgroundRect.x(), backgroundRect.y(), mid, backgroundRect.height()); - painter.drawRect(progressRect); - } -} diff --git a/examples/widgets/browser/urllineedit.h b/examples/widgets/browser/urllineedit.h deleted file mode 100644 index c30f40b57..000000000 --- a/examples/widgets/browser/urllineedit.h +++ /dev/null @@ -1,114 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef URLLINEEDIT_H -#define URLLINEEDIT_H - -#include -#include -#include - -QT_BEGIN_NAMESPACE -class QLineEdit; -QT_END_NAMESPACE - -class ClearButton; -class ExLineEdit : public QWidget -{ - Q_OBJECT - -public: - ExLineEdit(QWidget *parent = 0); - - inline QLineEdit *lineEdit() const { return m_lineEdit; } - - void setLeftWidget(QWidget *widget); - QWidget *leftWidget() const; - - QSize sizeHint() const; - - QVariant inputMethodQuery(Qt::InputMethodQuery property) const; -protected: - void focusInEvent(QFocusEvent *event); - void focusOutEvent(QFocusEvent *event); - void keyPressEvent(QKeyEvent *event); - void paintEvent(QPaintEvent *event); - void resizeEvent(QResizeEvent *event); - void inputMethodEvent(QInputMethodEvent *e); - bool event(QEvent *event); - -protected: - void updateGeometries(); - void initStyleOption(QStyleOptionFrameV2 *option) const; - - QWidget *m_leftWidget; - QLineEdit *m_lineEdit; - ClearButton *m_clearButton; -}; - -class UrlIconLabel; -class WebView; -class UrlLineEdit : public ExLineEdit -{ - Q_OBJECT - -public: - UrlLineEdit(QWidget *parent = 0); - void setWebView(WebView *webView); - -protected: - void paintEvent(QPaintEvent *event); - void focusOutEvent(QFocusEvent *event); - -private slots: - void webViewUrlChanged(const QUrl &url); - void webViewIconChanged(); - -private: - QLinearGradient generateGradient(const QColor &color) const; - WebView *m_webView; - UrlIconLabel *m_iconLabel; - QColor m_defaultBaseColor; - -}; - - -#endif // URLLINEEDIT_H diff --git a/examples/widgets/browser/webview.cpp b/examples/widgets/browser/webview.cpp deleted file mode 100644 index 193cb4797..000000000 --- a/examples/widgets/browser/webview.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "browserapplication.h" -#include "browsermainwindow.h" -#include "cookiejar.h" -#include "downloadmanager.h" -#include "networkaccessmanager.h" -#include "ui_passworddialog.h" -#include "ui_proxy.h" -#include "tabwidget.h" -#include "webview.h" - -#include -#include -#include -#include -#include - -#include - -#ifndef QT_NO_UITOOLS -#include -#endif //QT_NO_UITOOLS - -#include -#include - -WebPage::WebPage(QObject *parent) - : QWebEnginePage(parent) - , m_keyboardModifiers(Qt::NoModifier) - , m_pressedButtons(Qt::NoButton) - , m_openInNewTab(false) -{ -#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) - setNetworkAccessManager(BrowserApplication::networkAccessManager()); -#endif - connect(this, SIGNAL(unsupportedContent(QNetworkReply*)), - this, SLOT(handleUnsupportedContent(QNetworkReply*))); - connect(this, SIGNAL(authenticationRequired(const QUrl &, QAuthenticator*)), - SLOT(authenticationRequired(const QUrl &, QAuthenticator*))); - connect(this, SIGNAL(proxyAuthenticationRequired(const QUrl &, QAuthenticator *, const QString &)), - SLOT(proxyAuthenticationRequired(const QUrl &, QAuthenticator *, const QString &))); -} - -BrowserMainWindow *WebPage::mainWindow() -{ - QObject *w = this->parent(); - while (w) { - if (BrowserMainWindow *mw = qobject_cast(w)) - return mw; - w = w->parent(); - } - return BrowserApplication::instance()->mainWindow(); -} - -bool WebPage::acceptNavigationRequest(QWebEngineFrame *frame, const QNetworkRequest &request, NavigationType type) -{ -#if defined(QWEBENGINEPAGE_ACCEPTNAVIGATIONREQUEST) - // ctrl open in new tab - // ctrl-shift open in new tab and select - // ctrl-alt open in new window - if (type == QWebEnginePage::NavigationTypeLinkClicked - && (m_keyboardModifiers & Qt::ControlModifier - || m_pressedButtons == Qt::MidButton)) { - bool newWindow = (m_keyboardModifiers & Qt::AltModifier); - WebView *webView; - if (newWindow) { - BrowserApplication::instance()->newMainWindow(); - BrowserMainWindow *newMainWindow = BrowserApplication::instance()->mainWindow(); - webView = newMainWindow->currentTab(); - newMainWindow->raise(); - newMainWindow->activateWindow(); - webView->setFocus(); - } else { - bool selectNewTab = (m_keyboardModifiers & Qt::ShiftModifier); - webView = mainWindow()->tabWidget()->newTab(selectNewTab); - } - webView->load(request); - m_keyboardModifiers = Qt::NoModifier; - m_pressedButtons = Qt::NoButton; - return false; - } - m_loadingUrl = request.url(); - emit loadingUrl(m_loadingUrl); -#endif - return QWebEnginePage::acceptNavigationRequest(frame, request, type); -} - -class PopupWindow : public QWidget { - Q_OBJECT -public: - PopupWindow() - : m_addressBar(new QLineEdit(this)) - , m_view(new WebView(this)) - { - QVBoxLayout *layout = new QVBoxLayout; - layout->setMargin(0); - setLayout(layout); - layout->addWidget(m_addressBar); - layout->addWidget(m_view); - m_view->setFocus(); - - connect(m_view, &WebView::titleChanged, this, &QWidget::setWindowTitle); - connect(m_view, &WebView::urlChanged, this, &PopupWindow::setUrl); - connect(page(), &WebPage::geometryChangeRequested, this, &PopupWindow::adjustGeometry); - connect(page(), &WebPage::windowCloseRequested, this, &QWidget::close); - } - - QWebEnginePage* page() const { return m_view->page(); } - -private Q_SLOTS: - void setUrl(const QUrl &url) - { - m_addressBar->setText(url.toString()); - } - - void adjustGeometry(const QRect &newGeometry) - { - const int x1 = frameGeometry().left() - geometry().left(); - const int y1 = frameGeometry().top() - geometry().top(); - const int x2 = frameGeometry().right() - geometry().right(); - const int y2 = frameGeometry().bottom() - geometry().bottom(); - - setGeometry(newGeometry.adjusted(x1, y1 - m_addressBar->height(), x2, y2)); - } - -private: - QLineEdit *m_addressBar; - WebView *m_view; - -}; - -#include "webview.moc" - -QWebEnginePage *WebPage::createWindow(QWebEnginePage::WebWindowType type) -{ - if (m_keyboardModifiers & Qt::ControlModifier || m_pressedButtons == Qt::MidButton) - m_openInNewTab = true; - if (m_openInNewTab) { - m_openInNewTab = false; - return mainWindow()->tabWidget()->newTab()->page(); - } - if (type == QWebEnginePage::WebBrowserWindow) { - BrowserApplication::instance()->newMainWindow(); - BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow(); - return mainWindow->currentTab()->page(); - } else { - PopupWindow *popup = new PopupWindow; - popup->setAttribute(Qt::WA_DeleteOnClose); - popup->show(); - return popup->page(); - } -} - -#if !defined(QT_NO_UITOOLS) -QObject *WebPage::createPlugin(const QString &classId, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) -{ - Q_UNUSED(url); - Q_UNUSED(paramNames); - Q_UNUSED(paramValues); - QUiLoader loader; - return loader.createWidget(classId, view()); -} -#endif // !defined(QT_NO_UITOOLS) - -void WebPage::handleUnsupportedContent(QNetworkReply *reply) -{ -#if defined(QWEBENGINEPAGE_UNSUPPORTEDCONTENT) - QString errorString = reply->errorString(); - - if (m_loadingUrl != reply->url()) { - // sub resource of this page - qWarning() << "Resource" << reply->url().toEncoded() << "has unknown Content-Type, will be ignored."; - reply->deleteLater(); - return; - } - - if (reply->error() == QNetworkReply::NoError && !reply->header(QNetworkRequest::ContentTypeHeader).isValid()) { - errorString = "Unknown Content-Type"; - } - - QFile file(QLatin1String(":/notfound.html")); - bool isOpened = file.open(QIODevice::ReadOnly); - Q_ASSERT(isOpened); - Q_UNUSED(isOpened) - - QString title = tr("Error loading page: %1").arg(reply->url().toString()); - QString html = QString(QLatin1String(file.readAll())) - .arg(title) - .arg(errorString) - .arg(reply->url().toString()); - - QBuffer imageBuffer; - imageBuffer.open(QBuffer::ReadWrite); - QIcon icon = view()->style()->standardIcon(QStyle::SP_MessageBoxWarning, 0, view()); - QPixmap pixmap = icon.pixmap(QSize(32,32)); - if (pixmap.save(&imageBuffer, "PNG")) { - html.replace(QLatin1String("IMAGE_BINARY_DATA_HERE"), - QString(QLatin1String(imageBuffer.buffer().toBase64()))); - } - - QList frames; - frames.append(mainFrame()); - while (!frames.isEmpty()) { - QWebEngineFrame *frame = frames.takeFirst(); - if (frame->url() == reply->url()) { - frame->setHtml(html, reply->url()); - return; - } - QList children = frame->childFrames(); - foreach (QWebEngineFrame *frame, children) - frames.append(frame); - } - if (m_loadingUrl == reply->url()) { - mainFrame()->setHtml(html, reply->url()); - } -#endif -} - -void WebPage::authenticationRequired(const QUrl &requestUrl, QAuthenticator *auth) -{ - BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow(); - - QDialog dialog(mainWindow); - dialog.setWindowFlags(Qt::Sheet); - - Ui::PasswordDialog passwordDialog; - passwordDialog.setupUi(&dialog); - - passwordDialog.iconLabel->setText(QString()); - passwordDialog.iconLabel->setPixmap(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, 0, mainWindow).pixmap(32, 32)); - - QString introMessage = tr("Enter username and password for \"%1\" at %2"); - introMessage = introMessage.arg(auth->realm()).arg(requestUrl.toString().toHtmlEscaped()); - passwordDialog.introLabel->setText(introMessage); - passwordDialog.introLabel->setWordWrap(true); - - if (dialog.exec() == QDialog::Accepted) { - auth->setUser(passwordDialog.userNameLineEdit->text()); - auth->setPassword(passwordDialog.passwordLineEdit->text()); - } -} - -void WebPage::proxyAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth, const QString &proxyHost) -{ - BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow(); - - QDialog dialog(mainWindow); - dialog.setWindowFlags(Qt::Sheet); - - Ui::ProxyDialog proxyDialog; - proxyDialog.setupUi(&dialog); - - proxyDialog.iconLabel->setText(QString()); - proxyDialog.iconLabel->setPixmap(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, 0, mainWindow).pixmap(32, 32)); - - QString introMessage = tr("Connect to proxy \"%1\" using:"); - introMessage = introMessage.arg(proxyHost.toHtmlEscaped()); - proxyDialog.introLabel->setText(introMessage); - proxyDialog.introLabel->setWordWrap(true); - - if (dialog.exec() == QDialog::Accepted) { - auth->setUser(proxyDialog.userNameLineEdit->text()); - auth->setPassword(proxyDialog.passwordLineEdit->text()); - } -} - -WebView::WebView(QWidget* parent) - : QWebEngineView(parent) - , m_progress(0) - , m_page(new WebPage(this)) -{ - setPage(m_page); - connect(page(), SIGNAL(statusBarMessage(QString)), - SLOT(setStatusBarText(QString))); - connect(this, SIGNAL(loadProgress(int)), - this, SLOT(setProgress(int))); - connect(this, SIGNAL(loadFinished(bool)), - this, SLOT(loadFinished())); - connect(page(), SIGNAL(loadingUrl(QUrl)), - this, SIGNAL(urlChanged(QUrl))); - connect(page(), SIGNAL(downloadRequested(QNetworkRequest)), - this, SLOT(downloadRequested(QNetworkRequest))); -#if defined(QWEBENGINEPAGE_UNSUPPORTEDCONTENT) - page()->setForwardUnsupportedContent(true); -#endif - -} - -void WebView::contextMenuEvent(QContextMenuEvent *event) -{ -#if defined(QWEBENGINEPAGE_HITTESTCONTENT) - QWebEngineHitTestResult r = page()->hitTestContent(event->pos()); - if (!r.linkUrl().isEmpty()) { - QMenu menu(this); - menu.addAction(pageAction(QWebEnginePage::OpenLinkInNewWindow)); - menu.addAction(tr("Open in New Tab"), this, SLOT(openLinkInNewTab())); - menu.addSeparator(); - menu.addAction(pageAction(QWebEnginePage::DownloadLinkToDisk)); - // Add link to bookmarks... - menu.addSeparator(); - menu.addAction(pageAction(QWebEnginePage::CopyLinkToClipboard)); - if (page()->settings()->testAttribute(QWebEngineSettings::DeveloperExtrasEnabled)) - menu.addAction(pageAction(QWebEnginePage::InspectElement)); - menu.exec(mapToGlobal(event->pos())); - return; - } -#endif - QWebEngineView::contextMenuEvent(event); -} - -void WebView::wheelEvent(QWheelEvent *event) -{ -#if defined(QWEBENGINEPAGE_SETTEXTSIZEMULTIPLIER) - if (QApplication::keyboardModifiers() & Qt::ControlModifier) { - int numDegrees = event->delta() / 8; - int numSteps = numDegrees / 15; - setTextSizeMultiplier(textSizeMultiplier() + numSteps * 0.1); - event->accept(); - return; - } -#endif - QWebEngineView::wheelEvent(event); -} - -void WebView::openLinkInNewTab() -{ - m_page->m_openInNewTab = true; - pageAction(QWebEnginePage::OpenLinkInNewWindow)->trigger(); -} - -void WebView::setProgress(int progress) -{ - m_progress = progress; -} - -void WebView::loadFinished() -{ - if (100 != m_progress) { - qWarning() << "Received finished signal while progress is still:" << progress() - << "Url:" << url(); - } - m_progress = 0; -} - -void WebView::loadUrl(const QUrl &url) -{ - m_initialUrl = url; - load(url); -} - -QString WebView::lastStatusBarText() const -{ - return m_statusBarText; -} - -QUrl WebView::url() const -{ - QUrl url = QWebEngineView::url(); - if (!url.isEmpty()) - return url; - - return m_initialUrl; -} - -void WebView::mousePressEvent(QMouseEvent *event) -{ - m_page->m_pressedButtons = event->buttons(); - m_page->m_keyboardModifiers = event->modifiers(); - QWebEngineView::mousePressEvent(event); -} - -void WebView::mouseReleaseEvent(QMouseEvent *event) -{ - QWebEngineView::mouseReleaseEvent(event); - if (!event->isAccepted() && (m_page->m_pressedButtons & Qt::MidButton)) { - QUrl url(QApplication::clipboard()->text(QClipboard::Selection)); - if (!url.isEmpty() && url.isValid() && !url.scheme().isEmpty()) { - setUrl(url); - } - } -} - -void WebView::setStatusBarText(const QString &string) -{ - m_statusBarText = string; -} - -void WebView::downloadRequested(const QNetworkRequest &request) -{ - BrowserApplication::downloadManager()->download(request); -} diff --git a/examples/widgets/browser/webview.h b/examples/widgets/browser/webview.h deleted file mode 100644 index 2d3ec50cc..000000000 --- a/examples/widgets/browser/webview.h +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef WEBVIEW_H -#define WEBVIEW_H - -#include - -QT_BEGIN_NAMESPACE -class QAuthenticator; -class QMouseEvent; -class QNetworkProxy; -class QNetworkReply; -class QSslError; -QT_END_NAMESPACE - -class BrowserMainWindow; -class WebPage : public QWebEnginePage { - Q_OBJECT - -signals: - void loadingUrl(const QUrl &url); - -public: - WebPage(QObject *parent = 0); - BrowserMainWindow *mainWindow(); - -protected: - bool acceptNavigationRequest(QWebEngineFrame *frame, const QNetworkRequest &request, NavigationType type); - QWebEnginePage *createWindow(QWebEnginePage::WebWindowType type); -#if !defined(QT_NO_UITOOLS) - QObject *createPlugin(const QString &classId, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues); -#endif - -private slots: - void handleUnsupportedContent(QNetworkReply *reply); - void authenticationRequired(const QUrl &requestUrl, QAuthenticator *auth); - void proxyAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth, const QString &proxyHost); - -private: - friend class WebView; - - // set the webview mousepressedevent - Qt::KeyboardModifiers m_keyboardModifiers; - Qt::MouseButtons m_pressedButtons; - bool m_openInNewTab; - QUrl m_loadingUrl; -}; - -class WebView : public QWebEngineView { - Q_OBJECT - -public: - WebView(QWidget *parent = 0); - WebPage *webPage() const { return m_page; } - - void loadUrl(const QUrl &url); - QUrl url() const; - - QString lastStatusBarText() const; - inline int progress() const { return m_progress; } - -protected: - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void contextMenuEvent(QContextMenuEvent *event); - void wheelEvent(QWheelEvent *event); - -private slots: - void setProgress(int progress); - void loadFinished(); - void setStatusBarText(const QString &string); - void downloadRequested(const QNetworkRequest &request); - void openLinkInNewTab(); - -private: - QString m_statusBarText; - QUrl m_initialUrl; - int m_progress; - WebPage *m_page; -}; - -#endif diff --git a/examples/widgets/browser/xbel.cpp b/examples/widgets/browser/xbel.cpp deleted file mode 100644 index ae84a6a37..000000000 --- a/examples/widgets/browser/xbel.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "xbel.h" - -#include - -BookmarkNode::BookmarkNode(BookmarkNode::Type type, BookmarkNode *parent) : - expanded(false) - , m_parent(parent) - , m_type(type) -{ - if (parent) - parent->add(this); -} - -BookmarkNode::~BookmarkNode() -{ - if (m_parent) - m_parent->remove(this); - qDeleteAll(m_children); - m_parent = 0; - m_type = BookmarkNode::Root; -} - -bool BookmarkNode::operator==(const BookmarkNode &other) -{ - if (url != other.url - || title != other.title - || desc != other.desc - || expanded != other.expanded - || m_type != other.m_type - || m_children.count() != other.m_children.count()) - return false; - - for (int i = 0; i < m_children.count(); ++i) - if (!((*(m_children[i])) == (*(other.m_children[i])))) - return false; - return true; -} - -BookmarkNode::Type BookmarkNode::type() const -{ - return m_type; -} - -void BookmarkNode::setType(Type type) -{ - m_type = type; -} - -QList BookmarkNode::children() const -{ - return m_children; -} - -BookmarkNode *BookmarkNode::parent() const -{ - return m_parent; -} - -void BookmarkNode::add(BookmarkNode *child, int offset) -{ - Q_ASSERT(child->m_type != Root); - if (child->m_parent) - child->m_parent->remove(child); - child->m_parent = this; - if (-1 == offset) - offset = m_children.size(); - m_children.insert(offset, child); -} - -void BookmarkNode::remove(BookmarkNode *child) -{ - child->m_parent = 0; - m_children.removeAll(child); -} - - -XbelReader::XbelReader() -{ -} - -BookmarkNode *XbelReader::read(const QString &fileName) -{ - QFile file(fileName); - if (!file.exists()) { - return new BookmarkNode(BookmarkNode::Root); - } - file.open(QFile::ReadOnly); - return read(&file); -} - -BookmarkNode *XbelReader::read(QIODevice *device) -{ - BookmarkNode *root = new BookmarkNode(BookmarkNode::Root); - setDevice(device); - if (readNextStartElement()) { - QString version = attributes().value(QLatin1String("version")).toString(); - if (name() == QLatin1String("xbel") - && (version.isEmpty() || version == QLatin1String("1.0"))) { - readXBEL(root); - } else { - raiseError(QObject::tr("The file is not an XBEL version 1.0 file.")); - } - } - return root; -} - -void XbelReader::readXBEL(BookmarkNode *parent) -{ - Q_ASSERT(isStartElement() && name() == QLatin1String("xbel")); - - while (readNextStartElement()) { - if (name() == QLatin1String("folder")) - readFolder(parent); - else if (name() == QLatin1String("bookmark")) - readBookmarkNode(parent); - else if (name() == QLatin1String("separator")) - readSeparator(parent); - else - skipCurrentElement(); - } -} - -void XbelReader::readFolder(BookmarkNode *parent) -{ - Q_ASSERT(isStartElement() && name() == QLatin1String("folder")); - - BookmarkNode *folder = new BookmarkNode(BookmarkNode::Folder, parent); - folder->expanded = (attributes().value(QLatin1String("folded")) == QLatin1String("no")); - - while (readNextStartElement()) { - if (name() == QLatin1String("title")) - readTitle(folder); - else if (name() == QLatin1String("desc")) - readDescription(folder); - else if (name() == QLatin1String("folder")) - readFolder(folder); - else if (name() == QLatin1String("bookmark")) - readBookmarkNode(folder); - else if (name() == QLatin1String("separator")) - readSeparator(folder); - else - skipCurrentElement(); - } -} - -void XbelReader::readTitle(BookmarkNode *parent) -{ - Q_ASSERT(isStartElement() && name() == QLatin1String("title")); - parent->title = readElementText(); -} - -void XbelReader::readDescription(BookmarkNode *parent) -{ - Q_ASSERT(isStartElement() && name() == QLatin1String("desc")); - parent->desc = readElementText(); -} - -void XbelReader::readSeparator(BookmarkNode *parent) -{ - new BookmarkNode(BookmarkNode::Separator, parent); - // empty elements have a start and end element - readNext(); -} - -void XbelReader::readBookmarkNode(BookmarkNode *parent) -{ - Q_ASSERT(isStartElement() && name() == QLatin1String("bookmark")); - BookmarkNode *bookmark = new BookmarkNode(BookmarkNode::Bookmark, parent); - bookmark->url = attributes().value(QLatin1String("href")).toString(); - while (readNextStartElement()) { - if (name() == QLatin1String("title")) - readTitle(bookmark); - else if (name() == QLatin1String("desc")) - readDescription(bookmark); - else - skipCurrentElement(); - } - if (bookmark->title.isEmpty()) - bookmark->title = QObject::tr("Unknown title"); -} - - -XbelWriter::XbelWriter() -{ - setAutoFormatting(true); -} - -bool XbelWriter::write(const QString &fileName, const BookmarkNode *root) -{ - QFile file(fileName); - if (!root || !file.open(QFile::WriteOnly)) - return false; - return write(&file, root); -} - -bool XbelWriter::write(QIODevice *device, const BookmarkNode *root) -{ - setDevice(device); - - writeStartDocument(); - writeDTD(QLatin1String("")); - writeStartElement(QLatin1String("xbel")); - writeAttribute(QLatin1String("version"), QLatin1String("1.0")); - if (root->type() == BookmarkNode::Root) { - for (int i = 0; i < root->children().count(); ++i) - writeItem(root->children().at(i)); - } else { - writeItem(root); - } - - writeEndDocument(); - return true; -} - -void XbelWriter::writeItem(const BookmarkNode *parent) -{ - switch (parent->type()) { - case BookmarkNode::Folder: - writeStartElement(QLatin1String("folder")); - writeAttribute(QLatin1String("folded"), parent->expanded ? QLatin1String("no") : QLatin1String("yes")); - writeTextElement(QLatin1String("title"), parent->title); - for (int i = 0; i < parent->children().count(); ++i) - writeItem(parent->children().at(i)); - writeEndElement(); - break; - case BookmarkNode::Bookmark: - writeStartElement(QLatin1String("bookmark")); - if (!parent->url.isEmpty()) - writeAttribute(QLatin1String("href"), parent->url); - writeTextElement(QLatin1String("title"), parent->title); - if (!parent->desc.isEmpty()) - writeAttribute(QLatin1String("desc"), parent->desc); - writeEndElement(); - break; - case BookmarkNode::Separator: - writeEmptyElement(QLatin1String("separator")); - break; - default: - break; - } -} diff --git a/examples/widgets/browser/xbel.h b/examples/widgets/browser/xbel.h deleted file mode 100644 index 8ee9558ef..000000000 --- a/examples/widgets/browser/xbel.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef XBEL_H -#define XBEL_H - -#include -#include - -class BookmarkNode -{ -public: - enum Type { - Root, - Folder, - Bookmark, - Separator - }; - - BookmarkNode(Type type = Root, BookmarkNode *parent = 0); - ~BookmarkNode(); - bool operator==(const BookmarkNode &other); - - Type type() const; - void setType(Type type); - QList children() const; - BookmarkNode *parent() const; - - void add(BookmarkNode *child, int offset = -1); - void remove(BookmarkNode *child); - - QString url; - QString title; - QString desc; - bool expanded; - -private: - BookmarkNode *m_parent; - Type m_type; - QList m_children; - -}; - -class XbelReader : public QXmlStreamReader -{ -public: - XbelReader(); - BookmarkNode *read(const QString &fileName); - BookmarkNode *read(QIODevice *device); - -private: - void readXBEL(BookmarkNode *parent); - void readTitle(BookmarkNode *parent); - void readDescription(BookmarkNode *parent); - void readSeparator(BookmarkNode *parent); - void readFolder(BookmarkNode *parent); - void readBookmarkNode(BookmarkNode *parent); -}; - -#include - -class XbelWriter : public QXmlStreamWriter -{ -public: - XbelWriter(); - bool write(const QString &fileName, const BookmarkNode *root); - bool write(QIODevice *device, const BookmarkNode *root); - -private: - void writeItem(const BookmarkNode *parent); -}; - -#endif // XBEL_H diff --git a/examples/widgets/fancybrowser/doc/images/fancybrowser-example.png b/examples/widgets/fancybrowser/doc/images/fancybrowser-example.png deleted file mode 100644 index 717ac9ddc..000000000 Binary files a/examples/widgets/fancybrowser/doc/images/fancybrowser-example.png and /dev/null differ diff --git a/examples/widgets/fancybrowser/doc/src/fancybrowser.qdoc b/examples/widgets/fancybrowser/doc/src/fancybrowser.qdoc deleted file mode 100644 index c1de06332..000000000 --- a/examples/widgets/fancybrowser/doc/src/fancybrowser.qdoc +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: http://www.gnu.org/copyleft/fdl.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example webengine/fancybrowser - \title Fancy Browser Example - \brief Demonstrates how to use browse web and manipulate content - \ingroup webengine-widgetexamples - - \brief The Fancy Browser example shows how to use JQuery with QtWebEngine to - create a web browser with special effects and content - manipulation. - - \image fancybrowser-example.png - - The application makes use of QWebEnginePage::evaluateJavaScript to - evaluate the jQuery JavaScript code. A QMainWindow with a QWebEngineView - as central widget builds up the browser itself. - - \section1 MainWindow Class Definition - - The \c MainWindow class inherits QMainWindow. It implements a number of - slots to perform actions on both the application and on the web content. - - \snippet webenginewidgets/fancybrowser/mainwindow.h 1 - - We also declare a QString that contains the jQuery, a QWebView - that displays the web content, and a QLineEdit that acts as the - address bar. - - \section1 MainWindow Class Implementation - - We start by implementing the constructor. - - \snippet webenginewidgets/fancybrowser/mainwindow.cpp 1 - - The first part of the constructor sets the value of \c progress to - 0. This value will be used later in the code to visualize the - loading of a webpage. - - Next, the jQuery library is loaded using a QFile and reading the file - content. The jQuery library is a JavaScript library that provides different - functions for manipulating HTML. - - \snippet webenginewidgets/fancybrowser/mainwindow.cpp 2 - - The second part of the constructor creates a QWebView and connects - slots to the views signals. Furthermore, we create a QLineEdit as - the browsers address bar. We then set the horizontal QSizePolicy - to fill the available area in the browser at all times. We add the - QLineEdit to a QToolbar together with a set of navigation actions - from QWebView::pageAction. - - \snippet webenginewidgets/fancybrowser/mainwindow.cpp 3 - - The third and last part of the constructor implements two QMenus and assigns - a set of actions to them. The last line sets the QWebView as the central - widget in the QMainWindow. - - \snippet webenginewidgets/fancybrowser/mainwindow.cpp 4 - - When the page is loaded, \c adjustLocation() updates the address - bar; \c adjustLocation() is triggered by the \c loadFinished() - signal in QWebView. In \c changeLocation() we create a QUrl - object, and then use it to load the page into the QWebView. When - the new web page has finished loading, \c adjustLocation() will be - run once more to update the address bar. - - \snippet webenginewidgets/fancybrowser/mainwindow.cpp 5 - - \c adjustTitle() sets the window title and displays the loading - progress. This slot is triggered by the \c titleChanged() signal - in QWebView. - - \snippet webenginewidgets/fancybrowser/mainwindow.cpp 6 - - When a web page has loaded, \c finishLoading() is triggered by the - \c loadFinished() signal in QWebView. \c finishLoading() then updates the - progress in the title bar and calls \c evaluateJavaScript() - to evaluate the jQuery library. This evaluates the JavaScript against the - current web page. What that means is that the JavaScript can be viewed as - part of the content loaded into the QWebView, and therefore needs to be - loaded every time a new page is loaded. Once the jQuery library is loaded, - we can start executing the different jQuery functions in the browser. - - The rotateImages() function is then called explicitely to make sure - that the images of the newly loaded page respect the state of the toggle - action. - - \snippet webenginewidgets/fancybrowser/mainwindow.cpp 7 - - The first jQuery-based function, \c highlightAllLinks(), is designed to - highlight all links in the current webpage. The JavaScript code looks - for web elements named \e {a}, which is the tag for a hyperlink. - For each such element, the background color is set to be yellow by - using CSS. - - \snippet webenginewidgets/fancybrowser/mainwindow.cpp 8 - - The \c rotateImages() function rotates the images on the current - web page. This JavaScript code relies on CSS transforms and - looks up all \e {img} elements and rotates the images 180 degrees - and then back again. - - \snippet webenginewidgets/fancybrowser/mainwindow.cpp 9 - - The remaining four methods remove different elements from the current web - page. \c removeGifImages() removes all GIF images on the page by looking up - the \e {src} attribute of all the elements on the web page. Any element with - a \e {gif} file as its source is removed. \c removeInlineFrames() removes all - \e {iframe} or inline elements. \c removeObjectElements() removes all - \e {object} elements, and \c removeEmbeddedElements() removes any elements - such as plugins embedded on the page using the \e {embed} tag. - -*/ - diff --git a/examples/widgets/fancybrowser/fancybrowser.pro b/examples/widgets/fancybrowser/fancybrowser.pro deleted file mode 100644 index eb5e5a34c..000000000 --- a/examples/widgets/fancybrowser/fancybrowser.pro +++ /dev/null @@ -1,12 +0,0 @@ -QT += webenginewidgets - -macx: CONFIG -= app_bundle - -HEADERS = mainwindow.h -SOURCES = main.cpp \ - mainwindow.cpp -RESOURCES = jquery.qrc - -# install -#target.path = $$[QT_INSTALL_EXAMPLES]/webkitwidgets/fancybrowser -#INSTALLS += target diff --git a/examples/widgets/fancybrowser/jquery.min.js b/examples/widgets/fancybrowser/jquery.min.js deleted file mode 100644 index b1ae21d8b..000000000 --- a/examples/widgets/fancybrowser/jquery.min.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * jQuery JavaScript Library v1.3.2 - * http://jquery.com/ - * - * Copyright (c) 2009 John Resig - * Dual licensed under the MIT and GPL licenses. - * http://docs.jquery.com/License - * - * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) - * Revision: 6246 - */ -(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
"]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
","
"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); -/* - * Sizzle CSS Selector Engine - v0.9.3 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/examples/widgets/fancybrowser/jquery.qrc b/examples/widgets/fancybrowser/jquery.qrc deleted file mode 100644 index 1022d682f..000000000 --- a/examples/widgets/fancybrowser/jquery.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - jquery.min.js - - diff --git a/examples/widgets/fancybrowser/main.cpp b/examples/widgets/fancybrowser/main.cpp deleted file mode 100644 index 451f247f3..000000000 --- a/examples/widgets/fancybrowser/main.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "mainwindow.h" - -int main(int argc, char * argv[]) -{ - QApplication app(argc, argv); - QUrl url; - if (argc > 1) - url = QUrl::fromUserInput(argv[1]); - else - url = QUrl("http://www.google.com/ncr"); - MainWindow *browser = new MainWindow(url); - browser->show(); - return app.exec(); -} diff --git a/examples/widgets/fancybrowser/mainwindow.cpp b/examples/widgets/fancybrowser/mainwindow.cpp deleted file mode 100644 index 3366d2006..000000000 --- a/examples/widgets/fancybrowser/mainwindow.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include "mainwindow.h" - -template -struct InvokeWrapper { - R *receiver; - void (C::*memberFun)(Arg); - void operator()(Arg result) { - (receiver->*memberFun)(result); - } -}; - -template -InvokeWrapper invoke(R *receiver, void (C::*memberFun)(Arg)) -{ - InvokeWrapper wrapper = {receiver, memberFun}; - return wrapper; -} - -//! [1] - -MainWindow::MainWindow(const QUrl& url) -{ - progress = 0; - - QFile file; - file.setFileName(":/jquery.min.js"); - file.open(QIODevice::ReadOnly); - jQuery = file.readAll(); - jQuery.append("\nvar qt = { 'jQuery': jQuery.noConflict(true) };"); - file.close(); - -//! [1] - view = new QWebEngineView(this); - view->load(url); - connect(view, SIGNAL(loadFinished(bool)), SLOT(adjustLocation())); - connect(view, SIGNAL(titleChanged(QString)), SLOT(adjustTitle())); - connect(view, SIGNAL(loadProgress(int)), SLOT(setProgress(int))); - connect(view, SIGNAL(loadFinished(bool)), SLOT(finishLoading(bool))); - - locationEdit = new QLineEdit(this); - locationEdit->setSizePolicy(QSizePolicy::Expanding, locationEdit->sizePolicy().verticalPolicy()); - connect(locationEdit, SIGNAL(returnPressed()), SLOT(changeLocation())); - - QToolBar *toolBar = addToolBar(tr("Navigation")); - toolBar->addAction(view->pageAction(QWebEnginePage::Back)); - toolBar->addAction(view->pageAction(QWebEnginePage::Forward)); - toolBar->addAction(view->pageAction(QWebEnginePage::Reload)); - toolBar->addAction(view->pageAction(QWebEnginePage::Stop)); - toolBar->addWidget(locationEdit); -//! [1] - - QMenu *viewMenu = menuBar()->addMenu(tr("&View")); - QAction* viewSourceAction = new QAction("Page Source", this); - connect(viewSourceAction, SIGNAL(triggered()), SLOT(viewSource())); - viewMenu->addAction(viewSourceAction); - -//! [3] - QMenu *effectMenu = menuBar()->addMenu(tr("&Effect")); - effectMenu->addAction("Highlight all links", this, SLOT(highlightAllLinks())); - - rotateAction = new QAction(this); - rotateAction->setIcon(style()->standardIcon(QStyle::SP_FileDialogDetailedView)); - rotateAction->setCheckable(true); - rotateAction->setText(tr("Turn images upside down")); - connect(rotateAction, SIGNAL(toggled(bool)), this, SLOT(rotateImages(bool))); - effectMenu->addAction(rotateAction); - - QMenu *toolsMenu = menuBar()->addMenu(tr("&Tools")); - toolsMenu->addAction(tr("Remove GIF images"), this, SLOT(removeGifImages())); - toolsMenu->addAction(tr("Remove all inline frames"), this, SLOT(removeInlineFrames())); - toolsMenu->addAction(tr("Remove all object elements"), this, SLOT(removeObjectElements())); - toolsMenu->addAction(tr("Remove all embedded elements"), this, SLOT(removeEmbeddedElements())); - - setCentralWidget(view); - setUnifiedTitleAndToolBarOnMac(true); -} -//! [3] - -void MainWindow::viewSource() -{ - QTextEdit* textEdit = new QTextEdit(NULL); - textEdit->setAttribute(Qt::WA_DeleteOnClose); - textEdit->adjustSize(); - textEdit->move(this->geometry().center() - textEdit->rect().center()); - textEdit->show(); - - view->page()->toHtml(invoke(textEdit, &QTextEdit::setPlainText)); -} - -//! [4] -void MainWindow::adjustLocation() -{ - locationEdit->setText(view->url().toString()); -} - -void MainWindow::changeLocation() -{ - QUrl url = QUrl::fromUserInput(locationEdit->text()); - view->load(url); - view->setFocus(); -} -//! [4] - -//! [5] -void MainWindow::adjustTitle() -{ - if (progress <= 0 || progress >= 100) - setWindowTitle(view->title()); - else - setWindowTitle(QString("%1 (%2%)").arg(view->title()).arg(progress)); -} - -void MainWindow::setProgress(int p) -{ - progress = p; - adjustTitle(); -} -//! [5] - -//! [6] -void MainWindow::finishLoading(bool) -{ - progress = 100; - adjustTitle(); - view->page()->runJavaScript(jQuery); - - rotateImages(rotateAction->isChecked()); -} -//! [6] - -//! [7] -void MainWindow::highlightAllLinks() -{ - // We append '; undefined' after the jQuery call here to prevent a possible recursion loop and crash caused by - // the way the elements returned by the each iterator elements reference each other, which causes problems upon - // converting them to QVariants. - QString code = "qt.jQuery('a').each( function () { qt.jQuery(this).css('background-color', 'yellow') } ); undefined"; - view->page()->runJavaScript(code); -} -//! [7] - -//! [8] -void MainWindow::rotateImages(bool invert) -{ - QString code; - - // We append '; undefined' after each of the jQuery calls here to prevent a possible recursion loop and crash caused by - // the way the elements returned by the each iterator elements reference each other, which causes problems upon - // converting them to QVariants. - if (invert) - code = "qt.jQuery('img').each( function () { qt.jQuery(this).css('-webkit-transition', '-webkit-transform 2s'); qt.jQuery(this).css('-webkit-transform', 'rotate(180deg)') } ); undefined"; - else - code = "qt.jQuery('img').each( function () { qt.jQuery(this).css('-webkit-transition', '-webkit-transform 2s'); qt.jQuery(this).css('-webkit-transform', 'rotate(0deg)') } ); undefined"; - view->page()->runJavaScript(code); -} -//! [8] - -//! [9] -void MainWindow::removeGifImages() -{ - QString code = "qt.jQuery('[src*=gif]').remove()"; - view->page()->runJavaScript(code); -} - -void MainWindow::removeInlineFrames() -{ - QString code = "qt.jQuery('iframe').remove()"; - view->page()->runJavaScript(code); -} - -void MainWindow::removeObjectElements() -{ - QString code = "qt.jQuery('object').remove()"; - view->page()->runJavaScript(code); -} - -void MainWindow::removeEmbeddedElements() -{ - QString code = "qt.jQuery('embed').remove()"; - view->page()->runJavaScript(code); -} -//! [9] - diff --git a/examples/widgets/fancybrowser/mainwindow.h b/examples/widgets/fancybrowser/mainwindow.h deleted file mode 100644 index 5f33bdf96..000000000 --- a/examples/widgets/fancybrowser/mainwindow.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -QT_BEGIN_NAMESPACE -class QWebEngineView; -class QLineEdit; -QT_END_NAMESPACE - -//! [1] -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - MainWindow(const QUrl& url); - -protected slots: - - void adjustLocation(); - void changeLocation(); - void adjustTitle(); - void setProgress(int p); - void finishLoading(bool); - - void viewSource(); - - void highlightAllLinks(); - void rotateImages(bool invert); - void removeGifImages(); - void removeInlineFrames(); - void removeObjectElements(); - void removeEmbeddedElements(); - -private: - QString jQuery; - QWebEngineView *view; - QLineEdit *locationEdit; - QAction *rotateAction; - int progress; -//! [1] -}; -- cgit v1.2.3