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 #include "tracer.h"
29 
30 #include "mainwindow.h"
31 #include "searchwidget.h"
32 
33 #include <QtCore/QMap>
34 #include <QtCore/QMimeData>
35 #include <QtCore/QString>
36 #include <QtCore/QStringList>
37 
38 #include <QtWidgets/QMenu>
39 #include <QtWidgets/QLayout>
40 #include <QtGui/QKeyEvent>
41 #if QT_CONFIG(clipboard)
42 #include <QtGui/QClipboard>
43 #endif
44 #include <QtWidgets/QApplication>
45 #include <QtWidgets/QTextBrowser>
46 
47 #include <QtHelp/QHelpSearchEngine>
48 #include <QtHelp/QHelpSearchQueryWidget>
49 #include <QtHelp/QHelpSearchResultWidget>
50 
51 QT_BEGIN_NAMESPACE
52 
SearchWidget(QHelpSearchEngine * engine,QWidget * parent)53 SearchWidget::SearchWidget(QHelpSearchEngine *engine, QWidget *parent)
54     : QWidget(parent)
55     , zoomCount(0)
56     , searchEngine(engine)
57 {
58     TRACE_OBJ
59     QVBoxLayout *vLayout = new QVBoxLayout(this);
60 
61     resultWidget = searchEngine->resultWidget();
62     QHelpSearchQueryWidget *queryWidget = searchEngine->queryWidget();
63 
64     vLayout->addWidget(queryWidget);
65     vLayout->addWidget(resultWidget);
66 
67     setFocusProxy(queryWidget);
68 
69     connect(queryWidget, &QHelpSearchQueryWidget::search,
70             this, &SearchWidget::search);
71     connect(resultWidget, &QHelpSearchResultWidget::requestShowLink,
72             this, &SearchWidget::requestShowLink);
73 
74     connect(searchEngine, &QHelpSearchEngine::searchingStarted,
75             this, &SearchWidget::searchingStarted);
76     connect(searchEngine, &QHelpSearchEngine::searchingFinished,
77             this, &SearchWidget::searchingFinished);
78 
79     QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>();
80     if (browser)
81         browser->viewport()->installEventFilter(this);
82 }
83 
~SearchWidget()84 SearchWidget::~SearchWidget()
85 {
86     TRACE_OBJ
87     // nothing todo
88 }
89 
zoomIn()90 void SearchWidget::zoomIn()
91 {
92     TRACE_OBJ
93     QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>();
94     if (browser && zoomCount != 10) {
95         zoomCount++;
96         browser->zoomIn();
97     }
98 }
99 
zoomOut()100 void SearchWidget::zoomOut()
101 {
102     TRACE_OBJ
103     QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>();
104     if (browser && zoomCount != -5) {
105         zoomCount--;
106         browser->zoomOut();
107     }
108 }
109 
resetZoom()110 void SearchWidget::resetZoom()
111 {
112     TRACE_OBJ
113     if (zoomCount == 0)
114         return;
115 
116     QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>();
117     if (browser) {
118         browser->zoomOut(zoomCount);
119         zoomCount = 0;
120     }
121 }
122 
search() const123 void SearchWidget::search() const
124 {
125     TRACE_OBJ
126     searchEngine->search(searchEngine->queryWidget()->searchInput());
127 }
128 
searchingStarted()129 void SearchWidget::searchingStarted()
130 {
131     TRACE_OBJ
132     qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
133 }
134 
searchingFinished(int searchResultCount)135 void SearchWidget::searchingFinished(int searchResultCount)
136 {
137     TRACE_OBJ
138     Q_UNUSED(searchResultCount);
139     qApp->restoreOverrideCursor();
140 }
141 
eventFilter(QObject * o,QEvent * e)142 bool SearchWidget::eventFilter(QObject* o, QEvent *e)
143 {
144     TRACE_OBJ
145     QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>();
146     if (browser && o == browser->viewport()
147         && e->type() == QEvent::MouseButtonRelease){
148         QMouseEvent *me = static_cast<QMouseEvent*>(e);
149         QUrl link = resultWidget->linkAt(me->pos());
150         if (!link.isEmpty() || link.isValid()) {
151             bool controlPressed = me->modifiers() & Qt::ControlModifier;
152             if ((me->button() == Qt::LeftButton && controlPressed)
153                 || (me->button() == Qt::MiddleButton)) {
154                     emit requestShowLinkInNewTab(link);
155             }
156         }
157     }
158     return QWidget::eventFilter(o,e);
159 }
160 
keyPressEvent(QKeyEvent * keyEvent)161 void SearchWidget::keyPressEvent(QKeyEvent *keyEvent)
162 {
163     TRACE_OBJ
164     if (keyEvent->key() == Qt::Key_Escape)
165         MainWindow::activateCurrentBrowser();
166     else
167         keyEvent->ignore();
168 }
169 
contextMenuEvent(QContextMenuEvent * contextMenuEvent)170 void SearchWidget::contextMenuEvent(QContextMenuEvent *contextMenuEvent)
171 {
172     TRACE_OBJ
173     QMenu menu;
174     QPoint point = contextMenuEvent->globalPos();
175 
176     QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>();
177     if (!browser)
178         return;
179 
180     point = browser->mapFromGlobal(point);
181     if (!browser->rect().contains(point, true))
182         return;
183 
184     QUrl link = browser->anchorAt(point);
185 
186     QKeySequence keySeq;
187 #if QT_CONFIG(clipboard)
188     keySeq = QKeySequence::Copy;
189     QAction *copyAction = menu.addAction(tr("&Copy") + QLatin1Char('\t') +
190         keySeq.toString(QKeySequence::NativeText));
191     copyAction->setEnabled(QTextCursor(browser->textCursor()).hasSelection());
192 
193     QAction *copyAnchorAction = menu.addAction(tr("Copy &Link Location"));
194     copyAnchorAction->setEnabled(!link.isEmpty() && link.isValid());
195 #endif
196 
197     keySeq = QKeySequence(Qt::CTRL);
198     QAction *newTabAction = menu.addAction(tr("Open Link in New Tab") +
199         QLatin1Char('\t') + keySeq.toString(QKeySequence::NativeText) +
200         QLatin1String("LMB"));
201     newTabAction->setEnabled(!link.isEmpty() && link.isValid());
202 
203     menu.addSeparator();
204 
205     keySeq = QKeySequence::SelectAll;
206     QAction *selectAllAction = menu.addAction(tr("Select All") +
207         QLatin1Char('\t') + keySeq.toString(QKeySequence::NativeText));
208 
209     QAction *usedAction = menu.exec(mapToGlobal(contextMenuEvent->pos()));
210 #if QT_CONFIG(clipboard)
211     if (usedAction == copyAction) {
212         QTextCursor cursor = browser->textCursor();
213         if (!cursor.isNull() && cursor.hasSelection()) {
214             QString selectedText = cursor.selectedText();
215             QMimeData *data = new QMimeData();
216             data->setText(selectedText);
217             QApplication::clipboard()->setMimeData(data);
218         }
219     }
220     else if (usedAction == copyAnchorAction) {
221         QApplication::clipboard()->setText(link.toString());
222     }
223     else
224 #endif
225         if (usedAction == newTabAction) {
226         emit requestShowLinkInNewTab(link);
227     }
228     else if (usedAction == selectAllAction) {
229         browser->selectAll();
230     }
231 }
232 
233 QT_END_NAMESPACE
234