source: trunk/tools/assistant/lib/qassistantclient.cpp@ 191

Last change on this file since 191 was 191, checked in by rudi, 14 years ago

Qt Assistant added

File size: 9.5 KB
Line 
1/**********************************************************************
2** Copyright (C) 2005-2007 Trolltech ASA. All rights reserved.
3**
4** This file is part of the QAssistantClient library.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
12** licenses may use this file in accordance with the Qt Commercial License
13** Agreement provided with the Software.
14**
15** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17**
18** See http://www.trolltech.com/gpl/ for GPL licensing information.
19** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
20** information about Qt Commercial License Agreements.
21**
22** Contact info@trolltech.com if any conditions of this licensing are
23** not clear to you.
24**
25**********************************************************************/
26
27#include "qassistantclient.h"
28
29#include <qsocket.h>
30#include <qtextstream.h>
31#include <qprocess.h>
32#include <qtimer.h>
33#include <qfileinfo.h>
34
35class QAssistantClientPrivate
36{
37 friend class QAssistantClient;
38 QStringList arguments;
39};
40
41static QMap<const QAssistantClient*,QAssistantClientPrivate*> *dpointers = 0;
42
43static QAssistantClientPrivate *data( const QAssistantClient *client, bool create=FALSE )
44{
45 if( !dpointers )
46 dpointers = new QMap<const QAssistantClient*,QAssistantClientPrivate*>;
47 QAssistantClientPrivate *d = (*dpointers)[client];
48 if( !d && create ) {
49 d = new QAssistantClientPrivate;
50 dpointers->insert( client, d );
51 }
52 return d;
53}
54
55/*!
56 \class QAssistantClient
57 \brief The QAssistantClient class provides a means of using Qt
58 Assistant as an application's help tool.
59
60 Using Qt Assistant is simple: Create a QAssistantClient instance,
61 then call showPage() as often as necessary to show your help
62 pages. When you call showPage(), Qt Assistant will be launched if
63 it isn't already running.
64
65 The QAssistantClient instance can open (openAssistant()) or close
66 (closeAssistant()) Qt Assistant whenever required. If Qt Assistant
67 is open, isOpen() returns TRUE.
68
69 One QAssistantClient instance interacts with one Qt Assistant
70 instance, so every time you call openAssistant(), showPage() or
71 closeAssistant() they are applied to the particular Qt Assistant
72 instance associated with the QAssistantClient.
73
74 When you call openAssistant() the assistantOpened() signal is
75 emitted. Similarly when closeAssistant() is called,
76 assistantClosed() is emitted. In either case, if an error occurs,
77 error() is emitted.
78
79 This class is not included in the Qt library itself. To use it you
80 must link against \c libqassistantclient.a (Unix) or \c
81 qassistantclient.lib (Windows), which is built into \c INSTALL/lib
82 if you built the Qt tools (\c INSTALL is the directory where Qt is
83 installed). If you use qmake, then you can simply add the following
84 line to your pro file:
85
86 \code
87 LIBS += -lqassistantclient
88 \endcode
89
90 See also "Adding Documentation to Qt Assistant" in the \link
91 assistant.book Qt Assistant manual\endlink.
92*/
93
94/*!
95 \fn void QAssistantClient::assistantOpened()
96
97 This signal is emitted when Qt Assistant is open and the
98 client-server communication is set up.
99*/
100
101/*!
102 \fn void QAssistantClient::assistantClosed()
103
104 This signal is emitted when the connection to Qt Assistant is
105 closed. This happens when the user exits Qt Assistant, or when an
106 error in the server or client occurs, or if closeAssistant() is
107 called.
108*/
109
110/*!
111 \fn void QAssistantClient::error( const QString &msg )
112
113 This signal is emitted if Qt Assistant cannot be started or if an
114 error occurs during the initialization of the connection between
115 Qt Assistant and the calling application. The \a msg provides an
116 explanation of the error.
117*/
118
119/*!
120 Constructs an assistant client object. The \a path specifies the
121 path to the Qt Assistant executable. If \a path is an empty
122 string the system path (\c{%PATH%} or \c $PATH) is used.
123
124 The assistant client object is a child of \a parent and is called
125 \a name.
126*/
127QAssistantClient::QAssistantClient( const QString &path, QObject *parent, const char *name )
128 : QObject( parent, name ), host ( "localhost" )
129{
130 if ( path.isEmpty() )
131 assistantCommand = "assistant";
132 else {
133 QFileInfo fi( path );
134 if ( fi.isDir() )
135 assistantCommand = path + "/assistant";
136 else
137 assistantCommand = path;
138 }
139
140#if defined(Q_OS_MACX)
141 assistantCommand += ".app/Contents/MacOS/assistant";
142#elif defined(Q_WS_WIN)
143 if (!assistantCommand.endsWith(".exe"))
144 assistantCommand += ".exe";
145#endif
146 socket = new QSocket( this );
147 connect( socket, SIGNAL( connected() ),
148 SLOT( socketConnected() ) );
149 connect( socket, SIGNAL( connectionClosed() ),
150 SLOT( socketConnectionClosed() ) );
151 connect( socket, SIGNAL( error( int ) ),
152 SLOT( socketError( int ) ) );
153 opened = FALSE;
154 proc = new QProcess( this );
155 port = 0;
156 pageBuffer = "";
157 connect( proc, SIGNAL( readyReadStderr() ),
158 this, SLOT( readStdError() ) );
159}
160
161/*!
162 Destroys the assistant client object and frees up all allocated
163 resources.
164*/
165QAssistantClient::~QAssistantClient()
166{
167 if ( proc && proc->isRunning() ) {
168 proc->tryTerminate();
169 proc->kill();
170 }
171
172 if( dpointers ) {
173 QAssistantClientPrivate *d = (*dpointers)[ this ];
174 if( d ) {
175 dpointers->remove( this );
176 delete d;
177 if( dpointers->isEmpty() ) {
178 delete dpointers;
179 dpointers = 0;
180 }
181 }
182 }
183}
184
185/*!
186 This function opens Qt Assistant and sets up the client-server
187 communiction between the application and Qt Assistant. If it is
188 already open, this function does nothing. If an error occurs,
189 error() is emitted.
190
191 \sa assistantOpened()
192*/
193void QAssistantClient::openAssistant()
194{
195 if ( proc->isRunning() )
196 return;
197 proc->clearArguments();
198 proc->addArgument( assistantCommand );
199 proc->addArgument( "-server" );
200 if( !pageBuffer.isEmpty() ) {
201 proc->addArgument( "-file" );
202 proc->addArgument( pageBuffer );
203 }
204
205 QAssistantClientPrivate *d = data( this );
206 if( d ) {
207 QStringList::ConstIterator it = d->arguments.begin();
208 while( it!=d->arguments.end() ) {
209 proc->addArgument( *it );
210 ++it;
211 }
212 }
213
214 if ( !proc->launch( QString::null ) ) {
215 emit error( tr( "Cannot start Qt Assistant '%1'" )
216 .arg( proc->arguments().join( " " ) ) );
217 return;
218 }
219 connect( proc, SIGNAL( readyReadStdout() ),
220 this, SLOT( readPort() ) );
221}
222
223void QAssistantClient::readPort()
224{
225 QString p = proc->readLineStdout();
226 Q_UINT16 port = p.toUShort();
227 if ( port == 0 ) {
228 emit error( tr( "Cannot connect to Qt Assistant." ) );
229 return;
230 }
231 socket->connectToHost( host, port );
232 disconnect( proc, SIGNAL( readyReadStdout() ),
233 this, SLOT( readPort() ) );
234}
235
236/*!
237 Use this function to close Qt Assistant.
238
239 \sa assistantClosed()
240*/
241void QAssistantClient::closeAssistant()
242{
243 if ( !opened )
244 return;
245 proc->tryTerminate();
246 proc->kill();
247}
248
249/*!
250 Call this function to make Qt Assistant show a particular \a page.
251 The \a page is a filename (e.g. \c myhelpfile.html). See "Adding
252 Documentation to Qt Assistant" in the \link assistant.book Qt
253 Assistant manual\endlink for further information.
254
255 If Qt Assistant hasn't been \link openAssistant() opened\endlink
256 yet, this function will do nothing. You can use isOpen() to
257 determine whether Qt Assistant is up and running, or you can
258 connect to the asssistantOpened() signal.
259
260 \sa isOpen(), assistantOpened()
261*/
262void QAssistantClient::showPage( const QString &page )
263{
264 if ( !opened ) {
265 pageBuffer = page;
266 openAssistant();
267 pageBuffer = QString::null;
268 return;
269 }
270 QTextStream os( socket );
271 os << page << "\n";
272}
273
274/*!
275 \property QAssistantClient::open
276 \brief Whether Qt Assistant is open.
277
278*/
279bool QAssistantClient::isOpen() const
280{
281 return opened;
282}
283
284void QAssistantClient::socketConnected()
285{
286 opened = TRUE;
287 if ( !pageBuffer.isEmpty() )
288 showPage( pageBuffer );
289 emit assistantOpened();
290}
291
292void QAssistantClient::socketConnectionClosed()
293{
294 opened = FALSE;
295 emit assistantClosed();
296}
297
298void QAssistantClient::socketError( int i )
299{
300 if ( i == QSocket::ErrConnectionRefused )
301 emit error( tr( "Could not connect to Assistant: Connection refused" ) );
302 else if ( i == QSocket::ErrHostNotFound )
303 emit error( tr( "Could not connect to Assistant: Host not found" ) );
304 else
305 emit error( tr( "Communication error" ) );
306}
307
308void QAssistantClient::readStdError()
309{
310 QString errmsg;
311 while ( proc->canReadLineStderr() ) {
312 errmsg += proc->readLineStderr();
313 errmsg += "\n";
314 }
315 if (!errmsg.isEmpty())
316 emit error( tr( errmsg.simplifyWhiteSpace() ) );
317}
318
319/*!
320 Sets the command line arguments used when Qt Assistant is
321 started to \a args.
322*/
323void QAssistantClient::setArguments( const QStringList &args )
324{
325 QAssistantClientPrivate *d = data( this, TRUE );
326 d->arguments = args;
327}
Note: See TracBrowser for help on using the repository browser.