Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
helpviewerimpl_qwv.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
6
11#include "tracer.h"
12
13#include <QClipboard>
14#include <QtCore/QFileInfo>
15#include <QtCore/QString>
16#include <QtCore/QTimer>
17
18#include <QtWidgets/QApplication>
19#include <QtGui/QWheelEvent>
20
21#include <QtNetwork/QNetworkReply>
22
24
25// -- HelpPage
26
27class HelpPage : public QWebPage
28{
29public:
30 HelpPage(QObject *parent);
31
32protected:
34 virtual void triggerAction(WebAction action, bool checked = false);
35
36 virtual bool acceptNavigationRequest(QWebFrame *frame,
37 const QNetworkRequest &request, NavigationType type);
38
39private:
40 bool closeNewTabIfNeeded;
41
42 friend class HelpViewerImpl;
43 QUrl m_loadingUrl;
44 Qt::MouseButtons m_pressedButtons;
45 Qt::KeyboardModifiers m_keyboardModifiers;
46};
47
48HelpPage::HelpPage(QObject *parent)
50 , closeNewTabIfNeeded(false)
53{
55}
56
58{
60 HelpPage *newPage = static_cast<HelpPage *>(OpenPagesManager::instance()
61 ->createBlankPage()->page());
62 newPage->closeNewTabIfNeeded = closeNewTabIfNeeded;
63 closeNewTabIfNeeded = false;
64 return newPage;
65}
66
67void HelpPage::triggerAction(WebAction action, bool checked)
68{
70 switch (action) {
71 case OpenLinkInNewWindow:
72 closeNewTabIfNeeded = true;
73 Q_FALLTHROUGH();
74 default:
75 QWebPage::triggerAction(action, checked);
76 break;
77 }
78
79#if QT_CONFIG(clipboard)
80 if (action == CopyLinkToClipboard || action == CopyImageUrlToClipboard) {
81 const QString link = QApplication::clipboard()->text();
82 QApplication::clipboard()->setText(HelpEngineWrapper::instance().findFile(link).toString());
83 }
84#endif
85}
86
87bool HelpPage::acceptNavigationRequest(QWebFrame *,
88 const QNetworkRequest &request, QWebPage::NavigationType type)
89{
91 const bool closeNewTab = closeNewTabIfNeeded;
92 closeNewTabIfNeeded = false;
93
94 const QUrl &url = request.url();
95 if (HelpViewer::launchWithExternalApp(url)) {
96 if (closeNewTab)
97 QMetaObject::invokeMethod(OpenPagesManager::instance(), "closeCurrentPage");
98 return false;
99 }
100
101 if (type == QWebPage::NavigationTypeLinkClicked
102 && (m_keyboardModifiers & Qt::ControlModifier
103 || m_pressedButtons == Qt::MiddleButton)) {
104 m_pressedButtons = Qt::NoButton;
105 m_keyboardModifiers = Qt::NoModifier;
106 OpenPagesManager::instance()->createPage(url);
107 return false;
108 }
109
110 m_loadingUrl = url; // because of async page loading, we will hit some kind
111 // of race condition while using a remote command, like a combination of
112 // SetSource; SyncContent. SetSource would be called and SyncContents shortly
113 // afterwards, but the page might not have finished loading and the old url
114 // would be returned.
115 return true;
116}
117
118// -- HelpViewerImpl
119
120HelpViewerImpl::HelpViewerImpl(qreal zoom, QWidget *parent)
121 : QWebView(parent)
122 , d(new HelpViewerImplPrivate)
123{
125 setAcceptDrops(false);
126 settings()->setAttribute(QWebSettings::JavaEnabled, false);
127 settings()->setAttribute(QWebSettings::PluginsEnabled, false);
128
129 setPage(new HelpPage(this));
130 page()->setNetworkAccessManager(HelpBrowserSupport::createNetworkAccessManager(this));
131
132 QAction* action = pageAction(QWebPage::OpenLinkInNewWindow);
133 action->setText(tr("Open Link in New Page"));
134
135 pageAction(QWebPage::DownloadLinkToDisk)->setVisible(false);
136 pageAction(QWebPage::DownloadImageToDisk)->setVisible(false);
137 pageAction(QWebPage::OpenImageInNewWindow)->setVisible(false);
138
139 connect(pageAction(QWebPage::Copy), SIGNAL(changed()), this,
140 SLOT(actionChanged()));
141 connect(pageAction(QWebPage::Back), SIGNAL(changed()), this,
142 SLOT(actionChanged()));
143 connect(pageAction(QWebPage::Forward), SIGNAL(changed()), this,
144 SLOT(actionChanged()));
145 connect(page(), &QWebPage::linkHovered, this,
146 [this] (const QString &link, const QString &, const QString &) {
147 emit this->highlighted(QUrl(link));
148 });
149 connect(this, SIGNAL(urlChanged(QUrl)), this, SIGNAL(sourceChanged(QUrl)));
150 connect(this, SIGNAL(loadStarted()), this, SLOT(setLoadStarted()));
151 connect(this, SIGNAL(loadFinished(bool)), this, SLOT(setLoadFinished(bool)));
152 connect(this, SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged()));
153 connect(page(), SIGNAL(printRequested(QWebFrame*)), this, SIGNAL(printRequested()));
154
155 setFont(viewerFont());
156 setZoomFactor(d->webDpiRatio * (zoom == 0.0 ? 1.0 : zoom));
157}
158
159QFont HelpViewerImpl::viewerFont() const
160{
162 if (HelpEngineWrapper::instance().usesBrowserFont())
163 return HelpEngineWrapper::instance().browserFont();
164
165 QWebSettings *webSettings = QWebSettings::globalSettings();
166 return QFont(webSettings->fontFamily(QWebSettings::StandardFont),
167 webSettings->fontSize(QWebSettings::DefaultFontSize));
168}
169
170void HelpViewerImpl::setViewerFont(const QFont &font)
171{
173 QWebSettings *webSettings = settings();
174 webSettings->setFontFamily(QWebSettings::StandardFont, font.family());
175 webSettings->setFontSize(QWebSettings::DefaultFontSize, font.pointSize());
176}
177
178void HelpViewerImpl::scaleUp()
179{
181 setZoomFactor(zoomFactor() + 0.1);
182}
183
184void HelpViewerImpl::scaleDown()
185{
187 setZoomFactor(qMax(0.0, zoomFactor() - 0.1));
188}
189
190void HelpViewerImpl::resetScale()
191{
193 setZoomFactor(d->webDpiRatio);
194}
195
196qreal HelpViewerImpl::scale() const
197{
199 return zoomFactor() / d->webDpiRatio;
200}
201
202QString HelpViewerImpl::title() const
203{
205 return QWebView::title();
206}
207
208void HelpViewerImpl::setTitle(const QString &title)
209{
211 Q_UNUSED(title);
212}
213
214QUrl HelpViewerImpl::source() const
215{
217 HelpPage *currentPage = static_cast<HelpPage*> (page());
218 if (currentPage && !d->m_loadFinished) {
219 // see HelpPage::acceptNavigationRequest(...)
220 return currentPage->m_loadingUrl;
221 }
222 return url();
223}
224
225void HelpViewerImpl::setSource(const QUrl &url)
226{
228 load(url.toString() == QLatin1String("help") ? LocalHelpFile : url);
229}
230
231QString HelpViewerImpl::selectedText() const
232{
234 return QWebView::selectedText();
235}
236
237bool HelpViewerImpl::isForwardAvailable() const
238{
240 return pageAction(QWebPage::Forward)->isEnabled();
241}
242
243bool HelpViewerImpl::isBackwardAvailable() const
244{
246 return pageAction(QWebPage::Back)->isEnabled();
247}
248
249bool HelpViewerImpl::findText(const QString &text, HelpViewer::FindFlags flags, bool incremental,
250 bool fromSearch)
251{
253 Q_UNUSED(incremental); Q_UNUSED(fromSearch);
254 QWebPage::FindFlags options = QWebPage::FindWrapsAroundDocument;
255 if (flags & HelpViewer::FindBackward)
256 options |= QWebPage::FindBackward;
257 if (flags & HelpViewer::FindCaseSensitively)
258 options |= QWebPage::FindCaseSensitively;
259
260 bool found = QWebView::findText(text, options);
261 options = QWebPage::HighlightAllOccurrences;
262 QWebView::findText(QString(), options); // clear first
263 QWebView::findText(text, options); // force highlighting of all other matches
264 return found;
265}
266
267// -- public slots
268
269#if QT_CONFIG(clipboard)
270void HelpViewerImpl::copy()
271{
272 TRACE_OBJ
273 triggerPageAction(QWebPage::Copy);
274}
275#endif
276
277void HelpViewerImpl::forward()
278{
280 QWebView::forward();
281}
282
283void HelpViewerImpl::backward()
284{
286 back();
287}
288
289// -- protected
290
291void HelpViewerImpl::keyPressEvent(QKeyEvent *e)
292{
294 // TODO: remove this once we support multiple keysequences per command
295#if QT_CONFIG(clipboard)
296 if (e->key() == Qt::Key_Insert && e->modifiers() == Qt::CTRL) {
297 if (!selectedText().isEmpty())
298 copy();
299 }
300#endif
301 QWebView::keyPressEvent(e);
302}
303
304void HelpViewerImpl::wheelEvent(QWheelEvent *event)
305{
307 if (event->modifiers()& Qt::ControlModifier) {
308 event->accept();
309 event->delta() > 0 ? scaleUp() : scaleDown();
310 } else {
311 QWebView::wheelEvent(event);
312 }
313}
314
315void HelpViewerImpl::mousePressEvent(QMouseEvent *event)
316{
318#ifdef Q_OS_LINUX
319 if (handleForwardBackwardMouseButtons(event))
320 return;
321#endif
322
323 if (HelpPage *currentPage = static_cast<HelpPage*> (page())) {
324 currentPage->m_pressedButtons = event->buttons();
325 currentPage->m_keyboardModifiers = event->modifiers();
326 }
327
328 QWebView::mousePressEvent(event);
329}
330
331void HelpViewerImpl::mouseReleaseEvent(QMouseEvent *event)
332{
334#ifndef Q_OS_LINUX
335 if (handleForwardBackwardMouseButtons(event))
336 return;
337#endif
338
339 QWebView::mouseReleaseEvent(event);
340}
341
342// -- private slots
343
344void HelpViewerImpl::actionChanged()
345{
347 QAction *a = qobject_cast<QAction *>(sender());
348 if (a == pageAction(QWebPage::Copy))
349 emit copyAvailable(a->isEnabled());
350 else if (a == pageAction(QWebPage::Back))
351 emit backwardAvailable(a->isEnabled());
352 else if (a == pageAction(QWebPage::Forward))
353 emit forwardAvailable(a->isEnabled());
354}
355
356// -- private
357
358bool HelpViewerImpl::eventFilter(QObject *obj, QEvent *event)
359{
361 return QWebView::eventFilter(obj, event);
362}
363
364void HelpViewerImpl::contextMenuEvent(QContextMenuEvent *event)
365{
367 QWebView::contextMenuEvent(event);
368}
369
370QT_END_NAMESPACE
virtual void triggerAction(WebAction action, bool checked=false)
HelpPage(QObject *parent)
virtual bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type)
virtual QWebPage * createWindow(QWebPage::WebWindowType)
HelpViewer * createBlankPage()
static OpenPagesManager * instance()
Combined button and popup list for selecting options.
#define TRACE_OBJ
Definition tracer.h:34