diff options
227 files changed, 3076 insertions, 15686 deletions
diff --git a/.qmake.conf b/.qmake.conf index d5977d016..76ab2f4b2 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -5,4 +5,4 @@ QTWEBENGINE_OUT_ROOT = $$shadowed($$PWD) load(qt_build_config) CONFIG += warning_clean -MODULE_VERSION = 5.9.2 +MODULE_VERSION = 5.10.0 diff --git a/config.tests/libvpx/libvpx.cpp b/config.tests/libvpx/libvpx.cpp index 258790309..ec261cd5a 100644 --- a/config.tests/libvpx/libvpx.cpp +++ b/config.tests/libvpx/libvpx.cpp @@ -28,6 +28,11 @@ #include <vpx/svc_context.h> #include <vpx/vpx_frame_buffer.h> +#include <vpx/vp8dx.h> + +#ifndef VPX_CTRL_VPXD_GET_LAST_QUANTIZER +#error "This version of libvpx is too old, it is missing VPX_CTRL_VPXD_GET_LAST_QUANTIZER define" +#endif int main(int, char **) { diff --git a/configure.json b/configure.json index e82247ec5..b291e6645 100644 --- a/configure.json +++ b/configure.json @@ -12,6 +12,7 @@ "ffmpeg": { "type": "enum", "name": "system-ffmpeg", "values": { "system": "yes", "qt": "no" } }, "opus": { "type": "enum", "name": "system-opus", "values": { "system": "yes", "qt": "no" } }, "webp": { "type": "enum", "name": "system-webp", "values": { "system": "yes", "qt": "no" } }, + "nss-certificate-handling": "boolean", "pepper-plugins": "boolean", "printing-and-pdf": "boolean", "proprietary-codecs": "boolean", @@ -58,6 +59,12 @@ "sources": [ { "type": "pkgConfig", "args": "libwebp libwebpdemux" } ] + }, + "nss": { + "label": "NSS", + "sources": [ + { "type": "pkgConfig", "args": "nss" } + ] } }, @@ -67,6 +74,18 @@ "type": "detectPython2", "log": "location" }, + "gperf": { + "label": "gperf", + "type": "detectGperf" + }, + "bison": { + "label": "bison", + "type": "detectBison" + }, + "flex": { + "label": "flex", + "type": "detectFlex" + }, "ninja": { "label": "system ninja", "type": "detectNinja" @@ -86,9 +105,25 @@ "label": "Python 2", "condition": "tests.python2", "output": [ + "privateFeature", { "type": "varAssign", "name": "QMAKE_PYTHON2", "value": "tests.python2.location" } ] }, + "gperf": { + "label": "gperf", + "condition": "tests.gperf", + "output": [ "privateFeature" ] + }, + "bison": { + "label": "bison", + "condition": "tests.bison", + "output": [ "privateFeature" ] + }, + "flex": { + "label": "flex", + "condition": "tests.flex", + "output": [ "privateFeature" ] + }, "embedded": { "label": "Embedded build", "purpose": "Enables the embedded build configuration.", @@ -143,6 +178,14 @@ "autoDetect": "!features.embedded", "output": [ "privateFeature" ] }, + "nss-certificate-handling": { + "label": "NSS certificate handling", + "purpose": "Use NSS to handle certificates instead of BoringSSL. Recommended on Linux.", + "section": "WebEngine", + "condition": "config.unix && !config.darwin", + "autoDetect": "libs.nss", + "output": [ "privateFeature" ] + }, "system-webp": { "label": "libwebp and libwebpdemux", "autoDetect": "config.unix", @@ -185,6 +228,21 @@ "type": "warning", "condition": "!features.python2", "message": "Python version 2 (2.7.5 or later) is required to build QtWebEngine." + }, + { + "type": "warning", + "condition": "!features.gperf", + "message": "gperf is required to build QtWebEngine." + }, + { + "type": "warning", + "condition": "!features.bison", + "message": "bison is required to build QtWebEngine." + }, + { + "type": "warning", + "condition": "!features.flex", + "message": "flex is required to build QtWebEngine." } ], @@ -210,6 +268,11 @@ "condition": "config.unix" }, { + "type": "feature", + "args": "nss-certificate-handling", + "condition": "config.unix && !config.darwin" + }, + { "section": "System libraries", "condition": "config.unix", "entries": [ diff --git a/configure.pri b/configure.pri index ce36642bb..2d6983354 100644 --- a/configure.pri +++ b/configure.pri @@ -41,6 +41,36 @@ defineTest(qtConfTest_detectPython2) { return(true) } +defineTest(qtConfTest_detectGperf) { + gperf = $$qtConfFindInPath("gperf$$EXE_SUFFIX") + isEmpty(gperf) { + qtLog("Required gperf could not be found.") + return(false) + } + qtLog("Found gperf from path: $$gperf") + return(true) +} + +defineTest(qtConfTest_detectBison) { + bison = $$qtConfFindInPath("bison$$EXE_SUFFIX") + isEmpty(bison) { + qtLog("Required bison could not be found.") + return(false) + } + qtLog("Found bison from path: $$bison") + return(true) +} + +defineTest(qtConfTest_detectFlex) { + flex = $$qtConfFindInPath("flex$$EXE_SUFFIX") + isEmpty(flex) { + qtLog("Required flex could not be found.") + return(false) + } + qtLog("Found flex from path: $$flex") + return(true) +} + defineTest(qtConfTest_detectNinja) { ninja = $$qtConfFindInPath("ninja$$EXE_SUFFIX") !isEmpty(ninja) { diff --git a/examples/webenginewidgets/demobrowser/Info_mac.plist b/examples/webenginewidgets/demobrowser/Info_mac.plist deleted file mode 100644 index 25443f7be..000000000 --- a/examples/webenginewidgets/demobrowser/Info_mac.plist +++ /dev/null @@ -1,47 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd"> -<plist version="1.0"> -<dict> - <key>NSPrincipalClass</key> - <string>NSApplication</string> - <key>CFBundleIconFile</key> - <string>@ICON@</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleGetInfoString</key> - <string>Created by Qt/QMake</string> - <key>CFBundleIdentifier</key> - <string>com.trolltech.DemoBrowser</string> - <key>CFBundleSignature</key> - <string>ttxt</string> - <key>CFBundleExecutable</key> - <string>@EXECUTABLE@</string> - <key>CFBundleDocumentTypes</key> - <array> - <dict> - <key>CFBundleTypeExtensions</key> - <array> - <string>html</string> - <string>htm</string> - <string>shtml</string> - <string>xht</string> - <string>xhtml</string> - </array> - <key>CFBundleTypeIconFile</key> - <string>@ICON@</string> - <key>CFBundleTypeName</key> - <string>HTML Document</string> - <key>CFBundleTypeOSTypes</key> - <array> - <string>HTML</string> - </array> - <key>CFBundleTypeRole</key> - <string>Viewer</string> - </dict> - </array> - <key>NOTE</key> - <string>DemoBrowser by The Qt Company Ltd.</string> - <key>NSSupportsAutomaticGraphicsSwitching</key> - <string>YES</string> -</dict> -</plist> diff --git a/examples/webenginewidgets/demobrowser/addbookmarkdialog.ui b/examples/webenginewidgets/demobrowser/addbookmarkdialog.ui deleted file mode 100644 index 3460d7bb8..000000000 --- a/examples/webenginewidgets/demobrowser/addbookmarkdialog.ui +++ /dev/null @@ -1,98 +0,0 @@ -<ui version="4.0" > - <class>AddBookmarkDialog</class> - <widget class="QDialog" name="AddBookmarkDialog" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>240</width> - <height>168</height> - </rect> - </property> - <property name="windowTitle" > - <string>Add Bookmark</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout" > - <item> - <widget class="QLabel" name="label" > - <property name="text" > - <string>Type a name for the bookmark, and choose where to keep it.</string> - </property> - <property name="textFormat" > - <enum>Qt::PlainText</enum> - </property> - <property name="wordWrap" > - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="name" /> - </item> - <item> - <widget class="QComboBox" name="location" /> - </item> - <item> - <spacer name="verticalSpacer" > - <property name="orientation" > - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>20</width> - <height>2</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox" > - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons" > - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - <property name="centerButtons" > - <bool>false</bool> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>AddBookmarkDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel" > - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel" > - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>AddBookmarkDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel" > - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel" > - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/examples/webenginewidgets/demobrowser/autosaver.cpp b/examples/webenginewidgets/demobrowser/autosaver.cpp deleted file mode 100644 index 005e291bd..000000000 --- a/examples/webenginewidgets/demobrowser/autosaver.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "autosaver.h" - -#include <QtCore/QDir> -#include <QtCore/QCoreApplication> -#include <QtCore/QMetaObject> -#include <QtDebug> - -#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/demobrowser/autosaver.h b/examples/webenginewidgets/demobrowser/autosaver.h deleted file mode 100644 index be6eeeb4c..000000000 --- a/examples/webenginewidgets/demobrowser/autosaver.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef AUTOSAVER_H -#define AUTOSAVER_H - -#include <QtCore/QObject> -#include <QtCore/QBasicTimer> -#include <QtCore/QTime> - -/* - 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/demobrowser/bookmarks.cpp b/examples/webenginewidgets/demobrowser/bookmarks.cpp deleted file mode 100644 index 3d6d9c294..000000000 --- a/examples/webenginewidgets/demobrowser/bookmarks.cpp +++ /dev/null @@ -1,993 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "bookmarks.h" - -#include "autosaver.h" -#include "browserapplication.h" -#include "history.h" -#include "xbel.h" - -#include <QtCore/QBuffer> -#include <QtCore/QFile> -#include <QtCore/QMimeData> - -#include <QtGui/QDesktopServices> -#include <QtGui/QDragEnterEvent> -#include <QtGui/QIcon> -#include <QtWidgets/QFileDialog> -#include <QtWidgets/QHeaderView> -#include <QtWidgets/QMessageBox> -#include <QtWidgets/QToolButton> - -#include <QtCore/QDebug> - -#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<BookmarkNode*> 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<BookmarkNode*>(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<BookmarkNode*> 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<BookmarkNode*>(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<QAction*> 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<QUrl> 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<QUrl>()) { - emit openUrl(v.toUrl()); - } -} - -void BookmarksToolBar::activated(const QModelIndex &index) -{ - emit openUrl(index.data(BookmarksModel::UrlRole).toUrl()); -} diff --git a/examples/webenginewidgets/demobrowser/bookmarks.h b/examples/webenginewidgets/demobrowser/bookmarks.h deleted file mode 100644 index 922e7ce39..000000000 --- a/examples/webenginewidgets/demobrowser/bookmarks.h +++ /dev/null @@ -1,318 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BOOKMARKS_H -#define BOOKMARKS_H - -#include <QtCore/QObject> -#include <QtCore/QAbstractItemModel> - -#include <QtWidgets/QUndoCommand> - -/*! - 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<QAction*> actions); - -protected: - bool prePopulated(); - -private slots: - void activated(const QModelIndex &index); - -private: - BookmarksManager *m_bookmarksManager; - QList<QAction*> m_initialActions; -}; - -/* - Proxy model that filters out the bookmarks so only the folders - are left behind. Used in the add bookmark dialog combobox. - */ -#include <QtCore/QSortFilterProxyModel> -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 <QtWidgets/QToolBar> -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/demobrowser/bookmarks.ui b/examples/webenginewidgets/demobrowser/bookmarks.ui deleted file mode 100644 index c893e941d..000000000 --- a/examples/webenginewidgets/demobrowser/bookmarks.ui +++ /dev/null @@ -1,106 +0,0 @@ -<ui version="4.0" > - <class>BookmarksDialog</class> - <widget class="QDialog" name="BookmarksDialog" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>758</width> - <height>450</height> - </rect> - </property> - <property name="windowTitle" > - <string>Bookmarks</string> - </property> - <layout class="QGridLayout" name="gridLayout" > - <item row="0" column="0" > - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>252</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="1" > - <widget class="SearchLineEdit" name="search" /> - </item> - <item row="1" column="0" colspan="2" > - <widget class="EditTreeView" name="tree" /> - </item> - <item row="2" column="0" colspan="2" > - <layout class="QHBoxLayout" > - <item> - <widget class="QPushButton" name="removeButton" > - <property name="text" > - <string>&Remove</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="addFolderButton" > - <property name="text" > - <string>Add Folder</string> - </property> - </widget> - </item> - <item> - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox" > - <property name="standardButtons" > - <set>QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>SearchLineEdit</class> - <extends>QLineEdit</extends> - <header>searchlineedit.h</header> - </customwidget> - <customwidget> - <class>EditTreeView</class> - <extends>QTreeView</extends> - <header>edittreeview.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>BookmarksDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel" > - <x>472</x> - <y>329</y> - </hint> - <hint type="destinationlabel" > - <x>461</x> - <y>356</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/examples/webenginewidgets/demobrowser/browserapplication.cpp b/examples/webenginewidgets/demobrowser/browserapplication.cpp deleted file mode 100644 index c3f3ef9b9..000000000 --- a/examples/webenginewidgets/demobrowser/browserapplication.cpp +++ /dev/null @@ -1,587 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "browserapplication.h" - -#include "bookmarks.h" -#include "browsermainwindow.h" -#include "cookiejar.h" -#include "downloadmanager.h" -#include "history.h" -#include "tabwidget.h" -#include "webview.h" - -#include <QtCore/QBuffer> -#include <QtCore/QDir> -#include <QtCore/QLibraryInfo> -#include <QtCore/QSettings> -#include <QtCore/QTextStream> -#include <QtCore/QTranslator> - -#include <QtGui/QDesktopServices> -#include <QtGui/QFileOpenEvent> -#include <QtWidgets/QMessageBox> - -#include <QtNetwork/QLocalServer> -#include <QtNetwork/QLocalSocket> -#include <QtNetwork/QNetworkProxy> -#include <QtNetwork/QSslSocket> - -#include <QWebEngineProfile> -#include <QWebEngineSettings> -#include <QWebEngineScript> -#include <QWebEngineScriptCollection> - -#include <QtCore/QDebug> - -DownloadManager *BrowserApplication::s_downloadManager = 0; -HistoryManager *BrowserApplication::s_historyManager = 0; -QNetworkAccessManager *BrowserApplication::s_networkAccessManager = 0; -BookmarksManager *BrowserApplication::s_bookmarksManager = 0; - -static void setUserStyleSheet(QWebEngineProfile *profile, const QString &styleSheet, BrowserMainWindow *mainWindow = 0) -{ - Q_ASSERT(profile); - QString scriptName(QStringLiteral("userStyleSheet")); - QWebEngineScript script; - QList<QWebEngineScript> styleSheets = profile->scripts()->findScripts(scriptName); - if (!styleSheets.isEmpty()) - script = styleSheets.first(); - Q_FOREACH (const QWebEngineScript &s, styleSheets) - profile->scripts()->remove(s); - - if (script.isNull()) { - script.setName(scriptName); - script.setInjectionPoint(QWebEngineScript::DocumentReady); - script.setRunsOnSubFrames(true); - script.setWorldId(QWebEngineScript::ApplicationWorld); - } - QString source = QString::fromLatin1("(function() {"\ - "var css = document.getElementById(\"_qt_testBrowser_userStyleSheet\");"\ - "if (css == undefined) {"\ - " css = document.createElement(\"style\");"\ - " css.type = \"text/css\";"\ - " css.id = \"_qt_testBrowser_userStyleSheet\";"\ - " document.head.appendChild(css);"\ - "}"\ - "css.innerText = \"%1\";"\ - "})()").arg(styleSheet); - script.setSourceCode(source); - profile->scripts()->insert(script); - // run the script on the already loaded views - // this has to be deferred as it could mess with the storage initialization on startup - if (mainWindow) - QMetaObject::invokeMethod(mainWindow, "runScriptOnOpenViews", Qt::QueuedConnection, Q_ARG(QString, source)); -} - -BrowserApplication::BrowserApplication(int &argc, char **argv) - : QApplication(argc, argv) - , m_localServer(0) - , m_privateProfile(0) - , m_privateBrowsing(false) -{ - QCoreApplication::setOrganizationName(QLatin1String("Qt")); - QCoreApplication::setApplicationName(QLatin1String("demobrowser")); - QCoreApplication::setApplicationVersion(QLatin1String("0.1")); - QString serverName = QCoreApplication::applicationName() - + QString::fromLatin1(QT_VERSION_STR).remove('.') + QLatin1String("webengine"); - QLocalSocket socket; - socket.connectToServer(serverName); - if (socket.waitForConnected(500)) { - QTextStream stream(&socket); - stream << getCommandLineUrlArgument(); - stream.flush(); - socket.waitForBytesWritten(); - return; - } - -#if defined(Q_OS_OSX) - 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) - && m_localServer->serverError() == QAbstractSocket::AddressInUseError) { - QLocalServer::removeServer(serverName); - if (!m_localServer->listen(serverName)) - qWarning("Could not create local socket %s.", qPrintable(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_OS_OSX) - 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; -} - -void BrowserApplication::lastWindowClosed() -{ -#if defined(Q_OS_OSX) - clean(); - BrowserMainWindow *mw = new BrowserMainWindow; - mw->slotHome(); - m_mainWindows.prepend(mw); -#endif -} - -BrowserApplication *BrowserApplication::instance() -{ - return (static_cast<BrowserApplication *>(QCoreApplication::instance())); -} - -void BrowserApplication::quitBrowser() -{ -#if defined(Q_OS_OSX) - 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() -{ - QString directory = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - if (directory.isEmpty()) - directory = QDir::homePath() + QLatin1String("/.") + QCoreApplication::applicationName(); -#if defined(QWEBENGINESETTINGS_PATHS) - QWebEngineSettings::setIconDatabasePath(directory); - QWebEngineSettings::setOfflineStoragePath(directory); -#endif - - setWindowIcon(QIcon(QLatin1String(":demobrowser.svg"))); - - loadSettings(); - - // newMainWindow() needs to be called in main() for this to happen - if (m_mainWindows.count() > 0) { - const QString url = getCommandLineUrlArgument(); - if (!url.isEmpty()) { - mainWindow()->loadPage(url); - } else { - mainWindow()->slotHome(); - } - - } - BrowserApplication::historyManager(); -} - -void BrowserApplication::loadSettings() -{ - QSettings settings; - settings.beginGroup(QLatin1String("websettings")); - - QWebEngineSettings *defaultSettings = QWebEngineSettings::globalSettings(); - QWebEngineProfile *defaultProfile = QWebEngineProfile::defaultProfile(); - - QString standardFontFamily = defaultSettings->fontFamily(QWebEngineSettings::StandardFont); - int standardFontSize = defaultSettings->fontSize(QWebEngineSettings::DefaultFontSize); - QFont standardFont = QFont(standardFontFamily, standardFontSize); - standardFont = qvariant_cast<QFont>(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<QFont>(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::ScrollAnimatorEnabled, settings.value(QLatin1String("enableScrollAnimator"), true).toBool()); - - defaultSettings->setAttribute(QWebEngineSettings::PluginsEnabled, settings.value(QLatin1String("enablePlugins"), true).toBool()); - - defaultSettings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); - - QString css = settings.value(QLatin1String("userStyleSheet")).toString(); - setUserStyleSheet(defaultProfile, css, mainWindow()); - - defaultProfile->setHttpUserAgent(settings.value(QLatin1String("httpUserAgent")).toString()); - defaultProfile->setHttpAcceptLanguage(settings.value(QLatin1String("httpAcceptLanguage")).toString()); - - switch (settings.value(QLatin1String("faviconDownloadMode"), 1).toInt()) { - case 0: - defaultSettings->setAttribute(QWebEngineSettings::AutoLoadIconsForPage, false); - break; - case 1: - defaultSettings->setAttribute(QWebEngineSettings::AutoLoadIconsForPage, true); - defaultSettings->setAttribute(QWebEngineSettings::TouchIconsEnabled, false); - break; - case 2: - defaultSettings->setAttribute(QWebEngineSettings::AutoLoadIconsForPage, true); - defaultSettings->setAttribute(QWebEngineSettings::TouchIconsEnabled, true); - break; - } - - settings.endGroup(); - settings.beginGroup(QLatin1String("cookies")); - - QWebEngineProfile::PersistentCookiesPolicy persistentCookiesPolicy = - QWebEngineProfile::PersistentCookiesPolicy(settings.value(QLatin1String("persistentCookiesPolicy"), - QWebEngineProfile::AllowPersistentCookies).toInt()); - defaultProfile->setPersistentCookiesPolicy(persistentCookiesPolicy); - QString pdataPath = settings.value(QLatin1String("persistentDataPath")).toString(); - defaultProfile->setPersistentStoragePath(pdataPath); - - settings.endGroup(); - - 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()); - QNetworkProxy::setApplicationProxy(proxy); - } - settings.endGroup(); -} - -QList<BrowserMainWindow*> BrowserApplication::mainWindows() -{ - clean(); - QList<BrowserMainWindow*> 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 (m_privateBrowsing) - return; - - 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<QByteArray> 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); -} - -QString BrowserApplication::getCommandLineUrlArgument() const -{ - const QStringList args = QCoreApplication::arguments(); - if (args.count() > 1) { - const QString lastArg = args.last(); - const bool isValidUrl = QUrl::fromUserInput(lastArg).isValid(); - if (isValidUrl) - return lastArg; - } - - return QString(); -} - -#if defined(Q_OS_OSX) -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<QFileOpenEvent *>(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; -} - -QNetworkAccessManager *BrowserApplication::networkAccessManager() -{ - if (!s_networkAccessManager) { - s_networkAccessManager = new QNetworkAccessManager(); - } - return s_networkAccessManager; -} - -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(QTWEBENGINE_ICONDATABASE) - QIcon icon = QWebEngineSettings::iconForUrl(url); - if (!icon.isNull()) - return icon.pixmap(16, 16); -#else - Q_UNUSED(url); -#endif - return defaultIcon(); -} - -QIcon BrowserApplication::defaultIcon() const -{ - if (m_defaultIcon.isNull()) - m_defaultIcon = QIcon(QLatin1String(":defaulticon.png")); - return m_defaultIcon; -} - -void BrowserApplication::setPrivateBrowsing(bool privateBrowsing) -{ - if (m_privateBrowsing == privateBrowsing) - return; - m_privateBrowsing = privateBrowsing; - if (privateBrowsing) { - if (!m_privateProfile) - m_privateProfile = new QWebEngineProfile(this); - Q_FOREACH (BrowserMainWindow* window, mainWindows()) { - window->tabWidget()->setProfile(m_privateProfile); - } - } else { - Q_FOREACH (BrowserMainWindow* window, mainWindows()) { - window->tabWidget()->setProfile(QWebEngineProfile::defaultProfile()); - window->m_lastSearch = QString(); - window->tabWidget()->clear(); - } - } - emit privateBrowsingChanged(privateBrowsing); -} diff --git a/examples/webenginewidgets/demobrowser/browserapplication.h b/examples/webenginewidgets/demobrowser/browserapplication.h deleted file mode 100644 index 5c75d41b3..000000000 --- a/examples/webenginewidgets/demobrowser/browserapplication.h +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BROWSERAPPLICATION_H -#define BROWSERAPPLICATION_H - -#include <QtWidgets/QApplication> - -#include <QtCore/QUrl> -#include <QtCore/QPointer> - -#include <QtGui/QIcon> - -#include <QtNetwork/QAuthenticator> - -QT_BEGIN_NAMESPACE -class QLocalServer; -class QNetworkAccessManager; -class QWebEngineProfile; -QT_END_NAMESPACE - -class BookmarksManager; -class BrowserMainWindow; -class CookieJar; -class DownloadManager; -class HistoryManager; -class BrowserApplication : public QApplication -{ - Q_OBJECT - -public: - BrowserApplication(int &argc, char **argv); - ~BrowserApplication(); - static BrowserApplication *instance(); - void loadSettings(); - - bool isTheOnlyBrowser() const; - BrowserMainWindow *mainWindow(); - QList<BrowserMainWindow*> mainWindows(); - QIcon icon(const QUrl &url) const; - QIcon defaultIcon() const; - - void saveSession(); - bool canRestoreSession() const; - bool privateBrowsing() const { return m_privateBrowsing; } - - static HistoryManager *historyManager(); - static CookieJar *cookieJar(); - static DownloadManager *downloadManager(); - static QNetworkAccessManager *networkAccessManager(); - static BookmarksManager *bookmarksManager(); - -#if defined(Q_OS_OSX) - bool event(QEvent *event); -#endif - -public slots: - BrowserMainWindow *newMainWindow(); - void restoreLastSession(); - void lastWindowClosed(); - void quitBrowser(); - void setPrivateBrowsing(bool); - -signals: - void privateBrowsingChanged(bool); - -private slots: - void postLaunch(); - void openUrl(const QUrl &url); - void newLocalSocketConnection(); - -private: - void clean(); - void installTranslator(const QString &name); - QString getCommandLineUrlArgument() const; - - static HistoryManager *s_historyManager; - static DownloadManager *s_downloadManager; - static QNetworkAccessManager *s_networkAccessManager; - static BookmarksManager *s_bookmarksManager; - - QList<QPointer<BrowserMainWindow> > m_mainWindows; - QLocalServer *m_localServer; - QByteArray m_lastSession; - QWebEngineProfile *m_privateProfile; - bool m_privateBrowsing; - mutable QIcon m_defaultIcon; - - QAuthenticator m_lastAuthenticator; - QAuthenticator m_lastProxyAuthenticator; -}; - -#endif // BROWSERAPPLICATION_H diff --git a/examples/webenginewidgets/demobrowser/browsermainwindow.cpp b/examples/webenginewidgets/demobrowser/browsermainwindow.cpp deleted file mode 100644 index 14d49f7f3..000000000 --- a/examples/webenginewidgets/demobrowser/browsermainwindow.cpp +++ /dev/null @@ -1,1032 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "browsermainwindow.h" - -#include "autosaver.h" -#include "bookmarks.h" -#include "browserapplication.h" -#include "chasewidget.h" -#include "downloadmanager.h" -#include "history.h" -#include "printtopdfdialog.h" -#include "settings.h" -#include "tabwidget.h" -#include "toolbarsearch.h" -#include "ui_passworddialog.h" -#include "webview.h" - -#include <QtCore/QSettings> - -#include <QtWidgets/QDesktopWidget> -#include <QtWidgets/QFileDialog> -#include <QtWidgets/QPlainTextEdit> -#include <QtPrintSupport/QPrintDialog> -#include <QtPrintSupport/QPrintPreviewDialog> -#include <QtPrintSupport/QPrinter> -#include <QtWidgets/QMenuBar> -#include <QtWidgets/QMessageBox> -#include <QtWidgets/QStatusBar> -#include <QtWidgets/QToolBar> -#include <QtWidgets/QInputDialog> - -#include <QWebEngineHistory> -#include <QWebEngineProfile> -#include <QWebEngineSettings> - -#include <QtCore/QDebug> - -template<typename Arg, typename R, typename C> -struct InvokeWrapper { - R *receiver; - void (C::*memberFun)(Arg); - void operator()(Arg result) { - (receiver->*memberFun)(result); - } -}; - -template<typename Arg, typename R, typename C> -InvokeWrapper<Arg, R, C> invoke(R *receiver, void (C::*memberFun)(Arg)) -{ - InvokeWrapper<Arg, R, C> wrapper = {receiver, memberFun}; - return wrapper; -} - -const char *BrowserMainWindow::defaultHome = "http://qt.io/"; - -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) - , m_currentPrinter(nullptr) -{ - setToolButtonStyle(Qt::ToolButtonFollowStyle); - setAttribute(Qt::WA_DeleteOnClose, true); - statusBar()->setSizeGripEnabled(true); - setupMenu(); - setupToolBar(); - - QWidget *centralWidget = new QWidget(this); - BookmarksModel *bookmarksModel = BrowserApplication::bookmarksManager()->bookmarksModel(); - m_bookmarksToolbar = new BookmarksToolBar(bookmarksModel, 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_OS_OSX) - 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))); -#if defined(QWEBENGINEPAGE_PRINTREQUESTED) - connect(m_tabWidget, SIGNAL(printRequested(QWebEngineFrame*)), - this, SLOT(printRequested(QWebEngineFrame*))); -#endif - 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))); - - connect(m_tabWidget, SIGNAL(lastTabClosed()), - m_tabWidget, SLOT(newTab())); - - 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::runScriptOnOpenViews(const QString &source) -{ - for (int i =0; i < tabWidget()->count(); ++i) - tabWidget()->webView(i)->page()->runJavaScript(source); -} - -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(QWEBENGINE_SAVE_AS_FILE) - 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())); -#endif - fileMenu->addAction(tr("&Print..."), this, SLOT(slotFilePrint()), QKeySequence::Print); - fileMenu->addAction(tr("&Print to PDF..."), this, SLOT(slotFilePrintToPDF())); - fileMenu->addSeparator(); - - QAction *action = fileMenu->addAction(tr("Private &Browsing..."), this, SLOT(slotPrivateBrowsing())); - action->setCheckable(true); - action->setChecked(BrowserApplication::instance()->privateBrowsing()); - connect(BrowserApplication::instance(), SIGNAL(privateBrowsingChanged(bool)), action, SLOT(setChecked(bool))); - fileMenu->addSeparator(); - -#if defined(Q_OS_OSX) - 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())); - - 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<QKeySequence> 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)); - - viewMenu->addSeparator(); - QAction *m_pageSource = viewMenu->addAction(tr("Page S&ource")); - m_pageSource->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_U)); - m_tabWidget->addWebAction(m_pageSource, QWebEnginePage::ViewSource); - - 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<QAction*> historyActions; - - m_historyBack = new QAction(tr("Back"), this); - m_tabWidget->addWebAction(m_historyBack, QWebEnginePage::Back); - QList<QKeySequence> backShortcuts = QKeySequence::keyBindings(QKeySequence::Back); - for (auto it = backShortcuts.begin(); it != backShortcuts.end();) { - // Chromium already handles navigate on backspace when appropriate. - if ((*it)[0] == Qt::Key_Backspace) - it = backShortcuts.erase(it); - else - ++it; - } - // For some reason Qt doesn't bind the dedicated Back key to Back. - backShortcuts.append(QKeySequence(Qt::Key_Back)); - m_historyBack->setShortcuts(backShortcuts); - m_historyBack->setIconVisibleInMenu(false); - historyActions.append(m_historyBack); - - m_historyForward = new QAction(tr("Forward"), this); - m_tabWidget->addWebAction(m_historyForward, QWebEnginePage::Forward); - QList<QKeySequence> fwdShortcuts = QKeySequence::keyBindings(QKeySequence::Forward); - for (auto it = fwdShortcuts.begin(); it != fwdShortcuts.end();) { - if (((*it)[0] & Qt::Key_unknown) == Qt::Key_Backspace) - it = fwdShortcuts.erase(it); - else - ++it; - } - fwdShortcuts.append(QKeySequence(Qt::Key_Forward)); - m_historyForward->setShortcuts(fwdShortcuts); - 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<QAction*> 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() -{ - 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() -{ - // not implemented yet. -} - -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_OS_OSX) - 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" - "<p>This demo demonstrates the facilities " - "of Qt WebEngine in action, providing an example " - "browser for you to experiment with.<p>" - "<p>Qt WebEngine is based on the Chromium open source project " - "developed at <a href=\"http://www.chromium.org/\">http://www.chromium.org/</a>." - ).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() -{ - if (!currentTab()) - return; - QPrintPreviewDialog *dialog = new QPrintPreviewDialog(this); - connect(dialog, SIGNAL(paintRequested(QPrinter*)), - currentTab(), SLOT(print(QPrinter*))); - dialog->exec(); -} - -void BrowserMainWindow::slotFilePrint() -{ - if (!currentTab()) - return; - printRequested(currentTab()->page()); -} - -void BrowserMainWindow::slotHandlePdfPrinted(const QByteArray& result) -{ - if (!result.size()) - return; - - QFile file(m_printerOutputFileName); - - m_printerOutputFileName.clear(); - if (!file.open(QFile::WriteOnly)) - return; - - file.write(result.data(), result.size()); - file.close(); -} - -void BrowserMainWindow::slotFilePrintToPDF() -{ - if (!currentTab() || !m_printerOutputFileName.isEmpty()) - return; - - QFileInfo info(QStringLiteral("printout.pdf")); - PrintToPdfDialog *dialog = new PrintToPdfDialog(info.absoluteFilePath(), this); - dialog->setWindowTitle(tr("Print to PDF")); - if (dialog->exec() != QDialog::Accepted || dialog->filePath().isEmpty()) - return; - - m_printerOutputFileName = dialog->filePath(); - currentTab()->page()->printToPdf(invoke(this, &BrowserMainWindow::slotHandlePdfPrinted), dialog->pageLayout()); -} - -void BrowserMainWindow::slotHandlePagePrinted(bool result) -{ - Q_UNUSED(result); - - delete m_currentPrinter; - m_currentPrinter = nullptr; -} - - -void BrowserMainWindow::printRequested(QWebEnginePage *page) -{ - if (m_currentPrinter) - return; - m_currentPrinter = new QPrinter(); - QScopedPointer<QPrintDialog> dialog(new QPrintDialog(m_currentPrinter, this)); - dialog->setWindowTitle(tr("Print Document")); - if (dialog->exec() != QDialog::Accepted) { - slotHandlePagePrinted(false); - return; - } - page->print(m_currentPrinter, invoke(this, &BrowserMainWindow::slotHandlePagePrinted)); -} - -void BrowserMainWindow::slotPrivateBrowsing() -{ - if (!BrowserApplication::instance()->privateBrowsing()) { - QString title = tr("Are you sure you want to turn on private browsing?"); - QString text = tr("<b>%1</b><br><br>" - "This action will reload all open tabs.<br>" - "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) - BrowserApplication::instance()->setPrivateBrowsing(true); - } else { - // TODO: Also ask here - BrowserApplication::instance()->setPrivateBrowsing(false); - } -} - -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::slotViewFullScreen(bool makeFullScreen) -{ - if (makeFullScreen) { - showFullScreen(); - } else { - if (isMinimized()) - showMinimized(); - else if (isMaximized()) - showMaximized(); - else showNormal(); - } -} - -void BrowserMainWindow::slotHome() -{ - QSettings settings; - settings.beginGroup(QLatin1String("MainWindow")); - QString home = settings.value(QLatin1String("home"), QLatin1String(defaultHome)).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(); - } - } -#else - Q_UNUSED(enable); -#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(); - m_windowMenu->addAction(tr("Downloads"), this, SLOT(slotDownloadManager()), QKeySequence(tr("Alt+Ctrl+L", "Download Manager"))); - m_windowMenu->addSeparator(); - - QList<BrowserMainWindow*> 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<QAction*>(sender())) { - QVariant v = action->data(); - if (v.canConvert<int>()) { - int offset = qvariant_cast<int>(v); - QList<BrowserMainWindow*> 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/demobrowser/browsermainwindow.h b/examples/webenginewidgets/demobrowser/browsermainwindow.h deleted file mode 100644 index 5bbbb2924..000000000 --- a/examples/webenginewidgets/demobrowser/browsermainwindow.h +++ /dev/null @@ -1,189 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BROWSERMAINWINDOW_H -#define BROWSERMAINWINDOW_H - -#include <QtWidgets/QMainWindow> -#include <QtGui/QIcon> -#include <QtCore/QUrl> - -QT_BEGIN_NAMESPACE -class QPrinter; -class QWebEnginePage; -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; - - static const char *defaultHome; - -public: - TabWidget *tabWidget() const; - WebView *currentTab() const; - QByteArray saveState(bool withTabs = true) const; - bool restoreState(const QByteArray &state); - Q_INVOKABLE void runScriptOnOpenViews(const QString &); - -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 slotFilePrintToPDF(); - void slotPrivateBrowsing(); - void slotFileSaveAs(); - void slotEditFind(); - void slotEditFindNext(); - void slotEditFindPrevious(); - void slotShowBookmarksDialog(); - void slotAddBookmark(); - void slotViewZoomIn(); - void slotViewZoomOut(); - void slotViewResetZoom(); - void slotViewToolbar(); - void slotViewBookmarksBar(); - void slotViewStatusbar(); - 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 slotHandlePdfPrinted(const QByteArray&); - - void slotHandlePagePrinted(bool result); - void printRequested(QWebEnginePage *page); - 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; - - QPrinter *m_currentPrinter; - - QIcon m_reloadIcon; - QIcon m_stopIcon; - - QString m_lastSearch; - QString m_printerOutputFileName; - friend class BrowserApplication; -}; - -#endif // BROWSERMAINWINDOW_H diff --git a/examples/webenginewidgets/demobrowser/chasewidget.cpp b/examples/webenginewidgets/demobrowser/chasewidget.cpp deleted file mode 100644 index 0f066bc73..000000000 --- a/examples/webenginewidgets/demobrowser/chasewidget.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "chasewidget.h" - -#include <QtCore/QPoint> - -#include <QtWidgets/QApplication> -#include <QtGui/QHideEvent> -#include <QtGui/QPainter> -#include <QtGui/QPaintEvent> -#include <QtGui/QShowEvent> - -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/demobrowser/chasewidget.h b/examples/webenginewidgets/demobrowser/chasewidget.h deleted file mode 100644 index 63a8ff310..000000000 --- a/examples/webenginewidgets/demobrowser/chasewidget.h +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CHASEWIDGET_H -#define CHASEWIDGET_H - -#include <QtWidgets/QWidget> - -#include <QtCore/QSize> -#include <QtGui/QColor> -#include <QtGui/QPixmap> - -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/demobrowser/cookiejar.cpp b/examples/webenginewidgets/demobrowser/cookiejar.cpp deleted file mode 100644 index 479601ee3..000000000 --- a/examples/webenginewidgets/demobrowser/cookiejar.cpp +++ /dev/null @@ -1,746 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "cookiejar.h" - -#include "autosaver.h" - -#include <QtCore/QDateTime> -#include <QtCore/QDir> -#include <QtCore/QFile> -#include <QtCore/QMetaEnum> -#include <QtCore/QSettings> -#include <QtCore/QUrl> - -#include <QtWidgets/QCompleter> -#include <QtGui/QDesktopServices> -#include <QtGui/QFont> -#include <QtGui/QFontMetrics> -#include <QtWidgets/QHeaderView> -#include <QtGui/QKeyEvent> -#include <QtCore/QSortFilterProxyModel> -#include <QtNetwork/QNetworkCookie> - -#include <QWebEngineSettings> - -#include <QtCore/QDebug> - -static const unsigned int JAR_VERSION = 23; - -QT_BEGIN_NAMESPACE -QDataStream &operator<<(QDataStream &stream, const QList<QNetworkCookie> &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<QNetworkCookie> &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<QNetworkCookie> 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<QNetworkCookie>()); - m_saveTimer->changeOccurred(); - emit cookiesChanged(); -} - -void CookieJar::load() -{ - if (m_loaded) - return; - // load cookies and exceptions - qRegisterMetaTypeStreamOperators<QList<QNetworkCookie> >("QList<QNetworkCookie>"); - QSettings cookieSettings(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1String("/cookies.ini"), QSettings::IniFormat); - setAllCookies(qvariant_cast<QList<QNetworkCookie> >(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<AcceptPolicy>(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<KeepPolicy>(keepPolicyEnum.keyToValue(value)); - - if (m_keepCookies == KeepUntilExit) - setAllCookies(QList<QNetworkCookie>()); - - 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<QNetworkCookie> 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<QList<QNetworkCookie> >(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<QNetworkCookie> 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<QNetworkCookie> CookieJar::cookiesForUrl(const QUrl &url) const -{ - CookieJar *that = const_cast<CookieJar*>(this); - if (!m_loaded) - that->load(); - - QWebEngineSettings *globalSettings = QWebEngineSettings::globalSettings(); - if (globalSettings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled)) { - QList<QNetworkCookie> noCookies; - return noCookies; - } - - return QNetworkCookieJar::cookiesForUrl(url); -} - -bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &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<QNetworkCookie> 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<QNetworkCookie> 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<CookieJar*>(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<CookieJar*>(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<CookieJar*>(this))->load(); - return m_exceptions_block; -} - -QStringList CookieJar::allowedCookies() const -{ - if (!m_loaded) - (const_cast<CookieJar*>(this))->load(); - return m_exceptions_allow; -} - -QStringList CookieJar::allowForSessionCookies() const -{ - if (!m_loaded) - (const_cast<CookieJar*>(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<QNetworkCookie> 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<QNetworkCookie> 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/demobrowser/cookiejar.h b/examples/webenginewidgets/demobrowser/cookiejar.h deleted file mode 100644 index 3f8707955..000000000 --- a/examples/webenginewidgets/demobrowser/cookiejar.h +++ /dev/null @@ -1,212 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef COOKIEJAR_H -#define COOKIEJAR_H - -#include <QtNetwork/QNetworkCookieJar> - -#include <QtCore/QAbstractItemModel> -#include <QtCore/QStringList> - -#include <QtWidgets/QDialog> -#include <QtWidgets/QTableView> - -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<QNetworkCookie> cookiesForUrl(const QUrl &url) const; - bool setCookiesFromUrl(const QList<QNetworkCookie> &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/demobrowser/cookies.ui b/examples/webenginewidgets/demobrowser/cookies.ui deleted file mode 100644 index c4bccc548..000000000 --- a/examples/webenginewidgets/demobrowser/cookies.ui +++ /dev/null @@ -1,106 +0,0 @@ -<ui version="4.0" > - <class>CookiesDialog</class> - <widget class="QDialog" name="CookiesDialog" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>550</width> - <height>370</height> - </rect> - </property> - <property name="windowTitle" > - <string>Cookies</string> - </property> - <layout class="QGridLayout" > - <item row="0" column="0" > - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>252</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="1" > - <widget class="SearchLineEdit" name="search" /> - </item> - <item row="1" column="0" colspan="2" > - <widget class="EditTableView" name="cookiesTable" /> - </item> - <item row="2" column="0" colspan="2" > - <layout class="QHBoxLayout" > - <item> - <widget class="QPushButton" name="removeButton" > - <property name="text" > - <string>&Remove</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="removeAllButton" > - <property name="text" > - <string>Remove &All Cookies</string> - </property> - </widget> - </item> - <item> - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox" > - <property name="standardButtons" > - <set>QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>SearchLineEdit</class> - <extends>QLineEdit</extends> - <header>searchlineedit.h</header> - </customwidget> - <customwidget> - <class>EditTableView</class> - <extends>QTableView</extends> - <header>edittableview.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>CookiesDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel" > - <x>472</x> - <y>329</y> - </hint> - <hint type="destinationlabel" > - <x>461</x> - <y>356</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/examples/webenginewidgets/demobrowser/cookiesexceptions.ui b/examples/webenginewidgets/demobrowser/cookiesexceptions.ui deleted file mode 100644 index 3d9ef6241..000000000 --- a/examples/webenginewidgets/demobrowser/cookiesexceptions.ui +++ /dev/null @@ -1,184 +0,0 @@ -<ui version="4.0" > - <class>CookiesExceptionsDialog</class> - <widget class="QDialog" name="CookiesExceptionsDialog" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>466</width> - <height>446</height> - </rect> - </property> - <property name="windowTitle" > - <string>Cookie Exceptions</string> - </property> - <layout class="QVBoxLayout" > - <item> - <widget class="QGroupBox" name="newExceptionGroupBox" > - <property name="title" > - <string>New Exception</string> - </property> - <layout class="QGridLayout" > - <item row="0" column="0" > - <layout class="QHBoxLayout" > - <item> - <widget class="QLabel" name="label" > - <property name="text" > - <string>Domain:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="domainLineEdit" /> - </item> - </layout> - </item> - <item row="1" column="0" > - <layout class="QHBoxLayout" > - <item> - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>81</width> - <height>25</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="blockButton" > - <property name="enabled" > - <bool>false</bool> - </property> - <property name="text" > - <string>Block</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="allowForSessionButton" > - <property name="enabled" > - <bool>false</bool> - </property> - <property name="text" > - <string>Allow For Session</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="allowButton" > - <property name="enabled" > - <bool>false</bool> - </property> - <property name="text" > - <string>Allow</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="ExceptionsGroupBox" > - <property name="title" > - <string>Exceptions</string> - </property> - <layout class="QGridLayout" > - <item row="0" column="0" colspan="3" > - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>252</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="3" > - <widget class="SearchLineEdit" name="search" /> - </item> - <item row="1" column="0" colspan="4" > - <widget class="EditTableView" name="exceptionTable" /> - </item> - <item row="2" column="0" > - <widget class="QPushButton" name="removeButton" > - <property name="text" > - <string>&Remove</string> - </property> - </widget> - </item> - <item row="2" column="1" > - <widget class="QPushButton" name="removeAllButton" > - <property name="text" > - <string>Remove &All</string> - </property> - </widget> - </item> - <item row="2" column="2" colspan="2" > - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox" > - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons" > - <set>QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>SearchLineEdit</class> - <extends>QLineEdit</extends> - <header>searchlineedit.h</header> - </customwidget> - <customwidget> - <class>EditTableView</class> - <extends>QTableView</extends> - <header>edittableview.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>CookiesExceptionsDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel" > - <x>381</x> - <y>428</y> - </hint> - <hint type="destinationlabel" > - <x>336</x> - <y>443</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/examples/webenginewidgets/demobrowser/data/addtab.png b/examples/webenginewidgets/demobrowser/data/addtab.png Binary files differdeleted file mode 100644 index 20928fb40..000000000 --- a/examples/webenginewidgets/demobrowser/data/addtab.png +++ /dev/null diff --git a/examples/webenginewidgets/demobrowser/data/closetab.png b/examples/webenginewidgets/demobrowser/data/closetab.png Binary files differdeleted file mode 100644 index ab9d669ee..000000000 --- a/examples/webenginewidgets/demobrowser/data/closetab.png +++ /dev/null diff --git a/examples/webenginewidgets/demobrowser/data/data.qrc b/examples/webenginewidgets/demobrowser/data/data.qrc deleted file mode 100644 index 5cb8a97c0..000000000 --- a/examples/webenginewidgets/demobrowser/data/data.qrc +++ /dev/null @@ -1,11 +0,0 @@ -<!DOCTYPE RCC><RCC version="1.0"> -<qresource> - <file>addtab.png</file> - <file>closetab.png</file> - <file>history.png</file> - <file>demobrowser.svg</file> - <file>defaultbookmarks.xbel</file> - <file>loading.gif</file> - <file>defaulticon.png</file> -</qresource> -</RCC> diff --git a/examples/webenginewidgets/demobrowser/data/defaultbookmarks.xbel b/examples/webenginewidgets/demobrowser/data/defaultbookmarks.xbel deleted file mode 100644 index fef7f5514..000000000 --- a/examples/webenginewidgets/demobrowser/data/defaultbookmarks.xbel +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE xbel> -<xbel version="1.0"> - <folder folded="yes"> - <title>Bookmarks Bar</title> - <bookmark href="http://qt.io/"> - <title>Qt Home Page</title> - </bookmark> - <bookmark href="http://doc.qt.io/"> - <title>Qt Documentation</title> - </bookmark> - <bookmark href="http://planet.qt.io/"> - <title>Qt Blog</title> - </bookmark> - <bookmark href="http://www.qtcentre.org/"> - <title>Qt Centre</title> - </bookmark> - <bookmark href="http://qt-apps.org/"> - <title>Qt-Apps.org</title> - </bookmark> - <bookmark href="http://wiki.qt.io/OnlineCommunities"> - <title>Online Communities</title> - </bookmark> - <bookmark href="http://www.chromium.org/"> - <title>The Chromium Projects</title> - </bookmark> - <bookmark href="http://xkcd.com/"> - <title>xkcd</title> - </bookmark> - <bookmark href="http://twitter.com/qtproject"> - <title>Twitter</title> - </bookmark> - </folder> - <folder folded="yes"> - <title>Bookmarks Menu</title> - <bookmark href="http://reddit.com/"> - <title>reddit.com: what's new online!</title> - </bookmark> - </folder> -</xbel> diff --git a/examples/webenginewidgets/demobrowser/data/defaulticon.png b/examples/webenginewidgets/demobrowser/data/defaulticon.png Binary files differdeleted file mode 100644 index 01a0920c9..000000000 --- a/examples/webenginewidgets/demobrowser/data/defaulticon.png +++ /dev/null diff --git a/examples/webenginewidgets/demobrowser/data/demobrowser.svg b/examples/webenginewidgets/demobrowser/data/demobrowser.svg deleted file mode 100644 index 9f39deb66..000000000 --- a/examples/webenginewidgets/demobrowser/data/demobrowser.svg +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> -<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" - width="94px" height="94px" viewBox="0 0 94 94" enable-background="new 0 0 94 94" xml:space="preserve"> -<g> - <circle fill="none" cx="47" cy="47" r="47"/> - <g> - <path fill="#46A2DA" d="M47,92.979c-11.779,0-23.559-4.484-32.526-13.451C-3.461,61.591-3.461,32.409,14.472,14.474 - C32.41-3.463,61.592-3.461,79.526,14.473c17.935,17.936,17.935,47.119,0.002,65.054l-0.002,0.001 - C70.559,88.495,58.779,92.979,47,92.979z"/> - </g> - <path fill="#80C342" d="M93,47C93,21.595,72.405,1,47,1C34.297,1,22.797,6.149,14.473,14.473l65.054,65.054 - C87.851,71.203,93,59.703,93,47z"/> - <g> - <path fill="#46A2DA" d="M47,65c-4.808,0-9.328-1.873-12.728-5.272c-7.018-7.019-7.018-18.438,0-25.456 - C37.672,30.873,42.192,29,47,29s9.328,1.873,12.728,5.272c7.018,7.019,7.018,18.438,0,25.456C56.328,63.127,51.808,65,47,65z"/> - <path fill="#FFFFFF" d="M62.248,59.919c6.671-7.858,6.312-19.644-1.105-27.061C57.237,28.953,52.118,27,47,27 - c-5.118,0-10.237,1.953-14.142,5.858c-7.81,7.81-7.81,20.474,0,28.284C36.763,65.047,41.882,67,47,67 - c4.379,0,8.752-1.441,12.372-4.3L77.88,81.209c0.989-0.895,1.935-1.837,2.843-2.814L62.248,59.919z M35.686,58.314 - c-6.238-6.238-6.238-16.389,0-22.627C38.708,32.664,42.726,31,47,31c4.274,0,8.292,1.664,11.314,4.686 - c6.238,6.238,6.238,16.389,0,22.627C55.292,61.336,51.274,63,47,63C42.726,63,38.708,61.336,35.686,58.314z"/> - </g> -</g> -</svg> diff --git a/examples/webenginewidgets/demobrowser/data/history.png b/examples/webenginewidgets/demobrowser/data/history.png Binary files differdeleted file mode 100644 index 552a1cbd8..000000000 --- a/examples/webenginewidgets/demobrowser/data/history.png +++ /dev/null diff --git a/examples/webenginewidgets/demobrowser/data/loading.gif b/examples/webenginewidgets/demobrowser/data/loading.gif Binary files differdeleted file mode 100644 index c1545eb0e..000000000 --- a/examples/webenginewidgets/demobrowser/data/loading.gif +++ /dev/null diff --git a/examples/webenginewidgets/demobrowser/demobrowser.icns b/examples/webenginewidgets/demobrowser/demobrowser.icns Binary files differdeleted file mode 100644 index f24ac6ee7..000000000 --- a/examples/webenginewidgets/demobrowser/demobrowser.icns +++ /dev/null diff --git a/examples/webenginewidgets/demobrowser/demobrowser.ico b/examples/webenginewidgets/demobrowser/demobrowser.ico Binary files differdeleted file mode 100644 index d197d0358..000000000 --- a/examples/webenginewidgets/demobrowser/demobrowser.ico +++ /dev/null diff --git a/examples/webenginewidgets/demobrowser/demobrowser.pro b/examples/webenginewidgets/demobrowser/demobrowser.pro deleted file mode 100644 index aef7b9eac..000000000 --- a/examples/webenginewidgets/demobrowser/demobrowser.pro +++ /dev/null @@ -1,95 +0,0 @@ -TEMPLATE = app -TARGET = demobrowser -QT += webenginewidgets network widgets printsupport -CONFIG += c++11 - -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 \ - printtopdfdialog.ui \ - proxy.ui \ - savepagedialog.ui \ - settings.ui - -HEADERS += \ - autosaver.h \ - bookmarks.h \ - browserapplication.h \ - browsermainwindow.h \ - chasewidget.h \ - downloadmanager.h \ - edittableview.h \ - edittreeview.h \ - featurepermissionbar.h\ - fullscreennotification.h \ - history.h \ - modelmenu.h \ - printtopdfdialog.h \ - savepagedialog.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 \ - featurepermissionbar.cpp\ - fullscreennotification.cpp \ - history.cpp \ - modelmenu.cpp \ - printtopdfdialog.cpp \ - savepagedialog.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 - -build_all:!build_pass { - CONFIG -= build_all - CONFIG += release -} - -win32 { - RC_FILE = demobrowser.rc -} - -mac { - ICON = demobrowser.icns - QMAKE_INFO_PLIST = Info_mac.plist - TARGET = Demobrowser -} - -EXAMPLE_FILES = \ - Info_mac.plist demobrowser.icns demobrowser.ico demobrowser.rc \ - cookiejar.h cookiejar.cpp # FIXME: these are currently unused. - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/demobrowser -INSTALLS += target diff --git a/examples/webenginewidgets/demobrowser/demobrowser.rc b/examples/webenginewidgets/demobrowser/demobrowser.rc deleted file mode 100644 index 70cd8bb1c..000000000 --- a/examples/webenginewidgets/demobrowser/demobrowser.rc +++ /dev/null @@ -1 +0,0 @@ -IDI_ICON1 ICON DISCARDABLE "demobrowser.ico" diff --git a/examples/webenginewidgets/demobrowser/doc/images/browser-demo.png b/examples/webenginewidgets/demobrowser/doc/images/browser-demo.png Binary files differdeleted file mode 100644 index e8695dbca..000000000 --- a/examples/webenginewidgets/demobrowser/doc/images/browser-demo.png +++ /dev/null diff --git a/examples/webenginewidgets/demobrowser/doc/src/demobrowser.qdoc b/examples/webenginewidgets/demobrowser/doc/src/demobrowser.qdoc deleted file mode 100644 index dfd7a7a3d..000000000 --- a/examples/webenginewidgets/demobrowser/doc/src/demobrowser.qdoc +++ /dev/null @@ -1,40 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU 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: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example webenginewidgets/demobrowser - \title WebEngine Demo Browser Example - \ingroup webengine-widgetexamples - \brief A demo browser based on Qt WebEngine Widgets - - \e {Demo Browser} demonstrates how to use the \l{Qt WebEngine Widgets C++ Classes} - {Qt WebEngine C++ classes} to develop a small Web browser application with support for tabs. - - \image browser-demo.png - - \include examples-run.qdocinc -*/ diff --git a/examples/webenginewidgets/demobrowser/downloaditem.ui b/examples/webenginewidgets/demobrowser/downloaditem.ui deleted file mode 100644 index e506f28b6..000000000 --- a/examples/webenginewidgets/demobrowser/downloaditem.ui +++ /dev/null @@ -1,133 +0,0 @@ -<ui version="4.0" > - <class>DownloadItem</class> - <widget class="QWidget" name="DownloadItem" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>423</width> - <height>110</height> - </rect> - </property> - <property name="windowTitle" > - <string>Form</string> - </property> - <layout class="QHBoxLayout" name="horizontalLayout" > - <property name="leftMargin"> - <number>5</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>5</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="QLabel" name="fileIcon" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Minimum" hsizetype="Minimum" > - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text" > - <string>Ico</string> - </property> - </widget> - </item> - <item> - <layout class="QVBoxLayout" name="verticalLayout_2" > - <item> - <widget class="SqueezeLabel" native="1" name="fileNameLabel" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Preferred" hsizetype="Expanding" > - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text" stdset="0" > - <string>Filename</string> - </property> - </widget> - </item> - <item> - <widget class="QProgressBar" name="progressBar" > - <property name="value" > - <number>0</number> - </property> - </widget> - </item> - <item> - <widget class="SqueezeLabel" native="1" name="downloadInfoLabel" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Preferred" hsizetype="Minimum" > - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text" stdset="0" > - <string/> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QVBoxLayout" name="verticalLayout" > - <item> - <spacer name="verticalSpacer" > - <property name="orientation" > - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>17</width> - <height>1</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="stopButton" > - <property name="text" > - <string>Stop</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="openButton" > - <property name="text" > - <string>Open</string> - </property> - </widget> - </item> - <item> - <spacer name="verticalSpacer_2" > - <property name="orientation" > - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>17</width> - <height>5</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>SqueezeLabel</class> - <extends>QWidget</extends> - <header>squeezelabel.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui> diff --git a/examples/webenginewidgets/demobrowser/downloadmanager.cpp b/examples/webenginewidgets/demobrowser/downloadmanager.cpp deleted file mode 100644 index 33893c912..000000000 --- a/examples/webenginewidgets/demobrowser/downloadmanager.cpp +++ /dev/null @@ -1,505 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "downloadmanager.h" - -#include "autosaver.h" -#include "browserapplication.h" - -#include <math.h> - -#include <QtCore/QMetaEnum> -#include <QtCore/QSettings> - -#include <QtGui/QDesktopServices> -#include <QtWidgets/QFileDialog> -#include <QtWidgets/QHeaderView> -#include <QtWidgets/QFileIconProvider> - -#include <QtCore/QDebug> - -#include <QWebEngineSettings> -#include <QWebEngineDownloadItem> - -/*! - DownloadWidget is a widget that is displayed in the download manager list. - It moves the data from the QWebEngineDownloadItem into the QFile as well - as update the information/progressbar and report errors. - */ - -DownloadWidget::DownloadWidget(QWebEngineDownloadItem *download, QWidget *parent) - : QWidget(parent) - , m_bytesReceived(0) - , m_download(download) -{ - setupUi(this); - QPalette p = downloadInfoLabel->palette(); - p.setColor(QPalette::Text, Qt::darkGray); - downloadInfoLabel->setPalette(p); - progressBar->setMaximum(0); - connect(stopButton, SIGNAL(clicked()), this, SLOT(stop())); - connect(openButton, SIGNAL(clicked()), this, SLOT(open())); - - if (download) { - m_file.setFile(download->path()); - m_url = download->url(); - } - - init(); -} - -void DownloadWidget::init() -{ - if (m_download) { - connect(m_download.data(), SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(downloadProgress(qint64,qint64))); - connect(m_download.data(), SIGNAL(finished()), - this, SLOT(finished())); - } - - // reset info - downloadInfoLabel->clear(); - progressBar->setValue(0); - getFileName(); - - // start timer for the download estimation - m_downloadTime.start(); -} - -bool DownloadWidget::getFileName(bool promptForFileName) -{ - QSettings settings; - settings.beginGroup(QLatin1String("downloadmanager")); - QString defaultLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); - if (m_file.absoluteDir().exists()) - defaultLocation = m_file.absolutePath(); - QString downloadDirectory = settings.value(QLatin1String("downloadDirectory"), defaultLocation).toString(); - if (!downloadDirectory.isEmpty()) - downloadDirectory += QLatin1Char('/'); - - QString defaultFileName = QFileInfo(downloadDirectory, m_file.fileName()).absoluteFilePath(); - QString fileName = defaultFileName; - if (promptForFileName) { - fileName = QFileDialog::getSaveFileName(this, tr("Save File"), defaultFileName); - if (fileName.isEmpty()) { - if (m_download) - m_download->cancel(); - fileNameLabel->setText(tr("Download canceled: %1").arg(QFileInfo(defaultFileName).fileName())); - return false; - } - } - m_file.setFile(fileName); - - if (m_download && m_download->state() == QWebEngineDownloadItem::DownloadRequested) - m_download->setPath(m_file.absoluteFilePath()); - - fileNameLabel->setText(m_file.fileName()); - return true; -} - -void DownloadWidget::stop() -{ - setUpdatesEnabled(false); - stopButton->setEnabled(false); - stopButton->hide(); - setUpdatesEnabled(true); - if (m_download) - m_download->cancel(); - - emit statusChanged(); -} - -void DownloadWidget::open() -{ - QUrl url = QUrl::fromLocalFile(m_file.absoluteFilePath()); - QDesktopServices::openUrl(url); -} - -void DownloadWidget::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 DownloadWidget::updateInfoLabel() -{ - qint64 bytesTotal = progressBar->maximum(); - - // 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 (!downloadedSuccessfully()) { - 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 = tr("%1 of %2 - Stopped") - .arg(dataString(m_bytesReceived)) - .arg(dataString(bytesTotal)); - } else - info = dataString(m_bytesReceived); - } - downloadInfoLabel->setText(info); -} - -QString DownloadWidget::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 DownloadWidget::downloading() const -{ - return (progressBar->isVisible()); -} - -bool DownloadWidget::downloadedSuccessfully() const -{ - bool completed = m_download - && m_download->isFinished() - && m_download->state() == QWebEngineDownloadItem::DownloadCompleted; - return completed || !stopButton->isVisible(); -} - -void DownloadWidget::finished() -{ - if (m_download) { - QWebEngineDownloadItem::DownloadState state = m_download->state(); - QString message; - bool interrupted = false; - - switch (state) { - case QWebEngineDownloadItem::DownloadRequested: // Fall-through. - case QWebEngineDownloadItem::DownloadInProgress: - Q_UNREACHABLE(); - break; - case QWebEngineDownloadItem::DownloadCompleted: - break; - case QWebEngineDownloadItem::DownloadCancelled: - message = QStringLiteral("Download cancelled"); - interrupted = true; - break; - case QWebEngineDownloadItem::DownloadInterrupted: - message = QStringLiteral("Download interrupted"); - interrupted = true; - break; - } - - if (interrupted) { - downloadInfoLabel->setText(message); - return; - } - } - - progressBar->hide(); - stopButton->setEnabled(false); - stopButton->hide(); - updateInfoLabel(); - emit statusChanged(); -} - -/*! - DownloadManager is a Dialog that contains a list of DownloadWidgets - - 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_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(QWebEngineDownloadItem *download) -{ - DownloadWidget *widget = new DownloadWidget(download, this); - addItem(widget); -} - -void DownloadManager::addItem(DownloadWidget *widget) -{ - connect(widget, SIGNAL(statusChanged()), this, SLOT(updateRow())); - int row = m_downloads.count(); - m_model->beginInsertRows(QModelIndex(), row, row); - m_downloads.append(widget); - m_model->endInsertRows(); - updateItemCount(); - if (row == 0) - show(); - downloadsView->setIndexWidget(m_model->index(row, 0), widget); - QIcon icon = style()->standardIcon(QStyle::SP_FileIcon); - widget->fileIcon->setPixmap(icon.pixmap(48, 48)); - downloadsView->setRowHeight(row, widget->sizeHint().height()); -} - -void DownloadManager::updateRow() -{ - DownloadWidget *widget = qobject_cast<DownloadWidget*>(sender()); - int row = m_downloads.indexOf(widget); - if (-1 == row) - return; - if (!m_iconProvider) - m_iconProvider = new QFileIconProvider(); - QIcon icon = m_iconProvider->icon(widget->m_file); - if (icon.isNull()) - icon = style()->standardIcon(QStyle::SP_FileIcon); - widget->fileIcon->setPixmap(icon.pixmap(48, 48)); - downloadsView->setRowHeight(row, widget->minimumSizeHint().height()); - - bool remove = false; - if (!widget->downloading() - && BrowserApplication::instance()->privateBrowsing()) - remove = true; - - if (widget->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"), m_downloads[i]->m_file.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<RemovePolicy>(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 (done && !url.isEmpty() && !fileName.isEmpty()) { - DownloadWidget *widget = new DownloadWidget(0, this); - widget->m_file.setFile(fileName); - widget->fileNameLabel->setText(widget->m_file.fileName()); - widget->m_url = url; - widget->stopButton->setVisible(false); - widget->stopButton->setEnabled(false); - widget->progressBar->hide(); - addItem(widget); - } - 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()) { - beginRemoveRows(parent, i, i); - m_downloadManager->m_downloads.takeAt(i)->deleteLater(); - endRemoveRows(); - } - } - m_downloadManager->m_autoSaver->changeOccurred(); - return true; -} diff --git a/examples/webenginewidgets/demobrowser/downloadmanager.h b/examples/webenginewidgets/demobrowser/downloadmanager.h deleted file mode 100644 index ea5a7e79d..000000000 --- a/examples/webenginewidgets/demobrowser/downloadmanager.h +++ /dev/null @@ -1,163 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef DOWNLOADMANAGER_H -#define DOWNLOADMANAGER_H - -#include "ui_downloads.h" -#include "ui_downloaditem.h" - -#include <QtCore/QFileInfo> -#include <QtCore/QTime> -#include <QtCore/QUrl> - -#include <QWebEngineDownloadItem> - -class DownloadManager; -class DownloadWidget : public QWidget, public Ui_DownloadItem -{ - Q_OBJECT - -signals: - void statusChanged(); - -public: - DownloadWidget(QWebEngineDownloadItem *download, QWidget *parent = 0); - bool downloading() const; - bool downloadedSuccessfully() const; - - void init(); - bool getFileName(bool promptForFileName = false); - -private slots: - void stop(); - void open(); - - void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); - void finished(); - -private: - friend class DownloadManager; - void updateInfoLabel(); - QString dataString(int size) const; - - QUrl m_url; - QFileInfo m_file; - qint64 m_bytesReceived; - QTime m_downloadTime; - bool m_stopped; - - QScopedPointer<QWebEngineDownloadItem> m_download; -}; - -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) - -public: - enum RemovePolicy { - Never, - Exit, - SuccessFullDownload - }; - Q_ENUM(RemovePolicy) - - DownloadManager(QWidget *parent = 0); - ~DownloadManager(); - int activeDownloads() const; - - RemovePolicy removePolicy() const; - void setRemovePolicy(RemovePolicy policy); - -public slots: - void download(QWebEngineDownloadItem *download); - void cleanup(); - -private slots: - void save() const; - void updateRow(); - -private: - void addItem(DownloadWidget *item); - void updateItemCount(); - void load(); - - AutoSaver *m_autoSaver; - DownloadModel *m_model; - QFileIconProvider *m_iconProvider; - QList<DownloadWidget*> 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/demobrowser/downloads.ui b/examples/webenginewidgets/demobrowser/downloads.ui deleted file mode 100644 index a2e256935..000000000 --- a/examples/webenginewidgets/demobrowser/downloads.ui +++ /dev/null @@ -1,83 +0,0 @@ -<ui version="4.0" > - <class>DownloadDialog</class> - <widget class="QDialog" name="DownloadDialog" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>332</width> - <height>252</height> - </rect> - </property> - <property name="windowTitle" > - <string>Downloads</string> - </property> - <layout class="QGridLayout" name="gridLayout" > - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>0</number> - </property> - <item row="0" column="0" colspan="3" > - <widget class="EditTableView" name="downloadsView" /> - </item> - <item row="1" column="0" > - <layout class="QHBoxLayout" name="horizontalLayout" > - <item> - <widget class="QPushButton" name="cleanupButton" > - <property name="enabled" > - <bool>false</bool> - </property> - <property name="text" > - <string>Clean up</string> - </property> - </widget> - </item> - <item> - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>58</width> - <height>24</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item row="1" column="1" > - <widget class="QLabel" name="itemCount" > - <property name="text" > - <string>0 Items</string> - </property> - </widget> - </item> - <item row="1" column="2" > - <spacer name="horizontalSpacer" > - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>148</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>EditTableView</class> - <extends>QTableView</extends> - <header>edittableview.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui> diff --git a/examples/webenginewidgets/demobrowser/edittableview.cpp b/examples/webenginewidgets/demobrowser/edittableview.cpp deleted file mode 100644 index 4d237ecd9..000000000 --- a/examples/webenginewidgets/demobrowser/edittableview.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "edittableview.h" -#include <QtGui/QKeyEvent> - -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/demobrowser/edittableview.h b/examples/webenginewidgets/demobrowser/edittableview.h deleted file mode 100644 index 1acee59f1..000000000 --- a/examples/webenginewidgets/demobrowser/edittableview.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef EDITTABLEVIEW_H -#define EDITTABLEVIEW_H - -#include <QtWidgets/QTableView> - -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/demobrowser/edittreeview.cpp b/examples/webenginewidgets/demobrowser/edittreeview.cpp deleted file mode 100644 index f4c9a0d70..000000000 --- a/examples/webenginewidgets/demobrowser/edittreeview.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "edittreeview.h" -#include "browserapplication.h" -#include "history.h" - -#include <QtGui/QKeyEvent> - -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(); - BrowserApplication::historyManager()->removeHistoryEntry(model()->data(ci,HistoryModel::UrlStringRole).toString()); -} - -void EditTreeView::removeAll() -{ - if (!model()) - return; - BrowserApplication::historyManager()->clear(); -} diff --git a/examples/webenginewidgets/demobrowser/edittreeview.h b/examples/webenginewidgets/demobrowser/edittreeview.h deleted file mode 100644 index f9dcd5e63..000000000 --- a/examples/webenginewidgets/demobrowser/edittreeview.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef EDITTREEVIEW_H -#define EDITTREEVIEW_H - -#include <QtWidgets/QTreeView> - -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/demobrowser/featurepermissionbar.cpp b/examples/webenginewidgets/demobrowser/featurepermissionbar.cpp deleted file mode 100644 index 4cac05082..000000000 --- a/examples/webenginewidgets/demobrowser/featurepermissionbar.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "featurepermissionbar.h" - -#include <QLabel> -#include <QPushButton> -#include <QHBoxLayout> -#include <QUrl> -#include <QPropertyAnimation> - -static const int defaultHeight = 30; - -static QString textForPermissionType(QWebEnginePage::Feature type) -{ - switch (type) { - case QWebEnginePage::Notifications: - return QObject::tr("use desktop notifications"); - case QWebEnginePage::Geolocation: - return QObject::tr("use your position"); - case QWebEnginePage::MediaAudioCapture: - return QObject::tr("use your microphone"); - case QWebEnginePage::MediaVideoCapture: - return QObject::tr("use your camera"); - case QWebEnginePage::MediaAudioVideoCapture: - return QObject::tr("use your camera and microphone"); - case QWebEnginePage::MouseLock: - return QObject::tr("lock your mouse"); - default: - Q_UNREACHABLE(); - } - return QString(); -} - -FeaturePermissionBar::FeaturePermissionBar(QWidget *view) - : QWidget(view) - , m_messageLabel(new QLabel(this)) -{ - setAutoFillBackground(true); - QHBoxLayout *l = new QHBoxLayout; - setLayout(l); - l->setContentsMargins(defaultHeight, 0, 0, 0); - l->addWidget(m_messageLabel); - l->addStretch(); - QPushButton *allowButton = new QPushButton(tr("Allow"), this); - QPushButton *denyButton = new QPushButton(tr("Deny"), this); - QPushButton *discardButton = new QPushButton(QIcon(QStringLiteral(":closetab.png")), QString(), this); - connect(allowButton, &QPushButton::clicked, this, &FeaturePermissionBar::permissionGranted); - connect(denyButton, &QPushButton::clicked, this, &FeaturePermissionBar::permissionDenied); - connect(discardButton, &QPushButton::clicked, this, &FeaturePermissionBar::permissionUnknown); - connect(allowButton, &QPushButton::clicked, this, &QObject::deleteLater); - connect(denyButton, &QPushButton::clicked, this, &QObject::deleteLater); - connect(discardButton, &QPushButton::clicked, this, &QObject::deleteLater); - l->addWidget(denyButton); - l->addWidget(allowButton); - l->addWidget(discardButton); - setGeometry(0, -defaultHeight, view->width(), defaultHeight); -} - -void FeaturePermissionBar::requestPermission(const QUrl &securityOrigin, QWebEnginePage::Feature feature) -{ - m_securityOrigin = securityOrigin; - m_feature = feature; - m_messageLabel->setText(tr("%1 wants to %2.").arg(securityOrigin.host()).arg(textForPermissionType(feature))); - show(); - // Ease in - QPropertyAnimation *animation = new QPropertyAnimation(this); - animation->setTargetObject(this); - animation->setPropertyName(QByteArrayLiteral("pos")); - animation->setDuration(300); - animation->setStartValue(QVariant::fromValue(pos())); - animation->setEndValue(QVariant::fromValue(QPoint(0,0))); - animation->setEasingCurve(QEasingCurve::InOutQuad); - animation->start(QPropertyAnimation::DeleteWhenStopped); -} - -void FeaturePermissionBar::permissionDenied() -{ - emit featurePermissionProvided(m_securityOrigin, m_feature, QWebEnginePage::PermissionDeniedByUser); -} - -void FeaturePermissionBar::permissionGranted() -{ - emit featurePermissionProvided(m_securityOrigin, m_feature, QWebEnginePage::PermissionGrantedByUser); -} - -void FeaturePermissionBar::permissionUnknown() -{ - emit featurePermissionProvided(m_securityOrigin, m_feature, QWebEnginePage::PermissionUnknown); -} diff --git a/examples/webenginewidgets/demobrowser/featurepermissionbar.h b/examples/webenginewidgets/demobrowser/featurepermissionbar.h deleted file mode 100644 index 63290df3b..000000000 --- a/examples/webenginewidgets/demobrowser/featurepermissionbar.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef FEATUREPERMISSIONBAR_H -#define FEATUREPERMISSIONBAR_H - -#include <QWidget> -#include <QWebEnginePage> - -QT_BEGIN_NAMESPACE -class QLabel; -class QPushButton; -QT_END_NAMESPACE - -class FeaturePermissionBar : public QWidget { -Q_OBJECT - -public: - FeaturePermissionBar(QWidget*); - void requestPermission(const QUrl &, QWebEnginePage::Feature feature); - -signals: - void featurePermissionProvided(const QUrl &securityOrigin, QWebEnginePage::Feature, QWebEnginePage::PermissionPolicy); - -private slots: - void permissionDenied(); - void permissionGranted(); - void permissionUnknown(); - -private: - QWebEnginePage::Feature m_feature; - QLabel *m_messageLabel; - QUrl m_securityOrigin; -}; - -#endif // FEATUREPERMISSIONBAR_H diff --git a/examples/webenginewidgets/demobrowser/fullscreennotification.cpp b/examples/webenginewidgets/demobrowser/fullscreennotification.cpp deleted file mode 100644 index aadabbadb..000000000 --- a/examples/webenginewidgets/demobrowser/fullscreennotification.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "fullscreennotification.h" - -#include <QApplication> -#include <QDesktopWidget> -#include <QGridLayout> -#include <QLabel> -#include <QPropertyAnimation> -#include <QTimer> - -FullScreenNotification::FullScreenNotification(QWidget *parent) - : QWidget(parent) - , width(400) - , height(80) - , x((parent->geometry().width() - width) / 2) - , y(80) -{ - setVisible(false); - setWindowFlags(Qt::ToolTip | Qt::WindowDoesNotAcceptFocus); - - QGridLayout *layout = new QGridLayout(this); - - m_label = new QLabel(tr("You are now in fullscreen mode. Press ESC to quit!"), this); - layout->addWidget(m_label, 0, 0, 0, 0, Qt::AlignHCenter | Qt::AlignVCenter); - - setGeometry(x, y, width, height); - - setStyleSheet("background-color: white;\ - color: black;"); - - m_animation = new QPropertyAnimation(this, "windowOpacity"); - connect(m_animation, SIGNAL(finished()), this, SLOT(fadeOutFinished())); -} - -FullScreenNotification::~FullScreenNotification() -{ -} - -void FullScreenNotification::show() -{ - setWindowOpacity(1.0); - QTimer::singleShot(300, [&] { - QWidget *parent = parentWidget(); - x = (parent->geometry().width() - width) / 2; - QPoint topLeft = parent->mapToGlobal(QPoint(x, y)); - QWidget::move(topLeft.x(), topLeft.y()); - QWidget::show(); - QWidget::raise(); - }); - QTimer::singleShot(5000, this, SLOT(fadeOut())); -} - -void FullScreenNotification::hide() -{ - QWidget::hide(); - m_animation->stop(); -} - -void FullScreenNotification::fadeOut() -{ - m_animation->setDuration(800); - m_animation->setStartValue(1.0); - m_animation->setEndValue(0.0); - m_animation->setEasingCurve(QEasingCurve::OutQuad); - m_animation->start(); -} - -void FullScreenNotification::fadeOutFinished() -{ - hide(); - setWindowOpacity(1.0); -} diff --git a/examples/webenginewidgets/demobrowser/fullscreennotification.h b/examples/webenginewidgets/demobrowser/fullscreennotification.h deleted file mode 100644 index 260f8e72f..000000000 --- a/examples/webenginewidgets/demobrowser/fullscreennotification.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef FULLSCREENNOTIFICATION_H -#define FULLSCREENNOTIFICATION_H - -#include <QWidget> - -QT_BEGIN_NAMESPACE -class QLabel; -class QGridLayout; -class QPropertyAnimation; -QT_END_NAMESPACE - -class FullScreenNotification : public QWidget -{ - Q_OBJECT -public: - FullScreenNotification(QWidget *parent = 0); - ~FullScreenNotification(); - - void show(); - void hide(); - -public slots: - void fadeOut(); - void fadeOutFinished(); - -private: - QLabel *m_label; - QGridLayout *m_layout; - QPropertyAnimation *m_animation; - int width; - int height; - int x; - int y; -}; - -#endif // FULLSCREENNOTIFICATION_H diff --git a/examples/webenginewidgets/demobrowser/history.cpp b/examples/webenginewidgets/demobrowser/history.cpp deleted file mode 100644 index bce65b917..000000000 --- a/examples/webenginewidgets/demobrowser/history.cpp +++ /dev/null @@ -1,1314 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "history.h" - -#include "autosaver.h" -#include "browserapplication.h" - -#include <QtCore/QBuffer> -#include <QtCore/QDir> -#include <QtCore/QFile> -#include <QtCore/QFileInfo> -#include <QtCore/QSettings> -#include <QtCore/QTemporaryFile> -#include <QtCore/QTextStream> - -#include <QtCore/QtAlgorithms> - -#include <QtGui/QClipboard> -#include <QtGui/QDesktopServices> -#include <QtWidgets/QHeaderView> -#include <QtWidgets/QStyle> - -#include <QWebEngineSettings> - -#include <QtCore/QDebug> - -static const unsigned int HISTORY_VERSION = 23; - -HistoryManager::HistoryManager(QObject *parent) - : QObject(parent) - , 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); -} - -HistoryManager::~HistoryManager() -{ - m_saveTimer->saveIfNeccessary(); -} - -QList<HistoryItem> &HistoryManager::history() -{ - 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::removeHistoryEntry(const QString &url) -{ - QUrl cleanUrl(url); - cleanUrl.setPassword(QString()); - cleanUrl.setHost(cleanUrl.host().toLower()); - HistoryItem item(cleanUrl.toString(), QDateTime::currentDateTime()); - removeHistoryItem(item); -} - -void HistoryManager::setHistory(const QList<HistoryItem> &history, bool loadedAndSorted) -{ - m_history = history; - - // verify that it is sorted by date - if (!loadedAndSorted) - qSort(m_history.begin(), m_history.end()); - - checkForExpired(loadedAndSorted); - - 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(bool removeEntriesDirectly) -{ - 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; - const HistoryItem& item = m_history.last(); - // remove from saved file also - m_lastSavedUrl = QString(); - - if (removeEntriesDirectly) - m_history.takeLast(); - else - emit entryRemoved(item); - } - - if (nextTimeout > 0) - m_expiredTimer.start(nextTimeout * 1000); -} - -void HistoryManager::addHistoryItem(const HistoryItem &item) -{ - if (BrowserApplication::instance()->privateBrowsing()) - return; - - emit entryAdded(item); - if (m_history.count() == 1) - checkForExpired(); -} - -void HistoryManager::removeHistoryItem(const HistoryItem &item) -{ - for (int i = m_history.count() - 1 ; i >= 0; --i) { - if (item.url == m_history.at(i).url) { - //delete all related entries with that url - emit entryRemoved(m_history.at(i)); - } - } -} - -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_lastSavedUrl = QString(); - emit historyReset(); - m_saveTimer->changeOccurred(); - m_saveTimer->saveIfNeccessary(); -} - -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<HistoryItem> 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(entryRemoved(HistoryItem))); - - connect(m_history, SIGNAL(entryAdded(HistoryItem)), - this, SLOT(entryAdded(HistoryItem))); - connect(m_history, SIGNAL(entryUpdated(int)), - this, SLOT(entryUpdated(int))); -} - -void HistoryModel::historyReset() -{ - beginResetModel(); - m_history->history().clear(); - endResetModel(); -} - -void HistoryModel::entryAdded(const HistoryItem &item) -{ - beginInsertRows(QModelIndex(), 0, 0); - m_history->history().prepend(item); - endInsertRows(); -} - -void HistoryModel::entryRemoved(const HistoryItem &item) -{ - int index = m_history->history().indexOf(item); - Q_ASSERT(index > -1); - beginRemoveRows(QModelIndex(),index, index); - m_history->history().takeAt(index); - endRemoveRows(); -} - -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<HistoryItem> 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<HistoryItem> &lst = m_history->history(); - for (int i = lastRow; i >= row; --i) - lst.removeAt(i); - 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<QAction*> 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 -{ - 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->historyFilterModel(); - 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()), tree, SLOT(removeAll())); - proxyModel->setSourceModel(model); - proxyModel->setFilterKeyColumn(1); - tree->setModel(proxyModel); - tree->setSortingEnabled(true); - 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); -} - -void HistoryFilterModel::setSourceModel(QAbstractItemModel *newSourceModel) -{ - beginResetModel(); - if (sourceModel()) { - disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset())); - disconnect(sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), - this, SLOT(sourceDataChanged(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()) { - 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))); - } - load(); - endResetModel(); -} - -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() -{ - beginResetModel(); - load(); - endResetModel(); -} - -int HistoryFilterModel::rowCount(const QModelIndex &parent) const -{ - 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 -{ - int sourceRow = sourceModel()->rowCount() - proxyIndex.internalId(); - return sourceModel()->index(sourceRow, proxyIndex.column()); -} - -QModelIndex HistoryFilterModel::mapFromSource(const QModelIndex &sourceIndex) const -{ - 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 -{ - 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 -{ - 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; - } - } -} - -void HistoryFilterModel::sourceRowsInserted(const QModelIndex &parent, int start, int end) -{ - Q_ASSERT(start == end && start == 0); - Q_UNUSED(end); - 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) -{ - beginResetModel(); - 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))); - disconnect(sourceModel(), &QAbstractItemModel::dataChanged, this, - &HistoryTreeModel::sourceDataChanged); - } - - 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))); - connect(sourceModel(), &QAbstractItemModel::dataChanged, this, - &HistoryTreeModel::sourceDataChanged); - } - 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<int>::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<int>::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(); - } -} - -void HistoryTreeModel::sourceDataChanged(const QModelIndex &topLeft, - const QModelIndex &bottomRight, - const QVector<int> roles) -{ - emit dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight), roles); -} diff --git a/examples/webenginewidgets/demobrowser/history.h b/examples/webenginewidgets/demobrowser/history.h deleted file mode 100644 index 2a6dce9e1..000000000 --- a/examples/webenginewidgets/demobrowser/history.h +++ /dev/null @@ -1,360 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef HISTORY_H -#define HISTORY_H - -#include "modelmenu.h" - -#include <QtCore/QDateTime> -#include <QtCore/QHash> -#include <QtCore/QObject> -#include <QtCore/QTimer> -#include <QtCore/QUrl> - -#include <QtCore/QSortFilterProxyModel> - -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 : public QObject -{ - 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 removeHistoryEntry(const QString &url); - - void updateHistoryItem(const QUrl &url, const QString &title); - - int historyLimit() const; - void setHistoryLimit(int limit); - - QList<HistoryItem>& history(); - void setHistory(const QList<HistoryItem> &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(bool removeExpiredEntriesDirectly = false); - -protected: - void addHistoryItem(const HistoryItem &item); - void removeHistoryItem(const HistoryItem &item); - -private: - void load(); - - AutoSaver *m_saveTimer; - int m_historyLimit; - QTimer m_expiredTimer; - QList<HistoryItem> 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(const HistoryItem &item); - void entryRemoved(const HistoryItem &item); - 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); } - - 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()); - -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<int> m_sourceRow; - mutable QHash<QString, int> 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<QAction*> actions); - -protected: - bool prePopulated(); - void postPopulated(); - -private slots: - void activated(const QModelIndex &index); - void showHistoryDialog(); - -private: - HistoryManager *m_history; - HistoryMenuModel *m_historyMenuModel; - QList<QAction*> 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); - void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, - const QVector<int> roles); -private: - int sourceDateRow(int row) const; - mutable QList<int> 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/demobrowser/history.ui b/examples/webenginewidgets/demobrowser/history.ui deleted file mode 100644 index 0944940e7..000000000 --- a/examples/webenginewidgets/demobrowser/history.ui +++ /dev/null @@ -1,106 +0,0 @@ -<ui version="4.0" > - <class>HistoryDialog</class> - <widget class="QDialog" name="HistoryDialog" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>758</width> - <height>450</height> - </rect> - </property> - <property name="windowTitle" > - <string>History</string> - </property> - <layout class="QGridLayout" name="gridLayout" > - <item row="0" column="0" > - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>252</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="1" > - <widget class="SearchLineEdit" name="search" /> - </item> - <item row="1" column="0" colspan="2" > - <widget class="EditTreeView" name="tree" /> - </item> - <item row="2" column="0" colspan="2" > - <layout class="QHBoxLayout" > - <item> - <widget class="QPushButton" name="removeButton" > - <property name="text" > - <string>&Remove</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="removeAllButton" > - <property name="text" > - <string>Remove &All</string> - </property> - </widget> - </item> - <item> - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox" > - <property name="standardButtons" > - <set>QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>SearchLineEdit</class> - <extends>QLineEdit</extends> - <header>searchlineedit.h</header> - </customwidget> - <customwidget> - <class>EditTreeView</class> - <extends>QTreeView</extends> - <header>edittreeview.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>HistoryDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel" > - <x>472</x> - <y>329</y> - </hint> - <hint type="destinationlabel" > - <x>461</x> - <y>356</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/examples/webenginewidgets/demobrowser/htmls/htmls.qrc b/examples/webenginewidgets/demobrowser/htmls/htmls.qrc deleted file mode 100644 index 03b256ccb..000000000 --- a/examples/webenginewidgets/demobrowser/htmls/htmls.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<!DOCTYPE RCC><RCC version="1.0"> -<qresource> - <file>notfound.html</file> -</qresource> -</RCC> diff --git a/examples/webenginewidgets/demobrowser/htmls/notfound.html b/examples/webenginewidgets/demobrowser/htmls/notfound.html deleted file mode 100644 index e89845aa6..000000000 --- a/examples/webenginewidgets/demobrowser/htmls/notfound.html +++ /dev/null @@ -1,63 +0,0 @@ -<html> -<head> -<title>%1</title> -<style> -body { - padding: 3em 0em; - background: #eeeeee; -} -hr { - color: lightgray; - width: 100%; -} -img { - float: left; - opacity: .8; -} -#box { - background: white; - border: 1px solid lightgray; - width: 600px; - padding: 60px; - margin: auto; -} -h1 { - font-size: 130%; - font-weight: bold; - border-bottom: 1px solid lightgray; - margin-left: 48px; -} -h2 { - font-size: 100%; - font-weight: normal; - border-bottom: 1px solid lightgray; - margin-left: 48px; -} -ul { - font-size: 80%; - padding-left: 48px; - margin: 0; -} -#reloadButton { - padding-left: 48px; -} -</style> -</head> -<body> - <div id="box"> - <img src="data:image/png;base64,IMAGE_BINARY_DATA_HERE" width="32" height="32"/> - <h1>%2</h1> - <h2>When connecting to: %3.</h2> - <ul> - <li>Check the address for errors such as <b>ww</b>.example.com - instead of <b>www</b>.example.com</li> - <li>If the address is correct, try checking the network - connection.</li> - <li>If your computer or network is protected by a firewall or - proxy, make sure that the browser demo is permitted to access - the network.</li> - </ul> - <br/><br/> - </div> -</body> -</html> diff --git a/examples/webenginewidgets/demobrowser/main.cpp b/examples/webenginewidgets/demobrowser/main.cpp deleted file mode 100644 index 41cae306a..000000000 --- a/examples/webenginewidgets/demobrowser/main.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "browserapplication.h" - -#include <qtwebenginewidgetsglobal.h> - -int main(int argc, char **argv) -{ - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - Q_INIT_RESOURCE(data); - BrowserApplication application(argc, argv); - if (!application.isTheOnlyBrowser()) - return 0; - - application.newMainWindow(); - return application.exec(); -} diff --git a/examples/webenginewidgets/demobrowser/modelmenu.cpp b/examples/webenginewidgets/demobrowser/modelmenu.cpp deleted file mode 100644 index 9064320f4..000000000 --- a/examples/webenginewidgets/demobrowser/modelmenu.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "modelmenu.h" - -#include <QtCore/QAbstractItemModel> -#include <qdebug.h> - -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<QMenu*>(sender())) { - QVariant v = menu->menuAction()->data(); - if (v.canConvert<QModelIndex>()) { - QModelIndex idx = qvariant_cast<QModelIndex>(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<QIcon>(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<QIcon>(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>()) { - QModelIndex idx = qvariant_cast<QModelIndex>(v); - emit activated(idx); - } -} - -void ModelMenu::hovered(QAction *action) -{ - QVariant v = action->data(); - if (v.canConvert<QModelIndex>()) { - QModelIndex idx = qvariant_cast<QModelIndex>(v); - QString hoveredString = idx.data(m_hoverRole).toString(); - if (!hoveredString.isEmpty()) - emit hovered(hoveredString); - } -} diff --git a/examples/webenginewidgets/demobrowser/modelmenu.h b/examples/webenginewidgets/demobrowser/modelmenu.h deleted file mode 100644 index 718b1d3cf..000000000 --- a/examples/webenginewidgets/demobrowser/modelmenu.h +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MODELMENU_H -#define MODELMENU_H - -#include <QtWidgets/QMenu> -#include <QtCore/QAbstractItemModel> - -// 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/demobrowser/passworddialog.ui b/examples/webenginewidgets/demobrowser/passworddialog.ui deleted file mode 100644 index 7c1665867..000000000 --- a/examples/webenginewidgets/demobrowser/passworddialog.ui +++ /dev/null @@ -1,111 +0,0 @@ -<ui version="4.0" > - <class>PasswordDialog</class> - <widget class="QDialog" name="PasswordDialog" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>399</width> - <height>148</height> - </rect> - </property> - <property name="windowTitle" > - <string>Authentication Required</string> - </property> - <layout class="QGridLayout" name="gridLayout" > - <item row="0" column="0" colspan="2" > - <layout class="QHBoxLayout" > - <item> - <widget class="QLabel" name="iconLabel" > - <property name="text" > - <string>DUMMY ICON</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="introLabel" > - <property name="sizePolicy" > - <sizepolicy vsizetype="MinimumExpanding" hsizetype="MinimumExpanding" > - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text" > - <string>INTRO TEXT DUMMY</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="1" column="0" > - <widget class="QLabel" name="label" > - <property name="text" > - <string>Username:</string> - </property> - </widget> - </item> - <item row="1" column="1" > - <widget class="QLineEdit" name="userNameLineEdit" /> - </item> - <item row="2" column="0" > - <widget class="QLabel" name="lblPassword" > - <property name="text" > - <string>Password:</string> - </property> - </widget> - </item> - <item row="2" column="1" > - <widget class="QLineEdit" name="passwordLineEdit" > - <property name="echoMode" > - <enum>QLineEdit::Password</enum> - </property> - </widget> - </item> - <item row="3" column="0" colspan="2" > - <widget class="QDialogButtonBox" name="buttonBox" > - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons" > - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>PasswordDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel" > - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel" > - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>PasswordDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel" > - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel" > - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/examples/webenginewidgets/demobrowser/printtopdfdialog.cpp b/examples/webenginewidgets/demobrowser/printtopdfdialog.cpp deleted file mode 100644 index 50a8bb91a..000000000 --- a/examples/webenginewidgets/demobrowser/printtopdfdialog.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "printtopdfdialog.h" -#include "ui_printtopdfdialog.h" - -#include <QtCore/QDir> -#include <QtPrintSupport/QPageSetupDialog> -#include <QtPrintSupport/QPrinter> -#include <QtWidgets/QFileDialog> - -PrintToPdfDialog::PrintToPdfDialog(const QString &filePath, QWidget *parent) : - QDialog(parent), - currentPageLayout(QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0.0, 0.0, 0.0, 0.0))), - ui(new Ui::PrintToPdfDialog) -{ - ui->setupUi(this); - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - connect(ui->chooseFilePathButton, &QToolButton::clicked, this, &PrintToPdfDialog::onChooseFilePathButtonClicked); - connect(ui->choosePageLayoutButton, &QToolButton::clicked, this, &PrintToPdfDialog::onChoosePageLayoutButtonClicked); - ui->choosePageLayoutButton->hide(); - updatePageLayoutLabel(); - setFilePath(filePath); -} - -PrintToPdfDialog::~PrintToPdfDialog() -{ - delete ui; -} - -void PrintToPdfDialog::onChoosePageLayoutButtonClicked() -{ - QPrinter printer; - printer.setPageLayout(currentPageLayout); - - QPageSetupDialog dlg(&printer, this); - if (dlg.exec() != QDialog::Accepted) - return; - currentPageLayout.setPageSize(printer.pageLayout().pageSize()); - currentPageLayout.setOrientation(printer.pageLayout().orientation()); - updatePageLayoutLabel(); -} - -void PrintToPdfDialog::onChooseFilePathButtonClicked() -{ - QFileInfo fi(filePath()); - QFileDialog dlg(this, tr("Save PDF as"), fi.absolutePath()); - dlg.setAcceptMode(QFileDialog::AcceptSave); - dlg.setDefaultSuffix(QStringLiteral(".pdf")); - dlg.selectFile(fi.absoluteFilePath()); - if (dlg.exec() != QDialog::Accepted) - return; - setFilePath(dlg.selectedFiles().first()); -} - -QString PrintToPdfDialog::filePath() const -{ - return QDir::fromNativeSeparators(ui->filePathLineEdit->text()); -} - -void PrintToPdfDialog::setFilePath(const QString &filePath) -{ - ui->filePathLineEdit->setText(QDir::toNativeSeparators(filePath)); -} - -QPageLayout PrintToPdfDialog::pageLayout() const -{ - return currentPageLayout; -} - -void PrintToPdfDialog::updatePageLayoutLabel() -{ - ui->pageLayoutLabel->setText(QString("%1, %2").arg( - currentPageLayout.pageSize().name()).arg( - currentPageLayout.orientation() == QPageLayout::Portrait - ? tr("Portrait") : tr("Landscape") - )); -} diff --git a/examples/webenginewidgets/demobrowser/printtopdfdialog.h b/examples/webenginewidgets/demobrowser/printtopdfdialog.h deleted file mode 100644 index 87fca72c3..000000000 --- a/examples/webenginewidgets/demobrowser/printtopdfdialog.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PRINTTOPDFDIALOG_H -#define PRINTTOPDFDIALOG_H - -#include <QDialog> -#include <QPageLayout> - -QT_BEGIN_NAMESPACE -namespace Ui { -class PrintToPdfDialog; -} -QT_END_NAMESPACE - -class PrintToPdfDialog : public QDialog -{ - Q_OBJECT - -public: - explicit PrintToPdfDialog(const QString &filePath, QWidget *parent = 0); - ~PrintToPdfDialog(); - - QString filePath() const; - QPageLayout pageLayout() const; - -private slots: - void onChoosePageLayoutButtonClicked(); - void onChooseFilePathButtonClicked(); - -private: - void setFilePath(const QString &); - void updatePageLayoutLabel(); - - QPageLayout currentPageLayout; - Ui::PrintToPdfDialog *ui; -}; - -#endif // PRINTTOPDFDIALOG_H diff --git a/examples/webenginewidgets/demobrowser/printtopdfdialog.ui b/examples/webenginewidgets/demobrowser/printtopdfdialog.ui deleted file mode 100644 index dcfd5a3aa..000000000 --- a/examples/webenginewidgets/demobrowser/printtopdfdialog.ui +++ /dev/null @@ -1,119 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>PrintToPdfDialog</class> - <widget class="QDialog" name="PrintToPdfDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>372</width> - <height>117</height> - </rect> - </property> - <property name="windowTitle"> - <string>Dialog</string> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="2" column="0"> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - <item row="0" column="0" colspan="2"> - <layout class="QGridLayout" name="gridLayout"> - <item row="1" column="3"> - <widget class="QToolButton" name="choosePageLayoutButton"> - <property name="text"> - <string>...</string> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="filePathLabel"> - <property name="text"> - <string>Save as:</string> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QLineEdit" name="filePathLineEdit"/> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="layoutLabel"> - <property name="text"> - <string>Page layout:</string> - </property> - </widget> - </item> - <item row="0" column="3"> - <widget class="QToolButton" name="chooseFilePathButton"> - <property name="text"> - <string>...</string> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QLabel" name="pageLayoutLabel"> - <property name="text"> - <string/> - </property> - </widget> - </item> - </layout> - </item> - <item row="1" column="0"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>PrintToPdfDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>PrintToPdfDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/examples/webenginewidgets/demobrowser/proxy.ui b/examples/webenginewidgets/demobrowser/proxy.ui deleted file mode 100644 index 62a8be627..000000000 --- a/examples/webenginewidgets/demobrowser/proxy.ui +++ /dev/null @@ -1,104 +0,0 @@ -<ui version="4.0" > - <class>ProxyDialog</class> - <widget class="QDialog" name="ProxyDialog" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>369</width> - <height>144</height> - </rect> - </property> - <property name="windowTitle" > - <string>Proxy Authentication</string> - </property> - <layout class="QGridLayout" name="gridLayout" > - <item row="0" column="0" > - <widget class="QLabel" name="iconLabel" > - <property name="text" > - <string>ICON</string> - </property> - </widget> - </item> - <item row="0" column="1" colspan="2" > - <widget class="QLabel" name="introLabel" > - <property name="text" > - <string>Connect to proxy</string> - </property> - <property name="wordWrap" > - <bool>true</bool> - </property> - </widget> - </item> - <item row="1" column="0" colspan="2" > - <widget class="QLabel" name="usernameLabel" > - <property name="text" > - <string>Username:</string> - </property> - </widget> - </item> - <item row="1" column="2" > - <widget class="QLineEdit" name="userNameLineEdit" /> - </item> - <item row="2" column="0" colspan="2" > - <widget class="QLabel" name="passwordLabel" > - <property name="text" > - <string>Password:</string> - </property> - </widget> - </item> - <item row="2" column="2" > - <widget class="QLineEdit" name="passwordLineEdit" > - <property name="echoMode" > - <enum>QLineEdit::Password</enum> - </property> - </widget> - </item> - <item row="3" column="0" colspan="3" > - <widget class="QDialogButtonBox" name="buttonBox" > - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons" > - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>ProxyDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel" > - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel" > - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>ProxyDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel" > - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel" > - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/examples/webenginewidgets/demobrowser/savepagedialog.cpp b/examples/webenginewidgets/demobrowser/savepagedialog.cpp deleted file mode 100644 index 8ec21f821..000000000 --- a/examples/webenginewidgets/demobrowser/savepagedialog.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "savepagedialog.h" -#include "ui_savepagedialog.h" - -#include <QtCore/QDir> -#include <QtWidgets/QFileDialog> - -const QWebEngineDownloadItem::SavePageFormat SavePageDialog::m_indexToFormatTable[] = { - QWebEngineDownloadItem::SingleHtmlSaveFormat, - QWebEngineDownloadItem::CompleteHtmlSaveFormat, - QWebEngineDownloadItem::MimeHtmlSaveFormat -}; - -SavePageDialog::SavePageDialog(QWidget *parent, QWebEngineDownloadItem::SavePageFormat format, - const QString &filePath) - : QDialog(parent) - , ui(new Ui::SavePageDialog) -{ - ui->setupUi(this); - ui->formatComboBox->setCurrentIndex(formatToIndex(format)); - setFilePath(filePath); -} - -SavePageDialog::~SavePageDialog() -{ - delete ui; -} - -QWebEngineDownloadItem::SavePageFormat SavePageDialog::pageFormat() const -{ - return indexToFormat(ui->formatComboBox->currentIndex()); -} - -QString SavePageDialog::filePath() const -{ - return QDir::fromNativeSeparators(ui->filePathLineEdit->text()); -} - -void SavePageDialog::on_chooseFilePathButton_clicked() -{ - QFileInfo fi(filePath()); - QFileDialog dlg(this, tr("Save Page As"), fi.absolutePath()); - dlg.setAcceptMode(QFileDialog::AcceptSave); - dlg.setDefaultSuffix(suffixOfFormat(pageFormat())); - dlg.selectFile(fi.absoluteFilePath()); - if (dlg.exec() != QDialog::Accepted) - return; - setFilePath(dlg.selectedFiles().first()); - ensureFileSuffix(pageFormat()); -} - -void SavePageDialog::on_formatComboBox_currentIndexChanged(int idx) -{ - ensureFileSuffix(indexToFormat(idx)); -} - -int SavePageDialog::formatToIndex(QWebEngineDownloadItem::SavePageFormat format) -{ - for (auto i : m_indexToFormatTable) { - if (m_indexToFormatTable[i] == format) - return i; - } - Q_UNREACHABLE(); -} - -QWebEngineDownloadItem::SavePageFormat SavePageDialog::indexToFormat(int idx) -{ - Q_ASSERT(idx >= 0 && size_t(idx) < (sizeof(m_indexToFormatTable) - / sizeof(QWebEngineDownloadItem::SavePageFormat))); - return m_indexToFormatTable[idx]; -} - -QString SavePageDialog::suffixOfFormat(QWebEngineDownloadItem::SavePageFormat format) -{ - if (format == QWebEngineDownloadItem::MimeHtmlSaveFormat) - return QStringLiteral(".mhtml"); - return QStringLiteral(".html"); -} - -void SavePageDialog::setFilePath(const QString &filePath) -{ - ui->filePathLineEdit->setText(QDir::toNativeSeparators(filePath)); -} - -void SavePageDialog::ensureFileSuffix(QWebEngineDownloadItem::SavePageFormat format) -{ - QFileInfo fi(filePath()); - setFilePath(fi.absolutePath() + QLatin1Char('/') + fi.completeBaseName() - + suffixOfFormat(format)); -} diff --git a/examples/webenginewidgets/demobrowser/savepagedialog.h b/examples/webenginewidgets/demobrowser/savepagedialog.h deleted file mode 100644 index 77095543c..000000000 --- a/examples/webenginewidgets/demobrowser/savepagedialog.h +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SAVEPAGEDIALOG_H -#define SAVEPAGEDIALOG_H - -#include <QtWidgets/QDialog> -#include <QtWebEngineWidgets/QWebEngineDownloadItem> - -QT_BEGIN_NAMESPACE -namespace Ui { -class SavePageDialog; -} -QT_END_NAMESPACE - -class SavePageDialog : public QDialog -{ - Q_OBJECT - -public: - explicit SavePageDialog(QWidget *parent, QWebEngineDownloadItem::SavePageFormat format, - const QString &filePath); - ~SavePageDialog(); - - QWebEngineDownloadItem::SavePageFormat pageFormat() const; - QString filePath() const; - -private slots: - void on_chooseFilePathButton_clicked(); - void on_formatComboBox_currentIndexChanged(int idx); - -private: - static int formatToIndex(QWebEngineDownloadItem::SavePageFormat format); - static QWebEngineDownloadItem::SavePageFormat indexToFormat(int idx); - static QString suffixOfFormat(QWebEngineDownloadItem::SavePageFormat format); - void setFilePath(const QString &filePath); - void ensureFileSuffix(QWebEngineDownloadItem::SavePageFormat format); - - static const QWebEngineDownloadItem::SavePageFormat m_indexToFormatTable[]; - Ui::SavePageDialog *ui; -}; - -#endif // SAVEPAGEDIALOG_H diff --git a/examples/webenginewidgets/demobrowser/savepagedialog.ui b/examples/webenginewidgets/demobrowser/savepagedialog.ui deleted file mode 100644 index 9aa7cbe55..000000000 --- a/examples/webenginewidgets/demobrowser/savepagedialog.ui +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>SavePageDialog</class> - <widget class="QDialog" name="SavePageDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>400</width> - <height>121</height> - </rect> - </property> - <property name="windowTitle"> - <string>Dialog</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>&Format:</string> - </property> - <property name="buddy"> - <cstring>formatComboBox</cstring> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QComboBox" name="formatComboBox"> - <item> - <property name="text"> - <string>Single HTML</string> - </property> - </item> - <item> - <property name="text"> - <string>Complete HTML</string> - </property> - </item> - <item> - <property name="text"> - <string>MIME HTML</string> - </property> - </item> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>&Save to:</string> - </property> - <property name="buddy"> - <cstring>filePathLineEdit</cstring> - </property> - </widget> - </item> - <item row="1" column="1"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLineEdit" name="filePathLineEdit"/> - </item> - <item> - <widget class="QToolButton" name="chooseFilePathButton"> - <property name="text"> - <string>...</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </item> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>12</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - <tabstops> - <tabstop>formatComboBox</tabstop> - <tabstop>filePathLineEdit</tabstop> - <tabstop>chooseFilePathButton</tabstop> - </tabstops> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>SavePageDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>227</x> - <y>104</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>120</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>SavePageDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>295</x> - <y>110</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>120</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/examples/webenginewidgets/demobrowser/searchlineedit.cpp b/examples/webenginewidgets/demobrowser/searchlineedit.cpp deleted file mode 100644 index 04f75df91..000000000 --- a/examples/webenginewidgets/demobrowser/searchlineedit.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "searchlineedit.h" - -#include <QtGui/QPainter> -#include <QtGui/QMouseEvent> -#include <QtWidgets/QMenu> -#include <QtWidgets/QStyle> -#include <QtWidgets/QStyleOptionFrame> - -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); - QStyleOptionFrame 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<SearchLineEdit*>(this))->updateGeometries(); - } - return m_searchButton->m_menu; -} diff --git a/examples/webenginewidgets/demobrowser/searchlineedit.h b/examples/webenginewidgets/demobrowser/searchlineedit.h deleted file mode 100644 index 9b9587082..000000000 --- a/examples/webenginewidgets/demobrowser/searchlineedit.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SEARCHLINEEDIT_H -#define SEARCHLINEEDIT_H - -#include "urllineedit.h" - -#include <QtWidgets/QLineEdit> -#include <QtWidgets/QAbstractButton> - -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/demobrowser/settings.cpp b/examples/webenginewidgets/demobrowser/settings.cpp deleted file mode 100644 index aa3110ae7..000000000 --- a/examples/webenginewidgets/demobrowser/settings.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "settings.h" - -#include "browserapplication.h" -#include "browsermainwindow.h" -#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) -#include "cookiejar.h" -#endif -#include "history.h" -#include "webview.h" - -#include <QtCore/QLocale> -#include <QtCore/QSettings> -#include <QtWidgets/QtWidgets> -#include <QtWebEngineWidgets/QtWebEngineWidgets> - -SettingsDialog::SettingsDialog(QWidget *parent) - : QDialog(parent) -{ - setupUi(this); - connect(setHomeToCurrentPageButton, SIGNAL(clicked()), this, SLOT(setHomeToCurrentPage())); - connect(standardFontButton, SIGNAL(clicked()), this, SLOT(chooseFont())); - connect(fixedFontButton, SIGNAL(clicked()), this, SLOT(chooseFixedFont())); - - loadDefaults(); - loadFromSettings(); -} - -static QString defaultAcceptLanguage() -{ - const QStringList langs = QLocale().uiLanguages(); - if (langs.isEmpty()) - return QString(); - QString str = langs.first(); - const float qstep = 1.0f / float(langs.count()); - float q = 1.0f - qstep; - for (int i = 1; i < langs.count(); ++i) { - str += QStringLiteral(", ") + langs.at(i) + QStringLiteral(";q=") + QString::number(q, 'f', 2); - q -= qstep; - } - return str; -} - -void SettingsDialog::loadDefaults() -{ - 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)); - - enableScrollAnimator->setChecked(defaultSettings->testAttribute(QWebEngineSettings::ScrollAnimatorEnabled)); - - persistentDataPath->setText(QWebEngineProfile::defaultProfile()->persistentStoragePath()); - sessionCookiesCombo->setCurrentIndex(QWebEngineProfile::defaultProfile()->persistentCookiesPolicy()); - httpUserAgent->setText(QWebEngineProfile::defaultProfile()->httpUserAgent()); - httpAcceptLanguage->setText(defaultAcceptLanguage()); - - if (!defaultSettings->testAttribute(QWebEngineSettings::AutoLoadIconsForPage)) - faviconDownloadMode->setCurrentIndex(0); - else if (!defaultSettings->testAttribute(QWebEngineSettings::TouchIconsEnabled)) - faviconDownloadMode->setCurrentIndex(1); - else - faviconDownloadMode->setCurrentIndex(2); -} - -void SettingsDialog::loadFromSettings() -{ - QSettings settings; - settings.beginGroup(QLatin1String("MainWindow")); - const QString defaultHome = QLatin1String(BrowserMainWindow::defaultHome); - 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<QFont>(settings.value(QLatin1String("fixedFont"), fixedFont)); - standardFont = qvariant_cast<QFont>(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->setPlainText(settings.value(QLatin1String("userStyleSheet")).toString()); - enableScrollAnimator->setChecked(settings.value(QLatin1String("enableScrollAnimator"), enableScrollAnimator->isChecked()).toBool()); - httpUserAgent->setText(settings.value(QLatin1String("httpUserAgent"), httpUserAgent->text()).toString()); - httpAcceptLanguage->setText(settings.value(QLatin1String("httpAcceptLanguage"), httpAcceptLanguage->text()).toString()); - faviconDownloadMode->setCurrentIndex(settings.value(QLatin1String("faviconDownloadMode"), faviconDownloadMode->currentIndex()).toInt()); - settings.endGroup(); - - // Privacy - settings.beginGroup(QLatin1String("cookies")); - - int persistentCookiesPolicy = settings.value(QLatin1String("persistentCookiesPolicy"), sessionCookiesCombo->currentIndex()).toInt(); - sessionCookiesCombo->setCurrentIndex(persistentCookiesPolicy); - - QString pdataPath = settings.value(QLatin1String("persistentDataPath"), persistentDataPath->text()).toString(); - persistentDataPath->setText(pdataPath); - - 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(); -} - -void SettingsDialog::saveToSettings() -{ - 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()); - settings.setValue(QLatin1String("enableScrollAnimator"), enableScrollAnimator->isChecked()); - settings.setValue(QLatin1String("userStyleSheet"), userStyleSheet->toPlainText()); - settings.setValue(QLatin1String("httpUserAgent"), httpUserAgent->text()); - settings.setValue(QLatin1String("httpAcceptLanguage"), httpAcceptLanguage->text()); - settings.setValue(QLatin1String("faviconDownloadMode"), faviconDownloadMode->currentIndex()); - settings.endGroup(); - - //Privacy - settings.beginGroup(QLatin1String("cookies")); - - int persistentCookiesPolicy = sessionCookiesCombo->currentIndex(); - settings.setValue(QLatin1String("persistentCookiesPolicy"), persistentCookiesPolicy); - - QString pdataPath = persistentDataPath->text(); - settings.setValue(QLatin1String("persistentDataPath"), pdataPath); - - 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(); -#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) - BrowserApplication::cookieJar()->loadSettings(); -#endif - BrowserApplication::historyManager()->loadSettings(); -} - -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::on_httpUserAgent_editingFinished() -{ - QWebEngineProfile::defaultProfile()->setHttpUserAgent(httpUserAgent->text()); -} - -void SettingsDialog::on_httpAcceptLanguage_editingFinished() -{ - QWebEngineProfile::defaultProfile()->setHttpAcceptLanguage(httpAcceptLanguage->text()); -} - -void SettingsDialog::setHomeToCurrentPage() -{ - BrowserMainWindow *mw = static_cast<BrowserMainWindow*>(parent()); - WebView *webView = mw->currentTab(); - if (webView) - homeLineEdit->setText(webView->url().toString()); -} diff --git a/examples/webenginewidgets/demobrowser/settings.h b/examples/webenginewidgets/demobrowser/settings.h deleted file mode 100644 index ff5795609..000000000 --- a/examples/webenginewidgets/demobrowser/settings.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SETTINGS_H -#define SETTINGS_H - -#include <QtWidgets/QDialog> -#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(); - - void on_httpUserAgent_editingFinished(); - void on_httpAcceptLanguage_editingFinished(); - -private: - QFont standardFont; - QFont fixedFont; -}; - -#endif // SETTINGS_H diff --git a/examples/webenginewidgets/demobrowser/settings.ui b/examples/webenginewidgets/demobrowser/settings.ui deleted file mode 100644 index c78a52dfe..000000000 --- a/examples/webenginewidgets/demobrowser/settings.ui +++ /dev/null @@ -1,621 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>Settings</class> - <widget class="QDialog" name="Settings"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>657</width> - <height>336</height> - </rect> - </property> - <property name="windowTitle"> - <string>Settings</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="2" column="0"> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QTabWidget" name="tabWidget"> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="tab"> - <attribute name="title"> - <string>General</string> - </attribute> - <layout class="QGridLayout" name="gridLayout_4"> - <item row="1" column="2"> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>280</width> - <height>18</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Home:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="0" column="1" colspan="2"> - <widget class="QLineEdit" name="homeLineEdit"/> - </item> - <item row="7" column="1" colspan="2"> - <spacer> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>391</width> - <height>262</height> - </size> - </property> - </spacer> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_7"> - <property name="text"> - <string>Save downloads to:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_8"> - <property name="text"> - <string>Open links from applications:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="6" column="1" colspan="2"> - <widget class="QCheckBox" name="enableScrollAnimator"> - <property name="text"> - <string>Enable Scroll Animator</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="4" column="1" colspan="2"> - <widget class="QComboBox" name="openLinksIn"> - <item> - <property name="text"> - <string>In a tab in the current window</string> - </property> - </item> - <item> - <property name="text"> - <string>In a new window</string> - </property> - </item> - </widget> - </item> - <item row="2" column="1" colspan="2"> - <widget class="QComboBox" name="expireHistory"> - <item> - <property name="text"> - <string>After one day</string> - </property> - </item> - <item> - <property name="text"> - <string>After one week</string> - </property> - </item> - <item> - <property name="text"> - <string>After two weeks</string> - </property> - </item> - <item> - <property name="text"> - <string>After one month</string> - </property> - </item> - <item> - <property name="text"> - <string>After one year</string> - </property> - </item> - <item> - <property name="text"> - <string>Manually</string> - </property> - </item> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>Remove history items:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="3" column="1" colspan="2"> - <widget class="QLineEdit" name="downloadsLocation"/> - </item> - <item row="1" column="1"> - <widget class="QPushButton" name="setHomeToCurrentPageButton"> - <property name="text"> - <string>Set to current page</string> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QLabel" name="label_17"> - <property name="text"> - <string>Favicon download mode:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="5" column="1" colspan="2"> - <widget class="QComboBox" name="faviconDownloadMode"> - <property name="currentIndex"> - <number>1</number> - </property> - <item> - <property name="text"> - <string>Disable icons</string> - </property> - </item> - <item> - <property name="text"> - <string>Enable favicons</string> - </property> - </item> - <item> - <property name="text"> - <string>Enable favicons and touch icons</string> - </property> - </item> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="tab_3"> - <attribute name="title"> - <string>Appearance</string> - </attribute> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="0" column="0"> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>Standard font:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLabel" name="standardLabel"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="frameShape"> - <enum>QFrame::StyledPanel</enum> - </property> - <property name="text"> - <string>Times 16</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QPushButton" name="standardFontButton"> - <property name="text"> - <string>Select...</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_6"> - <property name="text"> - <string>Fixed-width font:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLabel" name="fixedLabel"> - <property name="frameShape"> - <enum>QFrame::StyledPanel</enum> - </property> - <property name="text"> - <string>Courier 13</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QPushButton" name="fixedFontButton"> - <property name="text"> - <string>Select...</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>93</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - <widget class="QWidget" name="tab_2"> - <attribute name="title"> - <string>Privacy</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <widget class="QGroupBox" name="groupBox"> - <property name="title"> - <string>Web Content</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QCheckBox" name="enablePlugins"> - <property name="text"> - <string>Enable Plugins</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="enableJavascript"> - <property name="text"> - <string>Enable Javascript</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="cookiesGroupBox"> - <property name="title"> - <string>Cookies</string> - </property> - <layout class="QGridLayout"> - <property name="leftMargin"> - <number>9</number> - </property> - <item row="0" column="0"> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Persistent Cookie Policy</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QComboBox" name="sessionCookiesCombo"> - <item> - <property name="text"> - <string>Treat all cookies as session cookies</string> - </property> - </item> - <item> - <property name="text"> - <string>Allow persistent cookies</string> - </property> - </item> - <item> - <property name="text"> - <string>Treat all cookies as persistent cookies</string> - </property> - </item> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Persistent Data Path:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="persistentDataPath"/> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacer_4"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - <widget class="QWidget" name="tab_4"> - <attribute name="title"> - <string>Proxy</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QGroupBox" name="proxySupport"> - <property name="title"> - <string>Enable proxy</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <layout class="QGridLayout" name="gridLayout_6"> - <item row="0" column="0"> - <widget class="QLabel" name="label_9"> - <property name="text"> - <string>Type:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="0" column="1" colspan="2"> - <widget class="QComboBox" name="proxyType"> - <item> - <property name="text"> - <string>Socks5</string> - </property> - </item> - <item> - <property name="text"> - <string>Http</string> - </property> - </item> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_10"> - <property name="text"> - <string>Host:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="1" column="1" colspan="2"> - <widget class="QLineEdit" name="proxyHostName"/> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_11"> - <property name="text"> - <string>Port:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QSpinBox" name="proxyPort"> - <property name="maximum"> - <number>10000</number> - </property> - <property name="value"> - <number>1080</number> - </property> - </widget> - </item> - <item row="2" column="2"> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>293</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_12"> - <property name="text"> - <string>User Name:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="3" column="1" colspan="2"> - <widget class="QLineEdit" name="proxyUserName"/> - </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_13"> - <property name="text"> - <string>Password:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="4" column="1" colspan="2"> - <widget class="QLineEdit" name="proxyPassword"> - <property name="echoMode"> - <enum>QLineEdit::Password</enum> - </property> - </widget> - </item> - <item row="5" column="0"> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>8</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="tab_5"> - <attribute name="title"> - <string>Advanced</string> - </attribute> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0"> - <widget class="QLabel" name="label_15"> - <property name="text"> - <string>HTTP User-Agent:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="httpUserAgent"/> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_16"> - <property name="text"> - <string>HTTP Accept-&Language:</string> - </property> - <property name="buddy"> - <cstring>httpAcceptLanguage</cstring> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="httpAcceptLanguage"/> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_14"> - <property name="text"> - <string>Style Sheet:</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QTextEdit" name="userStyleSheet"/> - </item> - <item row="3" column="1"> - <spacer name="verticalSpacer_3"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>176</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>Settings</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>Settings</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/examples/webenginewidgets/demobrowser/squeezelabel.cpp b/examples/webenginewidgets/demobrowser/squeezelabel.cpp deleted file mode 100644 index 9607bb784..000000000 --- a/examples/webenginewidgets/demobrowser/squeezelabel.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#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/demobrowser/squeezelabel.h b/examples/webenginewidgets/demobrowser/squeezelabel.h deleted file mode 100644 index 8acd1fb6e..000000000 --- a/examples/webenginewidgets/demobrowser/squeezelabel.h +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SQUEEZELABEL_H -#define SQUEEZELABEL_H - -#include <QtWidgets/QLabel> - -class SqueezeLabel : public QLabel -{ - Q_OBJECT - -public: - SqueezeLabel(QWidget *parent = 0); - -protected: - void paintEvent(QPaintEvent *event); - -}; - -#endif // SQUEEZELABEL_H diff --git a/examples/webenginewidgets/demobrowser/tabwidget.cpp b/examples/webenginewidgets/demobrowser/tabwidget.cpp deleted file mode 100644 index aa730d1b6..000000000 --- a/examples/webenginewidgets/demobrowser/tabwidget.cpp +++ /dev/null @@ -1,1012 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "tabwidget.h" - -#include "browserapplication.h" -#include "browsermainwindow.h" -#include "downloadmanager.h" -#include "fullscreennotification.h" -#include "history.h" -#include "savepagedialog.h" -#include "urllineedit.h" -#include "webview.h" - -#include <QWebEngineDownloadItem> -#include <QWebEngineProfile> -#include <QWebEngineFullScreenRequest> -#include <QtCore/QMimeData> -#include <QtGui/QClipboard> -#include <QtWidgets/QCompleter> -#include <QtWidgets/QListView> -#include <QtWidgets/QMenu> -#include <QtWidgets/QMessageBox> -#include <QtGui/QDrag> -#include <QtGui/QMouseEvent> -#include <QtWidgets/QStackedWidget> -#include <QtWidgets/QStyle> -#include <QtWidgets/QToolButton> - -#include <QtCore/QDebug> - -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) { - QShortcut *shortCut = new QShortcut(ctrl.arg(i), 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<QShortcut*>(sender())) { - int index = m_tabShortcuts.indexOf(shortCut); - 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); - - // Audio mute / unmute. - action = menu.addAction(tr("Mute tab"), - this, SLOT(muteTab())); - action->setData(index); - - action = menu.addAction(tr("Unmute tab"), - this, SLOT(unmuteTab())); - 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<QAction*>(sender())) { - int index = action->data().toInt(); - emit cloneTab(index); - } -} - -void TabBar::closeTab() -{ - if (QAction *action = qobject_cast<QAction*>(sender())) { - int index = action->data().toInt(); - emit closeTab(index); - } -} - -void TabBar::closeOtherTabs() -{ - if (QAction *action = qobject_cast<QAction*>(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); - - // Middle click on tab should close it. - if (event->button() == Qt::MiddleButton) { - const QPoint pos = event->pos(); - int index = tabAt(pos); - if (index != -1) { - emit closeTab(index); - } - } -} - -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<QUrl> 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<WebView*>(widget)) - tab->reload(); -} - -void TabBar::reloadTab() -{ - if (QAction *action = qobject_cast<QAction*>(sender())) { - int index = action->data().toInt(); - emit reloadTab(index); - } -} - -void TabBar::muteTab() -{ - if (QAction *action = qobject_cast<QAction*>(sender())) { - int index = action->data().toInt(); - emit muteTab(index, true); - } -} - -void TabBar::unmuteTab() -{ - if (QAction *action = qobject_cast<QAction*>(sender())) { - int index = action->data().toInt(); - emit muteTab(index, false); - } -} - -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)) - , m_profile(QWebEngineProfile::defaultProfile()) - , m_fullScreenView(0) - , m_fullScreenNotification(0) -{ - setElideMode(Qt::ElideRight); - - connect(m_tabBar, SIGNAL(newTab()), this, SLOT(newTab())); - connect(m_tabBar, SIGNAL(closeTab(int)), this, SLOT(requestCloseTab(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))); - connect(m_tabBar, SIGNAL(tabBarDoubleClicked(int)), this, SLOT(handleTabBarDoubleClicked(int))); - connect(m_tabBar, SIGNAL(muteTab(int,bool)), this, SLOT(setAudioMutedForTab(int,bool))); - 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(requestCloseTab())); - - m_nextTabAction = new QAction(tr("Show Next Tab"), this); - QList<QKeySequence> 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); -} - -TabWidget::~TabWidget() -{ - if (m_fullScreenView) - delete m_fullScreenView; -} - -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::setAudioMutedForTab(int index, bool mute) -{ - if (index < 0) - index = currentIndex(); - if (index < 0 || index >= count()) - return; - - QWidget *widget = this->widget(index); - if (WebView *tab = qobject_cast<WebView*>(widget)) - tab->page()->setAudioMuted(mute); -} - -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) { -#if defined(QWEBENGINEVIEW_STATUSBARMESSAGE) - disconnect(oldWebView, SIGNAL(statusBarMessage(QString)), - this, SIGNAL(showStatusBarMessage(QString))); -#endif - disconnect(oldWebView->page(), SIGNAL(linkHovered(const QString&)), - this, SIGNAL(linkHovered(const QString&))); - disconnect(oldWebView, SIGNAL(loadProgress(int)), - this, SIGNAL(loadProgress(int))); - disconnect(oldWebView->page()->profile(), SIGNAL(downloadRequested(QWebEngineDownloadItem*)), - this, SLOT(downloadRequested(QWebEngineDownloadItem*))); - disconnect(oldWebView->page(), SIGNAL(fullScreenRequested(QWebEngineFullScreenRequest)), - this, SLOT(fullScreenRequested(QWebEngineFullScreenRequest))); - } - -#if defined(QWEBENGINEVIEW_STATUSBARMESSAGE) - connect(webView, SIGNAL(statusBarMessage(QString)), - this, SIGNAL(showStatusBarMessage(QString))); -#endif - connect(webView->page(), SIGNAL(linkHovered(const QString&)), - this, SIGNAL(linkHovered(const QString&))); - connect(webView, SIGNAL(loadProgress(int)), - this, SIGNAL(loadProgress(int))); - connect(webView->page()->profile(), SIGNAL(downloadRequested(QWebEngineDownloadItem*)), - this, SLOT(downloadRequested(QWebEngineDownloadItem*))); - connect(webView->page(), SIGNAL(fullScreenRequested(QWebEngineFullScreenRequest)), - this, SLOT(fullScreenRequested(QWebEngineFullScreenRequest))); - - 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(); -} - -void TabWidget::fullScreenRequested(QWebEngineFullScreenRequest request) -{ - WebPage *webPage = qobject_cast<WebPage*>(sender()); - if (request.toggleOn()) { - if (!m_fullScreenView) { - m_fullScreenView = new QWebEngineView(); - m_fullScreenNotification = new FullScreenNotification(m_fullScreenView); - - QAction *exitFullScreenAction = new QAction(m_fullScreenView); - exitFullScreenAction->setShortcut(Qt::Key_Escape); - connect(exitFullScreenAction, &QAction::triggered, [webPage] { - webPage->triggerAction(QWebEnginePage::ExitFullScreen); - }); - m_fullScreenView->addAction(exitFullScreenAction); - } - m_oldWindowGeometry = window()->geometry(); - m_fullScreenView->setGeometry(m_oldWindowGeometry); - webPage->setView(m_fullScreenView); - request.accept(); - m_fullScreenView->showFullScreen(); - m_fullScreenNotification->show(); - window()->hide(); - } else { - if (!m_fullScreenView) - return; - WebView *oldWebView = this->webView(m_lineEdits->currentIndex()); - webPage->setView(oldWebView); - request.accept(); - delete m_fullScreenView; - m_fullScreenView = 0; - window()->show(); - window()->setGeometry(m_oldWindowGeometry); - } -} - -void TabWidget::handleTabBarDoubleClicked(int index) -{ - if (index != -1) return; - newTab(); -} - -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<UrlLineEdit*>(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<WebView*>(widget)) { - return webView; - } else { - // optimization to delay creating the first webview - if (count() == 1) { - TabWidget *that = const_cast<TabWidget*>(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; -} - -void TabWidget::setupPage(QWebEnginePage* page) -{ - connect(page, SIGNAL(windowCloseRequested()), - this, SLOT(windowCloseRequested())); - connect(page, SIGNAL(geometryChangeRequested(QRect)), - this, SIGNAL(geometryChangeRequested(QRect))); -#if defined(QWEBENGINEPAGE_PRINTREQUESTED) - connect(page, SIGNAL(printRequested(QWebEngineFrame*)), - this, SIGNAL(printRequested(QWebEngineFrame*))); -#endif -#if defined(QWEBENGINEPAGE_MENUBARVISIBILITYCHANGEREQUESTED) - connect(page, SIGNAL(menuBarVisibilityChangeRequested(bool)), - this, SIGNAL(menuBarVisibilityChangeRequested(bool))); -#endif -#if defined(QWEBENGINEPAGE_STATUSBARVISIBILITYCHANGEREQUESTED) - connect(page, SIGNAL(statusBarVisibilityChangeRequested(bool)), - this, SIGNAL(statusBarVisibilityChangeRequested(bool))); -#endif -#if defined(QWEBENGINEPAGE_TOOLBARVISIBILITYCHANGEREQUESTED) - connect(page, SIGNAL(toolBarVisibilityChangeRequested(bool)), - this, SIGNAL(toolBarVisibilityChangeRequested(bool))); -#endif - - // webview actions - for (int i = 0; i < m_actions.count(); ++i) { - WebActionMapper *mapper = m_actions[i]; - mapper->addChild(page->action(mapper->webAction())); - } -} - -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<QListView*>(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; - webView->setPage(new WebPage(m_profile, webView)); - urlLineEdit->setWebView(webView); - connect(webView, SIGNAL(loadStarted()), - this, SLOT(webViewLoadStarted())); - connect(webView, SIGNAL(iconChanged(QIcon)), - this, SLOT(webViewIconChanged(QIcon))); - connect(webView, SIGNAL(titleChanged(QString)), - this, SLOT(webViewTitleChanged(QString))); - connect(webView->page(), SIGNAL(audioMutedChanged(bool)), - this, SLOT(webPageMutedOrAudibleChanged())); - connect(webView->page(), SIGNAL(recentlyAudibleChanged(bool)), - this, SLOT(webPageMutedOrAudibleChanged())); - connect(webView, SIGNAL(urlChanged(QUrl)), - this, SLOT(webViewUrlChanged(QUrl))); - - - addTab(webView, tr("(Untitled)")); - if (makeCurrent) - setCurrentWidget(webView); - - setupPage(webView->page()); - - 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<WebView*>(tabWidget)) { - tab->reload(); - } - } -} - -void TabWidget::lineEditReturnPressed() -{ - if (QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender())) { - emit loadPage(lineEdit->text()); - if (m_lineEdits->currentWidget() == lineEdit) - currentWebView()->setFocus(); - } -} - -void TabWidget::windowCloseRequested() -{ - WebPage *webPage = qobject_cast<WebPage*>(sender()); - WebView *webView = qobject_cast<WebView*>(webPage->view()); - int index = webViewIndex(webView); - if (index >= 0) - 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::requestCloseTab(int index) -{ - if (index < 0) - index = currentIndex(); - if (index < 0 || index >= count()) - return; - WebView *tab = webView(index); - if (!tab) - return; - tab->page()->triggerAction(QWebEnginePage::RequestClose); -} - -void TabWidget::closeTab(int index) -{ - if (index < 0 || index >= count()) - return; - - bool hasFocus = false; - if (WebView *tab = webView(index)) { - hasFocus = tab->hasFocus(); - - if (m_profile == QWebEngineProfile::defaultProfile()) { - 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::setProfile(QWebEngineProfile *profile) -{ - m_profile = profile; - for (int i = 0; i < count(); ++i) { - QWidget *tabWidget = widget(i); - if (WebView *tab = qobject_cast<WebView*>(tabWidget)) { - WebPage* webPage = new WebPage(m_profile, tab); - setupPage(webPage); - webPage->load(tab->page()->url()); - tab->setPage(webPage); - } - } -} - -void TabWidget::webViewLoadStarted() -{ - WebView *webView = qobject_cast<WebView*>(sender()); - int index = webViewIndex(webView); - if (-1 != index) { - QIcon icon(QLatin1String(":loading.gif")); - setTabIcon(index, icon); - } -} - -void TabWidget::webViewIconChanged(const QIcon &icon) -{ - WebView *webView = qobject_cast<WebView*>(sender()); - int index = webViewIndex(webView); - if (-1 != index) - setTabIcon(index, icon); -} - -void TabWidget::webViewTitleChanged(const QString &title) -{ - WebView *webView = qobject_cast<WebView*>(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::webPageMutedOrAudibleChanged() { - QWebEnginePage* webPage = qobject_cast<QWebEnginePage*>(sender()); - WebView *webView = qobject_cast<WebView*>(webPage->view()); - - int index = webViewIndex(webView); - if (-1 != index) { - QString title = webView->title(); - - bool muted = webPage->isAudioMuted(); - bool audible = webPage->recentlyAudible(); - if (muted) title += tr(" (muted)"); - else if (audible) title += tr(" (audible)"); - - setTabText(index, title); - } -} - -void TabWidget::webViewUrlChanged(const QUrl &url) -{ - WebView *webView = qobject_cast<WebView*>(sender()); - int index = webViewIndex(webView); - if (-1 != index) { - m_tabBar->setTabData(index, url); - HistoryManager *manager = BrowserApplication::historyManager(); - if (url.isValid()) - manager->addHistoryEntry(url.toString()); - } - 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<WebView*>(widget(i))) { - tabs.append(tab->url().toString()); - } else { - tabs.append(QString()); - } - } - 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; -} - -void TabWidget::downloadRequested(QWebEngineDownloadItem *download) -{ - if (download->savePageFormat() != QWebEngineDownloadItem::UnknownSaveFormat) { - SavePageDialog dlg(this, download->savePageFormat(), download->path()); - if (dlg.exec() != SavePageDialog::Accepted) - return; - download->setSavePageFormat(dlg.pageFormat()); - download->setPath(dlg.filePath()); - } - - BrowserApplication::downloadManager()->download(download); - download->accept(); -} - -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<QAction*>(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/demobrowser/tabwidget.h b/examples/webenginewidgets/demobrowser/tabwidget.h deleted file mode 100644 index 82dcf960d..000000000 --- a/examples/webenginewidgets/demobrowser/tabwidget.h +++ /dev/null @@ -1,263 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TABWIDGET_H -#define TABWIDGET_H - -#include <QtWebEngineWidgets/QWebEngineFullScreenRequest> -#include <QtWidgets/QTabBar> -#include <QtWidgets/QShortcut> - -QT_BEGIN_NAMESPACE -class QWebEngineDownloadItem; -class QWebEngineProfile; -class QWebEngineView; -QT_END_NAMESPACE - -/* - 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 muteTab(int index, bool mute); - 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 muteTab(); - void unmuteTab(); - void contextMenuRequested(const QPoint &position); - -private: - QList<QShortcut*> m_tabShortcuts; - friend class TabWidget; - - QPoint m_dragStartPos; - int m_dragCurrentIndex; -}; - -#include <QWebEnginePage> - -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 <QtCore/QUrl> -#include <QtWidgets/QTabWidget> - -class FullScreenNotification; - -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); -#if defined(QWEBENGINEPAGE_PRINTREQUESTED) - void printRequested(QWebEngineFrame *frame); -#endif - -public: - TabWidget(QWidget *parent = 0); - ~TabWidget(); - 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); - - void setProfile(QWebEngineProfile *profile); - -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 requestCloseTab(int index = -1); - void closeTab(int index); - void closeOtherTabs(int index); - void reloadTab(int index = -1); - void reloadAllTabs(); - void nextTab(); - void previousTab(); - void setAudioMutedForTab(int index, bool mute); - -private slots: - void currentChanged(int index); - void aboutToShowRecentTabsMenu(); - void aboutToShowRecentTriggeredAction(QAction *action); - void downloadRequested(QWebEngineDownloadItem *download); - void webViewLoadStarted(); - void webViewIconChanged(const QIcon &icon); - void webViewTitleChanged(const QString &title); - void webViewUrlChanged(const QUrl &url); - void lineEditReturnPressed(); - void windowCloseRequested(); - void moveTab(int fromIndex, int toIndex); - void fullScreenRequested(QWebEngineFullScreenRequest request); - void handleTabBarDoubleClicked(int index); - void webPageMutedOrAudibleChanged(); - -private: - void setupPage(QWebEnginePage* page); - - 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<QUrl> m_recentlyClosedTabs; - QList<WebActionMapper*> m_actions; - - QCompleter *m_lineEditCompleter; - QStackedWidget *m_lineEdits; - TabBar *m_tabBar; - QWebEngineProfile *m_profile; - QWebEngineView *m_fullScreenView; - FullScreenNotification *m_fullScreenNotification; - QRect m_oldWindowGeometry; -}; - -#endif // TABWIDGET_H diff --git a/examples/webenginewidgets/demobrowser/toolbarsearch.cpp b/examples/webenginewidgets/demobrowser/toolbarsearch.cpp deleted file mode 100644 index 41c5ef314..000000000 --- a/examples/webenginewidgets/demobrowser/toolbarsearch.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "toolbarsearch.h" -#include "autosaver.h" -#include "browserapplication.h" - -#include <QtCore/QSettings> -#include <QtCore/QUrl> -#include <QtCore/QUrlQuery> - -#include <QtWidgets/QCompleter> -#include <QtWidgets/QMenu> -#include <QtCore/QStringListModel> - -#include <QWebEngineSettings> - -/* - 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 (!BrowserApplication::instance()->privateBrowsing()) { - 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>()) { - QString text = v.toString(); - lineEdit()->setText(text); - searchNow(); - } -} - -void ToolbarSearch::clear() -{ - m_stringListModel->setStringList(QStringList()); - m_autosaver->changeOccurred();; -} diff --git a/examples/webenginewidgets/demobrowser/toolbarsearch.h b/examples/webenginewidgets/demobrowser/toolbarsearch.h deleted file mode 100644 index d3e914055..000000000 --- a/examples/webenginewidgets/demobrowser/toolbarsearch.h +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#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/demobrowser/urllineedit.cpp b/examples/webenginewidgets/demobrowser/urllineedit.cpp deleted file mode 100644 index 8203e4f0f..000000000 --- a/examples/webenginewidgets/demobrowser/urllineedit.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "urllineedit.h" - -#include "browserapplication.h" -#include "searchlineedit.h" -#include "webview.h" - -#include <QtCore/QEvent> -#include <QtCore/QMimeData> - -#include <QtWidgets/QApplication> -#include <QtWidgets/QCompleter> -#include <QtGui/QFocusEvent> -#include <QtWidgets/QHBoxLayout> -#include <QtWidgets/QLabel> -#include <QtWidgets/QLineEdit> -#include <QtGui/QDrag> -#include <QtGui/QPainter> -#include <QtWidgets/QStyle> -#include <QtWidgets/QStyleOptionFrame> - -#include <QtCore/QDebug> - -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() -{ - QStyleOptionFrame 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(QStyleOptionFrame *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 = QStyleOptionFrame::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); - QStyleOptionFrame 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<QUrl> 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); -} - -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(iconChanged(QIcon)), - this, SLOT(webViewIconChanged(QIcon))); - 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(const QIcon &icon) -{ - Q_ASSERT(m_webView); - m_iconLabel->setPixmap(icon.pixmap(16, 16)); -} - -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); - QStyleOptionFrame 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.0f * progress; - QRect progressRect(backgroundRect.x(), backgroundRect.y(), mid, backgroundRect.height()); - painter.drawRect(progressRect); - } -} diff --git a/examples/webenginewidgets/demobrowser/urllineedit.h b/examples/webenginewidgets/demobrowser/urllineedit.h deleted file mode 100644 index 51c5c0836..000000000 --- a/examples/webenginewidgets/demobrowser/urllineedit.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef URLLINEEDIT_H -#define URLLINEEDIT_H - -#include <QtCore/QUrl> -#include <QtWidgets/QWidget> -#include <QtWidgets/QStyleOptionFrame> - -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(QStyleOptionFrame *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(const QIcon &icon); - -private: - QLinearGradient generateGradient(const QColor &color) const; - WebView *m_webView; - UrlIconLabel *m_iconLabel; - QColor m_defaultBaseColor; - -}; - - -#endif // URLLINEEDIT_H diff --git a/examples/webenginewidgets/demobrowser/webview.cpp b/examples/webenginewidgets/demobrowser/webview.cpp deleted file mode 100644 index ce273c0f6..000000000 --- a/examples/webenginewidgets/demobrowser/webview.cpp +++ /dev/null @@ -1,468 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "browserapplication.h" -#include "browsermainwindow.h" -#include "cookiejar.h" -#include "downloadmanager.h" -#include "featurepermissionbar.h" -#include "ui_passworddialog.h" -#include "ui_proxy.h" -#include "tabwidget.h" -#include "webview.h" - -#include <QtGui/QClipboard> -#include <QtNetwork/QAuthenticator> -#include <QtNetwork/QNetworkReply> -#include <QtWidgets/QMenu> -#include <QtWidgets/QMessageBox> -#include <QtGui/QMouseEvent> - -#include <QWebEngineContextMenuData> - -#ifndef QT_NO_UITOOLS -#include <QtUiTools/QUiLoader> -#endif //QT_NO_UITOOLS - -#include <QtCore/QDebug> -#include <QtCore/QBuffer> -#include <QtCore/QTimer> - -WebPage::WebPage(QWebEngineProfile *profile, QObject *parent) - : QWebEnginePage(profile, parent) - , m_keyboardModifiers(Qt::NoModifier) - , m_pressedButtons(Qt::NoButton) -{ -#if defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER) - setNetworkAccessManager(BrowserApplication::networkAccessManager()); -#endif -#if defined(QWEBENGINEPAGE_UNSUPPORTEDCONTENT) - connect(this, SIGNAL(unsupportedContent(QNetworkReply*)), - this, SLOT(handleUnsupportedContent(QNetworkReply*))); -#endif - 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<BrowserMainWindow*>(w)) - return mw; - w = w->parent(); - } - return BrowserApplication::instance()->mainWindow(); -} - -bool WebPage::certificateError(const QWebEngineCertificateError &error) -{ - if (error.isOverridable()) { - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Warning); - msgBox.setText(error.errorDescription()); - msgBox.setInformativeText(tr("If you wish so, you may continue with an unverified certificate. " - "Accepting an unverified certificate means " - "you may not be connected with the host you tried to connect to.\n" - "Do you wish to override the security check and continue?")); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - return msgBox.exec() == QMessageBox::Yes; - } - QMessageBox::critical(view(), tr("Certificate Error"), error.errorDescription(), QMessageBox::Ok, QMessageBox::NoButton); - return false; -} - -class PopupWindow : public QWidget { - Q_OBJECT -public: - PopupWindow(QWebEngineProfile *profile) - : m_addressBar(new QLineEdit(this)) - , m_view(new WebView(this)) - { - m_view->setPage(new WebPage(profile, m_view)); - 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 (type == QWebEnginePage::WebBrowserTab) { - return mainWindow()->tabWidget()->newTab()->page(); - } else if (type == QWebEnginePage::WebBrowserBackgroundTab) { - return mainWindow()->tabWidget()->newTab(false)->page(); - } else if (type == QWebEnginePage::WebBrowserWindow) { - BrowserApplication::instance()->newMainWindow(); - BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow(); - return mainWindow->currentTab()->page(); - } else { - PopupWindow *popup = new PopupWindow(profile()); - 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) - -#if defined(QWEBENGINEPAGE_UNSUPPORTEDCONTENT) -void WebPage::handleUnsupportedContent(QNetworkReply *reply) -{ - 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<QWebEngineFrame*> frames; - frames.append(mainFrame()); - while (!frames.isEmpty()) { - QWebEngineFrame *frame = frames.takeFirst(); - if (frame->url() == reply->url()) { - frame->setHtml(html, reply->url()); - return; - } - QList<QWebEngineFrame *> 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("<qt>Enter username and password for \"%1\" at %2</qt>"); - 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()); - } else { - // Set authenticator null if dialog is cancelled - *auth = QAuthenticator(); - } -} - -void WebPage::proxyAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth, const QString &proxyHost) -{ - Q_UNUSED(requestUrl); - 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("<qt>Connect to proxy \"%1\" using:</qt>"); - 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()); - } else { - // Set authenticator null if dialog is cancelled - *auth = QAuthenticator(); - } -} - -WebView::WebView(QWidget* parent) - : QWebEngineView(parent) - , m_progress(0) - , m_page(0) -{ - connect(this, SIGNAL(loadProgress(int)), - this, SLOT(setProgress(int))); - connect(this, SIGNAL(loadFinished(bool)), - this, SLOT(loadFinished(bool))); - connect(this, &QWebEngineView::renderProcessTerminated, - [=](QWebEnginePage::RenderProcessTerminationStatus termStatus, int statusCode) { - const char *status = ""; - switch (termStatus) { - case QWebEnginePage::NormalTerminationStatus: - status = "(normal exit)"; - break; - case QWebEnginePage::AbnormalTerminationStatus: - status = "(abnormal exit)"; - break; - case QWebEnginePage::CrashedTerminationStatus: - status = "(crashed)"; - break; - case QWebEnginePage::KilledTerminationStatus: - status = "(killed)"; - break; - } - - qInfo() << "Render process exited with code" << statusCode << status; - QTimer::singleShot(0, [this] { reload(); }); - }); -} - -void WebView::setPage(WebPage *_page) -{ - m_page = _page; - QWebEngineView::setPage(_page); -#if defined(QWEBENGINEPAGE_STATUSBARMESSAGE) - connect(page(), SIGNAL(statusBarMessage(QString)), - SLOT(setStatusBarText(QString))); -#endif - disconnect(page(), &QWebEnginePage::iconChanged, this, &WebView::iconChanged); - connect(page(), SIGNAL(iconChanged(QIcon)), - this, SLOT(onIconChanged(QIcon))); - connect(page(), &WebPage::featurePermissionRequested, this, &WebView::onFeaturePermissionRequested); -#if defined(QWEBENGINEPAGE_UNSUPPORTEDCONTENT) - page()->setForwardUnsupportedContent(true); -#endif -} - -void WebView::contextMenuEvent(QContextMenuEvent *event) -{ - QMenu *menu; - if (page()->contextMenuData().linkUrl().isValid()) { - menu = new QMenu(this); - menu->setAttribute(Qt::WA_DeleteOnClose, true); - menu->addAction(page()->action(QWebEnginePage::OpenLinkInThisWindow)); - menu->addAction(page()->action(QWebEnginePage::OpenLinkInNewWindow)); - menu->addAction(page()->action(QWebEnginePage::OpenLinkInNewTab)); - menu->addAction(page()->action(QWebEnginePage::OpenLinkInNewBackgroundTab)); - menu->addSeparator(); - menu->addAction(page()->action(QWebEnginePage::DownloadLinkToDisk)); - menu->addAction(page()->action(QWebEnginePage::CopyLinkToClipboard)); - } else { - menu = page()->createStandardContextMenu(); - } - if (page()->contextMenuData().selectedText().isEmpty()) - menu->addAction(page()->action(QWebEnginePage::SavePage)); - menu->popup(event->globalPos()); -} - -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::onFeaturePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature feature) -{ - FeaturePermissionBar *permissionBar = new FeaturePermissionBar(this); - connect(permissionBar, &FeaturePermissionBar::featurePermissionProvided, page(), &QWebEnginePage::setFeaturePermission); - - // Discard the bar on new loads (if we navigate away or reload). - connect(page(), &QWebEnginePage::loadStarted, permissionBar, &QObject::deleteLater); - - permissionBar->requestPermission(securityOrigin, feature); -} - -void WebView::setProgress(int progress) -{ - m_progress = progress; -} - -void WebView::loadFinished(bool success) -{ - if (success && 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::onIconChanged(const QIcon &icon) -{ - if (icon.isNull()) - emit iconChanged(BrowserApplication::instance()->defaultIcon()); - else - emit iconChanged(icon); -} - -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; -} diff --git a/examples/webenginewidgets/demobrowser/webview.h b/examples/webenginewidgets/demobrowser/webview.h deleted file mode 100644 index 7531254d6..000000000 --- a/examples/webenginewidgets/demobrowser/webview.h +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef WEBVIEW_H -#define WEBVIEW_H - -#include <QIcon> -#include <QWebEngineView> - -QT_BEGIN_NAMESPACE -class QAuthenticator; -class QMouseEvent; -class QNetworkProxy; -class QNetworkReply; -class QSslError; -QT_END_NAMESPACE - -class BrowserMainWindow; -class WebPage : public QWebEnginePage { - Q_OBJECT -public: - WebPage(QWebEngineProfile *profile, QObject *parent = 0); - BrowserMainWindow *mainWindow(); - -protected: - QWebEnginePage *createWindow(QWebEnginePage::WebWindowType type) Q_DECL_OVERRIDE; -#if !defined(QT_NO_UITOOLS) - QObject *createPlugin(const QString &classId, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues); -#endif - virtual bool certificateError(const QWebEngineCertificateError &error) Q_DECL_OVERRIDE; - -private slots: -#if defined(QWEBENGINEPAGE_UNSUPPORTEDCONTENT) - void handleUnsupportedContent(QNetworkReply *reply); -#endif - 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; -}; - -class WebView : public QWebEngineView { - Q_OBJECT - -public: - WebView(QWidget *parent = 0); - WebPage *webPage() const { return m_page; } - void setPage(WebPage *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(bool success); - void setStatusBarText(const QString &string); - void onFeaturePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature); - void onIconChanged(const QIcon &icon); - -private: - QString m_statusBarText; - QUrl m_initialUrl; - int m_progress; - WebPage *m_page; -}; - -#endif diff --git a/examples/webenginewidgets/demobrowser/xbel.cpp b/examples/webenginewidgets/demobrowser/xbel.cpp deleted file mode 100644 index d66c44faa..000000000 --- a/examples/webenginewidgets/demobrowser/xbel.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "xbel.h" - -#include <QtCore/QFile> - -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 *> 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("<!DOCTYPE xbel>")); - 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/demobrowser/xbel.h b/examples/webenginewidgets/demobrowser/xbel.h deleted file mode 100644 index 89f5e259f..000000000 --- a/examples/webenginewidgets/demobrowser/xbel.h +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the demonstration applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef XBEL_H -#define XBEL_H - -#include <QtCore/QXmlStreamReader> -#include <QtCore/QDateTime> - -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<BookmarkNode *> 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<BookmarkNode *> 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 <QtCore/QXmlStreamWriter> - -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/simplebrowser/tabwidget.cpp b/examples/webenginewidgets/simplebrowser/tabwidget.cpp index c9fb32d83..3f02cd3d8 100644 --- a/examples/webenginewidgets/simplebrowser/tabwidget.cpp +++ b/examples/webenginewidgets/simplebrowser/tabwidget.cpp @@ -196,6 +196,9 @@ WebView *TabWidget::createBackgroundTab() setupView(webView); int index = addTab(webView, tr("(Untitled)")); setTabIcon(index, webView->favIcon()); + // Workaround for QTBUG-61770 + webView->resize(currentWidget()->size()); + webView->show(); return webView; } diff --git a/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc b/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc index b0240cd4d..b725f8317 100644 --- a/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc +++ b/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc @@ -75,15 +75,8 @@ about how to create \c dic and \c aff files, see the Hunspell dictionary file format specification in the \l{Hunspell Project}. - When a specific spellchecking language is requested, Qt WebEngine will try - to load the already compiled matching \c .bdic file first from - \e qtwebengine_dictionaries directories relative to the executable, - then it will look in \c QT_INSTALL_PREFIX/qtwebengine_dictionaries. - - On macOS, because this example was configured to use Hunspell dictionaries, Qt WebEngine will - look in the \e qtwebengine_dictionaries directory located inside the application bundle - \c Resources directory, and also in the \c Resources directory located inside the - Qt framework bundle. + See the \l {Spellchecker}{Spellchecker feature documentation} for how + dictionary files are searched. We specify the QMAKE_EXTRA_COMPILERS parameter in the project file to add a conversion step to the build process: diff --git a/examples/webenginewidgets/stylesheetbrowser/doc/images/stylesheetbrowser.png b/examples/webenginewidgets/stylesheetbrowser/doc/images/stylesheetbrowser.png Binary files differnew file mode 100644 index 000000000..32c7c43ed --- /dev/null +++ b/examples/webenginewidgets/stylesheetbrowser/doc/images/stylesheetbrowser.png diff --git a/examples/webenginewidgets/stylesheetbrowser/doc/src/stylesheetbrowser.qdoc b/examples/webenginewidgets/stylesheetbrowser/doc/src/stylesheetbrowser.qdoc new file mode 100644 index 000000000..c5506a623 --- /dev/null +++ b/examples/webenginewidgets/stylesheetbrowser/doc/src/stylesheetbrowser.qdoc @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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 webenginewidgets/stylesheetbrowser + \title WebEngine StyleSheet Browser Example + \ingroup webengine-widgetexamples + \brief Demonstrates how to inject CSS into web pages using user scripts + + \image stylesheetbrowser.png + + \e {StyleSheet Browser} demonstrates how to use the \l{Qt WebEngine Widgets C++ Classes} + {Qt WebEngine C++ classes} to inject user stylesheets into web pages. + + \include examples-run.qdocinc + + \section1 Working With Stylesheets + + We use JavaScript to create and append CSS elements to the documents. + After declaring the script source, QWebEnginePage::runJavaScript() can run it + immediately and apply newly created styles on the current content of the web view. + Encapsulating the script into a QWebEngineScript and adding it to the script collection + of QWebEnginePage makes its effect permanent. + + \quotefromfile webenginewidgets/stylesheetbrowser/mainwindow.cpp + \skipto MainWindow::insertStyleSheet + \printuntil /^\}/ + + Removing stylesheets can be done similarly: + + \quotefromfile webenginewidgets/stylesheetbrowser/mainwindow.cpp + \skipto MainWindow::removeStyleSheet + \printuntil /^\}/ +*/ diff --git a/examples/webenginewidgets/stylesheetbrowser/main.cpp b/examples/webenginewidgets/stylesheetbrowser/main.cpp new file mode 100644 index 000000000..c353a704b --- /dev/null +++ b/examples/webenginewidgets/stylesheetbrowser/main.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 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. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company 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 "mainwindow.h" +#include <QApplication> +#include <QUrl> + +int main(int argc, char *argv[]) +{ + QCoreApplication::setOrganizationName("The Qt Company"); + QCoreApplication::setOrganizationDomain("www.qt.io"); + QCoreApplication::setApplicationName("StyleSheet Browser"); + + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QApplication a(argc, argv); + MainWindow w(QUrl("http://qt.io")); + w.show(); + return a.exec(); +} diff --git a/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp b/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp new file mode 100644 index 000000000..01697e8e4 --- /dev/null +++ b/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 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. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company 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 "mainwindow.h" +#include "ui_mainwindow.h" + +#include "stylesheetdialog.h" + +MainWindow::MainWindow(const QUrl &url) : + QMainWindow(), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + + connect(ui->urlBar, &QLineEdit::returnPressed, this, &MainWindow::urlEntered); + connect(ui->webEngineView, &QWebEngineView::urlChanged, this, &MainWindow::urlChanged); + connect(ui->settingsButton, &QPushButton::clicked, this, &MainWindow::showStyleSheetsDialog); + connect(ui->reloadButton, &QPushButton::clicked, this, &MainWindow::reloadRequested); + + QSettings settings; + settings.beginGroup("styleSheets"); + QStringList styleSheets = settings.allKeys(); + for (auto name : qAsConst(styleSheets)) + insertStyleSheet(name, settings.value(name, QString()).toString(), false); + settings.endGroup(); + + ui->webEngineView->setUrl(url); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::insertStyleSheet(const QString &name, const QString &source, bool immediately) +{ + QWebEngineScript script; + QString s = QString::fromLatin1("(function() {"\ + " css = document.createElement('style');"\ + " css.type = 'text/css';"\ + " css.id = '%1';"\ + " document.head.appendChild(css);"\ + " css.innerText = '%2';"\ + "})()").arg(name).arg(source.simplified()); + if (immediately) + ui->webEngineView->page()->runJavaScript(s, QWebEngineScript::ApplicationWorld); + + script.setName(name); + script.setSourceCode(s); + script.setInjectionPoint(QWebEngineScript::DocumentReady); + script.setRunsOnSubFrames(true); + script.setWorldId(QWebEngineScript::ApplicationWorld); + ui->webEngineView->page()->scripts().insert(script); +} + +void MainWindow::removeStyleSheet(const QString &name, bool immediately) +{ + QString s = QString::fromLatin1("(function() {"\ + " var element = document.getElementById('%1');"\ + " element.outerHTML = '';"\ + " delete element;"\ + "})()").arg(name); + if (immediately) + ui->webEngineView->page()->runJavaScript(s, QWebEngineScript::ApplicationWorld); + + QWebEngineScript script = ui->webEngineView->page()->scripts().findScript(name); + ui->webEngineView->page()->scripts().remove(script); +} + +void MainWindow::urlEntered() +{ + ui->webEngineView->setUrl(QUrl::fromUserInput(ui->urlBar->text())); +} + +void MainWindow::urlChanged(const QUrl &url) +{ + ui->urlBar->setText(url.toString()); +} + +void MainWindow::showStyleSheetsDialog() +{ + StylesheetDialog *dialog = new StylesheetDialog(this); + dialog->show(); +} + +void MainWindow::reloadRequested() +{ + ui->webEngineView->reload(); +} diff --git a/examples/webenginewidgets/stylesheetbrowser/mainwindow.h b/examples/webenginewidgets/stylesheetbrowser/mainwindow.h new file mode 100644 index 000000000..a59cb882d --- /dev/null +++ b/examples/webenginewidgets/stylesheetbrowser/mainwindow.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 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. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company 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 MAINWINDOW_H +#define MAINWINDOW_H + +#include <QMainWindow> +#include <QSettings> +#include <QWebEngineScriptCollection> + +QT_BEGIN_NAMESPACE +namespace Ui { +class MainWindow; +} +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(const QUrl &url); + ~MainWindow(); + + void insertStyleSheet(const QString &name, const QString &source, bool immediately); + void removeStyleSheet(const QString &name, bool immediately); + +private slots: + void urlEntered(); + void urlChanged(const QUrl &url); + void showStyleSheetsDialog(); + void reloadRequested(); + +private: + Ui::MainWindow *ui; +}; + +#endif // MAINWINDOW_H diff --git a/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui b/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui new file mode 100644 index 000000000..f9c1af969 --- /dev/null +++ b/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>713</width> + <height>455</height> + </rect> + </property> + <property name="windowTitle"> + <string>StyleSheet Browser</string> + </property> + <property name="unifiedTitleAndToolBarOnMac"> + <bool>false</bool> + </property> + <widget class="QWidget" name="centralWidget"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QWidget" name="webContentsWidget" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QWidget" name="urlBarWidget" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLineEdit" name="urlBar"/> + </item> + <item> + <widget class="QPushButton" name="reloadButton"> + <property name="text"> + <string/> + </property> + <property name="shortcut"> + <string>Ctrl+R</string> + </property> + <property name="icon"> + <iconset resource="stylesheetbrowser.qrc"> + <normaloff>:/view-refresh.png</normaloff>:/view-refresh.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="settingsButton"> + <property name="text"> + <string>Settings</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QWebEngineView" name="webEngineView"> + <property name="url"> + <url> + <string>about:blank</string> + </url> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menuBar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>713</width> + <height>20</height> + </rect> + </property> + </widget> + </widget> + <layoutdefault spacing="6" margin="11"/> + <customwidgets> + <customwidget> + <class>QWebEngineView</class> + <extends>QWidget</extends> + <header location="global">QtWebEngineWidgets/QWebEngineView</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.pro b/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.pro new file mode 100644 index 000000000..c5f1080e3 --- /dev/null +++ b/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.pro @@ -0,0 +1,23 @@ +TEMPLATE = app +TARGET = stylesheetbrowser +QT += webenginewidgets +CONFIG += c++11 + +HEADERS += \ + mainwindow.h \ + stylesheetdialog.h + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + stylesheetdialog.cpp + +FORMS += \ + mainwindow.ui \ + stylesheetdialog.ui + +RESOURCES += stylesheetbrowser.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/stylesheetbrowser +INSTALLS += target diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.qrc b/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.qrc new file mode 100644 index 000000000..8805f2c53 --- /dev/null +++ b/examples/webenginewidgets/stylesheetbrowser/stylesheetbrowser.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>view-refresh.png</file> + </qresource> +</RCC> diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp new file mode 100644 index 000000000..65c50bfb3 --- /dev/null +++ b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 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. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company 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 "mainwindow.h" +#include "stylesheetdialog.h" +#include "ui_stylesheetdialog.h" + +StylesheetDialog::StylesheetDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::StylesheetDialog) +{ + ui->setupUi(this); + + connect(ui->styleSheetList, &QListWidget::currentItemChanged, this, &StylesheetDialog::currentStyleSheetChanged); + connect(ui->fileNameEdit, &QLineEdit::textChanged, this, &StylesheetDialog::fileNameChanged); + + connect(ui->addButton, &QPushButton::clicked, this, &StylesheetDialog::addButtonClicked); + connect(ui->removeButton, &QPushButton::clicked, this, &StylesheetDialog::removeButtonClicked); + + QSettings settings; + settings.beginGroup("styleSheets"); + for (auto name : settings.allKeys()) + new QListWidgetItem(name, ui->styleSheetList); + settings.endGroup(); +} + +StylesheetDialog::~StylesheetDialog() +{ + delete ui; +} + +void StylesheetDialog::currentStyleSheetChanged(QListWidgetItem *current, QListWidgetItem *previous) +{ + if (!previous) { + // Select the first item on startup + ui->styleSheetList->setCurrentItem(current); + } + + if (!current) { + ui->fileNameEdit->setText(QString()); + ui->sourceCodeEdit->setPlainText(QString()); + return; + } + + QSettings settings; + settings.beginGroup("styleSheets"); + ui->fileNameEdit->setText(current->text()); + ui->sourceCodeEdit->setPlainText(settings.value(current->text(), QString()).toString()); + settings.endGroup(); +} + +void StylesheetDialog::fileNameChanged(const QString &text) +{ + QList<QListWidgetItem *> items = ui->styleSheetList->findItems(text, Qt::MatchFixedString); + if (items.size()) + ui->addButton->setEnabled(false); + else + ui->addButton->setEnabled(true); +} + +void StylesheetDialog::addButtonClicked() +{ + new QListWidgetItem(ui->fileNameEdit->text(), ui->styleSheetList); + + MainWindow *window = static_cast<MainWindow *>(parent()); + const QString name = ui->fileNameEdit->text(); + const QString source = ui->sourceCodeEdit->toPlainText(); + window->insertStyleSheet(name, source, true); + + QSettings settings; + settings.beginGroup("styleSheets"); + settings.setValue(name, source); + settings.endGroup(); + + ui->addButton->setEnabled(false); +} + +void StylesheetDialog::removeButtonClicked() +{ + if (ui->styleSheetList->selectedItems().isEmpty()) + return; + + MainWindow *window = static_cast<MainWindow *>(parent()); + QSettings settings; + settings.beginGroup("styleSheets"); + + QListWidgetItem *item = ui->styleSheetList->selectedItems().first(); + const QString name = item->text(); + window->removeStyleSheet(name, true); + settings.remove(name); + delete item; + + settings.endGroup(); +} diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h new file mode 100644 index 000000000..0d6a01038 --- /dev/null +++ b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 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. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company 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 STYLESHEETDIALOG_H +#define STYLESHEETDIALOG_H + +#include <QDialog> +#include <QListWidgetItem> + +QT_BEGIN_NAMESPACE +namespace Ui { +class StylesheetDialog; +} +QT_END_NAMESPACE + +class StylesheetDialog : public QDialog +{ + Q_OBJECT + +public: + explicit StylesheetDialog(QWidget *parent = 0); + ~StylesheetDialog(); + +private slots: + void currentStyleSheetChanged(QListWidgetItem *current, QListWidgetItem *previous); + void fileNameChanged(const QString &text); + + void addButtonClicked(); + void removeButtonClicked(); + +private: + Ui::StylesheetDialog *ui; +}; + +#endif // STYLESHEETDIALOG_H diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.ui b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.ui new file mode 100644 index 000000000..3e70ce89a --- /dev/null +++ b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.ui @@ -0,0 +1,195 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>StylesheetDialog</class> + <widget class="QDialog" name="StylesheetDialog"> + <property name="windowModality"> + <enum>Qt::ApplicationModal</enum> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>547</width> + <height>431</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>547</width> + <height>431</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>547</width> + <height>431</height> + </size> + </property> + <property name="windowTitle"> + <string>Stylesheets</string> + </property> + <property name="modal"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QWidget" name="widget" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <widget class="QWidget" name="horizontalLayoutWidget"> + <property name="geometry"> + <rect> + <x>9</x> + <y>9</y> + <width>511</width> + <height>371</height> + </rect> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="sizeConstraint"> + <enum>QLayout::SetDefaultConstraint</enum> + </property> + <item> + <widget class="QListWidget" name="styleSheetList"/> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="fileNameLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Stylesheet name:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="fileNameEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="sourceLabel"> + <property name="text"> + <string>Source code:</string> + </property> + </widget> + </item> + <item> + <widget class="QPlainTextEdit" name="sourceCodeEdit"> + <property name="font"> + <font> + <family>Courier New</family> + <pointsize>10</pointsize> + </font> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QPushButton" name="addButton"> + <property name="text"> + <string>Add</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="removeButton"> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>StylesheetDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>StylesheetDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/examples/webenginewidgets/stylesheetbrowser/view-refresh.png b/examples/webenginewidgets/stylesheetbrowser/view-refresh.png Binary files differnew file mode 100644 index 000000000..cab4d02c7 --- /dev/null +++ b/examples/webenginewidgets/stylesheetbrowser/view-refresh.png diff --git a/examples/webenginewidgets/webenginewidgets.pro b/examples/webenginewidgets/webenginewidgets.pro index 61b294d7a..cb7c8aa22 100644 --- a/examples/webenginewidgets/webenginewidgets.pro +++ b/examples/webenginewidgets/webenginewidgets.pro @@ -4,10 +4,10 @@ SUBDIRS += \ minimal \ contentmanipulation \ cookiebrowser \ - demobrowser \ html2pdf \ markdowneditor \ simplebrowser \ + stylesheetbrowser \ videoplayer qtHaveModule(positioning): SUBDIRS += maps diff --git a/mkspecs/features/configure.prf b/mkspecs/features/configure.prf index f7a38ac12..002a0375a 100644 --- a/mkspecs/features/configure.prf +++ b/mkspecs/features/configure.prf @@ -20,32 +20,42 @@ defineTest(runConfigure) { qtCompileTest($$test) } - isQtMinimum(5, 8) { - include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) - QT_FOR_CONFIG += webengine-private + include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri) + QT_FOR_CONFIG += webengine-private - qtConfig(pepper-plugins): WEBENGINE_CONFIG += use_pepper_plugins - qtConfig(printing-and-pdf): WEBENGINE_CONFIG += use_printing use_pdf - qtConfig(proprietary-codecs): WEBENGINE_CONFIG += use_proprietary_codecs - qtConfig(spellchecker): WEBENGINE_CONFIG += use_spellchecker - qtConfig(webrtc): WEBENGINE_CONFIG += use_webrtc - qtConfig(embedded): WEBENGINE_CONFIG += embedded_build - qtConfig(system-webp): WEBENGINE_CONFIG += use_system_libwebp - qtConfig(system-opus): WEBENGINE_CONFIG += use_system_opus - qtConfig(system-ffmpeg): WEBENGINE_CONFIG += use_system_ffmpeg - qtConfig(system-icu): WEBENGINE_CONFIG += use_system_icu - !contains(WEBENGINE_CONFIG, use_system_libwebp): WEBENGINE_CONFIG += use_bundled_libwebp - !contains(WEBENGINE_CONFIG, use_system_opus): WEBENGINE_CONFIG += use_bundled_opus - !contains(WEBENGINE_CONFIG, use_system_ffmpeg): WEBENGINE_CONFIG += use_bundled_ffmpeg - !contains(WEBENGINE_CONFIG, use_system_icu): WEBENGINE_CONFIG += use_bundled_icu - } else { - # Feature defaults when building with Qt 5.6 LTS: - cross_compile { - WEBENGINE_CONFIG += embedded_build reduce_binary_size - } else { - WEBENGINE_CONFIG += use_spellchecker use_webrtc use_pepper_plugins use_printing use_pdf - } + !qtConfig(gperf) { + skipBuild("Required gperf could not be found.") + return(false) + } + !qtConfig(bison) { + skipBuild("Required bison could not be found.") + return(false) } + !qtConfig(flex) { + skipBuild("Required flex could not be found.") + return(false) + } + !qtConfig(python2) { + skipBuild("A suitable version of python2 could not be found.") + return(false) + } + + qtConfig(pepper-plugins): WEBENGINE_CONFIG += use_pepper_plugins + qtConfig(printing-and-pdf): WEBENGINE_CONFIG += use_printing use_pdf + qtConfig(proprietary-codecs): WEBENGINE_CONFIG += use_proprietary_codecs + qtConfig(spellchecker): WEBENGINE_CONFIG += use_spellchecker + qtConfig(webrtc): WEBENGINE_CONFIG += use_webrtc + qtConfig(embedded): WEBENGINE_CONFIG += embedded_build + qtConfig(system-webp): WEBENGINE_CONFIG += use_system_libwebp + qtConfig(system-opus): WEBENGINE_CONFIG += use_system_opus + qtConfig(system-ffmpeg): WEBENGINE_CONFIG += use_system_ffmpeg + qtConfig(system-icu): WEBENGINE_CONFIG += use_system_icu + qtConfig(nss-certificate-handling): WEBENGINE_CONFIG += use_nss + !contains(WEBENGINE_CONFIG, use_system_libwebp): WEBENGINE_CONFIG += use_bundled_libwebp + !contains(WEBENGINE_CONFIG, use_system_opus): WEBENGINE_CONFIG += use_bundled_opus + !contains(WEBENGINE_CONFIG, use_system_ffmpeg): WEBENGINE_CONFIG += use_bundled_ffmpeg + !contains(WEBENGINE_CONFIG, use_system_icu): WEBENGINE_CONFIG += use_bundled_icu + isQtMinimum(5, 9) { qtConfig(appstore-compliant): WEBENGINE_CONFIG += use_appstore_compliant_code optimize_size: WEBENGINE_CONFIG += reduce_binary_size @@ -74,12 +84,6 @@ defineTest(runConfigure) { } packagesExist(minizip, zlib): WEBENGINE_CONFIG += use_system_minizip use_system_zlib else: log("System zlib or minizip not found. Using Chromium's copies.$${EOL}") - !isQtMinimum(5, 8) { - packagesExist(libwebp,libwebpdemux): WEBENGINE_CONFIG += use_system_libwebp use_system_libwebpdemux - else: log("System libwebp or libwebpdemux not found. Using Chromium's copies.$${EOL}") - packagesExist(opus): WEBENGINE_CONFIG += use_system_opus - else: log("System opus not found. Using Chromium's copy.$${EOL}") - } packagesExist(libxml-2.0,libxslt) { PKGCONFIG_LIBS_STATIC = $$system($$PKG_CONFIG --libs --static libxml-2.0) contains(PKGCONFIG_LIBS_STATIC, -licuuc) { @@ -118,9 +122,6 @@ defineTest(runConfigure) { log("System snappy not found. Using Chromium's copy.$${EOL}") WEBENGINE_CONFIG += use_bundled_snappy } - - packagesExist(nss): WEBENGINE_CONFIG += use_nss - else: log("System NSS not found, BoringSSL will be used.$${EOL}") } win32 { @@ -137,35 +138,6 @@ defineTest(runConfigure) { unix:!darwin { log("System library dependencies:$${EOL}") - !isQtMinimum(5, 8) { - use?(system_icu) { - packagesExist("\'icu-uc >= 53\', \'icu-i18n >= 53\'") { - log(" ICU ................................ Using system version$${EOL}") - } else { - log(" ICU ................................ System ICU not found$${EOL}") - skipBuild("Unmet dependencies: icu-uc, icu-i18n") - } - } else { - log(" ICU ................................ Using internal copy (Default, force system ICU with WEBENGINE_CONFIG+=use_system_icu)$${EOL}") - WEBENGINE_CONFIG += use_bundled_icu - } - use?(system_ffmpeg) { - packagesExist("libavcodec libavformat libavutil") { - packagesExist("libwebp, libwebpdemux, opus, \'vpx >= 1.4\'"){ - log(" FFMPEG ............................. Using system version$${EOL}") - } else { - log(" FFMPEG ............................. Conflicting FFMPEG dependencies$${EOL}") - skipBuild("Unmet dependencies: opus, vpx, libwebp, libwebpdemux") - } - } else { - log(" FFMPEG ............................. System FFMPEG not found$${EOL}") - skipBuild("Unmet dependencies: libavcodec, libavformat, libavutil") - } - } else { - log(" FFMPEG ............................. Using internal copy (Default, force system FFMPEG with WEBENGINE_CONFIG+=use_system_ffmpeg)$${EOL}") - WEBENGINE_CONFIG += use_bundled_ffmpeg - } - } for(config, WEBENGINE_CONFIG) { match = $$find(config, "^use_system_") !isEmpty(match) { @@ -190,13 +162,6 @@ defineTest(runConfigure) { } else { log(" Geolocation ........................ Not enabled (Requires Qt Positioning module)$${EOL}") } - unix:!darwin { - use?(nss) { - log(" Certificate handling ............... Using system NSS$${EOL}") - } else { - log(" Certificate handling ............... Using bundled BoringSSL$${EOL}") - } - } osx { use?(native_spellchecker) { log("Native Spellchecker .............. Enabled$${EOL}") diff --git a/src/3rdparty b/src/3rdparty -Subproject 1a14be1c45c61b3d4c65519ec203f2d039eb34c +Subproject 582c5493439ba9ac57c6c14c706f530741f5bfc diff --git a/src/core/api/qtwebenginecoreglobal.cpp b/src/core/api/qtwebenginecoreglobal.cpp index 072f27967..0353dac7d 100644 --- a/src/core/api/qtwebenginecoreglobal.cpp +++ b/src/core/api/qtwebenginecoreglobal.cpp @@ -85,11 +85,9 @@ QWEBENGINE_PRIVATE_EXPORT void initialize() return; } -#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 1)) // Bail out silently if the user did not construct a QGuiApplication. if (!qobject_cast<QGuiApplication *>(app)) return; -#endif if (app->thread() != QThread::currentThread()) { qFatal("QtWebEngine::initialize() must be called from the Qt gui thread."); diff --git a/src/core/api/qwebenginecallback.h b/src/core/api/qwebenginecallback.h index b967f926a..b981b2afb 100644 --- a/src/core/api/qwebenginecallback.h +++ b/src/core/api/qwebenginecallback.h @@ -92,11 +92,9 @@ private: Q_DECLARE_SHARED(QWebEngineCallback<int>) Q_DECLARE_SHARED(QWebEngineCallback<const QByteArray &>) -#if QT_VERSION >= QT_VERSION_CHECK(5,6,0) Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QWebEngineCallback<bool>) Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QWebEngineCallback<const QString &>) Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QWebEngineCallback<const QVariant &>) -#endif QT_END_NAMESPACE diff --git a/src/core/api/qwebenginecallback_p.h b/src/core/api/qwebenginecallback_p.h index b88ef4d2c..fdaf84d21 100644 --- a/src/core/api/qwebenginecallback_p.h +++ b/src/core/api/qwebenginecallback_p.h @@ -242,12 +242,10 @@ void CallbackDirectory::CallbackSharedDataPointer<T>::invokeEmpty() parent->invokeEmptyInternal(callback); } -#if QT_VERSION >= QT_VERSION_CHECK(5,6,0) #define CHECK_RELOCATABLE(x) \ Q_STATIC_ASSERT((QTypeInfoQuery<QWebEngineCallback< x > >::isRelocatable)); FOR_EACH_TYPE(CHECK_RELOCATABLE) #undef CHECK_RELOCATABLE -#endif } // namespace QtWebEngineCore diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index ac4649d3d..7dad00f65 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -182,17 +182,21 @@ QRect BrowserAccessibilityQt::rect() const QAccessible::Role BrowserAccessibilityQt::role() const { switch (GetRole()) { + case ui::AX_ROLE_NONE: case ui::AX_ROLE_UNKNOWN: return QAccessible::NoRole; // Used by Chromium to distinguish between the root of the tree // for this page, and a web area for a frame within this page. case ui::AX_ROLE_WEB_AREA: + case ui::AX_ROLE_WEB_VIEW: case ui::AX_ROLE_ROOT_WEB_AREA: // not sure if we need to make a diff here, but this seems common return QAccessible::WebDocument; // These roles all directly correspond to blink accessibility roles, // keep these alphabetical. + case ui::AX_ROLE_ABBR: + return QAccessible::StaticText; case ui::AX_ROLE_ALERT: case ui::AX_ROLE_ALERT_DIALOG: return QAccessible::AlertMessage; @@ -202,18 +206,22 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Document; // returning Application here makes Qt return the top level app object case ui::AX_ROLE_ARTICLE: return QAccessible::Section; + case ui::AX_ROLE_AUDIO: + return QAccessible::Sound; case ui::AX_ROLE_BANNER: return QAccessible::Section; case ui::AX_ROLE_BLOCKQUOTE: return QAccessible::Section; case ui::AX_ROLE_BUSY_INDICATOR: - return QAccessible::Animation; // FIXME + return QAccessible::NoRole; // This is unused and planned to be removed. case ui::AX_ROLE_BUTTON: return QAccessible::Button; case ui::AX_ROLE_BUTTON_DROP_DOWN: - return QAccessible::Button; + return QAccessible::ButtonDropDown; case ui::AX_ROLE_CANVAS: return QAccessible::Canvas; + case ui::AX_ROLE_CAPTION: + return QAccessible::Heading; case ui::AX_ROLE_CELL: return QAccessible::Cell; case ui::AX_ROLE_CHECK_BOX: @@ -232,10 +240,17 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::ComplementaryContent; case ui::AX_ROLE_CONTENT_INFO: return QAccessible::Section; + case ui::AX_ROLE_DATE: + case ui::AX_ROLE_DATE_TIME: + return QAccessible::Clock; case ui::AX_ROLE_DEFINITION: return QAccessible::Paragraph; + case ui::AX_ROLE_DESCRIPTION_LIST: + return QAccessible::List; case ui::AX_ROLE_DESCRIPTION_LIST_DETAIL: return QAccessible::Paragraph; + case ui::AX_ROLE_DETAILS: + return QAccessible::Grouping; case ui::AX_ROLE_DESCRIPTION_LIST_TERM: return QAccessible::ListItem; case ui::AX_ROLE_DESKTOP: @@ -252,6 +267,12 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Document; case ui::AX_ROLE_EMBEDDED_OBJECT: return QAccessible::Grouping; // FIXME + case ui::AX_ROLE_FEED: + return QAccessible::Section; + case ui::AX_ROLE_FIGCAPTION: + return QAccessible::Heading; + case ui::AX_ROLE_FIGURE: + return QAccessible::Section; case ui::AX_ROLE_FOOTER: return QAccessible::Footer; case ui::AX_ROLE_FORM: @@ -264,6 +285,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Heading; case ui::AX_ROLE_IFRAME: return QAccessible::Grouping; + case ui::AX_ROLE_IFRAME_PRESENTATIONAL: + return QAccessible::NoRole; // FIXME case ui::AX_ROLE_IGNORED: return QAccessible::NoRole; case ui::AX_ROLE_IMAGE: @@ -274,16 +297,20 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Link; case ui::AX_ROLE_INLINE_TEXT_BOX: return QAccessible::EditableText; + case ui::AX_ROLE_INPUT_TIME: + return QAccessible::SpinBox; case ui::AX_ROLE_LABEL_TEXT: return QAccessible::StaticText; case ui::AX_ROLE_LEGEND: - return QAccessible::NoRole; // FIXME + return QAccessible::StaticText; + case ui::AX_ROLE_LINE_BREAK: + return QAccessible::Separator; case ui::AX_ROLE_LINK: return QAccessible::Link; case ui::AX_ROLE_LIST: return QAccessible::List; case ui::AX_ROLE_LIST_BOX: - return QAccessible::List; + return QAccessible::ComboBox; case ui::AX_ROLE_LIST_BOX_OPTION: return QAccessible::ListItem; case ui::AX_ROLE_LIST_ITEM: @@ -293,11 +320,13 @@ QAccessible::Role BrowserAccessibilityQt::role() const case ui::AX_ROLE_LOCATION_BAR: return QAccessible::NoRole; // FIXME case ui::AX_ROLE_LOG: - return QAccessible::NoRole; // FIXME + return QAccessible::Section; case ui::AX_ROLE_MAIN: - return QAccessible::NoRole; // FIXME + return QAccessible::Grouping; + case ui::AX_ROLE_MARK: + return QAccessible::StaticText; case ui::AX_ROLE_MARQUEE: - return QAccessible::NoRole; // FIXME + return QAccessible::Section; case ui::AX_ROLE_MATH: return QAccessible::Equation; case ui::AX_ROLE_MENU: @@ -306,12 +335,18 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::MenuBar; case ui::AX_ROLE_MENU_ITEM: return QAccessible::MenuItem; + case ui::AX_ROLE_MENU_ITEM_CHECK_BOX: + return QAccessible::CheckBox; + case ui::AX_ROLE_MENU_ITEM_RADIO: + return QAccessible::RadioButton; case ui::AX_ROLE_MENU_BUTTON: return QAccessible::MenuItem; case ui::AX_ROLE_MENU_LIST_OPTION: return QAccessible::MenuItem; case ui::AX_ROLE_MENU_LIST_POPUP: return QAccessible::PopupMenu; + case ui::AX_ROLE_METER: + return QAccessible::Chart; case ui::AX_ROLE_NAVIGATION: return QAccessible::Section; case ui::AX_ROLE_NOTE: @@ -340,6 +375,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Row; case ui::AX_ROLE_ROW_HEADER: return QAccessible::RowHeader; + case ui::AX_ROLE_RUBY: + return QAccessible::StaticText; case ui::AX_ROLE_RULER: return QAccessible::NoRole; // FIXME case ui::AX_ROLE_SCROLL_AREA: @@ -350,6 +387,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::NoRole; // FIXME case ui::AX_ROLE_SEARCH: return QAccessible::Section; + case ui::AX_ROLE_SEARCH_BOX: + return QAccessible::EditableText; case ui::AX_ROLE_SLIDER: return QAccessible::Slider; case ui::AX_ROLE_SLIDER_THUMB: @@ -363,9 +402,11 @@ QAccessible::Role BrowserAccessibilityQt::role() const case ui::AX_ROLE_STATIC_TEXT: return QAccessible::StaticText; case ui::AX_ROLE_STATUS: - return QAccessible::StatusBar; + return QAccessible::Indicator; case ui::AX_ROLE_SVG_ROOT: return QAccessible::Graphic; + case ui::AX_ROLE_SWITCH: + return QAccessible::Button; case ui::AX_ROLE_TABLE: return QAccessible::Table; case ui::AX_ROLE_TABLE_HEADER_CONTAINER: @@ -378,8 +419,11 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::PageTabList; case ui::AX_ROLE_TAB_PANEL: return QAccessible::PageTab; + case ui::AX_ROLE_TERM: + return QAccessible::StaticText; case ui::AX_ROLE_TEXT_FIELD: return QAccessible::EditableText; + case ui::AX_ROLE_TIME: case ui::AX_ROLE_TIMER: return QAccessible::Clock; case ui::AX_ROLE_TITLE_BAR: @@ -396,6 +440,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const return QAccessible::Tree; case ui::AX_ROLE_TREE_ITEM: return QAccessible::TreeItem; + case ui::AX_ROLE_VIDEO: + return QAccessible::Animation; case ui::AX_ROLE_WINDOW: return QAccessible::Window; } @@ -491,7 +537,7 @@ QStringList BrowserAccessibilityQt::keyBindingsForAction(const QString &actionNa void BrowserAccessibilityQt::addSelection(int startOffset, int endOffset) { - manager()->SetTextSelection(*this, startOffset, endOffset); + manager()->SetSelection(AXPlatformRange(CreatePositionAt(startOffset), CreatePositionAt(endOffset))); } QString BrowserAccessibilityQt::attributes(int offset, int *startOffset, int *endOffset) const @@ -549,19 +595,19 @@ QString BrowserAccessibilityQt::text(int startOffset, int endOffset) const void BrowserAccessibilityQt::removeSelection(int selectionIndex) { - manager()->SetTextSelection(*this, 0, 0); + manager()->SetSelection(AXPlatformRange(CreatePositionAt(0), CreatePositionAt(0))); } void BrowserAccessibilityQt::setCursorPosition(int position) { - manager()->SetTextSelection(*this, position, position); + manager()->SetSelection(AXPlatformRange(CreatePositionAt(position), CreatePositionAt(position))); } void BrowserAccessibilityQt::setSelection(int selectionIndex, int startOffset, int endOffset) { if (selectionIndex != 0) return; - manager()->SetTextSelection(*this, startOffset, endOffset); + manager()->SetSelection(AXPlatformRange(CreatePositionAt(startOffset), CreatePositionAt(endOffset))); } int BrowserAccessibilityQt::characterCount() const diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp index bec76ad81..f76969c74 100644 --- a/src/core/browser_context_adapter.cpp +++ b/src/core/browser_context_adapter.cpp @@ -184,6 +184,16 @@ void BrowserContextAdapter::cancelDownload(quint32 downloadId) downloadManagerDelegate()->cancelDownload(downloadId); } +void BrowserContextAdapter::pauseDownload(quint32 downloadId) +{ + downloadManagerDelegate()->pauseDownload(downloadId); +} + +void BrowserContextAdapter::resumeDownload(quint32 downloadId) +{ + downloadManagerDelegate()->resumeDownload(downloadId); +} + QSharedPointer<BrowserContextAdapter> BrowserContextAdapter::defaultContext() { return WebEngineContext::current()->defaultBrowserContext(); diff --git a/src/core/browser_context_adapter.h b/src/core/browser_context_adapter.h index f6ebfd51c..5960014b9 100644 --- a/src/core/browser_context_adapter.h +++ b/src/core/browser_context_adapter.h @@ -86,6 +86,8 @@ public: void removeClient(BrowserContextAdapterClient *adapterClient); void cancelDownload(quint32 downloadId); + void pauseDownload(quint32 downloadId); + void resumeDownload(quint32 downloadId); BrowserContextQt *browserContext(); diff --git a/src/core/browser_context_adapter_client.h b/src/core/browser_context_adapter_client.h index e1fd02f96..02bee8ed6 100644 --- a/src/core/browser_context_adapter_client.h +++ b/src/core/browser_context_adapter_client.h @@ -118,6 +118,8 @@ public: QString path; int savePageFormat; bool accepted; + bool paused; + bool done; int downloadType; int downloadInterruptReason; }; diff --git a/src/core/chromium_gpu_helper.cpp b/src/core/chromium_gpu_helper.cpp index 1b415b9ec..cea3aacaf 100644 --- a/src/core/chromium_gpu_helper.cpp +++ b/src/core/chromium_gpu_helper.cpp @@ -65,13 +65,13 @@ base::MessageLoop *gpu_message_loop() gpu::SyncPointManager *sync_point_manager() { - gpu::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager(); + gpu::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->gpu_channel_manager(); return gpuChannelManager->sync_point_manager(); } gpu::gles2::MailboxManager *mailbox_manager() { - gpu::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager(); + gpu::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->gpu_channel_manager(); return gpuChannelManager->mailbox_manager(); } diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp index 9afa80757..9aeeb1327 100644 --- a/src/core/chromium_overrides.cpp +++ b/src/core/chromium_overrides.cpp @@ -49,6 +49,7 @@ #include "content/common/font_list.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/dragdrop/os_exchange_data_provider_factory.h" +#include "ppapi/features/features.h" #include <QGuiApplication> #include <QScreen> @@ -141,7 +142,7 @@ std::unique_ptr<base::ListValue> GetFontList_SlowBlocking() return std::move(font_list); } -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) // content/browser/renderer_host/pepper/pepper_truetype_font_list.h void GetFontFamilies_SlowBlocking(std::vector<std::string> *font_families) { @@ -155,7 +156,7 @@ void GetFontsInFamily_SlowBlocking(const std::string &, std::vector<ppapi::proxy { QT_NOT_USED } -#endif //defined(ENABLE_PLUGINS) +#endif // BUILDFLAG(ENABLE_PLUGINS) } // namespace content @@ -170,7 +171,7 @@ ui::OSExchangeDataProviderFactory::CreateProvider() { #if defined(USE_OPENSSL_CERTS) namespace net { -scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(X509Certificate* certificate) +scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(const X509Certificate* certificate) { return OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey(certificate); } diff --git a/src/core/clipboard_qt.h b/src/core/clipboard_qt.h index c2ced4941..20b51a599 100644 --- a/src/core/clipboard_qt.h +++ b/src/core/clipboard_qt.h @@ -82,6 +82,8 @@ public: void ReadBookmark(base::string16* title, std::string* url) const override; void ReadData(const FormatType& format, std::string* result) const override; + virtual void OnPreShutdown() Q_DECL_OVERRIDE { } + protected: void WriteObjects(ui::ClipboardType type, const ObjectMap& objects) override; void WriteText(const char* text_data, size_t text_len) override; diff --git a/src/core/config/desktop_linux.pri b/src/core/config/desktop_linux.pri index 9918e1bb2..4d3f923e1 100644 --- a/src/core/config/desktop_linux.pri +++ b/src/core/config/desktop_linux.pri @@ -3,7 +3,6 @@ include(linux.pri) gn_args += \ use_sysroot=false \ enable_session_service=false \ - enable_notifications=false \ toolkit_views=false use?(icecc) { diff --git a/src/core/config/embedded_linux.pri b/src/core/config/embedded_linux.pri index d5f6d4bf5..e48f1fc12 100644 --- a/src/core/config/embedded_linux.pri +++ b/src/core/config/embedded_linux.pri @@ -6,7 +6,6 @@ gn_args += \ use_ozone=true \ use_sysroot=false \ enable_session_service=false \ - enable_notifications=false \ ozone_auto_platforms=false \ ozone_platform_headless=true \ ozone_platform_external=true \ diff --git a/src/core/config/windows.pri b/src/core/config/windows.pri index db1fbd3d7..f5dd4a9d3 100644 --- a/src/core/config/windows.pri +++ b/src/core/config/windows.pri @@ -4,19 +4,15 @@ gn_args += \ is_clang=false \ use_sysroot=false \ use_kerberos=true \ - enable_notifications=false \ enable_session_service=false \ ninja_use_custom_environment_files=false \ is_multi_dll_chrome=false \ + use_incremental_linking=false \ win_linker_timing=true isDeveloperBuild() { gn_args += \ - is_win_fastlink=true \ - use_incremental_linking=true -} else { - gn_args += \ - use_incremental_linking=false + is_win_fastlink=true } defineTest(usingMSVC32BitCrossCompiler) { diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index d446d8ff4..5bce81f25 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -59,6 +59,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/resource_dispatcher_host.h" +#include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_user_data.h" #include "content/public/common/content_switches.h" @@ -107,7 +108,7 @@ #include "ui/base/resource/resource_bundle.h" #endif -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) #include "content/public/browser/browser_ppapi_host.h" #include "ppapi/host/ppapi_host.h" #include "renderer_host/pepper/pepper_host_factory_qt.h" @@ -459,6 +460,17 @@ content::QuotaPermissionContext *ContentBrowserClientQt::CreateQuotaPermissionCo return new QuotaPermissionContextQt; } +void ContentBrowserClientQt::GetQuotaSettings(content::BrowserContext *context, + content::StoragePartition *partition, + const storage::OptionalQuotaSettingsCallback &callback) +{ + content::BrowserThread::PostTaskAndReplyWithResult( + content::BrowserThread::FILE, FROM_HERE, + base::Bind(&storage::CalculateNominalDynamicSettings, + partition->GetPath(), context->IsOffTheRecord()), + callback); +} + void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webContents, int cert_error, const net::SSLInfo& ssl_info, @@ -522,7 +534,7 @@ void ContentBrowserClientQt::GetAdditionalMappedFilesForChildProcess(const base: } #endif -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) void ContentBrowserClientQt::DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) { browser_host->GetPpapiHost()->AddHostFactoryFilter( diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h index b17dd3e39..95c7d2894 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -42,6 +42,7 @@ #include "base/memory/ref_counted.h" #include "content/public/browser/content_browser_client.h" +#include "ppapi/features/features.h" #include <QtGlobal> @@ -53,7 +54,7 @@ namespace content { class BrowserContext; class BrowserMainParts; -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) class BrowserPpapiHost; #endif @@ -93,6 +94,9 @@ public: gl::GLShareGroup* GetInProcessGpuShareGroup() override; content::MediaObserver* GetMediaObserver() override; content::QuotaPermissionContext *CreateQuotaPermissionContext() override; + void GetQuotaSettings(content::BrowserContext *context, + content::StoragePartition *partition, + const storage::OptionalQuotaSettingsCallback &callback) override; void OverrideWebkitPrefs(content::RenderViewHost *, content::WebPreferences *) override; void AllowCertificateError(content::WebContents* web_contents, int cert_error, @@ -119,7 +123,7 @@ public: void GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::FileDescriptorInfo* mappings) override; #endif -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override; #endif diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index e58fa93d7..10e198d6a 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -50,6 +50,8 @@ #include "ui/base/layout.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" + +#include "qrc_protocol_handler_qt.h" #include "type_conversion.h" #include <QCoreApplication> @@ -69,7 +71,7 @@ static QString getLocalAppDataDir() } #endif -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) // The plugin logic is based on chrome/common/chrome_content_client.cc: // Copyright (c) 2012 The Chromium Authors. All rights reserved. @@ -284,7 +286,7 @@ void ContentClientQt::AddPepperPlugins(std::vector<content::PepperPluginInfo>* p } } -#endif +#endif // BUILDFLAG(ENABLE_PLUGINS) #include <QCoreApplication> @@ -316,4 +318,9 @@ std::string ContentClientQt::GetProduct() const return productName.toStdString(); } +void ContentClientQt::AddAdditionalSchemes(Schemes* schemes) +{ + schemes->secure_schemes.push_back(kQrcSchemeQt); +} + } // namespace QtWebEngineCore diff --git a/src/core/content_client_qt.h b/src/core/content_client_qt.h index 7104b98b6..341406380 100644 --- a/src/core/content_client_qt.h +++ b/src/core/content_client_qt.h @@ -42,6 +42,7 @@ #include "base/strings/string_piece.h" #include "content/public/common/content_client.h" +#include "ppapi/features/features.h" #include "ui/base/layout.h" namespace QtWebEngineCore { @@ -50,9 +51,10 @@ class ContentClientQt : public content::ContentClient { public: static std::string getUserAgent(); -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) void AddPepperPlugins(std::vector<content::PepperPluginInfo>* plugins) override; #endif + void AddAdditionalSchemes(Schemes* schemes) override; base::StringPiece GetDataResource(int, ui::ScaleFactor) const override; base::RefCountedMemory* GetDataResourceBytes(int resource_id) const override; diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp index e49bc553f..5d6353740 100644 --- a/src/core/delegated_frame_node.cpp +++ b/src/core/delegated_frame_node.cpp @@ -57,7 +57,8 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "base/threading/thread_task_runner_handle.h" -#include "cc/output/delegated_frame_data.h" +#include "cc/output/compositor_frame.h" +#include "cc/output/compositor_frame_metadata.h" #include "cc/quads/debug_border_draw_quad.h" #include "cc/quads/draw_quad.h" #include "cc/quads/render_pass_draw_quad.h" @@ -81,13 +82,8 @@ #include <QSGTexture> #include <private/qsgadaptationlayer_p.h> -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) #include <QSGImageNode> #include <QSGRectangleNode> -#else -#include <QSGSimpleRectNode> -#include <QSGSimpleTextureNode> -#endif #if !defined(QT_NO_EGL) #include <EGL/egl.h> @@ -209,7 +205,6 @@ protected: QVector<QSGNode*> *m_sceneGraphNodes; }; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) class DelegatedNodeTreeUpdater : public DelegatedNodeTreeHandler { public: @@ -304,7 +299,6 @@ public: private: QVector<QSGNode*>::iterator m_nodeIterator; }; -#endif class DelegatedNodeTreeCreator : public DelegatedNodeTreeHandler { @@ -435,9 +429,9 @@ private: }; -static inline QSharedPointer<QSGLayer> findRenderPassLayer(const cc::RenderPassId &id, const QVector<QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > > &list) +static inline QSharedPointer<QSGLayer> findRenderPassLayer(const int &id, const QVector<QPair<int, QSharedPointer<QSGLayer> > > &list) { - typedef QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > Pair; + typedef QPair<int, QSharedPointer<QSGLayer> > Pair; Q_FOREACH (const Pair &pair, list) if (pair.first == id) return pair.second; @@ -753,7 +747,7 @@ void DelegatedFrameNode::preprocess() fetchAndSyncMailboxes(mailboxesToFetch); // Then render any intermediate RenderPass in order. - typedef QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > Pair; + typedef QPair<int, QSharedPointer<QSGLayer> > Pair; Q_FOREACH (const Pair &pair, m_sgObjects.renderPassLayers) { // The layer is non-live, request a one-time update here. pair.second->scheduleUpdate(); @@ -791,8 +785,8 @@ static bool areSharedQuadStatesEqual(const cc::SharedQuadState *layerState, // Compares if the frame data that we got from the Chromium Compositor is // *structurally* equivalent to the one of the previous frame. // If it is, we will just reuse and update the old nodes where necessary. -static bool areRenderPassStructuresEqual(cc::DelegatedFrameData *frameData, - cc::DelegatedFrameData *previousFrameData) +static bool areRenderPassStructuresEqual(cc::CompositorFrame *frameData, + cc::CompositorFrame *previousFrameData) { if (!previousFrameData) return false; @@ -840,8 +834,8 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, RenderWidgetHostViewQtDelegate *apiDelegate) { m_chromiumCompositorData = chromiumCompositorData; - cc::DelegatedFrameData* frameData = m_chromiumCompositorData->frameData.get(); - if (!frameData) + cc::CompositorFrame* frameData = &m_chromiumCompositorData->frameData; + if (frameData->render_pass_list.empty()) return; // DelegatedFrameNode is a transform node only for the purpose of @@ -874,15 +868,10 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, // We first compare if the render passes from the previous frame data are structurally // equivalent to the render passes in the current frame data. If they are, we are going // to reuse the old nodes. Otherwise, we will delete the old nodes and build a new tree. -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) - cc::DelegatedFrameData *previousFrameData = m_chromiumCompositorData->previousFrameData.get(); + cc::CompositorFrame *previousFrameData = &m_chromiumCompositorData->previousFrameData; const bool buildNewTree = !areRenderPassStructuresEqual(frameData, previousFrameData) || m_sceneGraphNodes.empty(); -#else - // No updates possible with old scenegraph nodes - const bool buildNewTree = true; -#endif - m_chromiumCompositorData->previousFrameData = nullptr; + m_chromiumCompositorData->previousFrameData = cc::CompositorFrame(); SGObjects previousSGObjects; QVector<QSharedPointer<QSGTexture> > textureStrongRefs; if (buildNewTree) { @@ -894,13 +883,11 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, delete oldChain; m_sceneGraphNodes.clear(); nodeHandler.reset(new DelegatedNodeTreeCreator(&m_sceneGraphNodes, apiDelegate)); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) } else { // Save the texture strong refs so they only go out of scope when the method returns and // the new vector of texture strong refs has been filled. qSwap(m_sgObjects.textureStrongRefs, textureStrongRefs); nodeHandler.reset(new DelegatedNodeTreeUpdater(&m_sceneGraphNodes)); -#endif } // The RenderPasses list is actually a tree where a parent RenderPass is connected // to its dependencies through a RenderPassId reference in one or more RenderPassQuads. @@ -926,7 +913,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, } QSharedPointer<QSGRootNode> rootNode(new QSGRootNode); rpLayer->setItem(rootNode.data()); - m_sgObjects.renderPassLayers.append(QPair<cc::RenderPassId, + m_sgObjects.renderPassLayers.append(QPair<int, QSharedPointer<QSGLayer> >(pass->id, rpLayer)); m_sgObjects.renderPassRootNodes.append(rootNode); renderPassParent = rootNode.data(); @@ -1128,27 +1115,15 @@ void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxe QMutexLocker lock(&m_mutex); gpu::SyncPointManager *syncPointManager = sync_point_manager(); - if (!m_syncPointClient) - m_syncPointClient = syncPointManager->CreateSyncPointClientWaiter(); base::MessageLoop *gpuMessageLoop = gpu_message_loop(); Q_ASSERT(m_numPendingSyncPoints == 0); m_numPendingSyncPoints = mailboxesToFetch.count(); - auto it = mailboxesToFetch.constBegin(); - auto end = mailboxesToFetch.constEnd(); - for (; it != end; ++it) { - MailboxTexture *mailboxTexture = *it; + for (MailboxTexture *mailboxTexture : qAsConst(mailboxesToFetch)) { gpu::SyncToken &syncToken = mailboxTexture->mailboxHolder().sync_token; - if (syncToken.HasData()) { - scoped_refptr<gpu::SyncPointClientState> release_state = - syncPointManager->GetSyncPointClientState(syncToken.namespace_id(), syncToken.command_buffer_id()); - if (release_state && !release_state->IsFenceSyncReleased(syncToken.release_count())) { - m_syncPointClient->WaitOutOfOrderNonThreadSafe( - release_state.get(), syncToken.release_count(), - gpuMessageLoop->task_runner(), base::Bind(&DelegatedFrameNode::pullTexture, this, mailboxTexture)); - continue; - } - } - gpuMessageLoop->task_runner()->PostTask(FROM_HERE, base::Bind(&DelegatedFrameNode::pullTexture, this, mailboxTexture)); + const auto task = base::Bind(&DelegatedFrameNode::pullTexture, this, mailboxTexture); + if (syncPointManager->WaitOutOfOrderNonThreadSafe(syncToken, gpuMessageLoop->task_runner(), task)) + continue; + gpuMessageLoop->task_runner()->PostTask(FROM_HERE, task); } m_mailboxesFetchedWaitCond.wait(&m_mutex); diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h index 6178bd232..b2b87a2f8 100644 --- a/src/core/delegated_frame_node.h +++ b/src/core/delegated_frame_node.h @@ -40,6 +40,7 @@ #ifndef DELEGATED_FRAME_NODE_H #define DELEGATED_FRAME_NODE_H +#include "cc/output/compositor_frame.h" #include "cc/quads/render_pass.h" #include "cc/resources/transferable_resource.h" #include "gpu/command_buffer/service/sync_point_manager.h" @@ -58,10 +59,6 @@ QT_BEGIN_NAMESPACE class QSGLayer; QT_END_NAMESPACE -namespace cc { -class DelegatedFrameData; -} - namespace QtWebEngineCore { class MailboxTexture; @@ -73,8 +70,8 @@ class ChromiumCompositorData : public QSharedData { public: ChromiumCompositorData() : frameDevicePixelRatio(1) { } QHash<unsigned, QSharedPointer<ResourceHolder> > resourceHolders; - std::unique_ptr<cc::DelegatedFrameData> frameData; - std::unique_ptr<cc::DelegatedFrameData> previousFrameData; + cc::CompositorFrame frameData; + cc::CompositorFrame previousFrameData; qreal frameDevicePixelRatio; }; @@ -97,7 +94,7 @@ private: QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData; struct SGObjects { - QVector<QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > > renderPassLayers; + QVector<QPair<int, QSharedPointer<QSGLayer> > > renderPassLayers; QVector<QSharedPointer<QSGRootNode> > renderPassRootNodes; QVector<QSharedPointer<QSGTexture> > textureStrongRefs; } m_sgObjects; @@ -106,7 +103,6 @@ private: QWaitCondition m_mailboxesFetchedWaitCond; QMutex m_mutex; QList<gl::TransferableFence> m_textureFences; - std::unique_ptr<gpu::SyncPointClient> m_syncPointClient; #if defined(USE_X11) bool m_contextShared; QScopedPointer<QOffscreenSurface> m_offsurface; diff --git a/src/core/desktop_screen_qt.cpp b/src/core/desktop_screen_qt.cpp index 1f4c9730f..ec7b6ce98 100644 --- a/src/core/desktop_screen_qt.cpp +++ b/src/core/desktop_screen_qt.cpp @@ -70,10 +70,11 @@ int DesktopScreenQt::GetNumDisplays() const return 0; } -std::vector<display::Display> DesktopScreenQt::GetAllDisplays() const +std::vector<display::Display>& DesktopScreenQt::GetAllDisplays() const { Q_UNREACHABLE(); - return std::vector<display::Display>(); + static std::vector<display::Display> empty; + return empty; } display::Display DesktopScreenQt::GetDisplayNearestWindow(gfx::NativeView window) const diff --git a/src/core/desktop_screen_qt.h b/src/core/desktop_screen_qt.h index f052461a2..b91cb6aab 100644 --- a/src/core/desktop_screen_qt.h +++ b/src/core/desktop_screen_qt.h @@ -51,7 +51,7 @@ public: bool IsWindowUnderCursor(gfx::NativeWindow) override; gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override; int GetNumDisplays() const override; - std::vector<display::Display> GetAllDisplays() const override; + std::vector<display::Display>& GetAllDisplays() const override; display::Display GetDisplayNearestWindow(gfx::NativeView window) const override; display::Display GetDisplayNearestPoint(const gfx::Point& point) const override; display::Display GetDisplayMatching(const gfx::Rect& match_rect) const override; diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 77469a8ea..67c809032 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -92,6 +92,22 @@ void DownloadManagerDelegateQt::cancelDownload(quint32 downloadId) download->Cancel(/* user_cancel */ true); } +void DownloadManagerDelegateQt::pauseDownload(quint32 downloadId) +{ + content::DownloadManager* dlm = content::BrowserContext::GetDownloadManager(m_contextAdapter->browserContext()); + content::DownloadItem *download = dlm->GetDownload(downloadId); + if (download) + download->Pause(); +} + +void DownloadManagerDelegateQt::resumeDownload(quint32 downloadId) +{ + content::DownloadManager* dlm = content::BrowserContext::GetDownloadManager(m_contextAdapter->browserContext()); + content::DownloadItem *download = dlm->GetDownload(downloadId); + if (download) + download->Resume(); +} + bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* item, const content::DownloadTargetCallback& callback) { @@ -155,6 +171,8 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i suggestedFilePath, BrowserContextAdapterClient::UnknownSavePageFormat, false /* accepted */, + false /* paused */, + false /* done */, m_downloadType, item->GetLastReason() }; @@ -245,6 +263,8 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content suggestedFilePath, suggestedSaveFormat, acceptedByDefault, + false, /* paused */ + false, /* done */ BrowserContextAdapterClient::SavePage, BrowserContextAdapterClient::NoReason }; @@ -283,6 +303,8 @@ void DownloadManagerDelegateQt::OnDownloadUpdated(content::DownloadItem *downloa QString(), BrowserContextAdapterClient::UnknownSavePageFormat, true /* accepted */, + download->IsPaused(), + download->IsDone(), m_downloadType, download->GetLastReason() }; diff --git a/src/core/download_manager_delegate_qt.h b/src/core/download_manager_delegate_qt.h index cd21d330c..aec83cb41 100644 --- a/src/core/download_manager_delegate_qt.h +++ b/src/core/download_manager_delegate_qt.h @@ -83,6 +83,8 @@ public: const content::SavePackagePathPickedCallback &callback) override; void cancelDownload(quint32 downloadId); + void pauseDownload(quint32 downloadId); + void resumeDownload(quint32 downloadId); void setDownloadType(int downloadType) { m_downloadType = downloadType; } diff --git a/src/core/gl_context_qt.cpp b/src/core/gl_context_qt.cpp index 8f812a9cb..cd82b1069 100644 --- a/src/core/gl_context_qt.cpp +++ b/src/core/gl_context_qt.cpp @@ -93,21 +93,20 @@ void GLContextHelper::destroy() contextHelper = 0; } -bool GLContextHelper::initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface) +bool GLContextHelper::initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs) { - gl::GLContextAttribs attribs; - attribs.gpu_preference = gl::PreferDiscreteGpu; return context->Initialize(surface, attribs); } -bool GLContextHelper::initializeContext(gl::GLContext* context, gl::GLSurface* surface) +bool GLContextHelper::initializeContext(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs) { bool ret = false; Qt::ConnectionType connType = (QThread::currentThread() == qApp->thread()) ? Qt::DirectConnection : Qt::BlockingQueuedConnection; QMetaObject::invokeMethod(contextHelper, "initializeContextOnBrowserThread", connType, Q_RETURN_ARG(bool, ret), Q_ARG(gl::GLContext*, context), - Q_ARG(gl::GLSurface*, surface)); + Q_ARG(gl::GLSurface*, surface), + Q_ARG(gl::GLContextAttribs, attribs)); return ret; } @@ -171,7 +170,7 @@ scoped_refptr<GLContext> CreateGLContext(GLShareGroup* share_group, scoped_refptr<GLContext> context = new GLContextEGL(share_group); #endif - if (!GLContextHelper::initializeContext(context.get(), compatible_surface)) + if (!GLContextHelper::initializeContext(context.get(), compatible_surface, attribs)) return NULL; return context; diff --git a/src/core/gl_context_qt.h b/src/core/gl_context_qt.h index 47cd7dc7f..9c8a43a0a 100644 --- a/src/core/gl_context_qt.h +++ b/src/core/gl_context_qt.h @@ -41,6 +41,7 @@ #define GL_GL_CONTEXT_QT_H_ #include <QObject> +#include "ui/gl/gl_context.h" namespace gl { class GLContext; @@ -54,7 +55,7 @@ class GLContextHelper : public QObject { public: static void initialize(); static void destroy(); - static bool initializeContext(gl::GLContext* context, gl::GLSurface* surface); + static bool initializeContext(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs); static void* getEGLConfig(); static void* getXConfig(); @@ -63,7 +64,7 @@ public: static void* getNativeDisplay(); private: - Q_INVOKABLE bool initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface); + Q_INVOKABLE bool initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs); static GLContextHelper* contextHelper; }; diff --git a/src/core/gl_surface_qt.cpp b/src/core/gl_surface_qt.cpp index 766c14738..e0672f14f 100644 --- a/src/core/gl_surface_qt.cpp +++ b/src/core/gl_surface_qt.cpp @@ -102,7 +102,7 @@ public: static bool InitializeOneOff(); - bool Initialize() override; + bool Initialize(GLSurfaceFormat format) override; void Destroy() override; void* GetHandle() override; bool Resize(const gfx::Size& size, float scale_factor, bool has_alpha) override; @@ -124,7 +124,7 @@ public: explicit GLSurfacelessQtEGL(const gfx::Size& size); public: - bool Initialize() override; + bool Initialize(GLSurfaceFormat format) override; void Destroy() override; bool IsSurfaceless() const override; bool Resize(const gfx::Size& size, float scale_factor, bool has_alpha) override; @@ -152,7 +152,7 @@ public: static bool InitializeOneOff(); - bool Initialize() override; + bool Initialize(GLSurfaceFormat format) override; void Destroy() override; void* GetHandle() override; @@ -246,7 +246,7 @@ bool GLSurfaceQtGLX::InitializeOneOff() return true; } -bool GLSurfaceQtGLX::Initialize() +bool GLSurfaceQtGLX::Initialize(GLSurfaceFormat format) { Q_ASSERT(!m_surfaceBuffer); @@ -260,6 +260,7 @@ bool GLSurfaceQtGLX::Initialize() }; m_surfaceBuffer = glXCreatePbuffer(display, static_cast<GLXFBConfig>(g_config), pbuffer_attributes); + m_format = format; if (!m_surfaceBuffer) { Destroy(); @@ -296,7 +297,7 @@ public: static bool InitializeOneOff(); - bool Initialize() override; + bool Initialize(GLSurfaceFormat format) override; void Destroy() override; void *GetHandle() override; void *GetDisplay() override; @@ -326,11 +327,12 @@ bool GLSurfaceQtWGL::InitializeOneOff() return GLSurfaceWGL::InitializeOneOff(); } -bool GLSurfaceQtWGL::Initialize() +bool GLSurfaceQtWGL::Initialize(GLSurfaceFormat format) { m_surfaceBuffer = new PbufferGLSurfaceWGL(m_size); + m_format = format; - return m_surfaceBuffer->Initialize(gl::GLSurface::SURFACE_DEFAULT); + return m_surfaceBuffer->Initialize(format); } void GLSurfaceQtWGL::Destroy() @@ -425,6 +427,10 @@ bool GLSurfaceEGL::IsCreateContextWebGLCompatabilitySupported() return false; } +void GLSurfaceEGL::ShutdownOneOff() +{ +} + const char* GLSurfaceEGL::GetEGLExtensions() { return g_extensions; @@ -435,6 +441,11 @@ bool GLSurfaceEGL::HasEGLExtension(const char* name) return ExtensionsContain(GetEGLExtensions(), name); } +bool GLSurfaceEGL::InitializeOneOff(EGLNativeDisplayType /*native_display*/) +{ + return GLSurfaceQtEGL::InitializeOneOff(); +} + GLSurfaceQt::GLSurfaceQt(const gfx::Size& size) : m_size(size) { @@ -455,9 +466,10 @@ GLSurfaceQtEGL::GLSurfaceQtEGL(const gfx::Size& size) { } -bool GLSurfaceQtEGL::Initialize() +bool GLSurfaceQtEGL::Initialize(GLSurfaceFormat format) { Q_ASSERT(!m_surfaceBuffer); + m_format = format; EGLDisplay display = g_display; if (!display) { @@ -512,6 +524,12 @@ gfx::Size GLSurfaceQt::GetSize() } +GLSurfaceFormat GLSurfaceQt::GetFormat() +{ + return m_format; +} + + bool GLSurfaceQtEGL::Resize(const gfx::Size& size, float scale_factor, bool has_alpha) { if (size == m_size) @@ -526,7 +544,7 @@ bool GLSurfaceQtEGL::Resize(const gfx::Size& size, float scale_factor, bool has_ m_size = size; - if (!Initialize()) { + if (!Initialize(GetFormat())) { LOG(ERROR) << "Failed to resize pbuffer."; return false; } @@ -557,8 +575,9 @@ GLSurfacelessQtEGL::GLSurfacelessQtEGL(const gfx::Size& size) { } -bool GLSurfacelessQtEGL::Initialize() +bool GLSurfacelessQtEGL::Initialize(GLSurfaceFormat format) { + m_format = format; return true; } @@ -619,7 +638,7 @@ bool InitializeGLOneOffPlatform() } scoped_refptr<GLSurface> -CreateOffscreenGLSurface(const gfx::Size& size) +CreateOffscreenGLSurfaceWithFormat(const gfx::Size& size, GLSurfaceFormat format) { scoped_refptr<GLSurface> surface; switch (GetGLImplementation()) { @@ -627,13 +646,13 @@ CreateOffscreenGLSurface(const gfx::Size& size) case kGLImplementationDesktopGL: { #if defined(OS_WIN) surface = new GLSurfaceQtWGL(size); - if (surface->Initialize()) + if (surface->Initialize(format)) return surface; break; #elif defined(USE_X11) if (!g_initializedEGL) { surface = new GLSurfaceQtGLX(size); - if (surface->Initialize()) + if (surface->Initialize(format)) return surface; } // no break @@ -641,7 +660,7 @@ CreateOffscreenGLSurface(const gfx::Size& size) } case kGLImplementationEGLGLES2: { surface = new GLSurfaceQtEGL(size); - if (surface->Initialize()) + if (surface->Initialize(format)) return surface; // Surfaceless context will be used ONLY if pseudo surfaceless context @@ -649,7 +668,7 @@ CreateOffscreenGLSurface(const gfx::Size& size) // have problems. (e.g. QTBUG-57290) if (g_egl_surfaceless_context_supported) { surface = new GLSurfacelessQtEGL(size); - if (surface->Initialize()) + if (surface->Initialize(format)) return surface; } LOG(WARNING) << "Failed to create offscreen GL surface"; @@ -689,7 +708,7 @@ namespace gpu { class GpuCommandBufferStub; class GpuChannelManager; scoped_refptr<gl::GLSurface> ImageTransportSurface::CreateNativeSurface(base::WeakPtr<ImageTransportSurfaceDelegate>, - SurfaceHandle, gl::GLSurface::Format) + SurfaceHandle, gl::GLSurfaceFormat) { QT_NOT_USED return scoped_refptr<gl::GLSurface>(); diff --git a/src/core/gl_surface_qt.h b/src/core/gl_surface_qt.h index 08b501846..c26cb7ed0 100644 --- a/src/core/gl_surface_qt.h +++ b/src/core/gl_surface_qt.h @@ -59,12 +59,14 @@ public: bool IsOffscreen() override; gfx::SwapResult SwapBuffers() override; gfx::Size GetSize() override; + GLSurfaceFormat GetFormat() override; protected: GLSurfaceQt(); virtual ~GLSurfaceQt(); gfx::Size m_size; + GLSurfaceFormat m_format; private: DISALLOW_COPY_AND_ASSIGN(GLSurfaceQt); diff --git a/src/core/javascript_dialog_manager_qt.cpp b/src/core/javascript_dialog_manager_qt.cpp index 5fac12dd3..a1a8604a4 100644 --- a/src/core/javascript_dialog_manager_qt.cpp +++ b/src/core/javascript_dialog_manager_qt.cpp @@ -48,14 +48,17 @@ namespace QtWebEngineCore { -Q_STATIC_ASSERT_X(static_cast<int>(content::JAVASCRIPT_MESSAGE_TYPE_PROMPT) == static_cast<int>(WebContentsAdapterClient::PromptDialog), "These enums should be in sync."); +ASSERT_ENUMS_MATCH(content::JAVASCRIPT_DIALOG_TYPE_ALERT, WebContentsAdapterClient::AlertDialog) +ASSERT_ENUMS_MATCH(content::JAVASCRIPT_DIALOG_TYPE_CONFIRM, WebContentsAdapterClient::ConfirmDialog) +ASSERT_ENUMS_MATCH(content::JAVASCRIPT_DIALOG_TYPE_PROMPT, WebContentsAdapterClient::PromptDialog) + JavaScriptDialogManagerQt *JavaScriptDialogManagerQt::GetInstance() { return base::Singleton<JavaScriptDialogManagerQt>::get(); } -void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webContents, const GURL &originUrl, content::JavaScriptMessageType javascriptMessageType, const base::string16 &messageText, const base::string16 &defaultPromptText, const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage) +void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webContents, const GURL &originUrl, content::JavaScriptDialogType dialog_type, const base::string16 &messageText, const base::string16 &defaultPromptText, const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage) { WebContentsAdapterClient *client = WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); if (!client) { @@ -64,7 +67,7 @@ void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webCon return; } - WebContentsAdapterClient::JavascriptDialogType dialogType = static_cast<WebContentsAdapterClient::JavascriptDialogType>(javascriptMessageType); + WebContentsAdapterClient::JavascriptDialogType dialogType = static_cast<WebContentsAdapterClient::JavascriptDialogType>(dialog_type); runDialogForContents(webContents, dialogType, toQt(messageText).toHtmlEscaped(), toQt(defaultPromptText).toHtmlEscaped(), toQt(originUrl.GetOrigin()), callback); } diff --git a/src/core/javascript_dialog_manager_qt.h b/src/core/javascript_dialog_manager_qt.h index ad2a54cac..291f027a9 100644 --- a/src/core/javascript_dialog_manager_qt.h +++ b/src/core/javascript_dialog_manager_qt.h @@ -40,7 +40,6 @@ #define JAVASCRIPT_DIALOG_MANAGER_QT_H #include "content/public/browser/javascript_dialog_manager.h" -#include "content/public/common/javascript_message_type.h" #include "web_contents_adapter_client.h" @@ -60,13 +59,15 @@ public: // For use with the Singleton helper class from chromium static JavaScriptDialogManagerQt *GetInstance(); - void RunJavaScriptDialog(content::WebContents *, const GURL &, content::JavaScriptMessageType javascriptMessageType, + void RunJavaScriptDialog(content::WebContents *, const GURL &, content::JavaScriptDialogType dialog_type, const base::string16 &messageText, const base::string16 &defaultPromptText, - const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage) override; + const content::JavaScriptDialogManager::DialogClosedCallback &callback, + bool *didSuppressMessage) override; - void RunBeforeUnloadDialog(content::WebContents *, bool isReload, const content::JavaScriptDialogManager::DialogClosedCallback &callback) override; + void RunBeforeUnloadDialog(content::WebContents *, bool isReload, + const content::JavaScriptDialogManager::DialogClosedCallback &callback) override; bool HandleJavaScriptDialog(content::WebContents *, bool accept, const base::string16 *promptOverride) override; - void CancelDialogs(content::WebContents *contents, bool /*suppress_callbacks*/, bool /*reset_state*/) override + void CancelDialogs(content::WebContents *contents, bool /*reset_state*/) override { takeDialogForContents(contents); } diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index 65c818903..04d4a1924 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -62,9 +62,13 @@ #include "content/public/common/media_stream_request.h" #include "media/audio/audio_device_description.h" #include "media/audio/audio_manager_base.h" +#include "media/media_features.h" +#include "ui/base/l10n/l10n_util.h" + +#if BUILDFLAG(ENABLE_WEBRTC) #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" -#include "ui/base/l10n/l10n_util.h" +#endif #include <QtCore/qcoreapplication.h> @@ -117,13 +121,51 @@ std::unique_ptr<content::MediaStreamUI> getDevicesForDesktopCapture(content::Med return std::move(ui); } +content::DesktopMediaID getDefaultScreenId() +{ +#if BUILDFLAG(ENABLE_WEBRTC) + // Source id patterns are different across platforms. + // On Linux, the hardcoded value "0" is used. + // On Windows, the screens are enumerated consecutively in increasing order from 0. + // On macOS the source ids are randomish numbers assigned by the OS. + + // In order to provide a correct screen id, we query for the available screen ids, and + // select the first one as the main display id. + // The code is based on the file + // src/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc. + webrtc::DesktopCaptureOptions options = + webrtc::DesktopCaptureOptions::CreateDefault(); + options.set_disable_effects(false); + std::unique_ptr<webrtc::DesktopCapturer> screen_capturer( + webrtc::DesktopCapturer::CreateScreenCapturer(options)); + + if (screen_capturer) { + webrtc::DesktopCapturer::SourceList screens; + if (screen_capturer->GetSourceList(&screens)) { + if (screens.size() > 0) { + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, screens[0].id); + } + } + } +#endif + + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); +} + WebContentsAdapterClient::MediaRequestFlags mediaRequestFlagsForRequest(const content::MediaStreamRequest &request) { WebContentsAdapterClient::MediaRequestFlags requestFlags = WebContentsAdapterClient::MediaNone; + if (request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE) requestFlags |= WebContentsAdapterClient::MediaAudioCapture; + else if (request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) + requestFlags |= WebContentsAdapterClient::MediaDesktopAudioCapture; + if (request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) requestFlags |= WebContentsAdapterClient::MediaVideoCapture; + else if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) + requestFlags |= WebContentsAdapterClient::MediaDesktopVideoCapture; + return requestFlags; } @@ -146,6 +188,7 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content: { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + std::unique_ptr<content::MediaStreamUI> ui; content::MediaStreamDevices devices; std::map<content::WebContents*, RequestsQueue>::iterator it = m_pendingRequests.find(webContents); @@ -172,16 +215,30 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content: (request.audio_type && authorizationFlags & WebContentsAdapterClient::MediaAudioCapture); bool webcamRequested = (request.video_type && authorizationFlags & WebContentsAdapterClient::MediaVideoCapture); - if (securityOriginsMatch && (microphoneRequested || webcamRequested)) { - switch (request.request_type) { - case content::MEDIA_OPEN_DEVICE_PEPPER_ONLY: - getDefaultDevices("", "", microphoneRequested, webcamRequested, &devices); - break; - case content::MEDIA_DEVICE_ACCESS: - case content::MEDIA_GENERATE_STREAM: - getDefaultDevices(request.requested_audio_device_id, request.requested_video_device_id, - microphoneRequested, webcamRequested, &devices); - break; + bool desktopAudioRequested = + (request.audio_type && authorizationFlags & WebContentsAdapterClient::MediaDesktopAudioCapture); + bool desktopVideoRequested = + (request.video_type && authorizationFlags & WebContentsAdapterClient::MediaDesktopVideoCapture); + + if (securityOriginsMatch) { + if (microphoneRequested || webcamRequested) { + switch (request.request_type) { + case content::MEDIA_OPEN_DEVICE_PEPPER_ONLY: + getDefaultDevices("", "", microphoneRequested, webcamRequested, &devices); + break; + case content::MEDIA_DEVICE_ACCESS: + case content::MEDIA_GENERATE_STREAM: + getDefaultDevices(request.requested_audio_device_id, request.requested_video_device_id, + microphoneRequested, webcamRequested, &devices); + break; + } + } else if (desktopVideoRequested) { + ui = getDevicesForDesktopCapture( + &devices, + getDefaultScreenId(), + desktopAudioRequested, + /* display_notification: */ false, + getContentsUrl(webContents)); } } @@ -196,7 +253,7 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content: BrowserThread::UI, FROM_HERE, base::Bind(&MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest, base::Unretained(this), webContents)); } - callback.Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, std::unique_ptr<content::MediaStreamUI>()); + callback.Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, std::move(ui)); } @@ -234,22 +291,34 @@ void MediaCaptureDevicesDispatcher::processMediaAccessRequest(WebContentsAdapter , const content::MediaStreamRequest &request , const content::MediaResponseCallback &callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - // Let's not support tab capture for now. - if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE || request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE) - return; - - if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE || request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) - // It's still unclear what to make of screen capture. We can rely on existing javascript dialog infrastructure - // to experiment with this without exposing it through our API yet. - processDesktopCaptureAccessRequest(webContents, request, callback); - else { - enqueueMediaAccessRequest(webContents, request, callback); - // We might not require this approval for pepper requests. - adapterClient->runMediaAccessPermissionRequest(toQt(request.security_origin), mediaRequestFlagsForRequest(request)); - } + // Let's not support tab capture for now. + if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE || request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE) { + callback.Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_NOT_SUPPORTED, std::unique_ptr<content::MediaStreamUI>()); + return; + } + if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE || + request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) { + const bool screenCaptureEnabled = + adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::ScreenCaptureEnabled); + const bool originIsSecure = content::IsOriginSecure(request.security_origin); + if (!screenCaptureEnabled || !originIsSecure) { + callback.Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_INVALID_STATE, std::unique_ptr<content::MediaStreamUI>()); + return; + } + + if (!request.requested_video_device_id.empty()) { + // Non-empty device id from the chooseDesktopMedia() extension API. + processDesktopCaptureAccessRequest(webContents, request, callback); + return; + } + } + + enqueueMediaAccessRequest(webContents, request, callback); + // We might not require this approval for pepper requests. + adapterClient->runMediaAccessPermissionRequest(toQt(request.security_origin), mediaRequestFlagsForRequest(request)); } void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content::WebContents *webContents, const content::MediaStreamRequest &request @@ -258,19 +327,12 @@ void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content:: content::MediaStreamDevices devices; std::unique_ptr<content::MediaStreamUI> ui; - if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE) { + if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE || + request.requested_video_device_id.empty()) { callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, std::move(ui)); return; } - // If the device id wasn't specified then this is a screen capture request - // (i.e. chooseDesktopMedia() API wasn't used to generate device id). - if (request.requested_video_device_id.empty()) { - processScreenCaptureAccessRequest( - webContents, request, callback); - return; - } - content::WebContents* const web_contents_for_stream = content::WebContents::FromRenderFrameHost( content::RenderFrameHost::FromID(request.render_process_id, request.render_frame_id)); content::RenderFrameHost* const main_frame = web_contents_for_stream ? web_contents_for_stream->GetMainFrame() : NULL; @@ -303,84 +365,6 @@ void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content:: callback.Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, std::move(ui)); } -void MediaCaptureDevicesDispatcher::processScreenCaptureAccessRequest(content::WebContents *webContents, const content::MediaStreamRequest &request - ,const content::MediaResponseCallback &callback) -{ - DCHECK_EQ(request.video_type, content::MEDIA_DESKTOP_VIDEO_CAPTURE); - - WebContentsAdapterClient *adapterClient = WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client(); - const bool screenCaptureEnabled = adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::ScreenCaptureEnabled); - - const bool originIsSecure = content::IsOriginSecure(request.security_origin); - - if (screenCaptureEnabled && originIsSecure) { - - enqueueMediaAccessRequest(webContents, request, callback); - base::Callback<void(bool, const base::string16&)> dialogCallback = base::Bind(&MediaCaptureDevicesDispatcher::handleScreenCaptureAccessRequest, - base::Unretained(this), base::Unretained(webContents)); - - QUrl securityOrigin(toQt(request.security_origin)); - QString message = QCoreApplication::translate("MediaCaptureDevicesDispatcher", "Do you want %1 to share your screen?").arg(securityOrigin.toString()); - QString title = QCoreApplication::translate("MediaCaptureDevicesDispatcher", "%1 Screen Sharing request").arg(securityOrigin.toString()); - JavaScriptDialogManagerQt::GetInstance()->runDialogForContents(webContents, WebContentsAdapterClient::InternalAuthorizationDialog, message - , QString(), securityOrigin, dialogCallback, title); - } else - callback.Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_INVALID_STATE, std::unique_ptr<content::MediaStreamUI>()); -} - -void MediaCaptureDevicesDispatcher::handleScreenCaptureAccessRequest(content::WebContents *webContents, bool userAccepted, const base::string16 &) -{ - content::MediaStreamDevices devices; - std::unique_ptr<content::MediaStreamUI> ui; - if (userAccepted) { - // Source id patterns are different across platforms. - // On Linux, the hardcoded value "0" is used. - // On Windows, the screens are enumerated consecutively in increasing order from 0. - // On macOS the source ids are randomish numbers assigned by the OS. - webrtc::DesktopCapturer::SourceId id = 0; - -#if defined(ENABLE_WEBRTC) - // In order to provide a correct screen id, we query for the available screen ids, and - // select the first one as the main display id. - // The code is based on the file - // src/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc. - webrtc::DesktopCaptureOptions options = - webrtc::DesktopCaptureOptions::CreateDefault(); - options.set_disable_effects(false); - std::unique_ptr<webrtc::DesktopCapturer> screen_capturer( - webrtc::DesktopCapturer::CreateScreenCapturer(options)); - - if (screen_capturer) { - webrtc::DesktopCapturer::SourceList screens; - if (screen_capturer->GetSourceList(&screens)) { - if (screens.size() > 0) { - id = screens[0].id; - } - } - } -#endif - - content::DesktopMediaID screenId = content::DesktopMediaID( - content::DesktopMediaID::TYPE_SCREEN, id); - ui = getDevicesForDesktopCapture(&devices, screenId, false/*capture_audio*/, false/*display_notification*/, getContentsUrl(webContents)); - } - std::map<content::WebContents*, RequestsQueue>::iterator it = - m_pendingRequests.find(webContents); - if (it == m_pendingRequests.end()) { - // WebContents has been destroyed. Don't need to do anything. - return; - } - - RequestsQueue &queue(it->second); - if (queue.empty()) - return; - - content::MediaResponseCallback callback = queue.front().callback; - queue.pop_front(); - - callback.Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, std::move(ui)); -} - void MediaCaptureDevicesDispatcher::enqueueMediaAccessRequest(content::WebContents *webContents, const content::MediaStreamRequest &request ,const content::MediaResponseCallback &callback) { diff --git a/src/core/media_capture_devices_dispatcher.h b/src/core/media_capture_devices_dispatcher.h index c378c327e..579d159a4 100644 --- a/src/core/media_capture_devices_dispatcher.h +++ b/src/core/media_capture_devices_dispatcher.h @@ -116,8 +116,6 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver, // Helpers for ProcessMediaAccessRequest(). void processDesktopCaptureAccessRequest(content::WebContents *, const content::MediaStreamRequest &, const content::MediaResponseCallback &); - void processScreenCaptureAccessRequest(content::WebContents *,const content::MediaStreamRequest &, const content::MediaResponseCallback &); - void handleScreenCaptureAccessRequest(content::WebContents *, bool userAccepted, const base::string16 &/*unused callback_input*/); void enqueueMediaAccessRequest(content::WebContents *, const content::MediaStreamRequest &, const content::MediaResponseCallback &); void ProcessQueuedAccessRequest(content::WebContents *); diff --git a/src/core/native_web_keyboard_event_qt.cpp b/src/core/native_web_keyboard_event_qt.cpp index 2bb190ceb..c2e48826e 100644 --- a/src/core/native_web_keyboard_event_qt.cpp +++ b/src/core/native_web_keyboard_event_qt.cpp @@ -66,9 +66,9 @@ using blink::WebKeyboardEvent; namespace content { -NativeWebKeyboardEvent::NativeWebKeyboardEvent() - : os_event(0), - skip_in_browser(false) +NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type, int, base::TimeTicks) + : os_event(0) + , skip_in_browser(false) { } diff --git a/src/core/network_delegate_qt.cpp b/src/core/network_delegate_qt.cpp index 9b4c415c9..5878095e6 100644 --- a/src/core/network_delegate_qt.cpp +++ b/src/core/network_delegate_qt.cpp @@ -311,11 +311,6 @@ bool NetworkDelegateQt::OnAreExperimentalCookieFeaturesEnabled() const return false; } -bool NetworkDelegateQt::OnAreStrictSecureCookiesEnabled() const -{ - return false; -} - bool NetworkDelegateQt::OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest&, const GURL&, const GURL&) const { return false; diff --git a/src/core/network_delegate_qt.h b/src/core/network_delegate_qt.h index 4ded56a9d..da5b36d19 100644 --- a/src/core/network_delegate_qt.h +++ b/src/core/network_delegate_qt.h @@ -92,7 +92,6 @@ public: virtual bool OnCanAccessFile(const net::URLRequest& request, const base::FilePath& path) const override; virtual bool OnCanEnablePrivacyMode(const GURL&, const GURL&) const override; virtual bool OnAreExperimentalCookieFeaturesEnabled() const override; - virtual bool OnAreStrictSecureCookiesEnabled() const override; virtual bool OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest&, const GURL&, const GURL&) const override; }; diff --git a/src/core/ozone_platform_qt.cpp b/src/core/ozone_platform_qt.cpp index 9cdafa279..20c1f43c8 100644 --- a/src/core/ozone_platform_qt.cpp +++ b/src/core/ozone_platform_qt.cpp @@ -143,7 +143,7 @@ public: ui::CursorFactoryOzone* GetCursorFactoryOzone() override; GpuPlatformSupportHost* GetGpuPlatformSupportHost() override; std::unique_ptr<PlatformWindow> CreatePlatformWindow(PlatformWindowDelegate* delegate, const gfx::Rect& bounds) override; - std::unique_ptr<ui::NativeDisplayDelegate> CreateNativeDisplayDelegate() override; + std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate() override; ui::InputController* GetInputController() override; std::unique_ptr<ui::SystemInputInjector> CreateSystemInputInjector() override; ui::OverlayManagerOzone* GetOverlayManager() override; @@ -202,7 +202,7 @@ ui::OverlayManagerOzone* OzonePlatformQt::GetOverlayManager() return overlay_manager_.get(); } -std::unique_ptr<ui::NativeDisplayDelegate> OzonePlatformQt::CreateNativeDisplayDelegate() +std::unique_ptr<display::NativeDisplayDelegate> OzonePlatformQt::CreateNativeDisplayDelegate() { NOTREACHED(); return nullptr; diff --git a/src/core/pdfium_document_wrapper_qt.cpp b/src/core/pdfium_document_wrapper_qt.cpp index 7c43c77db..df829a426 100644 --- a/src/core/pdfium_document_wrapper_qt.cpp +++ b/src/core/pdfium_document_wrapper_qt.cpp @@ -36,7 +36,12 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#if defined (ENABLE_PDF) +#include "pdf/features.h" +#if BUILDFLAG(ENABLE_PDF) +#define ENABLE_PDF +#endif + +#if defined(ENABLE_PDF) #include "pdfium_document_wrapper_qt.h" #include <QtCore/qhash.h> diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index 970a608a3..4c941406c 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -202,14 +202,6 @@ void PermissionManagerQt::ResetPermission( m_permissions.remove(key); } -void PermissionManagerQt::RegisterPermissionUsage( - content::PermissionType /*permission*/, - const GURL& /*requesting_origin*/, - const GURL& /*embedding_origin*/) -{ - // We do not currently track which permissions are used. -} - int PermissionManagerQt::SubscribePermissionStatusChange( content::PermissionType permission, const GURL& requesting_origin, diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h index 1cbb41b5e..e98174762 100644 --- a/src/core/permission_manager_qt.h +++ b/src/core/permission_manager_qt.h @@ -87,11 +87,6 @@ public: const base::Callback<void( const std::vector<blink::mojom::PermissionStatus>&)>& callback) override; - void RegisterPermissionUsage( - content::PermissionType permission, - const GURL& requesting_origin, - const GURL& embedding_origin) override; - int SubscribePermissionStatusChange( content::PermissionType permission, const GURL& requesting_origin, diff --git a/src/core/print_view_manager_base_qt.cpp b/src/core/print_view_manager_base_qt.cpp index 81e07707a..50b529efa 100644 --- a/src/core/print_view_manager_base_qt.cpp +++ b/src/core/print_view_manager_base_qt.cpp @@ -68,7 +68,9 @@ namespace QtWebEngineCore { PrintViewManagerBaseQt::PrintViewManagerBaseQt(content::WebContents *contents) : printing::PrintManager(contents) , m_isInsideInnerMessageLoop(false) +#if !defined(OS_MACOSX) , m_isExpectingFirstPage(false) +#endif , m_didPrintingSucceed(false) , m_printerQueriesQueue(WebEngineContext::current()->getPrintJobManager()->queue()) { diff --git a/src/core/print_view_manager_base_qt.h b/src/core/print_view_manager_base_qt.h index 65bdbe3f1..9b302f960 100644 --- a/src/core/print_view_manager_base_qt.h +++ b/src/core/print_view_manager_base_qt.h @@ -146,7 +146,9 @@ private: base::Closure m_quitClosure; bool m_isInsideInnerMessageLoop; +#if !defined(OS_MACOSX) bool m_isExpectingFirstPage; +#endif bool m_didPrintingSucceed; scoped_refptr<printing::PrintQueriesQueue> m_printerQueriesQueue; // content::WebContentsObserver implementation. diff --git a/src/core/print_view_manager_qt.cpp b/src/core/print_view_manager_qt.cpp index 8a43cc419..6493bb7d5 100644 --- a/src/core/print_view_manager_qt.cpp +++ b/src/core/print_view_manager_qt.cpp @@ -138,6 +138,7 @@ static base::DictionaryValue *createPrintSettings() printSettings->SetBoolean(printing::kSettingShouldPrintSelectionOnly, false); printSettings->SetBoolean(printing::kSettingShouldPrintBackgrounds, true); printSettings->SetBoolean(printing::kSettingHeaderFooterEnabled, false); + printSettings->SetBoolean(printing::kSettingRasterizePdf, false); printSettings->SetInteger(printing::kSettingScaleFactor, 100); printSettings->SetString(printing::kSettingDeviceName, ""); printSettings->SetInteger(printing::kPreviewUIID, 12345678); diff --git a/src/core/qtwebengine.gni b/src/core/qtwebengine.gni index bb269baa2..c9f766a36 100644 --- a/src/core/qtwebengine.gni +++ b/src/core/qtwebengine.gni @@ -1,3 +1,4 @@ +import("//media/media_options.gni") import("//third_party/widevine/cdm/widevine.gni") chromium_version = exec_script("//build/util/version.py", [ "-f", rebase_path("//chrome/VERSION"), @@ -11,6 +12,7 @@ include_dirs = [ deps = [ "//base", + "//chrome/common:features", "//components/error_page/common", "//components/keyed_service/content", "//components/visitedlink/browser", @@ -22,10 +24,11 @@ deps = [ "//content/public/browser", "//content/public/common", "//content/public/renderer", + "//media:media_features", "//net:net_browser_services", + "//net:net_with_v8", "//skia", "//third_party/WebKit/public:blink", - "//third_party/webrtc/base:base", "//ui/accessibility", "//third_party/mesa:mesa_headers", ":qtwebengine_sources", @@ -36,6 +39,10 @@ if (enable_widevine) { deps += [ "//components/cdm/renderer"] } +if (enable_webrtc) { + deps += [ "//third_party/webrtc/base:base" ] +} + if (is_linux && !is_desktop_linux) { deps += [ "//ui/events/ozone:events_ozone_evdev"] } diff --git a/src/core/qtwebengine_resources.gni b/src/core/qtwebengine_resources.gni index a7ffb40f3..acf5f1590 100644 --- a/src/core/qtwebengine_resources.gni +++ b/src/core/qtwebengine_resources.gni @@ -70,7 +70,7 @@ repack("qtwebengine_repack_resources_200") { repack("qtwebengine_repack_resources_devtools") { sources = [ - "$root_gen_dir/blink/devtools_resources.pak", + "$root_gen_dir/content/browser/devtools/devtools_resources.pak", ] output = "$root_out_dir/qtwebengine_devtools_resources.pak" deps = [ diff --git a/src/core/qtwebengine_sources.gni b/src/core/qtwebengine_sources.gni index 9a559732d..785c252cb 100644 --- a/src/core/qtwebengine_sources.gni +++ b/src/core/qtwebengine_sources.gni @@ -1,5 +1,8 @@ import("//build/config/features.gni") +import("//build/config/ui.gni") import("//components/spellcheck/spellcheck_build_features.gni") +import("//pdf/features.gni") +import("//ppapi/features/features.gni") import("//printing/features/features.gni") source_set("qtwebengine_spellcheck_sources") { @@ -99,10 +102,10 @@ source_set("qtwebengine_sources") { if (enable_pdf) { deps += [ "//pdf", + "//pdf:features", "//components/printing/browser", "//components/printing/renderer", ] } - } diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index dd372b72f..0c98c9e21 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -104,9 +104,9 @@ enum ImStateFlags { static inline ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) { ui::LatencyInfo latency_info; // The latency number should only be added if the timestamp is valid. - if (event.timeStampSeconds) { + if (event.timeStampSeconds()) { const int64_t time_micros = static_cast<int64_t>( - event.timeStampSeconds * base::Time::kMicrosecondsPerSecond); + event.timeStampSeconds() * base::Time::kMicrosecondsPerSecond); latency_info.AddLatencyNumberWithTimestamp( ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, @@ -639,39 +639,11 @@ void RenderWidgetHostViewQt::SetTooltipText(const base::string16 &tooltip_text) m_adapterClient->setToolTip(toQt(tooltip_text)); } -void RenderWidgetHostViewQt::CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, const content::ReadbackRequestCallback& callback, const SkColorType color_type) -{ - NOTIMPLEMENTED(); - Q_UNUSED(src_subrect); - Q_UNUSED(dst_size); - Q_UNUSED(color_type); - callback.Run(SkBitmap(), content::READBACK_FAILED); -} - -void RenderWidgetHostViewQt::CopyFromCompositingSurfaceToVideoFrame(const gfx::Rect& src_subrect, const scoped_refptr<media::VideoFrame>& target, const base::Callback<void(const gfx::Rect&, bool)>& callback) -{ - NOTIMPLEMENTED(); - callback.Run(gfx::Rect(), false); -} - -bool RenderWidgetHostViewQt::CanCopyToVideoFrame() const -{ - return false; -} - bool RenderWidgetHostViewQt::HasAcceleratedSurface(const gfx::Size&) { return false; } -void RenderWidgetHostViewQt::LockCompositingSurface() -{ -} - -void RenderWidgetHostViewQt::UnlockCompositingSurface() -{ -} - void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32_t output_surface_id, cc::CompositorFrame frame) { bool scrollOffsetChanged = (m_lastScrollOffset != frame.metadata.root_scroll_offset); @@ -681,12 +653,9 @@ void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32_t output_surface_id, c Q_ASSERT(!m_needsDelegatedFrameAck); m_needsDelegatedFrameAck = true; m_pendingOutputSurfaceId = output_surface_id; - Q_ASSERT(frame.delegated_frame_data); - Q_ASSERT(!m_chromiumCompositorData->frameData || m_chromiumCompositorData->frameData->resource_list.empty()); - if (m_chromiumCompositorData->frameData.get()) - m_chromiumCompositorData->previousFrameData = std::move(m_chromiumCompositorData->frameData); - m_chromiumCompositorData->frameData = std::move(frame.delegated_frame_data); + m_chromiumCompositorData->previousFrameData = std::move(m_chromiumCompositorData->frameData); m_chromiumCompositorData->frameDevicePixelRatio = frame.metadata.device_scale_factor; + m_chromiumCompositorData->frameData = std::move(frame); // Support experimental.viewport.devicePixelRatio, see GetScreenInfo implementation below. float dpiScale = this->dpiScale(); @@ -788,8 +757,12 @@ void RenderWidgetHostViewQt::OnTextSelectionChanged(content::TextInputManager *t Q_UNUSED(text_input_manager); Q_UNUSED(updated_view); + const content::TextInputManager::TextSelection *selection = GetTextInputManager()->GetTextSelection(updated_view); + if (!selection) + return; + #if defined(USE_X11) - if (!GetSelectedText().empty()) { + if (!GetSelectedText().empty() && selection->user_initiated()) { // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard. ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_SELECTION); clipboard_writer.WriteText(GetSelectedText()); @@ -824,29 +797,34 @@ void RenderWidgetHostViewQt::selectionChanged() return; } - const content::TextInputManager::TextSelection *selection = text_input_manager_->GetTextSelection(); - if (!selection) + if (GetSelectedText().empty()) { + m_anchorPositionWithinSelection = m_cursorPosition; + m_cursorPositionWithinSelection = m_cursorPosition; + + if (!m_emptyPreviousSelection) { + m_emptyPreviousSelection = GetSelectedText().empty(); + m_adapterClient->selectionChanged(); + } + return; + } - if (!selection->range.IsValid()) + const content::TextInputManager::TextSelection *selection = text_input_manager_->GetTextSelection(); + if (!selection) return; - // Avoid duplicate empty selectionChanged() signals - if (GetSelectedText().empty() && m_emptyPreviousSelection) { - m_anchorPositionWithinSelection = m_cursorPosition; - m_cursorPositionWithinSelection = m_cursorPosition; + if (!selection->range().IsValid()) return; - } int newAnchorPositionWithinSelection = 0; int newCursorPositionWithinSelection = 0; if (text_input_manager_->GetSelectionRegion()->anchor.type() == gfx::SelectionBound::RIGHT) { - newAnchorPositionWithinSelection = selection->range.GetMax() - selection->offset; - newCursorPositionWithinSelection = selection->range.GetMin() - selection->offset; + newAnchorPositionWithinSelection = selection->range().GetMax() - selection->offset(); + newCursorPositionWithinSelection = selection->range().GetMin() - selection->offset(); } else { - newAnchorPositionWithinSelection = selection->range.GetMin() - selection->offset; - newCursorPositionWithinSelection = selection->range.GetMax() - selection->offset; + newAnchorPositionWithinSelection = selection->range().GetMin() - selection->offset(); + newCursorPositionWithinSelection = selection->range().GetMax() - selection->offset(); } if (m_anchorPositionWithinSelection == newAnchorPositionWithinSelection && m_cursorPositionWithinSelection == newCursorPositionWithinSelection) @@ -1010,7 +988,8 @@ void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWit void RenderWidgetHostViewQt::sendDelegatedFrameAck() { - m_beginFrameSource->DidFinishFrame(this, 0); + const cc::BeginFrameAck ack; + m_beginFrameSource->DidFinishFrame(this, ack); cc::ReturnedResourceArray resources; m_resourcesToRelease.swap(resources); content::RenderWidgetHostImpl::SendReclaimCompositorResources( @@ -1068,7 +1047,7 @@ void RenderWidgetHostViewQt::handleMouseEvent(QMouseEvent* event) return; blink::WebMouseEvent webEvent = WebEventFactory::toWebMouseEvent(event, dpiScale()); - if ((webEvent.type == blink::WebInputEvent::MouseDown || webEvent.type == blink::WebInputEvent::MouseUp) + if ((webEvent.type() == blink::WebInputEvent::MouseDown || webEvent.type() == blink::WebInputEvent::MouseUp) && webEvent.button == blink::WebMouseEvent::Button::NoButton) { // Blink can only handle the 3 main mouse-buttons and may assert when processing mouse-down for no button. return; @@ -1139,7 +1118,7 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) } content::NativeWebKeyboardEvent webEvent = WebEventFactory::toWebKeyboardEvent(ev); - bool keyDownTextInsertion = webEvent.type == blink::WebInputEvent::RawKeyDown && webEvent.text[0]; + bool keyDownTextInsertion = webEvent.type() == blink::WebInputEvent::RawKeyDown && webEvent.text[0]; webEvent.skip_in_browser = keyDownTextInsertion; m_host->ForwardKeyboardEvent(webEvent); @@ -1148,7 +1127,7 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev) // The RawKeyDown is skipped on the way back (see above). // The same os_event will be set on both NativeWebKeyboardEvents. webEvent.skip_in_browser = false; - webEvent.type = blink::WebInputEvent::Char; + webEvent.setType(blink::WebInputEvent::Char); m_host->ForwardKeyboardEvent(webEvent); } } diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 3b679923e..cb1a5980d 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -148,10 +148,6 @@ public: void RenderProcessGone(base::TerminationStatus, int) override; void Destroy() override; void SetTooltipText(const base::string16 &tooltip_text) override; - void CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& dst_size, const content::ReadbackRequestCallback& callback, const SkColorType preferred_color_type) override; - void CopyFromCompositingSurfaceToVideoFrame(const gfx::Rect& src_subrect, const scoped_refptr<media::VideoFrame>& target, const base::Callback<void(const gfx::Rect&, bool)>& callback) override; - - bool CanCopyToVideoFrame() const override; bool HasAcceleratedSurface(const gfx::Size&) override; void OnSwapCompositorFrame(uint32_t output_surface_id, cc::CompositorFrame frame) override; @@ -159,8 +155,6 @@ public: gfx::Rect GetBoundsInRootWindow() override; void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) override; void ClearCompositorFrame() override; - void LockCompositingSurface() override; - void UnlockCompositingSurface() override; void SetNeedsBeginFrames(bool needs_begin_frames) override; // Overridden from ui::GestureProviderClient. diff --git a/src/core/render_widget_host_view_qt_delegate.h b/src/core/render_widget_host_view_qt_delegate.h index dda59a01a..7461e7608 100644 --- a/src/core/render_widget_host_view_qt_delegate.h +++ b/src/core/render_widget_host_view_qt_delegate.h @@ -58,16 +58,9 @@ class QVariant; class QWindow; class QInputMethodEvent; -#if (QT_VERSION < QT_VERSION_CHECK(5, 8, 0)) -class QSGImageNode; -typedef QSGImageNode QSGInternalImageNode; -class QSGSimpleTextureNode; -typedef QSGSimpleTextureNode QSGTextureNode; -#else class QSGInternalImageNode; class QSGImageNode; typedef QSGImageNode QSGTextureNode; -#endif QT_END_NAMESPACE diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index a2c2a722e..f09aa48f0 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -63,7 +63,6 @@ #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURLError.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" -#include "third_party/WebKit/public/web/WebSecurityPolicy.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h" #include "content/public/common/web_preferences.h" @@ -85,7 +84,6 @@ namespace QtWebEngineCore { static const char kHttpErrorDomain[] = "http"; -static const char kQrcSchemeQt[] = "qrc"; ContentRendererClientQt::ContentRendererClientQt() { @@ -108,10 +106,6 @@ void ContentRendererClientQt::RenderThreadStarted() m_spellCheck.reset(new SpellCheck()); renderThread->AddObserver(m_spellCheck.data()); #endif - - blink::WebString qrcScheme(base::ASCIIToUTF16(kQrcSchemeQt)); - // mark qrc as a secure scheme (avoids deprecation warnings) - blink::WebSecurityPolicy::registerURLSchemeAsSecure(qrcScheme); } void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view) diff --git a/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp b/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp index a46454407..3a34d5f93 100644 --- a/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp +++ b/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp @@ -48,7 +48,8 @@ #include <vector> #include "base/lazy_instance.h" -#include "base/metrics/histogram.h" +#include "base/macros.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "content/public/renderer/pepper_plugin_instance.h" #include "content/public/renderer/render_thread.h" diff --git a/src/core/renderer/render_frame_observer_qt.cpp b/src/core/renderer/render_frame_observer_qt.cpp index 53e9407db..111323b8a 100644 --- a/src/core/renderer/render_frame_observer_qt.cpp +++ b/src/core/renderer/render_frame_observer_qt.cpp @@ -64,7 +64,7 @@ RenderFrameObserverQt::~RenderFrameObserverQt() { } -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) void RenderFrameObserverQt::DidCreatePepperPlugin(content::RendererPpapiHost* host) { host->GetPpapiHost()->AddHostFactoryFilter( diff --git a/src/core/renderer/render_frame_observer_qt.h b/src/core/renderer/render_frame_observer_qt.h index b74be5cd1..7abd17e96 100644 --- a/src/core/renderer/render_frame_observer_qt.h +++ b/src/core/renderer/render_frame_observer_qt.h @@ -43,6 +43,7 @@ #include "base/compiler_specific.h" #include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_frame_observer_tracker.h" +#include "ppapi/features/features.h" namespace content { @@ -59,7 +60,7 @@ public: explicit RenderFrameObserverQt(content::RenderFrame* render_frame); ~RenderFrameObserverQt(); -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) void DidCreatePepperPlugin(content::RendererPpapiHost* host) override; #endif void OnDestruct() override { } diff --git a/src/core/renderer/render_view_observer_qt.cpp b/src/core/renderer/render_view_observer_qt.cpp index 97485afad..54aed8b59 100644 --- a/src/core/renderer/render_view_observer_qt.cpp +++ b/src/core/renderer/render_view_observer_qt.cpp @@ -65,7 +65,7 @@ void RenderViewObserverQt::onFetchDocumentMarkup(quint64 requestId) if (render_view()->GetWebView()->mainFrame()->isWebLocalFrame()) markup = blink::WebFrameContentDumper::dumpAsMarkup( static_cast<blink::WebLocalFrame*>(render_view()->GetWebView()->mainFrame())); - Send(new RenderViewObserverHostQt_DidFetchDocumentMarkup(routing_id(), requestId, markup)); + Send(new RenderViewObserverHostQt_DidFetchDocumentMarkup(routing_id(), requestId, markup.utf16())); } void RenderViewObserverQt::onFetchDocumentInnerText(quint64 requestId) @@ -75,7 +75,7 @@ void RenderViewObserverQt::onFetchDocumentInnerText(quint64 requestId) text = blink::WebFrameContentDumper::dumpWebViewAsText( render_view()->GetWebView(), std::numeric_limits<std::size_t>::max()); - Send(new RenderViewObserverHostQt_DidFetchDocumentInnerText(routing_id(), requestId, text)); + Send(new RenderViewObserverHostQt_DidFetchDocumentInnerText(routing_id(), requestId, text.utf16())); } void RenderViewObserverQt::onSetBackgroundColor(quint32 color) diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp index 161d6f493..f34e1310b 100644 --- a/src/core/renderer/web_channel_ipc_transport.cpp +++ b/src/core/renderer/web_channel_ipc_transport.cpp @@ -68,25 +68,30 @@ private: WebChannelTransport() { } virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate *isolate) override; - void NativeQtSendMessage(gin::Arguments *args) + bool NativeQtSendMessage(gin::Arguments *args) { content::RenderView *renderView = GetRenderView(args->isolate()); if (!renderView || args->Length() != 1) - return; + return false; v8::Handle<v8::Value> val; args->GetNext(&val); if (!val->IsString() && !val->IsStringObject()) - return; + return false; v8::String::Utf8Value utf8(val->ToString()); QByteArray valueData(*utf8, utf8.length()); QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(valueData, &error); - if (error.error != QJsonParseError::NoError) + if (error.error != QJsonParseError::NoError) { qWarning("%s %d: Parsing error: %s",__FILE__, __LINE__, qPrintable(error.errorString())); + return false; + } int size = 0; const char *rawData = doc.rawData(&size); + if (size == 0) + return false; renderView->Send(new WebChannelIPCTransportHost_SendMessage(renderView->GetRoutingID(), std::vector<char>(rawData, rawData + size))); + return true; } DISALLOW_COPY_AND_ASSIGN(WebChannelTransport); @@ -102,7 +107,7 @@ void WebChannelTransport::Install(blink::WebFrame *frame, uint worldId) if (worldId == 0) context = frame->mainWorldScriptContext(); else - context = frame->toWebLocalFrame()->isolatedWorldScriptContext(worldId, 0); + context = frame->toWebLocalFrame()->isolatedWorldScriptContext(worldId); v8::Context::Scope contextScope(context); gin::Handle<WebChannelTransport> transport = gin::CreateHandle(isolate, new WebChannelTransport); @@ -123,7 +128,7 @@ void WebChannelTransport::Uninstall(blink::WebFrame *frame, uint worldId) if (worldId == 0) context = frame->mainWorldScriptContext(); else - context = frame->toWebLocalFrame()->isolatedWorldScriptContext(worldId, 0); + context = frame->toWebLocalFrame()->isolatedWorldScriptContext(worldId); v8::Context::Scope contextScope(context); v8::Handle<v8::Object> global(context->Global()); @@ -206,7 +211,7 @@ void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector<char> & if (worldId == 0) context = frame->mainWorldScriptContext(); else - context = frame->toWebLocalFrame()->isolatedWorldScriptContext(worldId, 0); + context = frame->toWebLocalFrame()->isolatedWorldScriptContext(worldId); v8::Context::Scope contextScope(context); v8::Handle<v8::Object> global(context->Global()); diff --git a/src/core/renderer_host/user_resource_controller_host.cpp b/src/core/renderer_host/user_resource_controller_host.cpp index 95385ae2f..0a6decaf9 100644 --- a/src/core/renderer_host/user_resource_controller_host.cpp +++ b/src/core/renderer_host/user_resource_controller_host.cpp @@ -140,7 +140,7 @@ void UserResourceControllerHost::addUserScript(const UserScript &script, WebCont m_perContentsScripts.insert(contents, currentScripts); } } - contents->Send(new RenderViewObserverHelper_AddScript(contents->GetRoutingID(), script.data())); + contents->Send(new RenderViewObserverHelper_AddScript(contents->GetRenderViewHost()->GetRoutingID(), script.data())); } } @@ -174,7 +174,7 @@ bool UserResourceControllerHost::removeUserScript(const UserScript &script, WebC QList<UserScript>::iterator it = std::find(list.begin(), list.end(), script); if (it == list.end()) return false; - contents->Send(new RenderViewObserverHelper_RemoveScript(contents->GetRoutingID(), (*it).data())); + contents->Send(new RenderViewObserverHelper_RemoveScript(contents->GetRenderViewHost()->GetRoutingID(), (*it).data())); list.erase(it); } return true; @@ -189,7 +189,7 @@ void UserResourceControllerHost::clearAllScripts(WebContentsAdapter *adapter) } else { content::WebContents *contents = adapter->webContents(); m_perContentsScripts.remove(contents); - contents->Send(new RenderViewObserverHelper_ClearScripts(contents->GetRoutingID())); + contents->Send(new RenderViewObserverHelper_ClearScripts(contents->GetRenderViewHost()->GetRoutingID())); } } diff --git a/src/core/renderer_host/web_channel_ipc_transport_host.cpp b/src/core/renderer_host/web_channel_ipc_transport_host.cpp index aef16f0a0..1cd4e4063 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.cpp +++ b/src/core/renderer_host/web_channel_ipc_transport_host.cpp @@ -87,6 +87,7 @@ void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message) void WebChannelIPCTransportHost::onWebChannelMessage(const std::vector<char> &message) { + Q_ASSERT(!message.empty()); QJsonDocument doc = QJsonDocument::fromRawData(message.data(), message.size(), QJsonDocument::BypassValidation); Q_ASSERT(doc.isObject()); Q_EMIT messageReceived(doc.object(), this); diff --git a/src/core/resource_bundle_qt.cpp b/src/core/resource_bundle_qt.cpp index cc3c1de06..c37854ea6 100644 --- a/src/core/resource_bundle_qt.cpp +++ b/src/core/resource_bundle_qt.cpp @@ -38,7 +38,7 @@ ****************************************************************************/ #include "base/command_line.h" -#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "content/public/common/content_switches.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/data_pack.h" diff --git a/src/core/surface_factory_qt.cpp b/src/core/surface_factory_qt.cpp index 36c05ec5d..9e72885c3 100644 --- a/src/core/surface_factory_qt.cpp +++ b/src/core/surface_factory_qt.cpp @@ -44,7 +44,12 @@ #include "base/files/file_path.h" #include "base/native_library.h" +#include "ui/gl/gl_context_egl.h" #include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_surface.h" +#include "ui/gl/init/gl_initializer.h" +#include "ui/gl/init/gl_factory.h" +#include "ui/ozone/common/gl_ozone_egl.h" #include <QGuiApplication> @@ -61,6 +66,27 @@ namespace QtWebEngineCore { +class GLOzoneQt : public ui::GLOzoneEGL { +public: + scoped_refptr<gl::GLSurface> CreateViewGLSurface(gfx::AcceleratedWidget /*window*/) override + { + return nullptr; + } + scoped_refptr<gl::GLSurface> CreateOffscreenGLSurface(const gfx::Size& /*size*/) override + { + return nullptr; + } + +protected: + // Returns native platform display handle. This is used to obtain the EGL + // display connection for the native display. + intptr_t GetNativeDisplay() override; + + // Sets up GL bindings for the native surface. + bool LoadGLES2Bindings() override; + +}; + base::NativeLibrary LoadLibrary(const base::FilePath& filename) { base::NativeLibraryLoadError error; base::NativeLibrary library = base::LoadNativeLibrary(filename, &error); @@ -71,7 +97,7 @@ base::NativeLibrary LoadLibrary(const base::FilePath& filename) { return library; } -bool SurfaceFactoryQt::LoadEGLGLES2Bindings() +bool GLOzoneQt::LoadGLES2Bindings() { base::FilePath libEGLPath = QtWebEngineCore::toFilePath(QT_LIBDIR_EGL); libEGLPath = libEGLPath.Append("libEGL.so.1"); @@ -99,7 +125,7 @@ bool SurfaceFactoryQt::LoadEGLGLES2Bindings() return true; } -intptr_t SurfaceFactoryQt::GetNativeDisplay() +intptr_t GLOzoneQt::GetNativeDisplay() { static void *display = GLContextHelper::getNativeDisplay(); @@ -109,6 +135,18 @@ intptr_t SurfaceFactoryQt::GetNativeDisplay() return reinterpret_cast<intptr_t>(EGL_DEFAULT_DISPLAY); } +std::vector<gl::GLImplementation> SurfaceFactoryQt::GetAllowedGLImplementations() +{ + std::vector<gl::GLImplementation> impls; + impls.push_back(gl::kGLImplementationEGLGLES2); + return impls; +} + +ui::GLOzone* SurfaceFactoryQt::GetGLOzone(gl::GLImplementation implementation) +{ + return new GLOzoneQt(); +} + } // namespace QtWebEngineCore #endif // defined(USE_OZONE) diff --git a/src/core/surface_factory_qt.h b/src/core/surface_factory_qt.h index 76b6dc6ed..b7991829c 100644 --- a/src/core/surface_factory_qt.h +++ b/src/core/surface_factory_qt.h @@ -46,11 +46,10 @@ namespace QtWebEngineCore { -class SurfaceFactoryQt - : public ui::SurfaceFactoryOzone +class SurfaceFactoryQt : public ui::SurfaceFactoryOzone { - bool LoadEGLGLES2Bindings() override; - intptr_t GetNativeDisplay() override; + std::vector<gl::GLImplementation> GetAllowedGLImplementations() override; + ui::GLOzone* GetGLOzone(gl::GLImplementation implementation) override; }; } // namespace QtWebEngineCore diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp index 1f3d6fcbe..fe1758655 100644 --- a/src/core/url_request_context_getter_qt.cpp +++ b/src/core/url_request_context_getter_qt.cpp @@ -295,8 +295,7 @@ void URLRequestContextGetterQt::generateCookieStore() m_storage->set_channel_id_service( base::WrapUnique(new net::ChannelIDService( - new net::DefaultChannelIDStore(channel_id_db.get()), - base::WorkerPool::GetTaskRunner(true)))); + new net::DefaultChannelIDStore(channel_id_db.get())))); // Unset it first to get a chance to destroy and flush the old cookie store before opening a new on possibly the same file. m_storage->set_cookie_store(0); @@ -572,10 +571,11 @@ void URLRequestContextGetterQt::generateJobFactory() // Set up interceptors in the reverse order. std::unique_ptr<net::URLRequestJobFactory> topJobFactory = std::move(jobFactory); - for (content::URLRequestInterceptorScopedVector::reverse_iterator i = m_requestInterceptors.rbegin(); i != m_requestInterceptors.rend(); ++i) - topJobFactory.reset(new net::URLRequestInterceptingJobFactory(std::move(topJobFactory), std::unique_ptr<net::URLRequestInterceptor>(*i))); + for (content::URLRequestInterceptorScopedVector::reverse_iterator i = m_requestInterceptors.rbegin(); i != m_requestInterceptors.rend(); ++i) { + topJobFactory.reset(new net::URLRequestInterceptingJobFactory(std::move(topJobFactory), std::move(*i))); + } - m_requestInterceptors.weak_clear(); + m_requestInterceptors.clear(); m_jobFactory = std::move(topJobFactory); diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 8273b247f..c9b46b38a 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -50,7 +50,6 @@ #include "browser_context_qt.h" #include "download_manager_delegate_qt.h" #include "media_capture_devices_dispatcher.h" -#include "pdfium_document_wrapper_qt.h" #include "print_view_manager_qt.h" #include "qwebenginecallback_p.h" #include "renderer_host/web_channel_ipc_transport_host.h" @@ -108,37 +107,37 @@ static QVariant fromJSValue(const base::Value *result) { QVariant ret; switch (result->GetType()) { - case base::Value::TYPE_NULL: + case base::Value::Type::NONE: break; - case base::Value::TYPE_BOOLEAN: + case base::Value::Type::BOOLEAN: { bool out; if (result->GetAsBoolean(&out)) ret.setValue(out); break; } - case base::Value::TYPE_INTEGER: + case base::Value::Type::INTEGER: { int out; if (result->GetAsInteger(&out)) ret.setValue(out); break; } - case base::Value::TYPE_DOUBLE: + case base::Value::Type::DOUBLE: { double out; if (result->GetAsDouble(&out)) ret.setValue(out); break; } - case base::Value::TYPE_STRING: + case base::Value::Type::STRING: { base::string16 out; if (result->GetAsString(&out)) ret.setValue(toQt(out)); break; } - case base::Value::TYPE_LIST: + case base::Value::Type::LIST: { const base::ListValue *out; if (result->GetAsList(&out)) { @@ -153,7 +152,7 @@ static QVariant fromJSValue(const base::Value *result) } break; } - case base::Value::TYPE_DICTIONARY: + case base::Value::Type::DICTIONARY: { const base::DictionaryValue *out; if (result->GetAsDictionary(&out)) { @@ -167,7 +166,7 @@ static QVariant fromJSValue(const base::Value *result) } break; } - case base::Value::TYPE_BINARY: + case base::Value::Type::BINARY: { const base::BinaryValue *out = static_cast<const base::BinaryValue*>(result); QByteArray data(out->GetBuffer(), out->GetSize()); @@ -500,14 +499,14 @@ void WebContentsAdapter::stop() void WebContentsAdapter::reload() { Q_D(WebContentsAdapter); - d->webContents->GetController().Reload(/*checkRepost = */false); + d->webContents->GetController().Reload(content::ReloadType::NORMAL, /*checkRepost = */false); focusIfNecessary(); } void WebContentsAdapter::reloadAndBypassCache() { Q_D(WebContentsAdapter); - d->webContents->GetController().ReloadBypassingCache(/*checkRepost = */false); + d->webContents->GetController().Reload(content::ReloadType::BYPASSING_CACHE, /*checkRepost = */false); focusIfNecessary(); } @@ -609,7 +608,7 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; d->webContents->GetController().LoadURLWithParams(params); focusIfNecessary(); - d->webContents->Unselect(); + d->webContents->CollapseSelection(); } void WebContentsAdapter::save(const QString &filePath, int savePageFormat) @@ -717,7 +716,7 @@ void WebContentsAdapter::requestClose() void WebContentsAdapter::unselect() { Q_D(const WebContentsAdapter); - d->webContents->Unselect(); + d->webContents->CollapseSelection(); } void WebContentsAdapter::navigateToIndex(int offset) @@ -917,7 +916,7 @@ void WebContentsAdapter::stopFinding() d->webContentsDelegate->setLastSearchedString(QString()); // Clear any previous selection, // but keep the renderer blue rectangle selection just like Chromium does. - d->webContents->Unselect(); + d->webContents->CollapseSelection(); d->webContents->StopFinding(content::STOP_FIND_ACTION_KEEP_SELECTION); } @@ -1194,16 +1193,14 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD d->currentDropData.reset(new content::DropData(dropData)); d->currentDropData->download_metadata.clear(); d->currentDropData->file_contents.clear(); - d->currentDropData->file_description_filename.clear(); + d->currentDropData->file_contents_content_disposition.clear(); d->currentDropAction = blink::WebDragOperationNone; QDrag *drag = new QDrag(dragSource); // will be deleted by Qt's DnD implementation bool dValid = true; QMetaObject::Connection onDestroyed = QObject::connect(dragSource, &QObject::destroyed, [&dValid](){ dValid = false; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)) QDrag::cancel(); -#endif }); drag->setMimeData(mimeDataFromDropData(*d->currentDropData)); @@ -1360,7 +1357,7 @@ void WebContentsAdapter::leaveDrag() { Q_D(WebContentsAdapter); content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); - rvh->GetWidget()->DragTargetDragLeave(); + rvh->GetWidget()->DragTargetDragLeave(d->lastDragClientPos, d->lastDragScreenPos); d->currentDropData.reset(); } diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index e1fb3dc4c..8b7365342 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -90,6 +90,7 @@ public: uint mediaFlags; QPoint pos; QUrl linkUrl; + QUrl unfilteredLinkUrl; QUrl mediaUrl; QString linkText; QString selectedText; @@ -156,6 +157,14 @@ public: return d->linkUrl; } + void setUnfilteredLinkUrl(const QUrl &url) { + d->unfilteredLinkUrl = url; + } + + QUrl unfilteredLinkUrl() const { + return d->unfilteredLinkUrl; + } + void setLinkText(const QString &text) { d->linkText = text; } @@ -265,7 +274,7 @@ public: IgnoreActionDisposition = 9, }; - // Must match the values in javascript_message_type.h. + // Must match the values in javascript_dialog_type.h. enum JavascriptDialogType { AlertDialog, ConfirmDialog, @@ -307,6 +316,8 @@ public: MediaNone = 0, MediaAudioCapture = 0x01, MediaVideoCapture = 0x02, + MediaDesktopAudioCapture = 0x04, + MediaDesktopVideoCapture = 0x08 }; Q_DECLARE_FLAGS(MediaRequestFlags, MediaRequestFlag) diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 86366abaa..1121714eb 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -63,6 +63,7 @@ #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/public/browser/invalidate_type.h" #include "content/public/browser/navigation_entry.h" +#include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" @@ -169,10 +170,10 @@ void WebContentsDelegateQt::AddNewContents(content::WebContents* source, content void WebContentsDelegateQt::CloseContents(content::WebContents *source) { m_viewClient->close(); - GetJavaScriptDialogManager(source)->CancelDialogs(source, /* whatever?: */false, false); + GetJavaScriptDialogManager(source)->CancelDialogs(source, /* whatever?: */false); } -void WebContentsDelegateQt::LoadProgressChanged(content::WebContents* source, double progress) +void WebContentsDelegateQt::LoadProgressChanged(content::WebContents */*source*/, double progress) { if (!m_loadingErrorFrameList.isEmpty()) return; @@ -191,59 +192,92 @@ void WebContentsDelegateQt::RenderFrameDeleted(content::RenderFrameHost *render_ m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID()); } -void WebContentsDelegateQt::DidStartProvisionalLoadForFrame(content::RenderFrameHost* render_frame_host, const GURL& validated_url, bool is_error_page, bool is_iframe_srcdoc) +void WebContentsDelegateQt::DidStartNavigation(content::NavigationHandle *navigation_handle) { - if (is_error_page) { - m_loadingErrorFrameList.append(render_frame_host->GetRoutingID()); + if (!navigation_handle->IsInMainFrame()) + return; - // Trigger LoadStarted signal for main frame's error page only. - if (!render_frame_host->GetParent()) { - m_faviconManager->resetCandidates(); - m_viewClient->loadStarted(toQt(validated_url), true); - } + // Suppress extra loadStarted signal for data URL with specified base URL. + if (navigation_handle->GetURL().SchemeIs(url::kDataScheme)) { + content::NavigationEntry *pending_entry = navigation_handle->GetWebContents()->GetController().GetPendingEntry(); - return; + if (pending_entry && !pending_entry->GetBaseURLForDataURL().is_empty() && + navigation_handle->GetURL() == pending_entry->GetURL()) { + return; + } } - if (render_frame_host->GetParent()) - return; + // Error-pages are not reported as separate started navigations. + Q_ASSERT(!navigation_handle->IsErrorPage()); m_loadingErrorFrameList.clear(); m_faviconManager->resetCandidates(); - m_viewClient->loadStarted(toQt(validated_url)); + m_viewClient->loadStarted(toQt(navigation_handle->GetURL())); } -void WebContentsDelegateQt::DidCommitProvisionalLoadForFrame(content::RenderFrameHost* render_frame_host, const GURL& url, ui::PageTransition transition_type) +void WebContentsDelegateQt::DidFinishNavigation(content::NavigationHandle *navigation_handle) { - // Make sure that we don't set the findNext WebFindOptions on a new frame. - m_lastSearchedString = QString(); + if (!navigation_handle->IsInMainFrame()) + return; + + if (navigation_handle->HasCommitted() && !navigation_handle->IsErrorPage()) { + // VisistedLinksMaster asserts !IsOffTheRecord(). + if (navigation_handle->ShouldUpdateHistory() && m_viewClient->browserContextAdapter()->trackVisitedLinks()) + m_viewClient->browserContextAdapter()->visitedLinksManager()->addUrl(navigation_handle->GetURL()); + + // Make sure that we don't set the findNext WebFindOptions on a new frame. + m_lastSearchedString = QString(); - // This is currently used for canGoBack/Forward values, which is flattened across frames. For other purposes we might have to pass is_main_frame. - m_viewClient->loadCommitted(); + // This is currently used for canGoBack/Forward values, which is flattened across frames. For other purposes we might have to pass is_main_frame. + m_viewClient->loadCommitted(); + } + // Success is reported by DidFinishLoad, but DidFailLoad is now dead code and needs to be handled below + if (navigation_handle->GetNetErrorCode() == net::OK) + return; + + // WebContentsObserver::DidFailLoad is not called any longer so we have to report the failure here. + const net::Error error_code = navigation_handle->GetNetErrorCode(); + const std::string error_description = net::ErrorToString(error_code); + didFailLoad(toQt(navigation_handle->GetURL()), error_code, toQt(error_description)); + + // The load will succede as an error-page load later, and we reported the original error above + if (navigation_handle->IsErrorPage()) { + // Now report we are starting to load an error-page. + m_loadingErrorFrameList.append(navigation_handle->GetRenderFrameHost()->GetRoutingID()); + m_faviconManager->resetCandidates(); + m_viewClient->loadStarted(toQt(GURL(content::kUnreachableWebDataURL)), true); + + // If it is already committed we will not see another DidFinishNavigation call or a DidFinishLoad call. + if (navigation_handle->HasCommitted()) { + m_lastSearchedString = QString(); + m_viewClient->loadCommitted(); + } + } } -void WebContentsDelegateQt::DidFailProvisionalLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description, bool was_ignored_by_handler) +void WebContentsDelegateQt::didFailLoad(const QUrl &url, int errorCode, const QString &errorDescription) { - DidFailLoad(render_frame_host, validated_url, error_code, error_description, was_ignored_by_handler); + m_viewClient->iconChanged(QUrl()); + m_viewClient->loadFinished(false /* success */ , url, false /* isErrorPage */, errorCode, errorDescription); + m_viewClient->loadProgressChanged(0); } void WebContentsDelegateQt::DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description, bool was_ignored_by_handler) { Q_UNUSED(was_ignored_by_handler); + if (render_frame_host->GetParent()) + return; + if (validated_url.spec() == content::kUnreachableWebDataURL) { + // error-pages should only ever fail due to abort: + Q_ASSERT(error_code == -3 /* ERR_ABORTED */); m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID()); - qCritical("Loading error-page failed. This shouldn't happen."); - if (!render_frame_host->GetParent()) - m_viewClient->loadFinished(false /* success */, toQt(validated_url), true /* isErrorPage */); + m_viewClient->iconChanged(QUrl()); + m_viewClient->loadFinished(false /* success */, toQt(validated_url), true /* isErrorPage */); return; } - if (render_frame_host->GetParent()) - return; - - m_viewClient->iconChanged(QUrl()); - m_viewClient->loadFinished(false /* success */ , toQt(validated_url), false /* isErrorPage */, error_code, toQt(error_description)); - m_viewClient->loadProgressChanged(0); + didFailLoad(toQt(validated_url), error_code, toQt(error_description)); } void WebContentsDelegateQt::DidFinishLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url) @@ -380,14 +414,6 @@ void WebContentsDelegateQt::UpdateTargetURL(content::WebContents* source, const m_viewClient->didUpdateTargetURL(toQt(url)); } -void WebContentsDelegateQt::DidNavigateAnyFrame(content::RenderFrameHost* render_frame_host, const content::LoadCommittedDetails& details, const content::FrameNavigateParams& params) -{ - // VisistedLinksMaster asserts !IsOffTheRecord(). - if (!params.should_update_history || !m_viewClient->browserContextAdapter()->trackVisitedLinks()) - return; - m_viewClient->browserContextAdapter()->visitedLinksManager()->addUrl(params.url); -} - void WebContentsDelegateQt::WasShown() { web_cache::WebCacheManager::GetInstance()->ObserveActivity(web_contents()->GetRenderProcessHost()->GetID()); @@ -408,6 +434,13 @@ void WebContentsDelegateQt::DidFirstVisuallyNonEmptyPaint() } } +void WebContentsDelegateQt::ActivateContents(content::WebContents* contents) +{ + WebEngineSettings *settings = m_viewClient->webEngineSettings(); + if (settings->testAttribute(settings->Attribute::AllowWindowActivationFromJavaScript)) + contents->Focus(); +} + void WebContentsDelegateQt::RequestToLockMouse(content::WebContents *web_contents, bool user_gesture, bool last_unlocked_by_target) { Q_UNUSED(user_gesture); diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index 913bf356c..84799c2cd 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -126,18 +126,18 @@ public: // WebContentsObserver overrides void RenderFrameDeleted(content::RenderFrameHost *render_frame_host) override; - void DidStartProvisionalLoadForFrame(content::RenderFrameHost *render_frame_host, const GURL &validated_url, bool is_error_page, bool is_iframe_srcdoc) override; - void DidCommitProvisionalLoadForFrame(content::RenderFrameHost *render_frame_host, const GURL &url, ui::PageTransition transition_type) override; - void DidFailProvisionalLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url, - int error_code, const base::string16 &error_description, bool was_ignored_by_handler) override; + void DidStartNavigation(content::NavigationHandle *navigation_handle) override; + void DidFinishNavigation(content::NavigationHandle *navigation_handle) override; void DidFailLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url, int error_code, const base::string16 &error_description, bool was_ignored_by_handler) override; void DidFinishLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url) override; void DidUpdateFaviconURL(const std::vector<content::FaviconURL> &candidates) override; - void DidNavigateAnyFrame(content::RenderFrameHost *render_frame_host, const content::LoadCommittedDetails &details, const content::FrameNavigateParams ¶ms) override; void WasShown() override; void DidFirstVisuallyNonEmptyPaint() override; + void ActivateContents(content::WebContents* contents) override; + + void didFailLoad(const QUrl &url, int errorCode, const QString &errorDescription); void overrideWebPreferences(content::WebContents *, content::WebPreferences*); void allowCertificateError(const QSharedPointer<CertificateErrorController> &) ; void requestGeolocationPermission(const QUrl &requestingOrigin); diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp index 844544887..e627fa06d 100644 --- a/src/core/web_contents_view_qt.cpp +++ b/src/core/web_contents_view_qt.cpp @@ -164,6 +164,7 @@ static inline WebEngineContextMenuData fromParams(const content::ContextMenuPara ret.setPosition(QPoint(params.x, params.y)); ret.setLinkUrl(toQt(params.link_url)); ret.setLinkText(toQt(params.link_text.data())); + ret.setUnfilteredLinkUrl(toQt(params.unfiltered_link_url)); ret.setSelectedText(toQt(params.selection_text.data())); ret.setMediaUrl(toQt(params.src_url)); ret.setMediaType((WebEngineContextMenuData::MediaType)params.media_type); diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 9d993b7f4..54564718f 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -52,7 +52,7 @@ #include "chrome/browser/printing/print_job_manager.h" #endif // defined(ENABLE_BASIC_PRINTING) #include "content/browser/devtools/devtools_http_handler.h" -#include "content/browser/gpu/gpu_process_host.h" +#include "content/browser/gpu/gpu_main_thread_factory.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/utility_process_host_impl.h" #include "content/gpu/in_process_gpu_thread.h" @@ -67,6 +67,7 @@ #include "content/renderer/in_process_renderer_thread.h" #include "content/utility/in_process_utility_thread.h" #include "gpu/command_buffer/service/gpu_switches.h" +#include "ppapi/features/features.h" #include "ui/events/event_switches.h" #include "ui/native_theme/native_theme_switches.h" #include "ui/gl/gl_switches.h" @@ -173,7 +174,7 @@ bool usingQtQuick2DRenderer() return device != QLatin1String("default"); } #endif //QT_NO_OPENGL -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&) { } @@ -408,7 +409,8 @@ WebEngineContext::WebEngineContext() QSurfaceFormat globalSharedFormat = qt_gl_global_share_context()->format(); if (globalSharedFormat.profile() == QSurfaceFormat::CoreProfile) { #ifdef Q_OS_MACOS - glType = gl::kGLImplementationCoreProfileName; + // @TODO_FIXME_ADAPT_QT + // glType = gl::kGLImplementationCoreProfileName; #else qWarning("An OpenGL Core Profile was requested, but it is not supported " "on the current platform. Falling back to a non-Core profile. " @@ -417,6 +419,9 @@ WebEngineContext::WebEngineContext() } } } + + if (qt_gl_global_share_context()->format().profile() == QSurfaceFormat::CompatibilityProfile) + parsedCommandLine->AppendSwitch(switches::kCreateDefaultGLContext); } else { qWarning("WebEngineContext used before QtWebEngine::initialize() or OpenGL context creation failed."); } @@ -430,7 +435,7 @@ WebEngineContext::WebEngineContext() content::UtilityProcessHostImpl::RegisterUtilityMainThreadFactory(content::CreateInProcessUtilityThread); content::RenderProcessHostImpl::RegisterRendererMainThreadFactory(content::CreateInProcessRendererThread); - content::GpuProcessHost::RegisterGpuMainThreadFactory(content::CreateInProcessGpuThread); + content::RegisterGpuMainThreadFactory(content::CreateInProcessGpuThread); content::ContentMainParams contentMainParams(m_mainDelegate.get()); contentMainParams.setup_signal_handlers = false; @@ -455,7 +460,7 @@ WebEngineContext::WebEngineContext() base::ThreadRestrictions::SetIOAllowed(true); -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) // Creating pepper plugins from the page (which calls PluginService::GetPluginInfoArray) // might fail unless the page queried the list of available plugins at least once // (which ends up calling PluginService::GetPlugins). Since the plugins list can only diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index f46f8f425..35b139602 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -216,26 +216,32 @@ QString dictionariesPath() if (!initialized) { initialized = true; - // First try to find dictionaries near the application. + const QByteArray fromEnv = qgetenv("QTWEBENGINE_DICTIONARIES_PATH"); + if (!fromEnv.isEmpty()) { + // Only search in QTWEBENGINE_DICTIONARIES_PATH if set + candidatePaths << QString::fromLocal8Bit(fromEnv); + } else { + // First try to find dictionaries near the application. #ifdef OS_MACOSX - QString resourcesDictionariesPath = getMainApplicationResourcesPath() - % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); - candidatePaths << resourcesDictionariesPath; + QString resourcesDictionariesPath = getMainApplicationResourcesPath() + % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); + candidatePaths << resourcesDictionariesPath; #endif - QString applicationDictionariesPath = QCoreApplication::applicationDirPath() - % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); - candidatePaths << applicationDictionariesPath; + QString applicationDictionariesPath = QCoreApplication::applicationDirPath() + % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); + candidatePaths << applicationDictionariesPath; - // Then try to find dictionaries near the installed library. + // Then try to find dictionaries near the installed library. #if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD) - QString frameworkDictionariesPath = getResourcesPath(frameworkBundle()) - % QLatin1String("/qtwebengine_dictionaries"); - candidatePaths << frameworkDictionariesPath; + QString frameworkDictionariesPath = getResourcesPath(frameworkBundle()) + % QLatin1String("/qtwebengine_dictionaries"); + candidatePaths << frameworkDictionariesPath; #endif - QString libraryDictionariesPath = QLibraryInfo::location(QLibraryInfo::DataPath) - % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); - candidatePaths << libraryDictionariesPath; + QString libraryDictionariesPath = QLibraryInfo::location(QLibraryInfo::DataPath) + % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); + candidatePaths << libraryDictionariesPath; + } Q_FOREACH (const QString &candidate, candidatePaths) { if (QFileInfo::exists(candidate)) { diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index 0079e02ba..31d120899 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -107,13 +107,13 @@ static inline bool isTouchEventsAPIEnabled() { // By default the Touch Events API support (presence of 'ontouchstart' in 'window' object) // will be determined based on the availability of touch screen devices. const std::string touchEventsSwitchValue = - parsedCommandLine->HasSwitch(switches::kTouchEvents) ? - parsedCommandLine->GetSwitchValueASCII(switches::kTouchEvents) : - switches::kTouchEventsAuto; + parsedCommandLine->HasSwitch(switches::kTouchEventFeatureDetection) ? + parsedCommandLine->GetSwitchValueASCII(switches::kTouchEventFeatureDetection) : + switches::kTouchEventFeatureDetectionAuto; - if (touchEventsSwitchValue == switches::kTouchEventsEnabled) + if (touchEventsSwitchValue == switches::kTouchEventFeatureDetectionEnabled) touchEventsAPIEnabled = true; - else if (touchEventsSwitchValue == switches::kTouchEventsAuto) + else if (touchEventsSwitchValue == switches::kTouchEventFeatureDetectionAuto) touchEventsAPIEnabled = isTouchScreenAvailable(); initialized = true; @@ -228,7 +228,7 @@ QString WebEngineSettings::defaultTextEncoding() const return m_defaultEncoding.isEmpty()? parentSettings->defaultTextEncoding() : m_defaultEncoding; } -void WebEngineSettings::initDefaults(bool offTheRecord) +void WebEngineSettings::initDefaults() { if (s_defaultAttributes.isEmpty()) { // Initialize the default settings. @@ -247,6 +247,7 @@ void WebEngineSettings::initDefaults(bool offTheRecord) s_defaultAttributes.insert(PluginsEnabled, false); s_defaultAttributes.insert(FullScreenSupportEnabled, false); s_defaultAttributes.insert(ScreenCaptureEnabled, false); + s_defaultAttributes.insert(HideScrollbars, false); // The following defaults matches logic in render_view_host_impl.cc // But first we must ensure the WebContext has been initialized QtWebEngineCore::WebEngineContext::current(); @@ -267,9 +268,8 @@ void WebEngineSettings::initDefaults(bool offTheRecord) s_defaultAttributes.insert(PrintElementBackgrounds, true); s_defaultAttributes.insert(AllowRunningInsecureContent, allowRunningInsecureContent); s_defaultAttributes.insert(AllowGeolocationOnInsecureOrigins, false); + s_defaultAttributes.insert(AllowWindowActivationFromJavaScript, false); } - if (offTheRecord) - m_attributes.insert(LocalStorageEnabled, false); if (s_defaultFontFamilies.isEmpty()) { // Default fonts @@ -322,7 +322,7 @@ void WebEngineSettings::doApply() void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *prefs) { // Override for now - prefs->touch_enabled = isTouchEventsAPIEnabled(); + prefs->touch_event_feature_detection_enabled = isTouchEventsAPIEnabled(); prefs->device_supports_touch = isTouchScreenAvailable(); if (prefs->viewport_enabled) { // We should enable viewport and viewport-meta together, but since 5.7 we @@ -352,6 +352,7 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p prefs->should_print_backgrounds = testAttribute(PrintElementBackgrounds); prefs->allow_running_insecure_content = testAttribute(AllowRunningInsecureContent); prefs->allow_geolocation_on_insecure_origins = testAttribute(AllowGeolocationOnInsecureOrigins); + prefs->hide_scrollbars = testAttribute(HideScrollbars); // Fonts settings. prefs->standard_font_family_map[content::kCommonScript] = toString16(fontFamily(StandardFont)); diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h index 4b0ce7b39..1304d2ae9 100644 --- a/src/core/web_engine_settings.h +++ b/src/core/web_engine_settings.h @@ -83,7 +83,9 @@ public: FocusOnNavigationEnabled, PrintElementBackgrounds, AllowRunningInsecureContent, - AllowGeolocationOnInsecureOrigins + AllowGeolocationOnInsecureOrigins, + AllowWindowActivationFromJavaScript, + HideScrollbars }; // Must match the values from the public API in qwebenginesettings.h. @@ -127,7 +129,7 @@ public: void setDefaultTextEncoding(const QString &encoding); QString defaultTextEncoding() const; - void initDefaults(bool offTheRecord = false); + void initDefaults(); void scheduleApply(); void scheduleApplyRecursively(); diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index a7df934e4..7f164d6bd 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -72,12 +72,12 @@ #include <QCoreApplication> #include <QElapsedTimer> +#include <QGuiApplication> #include <QKeyEvent> #include <QMouseEvent> +#include <QStyleHints> #include <QWheelEvent> -static const int wheelScrollLines = 3; // FIXME: Still not available in QStyleHints in 5.1 - using namespace blink; static int windowsKeyCodeForKeyEvent(unsigned int keycode, bool isKeypad) @@ -903,11 +903,11 @@ static ui::DomKey getDomKeyFromQKeyEvent(QKeyEvent *ev) // Audio Keys case Qt::Key_BassDown: - return ui::DomKey::AUDIO_BASS_DOWN; + return ui::DomKey::AUDIO_BASS_BOOST_DOWN; case Qt::Key_BassBoost: return ui::DomKey::AUDIO_BASS_BOOST_TOGGLE; case Qt::Key_BassUp: - return ui::DomKey::AUDIO_BASS_UP; + return ui::DomKey::AUDIO_BASS_BOOST_UP; case Qt::Key_TrebleDown: return ui::DomKey::AUDIO_TREBLE_DOWN; case Qt::Key_TrebleUp: @@ -1182,16 +1182,17 @@ static WebInputEvent::Type webEventTypeForEvent(const QEvent* event) WebMouseEvent WebEventFactory::toWebMouseEvent(QMouseEvent *ev, double dpiScale) { WebMouseEvent webKitEvent; - webKitEvent.timeStampSeconds = currentTimeForEvent(ev); + webKitEvent.setTimeStampSeconds(currentTimeForEvent(ev)); + webKitEvent.setModifiers(modifiersForEvent(ev)); + webKitEvent.setType(webEventTypeForEvent(ev)); + webKitEvent.button = mouseButtonForEvent(ev); - webKitEvent.modifiers = modifiersForEvent(ev); webKitEvent.x = webKitEvent.windowX = ev->x() / dpiScale; webKitEvent.y = webKitEvent.windowY = ev->y() / dpiScale; webKitEvent.globalX = ev->globalX(); webKitEvent.globalY = ev->globalY(); - webKitEvent.type = webEventTypeForEvent(ev); webKitEvent.clickCount = 0; return webKitEvent; @@ -1200,23 +1201,23 @@ WebMouseEvent WebEventFactory::toWebMouseEvent(QMouseEvent *ev, double dpiScale) WebMouseEvent WebEventFactory::toWebMouseEvent(QHoverEvent *ev, double dpiScale) { WebMouseEvent webKitEvent; - webKitEvent.timeStampSeconds = currentTimeForEvent(ev); - webKitEvent.modifiers = modifiersForEvent(ev); + webKitEvent.setTimeStampSeconds(currentTimeForEvent(ev)); + webKitEvent.setModifiers(modifiersForEvent(ev)); + webKitEvent.setType(webEventTypeForEvent(ev)); webKitEvent.x = webKitEvent.windowX = ev->pos().x() / dpiScale; webKitEvent.y = webKitEvent.windowY = ev->pos().y() / dpiScale; webKitEvent.movementX = ev->pos().x() - ev->oldPos().x(); webKitEvent.movementY = ev->pos().y() - ev->oldPos().y(); - webKitEvent.type = webEventTypeForEvent(ev); return webKitEvent; } WebGestureEvent WebEventFactory::toWebGestureEvent(QNativeGestureEvent *ev, double dpiScale) { WebGestureEvent webKitEvent; - webKitEvent.timeStampSeconds = currentTimeForEvent(ev); - webKitEvent.modifiers = modifiersForEvent(ev); + webKitEvent.setTimeStampSeconds(currentTimeForEvent(ev)); + webKitEvent.setModifiers(modifiersForEvent(ev)); webKitEvent.x = static_cast<int>(ev->localPos().x() / dpiScale); webKitEvent.y = static_cast<int>(ev->localPos().y() / dpiScale); @@ -1229,11 +1230,11 @@ WebGestureEvent WebEventFactory::toWebGestureEvent(QNativeGestureEvent *ev, doub Qt::NativeGestureType gestureType = ev->gestureType(); switch (gestureType) { case Qt::ZoomNativeGesture: - webKitEvent.type = WebInputEvent::GesturePinchUpdate; + webKitEvent.setType(WebInputEvent::GesturePinchUpdate); webKitEvent.data.pinchUpdate.scale = static_cast<float>(ev->value() + 1.0); break; case Qt::SmartZoomNativeGesture: - webKitEvent.type = WebInputEvent::GestureDoubleTap; + webKitEvent.setType(WebInputEvent::GestureDoubleTap); webKitEvent.data.tap.tapCount = 1; break; case Qt::BeginNativeGesture: @@ -1242,7 +1243,7 @@ WebGestureEvent WebEventFactory::toWebGestureEvent(QNativeGestureEvent *ev, doub case Qt::PanNativeGesture: case Qt::SwipeNativeGesture: // Not implemented by Chromium for now. - webKitEvent.type = blink::WebInputEvent::Undefined; + webKitEvent.setType(blink::WebInputEvent::Undefined); break; } @@ -1252,13 +1253,13 @@ WebGestureEvent WebEventFactory::toWebGestureEvent(QNativeGestureEvent *ev, doub blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev, double dpiScale) { WebMouseWheelEvent webEvent; - webEvent.type = webEventTypeForEvent(ev); webEvent.deltaX = 0; webEvent.deltaY = 0; webEvent.wheelTicksX = 0; webEvent.wheelTicksY = 0; - webEvent.modifiers = modifiersForEvent(ev); - webEvent.timeStampSeconds = currentTimeForEvent(ev); + webEvent.setType(webEventTypeForEvent(ev)); + webEvent.setModifiers(modifiersForEvent(ev)); + webEvent.setTimeStampSeconds(currentTimeForEvent(ev)); webEvent.wheelTicksX = static_cast<float>(ev->angleDelta().x()) / QWheelEvent::DefaultDeltasPerStep; webEvent.wheelTicksY = static_cast<float>(ev->angleDelta().y()) / QWheelEvent::DefaultDeltasPerStep; @@ -1267,6 +1268,11 @@ blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev, doub // a pixel delta based on ticks and scroll per line. static const float cDefaultQtScrollStep = 20.f; +#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) + const int wheelScrollLines = QGuiApplication::styleHints()->wheelScrollLines(); +#else + const int wheelScrollLines = 3; +#endif webEvent.deltaX = webEvent.wheelTicksX * wheelScrollLines * cDefaultQtScrollStep; webEvent.deltaY = webEvent.wheelTicksY * wheelScrollLines * cDefaultQtScrollStep; @@ -1280,9 +1286,9 @@ blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev, doub content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *ev) { content::NativeWebKeyboardEvent webKitEvent(reinterpret_cast<gfx::NativeEvent>(ev)); - webKitEvent.timeStampSeconds = currentTimeForEvent(ev); - webKitEvent.modifiers = modifiersForEvent(ev); - webKitEvent.type = webEventTypeForEvent(ev); + webKitEvent.setTimeStampSeconds(currentTimeForEvent(ev)); + webKitEvent.setModifiers(modifiersForEvent(ev)); + webKitEvent.setType(webEventTypeForEvent(ev)); webKitEvent.nativeKeyCode = ev->nativeVirtualKey(); webKitEvent.windowsKeyCode = windowsKeyCodeForKeyEvent(ev->key(), ev->modifiers() & Qt::KeypadModifier); diff --git a/src/core/web_event_factory.h b/src/core/web_event_factory.h index d82113db3..b5e465610 100644 --- a/src/core/web_event_factory.h +++ b/src/core/web_event_factory.h @@ -41,8 +41,9 @@ #define WEB_EVENT_FACTORY_H #include "content/public/browser/native_web_keyboard_event.h" -#include "third_party/WebKit/public/platform/WebInputEvent.h" #include "third_party/WebKit/public/platform/WebGestureEvent.h" +#include "third_party/WebKit/public/platform/WebMouseEvent.h" +#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h" #include <QtGlobal> diff --git a/src/webengine/api/qquickwebenginecontextmenurequest.cpp b/src/webengine/api/qquickwebenginecontextmenurequest.cpp index df57442a1..c53e28d93 100644 --- a/src/webengine/api/qquickwebenginecontextmenurequest.cpp +++ b/src/webengine/api/qquickwebenginecontextmenurequest.cpp @@ -159,11 +159,12 @@ QString QQuickWebEngineContextMenuRequest::linkText() const \readonly The URL of the link if the selected web page content is a link. + It is not guaranteed to be a valid URL. */ QUrl QQuickWebEngineContextMenuRequest::linkUrl() const { - return m_data->linkUrl(); + return m_data->unfilteredLinkUrl(); } /*! diff --git a/src/webengine/api/qquickwebenginedownloaditem.cpp b/src/webengine/api/qquickwebenginedownloaditem.cpp index bc40e6771..5afb19531 100644 --- a/src/webengine/api/qquickwebenginedownloaditem.cpp +++ b/src/webengine/api/qquickwebenginedownloaditem.cpp @@ -39,6 +39,8 @@ #include "qquickwebenginedownloaditem_p.h" #include "qquickwebenginedownloaditem_p_p.h" + +#include "browser_context_adapter.h" #include "qquickwebengineprofile_p.h" using QtWebEngineCore::BrowserContextAdapterClient; @@ -103,6 +105,8 @@ QQuickWebEngineDownloadItemPrivate::QQuickWebEngineDownloadItemPrivate(QQuickWeb , interruptReason(QQuickWebEngineDownloadItem::NoReason) , totalBytes(-1) , receivedBytes(0) + , downloadFinished(false) + , downloadPaused(false) { } @@ -145,6 +149,16 @@ void QQuickWebEngineDownloadItemPrivate::update(const BrowserContextAdapterClien totalBytes = info.totalBytes; Q_EMIT q->totalBytesChanged(); } + + if (info.done != downloadFinished) { + downloadFinished = info.done; + Q_EMIT q->isFinishedChanged(); + } + + if (info.paused != downloadPaused) { + downloadPaused = info.paused; + Q_EMIT q->isPausedChanged(); + } } void QQuickWebEngineDownloadItemPrivate::updateState(QQuickWebEngineDownloadItem::DownloadState newState) @@ -199,6 +213,46 @@ void QQuickWebEngineDownloadItem::cancel() } } + +/*! + \qmlmethod void WebEngineDownloadItem::pause() + \since QtWebEngine 1.6 + + Pauses the download. +*/ + +void QQuickWebEngineDownloadItem::pause() +{ + Q_D(QQuickWebEngineDownloadItem); + + QQuickWebEngineDownloadItem::DownloadState state = d->downloadState; + + if (state != QQuickWebEngineDownloadItem::DownloadInProgress) + return; + + if (d->profile) + d->profile->d_ptr->browserContext()->pauseDownload(d->downloadId); +} + +/*! + \qmlmethod void WebEngineDownloadItem::resume() + \since QtWebEngine 1.6 + + Resumes the download if it was paused or interrupted. +*/ +void QQuickWebEngineDownloadItem::resume() +{ + Q_D(QQuickWebEngineDownloadItem); + + QQuickWebEngineDownloadItem::DownloadState state = d->downloadState; + + if (d->downloadFinished || (state != QQuickWebEngineDownloadItem::DownloadInProgress && state != QQuickWebEngineDownloadItem::DownloadInterrupted)) + return; + + if (d->profile) + d->profile->d_ptr->browserContext()->resumeDownload(d->downloadId); +} + /*! \qmlproperty int WebEngineDownloadItem::id @@ -426,6 +480,34 @@ QString QQuickWebEngineDownloadItem::interruptReasonString() const static_cast<BrowserContextAdapterClient::DownloadInterruptReason>(interruptReason())); } +/*! + \qmlproperty bool WebEngineDownloadItem::isFinished + \readonly + \since QtWebEngine 1.6 + + Whether this download is finished (completed, cancelled, or non-resumable interrupted state). + */ + +bool QQuickWebEngineDownloadItem::isFinished() const +{ + Q_D(const QQuickWebEngineDownloadItem); + return d->downloadFinished; +} + +/*! + \qmlproperty bool WebEngineDownloadItem::isPaused + \readonly + \since QtWebEngine 1.6 + + Whether this download is paused. + */ + +bool QQuickWebEngineDownloadItem::isPaused() const +{ + Q_D(const QQuickWebEngineDownloadItem); + return d->downloadPaused; +} + QQuickWebEngineDownloadItem::QQuickWebEngineDownloadItem(QQuickWebEngineDownloadItemPrivate *p, QObject *parent) : QObject(parent) , d_ptr(p) diff --git a/src/webengine/api/qquickwebenginedownloaditem_p.h b/src/webengine/api/qquickwebenginedownloaditem_p.h index 889d0bcb7..972b130aa 100644 --- a/src/webengine/api/qquickwebenginedownloaditem_p.h +++ b/src/webengine/api/qquickwebenginedownloaditem_p.h @@ -131,9 +131,13 @@ public: Q_PROPERTY(DownloadType type READ type NOTIFY typeChanged REVISION 3 FINAL) Q_PROPERTY(DownloadInterruptReason interruptReason READ interruptReason NOTIFY interruptReasonChanged REVISION 4 FINAL) Q_PROPERTY(QString interruptReasonString READ interruptReasonString NOTIFY interruptReasonChanged REVISION 4 FINAL) + Q_PROPERTY(bool isFinished READ isFinished NOTIFY isFinishedChanged REVISION 5 FINAL) + Q_PROPERTY(bool isPaused READ isPaused NOTIFY isPausedChanged REVISION 5 FINAL) Q_INVOKABLE void accept(); Q_INVOKABLE void cancel(); + Q_INVOKABLE void pause(); + Q_INVOKABLE void resume(); quint32 id() const; DownloadState state() const; @@ -147,6 +151,8 @@ public: DownloadType type() const; DownloadInterruptReason interruptReason() const; QString interruptReasonString() const; + bool isFinished() const; + bool isPaused() const; Q_SIGNALS: void stateChanged(); @@ -157,6 +163,8 @@ Q_SIGNALS: void pathChanged(); Q_REVISION(3) void typeChanged(); Q_REVISION(4) void interruptReasonChanged(); + Q_REVISION(5) void isFinishedChanged(); + Q_REVISION(5) void isPausedChanged(); private: QQuickWebEngineDownloadItem(QQuickWebEngineDownloadItemPrivate*, QObject *parent = 0); diff --git a/src/webengine/api/qquickwebenginedownloaditem_p_p.h b/src/webengine/api/qquickwebenginedownloaditem_p_p.h index 4fb609492..6b4f7c8d3 100644 --- a/src/webengine/api/qquickwebenginedownloaditem_p_p.h +++ b/src/webengine/api/qquickwebenginedownloaditem_p_p.h @@ -79,6 +79,8 @@ public: qint64 receivedBytes; QString mimeType; QString downloadPath; + bool downloadFinished; + bool downloadPaused; void update(const QtWebEngineCore::BrowserContextAdapterClient::DownloadItemInfo &info); void updateState(QQuickWebEngineDownloadItem::DownloadState newState); diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp index 260d8958b..fa30a39e0 100644 --- a/src/webengine/api/qquickwebengineprofile.cpp +++ b/src/webengine/api/qquickwebengineprofile.cpp @@ -145,7 +145,7 @@ QQuickWebEngineProfilePrivate::QQuickWebEngineProfilePrivate(QSharedPointer<Brow , m_browserContextRef(browserContext) { m_browserContextRef->addClient(this); - m_settings->d_ptr->initDefaults(browserContext->isOffTheRecord()); + m_settings->d_ptr->initDefaults(); // Fullscreen API was implemented before the supported setting, so we must // make it default true to avoid change in default API behavior. m_settings->d_ptr->setAttribute(QtWebEngineCore::WebEngineSettings::FullScreenSupportEnabled, true); @@ -668,34 +668,8 @@ QQuickWebEngineProfile *QQuickWebEngineProfile::defaultProfile() For example, the language \c en-US will load the \c en-US.bdic dictionary file. - Qt WebEngine checks for the \c qtwebengine_dictionaries subdirectory - first in the local directory and if it is not found, in the Qt - installation directory. - - On macOS, depending on how Qt WebEngine is configured at build time, there are two possibilities - how spellchecking data is found: - - \list - \li Hunspell dictionaries (default) - .bdic dictionaries are used, just like on other - platforms - \li Native dictionaries - the macOS spellchecking APIs are used (which means the results - will depend on the installed OS dictionaries) - \endlist - - Thus, in the macOS Hunspell case, Qt WebEngine will look in the \e qtwebengine_dictionaries - subdirectory located inside the application bundle \c Resources directory, and also in the - \c Resources directory located inside the Qt framework bundle. - - To summarize, in case of Hunspell usage, the following paths are considered: - - \list - \li QCoreApplication::applicationDirPath()/qtwebengine_dictionaries - or QCoreApplication::applicationDirPath()/../Contents/Resources/qtwebengine_dictionaries - (on macOS) - \li [QLibraryInfo::DataPath]/qtwebengine_dictionaries - or path/to/QtWebEngineCore.framework/Resources/qtwebengine_dictionaries (Qt framework - bundle on macOS) - \endlist + See the \l {Spellchecker}{Spellchecker feature documentation} for how + dictionary files are searched. For more information about how to compile \c .bdic dictionaries, see the \l{WebEngine Widgets Spellchecker Example}{Spellchecker Example}. diff --git a/src/webengine/api/qquickwebenginesettings.cpp b/src/webengine/api/qquickwebenginesettings.cpp index ff2541376..98a3eef39 100644 --- a/src/webengine/api/qquickwebenginesettings.cpp +++ b/src/webengine/api/qquickwebenginesettings.cpp @@ -363,6 +363,26 @@ bool QQuickWebEngineSettings::allowGeolocationOnInsecureOrigins() const } /*! + \qmlproperty bool WebEngineSettings::allowWindowActivationFromJavaScript + \since QtWebEngine 1.6 + Allows the window.focus() method in JavaScript. Disallowed by default. +*/ +bool QQuickWebEngineSettings::allowWindowActivationFromJavaScript() const +{ + return d_ptr->testAttribute(WebEngineSettings::AllowWindowActivationFromJavaScript); +} + +/*! + \qmlproperty bool WebEngineSettings::hideScrollbars + \since QtWebEngine 1.6 + Hides scrollbars. Disabled by default. +*/ +bool QQuickWebEngineSettings::hideScrollbars() const +{ + return d_ptr->testAttribute(WebEngineSettings::HideScrollbars); +} + +/*! \qmlproperty string WebEngineSettings::defaultTextEncoding \since QtWebEngine 1.2 @@ -564,6 +584,22 @@ void QQuickWebEngineSettings::setAllowGeolocationOnInsecureOrigins(bool on) Q_EMIT allowGeolocationOnInsecureOriginsChanged(); } +void QQuickWebEngineSettings::setAllowWindowActivationFromJavaScript(bool on) +{ + bool wasOn = d_ptr->testAttribute(WebEngineSettings::AllowWindowActivationFromJavaScript); + d_ptr->setAttribute(WebEngineSettings::AllowWindowActivationFromJavaScript, on); + if (wasOn != on) + Q_EMIT allowWindowActivationFromJavaScriptChanged(); +} + +void QQuickWebEngineSettings::setHideScrollbars(bool on) +{ + bool wasOn = d_ptr->testAttribute(WebEngineSettings::HideScrollbars); + d_ptr->setAttribute(WebEngineSettings::HideScrollbars, on); + if (wasOn != on) + Q_EMIT hideScrollbarsChanged(); +} + void QQuickWebEngineSettings::setParentSettings(QQuickWebEngineSettings *parentSettings) { d_ptr->setParentSettings(parentSettings->d_ptr.data()); diff --git a/src/webengine/api/qquickwebenginesettings_p.h b/src/webengine/api/qquickwebenginesettings_p.h index 10217c678..da838f52f 100644 --- a/src/webengine/api/qquickwebenginesettings_p.h +++ b/src/webengine/api/qquickwebenginesettings_p.h @@ -86,6 +86,8 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject { Q_PROPERTY(bool printElementBackgrounds READ printElementBackgrounds WRITE setPrintElementBackgrounds NOTIFY printElementBackgroundsChanged REVISION 3 FINAL) Q_PROPERTY(bool allowRunningInsecureContent READ allowRunningInsecureContent WRITE setAllowRunningInsecureContent NOTIFY allowRunningInsecureContentChanged REVISION 3 FINAL) Q_PROPERTY(bool allowGeolocationOnInsecureOrigins READ allowGeolocationOnInsecureOrigins WRITE setAllowGeolocationOnInsecureOrigins NOTIFY allowGeolocationOnInsecureOriginsChanged REVISION 4 FINAL) + Q_PROPERTY(bool allowWindowActivationFromJavaScript READ allowWindowActivationFromJavaScript WRITE setAllowWindowActivationFromJavaScript NOTIFY allowWindowActivationFromJavaScriptChanged REVISION 5 FINAL) + Q_PROPERTY(bool hideScrollbars READ hideScrollbars WRITE setHideScrollbars NOTIFY hideScrollbarsChanged REVISION 5 FINAL) public: ~QQuickWebEngineSettings(); @@ -113,6 +115,8 @@ public: bool printElementBackgrounds() const; bool allowRunningInsecureContent() const; bool allowGeolocationOnInsecureOrigins() const; + bool allowWindowActivationFromJavaScript() const; + bool hideScrollbars() const; void setAutoLoadImages(bool on); void setJavascriptEnabled(bool on); @@ -137,6 +141,8 @@ public: void setPrintElementBackgrounds(bool on); void setAllowRunningInsecureContent(bool on); void setAllowGeolocationOnInsecureOrigins(bool on); + void setAllowWindowActivationFromJavaScript(bool on); + void setHideScrollbars(bool on); signals: void autoLoadImagesChanged(); @@ -162,6 +168,8 @@ signals: Q_REVISION(3) void printElementBackgroundsChanged(); Q_REVISION(3) void allowRunningInsecureContentChanged(); Q_REVISION(4) void allowGeolocationOnInsecureOriginsChanged(); + Q_REVISION(5) void allowWindowActivationFromJavaScriptChanged(); + Q_REVISION(5) void hideScrollbarsChanged(); private: explicit QQuickWebEngineSettings(QQuickWebEngineSettings *parentSettings = 0); diff --git a/src/webengine/api/qquickwebenginetestsupport.cpp b/src/webengine/api/qquickwebenginetestsupport.cpp index 46ffb06f4..41f374766 100644 --- a/src/webengine/api/qquickwebenginetestsupport.cpp +++ b/src/webengine/api/qquickwebenginetestsupport.cpp @@ -49,8 +49,6 @@ QQuickWebEngineErrorPage::QQuickWebEngineErrorPage() void QQuickWebEngineErrorPage::loadFinished(bool success, const QUrl &url) { - // Loading of the error page should not fail. - Q_ASSERT(success); Q_UNUSED(success); QQuickWebEngineLoadRequest loadRequest(url, QQuickWebEngineView::LoadSucceededStatus); @@ -64,8 +62,48 @@ void QQuickWebEngineErrorPage::loadStarted(const QUrl &provisionalUrl) Q_EMIT loadingChanged(&loadRequest); } + +QQuickWebEngineTestInputContext::QQuickWebEngineTestInputContext() + : m_visible(false) +{ +} + +QQuickWebEngineTestInputContext::~QQuickWebEngineTestInputContext() +{ + release(); +} + +void QQuickWebEngineTestInputContext::create() +{ + QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod()); + inputMethodPrivate->testContext = this; +} + +void QQuickWebEngineTestInputContext::release() +{ + QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod()); + inputMethodPrivate->testContext = 0; +} + +void QQuickWebEngineTestInputContext::showInputPanel() +{ + m_visible = true; +} + +void QQuickWebEngineTestInputContext::hideInputPanel() +{ + m_visible = false; +} + +bool QQuickWebEngineTestInputContext::isInputPanelVisible() const +{ + return m_visible; +} + + QQuickWebEngineTestSupport::QQuickWebEngineTestSupport() - : m_errorPage(new QQuickWebEngineErrorPage()) + : m_errorPage(new QQuickWebEngineErrorPage) + , m_testInputContext(new QQuickWebEngineTestInputContext) { } @@ -74,6 +112,11 @@ QQuickWebEngineErrorPage *QQuickWebEngineTestSupport::errorPage() const return m_errorPage.data(); } +QQuickWebEngineTestInputContext *QQuickWebEngineTestSupport::testInputContext() const +{ + return m_testInputContext.data(); +} + QT_END_NAMESPACE #include "moc_qquickwebenginetestsupport_p.cpp" diff --git a/src/webengine/api/qquickwebenginetestsupport_p.h b/src/webengine/api/qquickwebenginetestsupport_p.h index cca8d1df4..a84d00307 100644 --- a/src/webengine/api/qquickwebenginetestsupport_p.h +++ b/src/webengine/api/qquickwebenginetestsupport_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <private/qinputmethod_p.h> #include <private/qtwebengineglobal_p.h> #include <QObject> @@ -73,13 +74,33 @@ Q_SIGNALS: void loadingChanged(QQuickWebEngineLoadRequest *loadRequest); }; +class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineTestInputContext : public QPlatformInputContext { + Q_OBJECT + +public: + QQuickWebEngineTestInputContext(); + ~QQuickWebEngineTestInputContext(); + + Q_INVOKABLE void create(); + Q_INVOKABLE void release(); + + virtual void showInputPanel(); + virtual void hideInputPanel(); + virtual bool isInputPanelVisible() const; + +private: + bool m_visible; +}; + class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineTestSupport : public QObject { Q_OBJECT Q_PROPERTY(QQuickWebEngineErrorPage *errorPage READ errorPage CONSTANT FINAL) + Q_PROPERTY(QQuickWebEngineTestInputContext *testInputContext READ testInputContext CONSTANT FINAL) public: QQuickWebEngineTestSupport(); QQuickWebEngineErrorPage *errorPage() const; + QQuickWebEngineTestInputContext *testInputContext() const; Q_SIGNALS: void windowCloseRejected(); @@ -87,6 +108,7 @@ Q_SIGNALS: private: QScopedPointer<QQuickWebEngineErrorPage> m_errorPage; + QScopedPointer<QQuickWebEngineTestInputContext> m_testInputContext; }; QT_END_NAMESPACE diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index ae75b7f34..123acb20c 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -265,10 +265,12 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu ui()->addMenuItem(item, QQuickWebEngineView::tr("Unselect")); } - if (!data.linkText().isEmpty() && data.linkUrl().isValid()) { + if (!data.linkText().isEmpty() && !data.unfilteredLinkUrl().isEmpty()) { item = new MenuItemHandler(menu); QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyLinkToClipboard); }); ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Link URL")); + } + if (!data.linkText().isEmpty() && data.linkUrl().isValid()) { item = new MenuItemHandler(menu); QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::DownloadLinkToDisk); }); ui()->addMenuItem(item, QQuickWebEngineView::tr("Save Link")); @@ -566,6 +568,9 @@ void QQuickWebEngineViewPrivate::loadFinished(bool success, const QUrl &url, boo void QQuickWebEngineViewPrivate::focusContainer() { Q_Q(QQuickWebEngineView); + QQuickWindow *window = q->window(); + if (window) + window->requestActivate(); q->forceActiveFocus(); } @@ -585,7 +590,7 @@ void QQuickWebEngineViewPrivate::unhandledKeyEvent(QKeyEvent *event) } #endif if (q->parentItem()) - q->window()->sendEvent(q->parentItem(), event); + QCoreApplication::sendEvent(q->parentItem(), event); } void QQuickWebEngineViewPrivate::adoptNewWindow(QSharedPointer<WebContentsAdapter> newWebContents, WindowOpenDisposition disposition, bool userGesture, const QRect &, const QUrl &targetUrl) @@ -698,8 +703,13 @@ void QQuickWebEngineViewPrivate::runMediaAccessPermissionRequest(const QUrl &sec feature = QQuickWebEngineView::MediaAudioVideoCapture; else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture)) feature = QQuickWebEngineView::MediaAudioCapture; - else // WebContentsAdapterClient::MediaVideoCapture + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) feature = QQuickWebEngineView::MediaVideoCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture) && + requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) + feature = QQuickWebEngineView::DesktopAudioVideoCapture; + else // if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) + feature = QQuickWebEngineView::DesktopVideoCapture; Q_EMIT q->featurePermissionRequested(securityOrigin, feature); } @@ -867,8 +877,7 @@ QQuickWebEngineView::QQuickWebEngineView(QQuickItem *parent) Q_D(QQuickWebEngineView); d->q_ptr = this; this->setActiveFocusOnTab(true); - this->setFlags(QQuickItem::ItemIsFocusScope | QQuickItem::ItemAcceptsInputMethod - | QQuickItem::ItemAcceptsDrops); + this->setFlags(QQuickItem::ItemIsFocusScope | QQuickItem::ItemAcceptsDrops); #ifndef QT_NO_ACCESSIBILITY QQuickAccessibleAttached *accessible = QQuickAccessibleAttached::qmlAttachedProperties(this); @@ -1427,7 +1436,8 @@ void QQuickWebEngineView::grantFeaturePermission(const QUrl &securityOrigin, QQu { if (!d_ptr->adapter) return; - if (!granted && feature >= MediaAudioCapture && feature <= MediaAudioVideoCapture) { + if (!granted && ((feature >= MediaAudioCapture && feature <= MediaAudioVideoCapture) || + (feature >= DesktopVideoCapture && feature <= DesktopAudioVideoCapture))) { d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaNone); return; } @@ -1445,6 +1455,16 @@ void QQuickWebEngineView::grantFeaturePermission(const QUrl &securityOrigin, QQu case Geolocation: d_ptr->adapter->runGeolocationRequestCallback(securityOrigin, granted); break; + case DesktopVideoCapture: + d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaDesktopVideoCapture); + break; + case DesktopAudioVideoCapture: + d_ptr->adapter->grantMediaAccessPermission( + securityOrigin, + WebContentsAdapterClient::MediaRequestFlags( + WebContentsAdapterClient::MediaDesktopAudioCapture | + WebContentsAdapterClient::MediaDesktopVideoCapture)); + break; default: Q_UNREACHABLE(); } @@ -1606,14 +1626,14 @@ void QQuickWebEngineView::triggerWebAction(WebAction action) } break; case CopyLinkToClipboard: - if (d->m_contextMenuData.linkUrl().isValid()) { - QString urlString = d->m_contextMenuData.linkUrl().toString(QUrl::FullyEncoded); + if (!d->m_contextMenuData.unfilteredLinkUrl().isEmpty()) { + QString urlString = d->m_contextMenuData.unfilteredLinkUrl().toString(QUrl::FullyEncoded); QString title = d->m_contextMenuData.linkText().toHtmlEscaped(); QMimeData *data = new QMimeData(); data->setText(urlString); QString html = QStringLiteral("<a href=\"") + urlString + QStringLiteral("\">") + title + QStringLiteral("</a>"); data->setHtml(html); - data->setUrls(QList<QUrl>() << d->m_contextMenuData.linkUrl()); + data->setUrls(QList<QUrl>() << d->m_contextMenuData.unfilteredLinkUrl()); qApp->clipboard()->setMimeData(data); } break; @@ -1709,6 +1729,42 @@ void QQuickWebEngineView::triggerWebAction(WebAction action) case ViewSource: d->adapter->viewSource(); break; + case ToggleBold: + runJavaScript(QStringLiteral("document.execCommand('bold');"), QQuickWebEngineScript::ApplicationWorld); + break; + case ToggleItalic: + runJavaScript(QStringLiteral("document.execCommand('italic');"), QQuickWebEngineScript::ApplicationWorld); + break; + case ToggleUnderline: + runJavaScript(QStringLiteral("document.execCommand('underline');"), QQuickWebEngineScript::ApplicationWorld); + break; + case ToggleStrikethrough: + runJavaScript(QStringLiteral("document.execCommand('strikethrough');"), QQuickWebEngineScript::ApplicationWorld); + break; + case AlignLeft: + runJavaScript(QStringLiteral("document.execCommand('justifyLeft');"), QQuickWebEngineScript::ApplicationWorld); + break; + case AlignCenter: + runJavaScript(QStringLiteral("document.execCommand('justifyCenter');"), QQuickWebEngineScript::ApplicationWorld); + break; + case AlignRight: + runJavaScript(QStringLiteral("document.execCommand('justifyRight');"), QQuickWebEngineScript::ApplicationWorld); + break; + case AlignJustified: + runJavaScript(QStringLiteral("document.execCommand('justifyFull');"), QQuickWebEngineScript::ApplicationWorld); + break; + case Indent: + runJavaScript(QStringLiteral("document.execCommand('indent');"), QQuickWebEngineScript::ApplicationWorld); + break; + case Outdent: + runJavaScript(QStringLiteral("document.execCommand('outdent');"), QQuickWebEngineScript::ApplicationWorld); + break; + case InsertOrderedList: + runJavaScript(QStringLiteral("document.execCommand('insertOrderedList');"), QQuickWebEngineScript::ApplicationWorld); + break; + case InsertUnorderedList: + runJavaScript(QStringLiteral("document.execCommand('insertUnorderedList');"), QQuickWebEngineScript::ApplicationWorld); + break; default: Q_UNREACHABLE(); } diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h index 8112c7609..ae0523460 100644 --- a/src/webengine/api/qquickwebengineview_p.h +++ b/src/webengine/api/qquickwebengineview_p.h @@ -199,7 +199,9 @@ public: MediaAudioCapture, MediaVideoCapture, MediaAudioVideoCapture, - Geolocation + Geolocation, + DesktopVideoCapture, + DesktopAudioVideoCapture }; Q_ENUM(Feature) @@ -244,6 +246,22 @@ public: Unselect, SavePage, ViewSource, + + ToggleBold, + ToggleItalic, + ToggleUnderline, + ToggleStrikethrough, + + AlignLeft, + AlignCenter, + AlignRight, + AlignJustified, + Indent, + Outdent, + + InsertOrderedList, + InsertUnorderedList, + WebActionCount }; Q_ENUM(WebAction) diff --git a/src/webengine/doc/src/qtwebengine-features.qdoc b/src/webengine/doc/src/qtwebengine-features.qdoc index 30d21f2ae..7850ff35d 100644 --- a/src/webengine/doc/src/qtwebengine-features.qdoc +++ b/src/webengine/doc/src/qtwebengine-features.qdoc @@ -78,8 +78,8 @@ This feature can be tested by launching a Qt WebEngine application with the command line option \c {--remote-debugging-port=[your-port]} or by setting the environment variable \c QTWEBENGINE_REMOTE_DEBUGGING, and then using a - Chromium based browser (such as \l{WebEngine Demo Browser Example} - {Demo Browser} or \l{WebEngine Quick Nano Browser}{Nano Browser}) to connect + Chromium based browser (such as \l{WebEngine Widgets Simple Browser Example} + {Simple Browser} or \l{WebEngine Quick Nano Browser}{Nano Browser}) to connect to \c {http://localhost:[your-port]}. For more information, see \l {Qt WebEngine Debugging and Profiling}. @@ -90,8 +90,8 @@ This feature can be tested by opening an HTML5 drag and drop demo, such as \l{HTML5 Demos - Drag and Drop}, \l{HTML5 Demos - Simple Drag and Drop}, or - \l{HTML5 Demos - Drag and Drop, Automatic Upload}, in \l{WebEngine Demo - Browser Example}{Demo Browser} or \l{WebEngine Quick Nano Browser} + \l{HTML5 Demos - Drag and Drop, Automatic Upload}, in \l{WebEngine Widgets + Simple Browser Example}{Simple Browser} or \l{WebEngine Quick Nano Browser} {Nano Browser}. Dragging files into the browser is not actually part of HTML5, but it is @@ -109,7 +109,7 @@ QWebEnginePage::fullScreenRequested. This feature can be tested by playing a video from YouTube in \l{WebEngine - Demo Browser Example}{Demo Browser} or \l{WebEngine Quick Nano Browser} + Widgets Video Player Example}{Video Player} or \l{WebEngine Quick Nano Browser} {Nano Browser}, and clicking the full screen icon to go into fullscreen mode. @@ -124,8 +124,8 @@ proprietary audio and video codecs. For more information about enabling the codecs, see \l{Audio and Video Codecs}. - This feature can be tested by playing a video in \l{WebEngine Demo Browser - Example}{Demo Browser} or \l{WebEngine Quick Nano Browser}{Nano Browser} + This feature can be tested by playing a video in \l{WebEngine Widgets Simple Browser + Example}{Simple Browser} or \l{WebEngine Quick Nano Browser}{Nano Browser} from \l{castLabs}, \l{Swank Motion Pictures, Inc.}, or \l{Shaka Player}. Support for this feature was added in Qt 5.7.0. @@ -137,11 +137,11 @@ QWebEnginePage::Geolocation or \l{WebEngineView::Feature} {WebEngineView.Feature}. - This feature can be tested if Qt Location has been built before Qt WebEngine. - The \c http://html5demos.com/geo page can be opened in the \l{WebEngine Demo - Browser Example}{Demo Browser} and allowed to find the current position of - the user. Note that on Windows an external GPS receiver must be connected to - the application. For more information, see \l{Qt Positioning}. + If Qt Location has been built before Qt WebEngine then this feature can be + tested by using \l{WebEngine Widgets Maps Example}{Maps} and allowing it to + find the current position of the user. Note that on Windows an external GPS + receiver must be connected to the application. For more information, see + \l{Qt Positioning}. Support for this feature was added in Qt 5.5.0. @@ -254,7 +254,7 @@ --ppapi-flash-version=16.0.0.235 \endcode - This feature can be tested in \l{WebEngine Demo Browser Example}{Demo Browser} + This feature can be tested in \l{WebEngine Widgets Simple Browser Example}{Simple Browser} or \l{WebEngine Quick Nano Browser}{Nano Browser} if the Adobe Flash PPAPI plugin is installed and plugins are enabled in the browser. To test the feature, the \c https://helpx.adobe.com/flash-player.html page can be opened @@ -266,8 +266,8 @@ information, see QWebEnginePage::printToPdf() and \l{WebEngineView::printToPdf}{WebEngineView.printToPdf}. - This feature can be tested in \l{WebEngine Demo Browser Example} - {Demo Browser} by selecting \uicontrol File > \uicontrol {Print to PDF}. + This feature can be tested using \l{WebEngine Widgets Html2Pdf Example} + {Html2Pdf}. Support for this feature was added in Qt 5.7.0. @@ -294,9 +294,40 @@ These two files can be converted into the \c bdic format by using the \c qwebengine_convert_dict tool that is shipped together with Qt. When the Qt WebEngine spellchecker initializes, it will try to load the - \c bdict dictionaries and to check them for consistency. First, it searches - \e qtwebengine_dictionaries directories relative to the executable, - then it will look in \c QT_INSTALL_PREFIX/qtwebengine_dictionaries. + \c bdict dictionaries and to check them for consistency. + + If \c QTWEBENGINE_DICTIONARIES_PATH is set, the spellchecker uses the + dictionaries in the specified directory without looking anywere else. + Otherwise, it uses the \e qtwebengine_dictionaries directory relative to the + executable if it exists. If it does not exist, it will look in \c + QT_INSTALL_PREFIX/qtwebengines_dictionaries. + + On macOS, depending on how Qt WebEngine is configured at build time, there + are two possibilities how spellchecking data is found: + + \list + \li Hunspell dictionaries (default) - .bdic dictionaries are used, just + like on other platforms + \li Native dictionaries - the macOS spellchecking APIs are used (which + means the results will depend on the installed OS dictionaries) + \endlist + + Thus, in the macOS Hunspell case, Qt WebEngine will look in the \e + qtwebengine_dictionaries subdirectory located inside the application bundle + \c Resources directory, and also in the \c Resources directory located + inside the Qt framework bundle. + + To summarize, in case of Hunspell usage, the following paths are considered: + + \list + \li \c QTWEBENGINE_DICTIONARIES_PATH, if set + \li QCoreApplication::applicationDirPath()/qtwebengine_dictionaries + or QCoreApplication::applicationDirPath()/../Contents/Resources/qtwebengine_dictionaries + (on macOS) + \li [QLibraryInfo::DataPath]/qtwebengine_dictionaries + or path/to/QtWebEngineCore.framework/Resources/qtwebengine_dictionaries (Qt framework + bundle on macOS) + \endlist Spellchecking is disabled by default and can be enabled per profile by using the QWebEngineProfile::setSpellCheckEnabled() method in widget-based diff --git a/src/webengine/doc/src/webengineview.qdoc b/src/webengine/doc/src/webengineview.qdoc index 27c3d6920..1d1c61f03 100644 --- a/src/webengine/doc/src/webengineview.qdoc +++ b/src/webengine/doc/src/webengineview.qdoc @@ -793,6 +793,46 @@ \value WebEngineView.ViewSource Show the source of the current page in a new tab. (Added in Qt 5.8) + \value WebEngineView.ToggleBold + Toggles boldness for the selection or at the cursor position. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.ToggleItalic + Toggles italics for the selection or at the cursor position. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.ToggleUnderline + Toggles underlining of the selection or at the cursor position. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.ToggleStrikethrough + Toggles striking through the selection or at the cursor position. + Requires \c contenteditable="true". (Added in Qt 5.10) + + \value WebEngineView.AlignLeft + Aligns the lines containing the selection or the cursor to the left. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.AlignCenter + Aligns the lines containing the selection or the cursor at the center. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.AlignRight + Aligns the lines containing the selection or the cursor to the right. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.AlignJustified + Stretches the lines containing the selection or the cursor so that each + line has equal width. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.Indent + Indents the lines containing the selection or the cursor. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.Outdent + Outdents the lines containing the selection or the cursor. + Requires \c contenteditable="true". (Added in Qt 5.10) + + \value WebEngineView.InsertOrderedList + Inserts an ordered list at the current cursor position, deleting the current selection. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.InsertUnorderedList + Inserts an unordered list at the current cursor position, + deleting the current selection. + Requires \c contenteditable="true". (Added in Qt 5.10) \omitvalue WebActionCount */ @@ -810,6 +850,11 @@ Video devices, such as cameras. \value WebEngineView.MediaAudioVideoCapture Both audio and video capture devices. + \value DesktopVideoCapture + Video output capture, that is, the capture of the user's display. + (Added in Qt 5.10) + \value DesktopAudioVideoCapture + Both audio and video output capture. (Added in Qt 5.10) \sa featurePermissionRequested(), grantFeaturePermission() */ diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp index 3c8991ff7..5ab792699 100644 --- a/src/webengine/plugin/plugin.cpp +++ b/src/webengine/plugin/plugin.cpp @@ -85,6 +85,7 @@ public: qmlRegisterType<QQuickWebEngineView, 3>(uri, 1, 3, "WebEngineView"); qmlRegisterType<QQuickWebEngineView, 4>(uri, 1, 4, "WebEngineView"); qmlRegisterType<QQuickWebEngineView, 5>(uri, 1, 5, "WebEngineView"); + qmlRegisterType<QQuickWebEngineView, 6>(uri, 1, 6, "WebEngineView"); qmlRegisterType<QQuickWebEngineProfile>(uri, 1, 1, "WebEngineProfile"); qmlRegisterType<QQuickWebEngineProfile, 1>(uri, 1, 2, "WebEngineProfile"); qmlRegisterType<QQuickWebEngineProfile, 2>(uri, 1, 3, "WebEngineProfile"); @@ -102,6 +103,8 @@ public: tr("Cannot create a separate instance of WebEngineDownloadItem")); qmlRegisterUncreatableType<QQuickWebEngineDownloadItem, 4>(uri, 1, 5, "WebEngineDownloadItem", tr("Cannot create a separate instance of WebEngineDownloadItem")); + qmlRegisterUncreatableType<QQuickWebEngineDownloadItem, 5>(uri, 1, 6, "WebEngineDownloadItem", + tr("Cannot create a separate instance of WebEngineDownloadItem")); qmlRegisterUncreatableType<QQuickWebEngineNewViewRequest>(uri, 1, 1, "WebEngineNewViewRequest", msgUncreatableType("WebEngineNewViewRequest")); qmlRegisterUncreatableType<QQuickWebEngineNewViewRequest, 1>(uri, 1, 5, "WebEngineNewViewRequest", tr("Cannot create separate instance of WebEngineNewViewRequest")); qmlRegisterUncreatableType<QQuickWebEngineSettings>(uri, 1, 1, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings")); @@ -109,6 +112,7 @@ public: qmlRegisterUncreatableType<QQuickWebEngineSettings, 2>(uri, 1, 3, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings")); qmlRegisterUncreatableType<QQuickWebEngineSettings, 3>(uri, 1, 4, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings")); qmlRegisterUncreatableType<QQuickWebEngineSettings, 4>(uri, 1, 5, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings")); + qmlRegisterUncreatableType<QQuickWebEngineSettings, 5>(uri, 1, 6, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings")); qmlRegisterSingletonType<QQuickWebEngineSingleton>(uri, 1, 1, "WebEngine", webEngineSingletonProvider); qmlRegisterUncreatableType<QQuickWebEngineHistory>(uri, 1, 1, "NavigationHistory", tr("Cannot create a separate instance of NavigationHistory")); diff --git a/src/webengine/plugin/plugin.pro b/src/webengine/plugin/plugin.pro index 68404b4f8..1f9ef00c5 100644 --- a/src/webengine/plugin/plugin.pro +++ b/src/webengine/plugin/plugin.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = qtwebengineplugin TARGETPATH = QtWebEngine -IMPORT_VERSION = 1.5 +IMPORT_VERSION = 1.6 QT += webengine qml quick QT_PRIVATE += webengine-private diff --git a/src/webengine/plugin/plugins.qmltypes b/src/webengine/plugin/plugins.qmltypes index 459d56c75..321c462b5 100644 --- a/src/webengine/plugin/plugins.qmltypes +++ b/src/webengine/plugin/plugins.qmltypes @@ -4,7 +4,7 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -defaultplatform -dependencies dependencies.json -nonrelocatable QtWebEngine 1.5' +// 'qmlplugindump -defaultplatform -dependencies dependencies.json -nonrelocatable QtWebEngine 1.6' Module { dependencies: ["QtQuick 2.6"] @@ -509,10 +509,11 @@ Module { "QtWebEngine/WebEngineSettings 1.2", "QtWebEngine/WebEngineSettings 1.3", "QtWebEngine/WebEngineSettings 1.4", - "QtWebEngine/WebEngineSettings 1.5" + "QtWebEngine/WebEngineSettings 1.5", + "QtWebEngine/WebEngineSettings 1.6" ] isCreatable: false - exportMetaObjectRevisions: [0, 1, 2, 3, 4] + exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5] Property { name: "autoLoadImages"; type: "bool" } Property { name: "javascriptEnabled"; type: "bool" } Property { name: "javascriptCanOpenWindows"; type: "bool" } @@ -536,6 +537,7 @@ Module { Property { name: "printElementBackgrounds"; revision: 3; type: "bool" } Property { name: "allowRunningInsecureContent"; revision: 3; type: "bool" } Property { name: "allowGeolocationOnInsecureOrigins"; revision: 4; type: "bool" } + Property { name: "allowWindowActivationFromJavaScript"; revision: 5; type: "bool" } Signal { name: "fullScreenSupportEnabledChanged"; revision: 1 } Signal { name: "screenCaptureEnabledChanged"; revision: 2 } Signal { name: "webGLEnabledChanged"; revision: 2 } @@ -546,6 +548,7 @@ Module { Signal { name: "printElementBackgroundsChanged"; revision: 3 } Signal { name: "allowRunningInsecureContentChanged"; revision: 3 } Signal { name: "allowGeolocationOnInsecureOriginsChanged"; revision: 4 } + Signal { name: "allowWindowActivationFromJavaScriptChanged"; revision: 5 } } Component { name: "QQuickWebEngineSingleton" @@ -573,9 +576,10 @@ Module { "QtWebEngine/WebEngineView 1.2", "QtWebEngine/WebEngineView 1.3", "QtWebEngine/WebEngineView 1.4", - "QtWebEngine/WebEngineView 1.5" + "QtWebEngine/WebEngineView 1.5", + "QtWebEngine/WebEngineView 1.6" ] - exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5] + exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5, 6] Enum { name: "NavigationRequestAction" values: { @@ -630,7 +634,9 @@ Module { "MediaAudioCapture": 0, "MediaVideoCapture": 1, "MediaAudioVideoCapture": 2, - "Geolocation": 3 + "Geolocation": 3, + "DesktopVideoCapture": 4, + "DesktopAudioVideoCapture": 5 } } Enum { @@ -669,7 +675,19 @@ Module { "Unselect": 29, "SavePage": 30, "ViewSource": 31, - "WebActionCount": 32 + "ToggleBold": 32, + "ToggleItalic": 33, + "ToggleUnderline": 34, + "ToggleStrikethrough": 35, + "AlignLeft": 36, + "AlignCenter": 37, + "AlignRight": 38, + "AlignJustified": 39, + "Indent": 40, + "Outdent": 41, + "InsertOrderedList": 42, + "InsertUnorderedList": 43, + "WebActionCount": 44 } } Enum { @@ -874,6 +892,7 @@ Module { Property { name: "audioMuted"; revision: 3; type: "bool" } Property { name: "recentlyAudible"; revision: 3; type: "bool"; isReadonly: true } Property { name: "webChannelWorld"; revision: 3; type: "uint" } + Property { name: "testSupport"; type: "QQuickWebEngineTestSupport"; isPointer: true } Signal { name: "loadingChanged" Parameter { name: "loadRequest"; type: "QQuickWebEngineLoadRequest"; isPointer: true } diff --git a/src/webengine/plugin/testsupport/plugin.cpp b/src/webengine/plugin/testsupport/plugin.cpp index 9352e3666..c7eda2405 100644 --- a/src/webengine/plugin/testsupport/plugin.cpp +++ b/src/webengine/plugin/testsupport/plugin.cpp @@ -58,6 +58,8 @@ public: qmlRegisterType<QQuickWebEngineTestSupport>(uri, 1, 0, "WebEngineTestSupport"); qmlRegisterUncreatableType<QQuickWebEngineErrorPage>(uri, 1, 0, "WebEngineErrorPage", tr("Cannot create a separate instance of WebEngineErrorPage")); + qmlRegisterUncreatableType<QQuickWebEngineTestInputContext>(uri, 1, 0, "TestInputContext", + tr("Cannot create a separate instance of WebEngineErrorPage")); } }; diff --git a/src/webengine/plugin/testsupport/testsupport.pro b/src/webengine/plugin/testsupport/testsupport.pro index 1a45ad56a..2804635f8 100644 --- a/src/webengine/plugin/testsupport/testsupport.pro +++ b/src/webengine/plugin/testsupport/testsupport.pro @@ -4,7 +4,7 @@ TARGETPATH = QtWebEngine/testsupport IMPORT_VERSION = 1.0 QT += webengine qml quick -QT_PRIVATE += webengine-private +QT_PRIVATE += webengine-private gui-private INCLUDEPATH += $$QTWEBENGINE_ROOT/src/core $$QTWEBENGINE_ROOT/src/webengine $$QTWEBENGINE_ROOT/src/webengine/api diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp index b6069d519..650a40988 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp +++ b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp @@ -50,11 +50,6 @@ #include <private/qquickwindow_p.h> #include <private/qsgcontext_p.h> -#if (QT_VERSION < QT_VERSION_CHECK(5, 8, 0)) -#include <QSGSimpleRectNode> -#include <QSGSimpleTextureNode> -#endif - namespace QtWebEngineCore { RenderWidgetHostViewQtDelegateQuick::RenderWidgetHostViewQtDelegateQuick(RenderWidgetHostViewQtDelegateClient *client, bool isPopup) @@ -185,30 +180,17 @@ QSGLayer *RenderWidgetHostViewQtDelegateQuick::createLayer() QSGInternalImageNode *RenderWidgetHostViewQtDelegateQuick::createImageNode() { QSGRenderContext *renderContext = QQuickWindowPrivate::get(QQuickItem::window())->context; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) return renderContext->sceneGraphContext()->createInternalImageNode(); -#else - return renderContext->sceneGraphContext()->createImageNode(); -#endif } QSGTextureNode *RenderWidgetHostViewQtDelegateQuick::createTextureNode() { -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) return QQuickItem::window()->createImageNode(); -#else - return new QSGSimpleTextureNode(); -#endif } QSGRectangleNode *RenderWidgetHostViewQtDelegateQuick::createRectangleNode() { -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) return QQuickItem::window()->createRectangleNode(); -#else - QSGRenderContext *renderContext = QQuickWindowPrivate::get(QQuickItem::window())->context; - return renderContext->sceneGraphContext()->createRectangleNode(); -#endif } void RenderWidgetHostViewQtDelegateQuick::update() @@ -228,14 +210,15 @@ void RenderWidgetHostViewQtDelegateQuick::resize(int width, int height) void RenderWidgetHostViewQtDelegateQuick::inputMethodStateChanged(bool editorVisible) { - if (qApp->inputMethod()->isVisible() == editorVisible) - return; + setFlag(QQuickItem::ItemAcceptsInputMethod, editorVisible); - if (parentItem() && parentItem()->flags() & QQuickItem::ItemAcceptsInputMethod) { + if (parentItem()) + parentItem()->setFlag(QQuickItem::ItemAcceptsInputMethod, editorVisible); + + if (qApp->inputMethod()->isVisible() != editorVisible) { qApp->inputMethod()->update(Qt::ImQueryInput | Qt::ImEnabled | Qt::ImHints); qApp->inputMethod()->setVisible(editorVisible); } - } bool RenderWidgetHostViewQtDelegateQuick::event(QEvent *event) diff --git a/src/webengine/ui_delegates_manager.cpp b/src/webengine/ui_delegates_manager.cpp index 6cc496d5b..43e6e8817 100644 --- a/src/webengine/ui_delegates_manager.cpp +++ b/src/webengine/ui_delegates_manager.cpp @@ -560,11 +560,7 @@ void UIDelegatesManager::showToolTip(const QString &text) int width = QQmlProperty(m_toolTip.data(), QStringLiteral("width")).read().toInt(); QSize toolTipSize(width, height); QPoint position = m_view->cursor().pos(); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)) position = m_view->mapFromGlobal(calculateToolTipPosition(position, toolTipSize)).toPoint(); -#else - position = m_view->window()->mapFromGlobal(calculateToolTipPosition(position, toolTipSize)); -#endif QQmlProperty(m_toolTip.data(), QStringLiteral("x")).write(position.x()); QQmlProperty(m_toolTip.data(), QStringLiteral("y")).write(position.y()); diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro index 5ac93c9a7..f8df714c0 100644 --- a/src/webengine/webengine.pro +++ b/src/webengine/webengine.pro @@ -77,7 +77,7 @@ use?(pdf) { $$python chromium/tools/licenses.py \ --file-template ../../tools/about_credits.tmpl \ --entry-template ../../tools/about_credits_entry.tmpl credits \ - > $$shell_quote($$shell_path($$OUT_PWD/chromium_attributions.qdoc)) + $$shell_quote($$shell_path($$OUT_PWD/chromium_attributions.qdoc)) chromium_attributions.CONFIG += phony QMAKE_EXTRA_TARGETS += chromium_attributions diff --git a/src/webenginewidgets/api/qwebenginecontextmenudata.cpp b/src/webenginewidgets/api/qwebenginecontextmenudata.cpp index 5d68ed0ec..63e11175b 100644 --- a/src/webenginewidgets/api/qwebenginecontextmenudata.cpp +++ b/src/webenginewidgets/api/qwebenginecontextmenudata.cpp @@ -148,10 +148,11 @@ QString QWebEngineContextMenuData::linkText() const /*! Returns the URL of a link if the context is a link. + It is not guaranteed to be a valid URL. */ QUrl QWebEngineContextMenuData::linkUrl() const { - return d ? d->linkUrl() : QUrl(); + return d ? d->unfilteredLinkUrl() : QUrl(); } /*! diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp index c1d9a3698..a5569e408 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem.cpp +++ b/src/webenginewidgets/api/qwebenginedownloaditem.cpp @@ -38,10 +38,12 @@ ****************************************************************************/ #include "qwebenginedownloaditem.h" - #include "qwebenginedownloaditem_p.h" + +#include "browser_context_adapter.h" #include "qwebengineprofile_p.h" + QT_BEGIN_NAMESPACE using QtWebEngineCore::BrowserContextAdapterClient; @@ -116,6 +118,7 @@ QWebEngineDownloadItemPrivate::QWebEngineDownloadItemPrivate(QWebEngineProfilePr , type(QWebEngineDownloadItem::Attachment) , interruptReason(QWebEngineDownloadItem::NoReason) , downloadUrl(url) + , downloadPaused(false) , totalBytes(-1) , receivedBytes(0) { @@ -145,10 +148,16 @@ void QWebEngineDownloadItemPrivate::update(const BrowserContextAdapterClient::Do Q_EMIT q->downloadProgress(receivedBytes, totalBytes); } - downloadFinished = downloadState != QWebEngineDownloadItem::DownloadInProgress; + if (info.done != downloadFinished) { + downloadFinished = info.done; + if (downloadFinished) + Q_EMIT q->finished(); + } - if (downloadFinished) - Q_EMIT q->finished(); + if (downloadPaused != info.paused) { + downloadPaused = info.paused; + Q_EMIT q->isPausedChanged(downloadPaused); + } } /*! @@ -184,13 +193,50 @@ void QWebEngineDownloadItem::cancel() || state == QWebEngineDownloadItem::DownloadCancelled) return; - d->downloadState = QWebEngineDownloadItem::DownloadCancelled; - Q_EMIT stateChanged(d->downloadState); - // We directly cancel the download request if the user cancels // before it even started, so no need to notify the profile here. if (state == QWebEngineDownloadItem::DownloadInProgress) - d->profile->cancelDownload(d->downloadId); + d->profile->browserContext()->cancelDownload(d->downloadId); + else { + d->downloadState = QWebEngineDownloadItem::DownloadCancelled; + Q_EMIT stateChanged(d->downloadState); + } +} + +/*! + \since 5.10 + Pauses the current download. Has no effect if the state is not \c DownloadInProgress. + + \sa resume() +*/ + +void QWebEngineDownloadItem::pause() +{ + Q_D(QWebEngineDownloadItem); + + QWebEngineDownloadItem::DownloadState state = d->downloadState; + + if (state != QWebEngineDownloadItem::DownloadInProgress) + return; + + d->profile->browserContext()->pauseDownload(d->downloadId); +} + +/*! + \since 5.10 + Resumes the current download if it was paused or interrupted. + + \sa pause(), isPaused(), state() +*/ +void QWebEngineDownloadItem::resume() +{ + Q_D(QWebEngineDownloadItem); + + QWebEngineDownloadItem::DownloadState state = d->downloadState; + + if (d->downloadFinished || (state != QWebEngineDownloadItem::DownloadInProgress && state != QWebEngineDownloadItem::DownloadInterrupted)) + return; + d->profile->browserContext()->resumeDownload(d->downloadId); } /*! @@ -206,12 +252,21 @@ quint32 QWebEngineDownloadItem::id() const /*! \fn QWebEngineDownloadItem::finished() - This signal is emitted whenever the download finishes. + This signal is emitted when the download finishes. \sa state(), isFinished() */ /*! + \fn QWebEngineDownloadItem::isPausedChanged(bool isPaused) + \since 5.10 + + This signal is emitted whenever \a isPaused changes. + + \sa pause(), isPaused() +*/ + +/*! \fn QWebEngineDownloadItem::stateChanged(DownloadState state) This signal is emitted whenever the download's \a state changes. @@ -407,7 +462,7 @@ void QWebEngineDownloadItem::setPath(QString path) } /*! - Returns whether this download is finished (not in progress). + Returns whether this download is finished (completed, cancelled, or non-resumable interrupted state). \sa finished(), state(), */ @@ -419,6 +474,18 @@ bool QWebEngineDownloadItem::isFinished() const } /*! + Returns whether this download is paused. + + \sa pause() +*/ + +bool QWebEngineDownloadItem::isPaused() const +{ + Q_D(const QWebEngineDownloadItem); + return d->downloadPaused; +} + +/*! Returns the format the web page will be saved in if this is a download request for a web page. \since 5.7 diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.h b/src/webenginewidgets/api/qwebenginedownloaditem.h index a4b6c08aa..2aca2bb2a 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem.h +++ b/src/webenginewidgets/api/qwebenginedownloaditem.h @@ -120,6 +120,7 @@ public: QString path() const; void setPath(QString path); bool isFinished() const; + bool isPaused() const; SavePageFormat savePageFormat() const; void setSavePageFormat(SavePageFormat format); DownloadType type() const; @@ -129,11 +130,14 @@ public: public Q_SLOTS: void accept(); void cancel(); + void pause(); + void resume(); Q_SIGNALS: void finished(); void stateChanged(QWebEngineDownloadItem::DownloadState state); void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); + void isPausedChanged(bool isPaused); private: Q_DISABLE_COPY(QWebEngineDownloadItem) diff --git a/src/webenginewidgets/api/qwebenginedownloaditem_p.h b/src/webenginewidgets/api/qwebenginedownloaditem_p.h index 038332da3..da765e5c5 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem_p.h +++ b/src/webenginewidgets/api/qwebenginedownloaditem_p.h @@ -77,6 +77,7 @@ public: QString downloadPath; const QUrl downloadUrl; QString mimeType; + bool downloadPaused; qint64 totalBytes; qint64 receivedBytes; diff --git a/src/webenginewidgets/api/qwebenginehistory.h b/src/webenginewidgets/api/qwebenginehistory.h index 21ebbf41d..33d91d523 100644 --- a/src/webenginewidgets/api/qwebenginehistory.h +++ b/src/webenginewidgets/api/qwebenginehistory.h @@ -79,9 +79,7 @@ private: friend class QWebEngineHistoryPrivate; }; -#if QT_VERSION >= QT_VERSION_CHECK(5,6,0) Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QWebEngineHistoryItem) -#endif class QWebEngineHistoryPrivate; class QWEBENGINEWIDGETS_EXPORT QWebEngineHistory { diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 51456128f..178f6ec98 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -60,6 +60,7 @@ #include "render_widget_host_view_qt_delegate_widget.h" #include "web_contents_adapter.h" #include "web_engine_settings.h" +#include "qwebenginescript.h" #ifdef QT_UI_DELEGATES #include "ui/messagebubblewidget_p.h" @@ -100,13 +101,8 @@ static const int MaxTooltipLength = 1024; static bool printPdfDataOnPrinter(const QByteArray& data, QPrinter& printer) { if (!data.size()) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) qWarning("Failure to print on printer %ls: Print result data is empty.", qUtf16Printable(printer.printerName())); -#else - qWarning("Failure to print on printer %s: Print result data is empty.", - qPrintable(printer.printerName())); -#endif return false; } @@ -142,11 +138,7 @@ static bool printPdfDataOnPrinter(const QByteArray& data, QPrinter& printer) QPainter painter; if (!painter.begin(&printer)) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) qWarning("Failure to print on printer %ls: Could not open printer for painting.", qUtf16Printable(printer.printerName())); -#else - qWarning("Failure to print on printer %s: Could not open printer for painting.", qPrintable(printer.printerName())); -#endif return false; } @@ -352,7 +344,6 @@ void QWebEnginePagePrivate::loadFinished(bool success, const QUrl &url, bool isE if (isErrorPage) { Q_ASSERT(settings->testAttribute(QWebEngineSettings::ErrorPageEnabled)); - Q_ASSERT(success); Q_EMIT q->loadFinished(false); return; } @@ -376,8 +367,10 @@ void QWebEnginePagePrivate::didPrintPageToPdf(const QString &filePath, bool succ void QWebEnginePagePrivate::focusContainer() { - if (view) + if (view) { + view->activateWindow(); view->setFocus(); + } } void QWebEnginePagePrivate::unhandledKeyEvent(QKeyEvent *event) @@ -558,16 +551,20 @@ void QWebEnginePagePrivate::showColorDialog(QSharedPointer<ColorChooserControlle void QWebEnginePagePrivate::runMediaAccessPermissionRequest(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags requestFlags) { Q_Q(QWebEnginePage); - QWebEnginePage::Feature requestedFeature; - if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture) && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) - requestedFeature = QWebEnginePage::MediaAudioVideoCapture; + QWebEnginePage::Feature feature; + if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture) && + requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) + feature = QWebEnginePage::MediaAudioVideoCapture; else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture)) - requestedFeature = QWebEnginePage::MediaAudioCapture; + feature = QWebEnginePage::MediaAudioCapture; else if (requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) - requestedFeature = QWebEnginePage::MediaVideoCapture; - else - return; - Q_EMIT q->featurePermissionRequested(securityOrigin, requestedFeature); + feature = QWebEnginePage::MediaVideoCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture) && + requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) + feature = QWebEnginePage::DesktopAudioVideoCapture; + else // if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) + feature = QWebEnginePage::DesktopVideoCapture; + Q_EMIT q->featurePermissionRequested(securityOrigin, feature); } void QWebEnginePagePrivate::runGeolocationPermissionRequest(const QUrl &securityOrigin) @@ -1140,6 +1137,42 @@ QAction *QWebEnginePage::action(WebAction action) const case ViewSource: text = tr("&View Page Source"); break; + case ToggleBold: + text = tr("&Bold"); + break; + case ToggleItalic: + text = tr("&Italic"); + break; + case ToggleUnderline: + text = tr("&Underline"); + break; + case ToggleStrikethrough: + text = tr("&Strikethrough"); + break; + case AlignLeft: + text = tr("Align &Left"); + break; + case AlignCenter: + text = tr("Align &Center"); + break; + case AlignRight: + text = tr("Align &Right"); + break; + case AlignJustified: + text = tr("Align &Justified"); + break; + case Indent: + text = tr("&Indent"); + break; + case Outdent: + text = tr("&Outdent"); + break; + case InsertOrderedList: + text = tr("Insert &Ordered List"); + break; + case InsertUnorderedList: + text = tr("Insert &Unordered List"); + break; case NoWebAction: case WebActionCount: Q_UNREACHABLE(); @@ -1229,14 +1262,14 @@ void QWebEnginePage::triggerAction(WebAction action, bool) } break; case CopyLinkToClipboard: - if (menuData.linkUrl().isValid()) { - QString urlString = menuData.linkUrl().toString(QUrl::FullyEncoded); + if (!menuData.unfilteredLinkUrl().isEmpty()) { + QString urlString = menuData.unfilteredLinkUrl().toString(QUrl::FullyEncoded); QString title = menuData.linkText().toHtmlEscaped(); QMimeData *data = new QMimeData(); data->setText(urlString); QString html = QStringLiteral("<a href=\"") + urlString + QStringLiteral("\">") + title + QStringLiteral("</a>"); data->setHtml(html); - data->setUrls(QList<QUrl>() << menuData.linkUrl()); + data->setUrls(QList<QUrl>() << menuData.unfilteredLinkUrl()); qApp->clipboard()->setMimeData(data); } break; @@ -1341,6 +1374,42 @@ void QWebEnginePage::triggerAction(WebAction action, bool) // the viewSource() call after the QMenu's destruction. QTimer::singleShot(0, this, [d](){ d->adapter->viewSource(); }); break; + case ToggleBold: + runJavaScript(QStringLiteral("document.execCommand('bold');"), QWebEngineScript::ApplicationWorld); + break; + case ToggleItalic: + runJavaScript(QStringLiteral("document.execCommand('italic');"), QWebEngineScript::ApplicationWorld); + break; + case ToggleUnderline: + runJavaScript(QStringLiteral("document.execCommand('underline');"), QWebEngineScript::ApplicationWorld); + break; + case ToggleStrikethrough: + runJavaScript(QStringLiteral("document.execCommand('strikethrough');"), QWebEngineScript::ApplicationWorld); + break; + case AlignLeft: + runJavaScript(QStringLiteral("document.execCommand('justifyLeft');"), QWebEngineScript::ApplicationWorld); + break; + case AlignCenter: + runJavaScript(QStringLiteral("document.execCommand('justifyCenter');"), QWebEngineScript::ApplicationWorld); + break; + case AlignRight: + runJavaScript(QStringLiteral("document.execCommand('justifyRight');"), QWebEngineScript::ApplicationWorld); + break; + case AlignJustified: + runJavaScript(QStringLiteral("document.execCommand('justifyFull');"), QWebEngineScript::ApplicationWorld); + break; + case Indent: + runJavaScript(QStringLiteral("document.execCommand('indent');"), QWebEngineScript::ApplicationWorld); + break; + case Outdent: + runJavaScript(QStringLiteral("document.execCommand('outdent');"), QWebEngineScript::ApplicationWorld); + break; + case InsertOrderedList: + runJavaScript(QStringLiteral("document.execCommand('insertOrderedList');"), QWebEngineScript::ApplicationWorld); + break; + case InsertUnorderedList: + runJavaScript(QStringLiteral("document.execCommand('insertUnorderedList');"), QWebEngineScript::ApplicationWorld); + break; case NoWebAction: break; case WebActionCount: @@ -1607,7 +1676,7 @@ QMenu *QWebEnginePage::createStandardContextMenu() menu->addAction(QWebEnginePage::action(Unselect)); } - if (!contextMenuData.linkText().isEmpty() && contextMenuData.linkUrl().isValid()) { + if (!contextMenuData.linkText().isEmpty() && !contextMenuData.unfilteredLinkUrl().isEmpty()) { menu->addAction(QWebEnginePage::action(CopyLinkToClipboard)); } if (contextMenuData.mediaUrl().isValid()) { @@ -1654,37 +1723,58 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine Q_D(QWebEnginePage); if (policy == PermissionUnknown) return; - WebContentsAdapterClient::MediaRequestFlags flags = WebContentsAdapterClient::MediaNone; - switch (feature) { - case MediaAudioVideoCapture: - case MediaAudioCapture: - case MediaVideoCapture: - if (policy != PermissionUnknown) { - if (policy == PermissionDeniedByUser) - flags = WebContentsAdapterClient::MediaNone; - else { - if (feature == MediaAudioCapture) - flags = WebContentsAdapterClient::MediaAudioCapture; - else if (feature == MediaVideoCapture) - flags = WebContentsAdapterClient::MediaVideoCapture; - else - flags = WebContentsAdapterClient::MediaRequestFlags(WebContentsAdapterClient::MediaVideoCapture | WebContentsAdapterClient::MediaAudioCapture); - } - d->adapter->grantMediaAccessPermission(securityOrigin, flags); - } - d->adapter->grantMediaAccessPermission(securityOrigin, flags); - break; - case QWebEnginePage::Geolocation: - d->adapter->runGeolocationRequestCallback(securityOrigin, (policy == PermissionGrantedByUser) ? true : false); - break; - case MouseLock: - if (policy == PermissionGrantedByUser) + + const WebContentsAdapterClient::MediaRequestFlags audioVideoCaptureFlags( + WebContentsAdapterClient::MediaVideoCapture | + WebContentsAdapterClient::MediaAudioCapture); + const WebContentsAdapterClient::MediaRequestFlags desktopAudioVideoCaptureFlags( + WebContentsAdapterClient::MediaDesktopVideoCapture | + WebContentsAdapterClient::MediaDesktopAudioCapture); + + if (policy == PermissionGrantedByUser) { + switch (feature) { + case MediaAudioVideoCapture: + d->adapter->grantMediaAccessPermission(securityOrigin, audioVideoCaptureFlags); + break; + case MediaAudioCapture: + d->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaAudioCapture); + break; + case MediaVideoCapture: + d->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaVideoCapture); + break; + case DesktopAudioVideoCapture: + d->adapter->grantMediaAccessPermission(securityOrigin, desktopAudioVideoCaptureFlags); + break; + case DesktopVideoCapture: + d->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaDesktopVideoCapture); + break; + case Geolocation: + d->adapter->runGeolocationRequestCallback(securityOrigin, true); + break; + case MouseLock: d->adapter->grantMouseLockPermission(true); - else + break; + case Notifications: + break; + } + } else { // if (policy == PermissionDeniedByUser) + switch (feature) { + case MediaAudioVideoCapture: + case MediaAudioCapture: + case MediaVideoCapture: + case DesktopAudioVideoCapture: + case DesktopVideoCapture: + d->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaNone); + break; + case Geolocation: + d->adapter->runGeolocationRequestCallback(securityOrigin, false); + break; + case MouseLock: d->adapter->grantMouseLockPermission(false); - break; - case Notifications: - break; + break; + case Notifications: + break; + } } } @@ -1711,6 +1801,25 @@ WebEngineSettings *QWebEnginePagePrivate::webEngineSettings() const return settings->d_func(); } +/*! + \since 5.10 + Downloads the resource from the location given by \a url to a local file. + + If \a filename is given, it is used as the suggested file name. + If it is relative, the file is saved in the standard download location with + the given name. + If it is a null or empty QString, the default file name is used. + + This will emit QWebEngineProfile::downloadRequested() after the download + has started. +*/ + +void QWebEnginePage::download(const QUrl& url, const QString& filename) +{ + Q_D(QWebEnginePage); + d->adapter->download(url, filename); +} + void QWebEnginePage::load(const QUrl& url) { Q_D(QWebEnginePage); @@ -2001,11 +2110,7 @@ void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &page Q_D(const QWebEnginePage); #if defined(ENABLE_PRINTING) if (d->currentPrinter) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) qWarning("Cannot print to PDF while at the same time printing on printer %ls", qUtf16Printable(d->currentPrinter->printerName())); -#else - qWarning("Cannot print to PDF while at the same time printing on printer %s", qPrintable(d->currentPrinter->printerName())); -#endif return; } #endif // ENABLE_PRINTING @@ -2034,11 +2139,7 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res #if defined(ENABLE_PDF) #if defined(ENABLE_PRINTING) if (d->currentPrinter) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) qWarning("Cannot print to PDF while at the same time printing on printer %ls", qUtf16Printable(d->currentPrinter->printerName())); -#else - qWarning("Cannot print to PDF while at the same time printing on printer %s", qPrintable(d->currentPrinter->printerName())); -#endif d->m_callbacks.invokeEmpty(resultCallback); return; } @@ -2070,11 +2171,7 @@ void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &re #if defined(ENABLE_PDF) #if defined(ENABLE_PRINTING) if (d->currentPrinter) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) qWarning("Cannot print page on printer %ls: Already printing on %ls.", qUtf16Printable(printer->printerName()), qUtf16Printable(d->currentPrinter->printerName())); -#else - qWarning("Cannot print page on printer %s: Already printing on %s.", qPrintable(printer->printerName()), qPrintable(d->currentPrinter->printerName())); -#endif d->m_callbacks.invokeDirectly(resultCallback, false); return; } diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h index 5619639c7..295527e74 100644 --- a/src/webenginewidgets/api/qwebenginepage.h +++ b/src/webenginewidgets/api/qwebenginepage.h @@ -128,6 +128,22 @@ public: SavePage, OpenLinkInNewBackgroundTab, ViewSource, + + ToggleBold, + ToggleItalic, + ToggleUnderline, + ToggleStrikethrough, + + AlignLeft, + AlignCenter, + AlignRight, + AlignJustified, + Indent, + Outdent, + + InsertOrderedList, + InsertUnorderedList, + WebActionCount }; Q_ENUM(WebAction) @@ -172,7 +188,9 @@ public: MediaAudioCapture = 2, MediaVideoCapture, MediaAudioVideoCapture, - MouseLock + MouseLock, + DesktopVideoCapture, + DesktopAudioVideoCapture }; Q_ENUM(Feature) @@ -234,6 +252,7 @@ public: void load(const QUrl &url); void load(const QWebEngineHttpRequest &request); + void download(const QUrl &url, const QString &filename = QString()); void setHtml(const QString &html, const QUrl &baseUrl = QUrl()); void setContent(const QByteArray &data, const QString &mimeType = QString(), const QUrl &baseUrl = QUrl()); diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp index cd4fc8b02..adafc1544 100644 --- a/src/webenginewidgets/api/qwebengineprofile.cpp +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -142,7 +142,7 @@ using QtWebEngineCore::BrowserContextAdapter; will be deleted immediately after the signal emission. This signal cannot be used with a queued connection. - \sa QWebEngineDownloadItem + \sa QWebEngineDownloadItem, QWebEnginePage::download() */ QWebEngineProfilePrivate::QWebEngineProfilePrivate(QSharedPointer<BrowserContextAdapter> browserContext) @@ -151,7 +151,7 @@ QWebEngineProfilePrivate::QWebEngineProfilePrivate(QSharedPointer<BrowserContext , m_browserContextRef(browserContext) { m_browserContextRef->addClient(this); - m_settings->d_ptr->initDefaults(browserContext->isOffTheRecord()); + m_settings->d_ptr->initDefaults(); } QWebEngineProfilePrivate::~QWebEngineProfilePrivate() @@ -172,11 +172,6 @@ QWebEngineProfilePrivate::~QWebEngineProfilePrivate() m_ongoingDownloads.clear(); } -void QWebEngineProfilePrivate::cancelDownload(quint32 downloadId) -{ - browserContext()->cancelDownload(downloadId); -} - void QWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId) { m_ongoingDownloads.remove(downloadId); @@ -574,34 +569,8 @@ QWebEngineProfile *QWebEngineProfile::defaultProfile() For example, the language \c en-US will load the \c en-US.bdic dictionary file. - Qt WebEngine checks for the \c qtwebengine_dictionaries subdirectory - first in the local directory and if it is not found, in the Qt - installation directory. - - On macOS, depending on how Qt WebEngine is configured at build time, there are two possibilities - how spellchecking data is found: - - \list - \li Hunspell dictionaries (default) - .bdic dictionaries are used, just like on other - platforms - \li Native dictionaries - the macOS spellchecking APIs are used (which means the results - will depend on the installed OS dictionaries) - \endlist - - Thus, in the macOS Hunspell case, Qt WebEngine will look in the \e qtwebengine_dictionaries - subdirectory located inside the application bundle \c Resources directory, and also in the - \c Resources directory located inside the Qt framework bundle. - - To summarize, in case of Hunspell usage, the following paths are considered: - - \list - \li QCoreApplication::applicationDirPath()/qtwebengine_dictionaries - or QCoreApplication::applicationDirPath()/../Contents/Resources/qtwebengine_dictionaries - (on macOS) - \li [QLibraryInfo::DataPath]/qtwebengine_dictionaries - or path/to/QtWebEngineCore.framework/Resources/qtwebengine_dictionaries (Qt framework - bundle on macOS) - \endlist + See the \l {Spellchecker}{Spellchecker feature documentation} for how + dictionary files are searched. For more information about how to compile \c .bdic dictionaries, see the \l{WebEngine Widgets Spellchecker Example}{Spellchecker Example}. diff --git a/src/webenginewidgets/api/qwebengineprofile_p.h b/src/webenginewidgets/api/qwebengineprofile_p.h index 4d31c5a81..c5a75f6d4 100644 --- a/src/webenginewidgets/api/qwebengineprofile_p.h +++ b/src/webenginewidgets/api/qwebengineprofile_p.h @@ -76,7 +76,6 @@ public: QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext() const { return m_browserContextRef; } QWebEngineSettings *settings() const { return m_settings; } - void cancelDownload(quint32 downloadId); void downloadDestroyed(quint32 downloadId); void downloadRequested(DownloadItemInfo &info) Q_DECL_OVERRIDE; diff --git a/src/webenginewidgets/api/qwebenginescript.h b/src/webenginewidgets/api/qwebenginescript.h index 34c13e4b7..e3f65ec59 100644 --- a/src/webenginewidgets/api/qwebenginescript.h +++ b/src/webenginewidgets/api/qwebenginescript.h @@ -102,9 +102,7 @@ private: QSharedDataPointer<QtWebEngineCore::UserScript> d; }; -#if QT_VERSION >= QT_VERSION_CHECK(5,6,0) Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QWebEngineScript) -#endif #ifndef QT_NO_DEBUG_STREAM QWEBENGINEWIDGETS_EXPORT QDebug operator<<(QDebug, const QWebEngineScript &); diff --git a/src/webenginewidgets/api/qwebenginesettings.cpp b/src/webenginewidgets/api/qwebenginesettings.cpp index 65c77a54d..439e00590 100644 --- a/src/webenginewidgets/api/qwebenginesettings.cpp +++ b/src/webenginewidgets/api/qwebenginesettings.cpp @@ -97,6 +97,10 @@ static WebEngineSettings::Attribute toWebEngineAttribute(QWebEngineSettings::Web return WebEngineSettings::AllowRunningInsecureContent; case QWebEngineSettings::AllowGeolocationOnInsecureOrigins: return WebEngineSettings::AllowGeolocationOnInsecureOrigins; + case QWebEngineSettings::AllowWindowActivationFromJavaScript: + return WebEngineSettings::AllowWindowActivationFromJavaScript; + case QWebEngineSettings::HideScrollbars: + return WebEngineSettings::HideScrollbars; default: return WebEngineSettings::UnsupportedInCoreSettings; diff --git a/src/webenginewidgets/api/qwebenginesettings.h b/src/webenginewidgets/api/qwebenginesettings.h index 73995a457..1857e5228 100644 --- a/src/webenginewidgets/api/qwebenginesettings.h +++ b/src/webenginewidgets/api/qwebenginesettings.h @@ -89,7 +89,9 @@ public: FocusOnNavigationEnabled, PrintElementBackgrounds, AllowRunningInsecureContent, - AllowGeolocationOnInsecureOrigins + AllowGeolocationOnInsecureOrigins, + AllowWindowActivationFromJavaScript, + HideScrollbars }; enum FontSize { diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc index 715fce6d0..3b9300a4b 100644 --- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc @@ -158,6 +158,46 @@ the web page on disk. (Added in Qt 5.7) \value ViewSource Show the source of the current page in a new tab. (Added in Qt 5.8) + \value ToggleBold + Toggles boldness for the selection or at the cursor position. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value ToggleItalic + Toggles italics for the selection or at the cursor position. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value ToggleUnderline + Toggles underlining of the selection or at the cursor position. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value ToggleStrikethrough + Toggles striking through the selection or at the cursor position. + Requires \c contenteditable="true". (Added in Qt 5.10) + + \value AlignLeft + Aligns the lines containing the selection or the cursor to the left. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value AlignCenter + Aligns the lines containing the selection or the cursor at the center. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value AlignRight + Aligns the lines containing the selection or the cursor to the right. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value AlignJustified + Stretches the lines containing the selection or the cursor so that each + line has equal width. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value Indent + Indents the lines containing the selection or the cursor. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value Outdent + Outdents the lines containing the selection or the cursor. + Requires \c contenteditable="true". (Added in Qt 5.10) + + \value InsertOrderedList + Inserts an ordered list at the current cursor position, deleting the current selection. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value InsertUnorderedList + Inserts an unordered list at the current cursor position, + deleting the current selection. + Requires \c contenteditable="true". (Added in Qt 5.10) \omitvalue WebActionCount */ @@ -246,6 +286,11 @@ \value MouseLock Mouse locking, which locks the mouse pointer to the web view and is typically used in games. + \value DesktopVideoCapture + Video output capture, that is, the capture of the user's display, + for screen sharing purposes for example. (Added in Qt 5.10) + \value DesktopAudioVideoCapture + Both audio and video output capture. (Added in Qt 5.10) \sa featurePermissionRequested(), featurePermissionRequestCanceled(), setFeaturePermission(), PermissionPolicy diff --git a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc index d26babd5a..907f6f643 100644 --- a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc @@ -162,6 +162,12 @@ Geolocation features. This provides an override to allow non secure origins to access Geolocation again. Disabled by default. (Added in Qt 5.9) + \value AllowWindowActivationFromJavaScript + Allows the window.focus() method in JavaScript. Disallowed by default. + (Added in Qt 5.10) + \value HideScrollbars + Hides scrollbars. + Disabled by default. (Added in Qt 5.10) */ diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc index e54c5d507..34a61ded3 100644 --- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc @@ -77,7 +77,7 @@ new windows, such as pop-up windows, you can subclass QWebEngineView and reimplement the createWindow() function. - \sa {WebEngine Demo Browser Example}, {WebEngine Content Manipulation Example}, {WebEngine Markdown Editor Example} + \sa {WebEngine Widgets Simple Browser Example}, {WebEngine Content Manipulation Example}, {WebEngine Markdown Editor Example} */ diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp index d02191b23..a504506a0 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp @@ -51,10 +51,6 @@ #include <QWindow> #include <private/qquickwindow_p.h> -#if (QT_VERSION < QT_VERSION_CHECK(5, 8, 0)) -#include <QSGSimpleRectNode> -#include <QSGSimpleTextureNode> -#endif #include <private/qwidget_p.h> namespace QtWebEngineCore { @@ -115,8 +111,6 @@ RenderWidgetHostViewQtDelegateWidget::RenderWidgetHostViewQtDelegateWidget(Rende { setFocusPolicy(Qt::StrongFocus); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)) - QSurfaceFormat format; format.setDepthBufferSize(24); format.setStencilBufferSize(8); @@ -150,7 +144,6 @@ RenderWidgetHostViewQtDelegateWidget::RenderWidgetHostViewQtDelegateWidget(Rende setFormat(format); #endif -#endif setMouseTracking(true); setAttribute(Qt::WA_AcceptTouchEvents); setAttribute(Qt::WA_OpaquePaintEvent); @@ -290,30 +283,17 @@ QSGLayer *RenderWidgetHostViewQtDelegateWidget::createLayer() QSGInternalImageNode *RenderWidgetHostViewQtDelegateWidget::createImageNode() { QSGRenderContext *renderContext = QQuickWindowPrivate::get(quickWindow())->context; -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) return renderContext->sceneGraphContext()->createInternalImageNode(); -#else - return renderContext->sceneGraphContext()->createImageNode(); -#endif } QSGTextureNode *RenderWidgetHostViewQtDelegateWidget::createTextureNode() { -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) return quickWindow()->createImageNode(); -#else - return new QSGSimpleTextureNode(); -#endif } QSGRectangleNode *RenderWidgetHostViewQtDelegateWidget::createRectangleNode() { -#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)) return quickWindow()->createRectangleNode(); -#else - QSGRenderContext *renderContext = QQuickWindowPrivate::get(quickWindow())->context; - return renderContext->sceneGraphContext()->createRectangleNode(); -#endif } void RenderWidgetHostViewQtDelegateWidget::update() diff --git a/src/webenginewidgets/ui/messagebubblewidget.cpp b/src/webenginewidgets/ui/messagebubblewidget.cpp index 4a53a421f..70dada0c4 100644 --- a/src/webenginewidgets/ui/messagebubblewidget.cpp +++ b/src/webenginewidgets/ui/messagebubblewidget.cpp @@ -41,6 +41,7 @@ #include "api/qwebengineview.h" +#include <qglobal.h> #include <QBitmap> #include <QHBoxLayout> #include <QIcon> diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp index 89ebbac62..daf4d811e 100644 --- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp @@ -106,6 +106,7 @@ void tst_QWebEngineUrlRequestInterceptor::interceptRequest() { QWebEngineView view; TestRequestInterceptor interceptor(/* intercept */ true); + view.page()->settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool))); view.page()->profile()->setRequestInterceptor(&interceptor); @@ -193,21 +194,19 @@ void tst_QWebEngineUrlRequestInterceptor::requestedUrl() page.setUrl(QUrl("qrc:///resources/__placeholder__")); QVERIFY(spy.wait()); - QCOMPARE(spy.count(), 1); + QTRY_COMPARE(spy.count(), 1); QCOMPARE(interceptor.observedUrls.at(0), QUrl("qrc:///resources/content.html")); QCOMPARE(page.requestedUrl(), QUrl("qrc:///resources/__placeholder__")); QCOMPARE(page.url(), QUrl("qrc:///resources/content.html")); page.setUrl(QUrl("qrc:/non-existent.html")); - QVERIFY(spy.wait()); - QCOMPARE(spy.count(), 2); + QTRY_COMPARE(spy.count(), 2); QCOMPARE(interceptor.observedUrls.at(2), QUrl("qrc:/non-existent.html")); QCOMPARE(page.requestedUrl(), QUrl("qrc:///resources/__placeholder__")); QCOMPARE(page.url(), QUrl("qrc:///resources/content.html")); page.setUrl(QUrl("http://abcdef.abcdef")); - QVERIFY(spy.wait()); - QCOMPARE(spy.count(), 3); + QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 3, 12000); QCOMPARE(interceptor.observedUrls.at(3), QUrl("http://abcdef.abcdef/")); QCOMPARE(page.requestedUrl(), QUrl("qrc:///resources/__placeholder__")); QCOMPARE(page.url(), QUrl("qrc:///resources/content.html")); diff --git a/tests/auto/quick/qmltests/BLACKLIST b/tests/auto/quick/qmltests/BLACKLIST index 19d75dfb7..010b014d7 100644 --- a/tests/auto/quick/qmltests/BLACKLIST +++ b/tests/auto/quick/qmltests/BLACKLIST @@ -19,3 +19,6 @@ linux [WebEngineViewSingleFileUpload::test_acceptSingleFileSelection] * + +[WebEngineViewLoadProgress::test_loadProgress] +osx diff --git a/tests/auto/quick/qmltests/data/tst_favicon.qml b/tests/auto/quick/qmltests/data/tst_favicon.qml index f8ad998ef..ea474e0dc 100644 --- a/tests/auto/quick/qmltests/data/tst_favicon.qml +++ b/tests/auto/quick/qmltests/data/tst_favicon.qml @@ -152,6 +152,7 @@ TestWebEngineView { var url = Qt.resolvedUrl("invalid://url") webEngineView.url = url + verify(webEngineView.waitForLoadFailed()) verify(webEngineView.testSupport.waitForErrorPageLoadSucceeded()) compare(iconChangedSpy.count, 0) diff --git a/tests/auto/quick/qmltests/data/tst_findText.qml b/tests/auto/quick/qmltests/data/tst_findText.qml index f8730ca7b..dfcfd586f 100644 --- a/tests/auto/quick/qmltests/data/tst_findText.qml +++ b/tests/auto/quick/qmltests/data/tst_findText.qml @@ -57,7 +57,7 @@ TestWebEngineView { runJavaScript("document.body.innerHTML", function(result) { bodyInnerHTML = result; }); - tryVerify(function() { return bodyInnerHTML != undefined; }); + tryVerify(function() { return bodyInnerHTML != undefined; }, 20000); return bodyInnerHTML; } @@ -66,7 +66,7 @@ TestWebEngineView { runJavaScript("document.getElementById('list').getElementsByTagName('li')[" + index + "].innerText;", function(result) { listItemText = result; }); - tryVerify(function() { return listItemText != undefined; }); + tryVerify(function() { return listItemText != undefined; }, 20000); return listItemText; } @@ -82,9 +82,9 @@ TestWebEngineView { var itemIndex; runJavaScript(script, function(result) { itemIndex = result; }); - tryVerify(function() { return itemIndex != undefined; }); + tryVerify(function() { return itemIndex != undefined; }, 20000); // Make sure the DOM is up-to-date. - tryVerify(function() { return getListItemText(itemIndex).length == text.length; }); + tryVerify(function() { return getListItemText(itemIndex).length == text.length; }, 20000); } function test_findText() { @@ -176,7 +176,7 @@ TestWebEngineView { verify(findFailed) runJavaScript("document.body.innerHTML = 'blahellobla'"); - tryVerify(function() { return getBodyInnerHTML() == "blahellobla"; }); + tryVerify(function() { return getBodyInnerHTML() == "blahellobla"; }, 20000); webEngineView.clear() webEngineView.findText("hello", findFlags, webEngineView.findTextCallback) @@ -213,7 +213,7 @@ TestWebEngineView { // The callback is not supposed to be called, see QTBUG-61506. // Check whether the callback was called (-1 = no, other values = yes). - tryVerify(function() { return webEngineView.matchCount == -1; }); + tryVerify(function() { return webEngineView.matchCount == -1; }, 20000); } } } diff --git a/tests/auto/quick/qmltests/data/tst_getUserMedia.qml b/tests/auto/quick/qmltests/data/tst_getUserMedia.qml new file mode 100644 index 000000000..b497542e3 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_getUserMedia.qml @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtTest 1.0 +import QtWebEngine 1.6 + +TestWebEngineView { + id: webEngineView + + settings.screenCaptureEnabled: true + + TestCase { + name: "GetUserMedia" + + function init_data() { + return [ + { + tag: "device audio", + constraints: { audio: true }, + feature: WebEngineView.MediaAudioCapture, + }, + { + tag: "device video", + constraints: { video: true }, + feature: WebEngineView.MediaVideoCapture, + }, + { + tag: "device audio+video", + constraints: { audio: true, video: true }, + feature: WebEngineView.MediaAudioVideoCapture, + }, + { + tag: "desktop video", + constraints: { + video: { + mandatory: { + chromeMediaSource: "desktop" + } + } + }, + feature: WebEngineView.DesktopVideoCapture, + }, + { + tag: "desktop audio+video", + constraints: { + audio: { + mandatory: { + chromeMediaSource: "desktop" + } + }, + video: { + mandatory: { + chromeMediaSource: "desktop" + } + } + }, + feature: WebEngineView.DesktopAudioVideoCapture, + } + ] + } + + function test_getUserMedia(row) { + loadSync(Qt.resolvedUrl("test1.html")) + + // 1. Rejecting request on QML side should reject promise on JS side. + jsGetUserMedia(row.constraints) + tryVerify(function(){ return gotFeatureRequest(row.feature) }) + rejectPendingRequest() + tryVerify(function(){ return !jsPromiseFulfilled() && jsPromiseRejected() }) + + // 2. Accepting request on QML side should either fulfill or reject the + // Promise on JS side. Due to the potential lack of physical media devices + // deeper in the content layer we cannot guarantee that the promise will + // always be fulfilled, however in this case an error should be returned to + // JS instead of leaving the Promise in limbo. + jsGetUserMedia(row.constraints) + tryVerify(function(){ return gotFeatureRequest(row.feature) }) + acceptPendingRequest() + tryVerify(function(){ return jsPromiseFulfilled() || jsPromiseRejected() }); + + // 3. Media feature permissions are not remembered. + jsGetUserMedia(row.constraints); + tryVerify(function(){ return gotFeatureRequest(row.feature) }) + acceptPendingRequest() + tryVerify(function(){ return jsPromiseFulfilled() || jsPromiseRejected() }); + } + } + + //// + // synchronous loading + + signal loadFinished + + SignalSpy { + id: spyOnLoadFinished + target: webEngineView + signalName: "loadFinished" + } + + onLoadingChanged: { + if (loadRequest.status == WebEngineLoadRequest.LoadSucceededStatus) { + loadFinished() + } + } + + function loadSync(url) { + webEngineView.url = url + spyOnLoadFinished.wait() + } + + //// + // synchronous permission requests + + property variant requestedFeature + property variant requestedSecurityOrigin + + onFeaturePermissionRequested: { + requestedFeature = feature + requestedSecurityOrigin = securityOrigin + } + + function gotFeatureRequest(expectedFeature) { + return requestedFeature == expectedFeature + } + + function acceptPendingRequest() { + webEngineView.grantFeaturePermission(requestedSecurityOrigin, requestedFeature, true) + requestedFeature = undefined + requestedSecurityOrigin = undefined + } + + function rejectPendingRequest() { + webEngineView.grantFeaturePermission(requestedSecurityOrigin, requestedFeature, false) + requestedFeature = undefined + requestedSecurityOrigin = undefined + } + + //// + // synchronous JavaScript evaluation + + signal runJavaScriptFinished(variant result) + + SignalSpy { + id: spyOnRunJavaScriptFinished + target: webEngineView + signalName: "runJavaScriptFinished" + } + + function runJavaScriptSync(code) { + spyOnRunJavaScriptFinished.clear() + runJavaScript(code, runJavaScriptFinished) + spyOnRunJavaScriptFinished.wait() + return spyOnRunJavaScriptFinished.signalArguments[0][0] + } + + //// + // JavaScript snippets + + function jsGetUserMedia(constraints) { + runJavaScript( + "var promiseFulfilled = false;" + + "var promiseRejected = false;" + + "navigator.mediaDevices.getUserMedia(" + JSON.stringify(constraints) + ")" + + ".then(stream => { promiseFulfilled = true})" + + ".catch(err => { promiseRejected = true})") + } + + function jsPromiseFulfilled() { + return runJavaScriptSync("promiseFulfilled") + } + + function jsPromiseRejected() { + return runJavaScriptSync("promiseRejected") + } +} diff --git a/tests/auto/quick/qmltests/data/tst_inputMethod.qml b/tests/auto/quick/qmltests/data/tst_inputMethod.qml new file mode 100644 index 000000000..c09a8bdd9 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_inputMethod.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtTest 1.0 +import QtWebEngine 1.4 +import QtWebEngine.testsupport 1.0 + +TestWebEngineView { + id: webEngineView + width: 200 + height: 400 + + testSupport: WebEngineTestSupport { } + + TestCase { + name: "WebEngineViewInputMethod" + when: windowShown + + function init() { + testSupport.testInputContext.create(); + } + + function cleanup() { + testSupport.testInputContext.release(); + } + + function test_softwareInputPanel() { + verify(!Qt.inputMethod.visible); + webEngineView.loadHtml( + "<html><body>" + + " <form><input id='textInput' type='text' /></form>" + + "</body></html"); + verify(webEngineView.waitForLoadSucceeded()); + + verify(!getActiveElementId()); + verify(!Qt.inputMethod.visible); + + // Show input panel + webEngineView.runJavaScript("document.getElementById('textInput').focus()"); + webEngineView.verifyElementHasFocus("textInput"); + tryVerify(function() { return Qt.inputMethod.visible; }); + + // Hide input panel + webEngineView.runJavaScript("document.getElementById('textInput').blur()"); + verify(!getActiveElementId()); + tryVerify(function() { return !Qt.inputMethod.visible; }); + } + } +} + diff --git a/tests/auto/quick/qmltests/data/tst_loadProgress.qml b/tests/auto/quick/qmltests/data/tst_loadProgress.qml index bb85ed8e3..15058cb8f 100644 --- a/tests/auto/quick/qmltests/data/tst_loadProgress.qml +++ b/tests/auto/quick/qmltests/data/tst_loadProgress.qml @@ -71,7 +71,8 @@ TestWebEngineView { var loadProgressMin = 0 for (var i in loadProgressArray) { var loadProgress = loadProgressArray[i] - verify(loadProgressMin <= loadProgress) + if (loadProgressMin > loadProgress) + fail("Invalid sequence of progress-values: " + loadProgressArray) loadProgressMin = loadProgress } } diff --git a/tests/auto/quick/qmltests/data/tst_loadUrl.qml b/tests/auto/quick/qmltests/data/tst_loadUrl.qml index 2cb9f6b81..80d7a18b3 100644 --- a/tests/auto/quick/qmltests/data/tst_loadUrl.qml +++ b/tests/auto/quick/qmltests/data/tst_loadUrl.qml @@ -231,9 +231,11 @@ TestWebEngineView { loadRequest = loadRequestArray[2]; compare(loadRequest.status, WebEngineView.LoadStartedStatus); compare(loadRequest.activeUrl, aboutBlank); + compare(loadRequest.url, bogusSite) loadRequest = loadRequestArray[3]; compare(loadRequest.status, WebEngineView.LoadSucceededStatus); compare(loadRequest.activeUrl, bogusSite); + compare(loadRequest.url, bogusSite) webEngineView.clear(); } diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro index e7c5ededc..39b9d0151 100644 --- a/tests/auto/quick/qmltests/qmltests.pro +++ b/tests/auto/quick/qmltests/qmltests.pro @@ -52,6 +52,8 @@ OTHER_FILES += \ $$PWD/data/tst_focusOnNavigation.qml \ $$PWD/data/tst_formValidation.qml \ $$PWD/data/tst_geopermission.qml \ + $$PWD/data/tst_getUserMedia.qml \ + $$PWD/data/tst_inputMethod.qml \ $$PWD/data/tst_javaScriptDialogs.qml \ $$PWD/data/tst_linkHovered.qml \ $$PWD/data/tst_loadFail.qml \ diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index 2f9063ea5..8af5a2808 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -36,6 +36,7 @@ #include <QtTest/QtTest> #include <QtWebEngine/QQuickWebEngineProfile> #include <private/qquickwebengineview_p.h> +#include <private/qquickwebenginesettings_p.h> #include <functional> @@ -383,7 +384,8 @@ void tst_QQuickWebEngineView::titleUpdate() titleSpy.clear(); - // No titleChanged signal for failed load + // No titleChanged signal for failed load (with no error-page) + webEngineView()->settings()->setErrorPageEnabled(false); webEngineView()->setUrl(urlFromTestPath("html/file_that_does_not_exist.html")); QVERIFY(waitForLoadFailed(webEngineView())); QCOMPARE(titleSpy.size(), 0); @@ -435,50 +437,69 @@ void tst_QQuickWebEngineView::transparentWebEngineViews() void tst_QQuickWebEngineView::inputMethod() { -#if !defined(QQUICKWEBENGINEVIEW_ITEMACCEPTSINPUTMETHOD) - QSKIP("QQUICKWEBENGINEVIEW_ITEMACCEPTSINPUTMETHOD"); -#else + m_window->show(); + QTRY_VERIFY(qApp->focusObject()); + QQuickItem *input; + QQuickWebEngineView *view = webEngineView(); view->setUrl(urlFromTestPath("html/inputmethod.html")); QVERIFY(waitForLoadSucceeded(view)); + input = qobject_cast<QQuickItem *>(qApp->focusObject()); + QVERIFY(!input->flags().testFlag(QQuickItem::ItemAcceptsInputMethod)); QVERIFY(!view->flags().testFlag(QQuickItem::ItemAcceptsInputMethod)); + runJavaScript("document.getElementById('inputField').focus();"); + QTRY_COMPARE(activeElementId(view), QStringLiteral("inputField")); + input = qobject_cast<QQuickItem *>(qApp->focusObject()); + QTRY_VERIFY(input->flags().testFlag(QQuickItem::ItemAcceptsInputMethod)); QVERIFY(view->flags().testFlag(QQuickItem::ItemAcceptsInputMethod)); + runJavaScript("document.getElementById('inputField').blur();"); + QTRY_VERIFY(activeElementId(view).isEmpty()); + input = qobject_cast<QQuickItem *>(qApp->focusObject()); + QTRY_VERIFY(!input->flags().testFlag(QQuickItem::ItemAcceptsInputMethod)); QVERIFY(!view->flags().testFlag(QQuickItem::ItemAcceptsInputMethod)); -#endif } void tst_QQuickWebEngineView::inputMethodHints() { -#if !defined(QQUICKWEBENGINEVIEW_ITEMACCEPTSINPUTMETHOD) - QSKIP("QQUICKWEBENGINEVIEW_ITEMACCEPTSINPUTMETHOD"); -#else - QQuickWebEngineView *view = webEngineView(); + m_window->show(); + QTRY_VERIFY(qApp->focusObject()); + QQuickItem *input; + QQuickWebEngineView *view = webEngineView(); view->setUrl(urlFromTestPath("html/inputmethod.html")); QVERIFY(waitForLoadSucceeded(view)); + // Initialize input fields with values to check input method query is being updated. + runJavaScript("document.getElementById('emailInputField').value = 'a@b.com';"); + runJavaScript("document.getElementById('editableDiv').innerText = 'bla';"); + // Setting focus on an input element results in an element in its shadow tree becoming the focus node. // Input hints should not be set from this shadow tree node but from the input element itself. runJavaScript("document.getElementById('emailInputField').focus();"); + QTRY_COMPARE(activeElementId(view), QStringLiteral("emailInputField")); + input = qobject_cast<QQuickItem *>(qApp->focusObject()); + QTRY_COMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("a@b.com")); + QVERIFY(input->flags().testFlag(QQuickItem::ItemAcceptsInputMethod)); QVERIFY(view->flags().testFlag(QQuickItem::ItemAcceptsInputMethod)); QInputMethodQueryEvent query(Qt::ImHints); - QGuiApplication::sendEvent(view, &query); - Qt::InputMethodHints hints(query.value(Qt::ImHints).toUInt() & Qt::ImhExclusiveInputMask); - QCOMPARE(hints, Qt::ImhEmailCharactersOnly); + QGuiApplication::sendEvent(input, &query); + QTRY_COMPARE(Qt::InputMethodHints(query.value(Qt::ImHints).toUInt() & Qt::ImhExclusiveInputMask), Qt::ImhEmailCharactersOnly); // The focus of an editable DIV is given directly to it, so no shadow root element // is necessary. This tests the WebPage::editorState() method ability to get the // right element without breaking. runJavaScript("document.getElementById('editableDiv').focus();"); + QTRY_COMPARE(activeElementId(view), QStringLiteral("editableDiv")); + input = qobject_cast<QQuickItem *>(qApp->focusObject()); + QTRY_COMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("bla")); + QVERIFY(input->flags().testFlag(QQuickItem::ItemAcceptsInputMethod)); QVERIFY(view->flags().testFlag(QQuickItem::ItemAcceptsInputMethod)); query = QInputMethodQueryEvent(Qt::ImHints); - QGuiApplication::sendEvent(view, &query); - hints = Qt::InputMethodHints(query.value(Qt::ImHints).toUInt()); - QCOMPARE(hints, Qt::ImhNone); -#endif + QGuiApplication::sendEvent(input, &query); + QTRY_COMPARE(Qt::InputMethodHints(query.value(Qt::ImHints).toUInt()), Qt::ImhPreferLowercase | Qt::ImhMultiLine); } void tst_QQuickWebEngineView::setZoomFactor() diff --git a/tests/auto/quick/qquickwebengineviewgraphics/qquickwebengineviewgraphics.pro b/tests/auto/quick/qquickwebengineviewgraphics/qquickwebengineviewgraphics.pro index 9471def00..2a2155e44 100644 --- a/tests/auto/quick/qquickwebengineviewgraphics/qquickwebengineviewgraphics.pro +++ b/tests/auto/quick/qquickwebengineviewgraphics/qquickwebengineviewgraphics.pro @@ -1,4 +1,4 @@ include(../tests.pri) CONFIG -= testcase # remove, once this passes in the CI exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc -QT_PRIVATE += webengine-private +QT_PRIVATE += webengine-private gui-private diff --git a/tests/auto/quick/shared/util.h b/tests/auto/quick/shared/util.h index dce0afb8e..98f19bd49 100644 --- a/tests/auto/quick/shared/util.h +++ b/tests/auto/quick/shared/util.h @@ -142,4 +142,26 @@ inline QString bodyInnerText(QQuickWebEngineView *webEngineView) return arguments.at(1).toString(); } +inline QString activeElementId(QQuickWebEngineView *webEngineView) +{ + qRegisterMetaType<QQuickWebEngineView::JavaScriptConsoleMessageLevel>("JavaScriptConsoleMessageLevel"); + QSignalSpy consoleMessageSpy(webEngineView, &QQuickWebEngineView::javaScriptConsoleMessage); + + webEngineView->runJavaScript( + "if (document.activeElement == null)" + " console.log('');" + "else" + " console.log(document.activeElement.id);" + ); + + if (!consoleMessageSpy.wait()) + return QString(); + + QList<QVariant> arguments = consoleMessageSpy.takeFirst(); + if (static_cast<QQuickWebEngineView::JavaScriptConsoleMessageLevel>(arguments.at(0).toInt()) != QQuickWebEngineView::InfoMessageLevel) + return QString(); + + return arguments.at(1).toString(); +} + #endif /* UTIL_H */ diff --git a/tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp b/tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp index 3d2c04486..56890bbae 100644 --- a/tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp +++ b/tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp @@ -40,6 +40,8 @@ private Q_SLOTS: void hierarchy(); void text(); void value(); + void roles_data(); + void roles(); }; // This will be called before the first test function is executed. @@ -248,6 +250,173 @@ void tst_QWebEngineAccessibility::value() QCOMPARE(progressBarValueInterface->maximumValue().toInt(), 99); } +void tst_QWebEngineAccessibility::roles_data() +{ + QTest::addColumn<QString>("html"); + QTest::addColumn<bool>("isSection"); + QTest::addColumn<QAccessible::Role>("role"); + + QTest::newRow("AX_ROLE_ABBR") << QString("<abbr>a</abbr>") << false << QAccessible::StaticText; + QTest::newRow("AX_ROLE_ALERT") << QString("<div role='alert'>alert</div>") << true << QAccessible::AlertMessage; + QTest::newRow("AX_ROLE_ALERT_DIALOG") << QString("<div role='alertdialog'>alert</div>") << true << QAccessible::AlertMessage; + QTest::newRow("AX_ROLE_ANNOTATION") << QString("<rt>a</rt>") << false << QAccessible::StaticText; + QTest::newRow("AX_ROLE_APPLICATION") << QString("<div role='application'>landmark</div>") << true << QAccessible::Document; + QTest::newRow("AX_ROLE_ARTICLE") << QString("<article>a</article>") << true << QAccessible::Section; + QTest::newRow("AX_ROLE_AUDIO") << QString("<audio controls><source src='test.mp3' type='audio/mpeg'></audio>") << false << QAccessible::Sound; + QTest::newRow("AX_ROLE_BANNER") << QString("<header>a</header>") << true << QAccessible::Section; + QTest::newRow("AX_ROLE_BLOCKQUOTE") << QString("<blockquote>a</blockquote>") << true << QAccessible::Section; + //QTest::newRow("AX_ROLE_BUSY_INDICATOR"); // Deprecated + QTest::newRow("AX_ROLE_BUTTON") << QString("<button>a</button>") << false << QAccessible::Button; + //QTest::newRow("AX_ROLE_BUTTON_DROP_DOWN"); // Not a blink accessibility role + //QTest::newRow("AX_ROLE_CANVAS") << QString("<canvas width='10' height='10'></canvas>") << true << QAccessible::Canvas; // FIXME: The test case might be wrong (see AXLayoutObject.cpp) + QTest::newRow("AX_ROLE_CAPTION") << QString("<table><caption>a</caption></table>") << false << QAccessible::Heading; + //QTest::newRow("AX_ROLE_CELL") << QString("<td role='cell'>a</td>") << true << QAccessible::Cell; // FIXME: Aria role 'cell' should work for <td> + QTest::newRow("AX_ROLE_CHECK_BOX") << QString("<input type='checkbox'>a</input>") << false << QAccessible::CheckBox; + QTest::newRow("AX_ROLE_CLIENT") << QString("") << true << QAccessible::Client; + QTest::newRow("AX_ROLE_COLOR_WELL") << QString("<input type='color'>a</input>") << false << QAccessible::ColorChooser; + //QTest::newRow("AX_ROLE_COLUMN") << QString("<table><tr><td>a</td></tr>") << true << QAccessible::Column; // FIXME: The test case might be wrong (see AXTableColumn.h) + QTest::newRow("AX_ROLE_COLUMN_HEADER") << QString("<div role='columnheader'>a</div>") << true << QAccessible::ColumnHeader; + QTest::newRow("AX_ROLE_COMBO_BOX") << QString("<select><option>a</option></select>") << false << QAccessible::ComboBox; + QTest::newRow("AX_ROLE_COMPLEMENTARY") << QString("<aside>a</aside>") << true << QAccessible::ComplementaryContent; + QTest::newRow("AX_ROLE_CONTENT_INFO") << QString("<address>a</address>") << true << QAccessible::Section; + QTest::newRow("AX_ROLE_DATE") << QString("<input type='date'></input>") << false << QAccessible::Clock; + QTest::newRow("AX_ROLE_DATE_TIME") << QString("<input type='datetime-local'></input>") << false << QAccessible::Clock; + QTest::newRow("AX_ROLE_DEFINITION") << QString("<div role='definition'>landmark</div>") << true << QAccessible::Paragraph; + QTest::newRow("AX_ROLE_DESCRIPTION_LIST") << QString("<dl>a</dl>") << true << QAccessible::List; + QTest::newRow("AX_ROLE_DESCRIPTION_LIST_DETAIL") << QString("<dd>a</dd>") << true << QAccessible::Paragraph; + QTest::newRow("AX_ROLE_DESCRIPTION_LIST_TERM") << QString("<dt>a</dt>") << true << QAccessible::ListItem; + QTest::newRow("AX_ROLE_DETAILS") << QString("<details>a</details>") << true << QAccessible::Grouping; + //QTest::newRow("AX_ROLE_DESKTOP"); // Not a blink accessibility role + QTest::newRow("AX_ROLE_DIALOG") << QString("<div role='dialog'></div>") << true << QAccessible::Dialog; + //QTest::newRow("AX_ROLE_DIRECTORY") << QString("<div role='directory'></div>") << true << QAccessible::NoRole; // FIXME: Aria role 'directory' should work + QTest::newRow("AX_ROLE_DISCLOSURE_TRIANGLE") << QString("<details><summary>a</summary></details>") << false << QAccessible::NoRole; + QTest::newRow("AX_ROLE_DIV") << QString("<div>a</div>") << true << QAccessible::Section; + QTest::newRow("AX_ROLE_DOCUMENT") << QString("<div role='document'>a</div>") << true << QAccessible::Document; + QTest::newRow("AX_ROLE_EMBEDDED_OBJECT") << QString("<object width='10' height='10'></object>") << false << QAccessible::Grouping; + QTest::newRow("AX_ROLE_FEED") << QString("<div role='feed'>a</div>") << true << QAccessible::Section; + QTest::newRow("AX_ROLE_FIGCAPTION") << QString("<figcaption>a</figcaption>") << true << QAccessible::Heading; + QTest::newRow("AX_ROLE_FIGURE") << QString("<figure>a</figure>") << true << QAccessible::Section; + QTest::newRow("AX_ROLE_FOOTER") << QString("<footer>a</footer>") << true << QAccessible::Footer; + QTest::newRow("AX_ROLE_FORM") << QString("<form></form>") << true << QAccessible::Form; + QTest::newRow("AX_ROLE_GRID") << QString("<div role='grid'></div>") << true << QAccessible::Table; + QTest::newRow("AX_ROLE_GROUP") << QString("<fieldset></fieldset>") << true << QAccessible::Grouping; + QTest::newRow("AX_ROLE_HEADING") << QString("<h1>a</h1>") << true << QAccessible::Heading; + QTest::newRow("AX_ROLE_IFRAME") << QString("<iframe>a</iframe>") << true << QAccessible::Grouping; + QTest::newRow("AX_ROLE_IFRAME_PRESENTATIONAL") << QString("<iframe role='presentation'>a</iframe>") << false << QAccessible::NoRole; + //QTest::newRow("AX_ROLE_IGNORED") << QString("<tag>a</tag>") << true << QAccessible::NoRole; // FIXME: The HTML element should not be exposed as an element (see AXNodeObject.cpp) + QTest::newRow("AX_ROLE_IMAGE") << QString("<img>") << false << QAccessible::Graphic; + //QTest::newRow("AX_ROLE_IMAGE_MAP") << QString("<map>a</map>") << true << QAccessible::Graphic; // FIXME: The test case might be wrong (see AXLayoutObject.cpp) + //QTest::newRow("AX_ROLE_IMAGE_MAP_LINK") << QString("<map>a</map>") << true << QAccessible::Graphic; // FIXME: The test case might be wrong (see AXLayoutObject.cpp) + QTest::newRow("AX_ROLE_INLINE_TEXT_BOX") << QString("<textarea rows='4' cols='50'></textarea>") << false << QAccessible::EditableText; + QTest::newRow("AX_ROLE_INPUT_TIME") << QString("<input type='time'></input>") << false << QAccessible::SpinBox; + QTest::newRow("AX_ROLE_LABEL_TEXT") << QString("<label>a</label>") << false << QAccessible::StaticText; + QTest::newRow("AX_ROLE_LEGEND") << QString("<legend>a</legend>") << true << QAccessible::StaticText; + QTest::newRow("AX_ROLE_LINE_BREAK") << QString("<br>") << false << QAccessible::Separator; + QTest::newRow("AX_ROLE_LINK") << QString("<a href=''>link</a>") << false << QAccessible::Link; + QTest::newRow("AX_ROLE_LIST") << QString("<ul></ul>") << true << QAccessible::List; + QTest::newRow("AX_ROLE_LIST_BOX") << QString("<select role='listbox'></select>") << false << QAccessible::ComboBox; + QTest::newRow("AX_ROLE_LIST_BOX_OPTION") << QString("<option>a</option>") << true << QAccessible::ListItem; + QTest::newRow("AX_ROLE_LIST_ITEM") << QString("<li>a</li>") << true << QAccessible::ListItem; + QTest::newRow("AX_ROLE_LIST_MARKER") << QString("<li><ul></ul></li>") << false << QAccessible::StaticText; + //QTest::newRow("AX_ROLE_LOCATION_BAR"); // Not a blink accessibility role + QTest::newRow("AX_ROLE_LOG") << QString("<div role='log'>a</div>") << true << QAccessible::Section; + QTest::newRow("AX_ROLE_MAIN") << QString("<main>a</main>") << true << QAccessible::Grouping; + QTest::newRow("AX_ROLE_MARK") << QString("<mark>a</mark>") << false << QAccessible::StaticText; + QTest::newRow("AX_ROLE_MARQUEE") << QString("<div role='marquee'>a</div>") << true << QAccessible::Section; + QTest::newRow("AX_ROLE_MATH") << QString("<math>a</math>") << false << QAccessible::Equation; + QTest::newRow("AX_ROLE_MENU") << QString("<div role='menu'>a</div>") << true << QAccessible::PopupMenu; + QTest::newRow("AX_ROLE_MENU_BAR") << QString("<div role='menubar'>a</div>") << true << QAccessible::MenuBar; + QTest::newRow("AX_ROLE_MENU_ITEM") << QString("<menu role='menu'><input type='button' /></menu>") << false << QAccessible::MenuItem; + QTest::newRow("AX_ROLE_MENU_ITEM_CHECK_BOX") << QString("<menu role='menu'><input type='checkbox'></input></menu>") << false << QAccessible::CheckBox; + QTest::newRow("AX_ROLE_MENU_ITEM_RADIO") << QString("<menu role='menu'><input type='radio'></input></menu>") << false << QAccessible::RadioButton; + QTest::newRow("AX_ROLE_MENU_BUTTON") << QString("<menu role='group'><div role='menuitem'>a</div></menu>") << false << QAccessible::MenuItem; + //QTest::newRow("AX_ROLE_MENU_LIST_OPTION") << QString("<select role='menu'><option>a</option></select>") << false << QAccessible::MenuItem; // FIXME: <select> should be a menu list (see AXMenuListOption.cpp) + //QTest::newRow("AX_ROLE_MENU_LIST_POPUP") << QString("<menu type='context'>a</menu>") << true << QAccessible::PopupMenu; // FIXME: <menu> is not fully supported by Chromium (see AXMenuListPopup.h) + QTest::newRow("AX_ROLE_METER") << QString("<meter>a</meter>") << false << QAccessible::Chart; + QTest::newRow("AX_ROLE_NAVIGATION") << QString("<nav>a</nav>") << true << QAccessible::Section; + QTest::newRow("AX_ROLE_NOTE") << QString("<div role='note'>a</div>") << true << QAccessible::Note; + //QTest::newRow("AX_ROLE_OUTLINE"); // No mapping to ARIA role + //QTest::newRow("AX_ROLE_PANE"); // Not a blink accessibility role + QTest::newRow("AX_ROLE_PARAGRAH") << QString("<p>a</p>") << true << QAccessible::Paragraph; + QTest::newRow("AX_ROLE_POP_UP_BUTTON") << QString("<select multiple></select>") << false << QAccessible::ComboBox; + QTest::newRow("AX_ROLE_PRE") << QString("<pre>a</pre>") << true << QAccessible::Section; + //QTest::newRow("AX_ROLE_PRESENTATIONAL") << QString("<div role='presentation'>a</div>") << true << QAccessible::NoRole; // FIXME: Aria role 'presentation' should work + QTest::newRow("AX_ROLE_PROGRESS_INDICATOR") << QString("<div role='progressbar' aria-valuenow='77' aria-valuemin='22' aria-valuemax='99'></div>") << true << QAccessible::ProgressBar; + QTest::newRow("AX_ROLE_RADIO_BUTTON") << QString("<input type='radio'></input>") << false << QAccessible::RadioButton; + QTest::newRow("AX_ROLE_RADIO_GROUP") << QString("<fieldset role='radiogroup'></fieldset>") << true << QAccessible::Grouping; + QTest::newRow("AX_ROLE_REGION") << QString("<section>a</section>") << true << QAccessible::Section; + //QTest::newRow("AX_ROLE_ROW") << QString("<tr role='row'>a</tr>") << true << QAccessible::Row; // FIXME: Aria role 'row' should work for <tr> + //QTest::newRow("AX_ROLE_ROW_HEADER") << QString("<td role='rowheader'>a</td>") << true << QAccessible::RowHeader; // FIXME: Aria role 'rowheader' should work for <td> + QTest::newRow("AX_ROLE_RUBY") << QString("<ruby>a</ruby>") << false << QAccessible::StaticText; + //QTest::newRow("AX_ROLE_RULER"); // No mapping to ARIA role + //QTest::newRow("AX_ROLE_SCROLL_AREA"); // No mapping to ARIA role + QTest::newRow("AX_ROLE_SCROLL_BAR") << QString("<div role='scrollbar'>a</a>") << true << QAccessible::ScrollBar; + //QTest::newRow("AX_ROLE_SEAMLESS_WEB_AREA"); // No mapping to ARIA role + QTest::newRow("AX_ROLE_SEARCH") << QString("<div role='search'>landmark</div>") << true << QAccessible::Section; + QTest::newRow("AX_ROLE_SEARCH_BOX") << QString("<input type='search'></input>") << false << QAccessible::EditableText; + QTest::newRow("AX_ROLE_SLIDER") << QString("<input type='range'></input>") << false << QAccessible::Slider; + //QTest::newRow("AX_ROLE_SLIDER_THUMB"); // No mapping to ARIA role + QTest::newRow("AX_ROLE_SPIN_BUTTON") << QString("<input type='number'></input>") << false << QAccessible::SpinBox; + //QTest::newRow("AX_ROLE_SPIN_BUTTON_PART"); // No mapping to ARIA role + QTest::newRow("AX_ROLE_SPLITER") << QString("<hr>") << true << QAccessible::Splitter; + QTest::newRow("AX_ROLE_STATIC_TEXT") << QString("a") << false << QAccessible::StaticText; + QTest::newRow("AX_ROLE_STATUS") << QString("<output>a</output>") << false << QAccessible::Indicator; + QTest::newRow("AX_ROLE_SVG_ROOT") << QString("<svg width='10' height='10'></svg>") << false << QAccessible::Graphic; + QTest::newRow("AX_ROLE_SWITCH") << QString("<button aria-checked='false'>a</button>") << false << QAccessible::Button; + //QTest::newRow("AX_ROLE_TABLE") << QString("<table>a</table>") << true << QAccessible::Table; // FIXME: The test case might be wrong (see AXTable.cpp) + //QTest::newRow("AX_ROLE_TABLE_HEADER_CONTAINER"); // No mapping to ARIA role + QTest::newRow("AX_ROLE_TAB") << QString("<div role='tab'>a</div>") << true << QAccessible::PageTab; + //QTest::newRow("AX_ROLE_TAB_GROUP"); // No mapping to ARIA role + QTest::newRow("AX_ROLE_TAB_LIST") << QString("<div role='tablist'>a</div>") << true << QAccessible::PageTabList; + QTest::newRow("AX_ROLE_TAB_PANEL") << QString("<div role='tab'>a</div>") << true << QAccessible::PageTab; + QTest::newRow("AX_ROLE_TERM") << QString("<div role='term'>a</div>") << true << QAccessible::StaticText; + QTest::newRow("AX_ROLE_TEXT_FIELD") << QString("<input type='text'></input>") << false << QAccessible::EditableText; + QTest::newRow("AX_ROLE_TIME") << QString("<time>a</time>") << false << QAccessible::Clock; + QTest::newRow("AX_ROLE_TIMER") << QString("<div role='timer'>a</div>") << true << QAccessible::Clock; + //QTest::newRow("AX_ROLE_TITLE_BAR"); // Not a blink accessibility role + QTest::newRow("AX_ROLE_TOGGLE_BUTTON") << QString("<button aria-pressed='false'>a</button>") << false << QAccessible::Button; + QTest::newRow("AX_ROLE_TOOLBAR") << QString("<div role='toolbar'>a</div>") << true << QAccessible::ToolBar; + QTest::newRow("AX_ROLE_TOOLTIP") << QString("<div role='tooltip'>a</div>") << true << QAccessible::ToolTip; + QTest::newRow("AX_ROLE_TREE") << QString("<div role='tree'>a</div>") << true << QAccessible::Tree; + //QTest::newRow("AX_ROLE_TREE_GRID") << QString("<div role='treegrid'>a</div>") << true << QAccessible::Tree; // FIXME: Aria role 'treegrid' should work + QTest::newRow("AX_ROLE_TREE_ITEM") << QString("<div role='treeitem'>a</div>") << true << QAccessible::TreeItem; + QTest::newRow("AX_ROLE_VIDEO") << QString("<video><source src='test.mp4' type='video/mp4'></video>") << false << QAccessible::Animation; + //QTest::newRow("AX_ROLE_WINDOW"); // No mapping to ARIA role +} + +void tst_QWebEngineAccessibility::roles() +{ + QFETCH(QString, html); + QFETCH(bool, isSection); + QFETCH(QAccessible::Role, role); + + QWebEngineView webView; + webView.setHtml("<html><body>" + html + "</body></html>"); + QSignalSpy spyFinished(&webView, &QWebEngineView::loadFinished); + QVERIFY(spyFinished.wait()); + + QAccessibleInterface *view = QAccessible::queryAccessibleInterface(&webView); + + // Corner case for Client role + if (html.isEmpty()) { + QCOMPARE(view->role(), QAccessible::Client); + return; + } + + QTRY_COMPARE(view->child(0)->childCount(), 1); + QAccessibleInterface *document = view->child(0); + QAccessibleInterface *section = document->child(0); + + if (isSection) { + QCOMPARE(section->role(), role); + return; + } + + QVERIFY(section->childCount() > 0); + QAccessibleInterface *element = section->child(0); + QCOMPARE(element->role(), role); +} + static QByteArrayList params = QByteArrayList() << "--force-renderer-accessibility"; diff --git a/tests/auto/widgets/qwebenginepage/BLACKLIST b/tests/auto/widgets/qwebenginepage/BLACKLIST index b376cd375..7470a1523 100644 --- a/tests/auto/widgets/qwebenginepage/BLACKLIST +++ b/tests/auto/widgets/qwebenginepage/BLACKLIST @@ -7,8 +7,6 @@ [macCopyUnicodeToClipboard] osx -[getUserMediaRequest] -* [mouseMovementProperties] osx-10.11 osx-10.12 diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index bef77d3f1..4cb8e23e5 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -125,7 +125,10 @@ private Q_SLOTS: void userAgentNewlineStripping(); void undoActionHaveCustomText(); void renderWidgetHostViewNotShowTopLevel(); + void getUserMediaRequest_data(); void getUserMediaRequest(); + void getUserMediaRequestDesktopAudio(); + void getUserMediaRequestSettingDisabled(); void savePage(); void crashTests_LazyInitializationOfMainFrame(); @@ -181,7 +184,6 @@ private Q_SLOTS: void baseUrl_data(); void baseUrl(); void scrollPosition(); - void scrollToAnchor(); void scrollbarsOff(); void evaluateWillCauseRepaint(); void setContent_data(); @@ -2605,6 +2607,33 @@ public: : m_gotRequest(false) { connect(this, &QWebEnginePage::featurePermissionRequested, this, &GetUserMediaTestPage::onFeaturePermissionRequested); + + // We need to load content from a resource in order for the securityOrigin to be valid. + QSignalSpy loadSpy(this, SIGNAL(loadFinished(bool))); + load(QUrl("qrc:///resources/content.html")); + QTRY_COMPARE(loadSpy.count(), 1); + } + + void jsGetUserMedia(const QString & constraints) + { + runJavaScript( + QStringLiteral( + "var promiseFulfilled = false;" + "var promiseRejected = false;" + "navigator.mediaDevices.getUserMedia(%1)" + ".then(stream => { promiseFulfilled = true})" + ".catch(err => { promiseRejected = true})") + .arg(constraints)); + } + + bool jsPromiseFulfilled() + { + return evaluateJavaScriptSync(this, QStringLiteral("promiseFulfilled")).toBool(); + } + + bool jsPromiseRejected() + { + return evaluateJavaScriptSync(this, QStringLiteral("promiseRejected")).toBool(); } void rejectPendingRequest() @@ -2623,6 +2652,11 @@ public: return m_gotRequest && m_requestedFeature == feature; } + bool gotFeatureRequest() const + { + return m_gotRequest; + } + private Q_SLOTS: void onFeaturePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature feature) { @@ -2638,28 +2672,83 @@ private: }; +void tst_QWebEnginePage::getUserMediaRequest_data() +{ + QTest::addColumn<QString>("constraints"); + QTest::addColumn<QWebEnginePage::Feature>("feature"); + + QTest::addRow("device audio") + << "{audio: true}" << QWebEnginePage::MediaAudioCapture; + QTest::addRow("device video") + << "{video: true}" << QWebEnginePage::MediaVideoCapture; + QTest::addRow("device audio+video") + << "{audio: true, video: true}" << QWebEnginePage::MediaAudioVideoCapture; + QTest::addRow("desktop video") + << "{video: { mandatory: { chromeMediaSource: 'desktop' }}}" + << QWebEnginePage::DesktopVideoCapture; + QTest::addRow("desktop audio+video") + << "{audio: { mandatory: { chromeMediaSource: 'desktop' }}, video: { mandatory: { chromeMediaSource: 'desktop' }}}" + << QWebEnginePage::DesktopAudioVideoCapture; +} void tst_QWebEnginePage::getUserMediaRequest() { - GetUserMediaTestPage page; + QFETCH(QString, constraints); + QFETCH(QWebEnginePage::Feature, feature); - // We need to load content from a resource in order for the securityOrigin to be valid. - QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); - page.load(QUrl("qrc:///resources/content.html")); - QTRY_COMPARE(loadSpy.count(), 1); + GetUserMediaTestPage page; + page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true); + + // 1. Rejecting request on C++ side should reject promise on JS side. + page.jsGetUserMedia(constraints); + QTRY_VERIFY(page.gotFeatureRequest(feature)); + page.rejectPendingRequest(); + QTRY_VERIFY(!page.jsPromiseFulfilled() && page.jsPromiseRejected()); + + // 2. Accepting request on C++ side should either fulfill or reject the + // Promise on JS side. Due to the potential lack of physical media devices + // deeper in the content layer we cannot guarantee that the promise will + // always be fulfilled, however in this case an error should be returned to + // JS instead of leaving the Promise in limbo. + page.jsGetUserMedia(constraints); + QTRY_VERIFY(page.gotFeatureRequest(feature)); + page.acceptPendingRequest(); + QTRY_VERIFY(page.jsPromiseFulfilled() || page.jsPromiseRejected()); - QVERIFY(evaluateJavaScriptSync(&page, QStringLiteral("!!navigator.webkitGetUserMedia")).toBool()); - evaluateJavaScriptSync(&page, QStringLiteral("navigator.webkitGetUserMedia({audio: true}, function() {}, function(){})")); - QTRY_VERIFY(page.gotFeatureRequest(QWebEnginePage::MediaAudioCapture)); - // Might end up failing due to the lack of physical media devices deeper in the content layer, so the JS callback is not guaranteed to be called, - // but at least we go through that code path, potentially uncovering failing assertions. + // 3. Media feature permissions are not remembered. + page.jsGetUserMedia(constraints); + QTRY_VERIFY(page.gotFeatureRequest(feature)); page.acceptPendingRequest(); + QTRY_VERIFY(page.jsPromiseFulfilled() || page.jsPromiseRejected()); +} + +void tst_QWebEnginePage::getUserMediaRequestDesktopAudio() +{ + GetUserMediaTestPage page; + page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true); + + // Audio-only desktop capture is not supported. JS Promise should be + // rejected immediately. + + page.jsGetUserMedia( + QStringLiteral("{audio: { mandatory: { chromeMediaSource: 'desktop' }}}")); + QTRY_VERIFY(!page.jsPromiseFulfilled() && page.jsPromiseRejected()); + + page.jsGetUserMedia( + QStringLiteral("{audio: { mandatory: { chromeMediaSource: 'desktop' }}, video: true}")); + QTRY_VERIFY(!page.jsPromiseFulfilled() && page.jsPromiseRejected()); +} - page.runJavaScript(QStringLiteral("errorCallbackCalled = false;")); - evaluateJavaScriptSync(&page, QStringLiteral("navigator.webkitGetUserMedia({audio: true, video: true}, function() {}, function(){errorCallbackCalled = true;})")); - QTRY_VERIFY(page.gotFeatureRequest(QWebEnginePage::MediaAudioVideoCapture)); - page.rejectPendingRequest(); // Should always end up calling the error callback in JS. - QTRY_VERIFY(evaluateJavaScriptSync(&page, QStringLiteral("errorCallbackCalled;")).toBool()); +void tst_QWebEnginePage::getUserMediaRequestSettingDisabled() +{ + GetUserMediaTestPage page; + page.settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, false); + + // With the setting disabled, the JS Promise should be rejected without + // asking for permission first. + + page.jsGetUserMedia(QStringLiteral("{video: { mandatory: { chromeMediaSource: 'desktop' }}}")); + QTRY_VERIFY(!page.jsPromiseFulfilled() && page.jsPromiseRejected()); } void tst_QWebEnginePage::savePage() @@ -3424,77 +3513,21 @@ void tst_QWebEnginePage::scrollPosition() QCOMPARE(y, 29); } -void tst_QWebEnginePage::scrollToAnchor() +void tst_QWebEnginePage::scrollbarsOff() { -#if !defined(QWEBENGINEELEMENT) - QSKIP("QWEBENGINEELEMENT"); -#else - QWebEnginePage page; - page.setViewportSize(QSize(480, 800)); + QWebEngineView view; + view.page()->settings()->setAttribute(QWebEngineSettings::HideScrollbars, true); - QString html("<html><body><p style=\"margin-bottom: 1500px;\">Hello.</p>" - "<p><a id=\"foo\">This</a> is an anchor</p>" - "<p style=\"margin-bottom: 1500px;\"><a id=\"bar\">This</a> is another anchor</p>" + QString html("<html><body>" + " <div style='margin-top:1000px ; margin-left:1000px'>" + " <a id='offscreen' href='a'>End</a>" + " </div>" "</body></html>"); - page.setHtml(html); - page.setScrollPosition(QPoint(0, 0)); - QCOMPARE(page.scrollPosition().x(), 0); - QCOMPARE(page.scrollPosition().y(), 0); - - QWebEngineElement fooAnchor = page.findFirstElement("a[id=foo]"); - - page.scrollToAnchor("foo"); - QCOMPARE(page.scrollPosition().y(), fooAnchor.geometry().top()); - - page.scrollToAnchor("bar"); - page.scrollToAnchor("foo"); - QCOMPARE(page.scrollPosition().y(), fooAnchor.geometry().top()); - page.scrollToAnchor("top"); - QCOMPARE(page.scrollPosition().y(), 0); - - page.scrollToAnchor("bar"); - page.scrollToAnchor("notexist"); - QVERIFY(page.scrollPosition().y() != 0); -#endif -} - - -void tst_QWebEnginePage::scrollbarsOff() -{ -#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT) - QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT"); -#else - QWebEngineView view; - QWebEngineFrame* mainFrame = view.page(); - - mainFrame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); - mainFrame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); - - QString html("<script>" \ - " function checkScrollbar() {" \ - " if (innerWidth === document.documentElement.offsetWidth)" \ - " document.getElementById('span1').innerText = 'SUCCESS';" \ - " else" \ - " document.getElementById('span1').innerText = 'FAIL';" \ - " }" \ - "</script>" \ - "<body>" \ - " <div style='margin-top:1000px ; margin-left:1000px'>" \ - " <a id='offscreen' href='a'>End</a>" \ - " </div>" \ - "<span id='span1'></span>" \ - "</body>"); - - - QSignalSpy loadSpy(&view, &QWebEngineView::loadFinished); + QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool))); view.setHtml(html); - QVERIFY(loadSpy.wait(200); - QCOMPARE(loadSpy.count(), 1); - - mainFrame->evaluateJavaScript("checkScrollbar();"); - QCOMPARE(mainFrame->documentElement().findAll("span").at(0).toPlainText(), QString("SUCCESS")); -#endif + QTRY_COMPARE(loadSpy.count(), 1); + QVERIFY(evaluateJavaScriptSync(view.page(), "innerWidth == document.documentElement.offsetWidth").toBool()); } void tst_QWebEnginePage::horizontalScrollAfterBack() @@ -4090,10 +4123,10 @@ void tst_QWebEnginePage::toPlainTextLoadFinishedRace() QVERIFY(s.contains("foobarbaz") == !enableErrorPage); page->load(QUrl("data:text/plain,lalala")); - QTRY_VERIFY(spy.count() == 3); - QCOMPARE(toPlainTextSync(page.data()), QString("lalala")); + QTRY_COMPARE(spy.count(), 3); + QTRY_COMPARE(toPlainTextSync(page.data()), QString("lalala")); page.reset(); - QVERIFY(spy.count() == 3); + QCOMPARE(spy.count(), 3); } void tst_QWebEnginePage::setZoomFactor() diff --git a/tests/auto/widgets/qwebenginespellcheck/dict/de-DE.dic b/tests/auto/widgets/qwebenginespellcheck/dict/de-DE.dic index d10ae2600..a57ab15b4 100644 --- a/tests/auto/widgets/qwebenginespellcheck/dict/de-DE.dic +++ b/tests/auto/widgets/qwebenginespellcheck/dict/de-DE.dic @@ -8,6 +8,7 @@ liebe/Q lieben/Q liebst/Q liebt/Q +löwe/Q qt/Q sie/Q Sie/Q diff --git a/tests/auto/widgets/qwebenginespellcheck/dict/en-US.dic b/tests/auto/widgets/qwebenginespellcheck/dict/en-US.dic index 3d4ecdfa4..63e9164cc 100644 --- a/tests/auto/widgets/qwebenginespellcheck/dict/en-US.dic +++ b/tests/auto/widgets/qwebenginespellcheck/dict/en-US.dic @@ -4,6 +4,7 @@ I/Q it/Q love/Q loves/Q +low/Q qt/Q she/Q they/Q diff --git a/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp b/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp index c7b083660..d5e8a21cf 100644 --- a/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp +++ b/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp @@ -148,19 +148,20 @@ void tst_QWebEngineSpellcheck::spellcheck() profile->setSpellCheckLanguages(languages); profile->setSpellCheckEnabled(true); load(); + QCOMPARE(profile->spellCheckLanguages(), languages); // make textarea editable evaluateJavaScriptSync(m_view->page(), "makeEditable();"); // calcuate position of misspelled word - QVariantList list = evaluateJavaScriptSync(m_view->page(), "findWordPosition('I lovee Qt ....','lovee');").toList(); + QVariantList list = evaluateJavaScriptSync(m_view->page(), "findWordPosition('I lowe Qt ....','lowe');").toList(); QRect rect(list[0].value<int>(),list[1].value<int>(),list[2].value<int>(),list[3].value<int>()); //type text, spellchecker needs time QTest::mouseMove(m_view->focusWidget(), QPoint(20,20)); QTest::mousePress(m_view->focusWidget(), Qt::LeftButton, 0, QPoint(20,20)); QTest::mouseRelease(m_view->focusWidget(), Qt::LeftButton, 0, QPoint(20,20)); - QString text("I lovee Qt ...."); + QString text("I lowe Qt ...."); for (int i = 0; i < text.length(); i++) { QTest::keyClicks(m_view->focusWidget(), text.at(i)); QTest::qWait(60); @@ -180,10 +181,10 @@ void tst_QWebEngineSpellcheck::spellcheck() QVERIFY(m_view->data().isContentEditable()); // check misspelled word - QVERIFY(m_view->data().misspelledWord() == "lovee"); + QCOMPARE(m_view->data().misspelledWord(), QStringLiteral("lowe")); // check suggestions - QVERIFY(m_view->data().spellCheckerSuggestions() == suggestions); + QCOMPARE(m_view->data().spellCheckerSuggestions(), suggestions); // check replace word m_view->page()->replaceMisspelledWord("love"); @@ -195,8 +196,8 @@ void tst_QWebEngineSpellcheck::spellcheck_data() { QTest::addColumn<QStringList>("languages"); QTest::addColumn<QStringList>("suggestions"); - QTest::newRow("en-US") << QStringList({"en-US"}) << QStringList({"love", "loves"}); - QTest::newRow("en-US,de-DE") << QStringList({"en-US","de-DE"}) << QStringList({"love", "liebe", "loves"}); + QTest::newRow("en-US") << QStringList({"en-US"}) << QStringList({"low", "love"}); + QTest::newRow("en-US,de-DE") << QStringList({"en-US", "de-DE"}) << QStringList({"low", "löwe", "love"}); } QTEST_MAIN(tst_QWebEngineSpellcheck) diff --git a/tests/auto/widgets/qwebengineview/BLACKLIST b/tests/auto/widgets/qwebengineview/BLACKLIST index b3f393af4..a2ecd05b7 100644 --- a/tests/auto/widgets/qwebengineview/BLACKLIST +++ b/tests/auto/widgets/qwebengineview/BLACKLIST @@ -1,8 +1,5 @@ [doNotSendMouseKeyboardEventsWhenDisabled] windows -[imeComposition] -osx - [inputFieldOverridesShortcuts] osx diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index c9d5cda90..2ed461e57 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -33,6 +33,7 @@ #include <qdiriterator.h> #include <qstackedlayout.h> #include <qtemporarydir.h> +#include <QClipboard> #include <QCompleter> #include <QLineEdit> #include <QHBoxLayout> @@ -145,6 +146,9 @@ private Q_SLOTS: void imeCompositionQueryEvent_data(); void imeCompositionQueryEvent(); void newlineInTextarea(); +#ifndef QT_NO_CLIPBOARD + void globalMouseSelection(); +#endif }; // This will be called before the first test function is executed. @@ -1625,14 +1629,17 @@ void tst_QWebEngineView::textSelectionInInputField() event.setCommitString("XXX", 0, 0); QApplication::sendEvent(view.focusProxy(), &event); QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngineXXX")); + QCOMPARE(selectionChangedSpy.count(), 0); event.setCommitString(QString(), -2, 2); // Erase two characters. QApplication::sendEvent(view.focusProxy(), &event); QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngineX")); + QCOMPARE(selectionChangedSpy.count(), 0); event.setCommitString(QString(), -1, 1); // Erase one character. QApplication::sendEvent(view.focusProxy(), &event); QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngine")); + QCOMPARE(selectionChangedSpy.count(), 0); // Move to the start of the line QTest::keyClick(view.focusProxy(), Qt::Key_Home); @@ -1802,12 +1809,7 @@ void tst_QWebEngineView::emptyInputMethodEvent() QVERIFY(loadFinishedSpy.wait()); evaluateJavaScriptSync(view.page(), "var inputEle = document.getElementById('input1'); inputEle.focus(); inputEle.select();"); - QTRY_VERIFY(!evaluateJavaScriptSync(view.page(), "window.getSelection().toString()").toString().isEmpty()); - - QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue); - QVERIFY(selectionChangedSpy.wait(100)); - QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue); - QCOMPARE(selectionChangedSpy.count(), 1); + QTRY_COMPARE(selectionChangedSpy.count(), 1); // 1. Empty input method event does not clear text QInputMethodEvent emptyEvent; @@ -1854,12 +1856,7 @@ void tst_QWebEngineView::imeComposition() QVERIFY(loadFinishedSpy.wait()); evaluateJavaScriptSync(view.page(), "var inputEle = document.getElementById('input1'); inputEle.focus(); inputEle.select();"); - QTRY_VERIFY(!evaluateJavaScriptSync(view.page(), "window.getSelection().toString()").toString().isEmpty()); - - QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue); - QVERIFY(selectionChangedSpy.wait(100)); - QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue); - QCOMPARE(selectionChangedSpy.count(), 1); + QTRY_COMPARE(selectionChangedSpy.count(), 1); // Clear the selection, also cancel the ongoing composition if there is one. { @@ -1868,17 +1865,13 @@ void tst_QWebEngineView::imeComposition() attributes.append(newSelection); QInputMethodEvent event("", attributes); QApplication::sendEvent(view.focusProxy(), &event); - QTRY_VERIFY(evaluateJavaScriptSync(view.page(), "window.getSelection().toString()").toString().isEmpty()); - - QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue); - QVERIFY(selectionChangedSpy.wait(100)); - QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue); + selectionChangedSpy.wait(); QCOMPARE(selectionChangedSpy.count(), 2); } - QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngine inputMethod")); - QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 0); - QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 0); - QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString("")); + QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngine inputMethod")); + QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 0); + QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 0); + QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString("")); selectionChangedSpy.clear(); @@ -1999,19 +1992,14 @@ void tst_QWebEngineView::imeComposition() QList<QInputMethodEvent::Attribute> attributes; QInputMethodEvent event("w", attributes); QApplication::sendEvent(view.focusProxy(), &event); - QTRY_VERIFY(evaluateJavaScriptSync(view.page(), "window.getSelection().toString()").toString().isEmpty()); - QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), QString("oeQtWebEngine w")); - - QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue); - QVERIFY(selectionChangedSpy.wait(100)); - QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue); + // The new composition should clear the previous selection + QVERIFY(selectionChangedSpy.wait()); QCOMPARE(selectionChangedSpy.count(), 2); } - QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("oeQtWebEngine ")); - QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 14); - QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue); - QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 14); - QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue); + QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("oeQtWebEngine ")); + // The cursor should be positioned at the end of the composition text + QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 15); + QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 15); QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString("")); // Send commit text, which makes the editor conforms composition. @@ -2026,6 +2014,7 @@ void tst_QWebEngineView::imeComposition() QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 15); QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 15); QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString("")); + QCOMPARE(selectionChangedSpy.count(), 2); } void tst_QWebEngineView::newlineInTextarea() @@ -2207,5 +2196,44 @@ void tst_QWebEngineView::imeCompositionQueryEvent() QTRY_COMPARE(anchorPosQuery.value(Qt::ImAnchorPosition).toInt(), 11); } +#ifndef QT_NO_CLIPBOARD +void tst_QWebEngineView::globalMouseSelection() +{ + if (!QApplication::clipboard()->supportsSelection()) { + QSKIP("Test only relevant for systems with selection"); + return; + } + + QApplication::clipboard()->clear(QClipboard::Selection); + QWebEngineView view; + view.show(); + + QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged())); + QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool))); + view.setHtml("<html><body>" + " <input type='text' id='input1' value='QtWebEngine' size='50' />" + "</body></html>"); + QVERIFY(loadFinishedSpy.wait()); + + // Select text via JavaScript + evaluateJavaScriptSync(view.page(), "var inputEle = document.getElementById('input1'); inputEle.focus(); inputEle.select();"); + QTRY_COMPARE(selectionChangedSpy.count(), 1); + QVERIFY(QApplication::clipboard()->text(QClipboard::Selection).isEmpty()); + + // Deselect the selection (this moves the current cursor to the end of the text) + QPoint textInputCenter = elementCenter(view.page(), "input1"); + QTest::mouseClick(view.focusProxy(), Qt::LeftButton, 0, textInputCenter); + QVERIFY(selectionChangedSpy.wait()); + QCOMPARE(selectionChangedSpy.count(), 2); + QVERIFY(QApplication::clipboard()->text(QClipboard::Selection).isEmpty()); + + // Select to the start of the line + QTest::keyClick(view.focusProxy(), Qt::Key_Home, Qt::ShiftModifier); + QVERIFY(selectionChangedSpy.wait()); + QCOMPARE(selectionChangedSpy.count(), 3); + QCOMPARE(QApplication::clipboard()->text(QClipboard::Selection), QStringLiteral("QtWebEngine")); +} +#endif + QTEST_MAIN(tst_QWebEngineView) #include "tst_qwebengineview.moc" diff --git a/tools/scripts/take_snapshot.py b/tools/scripts/take_snapshot.py index 4a1031e80..2bd1ac5ed 100755 --- a/tools/scripts/take_snapshot.py +++ b/tools/scripts/take_snapshot.py @@ -113,6 +113,7 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('chrome_frame') or file_path.startswith('chromecast') or file_path.startswith('chromeos') + or file_path.startswith('cloud_print') or file_path.startswith('components/chrome_apps/') or file_path.startswith('components/cronet/') or file_path.startswith('components/drive/') @@ -144,6 +145,7 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('testing/buildbot') or file_path.startswith('third_party/WebKit/LayoutTests') or file_path.startswith('third_party/WebKit/ManualTests') + or file_path.startswith('third_party/WebKit/Source/devtools/devtools-node-modules') or file_path.startswith('third_party/WebKit/PerformanceTests') or file_path.startswith('third_party/accessibility-audit') or file_path.startswith('third_party/afl') @@ -169,6 +171,7 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('third_party/google_input_tools') or file_path.startswith('third_party/gperf') or file_path.startswith('third_party/gnu_binutils') + or file_path.startswith('third_party/grpc') or file_path.startswith('third_party/gtk+') or file_path.startswith('third_party/google_appengine_cloudstorage') or file_path.startswith('third_party/google_toolbox_for_mac') @@ -184,6 +187,7 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('third_party/libc++') or file_path.startswith('third_party/liblouis') or file_path.startswith('third_party/lighttpd') + or file_path.startswith('third_party/libwebm/source/webm_parser/fuzzing') or file_path.startswith('third_party/logilab') or file_path.startswith('third_party/markdown') or file_path.startswith('third_party/mingw-w64') @@ -199,6 +203,7 @@ def isInChromiumBlacklist(file_path): or file_path.startswith('third_party/pylint') or file_path.startswith('third_party/scons-2.0.1') or file_path.startswith('third_party/sfntly/src/cpp/data/fonts') + or file_path.startswith('third_party/skia/infra') or file_path.startswith('third_party/speech-dispatcher') or file_path.startswith('third_party/talloc') or file_path.startswith('third_party/trace-viewer') diff --git a/tools/scripts/version_resolver.py b/tools/scripts/version_resolver.py index 4c0b03a97..c6385b57d 100644 --- a/tools/scripts/version_resolver.py +++ b/tools/scripts/version_resolver.py @@ -38,8 +38,8 @@ import json import urllib2 import git_submodule as GitSubmodule -chromium_version = '56.0.2924.122' -chromium_branch = '2924' +chromium_version = '58.0.3029.54' +chromium_branch = '3029' ninja_version = 'v1.7.2' json_url = 'http://omahaproxy.appspot.com/all.json' |