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 | |
60 | Assistant::Assistant() = default; |
61 | |
62 | //! [0] |
63 | Assistant::~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] |
76 | void 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 | |
88 | QString 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] |
106 | bool 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 | |
147 | void Assistant::showError(const QString &message) |
148 | { |
149 | QMessageBox::critical(parent: QApplication::activeWindow(), |
150 | title: tr(sourceText: "Simple Text Viewer" ), text: message); |
151 | } |
152 | |
153 | void 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 | |