VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/helpbrowser/UIHelpViewer.cpp@ 88418

Last change on this file since 88418 was 88418, checked in by vboxsync, 4 years ago

FE/Qt: bugref:9831. Resizing images along side with font.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.8 KB
Line 
1/* $Id: UIHelpViewer.cpp 88418 2021-04-08 14:05:51Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIHelpBrowserWidget class implementation.
4 */
5
6/*
7 * Copyright (C) 2010-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/* Qt includes: */
19#include <QClipboard>
20#include <QtGlobal>
21#ifdef VBOX_WITH_QHELP_VIEWER
22 #include <QtHelp/QHelpEngine>
23 #include <QtHelp/QHelpContentWidget>
24 #include <QtHelp/QHelpIndexWidget>
25 #include <QtHelp/QHelpSearchEngine>
26 #include <QtHelp/QHelpSearchQueryWidget>
27 #include <QtHelp/QHelpSearchResultWidget>
28#endif
29#include <QLabel>
30#include <QMenu>
31#include <QHBoxLayout>
32#include <QScrollBar>
33#include <QTextBlock>
34#include <QWidgetAction>
35#ifdef RT_OS_SOLARIS
36# include <QFontDatabase>
37#endif
38
39/* GUI includes: */
40#include "QIToolButton.h"
41#include "UIHelpViewer.h"
42#include "UIHelpBrowserWidget.h"
43#include "UIIconPool.h"
44#include "UISearchLineEdit.h"
45
46/* COM includes: */
47#include "COMEnums.h"
48#include "CSystemProperties.h"
49
50#ifdef VBOX_WITH_QHELP_VIEWER
51
52static int iZoomPercentageStep = 20;
53const QPair<int, int> UIHelpViewer::zoomPercentageMinMax = QPair<int, int>(20, 300);
54
55
56/*********************************************************************************************************************************
57* UIContextMenuNavigationAction definition. *
58*********************************************************************************************************************************/
59class UIContextMenuNavigationAction : public QWidgetAction
60{
61
62 Q_OBJECT;
63
64signals:
65
66 void sigGoBackward();
67 void sigGoForward();
68 void sigGoHome();
69 void sigAddBookmark();
70
71public:
72
73 UIContextMenuNavigationAction(QObject *pParent = 0);
74 void setBackwardAvailable(bool fAvailable);
75 void setForwardAvailable(bool fAvailable);
76
77protected:
78
79
80private slots:
81
82
83private:
84
85 void prepare();
86 QIToolButton *m_pBackwardButton;
87 QIToolButton *m_pForwardButton;
88 QIToolButton *m_pHomeButton;
89 QIToolButton *m_pAddBookmarkButton;
90};
91
92/*********************************************************************************************************************************
93* UIFindInPageWidget definition. *
94*********************************************************************************************************************************/
95class UIFindInPageWidget : public QIWithRetranslateUI<QWidget>
96{
97
98 Q_OBJECT;
99
100signals:
101
102 void sigDragging(const QPoint &delta);
103 void sigSearchTextChanged(const QString &strSearchText);
104 void sigSelectNextMatch();
105 void sigSelectPreviousMatch();
106 void sigClose();
107
108public:
109
110 UIFindInPageWidget(QWidget *pParent = 0);
111 void setMatchCountAndCurrentIndex(int iTotalMatchCount, int iCurrentlyScrolledIndex);
112 void clearSearchField();
113
114protected:
115
116 virtual bool eventFilter(QObject *pObject, QEvent *pEvent) /* override */;
117 virtual void keyPressEvent(QKeyEvent *pEvent) /* override */;
118
119private:
120
121 void prepare();
122 void retranslateUi();
123 UISearchLineEdit *m_pSearchLineEdit;
124 QIToolButton *m_pNextButton;
125 QIToolButton *m_pPreviousButton;
126 QIToolButton *m_pCloseButton;
127 QLabel *m_pDragMoveLabel;
128 QPoint m_previousMousePosition;
129};
130
131
132/*********************************************************************************************************************************
133* UIContextMenuNavigationAction implementation. *
134*********************************************************************************************************************************/
135UIContextMenuNavigationAction::UIContextMenuNavigationAction(QObject *pParent /* = 0 */)
136 :QWidgetAction(pParent)
137 , m_pBackwardButton(0)
138 , m_pForwardButton(0)
139 , m_pHomeButton(0)
140 , m_pAddBookmarkButton(0)
141{
142 prepare();
143}
144
145void UIContextMenuNavigationAction::setBackwardAvailable(bool fAvailable)
146{
147 if (m_pBackwardButton)
148 m_pBackwardButton->setEnabled(fAvailable);
149}
150
151void UIContextMenuNavigationAction::setForwardAvailable(bool fAvailable)
152{
153 if (m_pForwardButton)
154 m_pForwardButton->setEnabled(fAvailable);
155}
156
157void UIContextMenuNavigationAction::prepare()
158{
159 QWidget *pWidget = new QWidget;
160 setDefaultWidget(pWidget);
161 QHBoxLayout *pMainLayout = new QHBoxLayout(pWidget);
162 AssertReturnVoid(pMainLayout);
163
164 m_pBackwardButton = new QIToolButton;
165 m_pForwardButton = new QIToolButton;
166 m_pHomeButton = new QIToolButton;
167 m_pAddBookmarkButton = new QIToolButton;
168
169 AssertReturnVoid(m_pBackwardButton &&
170 m_pForwardButton &&
171 m_pHomeButton);
172 m_pForwardButton->setEnabled(false);
173 m_pBackwardButton->setEnabled(false);
174 m_pHomeButton->setIcon(UIIconPool::iconSet(":/help_browser_home_32px.png"));
175 m_pForwardButton->setIcon(UIIconPool::iconSet(":/help_browser_forward_32px.png", ":/help_browser_forward_disabled_32px.png"));
176 m_pBackwardButton->setIcon(UIIconPool::iconSet(":/help_browser_backward_32px.png", ":/help_browser_backward_disabled_32px.png"));
177 m_pAddBookmarkButton->setIcon(UIIconPool::iconSet(":/help_browser_add_bookmark.png"));
178
179 pMainLayout->addWidget(m_pBackwardButton);
180 pMainLayout->addWidget(m_pForwardButton);
181 pMainLayout->addWidget(m_pHomeButton);
182 pMainLayout->addWidget(m_pAddBookmarkButton);
183 pMainLayout->setContentsMargins(0, 0, 0, 0);
184 //pMainLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed));
185
186 connect(m_pBackwardButton, &QIToolButton::pressed,
187 this, &UIContextMenuNavigationAction::sigGoBackward);
188 connect(m_pForwardButton, &QIToolButton::pressed,
189 this, &UIContextMenuNavigationAction::sigGoForward);
190 connect(m_pHomeButton, &QIToolButton::pressed,
191 this, &UIContextMenuNavigationAction::sigGoHome);
192 connect(m_pAddBookmarkButton, &QIToolButton::pressed,
193 this, &UIContextMenuNavigationAction::sigAddBookmark);
194}
195
196
197/*********************************************************************************************************************************
198* UIFindInPageWidget implementation. *
199*********************************************************************************************************************************/
200UIFindInPageWidget::UIFindInPageWidget(QWidget *pParent /* = 0 */)
201 : QIWithRetranslateUI<QWidget>(pParent)
202 , m_pSearchLineEdit(0)
203 , m_pNextButton(0)
204 , m_pPreviousButton(0)
205 , m_pCloseButton(0)
206 , m_previousMousePosition(-1, -1)
207{
208 prepare();
209}
210
211void UIFindInPageWidget::setMatchCountAndCurrentIndex(int iTotalMatchCount, int iCurrentlyScrolledIndex)
212{
213 if (!m_pSearchLineEdit)
214 return;
215 m_pSearchLineEdit->setMatchCount(iTotalMatchCount);
216 m_pSearchLineEdit->setScrollToIndex(iCurrentlyScrolledIndex);
217}
218
219void UIFindInPageWidget::clearSearchField()
220{
221 if (!m_pSearchLineEdit)
222 return;
223 m_pSearchLineEdit->blockSignals(true);
224 m_pSearchLineEdit->reset();
225 m_pSearchLineEdit->blockSignals(false);
226}
227
228bool UIFindInPageWidget::eventFilter(QObject *pObject, QEvent *pEvent)
229{
230 if (pObject == m_pDragMoveLabel)
231 {
232 if (pEvent->type() == QEvent::Enter)
233 m_pDragMoveLabel->setCursor(Qt::CrossCursor);
234 else if (pEvent->type() == QEvent::Leave)
235 {
236 if (parentWidget())
237 m_pDragMoveLabel->setCursor(parentWidget()->cursor());
238 }
239 else if (pEvent->type() == QEvent::MouseMove)
240 {
241 QMouseEvent *pMouseEvent = static_cast<QMouseEvent*>(pEvent);
242 if (pMouseEvent->buttons() == Qt::LeftButton)
243 {
244 if (m_previousMousePosition != QPoint(-1, -1))
245 emit sigDragging(pMouseEvent->globalPos() - m_previousMousePosition);
246 m_previousMousePosition = pMouseEvent->globalPos();
247 m_pDragMoveLabel->setCursor(Qt::ClosedHandCursor);
248 }
249 }
250 else if (pEvent->type() == QEvent::MouseButtonRelease)
251 {
252 m_previousMousePosition = QPoint(-1, -1);
253 m_pDragMoveLabel->setCursor(Qt::CrossCursor);
254 }
255 }
256 return QIWithRetranslateUI<QWidget>::eventFilter(pObject, pEvent);
257}
258
259void UIFindInPageWidget::keyPressEvent(QKeyEvent *pEvent)
260{
261 switch (pEvent->key())
262 {
263 case Qt::Key_Escape:
264 emit sigClose();
265 return;
266 break;
267 case Qt::Key_Down:
268 emit sigSelectNextMatch();
269 return;
270 break;
271 case Qt::Key_Up:
272 emit sigSelectPreviousMatch();
273 return;
274 break;
275 default:
276 QIWithRetranslateUI<QWidget>::keyPressEvent(pEvent);
277 break;
278 }
279}
280
281void UIFindInPageWidget::prepare()
282{
283 setAutoFillBackground(true);
284 setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum);
285
286 QHBoxLayout *pLayout = new QHBoxLayout(this);
287 m_pSearchLineEdit = new UISearchLineEdit;
288 AssertReturnVoid(pLayout && m_pSearchLineEdit);
289 setFocusProxy(m_pSearchLineEdit);
290 QFontMetrics fontMetric(m_pSearchLineEdit->font());
291 setMinimumSize(40 * fontMetric.width("x"),
292 fontMetric.height() +
293 qApp->style()->pixelMetric(QStyle::PM_LayoutBottomMargin) +
294 qApp->style()->pixelMetric(QStyle::PM_LayoutTopMargin));
295
296 connect(m_pSearchLineEdit, &UISearchLineEdit::textChanged,
297 this, &UIFindInPageWidget::sigSearchTextChanged);
298
299 m_pDragMoveLabel = new QLabel;
300 AssertReturnVoid(m_pDragMoveLabel);
301 m_pDragMoveLabel->installEventFilter(this);
302 m_pDragMoveLabel->setPixmap(QPixmap(":/drag_move_16px.png"));
303 pLayout->addWidget(m_pDragMoveLabel);
304
305
306 pLayout->setSpacing(0);
307 pLayout->addWidget(m_pSearchLineEdit);
308
309 m_pPreviousButton = new QIToolButton;
310 m_pNextButton = new QIToolButton;
311 m_pCloseButton = new QIToolButton;
312
313 pLayout->addWidget(m_pPreviousButton);
314 pLayout->addWidget(m_pNextButton);
315 pLayout->addWidget(m_pCloseButton);
316
317 m_pPreviousButton->setIcon(UIIconPool::iconSet(":/arrow_up_10px.png"));
318 m_pNextButton->setIcon(UIIconPool::iconSet(":/arrow_down_10px.png"));
319 m_pCloseButton->setIcon(UIIconPool::iconSet(":/close_16px.png"));
320
321 connect(m_pPreviousButton, &QIToolButton::pressed, this, &UIFindInPageWidget::sigSelectPreviousMatch);
322 connect(m_pNextButton, &QIToolButton::pressed, this, &UIFindInPageWidget::sigSelectNextMatch);
323 connect(m_pCloseButton, &QIToolButton::pressed, this, &UIFindInPageWidget::sigClose);
324}
325
326void UIFindInPageWidget::retranslateUi()
327{
328}
329
330
331/*********************************************************************************************************************************
332* UIHelpViewer implementation. *
333*********************************************************************************************************************************/
334
335UIHelpViewer::UIHelpViewer(const QHelpEngine *pHelpEngine, QWidget *pParent /* = 0 */)
336 :QIWithRetranslateUI<QTextBrowser>(pParent)
337 , m_pHelpEngine(pHelpEngine)
338 , m_pFindInPageWidget(new UIFindInPageWidget(this))
339 , m_fFindWidgetDragged(false)
340 , m_iMarginForFindWidget(qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin))
341 , m_iSelectedMatchIndex(0)
342 , m_iSearchTermLength(0)
343 , m_iZoomPercentage(100)
344{
345 m_iInitialFontPointSize = font().pointSize();
346 setUndoRedoEnabled(true);
347 connect(m_pFindInPageWidget, &UIFindInPageWidget::sigDragging,
348 this, &UIHelpViewer::sltHandleFindWidgetDrag);
349 connect(m_pFindInPageWidget, &UIFindInPageWidget::sigSearchTextChanged,
350 this, &UIHelpViewer::sltHandleFindInPageSearchTextChange);
351
352 connect(m_pFindInPageWidget, &UIFindInPageWidget::sigSelectPreviousMatch,
353 this, &UIHelpViewer::sltSelectPreviousMatch);
354 connect(m_pFindInPageWidget, &UIFindInPageWidget::sigSelectNextMatch,
355 this, &UIHelpViewer::sltSelectNextMatch);
356 connect(m_pFindInPageWidget, &UIFindInPageWidget::sigClose,
357 this, &UIHelpViewer::sigCloseFindInPageWidget);
358
359 m_pFindInPageWidget->setVisible(false);
360 retranslateUi();
361}
362
363QVariant UIHelpViewer::loadResource(int type, const QUrl &name)
364{
365 if (name.scheme() == "qthelp" && m_pHelpEngine)
366 return QVariant(m_pHelpEngine->fileData(name));
367 else
368 return QTextBrowser::loadResource(type, name);
369}
370
371void UIHelpViewer::emitHistoryChangedSignal()
372{
373 emit historyChanged();
374 emit backwardAvailable(true);
375}
376
377void UIHelpViewer::setSource(const QUrl &url)
378{
379 QTextBrowser::setSource(url);
380 QTextDocument *pDocument = document();
381 iterateDocumentImages();
382 if (!pDocument || pDocument->isEmpty())
383 {
384 setText(tr("<div><p><h3>404. Not found.</h3>The page <b>%1</b> could not be found.</p></div>").arg(url.toString()));
385 }
386 if (m_pFindInPageWidget && m_pFindInPageWidget->isVisible())
387 {
388 document()->undo();
389 m_pFindInPageWidget->clearSearchField();
390 }
391 scaleImages();
392}
393
394void UIHelpViewer::sltToggleFindInPageWidget(bool fVisible)
395{
396 if (!m_pFindInPageWidget)
397 return;
398 /* Closing the find in page widget causes QTextBrowser to jump to the top of the document. This hack puts it back into position: */
399 int iPosition = verticalScrollBar()->value();
400 m_iMarginForFindWidget = verticalScrollBar()->width() +
401 qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin);
402 /* Try to position the widget somewhere meaningful initially: */
403 if (!m_fFindWidgetDragged)
404 m_pFindInPageWidget->move(width() - m_iMarginForFindWidget - m_pFindInPageWidget->width(),
405 m_iMarginForFindWidget);
406
407 m_pFindInPageWidget->setVisible(fVisible);
408
409 if (!fVisible)
410 {
411 document()->undo();
412 m_pFindInPageWidget->clearSearchField();
413 verticalScrollBar()->setValue(iPosition);
414 }
415 else
416 m_pFindInPageWidget->setFocus();
417}
418
419void UIHelpViewer::setFont(const QFont &font)
420{
421 QIWithRetranslateUI<QTextBrowser>::setFont(font);
422 /* Make sure the font size of the find in widget stays constant: */
423 if (m_pFindInPageWidget)
424 {
425 QFont wFont(font);
426 wFont.setPointSize(m_iInitialFontPointSize);
427 m_pFindInPageWidget->setFont(wFont);
428 }
429}
430
431bool UIHelpViewer::isFindInPageWidgetVisible() const
432{
433 if (m_pFindInPageWidget)
434 return m_pFindInPageWidget->isVisible();
435 return false;
436}
437
438void UIHelpViewer::zoom(ZoomOperation enmZoomOperation)
439{
440 int iPrevZoom = m_iZoomPercentage;
441 switch (enmZoomOperation)
442 {
443 case ZoomOperation_In:
444 iPrevZoom += iZoomPercentageStep;
445 break;
446 case ZoomOperation_Out:
447 iPrevZoom -= iZoomPercentageStep;
448 break;
449 case ZoomOperation_Reset:
450 default:
451 iPrevZoom = 100;
452 break;
453 }
454 setZoomPercentage(iPrevZoom);
455}
456
457void UIHelpViewer::setZoomPercentage(int iZoomPercentage)
458{
459 if (iZoomPercentage > zoomPercentageMinMax.second ||
460 iZoomPercentage < zoomPercentageMinMax.first ||
461 m_iZoomPercentage == iZoomPercentage)
462 return;
463
464 m_iZoomPercentage = iZoomPercentage;
465 scaleFont();
466 scaleImages();
467 emit sigZoomPercentageChanged(m_iZoomPercentage);
468}
469
470
471int UIHelpViewer::zoomPercentage() const
472{
473 return m_iZoomPercentage;
474}
475
476void UIHelpViewer::contextMenuEvent(QContextMenuEvent *event)
477{
478 QMenu pMenu;
479
480 UIContextMenuNavigationAction *pNavigationActions = new UIContextMenuNavigationAction;
481 pNavigationActions->setBackwardAvailable(isBackwardAvailable());
482 pNavigationActions->setForwardAvailable(isForwardAvailable());
483
484 connect(pNavigationActions, &UIContextMenuNavigationAction::sigGoBackward,
485 this, &UIHelpViewer::sigGoBackward);
486 connect(pNavigationActions, &UIContextMenuNavigationAction::sigGoForward,
487 this, &UIHelpViewer::sigGoForward);
488 connect(pNavigationActions, &UIContextMenuNavigationAction::sigGoHome,
489 this, &UIHelpViewer::sigGoHome);
490 connect(pNavigationActions, &UIContextMenuNavigationAction::sigAddBookmark,
491 this, &UIHelpViewer::sigAddBookmark);
492
493 QAction *pOpenLinkAction = new QAction(UIHelpBrowserWidget::tr("Open Link"));
494 connect(pOpenLinkAction, &QAction::triggered,
495 this, &UIHelpViewer::sltHandleOpenLink);
496
497 QAction *pOpenInNewTabAction = new QAction(UIHelpBrowserWidget::tr("Open Link in New Tab"));
498 connect(pOpenInNewTabAction, &QAction::triggered,
499 this, &UIHelpViewer::sltHandleOpenLinkInNewTab);
500
501 QAction *pCopyLink = new QAction(UIHelpBrowserWidget::tr("Copy Link"));
502 connect(pCopyLink, &QAction::triggered,
503 this, &UIHelpViewer::sltHandleCopyLink);
504
505
506 QAction *pFindInPage = new QAction(UIHelpBrowserWidget::tr("Find in Page"));
507 pFindInPage->setCheckable(true);
508 if (m_pFindInPageWidget)
509 pFindInPage->setChecked(m_pFindInPageWidget->isVisible());
510 connect(pFindInPage, &QAction::toggled, this, &UIHelpViewer::sltToggleFindInPageWidget);
511
512 pMenu.addAction(pNavigationActions);
513 pMenu.addAction(pOpenLinkAction);
514 pMenu.addAction(pOpenInNewTabAction);
515 pMenu.addAction(pCopyLink);
516 pMenu.addAction(pFindInPage);
517
518 QString strAnchor = anchorAt(event->pos());
519 if (!strAnchor.isEmpty())
520 {
521 QString strLink = source().resolved(anchorAt(event->pos())).toString();
522 pOpenLinkAction->setData(strLink);
523 pOpenInNewTabAction->setData(strLink);
524 pCopyLink->setData(strLink);
525 }
526 else
527 {
528 pOpenLinkAction->setEnabled(false);
529 pOpenInNewTabAction->setEnabled(false);
530 pCopyLink->setEnabled(false);
531 }
532 pMenu.exec(event->globalPos());
533}
534
535void UIHelpViewer::resizeEvent(QResizeEvent *pEvent)
536{
537 /* Make sure the widget stays inside the parent during parent resize: */
538 if (m_pFindInPageWidget)
539 {
540 if (!isRectInside(m_pFindInPageWidget->geometry(), m_iMarginForFindWidget))
541 moveFindWidgetIn(m_iMarginForFindWidget);
542 }
543 QIWithRetranslateUI<QTextBrowser>::resizeEvent(pEvent);
544}
545
546void UIHelpViewer::wheelEvent(QWheelEvent *pEvent)
547{
548 /* QTextBrowser::wheelEvent scales font when some modifiers are pressed. We dont want: */
549 if (pEvent && pEvent->modifiers() == Qt::NoModifier)
550 QTextBrowser::wheelEvent(pEvent);
551}
552
553void UIHelpViewer::mousePressEvent(QMouseEvent *pEvent)
554{
555 QString strAnchor = anchorAt(pEvent->pos());
556 if (!strAnchor.isEmpty())
557 {
558 if (pEvent->modifiers() & Qt::ControlModifier)
559 {
560 QString strLink = source().resolved(strAnchor).toString();
561 emit sigOpenLinkInNewTab(strLink, true);
562 return;
563 }
564 }
565 QIWithRetranslateUI<QTextBrowser>::mousePressEvent(pEvent);
566}
567
568void UIHelpViewer::retranslateUi()
569{
570}
571
572void UIHelpViewer::moveFindWidgetIn(int iMargin)
573{
574 if (!m_pFindInPageWidget)
575 return;
576
577 QRect rect = m_pFindInPageWidget->geometry();
578 if (rect.left() < iMargin)
579 rect.translate(-rect.left() + iMargin, 0);
580 if (rect.right() > width() - iMargin)
581 rect.translate((width() - iMargin - rect.right()), 0);
582 if (rect.top() < iMargin)
583 rect.translate(0, -rect.top() + iMargin);
584
585 if (rect.bottom() > height() - iMargin)
586 rect.translate(0, (height() - iMargin - rect.bottom()));
587 m_pFindInPageWidget->setGeometry(rect);
588 m_pFindInPageWidget->update();
589}
590
591bool UIHelpViewer::isRectInside(const QRect &rect, int iMargin) const
592{
593 if (rect.left() < iMargin || rect.top() < iMargin)
594 return false;
595 if (rect.right() > width() - iMargin || rect.bottom() > height() - iMargin)
596 return false;
597 return true;
598}
599
600void UIHelpViewer::findAllMatches(const QString &searchString)
601{
602 QTextDocument *pDocument = document();
603 AssertReturnVoid(pDocument);
604
605 m_matchedCursorPosition.clear();
606 if (searchString.isEmpty())
607 return;
608 QTextCursor cursor(pDocument);
609 QTextDocument::FindFlags flags;
610 int iMatchCount = 0;
611 while (!cursor.isNull() && !cursor.atEnd())
612 {
613 cursor = pDocument->find(searchString, cursor, flags);
614 if (!cursor.isNull())
615 {
616 m_matchedCursorPosition << cursor.position() - searchString.length();
617 ++iMatchCount;
618 }
619 }
620}
621
622void UIHelpViewer::highlightFinds(int iSearchTermLength)
623{
624 QTextDocument* pDocument = document();
625 AssertReturnVoid(pDocument);
626 /* Clear previous highlight: */
627 pDocument->undo();
628
629 QTextCursor highlightCursor(pDocument);
630 QTextCursor cursor(pDocument);
631 cursor.beginEditBlock();
632 for (int i = 0; i < m_matchedCursorPosition.size(); ++i)
633 {
634 highlightCursor.setPosition(m_matchedCursorPosition[i]);
635
636 QTextCharFormat colorFormat(highlightCursor.charFormat());
637 colorFormat.setBackground(Qt::yellow);
638
639 highlightCursor.setPosition(m_matchedCursorPosition[i] + iSearchTermLength, QTextCursor::KeepAnchor);
640 if (!highlightCursor.isNull())
641 highlightCursor.setCharFormat(colorFormat);
642 }
643 cursor.endEditBlock();
644}
645
646void UIHelpViewer::selectMatch(int iMatchIndex, int iSearchStringLength)
647{
648 QTextCursor cursor = textCursor();
649 /* Move the cursor to the beginning of the matched string: */
650 cursor.setPosition(m_matchedCursorPosition.at(iMatchIndex), QTextCursor::MoveAnchor);
651 /* Move the cursor to the end of the matched string while keeping the anchor at the begining thus selecting the text: */
652 cursor.setPosition(m_matchedCursorPosition.at(iMatchIndex) + iSearchStringLength, QTextCursor::KeepAnchor);
653 ensureCursorVisible();
654 setTextCursor(cursor);
655}
656
657void UIHelpViewer::sltHandleOpenLinkInNewTab()
658{
659 QAction *pSender = qobject_cast<QAction*>(sender());
660 if (!pSender)
661 return;
662 QUrl url = pSender->data().toUrl();
663 if (url.isValid())
664 emit sigOpenLinkInNewTab(url, false);
665}
666
667void UIHelpViewer::sltHandleOpenLink()
668{
669 QAction *pSender = qobject_cast<QAction*>(sender());
670 if (!pSender)
671 return;
672 QUrl url = pSender->data().toUrl();
673 if (url.isValid())
674 QTextBrowser::setSource(url);
675}
676
677void UIHelpViewer::sltHandleCopyLink()
678{
679 QAction *pSender = qobject_cast<QAction*>(sender());
680 if (!pSender)
681 return;
682 QUrl url = pSender->data().toUrl();
683 if (url.isValid())
684 {
685 QClipboard *pClipboard = QApplication::clipboard();
686 if (pClipboard)
687 pClipboard->setText(url.toString());
688 }
689}
690
691void UIHelpViewer::sltHandleFindWidgetDrag(const QPoint &delta)
692{
693 if (!m_pFindInPageWidget)
694 return;
695 QRect geo = m_pFindInPageWidget->geometry();
696 geo.translate(delta);
697
698 /* Allow the move if m_pFindInPageWidget stays inside after the move: */
699 if (isRectInside(geo, m_iMarginForFindWidget))
700 m_pFindInPageWidget->move(m_pFindInPageWidget->pos() + delta);
701 m_fFindWidgetDragged = true;
702 update();
703}
704
705void UIHelpViewer::sltHandleFindInPageSearchTextChange(const QString &strSearchText)
706{
707 m_iSearchTermLength = strSearchText.length();
708 findAllMatches(strSearchText);
709 highlightFinds(m_iSearchTermLength);
710 //scrollToMatch(int iMatchIndex);
711 selectMatch(0, m_iSearchTermLength);
712 if (m_pFindInPageWidget)
713 m_pFindInPageWidget->setMatchCountAndCurrentIndex(m_matchedCursorPosition.size(), 0);
714}
715
716void UIHelpViewer::sltSelectPreviousMatch()
717{
718 m_iSelectedMatchIndex = m_iSelectedMatchIndex <= 0 ? m_matchedCursorPosition.size() - 1 : (m_iSelectedMatchIndex - 1);
719 selectMatch(m_iSelectedMatchIndex, m_iSearchTermLength);
720 if (m_pFindInPageWidget)
721 m_pFindInPageWidget->setMatchCountAndCurrentIndex(m_matchedCursorPosition.size(), m_iSelectedMatchIndex);
722}
723
724void UIHelpViewer::sltSelectNextMatch()
725{
726 m_iSelectedMatchIndex = m_iSelectedMatchIndex >= m_matchedCursorPosition.size() - 1 ? 0 : (m_iSelectedMatchIndex + 1);
727 selectMatch(m_iSelectedMatchIndex, m_iSearchTermLength);
728 if (m_pFindInPageWidget)
729 m_pFindInPageWidget->setMatchCountAndCurrentIndex(m_matchedCursorPosition.size(), m_iSelectedMatchIndex);
730}
731
732void UIHelpViewer::iterateDocumentImages()
733{
734 m_imageMap.clear();
735 QTextCursor cursor = textCursor();
736 cursor.movePosition(QTextCursor::Start);
737 while (!cursor.atEnd())
738 {
739 cursor.movePosition(QTextCursor::NextCharacter);
740 if (cursor.charFormat().isImageFormat())
741 {
742 DocumentImage image;
743 QTextImageFormat imageFormat = cursor.charFormat().toImageFormat();
744 image.m_fInitialWidth = imageFormat.width();
745 image.m_iPosition = cursor.position();
746 m_imageMap[imageFormat.name()] = image;
747 }
748 }
749}
750
751void UIHelpViewer::scaleFont()
752{
753 QFont mFont = font();
754 mFont.setPointSize(m_iInitialFontPointSize * m_iZoomPercentage / 100.);
755 setFont(mFont);
756}
757
758void UIHelpViewer::scaleImages()
759{
760 for (QMap<QString, DocumentImage>::iterator iterator = m_imageMap.begin();
761 iterator != m_imageMap.end(); ++iterator)
762 {
763 QTextCursor cursor = textCursor();
764 cursor.movePosition(QTextCursor::Start);
765 cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, (*iterator).m_iPosition - 1);
766 if (cursor.isNull())
767 continue;
768 QTextCharFormat format = cursor.charFormat();
769 if (!format.isImageFormat())
770 continue;
771 QTextImageFormat imageFormat = format.toImageFormat();
772 imageFormat.setWidth((*iterator).m_fInitialWidth * m_iZoomPercentage / 100.);
773 cursor.deleteChar();
774 cursor.insertImage(imageFormat);
775 }
776}
777
778
779#include "UIHelpViewer.moc"
780
781#endif /* #ifdef VBOX_WITH_QHELP_VIEWER */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette