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