WebEngine Widgets Simple Browser Example▲
Sélectionnez
/**
**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** 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
"browser.h"
#include
"browserwindow.h"
#include
"downloadmanagerwidget.h"
#include
"tabwidget.h"
#include
"webview.h"
#include <QApplication>
#include <QCloseEvent>
#include <QDesktopWidget>
#include <QEvent>
#include <QFileDialog>
#include <QInputDialog>
#include <QMenuBar>
#include <QMessageBox>
#include <QProgressBar>
#include <QStatusBar>
#include <QToolBar>
#include <QVBoxLayout>
#include <QWebEngineProfile>
BrowserWindow::
BrowserWindow(Browser *
browser, QWebEngineProfile *
profile, bool
forDevTools)
:
m_browser(browser)
, m_profile(profile)
, m_tabWidget(new
TabWidget(profile, this
))
, m_progressBar(nullptr
)
, m_historyBackAction(nullptr
)
, m_historyForwardAction(nullptr
)
, m_stopAction(nullptr
)
, m_reloadAction(nullptr
)
, m_stopReloadAction(nullptr
)
, m_urlLineEdit(nullptr
)
, m_favAction(nullptr
)
{
setAttribute(Qt::
WA_DeleteOnClose, true
);
setFocusPolicy(Qt::
ClickFocus);
if
(!
forDevTools) {
m_progressBar =
new
QProgressBar(this
);
QToolBar *
toolbar =
createToolBar();
addToolBar(toolbar);
menuBar()-&
gt;addMenu(createFileMenu(m_tabWidget));
menuBar()-&
gt;addMenu(createEditMenu());
menuBar()-&
gt;addMenu(createViewMenu(toolbar));
menuBar()-&
gt;addMenu(createWindowMenu(m_tabWidget));
menuBar()-&
gt;addMenu(createHelpMenu());
}
QWidget *
centralWidget =
new
QWidget(this
);
QVBoxLayout *
layout =
new
QVBoxLayout;
layout-&
gt;setSpacing(0
);
layout-&
gt;setMargin(0
);
if
(!
forDevTools) {
addToolBarBreak();
m_progressBar-&
gt;setMaximumHeight(1
);
m_progressBar-&
gt;setTextVisible(false
);
m_progressBar-&
gt;setStyleSheet(QStringLiteral("QProgressBar {border: 0px} QProgressBar::chunk {background-color: #da4453}"
));
layout-&
gt;addWidget(m_progressBar);
}
layout-&
gt;addWidget(m_tabWidget);
centralWidget-&
gt;setLayout(layout);
setCentralWidget(centralWidget);
connect(m_tabWidget, &
amp;TabWidget::
titleChanged, this
, &
amp;BrowserWindow::
handleWebViewTitleChanged);
if
(!
forDevTools) {
connect(m_tabWidget, &
amp;TabWidget::
linkHovered, [this
](const
QString&
amp; url) {
statusBar()-&
gt;showMessage(url);
}
);
connect(m_tabWidget, &
amp;TabWidget::
loadProgress, this
, &
amp;BrowserWindow::
handleWebViewLoadProgress);
connect(m_tabWidget, &
amp;TabWidget::
webActionEnabledChanged, this
, &
amp;BrowserWindow::
handleWebActionEnabledChanged);
connect(m_tabWidget, &
amp;TabWidget::
urlChanged, [this
](const
QUrl &
amp;url) {
m_urlLineEdit-&
gt;setText(url.toDisplayString());
}
);
connect(m_tabWidget, &
amp;TabWidget::
favIconChanged, m_favAction, &
amp;QAction::
setIcon);
connect(m_tabWidget, &
amp;TabWidget::
devToolsRequested, this
, &
amp;BrowserWindow::
handleDevToolsRequested);
connect(m_urlLineEdit, &
amp;QLineEdit::
returnPressed, [this
]() {
m_tabWidget-&
gt;setUrl(QUrl::
fromUserInput(m_urlLineEdit-&
gt;text()));
}
);
QAction *
focusUrlLineEditAction =
new
QAction(this
);
addAction(focusUrlLineEditAction);
focusUrlLineEditAction-&
gt;setShortcut(QKeySequence(Qt::
CTRL |
Qt::
Key_L));
connect(focusUrlLineEditAction, &
amp;QAction::
triggered, this
, [this
] () {
m_urlLineEdit-&
gt;setFocus(Qt::
ShortcutFocusReason);
}
);
}
handleWebViewTitleChanged(QString());
m_tabWidget-&
gt;createTab();
}
QSize BrowserWindow::
sizeHint() const
{
QRect desktopRect =
QApplication::
desktop()-&
gt;screenGeometry();
QSize size =
desktopRect.size() *
qreal(0.9
);
return
size;
}
QMenu *
BrowserWindow::
createFileMenu(TabWidget *
tabWidget)
{
QMenu *
fileMenu =
new
QMenu(tr("&File"
));
fileMenu-&
gt;addAction(tr("&New Window"
), this
, &
amp;BrowserWindow::
handleNewWindowTriggered, QKeySequence::
New);
fileMenu-&
gt;addAction(tr("New &Incognito Window"
), this
, &
amp;BrowserWindow::
handleNewIncognitoWindowTriggered);
QAction *
newTabAction =
new
QAction(tr("New &Tab"
), this
);
newTabAction-&
gt;setShortcuts(QKeySequence::
AddTab);
connect(newTabAction, &
amp;QAction::
triggered, this
, [this
]() {
m_tabWidget-&
gt;createTab();
m_urlLineEdit-&
gt;setFocus();
}
);
fileMenu-&
gt;addAction(newTabAction);
fileMenu-&
gt;addAction(tr("&Open File..."
), this
, &
amp;BrowserWindow::
handleFileOpenTriggered, QKeySequence::
Open);
fileMenu-&
gt;addSeparator();
QAction *
closeTabAction =
new
QAction(tr("&Close Tab"
), this
);
closeTabAction-&
gt;setShortcuts(QKeySequence::
Close);
connect(closeTabAction, &
amp;QAction::
triggered, [tabWidget]() {
tabWidget-&
gt;closeTab(tabWidget-&
gt;currentIndex());
}
);
fileMenu-&
gt;addAction(closeTabAction);
QAction *
closeAction =
new
QAction(tr("&Quit"
),this
);
closeAction-&
gt;setShortcut(QKeySequence(Qt::
CTRL |
Qt::
Key_Q));
connect(closeAction, &
amp;QAction::
triggered, this
, &
amp;QWidget::
close);
fileMenu-&
gt;addAction(closeAction);
connect(fileMenu, &
amp;QMenu::
aboutToShow, [this
, closeAction]() {
if
(m_browser-&
gt;windows().count() ==
1
)
closeAction-&
gt;setText(tr("&Quit"
));
else
closeAction-&
gt;setText(tr("&Close Window"
));
}
);
return
fileMenu;
}
QMenu *
BrowserWindow::
createEditMenu()
{
QMenu *
editMenu =
new
QMenu(tr("&Edit"
));
QAction *
findAction =
editMenu-&
gt;addAction(tr("&Find"
));
findAction-&
gt;setShortcuts(QKeySequence::
Find);
connect(findAction, &
amp;QAction::
triggered, this
, &
amp;BrowserWindow::
handleFindActionTriggered);
QAction *
findNextAction =
editMenu-&
gt;addAction(tr("Find &Next"
));
findNextAction-&
gt;setShortcut(QKeySequence::
FindNext);
connect(findNextAction, &
amp;QAction::
triggered, [this
]() {
if
(!
currentTab() ||
m_lastSearch.isEmpty())
return
;
currentTab()-&
gt;findText(m_lastSearch);
}
);
QAction *
findPreviousAction =
editMenu-&
gt;addAction(tr("Find &Previous"
));
findPreviousAction-&
gt;setShortcut(QKeySequence::
FindPrevious);
connect(findPreviousAction, &
amp;QAction::
triggered, [this
]() {
if
(!
currentTab() ||
m_lastSearch.isEmpty())
return
;
currentTab()-&
gt;findText(m_lastSearch, QWebEnginePage::
FindBackward);
}
);
return
editMenu;
}
QMenu *
BrowserWindow::
createViewMenu(QToolBar *
toolbar)
{
QMenu *
viewMenu =
new
QMenu(tr("&View"
));
m_stopAction =
viewMenu-&
gt;addAction(tr("&Stop"
));
QList&
lt;QKeySequence&
gt; shortcuts;
shortcuts.append(QKeySequence(Qt::
CTRL |
Qt::
Key_Period));
shortcuts.append(Qt::
Key_Escape);
m_stopAction-&
gt;setShortcuts(shortcuts);
connect(m_stopAction, &
amp;QAction::
triggered, [this
]() {
m_tabWidget-&
gt;triggerWebPageAction(QWebEnginePage::
Stop);
}
);
m_reloadAction =
viewMenu-&
gt;addAction(tr("Reload Page"
));
m_reloadAction-&
gt;setShortcuts(QKeySequence::
Refresh);
connect(m_reloadAction, &
amp;QAction::
triggered, [this
]() {
m_tabWidget-&
gt;triggerWebPageAction(QWebEnginePage::
Reload);
}
);
QAction *
zoomIn =
viewMenu-&
gt;addAction(tr("Zoom &In"
));
zoomIn-&
gt;setShortcut(QKeySequence(Qt::
CTRL |
Qt::
Key_Plus));
connect(zoomIn, &
amp;QAction::
triggered, [this
]() {
if
(currentTab())
currentTab()-&
gt;setZoomFactor(currentTab()-&
gt;zoomFactor() +
0.1
);
}
);
QAction *
zoomOut =
viewMenu-&
gt;addAction(tr("Zoom &Out"
));
zoomOut-&
gt;setShortcut(QKeySequence(Qt::
CTRL |
Qt::
Key_Minus));
connect(zoomOut, &
amp;QAction::
triggered, [this
]() {
if
(currentTab())
currentTab()-&
gt;setZoomFactor(currentTab()-&
gt;zoomFactor() -
0.1
);
}
);
QAction *
resetZoom =
viewMenu-&
gt;addAction(tr("Reset &Zoom"
));
resetZoom-&
gt;setShortcut(QKeySequence(Qt::
CTRL |
Qt::
Key_0));
connect(resetZoom, &
amp;QAction::
triggered, [this
]() {
if
(currentTab())
currentTab()-&
gt;setZoomFactor(1.0
);
}
);
viewMenu-&
gt;addSeparator();
QAction *
viewToolbarAction =
new
QAction(tr("Hide Toolbar"
),this
);
viewToolbarAction-&
gt;setShortcut(tr("Ctrl+|"
));
connect(viewToolbarAction, &
amp;QAction::
triggered, [toolbar,viewToolbarAction]() {
if
(toolbar-&
gt;isVisible()) {
viewToolbarAction-&
gt;setText(tr("Show Toolbar"
));
toolbar-&
gt;close();
}
else
{
viewToolbarAction-&
gt;setText(tr("Hide Toolbar"
));
toolbar-&
gt;show();
}
}
);
viewMenu-&
gt;addAction(viewToolbarAction);
QAction *
viewStatusbarAction =
new
QAction(tr("Hide Status Bar"
), this
);
viewStatusbarAction-&
gt;setShortcut(tr("Ctrl+/"
));
connect(viewStatusbarAction, &
amp;QAction::
triggered, [this
, viewStatusbarAction]() {
if
(statusBar()-&
gt;isVisible()) {
viewStatusbarAction-&
gt;setText(tr("Show Status Bar"
));
statusBar()-&
gt;close();
}
else
{
viewStatusbarAction-&
gt;setText(tr("Hide Status Bar"
));
statusBar()-&
gt;show();
}
}
);
viewMenu-&
gt;addAction(viewStatusbarAction);
return
viewMenu;
}
QMenu *
BrowserWindow::
createWindowMenu(TabWidget *
tabWidget)
{
QMenu *
menu =
new
QMenu(tr("&Window"
));
QAction *
nextTabAction =
new
QAction(tr("Show Next Tab"
), this
);
QList&
lt;QKeySequence&
gt; 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));
nextTabAction-&
gt;setShortcuts(shortcuts);
connect(nextTabAction, &
amp;QAction::
triggered, tabWidget, &
amp;TabWidget::
nextTab);
QAction *
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));
previousTabAction-&
gt;setShortcuts(shortcuts);
connect(previousTabAction, &
amp;QAction::
triggered, tabWidget, &
amp;TabWidget::
previousTab);
connect(menu, &
amp;QMenu::
aboutToShow, [this
, menu, nextTabAction, previousTabAction]() {
menu-&
gt;clear();
menu-&
gt;addAction(nextTabAction);
menu-&
gt;addAction(previousTabAction);
menu-&
gt;addSeparator();
QVector&
lt;BrowserWindow*&
gt; windows =
m_browser-&
gt;windows();
int
index(-
1
);
for
(auto
window : windows) {
QAction *
action =
menu-&
gt;addAction(window-&
gt;windowTitle(), this
, &
amp;BrowserWindow::
handleShowWindowTriggered);
action-&
gt;setData(++
index);
action-&
gt;setCheckable(true
);
if
(window ==
this
)
action-&
gt;setChecked(true
);
}
}
);
return
menu;
}
QMenu *
BrowserWindow::
createHelpMenu()
{
QMenu *
helpMenu =
new
QMenu(tr("&Help"
));
helpMenu-&
gt;addAction(tr("About &Qt"
), qApp, QApplication::
aboutQt);
return
helpMenu;
}
QToolBar *
BrowserWindow::
createToolBar()
{
QToolBar *
navigationBar =
new
QToolBar(tr("Navigation"
));
navigationBar-&
gt;setMovable(false
);
navigationBar-&
gt;toggleViewAction()-&
gt;setEnabled(false
);
m_historyBackAction =
new
QAction(this
);
QList&
lt;QKeySequence&
gt; 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_historyBackAction-&
gt;setShortcuts(backShortcuts);
m_historyBackAction-&
gt;setIconVisibleInMenu(false
);
m_historyBackAction-&
gt;setIcon(QIcon(QStringLiteral(":go-previous.png"
)));
m_historyBackAction-&
gt;setToolTip(tr("Go back in history"
));
connect(m_historyBackAction, &
amp;QAction::
triggered, [this
]() {
m_tabWidget-&
gt;triggerWebPageAction(QWebEnginePage::
Back);
}
);
navigationBar-&
gt;addAction(m_historyBackAction);
m_historyForwardAction =
new
QAction(this
);
QList&
lt;QKeySequence&
gt; fwdShortcuts =
QKeySequence::
keyBindings(QKeySequence::
Forward);
for
(auto
it =
fwdShortcuts.begin(); it !=
fwdShortcuts.end();) {
if
(((*
it)[0
] &
amp; Qt::
Key_unknown) ==
Qt::
Key_Backspace)
it =
fwdShortcuts.erase(it);
else
++
it;
}
fwdShortcuts.append(QKeySequence(Qt::
Key_Forward));
m_historyForwardAction-&
gt;setShortcuts(fwdShortcuts);
m_historyForwardAction-&
gt;setIconVisibleInMenu(false
);
m_historyForwardAction-&
gt;setIcon(QIcon(QStringLiteral(":go-next.png"
)));
m_historyForwardAction-&
gt;setToolTip(tr("Go forward in history"
));
connect(m_historyForwardAction, &
amp;QAction::
triggered, [this
]() {
m_tabWidget-&
gt;triggerWebPageAction(QWebEnginePage::
Forward);
}
);
navigationBar-&
gt;addAction(m_historyForwardAction);
m_stopReloadAction =
new
QAction(this
);
connect(m_stopReloadAction, &
amp;QAction::
triggered, [this
]() {
m_tabWidget-&
gt;triggerWebPageAction(QWebEnginePage::
WebAction(m_stopReloadAction-&
gt;data().toInt()));
}
);
navigationBar-&
gt;addAction(m_stopReloadAction);
m_urlLineEdit =
new
QLineEdit(this
);
m_favAction =
new
QAction(this
);
m_urlLineEdit-&
gt;addAction(m_favAction, QLineEdit::
LeadingPosition);
m_urlLineEdit-&
gt;setClearButtonEnabled(true
);
navigationBar-&
gt;addWidget(m_urlLineEdit);
auto
downloadsAction =
new
QAction(this
);
downloadsAction-&
gt;setIcon(QIcon(QStringLiteral(":go-bottom.png"
)));
downloadsAction-&
gt;setToolTip(tr("Show downloads"
));
navigationBar-&
gt;addAction(downloadsAction);
connect(downloadsAction, &
amp;QAction::
triggered, [this
]() {
m_browser-&
gt;downloadManagerWidget().show();
}
);
return
navigationBar;
}
void
BrowserWindow::
handleWebActionEnabledChanged(QWebEnginePage::
WebAction action, bool
enabled)
{
switch
(action) {
case
QWebEnginePage::
Back:
m_historyBackAction-&
gt;setEnabled(enabled);
break
;
case
QWebEnginePage::
Forward:
m_historyForwardAction-&
gt;setEnabled(enabled);
break
;
case
QWebEnginePage::
Reload:
m_reloadAction-&
gt;setEnabled(enabled);
break
;
case
QWebEnginePage::
Stop:
m_stopAction-&
gt;setEnabled(enabled);
break
;
default
:
qWarning("Unhandled webActionChanged signal"
);
}
}
void
BrowserWindow::
handleWebViewTitleChanged(const
QString &
amp;title)
{
QString suffix =
m_profile-&
gt;isOffTheRecord()
? tr("Qt Simple Browser (Incognito)"
)
:
tr("Qt Simple Browser"
);
if
(title.isEmpty())
setWindowTitle(suffix);
else
setWindowTitle(title +
" - "
+
suffix);
}
void
BrowserWindow::
handleNewWindowTriggered()
{
BrowserWindow *
window =
m_browser-&
gt;createWindow();
window-&
gt;m_urlLineEdit-&
gt;setFocus();
}
void
BrowserWindow::
handleNewIncognitoWindowTriggered()
{
BrowserWindow *
window =
m_browser-&
gt;createWindow(/* offTheRecord: */
true
);
window-&
gt;m_urlLineEdit-&
gt;setFocus();
}
void
BrowserWindow::
handleFileOpenTriggered()
{
QUrl url =
QFileDialog::
getOpenFileUrl(this
, tr("Open Web Resource"
), QString(),
tr("Web Resources (*.html *.htm *.svg *.png *.gif *.svgz);;All files (*.*)"
));
if
(url.isEmpty())
return
;
currentTab()-&
gt;setUrl(url);
}
void
BrowserWindow::
handleFindActionTriggered()
{
if
(!
currentTab())
return
;
bool
ok =
false
;
QString search =
QInputDialog::
getText(this
, tr("Find"
),
tr("Find:"
), QLineEdit::
Normal,
m_lastSearch, &
amp;ok);
if
(ok &
amp;&
amp; !
search.isEmpty()) {
m_lastSearch =
search;
currentTab()-&
gt;findText(m_lastSearch, 0
, [this
](bool
found) {
if
(!
found)
statusBar()-&
gt;showMessage(tr("
\"
%1
\"
not found."
).arg(m_lastSearch));
}
);
}
}
void
BrowserWindow::
closeEvent(QCloseEvent *
event)
{
if
(m_tabWidget-&
gt;count() &
gt; 1
) {
int
ret =
QMessageBox::
warning(this
, tr("Confirm close"
),
tr("Are you sure you want to close the window ?
\n
"
"There are %1 tabs open."
).arg(m_tabWidget-&
gt;count()),
QMessageBox::
Yes |
QMessageBox::
No, QMessageBox::
No);
if
(ret ==
QMessageBox::
No) {
event-&
gt;ignore();
return
;
}
}
event-&
gt;accept();
deleteLater();
}
TabWidget *
BrowserWindow::
tabWidget() const
{
return
m_tabWidget;
}
WebView *
BrowserWindow::
currentTab() const
{
return
m_tabWidget-&
gt;currentWebView();
}
void
BrowserWindow::
handleWebViewLoadProgress(int
progress)
{
static
QIcon stopIcon(QStringLiteral(":process-stop.png"
));
static
QIcon reloadIcon(QStringLiteral(":view-refresh.png"
));
if
(0
&
lt; progress &
amp;&
amp; progress &
lt; 100
) {
m_stopReloadAction-&
gt;setData(QWebEnginePage::
Stop);
m_stopReloadAction-&
gt;setIcon(stopIcon);
m_stopReloadAction-&
gt;setToolTip(tr("Stop loading the current page"
));
m_progressBar-&
gt;setValue(progress);
}
else
{
m_stopReloadAction-&
gt;setData(QWebEnginePage::
Reload);
m_stopReloadAction-&
gt;setIcon(reloadIcon);
m_stopReloadAction-&
gt;setToolTip(tr("Reload the current page"
));
m_progressBar-&
gt;setValue(0
);
}
}
void
BrowserWindow::
handleShowWindowTriggered()
{
if
(QAction *
action =
qobject_cast&
lt;QAction*&
gt;(sender())) {
int
offset =
action-&
gt;data().toInt();
QVector&
lt;BrowserWindow*&
gt; windows =
m_browser-&
gt;windows();
windows.at(offset)-&
gt;activateWindow();
windows.at(offset)-&
gt;currentTab()-&
gt;setFocus();
}
}
void
BrowserWindow::
handleDevToolsRequested(QWebEnginePage *
source)
{
source-&
gt;setDevToolsPage(m_browser-&
gt;createDevToolsWindow()-&
gt;currentTab()-&
gt;page());
source-&
gt;triggerAction(QWebEnginePage::
InspectElement);
}