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
56QT_BEGIN_NAMESPACE
57
58RemoteControl::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
73void 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
114void 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
125void RemoteControl::handleDebugCommand(const QString &arg)
126{
127 TRACE_OBJ
128 m_debug = arg == QLatin1String("on");
129}
130
131void 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
144void 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
160void RemoteControl::handleSyncContentsCommand()
161{
162 TRACE_OBJ
163 if (m_caching)
164 m_syncContents = true;
165 else
166 m_mainWindow->syncContents();
167}
168
169void 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
196void 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
209void 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
225void 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
238void 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
249void 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
261void 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
288void 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
298QT_END_NAMESPACE
299

source code of qttools/src/assistant/assistant/remotecontrol.cpp