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 | |
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(sender: queryWidget, signal: &QHelpSearchQueryWidget::search, |
70 | receiver: this, slot: &SearchWidget::search); |
71 | connect(sender: resultWidget, signal: &QHelpSearchResultWidget::requestShowLink, |
72 | receiver: this, slot: &SearchWidget::requestShowLink); |
73 | |
74 | connect(sender: searchEngine, signal: &QHelpSearchEngine::searchingStarted, |
75 | receiver: this, slot: &SearchWidget::searchingStarted); |
76 | connect(sender: searchEngine, signal: &QHelpSearchEngine::searchingFinished, |
77 | receiver: this, slot: &SearchWidget::searchingFinished); |
78 | |
79 | QTextBrowser* browser = resultWidget->findChild<QTextBrowser*>(); |
80 | if (browser) |
81 | browser->viewport()->installEventFilter(filterObj: this); |
82 | } |
83 | |
84 | SearchWidget::~SearchWidget() |
85 | { |
86 | TRACE_OBJ |
87 | // nothing todo |
88 | } |
89 | |
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 | |
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 | |
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(range: zoomCount); |
119 | zoomCount = 0; |
120 | } |
121 | } |
122 | |
123 | void SearchWidget::search() const |
124 | { |
125 | TRACE_OBJ |
126 | searchEngine->search(searchInput: searchEngine->queryWidget()->searchInput()); |
127 | } |
128 | |
129 | void SearchWidget::searchingStarted() |
130 | { |
131 | TRACE_OBJ |
132 | qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); |
133 | } |
134 | |
135 | void SearchWidget::searchingFinished(int searchResultCount) |
136 | { |
137 | TRACE_OBJ |
138 | Q_UNUSED(searchResultCount); |
139 | qApp->restoreOverrideCursor(); |
140 | } |
141 | |
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(point: 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(url: link); |
155 | } |
156 | } |
157 | } |
158 | return QWidget::eventFilter(watched: o,event: e); |
159 | } |
160 | |
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 | |
170 | void SearchWidget::(QContextMenuEvent *) |
171 | { |
172 | TRACE_OBJ |
173 | QMenu ; |
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(p: point, proper: true)) |
182 | return; |
183 | |
184 | QUrl link = browser->anchorAt(pos: point); |
185 | |
186 | QKeySequence keySeq; |
187 | #if QT_CONFIG(clipboard) |
188 | keySeq = QKeySequence::Copy; |
189 | QAction *copyAction = menu.addAction(text: tr(s: "&Copy" ) + QLatin1Char('\t') + |
190 | keySeq.toString(format: QKeySequence::NativeText)); |
191 | copyAction->setEnabled(QTextCursor(browser->textCursor()).hasSelection()); |
192 | |
193 | QAction *copyAnchorAction = menu.addAction(text: tr(s: "Copy &Link Location" )); |
194 | copyAnchorAction->setEnabled(!link.isEmpty() && link.isValid()); |
195 | #endif |
196 | |
197 | keySeq = QKeySequence(Qt::CTRL); |
198 | QAction *newTabAction = menu.addAction(text: tr(s: "Open Link in New Tab" ) + |
199 | QLatin1Char('\t') + keySeq.toString(format: 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(text: tr(s: "Select All" ) + |
207 | QLatin1Char('\t') + keySeq.toString(format: QKeySequence::NativeText)); |
208 | |
209 | QAction *usedAction = menu.exec(pos: 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(url: link); |
227 | } |
228 | else if (usedAction == selectAllAction) { |
229 | browser->selectAll(); |
230 | } |
231 | } |
232 | |
233 | QT_END_NAMESPACE |
234 | |