~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to tools/assistant/lib/qassistantclient.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

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