Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
assistantclient.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtCore/qstring.h>
7#include <QtCore/qprocess.h>
8#include <QtCore/qdir.h>
9#include <QtCore/qlibraryinfo.h>
10#include <QtCore/qdebug.h>
11#include <QtCore/qfileinfo.h>
12#include <QtCore/qobject.h>
13#include <QtCore/qtextstream.h>
14#include <QtCore/qcoreapplication.h>
15
17
18using namespace Qt::StringLiterals;
19
20constexpr bool debugAssistantClient = false;
21
22AssistantClient::AssistantClient() = default;
23
25{
26 if (isRunning()) {
27 QString errorMessage;
28 if (!sendCommand("quit"_L1, &errorMessage) || !m_process->waitForFinished(1000)) {
29 m_process->terminate();
30 m_process->waitForFinished();
31 }
32 }
33 delete m_process;
34}
35
36bool AssistantClient::showPage(const QString &path, QString *errorMessage)
37{
38 const QString cmd = "SetSource "_L1 + path;
39 return sendCommand(cmd, errorMessage);
40}
41
42bool AssistantClient::activateIdentifier(const QString &identifier, QString *errorMessage)
43{
44 const QString cmd = "ActivateIdentifier "_L1 + identifier;
45 return sendCommand(cmd, errorMessage);
46}
47
48bool AssistantClient::sendCommand(const QString &cmd, QString *errorMessage)
49{
50 if constexpr (debugAssistantClient)
51 qDebug() << "sendCommand " << cmd;
52 if (!ensureRunning(errorMessage))
53 return false;
54 if (!m_process->isWritable() || m_process->bytesToWrite() > 0) {
55 *errorMessage = QCoreApplication::translate("AssistantClient", "Unable to send request: Assistant is not responding.");
56 return false;
57 }
58 QTextStream str(m_process);
59 str << cmd << "\n\n";
60 return true;
61}
62
64{
65 return m_process && m_process->state() != QProcess::NotRunning;
66}
67
68QString AssistantClient::binary()
69{
70 QString app = QLibraryInfo::path(QLibraryInfo::BinariesPath) + QDir::separator();
71#if !defined(Q_OS_MACOS)
72 app += "assistant"_L1;
73#else
74 app += "Assistant.app/Contents/MacOS/Assistant"_L1;
75#endif
76
77#if defined(Q_OS_WIN)
78 app += ".exe"_L1;
79#endif
80
81 return app;
82}
83
84void AssistantClient::readyReadStandardError()
85{
86 qWarning("%s: %s",
87 qPrintable(QDir::toNativeSeparators(m_process->program())),
88 m_process->readAllStandardError().constData());
89}
90
91void AssistantClient::processTerminated(int exitCode, QProcess::ExitStatus exitStatus)
92{
93 const QString binary = QDir::toNativeSeparators(m_process->program());
94 if (exitStatus != QProcess::NormalExit)
95 qWarning("%s: crashed.", qPrintable(binary));
96 else if (exitCode != 0)
97 qWarning("%s: terminated with exit code %d.", qPrintable(binary), exitCode);
98}
99
100bool AssistantClient::ensureRunning(QString *errorMessage)
101{
102 if (isRunning())
103 return true;
104
105 if (!m_process) {
106 m_process = new QProcess;
107 auto exitHandler = [this](int exitCode, QProcess::ExitStatus exitStatus) { this->processTerminated(exitCode, exitStatus); };
108 QObject::connect(m_process, &QProcess::finished, m_process, exitHandler);
109 auto readHandler = [this]() { this->readyReadStandardError(); };
110 QObject::connect(m_process, &QProcess::readyReadStandardError, m_process, readHandler);
111 }
112
113 const QString app = binary();
114 if (!QFileInfo(app).isFile()) {
115 *errorMessage = QCoreApplication::translate("AssistantClient", "The binary '%1' does not exist.").arg(app);
116 return false;
117 }
118 if constexpr (debugAssistantClient)
119 qDebug() << "Running " << app;
120 // run
121 QStringList args{u"-enableRemoteControl"_s};
122 m_process->start(app, args);
123 if (!m_process->waitForStarted()) {
124 *errorMessage = QCoreApplication::translate("AssistantClient", "Unable to launch assistant (%1).").arg(app);
125 return false;
126 }
127 return true;
128}
129
130QString AssistantClient::documentUrl(const QString &module) const
131{
132 const int qtVersion = QT_VERSION;
133 QString rc;
134 QTextStream(&rc) << "qthelp://org.qt-project." << module << '.'
135 << (qtVersion >> 16) << ((qtVersion >> 8) & 0xFF) << (qtVersion & 0xFF)
136 << '/' << module << '/';
137 return rc;
138}
139
140QT_END_NAMESPACE
constexpr bool debugAssistantClient
bool isRunning() const
bool showPage(const QString &path, QString *errorMessage) override
~AssistantClient() override
bool activateIdentifier(const QString &identifier, QString *errorMessage) override
QString documentUrl(const QString &module) const override
Combined button and popup list for selecting options.