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