1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
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** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include "assistant.h"
52
53#include <QApplication>
54#include <QByteArray>
55#include <QDir>
56#include <QLibraryInfo>
57#include <QMessageBox>
58#include <QStandardPaths>
59
60Assistant::Assistant() = default;
61
62//! [0]
63Assistant::~Assistant()
64{
65 if (!m_process.isNull() && m_process->state() == QProcess::Running) {
66 QObject::disconnect(sender: m_process.data(),
67 signal: QOverload<int, QProcess::ExitStatus>::of(ptr: &QProcess::finished),
68 receiver: nullptr, zero: nullptr);
69 m_process->terminate();
70 m_process->waitForFinished(msecs: 3000);
71 }
72}
73//! [0]
74
75//! [1]
76void Assistant::showDocumentation(const QString &page)
77{
78 if (!startAssistant())
79 return;
80
81 QByteArray ba("SetSource ");
82 ba.append(s: "qthelp://org.qt-project.examples.simpletextviewer/doc/");
83
84 m_process->write(data: ba + page.toLocal8Bit() + '\n');
85}
86//! [1]
87
88QString documentationDirectory()
89{
90 QStringList paths;
91#ifdef SRCDIR
92 paths.append(t: QLatin1String(SRCDIR));
93#endif
94 paths.append(t: QLibraryInfo::location(QLibraryInfo::ExamplesPath));
95 paths.append(t: QCoreApplication::applicationDirPath());
96 paths.append(t: QStandardPaths::standardLocations(type: QStandardPaths::AppDataLocation));
97 for (const auto &dir : qAsConst(t&: paths)) {
98 const QString path = dir + QLatin1String("/documentation");
99 if (QFileInfo::exists(file: path))
100 return path;
101 }
102 return QString();
103}
104
105//! [2]
106bool Assistant::startAssistant()
107{
108 if (m_process.isNull()) {
109 m_process.reset(other: new QProcess());
110 QObject::connect(sender: m_process.data(),
111 signal: QOverload<int, QProcess::ExitStatus>::of(ptr: &QProcess::finished),
112 context: m_process.data(), slot: [this](int exitCode, QProcess::ExitStatus status) {
113 this->finished(exitCode, status);
114 });
115 }
116
117 if (m_process->state() != QProcess::Running) {
118 QString app = QLibraryInfo::location(QLibraryInfo::BinariesPath);
119#ifndef Q_OS_DARWIN
120 app += QLatin1String("/assistant");
121#else
122 app += QLatin1String("/Assistant.app/Contents/MacOS/Assistant");
123#endif
124
125 const QString collectionDirectory = documentationDirectory();
126 if (collectionDirectory.isEmpty()) {
127 showError(message: tr(sourceText: "The documentation directory cannot be found"));
128 return false;
129 }
130
131 QStringList args{QLatin1String("-collectionFile"),
132 collectionDirectory + QLatin1String("/simpletextviewer.qhc"),
133 QLatin1String("-enableRemoteControl")};
134
135 m_process->start(program: app, arguments: args);
136
137 if (!m_process->waitForStarted()) {
138 showError(message: tr(sourceText: "Unable to launch Qt Assistant (%1): %2")
139 .arg(args: QDir::toNativeSeparators(pathName: app), args: m_process->errorString()));
140 return false;
141 }
142 }
143 return true;
144}
145//! [2]
146
147void Assistant::showError(const QString &message)
148{
149 QMessageBox::critical(parent: QApplication::activeWindow(),
150 title: tr(sourceText: "Simple Text Viewer"), text: message);
151}
152
153void Assistant::finished(int exitCode, QProcess::ExitStatus status)
154{
155 const QString stdErr = QString::fromLocal8Bit(str: m_process->readAllStandardError());
156 if (status != QProcess::NormalExit) {
157 showError(message: tr(sourceText: "Assistant crashed: ").arg(a: stdErr));
158 } else if (exitCode != 0) {
159 showError(message: tr(sourceText: "Assistant exited with %1: %2").arg(a: exitCode).arg(a: stdErr));
160 }
161}
162

source code of qttools/examples/assistant/simpletextviewer/assistant.cpp