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