diff options
Diffstat (limited to 'tools/assistant/lib/qassistantclient.cpp')
-rw-r--r-- | tools/assistant/lib/qassistantclient.cpp | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/tools/assistant/lib/qassistantclient.cpp b/tools/assistant/lib/qassistantclient.cpp new file mode 100644 index 000000000..fc772b55b --- /dev/null +++ b/tools/assistant/lib/qassistantclient.cpp @@ -0,0 +1,334 @@ +/********************************************************************** +** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the TQAssistantClient library. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** Licensees holding valid TQt Commercial licenses may use this file in +** accordance with the TQt Commercial License Agreement provided with +** the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qassistantclient.h" + +#include <qsocket.h> +#include <qtextstream.h> +#include <qprocess.h> +#include <qtimer.h> +#include <qfileinfo.h> + +class TQAssistantClientPrivate +{ + friend class TQAssistantClient; + TQStringList arguments; +}; + +static TQMap<const TQAssistantClient*,TQAssistantClientPrivate*> *dpointers = 0; + +static TQAssistantClientPrivate *data( const TQAssistantClient *client, bool create=FALSE ) +{ + if( !dpointers ) + dpointers = new TQMap<const TQAssistantClient*,TQAssistantClientPrivate*>; + TQAssistantClientPrivate *d = (*dpointers)[client]; + if( !d && create ) { + d = new TQAssistantClientPrivate; + dpointers->insert( client, d ); + } + return d; +} + +/*! + \class TQAssistantClient + \brief The TQAssistantClient class provides a means of using TQt + Assistant as an application's help tool. + + Using TQt Assistant is simple: Create a TQAssistantClient instance, + then call showPage() as often as necessary to show your help + pages. When you call showPage(), TQt Assistant will be launched if + it isn't already running. + + The TQAssistantClient instance can open (openAssistant()) or close + (closeAssistant()) TQt Assistant whenever retquired. If TQt Assistant + is open, isOpen() returns TRUE. + + One TQAssistantClient instance interacts with one TQt Assistant + instance, so every time you call openAssistant(), showPage() or + closeAssistant() they are applied to the particular TQt Assistant + instance associated with the TQAssistantClient. + + When you call openAssistant() the assistantOpened() signal is + emitted. Similarly when closeAssistant() is called, + assistantClosed() is emitted. In either case, if an error occurs, + error() is emitted. + + This class is not included in the TQt library itself. To use it you + must link against \c libqassistantclient.a (Unix) or \c + qassistantclient.lib (Windows), which is built into \c INSTALL/lib + if you built the TQt tools (\c INSTALL is the directory where TQt is + installed). If you use qmake, then you can simply add the following + line to your pro file: + + \code + LIBS += -lqassistantclient + \endcode + + See also "Adding Documentation to TQt Assistant" in the \link + assistant.book TQt Assistant manual\endlink. +*/ + +/*! + \fn void TQAssistantClient::assistantOpened() + + This signal is emitted when TQt Assistant is open and the + client-server communication is set up. +*/ + +/*! + \fn void TQAssistantClient::assistantClosed() + + This signal is emitted when the connection to TQt Assistant is + closed. This happens when the user exits TQt Assistant, or when an + error in the server or client occurs, or if closeAssistant() is + called. +*/ + +/*! + \fn void TQAssistantClient::error( const TQString &msg ) + + This signal is emitted if TQt Assistant cannot be started or if an + error occurs during the initialization of the connection between + TQt Assistant and the calling application. The \a msg provides an + explanation of the error. +*/ + +/*! + Constructs an assistant client object. The \a path specifies the + path to the TQt Assistant executable. If \a path is an empty + string the system path (\c{%PATH%} or \c $PATH) is used. + + The assistant client object is a child of \a parent and is called + \a name. +*/ +TQAssistantClient::TQAssistantClient( const TQString &path, TQObject *parent, const char *name ) + : TQObject( parent, name ), host ( "localhost" ) +{ + if ( path.isEmpty() ) + assistantCommand = "assistant"; + else { + TQFileInfo fi( path ); + if ( fi.isDir() ) + assistantCommand = path + "/assistant"; + else + assistantCommand = path; + } + +#if defined(Q_OS_MACX) + assistantCommand += ".app/Contents/MacOS/assistant"; +#elif defined(Q_WS_WIN) + if (!assistantCommand.endsWith(".exe")) + assistantCommand += ".exe"; +#endif + socket = new TQSocket( this ); + connect( socket, SIGNAL( connected() ), + SLOT( socketConnected() ) ); + connect( socket, SIGNAL( connectionClosed() ), + SLOT( socketConnectionClosed() ) ); + connect( socket, SIGNAL( error( int ) ), + SLOT( socketError( int ) ) ); + opened = FALSE; + proc = new TQProcess( this ); + port = 0; + pageBuffer = ""; + connect( proc, SIGNAL( readyReadStderr() ), + this, SLOT( readStdError() ) ); +} + +/*! + Destroys the assistant client object and frees up all allocated + resources. +*/ +TQAssistantClient::~TQAssistantClient() +{ + if ( proc && proc->isRunning() ) { + proc->tryTerminate(); + proc->kill(); + } + + if( dpointers ) { + TQAssistantClientPrivate *d = (*dpointers)[ this ]; + if( d ) { + dpointers->remove( this ); + delete d; + if( dpointers->isEmpty() ) { + delete dpointers; + dpointers = 0; + } + } + } +} + +/*! + This function opens TQt Assistant and sets up the client-server + communiction between the application and TQt Assistant. If it is + already open, this function does nothing. If an error occurs, + error() is emitted. + + \sa assistantOpened() +*/ +void TQAssistantClient::openAssistant() +{ + if ( proc->isRunning() ) + return; + proc->clearArguments(); + proc->addArgument( assistantCommand ); + proc->addArgument( "-server" ); + if( !pageBuffer.isEmpty() ) { + proc->addArgument( "-file" ); + proc->addArgument( pageBuffer ); + } + + TQAssistantClientPrivate *d = data( this ); + if( d ) { + TQStringList::ConstIterator it = d->arguments.begin(); + while( it!=d->arguments.end() ) { + proc->addArgument( *it ); + ++it; + } + } + + if ( !proc->launch( TQString::null ) ) { + emit error( tr( "Cannot start TQt Assistant '%1'" ) + .arg( proc->arguments().join( " " ) ) ); + return; + } + connect( proc, SIGNAL( readyReadStdout() ), + this, SLOT( readPort() ) ); +} + +void TQAssistantClient::readPort() +{ + TQString p = proc->readLineStdout(); + Q_UINT16 port = p.toUShort(); + if ( port == 0 ) { + emit error( tr( "Cannot connect to TQt Assistant." ) ); + return; + } + socket->connectToHost( host, port ); + disconnect( proc, SIGNAL( readyReadStdout() ), + this, SLOT( readPort() ) ); +} + +/*! + Use this function to close TQt Assistant. + + \sa assistantClosed() +*/ +void TQAssistantClient::closeAssistant() +{ + if ( !opened ) + return; + proc->tryTerminate(); + proc->kill(); +} + +/*! + Call this function to make TQt Assistant show a particular \a page. + The \a page is a filename (e.g. \c myhelpfile.html). See "Adding + Documentation to TQt Assistant" in the \link assistant.book TQt + Assistant manual\endlink for further information. + + If TQt Assistant hasn't been \link openAssistant() opened\endlink + yet, this function will do nothing. You can use isOpen() to + determine whether TQt Assistant is up and running, or you can + connect to the asssistantOpened() signal. + + \sa isOpen(), assistantOpened() +*/ +void TQAssistantClient::showPage( const TQString &page ) +{ + if ( !opened ) { + pageBuffer = page; + openAssistant(); + pageBuffer = TQString::null; + return; + } + TQTextStream os( socket ); + os << page << "\n"; +} + +/*! + \property TQAssistantClient::open + \brief Whether TQt Assistant is open. + +*/ +bool TQAssistantClient::isOpen() const +{ + return opened; +} + +void TQAssistantClient::socketConnected() +{ + opened = TRUE; + if ( !pageBuffer.isEmpty() ) + showPage( pageBuffer ); + emit assistantOpened(); +} + +void TQAssistantClient::socketConnectionClosed() +{ + opened = FALSE; + emit assistantClosed(); +} + +void TQAssistantClient::socketError( int i ) +{ + if ( i == TQSocket::ErrConnectionRefused ) + emit error( tr( "Could not connect to Assistant: Connection refused" ) ); + else if ( i == TQSocket::ErrHostNotFound ) + emit error( tr( "Could not connect to Assistant: Host not found" ) ); + else + emit error( tr( "Communication error" ) ); +} + +void TQAssistantClient::readStdError() +{ + TQString errmsg; + while ( proc->canReadLineStderr() ) { + errmsg += proc->readLineStderr(); + errmsg += "\n"; + } + if (!errmsg.isEmpty()) + emit error( tr( errmsg.simplifyWhiteSpace() ) ); +} + +/*! + Sets the command line arguments used when TQt Assistant is + started to \a args. +*/ +void TQAssistantClient::setArguments( const TQStringList &args ) +{ + TQAssistantClientPrivate *d = data( this, TRUE ); + d->arguments = args; +} |