1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Assistant of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include "centralwidget.h" |
30 | |
31 | #include "findwidget.h" |
32 | #include "helpenginewrapper.h" |
33 | #include "helpviewer.h" |
34 | #include "openpagesmanager.h" |
35 | #include "tracer.h" |
36 | |
37 | #include <QtCore/QRegExp> |
38 | #include <QtCore/QTimer> |
39 | |
40 | #include <QtGui/QKeyEvent> |
41 | #include <QtWidgets/QMenu> |
42 | #ifndef QT_NO_PRINTER |
43 | #include <QtPrintSupport/QPageSetupDialog> |
44 | #include <QtPrintSupport/QPrintDialog> |
45 | #include <QtPrintSupport/QPrintPreviewDialog> |
46 | #include <QtPrintSupport/QPrinter> |
47 | #endif |
48 | #include <QtWidgets/QStackedWidget> |
49 | #include <QtWidgets/QTextBrowser> |
50 | #include <QtWidgets/QVBoxLayout> |
51 | |
52 | #include <QtHelp/QHelpSearchEngine> |
53 | |
54 | QT_BEGIN_NAMESPACE |
55 | |
56 | namespace { |
57 | CentralWidget *staticCentralWidget = nullptr; |
58 | } |
59 | |
60 | // -- TabBar |
61 | |
62 | TabBar::TabBar(QWidget *parent) |
63 | : QTabBar(parent) |
64 | { |
65 | TRACE_OBJ |
66 | #ifdef Q_OS_MAC |
67 | setDocumentMode(true); |
68 | #endif |
69 | setMovable(true); |
70 | setShape(QTabBar::RoundedNorth); |
71 | setContextMenuPolicy(Qt::CustomContextMenu); |
72 | setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred, |
73 | QSizePolicy::TabWidget)); |
74 | connect(sender: this, signal: &QTabBar::currentChanged, |
75 | receiver: this, slot: &TabBar::slotCurrentChanged); |
76 | connect(sender: this, signal: &QTabBar::tabCloseRequested, |
77 | receiver: this, slot: &TabBar::slotTabCloseRequested); |
78 | connect(sender: this, signal: &QWidget::customContextMenuRequested, |
79 | receiver: this, slot: &TabBar::slotCustomContextMenuRequested); |
80 | } |
81 | |
82 | TabBar::~TabBar() |
83 | { |
84 | TRACE_OBJ |
85 | } |
86 | |
87 | int TabBar::addNewTab(const QString &title) |
88 | { |
89 | TRACE_OBJ |
90 | const int index = addTab(text: title); |
91 | setTabsClosable(count() > 1); |
92 | return index; |
93 | } |
94 | |
95 | void TabBar::setCurrent(HelpViewer *viewer) |
96 | { |
97 | TRACE_OBJ |
98 | for (int i = 0; i < count(); ++i) { |
99 | HelpViewer *data = tabData(index: i).value<HelpViewer*>(); |
100 | if (data == viewer) { |
101 | setCurrentIndex(i); |
102 | break; |
103 | } |
104 | } |
105 | } |
106 | |
107 | void TabBar::removeTabAt(HelpViewer *viewer) |
108 | { |
109 | TRACE_OBJ |
110 | for (int i = 0; i < count(); ++i) { |
111 | HelpViewer *data = tabData(index: i).value<HelpViewer*>(); |
112 | if (data == viewer) { |
113 | removeTab(index: i); |
114 | break; |
115 | } |
116 | } |
117 | setTabsClosable(count() > 1); |
118 | } |
119 | |
120 | void TabBar::titleChanged() |
121 | { |
122 | TRACE_OBJ |
123 | for (int i = 0; i < count(); ++i) { |
124 | HelpViewer *data = tabData(index: i).value<HelpViewer*>(); |
125 | QString title = data->title(); |
126 | title.replace(c: QLatin1Char('&'), after: QLatin1String("&&" )); |
127 | setTabText(index: i, text: title.isEmpty() ? tr(s: "(Untitled)" ) : title); |
128 | } |
129 | } |
130 | |
131 | void TabBar::slotCurrentChanged(int index) |
132 | { |
133 | TRACE_OBJ |
134 | emit currentTabChanged(viewer: tabData(index).value<HelpViewer*>()); |
135 | } |
136 | |
137 | void TabBar::slotTabCloseRequested(int index) |
138 | { |
139 | TRACE_OBJ |
140 | OpenPagesManager::instance()->closePage(page: tabData(index).value<HelpViewer*>()); |
141 | } |
142 | |
143 | void TabBar::(const QPoint &pos) |
144 | { |
145 | TRACE_OBJ |
146 | const int tab = tabAt(pos); |
147 | if (tab < 0) |
148 | return; |
149 | |
150 | QMenu (QString(), this); |
151 | menu.addAction(text: tr(s: "New &Tab" ), object: OpenPagesManager::instance(), |
152 | slot: &OpenPagesManager::createBlankPage); |
153 | |
154 | const bool enableAction = count() > 1; |
155 | QAction *closePage = menu.addAction(text: tr(s: "&Close Tab" )); |
156 | closePage->setEnabled(enableAction); |
157 | |
158 | QAction *closePages = menu.addAction(text: tr(s: "Close Other Tabs" )); |
159 | closePages->setEnabled(enableAction); |
160 | |
161 | menu.addSeparator(); |
162 | |
163 | HelpViewer *viewer = tabData(index: tab).value<HelpViewer*>(); |
164 | QAction *newBookmark = menu.addAction(text: tr(s: "Add Bookmark for this Page..." )); |
165 | const QString &url = viewer->source().toString(); |
166 | if (url.isEmpty() || url == QLatin1String("about:blank" )) |
167 | newBookmark->setEnabled(false); |
168 | |
169 | QAction *pickedAction = menu.exec(pos: mapToGlobal(pos)); |
170 | if (pickedAction == closePage) |
171 | slotTabCloseRequested(index: tab); |
172 | else if (pickedAction == closePages) { |
173 | for (int i = count() - 1; i >= 0; --i) { |
174 | if (i != tab) |
175 | slotTabCloseRequested(index: i); |
176 | } |
177 | } else if (pickedAction == newBookmark) |
178 | emit addBookmark(title: viewer->title(), url); |
179 | } |
180 | |
181 | // -- CentralWidget |
182 | |
183 | CentralWidget::CentralWidget(QWidget *parent) |
184 | : QWidget(parent) |
185 | #ifndef QT_NO_PRINTER |
186 | , m_printer(nullptr) |
187 | #endif |
188 | , m_findWidget(new FindWidget(this)) |
189 | , m_stackedWidget(new QStackedWidget(this)) |
190 | , m_tabBar(new TabBar(this)) |
191 | { |
192 | TRACE_OBJ |
193 | staticCentralWidget = this; |
194 | QVBoxLayout *vboxLayout = new QVBoxLayout(this); |
195 | |
196 | vboxLayout->setContentsMargins(QMargins()); |
197 | vboxLayout->setSpacing(0); |
198 | vboxLayout->addWidget(m_tabBar); |
199 | m_tabBar->setVisible(HelpEngineWrapper::instance().showTabs()); |
200 | vboxLayout->addWidget(m_stackedWidget); |
201 | vboxLayout->addWidget(m_findWidget); |
202 | m_findWidget->hide(); |
203 | |
204 | connect(sender: m_findWidget, signal: &FindWidget::findNext, receiver: this, slot: &CentralWidget::findNext); |
205 | connect(sender: m_findWidget, signal: &FindWidget::findPrevious, receiver: this, slot: &CentralWidget::findPrevious); |
206 | connect(sender: m_findWidget, signal: &FindWidget::find, receiver: this, slot: &CentralWidget::find); |
207 | connect(sender: m_findWidget, signal: &FindWidget::escapePressed, receiver: this, slot: &CentralWidget::activateTab); |
208 | connect(sender: m_tabBar, signal: &TabBar::addBookmark, receiver: this, slot: &CentralWidget::addBookmark); |
209 | } |
210 | |
211 | CentralWidget::~CentralWidget() |
212 | { |
213 | TRACE_OBJ |
214 | QStringList zoomFactors; |
215 | QStringList currentPages; |
216 | for (int i = 0; i < m_stackedWidget->count(); ++i) { |
217 | const HelpViewer * const viewer = viewerAt(index: i); |
218 | const QUrl &source = viewer->source(); |
219 | if (source.isValid()) { |
220 | currentPages << source.toString(); |
221 | zoomFactors << QString::number(viewer->scale()); |
222 | } |
223 | } |
224 | |
225 | HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); |
226 | helpEngine.setLastShownPages(currentPages); |
227 | helpEngine.setLastZoomFactors(zoomFactors); |
228 | helpEngine.setLastTabPage(m_stackedWidget->currentIndex()); |
229 | |
230 | #ifndef QT_NO_PRINTER |
231 | delete m_printer; |
232 | #endif |
233 | } |
234 | |
235 | CentralWidget *CentralWidget::instance() |
236 | { |
237 | TRACE_OBJ |
238 | return staticCentralWidget; |
239 | } |
240 | |
241 | QUrl CentralWidget::currentSource() const |
242 | { |
243 | TRACE_OBJ |
244 | return currentHelpViewer()->source(); |
245 | } |
246 | |
247 | QString CentralWidget::currentTitle() const |
248 | { |
249 | TRACE_OBJ |
250 | return currentHelpViewer()->title(); |
251 | } |
252 | |
253 | bool CentralWidget::hasSelection() const |
254 | { |
255 | TRACE_OBJ |
256 | return !currentHelpViewer()->selectedText().isEmpty(); |
257 | } |
258 | |
259 | bool CentralWidget::isForwardAvailable() const |
260 | { |
261 | TRACE_OBJ |
262 | return currentHelpViewer()->isForwardAvailable(); |
263 | } |
264 | |
265 | bool CentralWidget::isBackwardAvailable() const |
266 | { |
267 | TRACE_OBJ |
268 | return currentHelpViewer()->isBackwardAvailable(); |
269 | } |
270 | |
271 | HelpViewer* CentralWidget::viewerAt(int index) const |
272 | { |
273 | TRACE_OBJ |
274 | return static_cast<HelpViewer*>(m_stackedWidget->widget(index)); |
275 | } |
276 | |
277 | HelpViewer* CentralWidget::currentHelpViewer() const |
278 | { |
279 | TRACE_OBJ |
280 | return static_cast<HelpViewer *>(m_stackedWidget->currentWidget()); |
281 | } |
282 | |
283 | void CentralWidget::addPage(HelpViewer *page, bool fromSearch) |
284 | { |
285 | TRACE_OBJ |
286 | page->installEventFilter(filterObj: this); |
287 | page->setFocus(Qt::OtherFocusReason); |
288 | connectSignals(page); |
289 | const int index = m_stackedWidget->addWidget(w: page); |
290 | m_tabBar->setTabData(index: m_tabBar->addNewTab(title: page->title()), |
291 | data: QVariant::fromValue(value: viewerAt(index))); |
292 | connect(sender: page, signal: &HelpViewer::titleChanged, receiver: m_tabBar, slot: &TabBar::titleChanged); |
293 | |
294 | if (fromSearch) { |
295 | connect(sender: currentHelpViewer(), signal: &HelpViewer::loadFinished, |
296 | receiver: this, slot: &CentralWidget::highlightSearchTerms); |
297 | } |
298 | } |
299 | |
300 | void CentralWidget::removePage(int index) |
301 | { |
302 | TRACE_OBJ |
303 | const bool currentChanged = index == currentIndex(); |
304 | m_tabBar->removeTabAt(viewer: viewerAt(index)); |
305 | m_stackedWidget->removeWidget(w: m_stackedWidget->widget(index)); |
306 | if (currentChanged) |
307 | emit currentViewerChanged(); |
308 | } |
309 | |
310 | int CentralWidget::currentIndex() const |
311 | { |
312 | TRACE_OBJ |
313 | return m_stackedWidget->currentIndex(); |
314 | } |
315 | |
316 | void CentralWidget::setCurrentPage(HelpViewer *page) |
317 | { |
318 | TRACE_OBJ |
319 | m_tabBar->setCurrent(page); |
320 | m_stackedWidget->setCurrentWidget(page); |
321 | emit currentViewerChanged(); |
322 | } |
323 | |
324 | void CentralWidget::connectTabBar() |
325 | { |
326 | TRACE_OBJ |
327 | connect(sender: m_tabBar, signal: &TabBar::currentTabChanged, receiver: OpenPagesManager::instance(), |
328 | slot: QOverload<HelpViewer *>::of(ptr: &OpenPagesManager::setCurrentPage)); |
329 | } |
330 | |
331 | // -- public slots |
332 | |
333 | #if QT_CONFIG(clipboard) |
334 | void CentralWidget::copy() |
335 | { |
336 | TRACE_OBJ |
337 | currentHelpViewer()->copy(); |
338 | } |
339 | #endif |
340 | |
341 | void CentralWidget::home() |
342 | { |
343 | TRACE_OBJ |
344 | currentHelpViewer()->home(); |
345 | } |
346 | |
347 | void CentralWidget::zoomIn() |
348 | { |
349 | TRACE_OBJ |
350 | currentHelpViewer()->scaleUp(); |
351 | } |
352 | |
353 | void CentralWidget::zoomOut() |
354 | { |
355 | TRACE_OBJ |
356 | currentHelpViewer()->scaleDown(); |
357 | } |
358 | |
359 | void CentralWidget::resetZoom() |
360 | { |
361 | TRACE_OBJ |
362 | currentHelpViewer()->resetScale(); |
363 | } |
364 | |
365 | void CentralWidget::forward() |
366 | { |
367 | TRACE_OBJ |
368 | currentHelpViewer()->forward(); |
369 | } |
370 | |
371 | void CentralWidget::nextPage() |
372 | { |
373 | TRACE_OBJ |
374 | m_stackedWidget->setCurrentIndex((m_stackedWidget->currentIndex() + 1) |
375 | % m_stackedWidget->count()); |
376 | } |
377 | |
378 | void CentralWidget::backward() |
379 | { |
380 | TRACE_OBJ |
381 | currentHelpViewer()->backward(); |
382 | } |
383 | |
384 | void CentralWidget::previousPage() |
385 | { |
386 | TRACE_OBJ |
387 | m_stackedWidget->setCurrentIndex((m_stackedWidget->currentIndex() - 1) |
388 | % m_stackedWidget->count()); |
389 | } |
390 | |
391 | void CentralWidget::print() |
392 | { |
393 | TRACE_OBJ |
394 | #if !defined(QT_NO_PRINTER) && !defined(QT_NO_PRINTDIALOG) |
395 | initPrinter(); |
396 | QPrintDialog dlg(m_printer, this); |
397 | |
398 | if (!currentHelpViewer()->selectedText().isEmpty()) |
399 | dlg.addEnabledOption(option: QAbstractPrintDialog::PrintSelection); |
400 | dlg.addEnabledOption(option: QAbstractPrintDialog::PrintPageRange); |
401 | dlg.addEnabledOption(option: QAbstractPrintDialog::PrintCollateCopies); |
402 | dlg.setWindowTitle(tr(s: "Print Document" )); |
403 | if (dlg.exec() == QDialog::Accepted) |
404 | currentHelpViewer()->print(printer: m_printer); |
405 | #endif |
406 | } |
407 | |
408 | void CentralWidget::pageSetup() |
409 | { |
410 | TRACE_OBJ |
411 | #if !defined(QT_NO_PRINTER) && !defined(QT_NO_PRINTDIALOG) |
412 | initPrinter(); |
413 | QPageSetupDialog dlg(m_printer); |
414 | dlg.exec(); |
415 | #endif |
416 | } |
417 | |
418 | void CentralWidget::printPreview() |
419 | { |
420 | TRACE_OBJ |
421 | #if !defined(QT_NO_PRINTER) && !defined(QT_NO_PRINTDIALOG) |
422 | initPrinter(); |
423 | QPrintPreviewDialog preview(m_printer, this); |
424 | connect(sender: &preview, signal: &QPrintPreviewDialog::paintRequested, |
425 | receiver: this, slot: &CentralWidget::printPreviewToPrinter); |
426 | preview.exec(); |
427 | #endif |
428 | } |
429 | |
430 | void CentralWidget::setSource(const QUrl &url) |
431 | { |
432 | TRACE_OBJ |
433 | HelpViewer *viewer = currentHelpViewer(); |
434 | viewer->setSource(url); |
435 | viewer->setFocus(Qt::OtherFocusReason); |
436 | } |
437 | |
438 | void CentralWidget::setSourceFromSearch(const QUrl &url) |
439 | { |
440 | TRACE_OBJ |
441 | connect(sender: currentHelpViewer(), signal: &HelpViewer::loadFinished, |
442 | receiver: this, slot: &CentralWidget::highlightSearchTerms); |
443 | currentHelpViewer()->setSource(url); |
444 | currentHelpViewer()->setFocus(Qt::OtherFocusReason); |
445 | } |
446 | |
447 | void CentralWidget::findNext() |
448 | { |
449 | TRACE_OBJ |
450 | find(text: m_findWidget->text(), forward: true, incremental: false); |
451 | } |
452 | |
453 | void CentralWidget::findPrevious() |
454 | { |
455 | TRACE_OBJ |
456 | find(text: m_findWidget->text(), forward: false, incremental: false); |
457 | } |
458 | |
459 | void CentralWidget::find(const QString &ttf, bool forward, bool incremental) |
460 | { |
461 | TRACE_OBJ |
462 | bool found = false; |
463 | if (HelpViewer *viewer = currentHelpViewer()) { |
464 | HelpViewer::FindFlags flags; |
465 | if (!forward) |
466 | flags |= HelpViewer::FindBackward; |
467 | if (m_findWidget->caseSensitive()) |
468 | flags |= HelpViewer::FindCaseSensitively; |
469 | found = viewer->findText(text: ttf, flags, incremental, fromSearch: false); |
470 | } |
471 | |
472 | if (!found && ttf.isEmpty()) |
473 | found = true; // the line edit is empty, no need to mark it red... |
474 | |
475 | if (!m_findWidget->isVisible()) |
476 | m_findWidget->show(); |
477 | m_findWidget->setPalette(found); |
478 | } |
479 | |
480 | void CentralWidget::activateTab() |
481 | { |
482 | TRACE_OBJ |
483 | currentHelpViewer()->setFocus(); |
484 | } |
485 | |
486 | void CentralWidget::showTextSearch() |
487 | { |
488 | TRACE_OBJ |
489 | m_findWidget->show(); |
490 | } |
491 | |
492 | void CentralWidget::updateBrowserFont() |
493 | { |
494 | TRACE_OBJ |
495 | const int count = m_stackedWidget->count(); |
496 | const QFont &font = viewerAt(index: count - 1)->viewerFont(); |
497 | for (int i = 0; i < count; ++i) |
498 | viewerAt(index: i)->setViewerFont(font); |
499 | } |
500 | |
501 | void CentralWidget::updateUserInterface() |
502 | { |
503 | m_tabBar->setVisible(HelpEngineWrapper::instance().showTabs()); |
504 | } |
505 | |
506 | // -- protected |
507 | |
508 | void CentralWidget::keyPressEvent(QKeyEvent *e) |
509 | { |
510 | TRACE_OBJ |
511 | const QString &text = e->text(); |
512 | if (text.startsWith(c: QLatin1Char('/'))) { |
513 | if (!m_findWidget->isVisible()) { |
514 | m_findWidget->showAndClear(); |
515 | } else { |
516 | m_findWidget->show(); |
517 | } |
518 | } else { |
519 | QWidget::keyPressEvent(event: e); |
520 | } |
521 | } |
522 | |
523 | void CentralWidget::focusInEvent(QFocusEvent * /* event */) |
524 | { |
525 | TRACE_OBJ |
526 | // If we have a current help viewer then this is the 'focus proxy', |
527 | // otherwise it's the central widget. This is needed, so an embedding |
528 | // program can just set the focus to the central widget and it does |
529 | // The Right Thing(TM) |
530 | QWidget *receiver = m_stackedWidget; |
531 | if (HelpViewer *viewer = currentHelpViewer()) |
532 | receiver = viewer; |
533 | QTimer::singleShot(interval: 1, receiver, |
534 | slot: QOverload<>::of(ptr: &QWidget::setFocus)); |
535 | } |
536 | |
537 | // -- private slots |
538 | |
539 | void CentralWidget::highlightSearchTerms() |
540 | { |
541 | TRACE_OBJ |
542 | QHelpSearchEngine *searchEngine = |
543 | HelpEngineWrapper::instance().searchEngine(); |
544 | const QString searchInput = searchEngine->searchInput(); |
545 | const bool wholePhrase = searchInput.startsWith(c: QLatin1Char('"')) && |
546 | searchInput.endsWith(c: QLatin1Char('"')); |
547 | const QStringList &words = wholePhrase ? QStringList(searchInput.mid(position: 1, n: searchInput.length() - 2)) : |
548 | searchInput.split(sep: QRegExp("\\W+" ), behavior: Qt::SkipEmptyParts); |
549 | HelpViewer *viewer = currentHelpViewer(); |
550 | for (const QString &word : words) |
551 | viewer->findText(text: word, flags: {}, incremental: false, fromSearch: true); |
552 | disconnect(sender: viewer, signal: &HelpViewer::loadFinished, |
553 | receiver: this, slot: &CentralWidget::highlightSearchTerms); |
554 | } |
555 | |
556 | void CentralWidget::printPreviewToPrinter(QPrinter *p) |
557 | { |
558 | TRACE_OBJ |
559 | #ifndef QT_NO_PRINTER |
560 | currentHelpViewer()->print(printer: p); |
561 | #endif |
562 | } |
563 | |
564 | void CentralWidget::handleSourceChanged(const QUrl &url) |
565 | { |
566 | TRACE_OBJ |
567 | if (sender() == currentHelpViewer()) |
568 | emit sourceChanged(url); |
569 | } |
570 | |
571 | void CentralWidget::slotHighlighted(const QUrl &link) |
572 | { |
573 | TRACE_OBJ |
574 | QUrl resolvedLink = m_resolvedLinks.value(akey: link); |
575 | if (!link.isEmpty() && resolvedLink.isEmpty()) { |
576 | resolvedLink = HelpEngineWrapper::instance().findFile(url: link); |
577 | m_resolvedLinks.insert(akey: link, avalue: resolvedLink); |
578 | } |
579 | emit highlighted(link: resolvedLink); |
580 | } |
581 | |
582 | // -- private |
583 | |
584 | void CentralWidget::initPrinter() |
585 | { |
586 | TRACE_OBJ |
587 | #ifndef QT_NO_PRINTER |
588 | if (!m_printer) |
589 | m_printer = new QPrinter(QPrinter::HighResolution); |
590 | #endif |
591 | } |
592 | |
593 | void CentralWidget::connectSignals(HelpViewer *page) |
594 | { |
595 | TRACE_OBJ |
596 | #if defined(BROWSER_QTWEBKIT) |
597 | connect(page, &HelpViewer::printRequested, |
598 | this, &CentralWidget::print); |
599 | #endif |
600 | #if QT_CONFIG(clipboard) |
601 | connect(sender: page, signal: &HelpViewer::copyAvailable, |
602 | receiver: this, slot: &CentralWidget::copyAvailable); |
603 | #endif |
604 | connect(sender: page, signal: &HelpViewer::forwardAvailable, |
605 | receiver: this, slot: &CentralWidget::forwardAvailable); |
606 | connect(sender: page, signal: &HelpViewer::backwardAvailable, |
607 | receiver: this, slot: &CentralWidget::backwardAvailable); |
608 | connect(sender: page, signal: &HelpViewer::sourceChanged, |
609 | receiver: this, slot: &CentralWidget::handleSourceChanged); |
610 | connect(sender: page, signal: QOverload<const QUrl &>::of(ptr: &HelpViewer::highlighted), |
611 | receiver: this, slot: &CentralWidget::slotHighlighted); |
612 | } |
613 | |
614 | bool CentralWidget::eventFilter(QObject *object, QEvent *e) |
615 | { |
616 | TRACE_OBJ |
617 | if (e->type() != QEvent::KeyPress) |
618 | return QWidget::eventFilter(watched: object, event: e); |
619 | |
620 | HelpViewer *viewer = currentHelpViewer(); |
621 | QKeyEvent *keyEvent = static_cast<QKeyEvent*> (e); |
622 | if (viewer == object && keyEvent->key() == Qt::Key_Backspace) { |
623 | if (viewer->isBackwardAvailable()) { |
624 | #if defined(BROWSER_QTWEBKIT) |
625 | // this helps in case there is an html <input> field |
626 | if (!viewer->hasFocus()) |
627 | #endif // BROWSER_QTWEBKIT |
628 | viewer->backward(); |
629 | } |
630 | } |
631 | return QWidget::eventFilter(watched: object, event: e); |
632 | } |
633 | |
634 | QT_END_NAMESPACE |
635 | |