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 "remotecontrol.h" |
29 | |
30 | #include "centralwidget.h" |
31 | #include "helpenginewrapper.h" |
32 | #include "mainwindow.h" |
33 | #include "openpagesmanager.h" |
34 | #include "tracer.h" |
35 | |
36 | #include <QtCore/QFile> |
37 | #include <QtCore/QFileInfo> |
38 | #include <QtCore/QFileSystemWatcher> |
39 | #include <QtCore/QTextStream> |
40 | |
41 | #include <QtWidgets/QMessageBox> |
42 | #include <QtWidgets/QApplication> |
43 | |
44 | #include <QtHelp/QHelpEngine> |
45 | #include <QtHelp/QHelpFilterEngine> |
46 | #include <QtHelp/QHelpIndexWidget> |
47 | #include <QtHelp/QHelpLink> |
48 | #include <QtHelp/QHelpSearchQueryWidget> |
49 | |
50 | #ifdef Q_OS_WIN |
51 | # include "stdinlistener_win.h" |
52 | #else |
53 | # include "stdinlistener.h" |
54 | #endif |
55 | |
56 | QT_BEGIN_NAMESPACE |
57 | |
58 | RemoteControl::RemoteControl(MainWindow *mainWindow) |
59 | : QObject(mainWindow) |
60 | , m_mainWindow(mainWindow) |
61 | , helpEngine(HelpEngineWrapper::instance()) |
62 | { |
63 | TRACE_OBJ |
64 | connect(sender: m_mainWindow, signal: &MainWindow::initDone, |
65 | receiver: this, slot: &RemoteControl::applyCache); |
66 | |
67 | StdInListener *l = new StdInListener(this); |
68 | connect(sender: l, signal: &StdInListener::receivedCommand, |
69 | receiver: this, slot: &RemoteControl::handleCommandString); |
70 | l->start(); |
71 | } |
72 | |
73 | void RemoteControl::handleCommandString(const QString &cmdString) |
74 | { |
75 | TRACE_OBJ |
76 | const QStringList &commands = cmdString.split(sep: QLatin1Char(';')); |
77 | for (const QString &command : commands) { |
78 | QString cmd, arg; |
79 | splitInputString(input: command, cmd, arg); |
80 | |
81 | if (m_debug) |
82 | QMessageBox::information(parent: nullptr, title: tr(s: "Debugging Remote Control" ), |
83 | text: tr(s: "Received Command: %1 %2" ).arg(a: cmd).arg(a: arg)); |
84 | |
85 | if (cmd == QLatin1String("debug" )) |
86 | handleDebugCommand(arg); |
87 | else if (cmd == QLatin1String("show" )) |
88 | handleShowOrHideCommand(arg, show: true); |
89 | else if (cmd == QLatin1String("hide" )) |
90 | handleShowOrHideCommand(arg, show: false); |
91 | else if (cmd == QLatin1String("setsource" )) |
92 | handleSetSourceCommand(arg); |
93 | else if (cmd == QLatin1String("synccontents" )) |
94 | handleSyncContentsCommand(); |
95 | else if (cmd == QLatin1String("activatekeyword" )) |
96 | handleActivateKeywordCommand(arg); |
97 | else if (cmd == QLatin1String("activateidentifier" )) |
98 | handleActivateIdentifierCommand(arg); |
99 | else if (cmd == QLatin1String("expandtoc" )) |
100 | handleExpandTocCommand(arg); |
101 | else if (cmd == QLatin1String("setcurrentfilter" )) |
102 | handleSetCurrentFilterCommand(arg); |
103 | else if (cmd == QLatin1String("register" )) |
104 | handleRegisterCommand(arg); |
105 | else if (cmd == QLatin1String("unregister" )) |
106 | handleUnregisterCommand(arg); |
107 | else |
108 | break; |
109 | } |
110 | m_mainWindow->raise(); |
111 | m_mainWindow->activateWindow(); |
112 | } |
113 | |
114 | void RemoteControl::splitInputString(const QString &input, QString &cmd, |
115 | QString &arg) |
116 | { |
117 | TRACE_OBJ |
118 | QString cmdLine = input.trimmed(); |
119 | int i = cmdLine.indexOf(c: QLatin1Char(' ')); |
120 | cmd = cmdLine.left(n: i); |
121 | arg = cmdLine.mid(position: i + 1); |
122 | cmd = cmd.toLower(); |
123 | } |
124 | |
125 | void RemoteControl::handleDebugCommand(const QString &arg) |
126 | { |
127 | TRACE_OBJ |
128 | m_debug = arg == QLatin1String("on" ); |
129 | } |
130 | |
131 | void RemoteControl::handleShowOrHideCommand(const QString &arg, bool show) |
132 | { |
133 | TRACE_OBJ |
134 | if (arg.toLower() == QLatin1String("contents" )) |
135 | m_mainWindow->setContentsVisible(show); |
136 | else if (arg.toLower() == QLatin1String("index" )) |
137 | m_mainWindow->setIndexVisible(show); |
138 | else if (arg.toLower() == QLatin1String("bookmarks" )) |
139 | m_mainWindow->setBookmarksVisible(show); |
140 | else if (arg.toLower() == QLatin1String("search" )) |
141 | m_mainWindow->setSearchVisible(show); |
142 | } |
143 | |
144 | void RemoteControl::handleSetSourceCommand(const QString &arg) |
145 | { |
146 | TRACE_OBJ |
147 | QUrl url(arg); |
148 | if (url.isValid()) { |
149 | if (url.isRelative()) |
150 | url = CentralWidget::instance()->currentSource().resolved(relative: url); |
151 | if (m_caching) { |
152 | clearCache(); |
153 | m_setSource = url; |
154 | } else { |
155 | CentralWidget::instance()->setSource(url); |
156 | } |
157 | } |
158 | } |
159 | |
160 | void RemoteControl::handleSyncContentsCommand() |
161 | { |
162 | TRACE_OBJ |
163 | if (m_caching) |
164 | m_syncContents = true; |
165 | else |
166 | m_mainWindow->syncContents(); |
167 | } |
168 | |
169 | void RemoteControl::handleActivateKeywordCommand(const QString &arg) |
170 | { |
171 | TRACE_OBJ |
172 | if (m_caching) { |
173 | clearCache(); |
174 | m_activateKeyword = arg; |
175 | } else { |
176 | m_mainWindow->setIndexString(arg); |
177 | if (!arg.isEmpty()) { |
178 | if (!helpEngine.indexWidget()->currentIndex().isValid() |
179 | && helpEngine.fullTextSearchFallbackEnabled()) { |
180 | if (QHelpSearchEngine *se = helpEngine.searchEngine()) { |
181 | m_mainWindow->setSearchVisible(true); |
182 | if (QHelpSearchQueryWidget *w = se->queryWidget()) { |
183 | w->collapseExtendedSearch(); |
184 | w->setSearchInput(arg); |
185 | se->search(searchInput: arg); |
186 | } |
187 | } |
188 | } else { |
189 | m_mainWindow->setIndexVisible(true); |
190 | helpEngine.indexWidget()->activateCurrentItem(); |
191 | } |
192 | } |
193 | } |
194 | } |
195 | |
196 | void RemoteControl::handleActivateIdentifierCommand(const QString &arg) |
197 | { |
198 | TRACE_OBJ |
199 | if (m_caching) { |
200 | clearCache(); |
201 | m_activateIdentifier = arg; |
202 | } else { |
203 | const auto docs = helpEngine.documentsForIdentifier(id: arg); |
204 | if (!docs.isEmpty()) |
205 | CentralWidget::instance()->setSource(docs.first().url); |
206 | } |
207 | } |
208 | |
209 | void RemoteControl::handleExpandTocCommand(const QString &arg) |
210 | { |
211 | TRACE_OBJ |
212 | bool ok = false; |
213 | int depth = -2; |
214 | if (!arg.isEmpty()) |
215 | depth = arg.toInt(ok: &ok); |
216 | if (!ok || depth < -2) |
217 | depth = -2; |
218 | |
219 | if (m_caching) |
220 | m_expandTOC = depth; |
221 | else if (depth != -2) |
222 | m_mainWindow->expandTOC(depth); |
223 | } |
224 | |
225 | void RemoteControl::handleSetCurrentFilterCommand(const QString &arg) |
226 | { |
227 | TRACE_OBJ |
228 | if (helpEngine.filterEngine()->filters().contains(str: arg)) { |
229 | if (m_caching) { |
230 | clearCache(); |
231 | m_currentFilter = arg; |
232 | } else { |
233 | helpEngine.filterEngine()->setActiveFilter(arg); |
234 | } |
235 | } |
236 | } |
237 | |
238 | void RemoteControl::handleRegisterCommand(const QString &arg) |
239 | { |
240 | TRACE_OBJ |
241 | const QString &absFileName = QFileInfo(arg).absoluteFilePath(); |
242 | if (helpEngine.registeredDocumentations(). |
243 | contains(str: QHelpEngineCore::namespaceName(documentationFileName: absFileName))) |
244 | return; |
245 | if (helpEngine.registerDocumentation(docFile: absFileName)) |
246 | helpEngine.setupData(); |
247 | } |
248 | |
249 | void RemoteControl::handleUnregisterCommand(const QString &arg) |
250 | { |
251 | TRACE_OBJ |
252 | const QString &absFileName = QFileInfo(arg).absoluteFilePath(); |
253 | const QString &ns = QHelpEngineCore::namespaceName(documentationFileName: absFileName); |
254 | if (helpEngine.registeredDocumentations().contains(str: ns)) { |
255 | OpenPagesManager::instance()->closePages(nameSpace: ns); |
256 | if (helpEngine.unregisterDocumentation(namespaceName: ns)) |
257 | helpEngine.setupData(); |
258 | } |
259 | } |
260 | |
261 | void RemoteControl::applyCache() |
262 | { |
263 | TRACE_OBJ |
264 | if (m_setSource.isValid()) { |
265 | CentralWidget::instance()->setSource(m_setSource); |
266 | } else if (!m_activateKeyword.isEmpty()) { |
267 | m_mainWindow->setIndexString(m_activateKeyword); |
268 | helpEngine.indexWidget()->activateCurrentItem(); |
269 | } else if (!m_activateIdentifier.isEmpty()) { |
270 | const auto docs = |
271 | helpEngine.documentsForIdentifier(id: m_activateIdentifier); |
272 | if (!docs.isEmpty()) |
273 | CentralWidget::instance()->setSource(docs.first().url); |
274 | } else if (!m_currentFilter.isEmpty()) { |
275 | helpEngine.filterEngine()->setActiveFilter(m_currentFilter); |
276 | } |
277 | |
278 | if (m_syncContents) |
279 | m_mainWindow->syncContents(); |
280 | |
281 | Q_ASSERT(m_expandTOC >= -2); |
282 | if (m_expandTOC != -2) |
283 | m_mainWindow->expandTOC(depth: m_expandTOC); |
284 | |
285 | m_caching = false; |
286 | } |
287 | |
288 | void RemoteControl::clearCache() |
289 | { |
290 | TRACE_OBJ |
291 | m_currentFilter.clear(); |
292 | m_setSource.clear(); |
293 | m_syncContents = false; |
294 | m_activateKeyword.clear(); |
295 | m_activateIdentifier.clear(); |
296 | } |
297 | |
298 | QT_END_NAMESPACE |
299 | |