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
31QT_BEGIN_NAMESPACE
32
33RemoteControl::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
48void 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
89void 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
100void RemoteControl::handleDebugCommand(const QString &arg)
101{
102 TRACE_OBJ
103 m_debug = arg == QLatin1String("on");
104}
105
106void 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
119void 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
135void RemoteControl::handleSyncContentsCommand()
136{
137 TRACE_OBJ
138 if (m_caching)
139 m_syncContents = true;
140 else
141 m_mainWindow->syncContents();
142}
143
144void 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
171void 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
184void 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
200void 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
213void 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
224void 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
236void 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
263void 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
273QT_END_NAMESPACE
274

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