Source Code (Use browser search to find items of interest.)
Class Index
kdelibs'DCOPClient (./kdelibs/dcop/dcopclient.h:65)
class DCOPClient : public QObject
{
Q_OBJECT
public:
/**
* Create a new DCOP client, but do not attach to any server. */
DCOPClient();
/**
* Clean up any open connections and dynamic data.
*/
virtual ~DCOPClient();
/**
* Specify the address of a server to use upon attaching.
*
* If no server address is ever specified, attach will try its best to
* find the server anyway.
*/
static void setServerAddress(const QCString &addr);
/**
* Attach to the DCOP server.
*
* If the connection was already attached,
* the connection will be re-established with the current server address.
*
* Naturally, only attached application can use DCOP services.
*
* If a @ref QApplication object exists then client registers itself as
* @ref QApplication->name() + "-" + <pid>.
* If no @ref QApplication object exists the client registers itself as
* "anonymous".
*
* If you want to register differently, you should use @ref registerAs()
* instead.
*
* @return @p true if attaching was successful.
*/
bool attach();
/**
* @internal
* Internal function for @ref KUniqueApplication to register the @ref DCOPClient
* with the application in case the application didn't exist at the
* time the @ref DCOPClient was created.
*/
void bindToApp();
/**
* Detach from the DCOP server.
*/
bool detach();
/**
* Query whether or not the client is attached to the server.
*/
bool isAttached() const;
/**
* Register at the DCOP server.
*
* If the application was already registered,
* the registration will be re-done with the new @ref appId.
*
* @p appId is a @em unique application/program id that the server
* will use to associate requests with. If there is already an application
* registered with the same name, the server will add a number to the
* id to unify it. If @p addPID is true, the PID of the current process
* will be added to id.
*
* Registration is necessary if you want to allow other clients to talk
* to you. They can do so using your @p appId as first parameter
* for @ref send() or @ref call(). If you just want to talk to
* other clients, you
* do not need to register at the server. In that case @ref attach() is
* enough.
* It will implicitly register you as "anonymous".
*
* @return The actual @p appId used for the registration or a null string
* if the registration wasn't successful.
*/
QCString registerAs( QCString appId, bool addPID = true );
/**
* Query whether or not the client is registered at the server.
*/
bool isRegistered() const;
/**
* Returns the current app id or a null string if the application
* hasn't yet been registered.
*/
QCString appId() const;
/**
* @return The socket over which DCOP is communicating with the server.
*/
int socket() const;
/**
* Send a data block to the server.
*
* @param remApp The remote application id.
* @param remObj The name of the remote object.
* @param remFun The remote function in the specified object to call.
* @param data The data to provide to the remote function.
* @param fast Tf set to @p true, a "fast" form of IPC will be used.
* Fast connections are not guaranteed to be implemented, but
* if they are they work only on the local machine, not across
* the network. "fast" is only a hint not an order.
*
* @return Whether or not the server was able to accept the send.
*/
bool send(const QCString &remApp, const QCString &remObj,
const QCString &remFun, const QByteArray &data,
bool fast=false);
/**
* This function acts exactly the same as the above, but the data
* parameter can be specified as a @ref QString for convenience.
*/
bool send(const QCString &remApp, const QCString &remObj,
const QCString &remFun, const QString &data,
bool fast=false);
/**
* Perform a synchronous send and receive.
*
* The parameters are
* the same as for send, with the exception of another @ref QByteArray
* being provided for results to be (optionally) returned in.
*
* @see send()
*/
bool call(const QCString &remApp, const QCString &remObj,
const QCString &remFun, const QByteArray &data,
QCString& replyType, QByteArray &replyData, bool fast=false);
/**
* Reimplement to handle app-wide function calls unassociated w/an object.
*
* Note that @p fun is normalized. See @ref normalizeFunctionSignature().
*
* If you do not want to reimplement this function for whatever reason,
* you can also use a @ref DCOPObjectProxy.
*/
virtual bool process(const QCString &fun, const QByteArray &data,
QCString& replyType, QByteArray &replyData);
/**
* Delay the reply of the current function call
* until @ref endTransaction() is called.
*
* This allows a server to queue requests.
*
* NOTE: Should be called from inside process(...) only!
*/
DCOPClientTransaction *beginTransaction( );
/**
* Send the delayed reply of a function call.
*/
void endTransaction( DCOPClientTransaction *, QCString& replyType, QByteArray &replyData);
/**
* Test whether the current function call is delayed.
*
* NOTE: Should be called from inside process(...) only!
* @return The ID of the current transaction
* 0 if no transaction is going on.
*/
Q_INT32 transactionId();
/**
* Check whether @p remApp is registered with the @ref DCOPServer.
* @return @p true if the remote application is registered, otherwise @p false.
*/
bool isApplicationRegistered( const QCString& remApp);
/**
* Retrieve the list of all currently registered applications.
*/
QCStringList registeredApplications();
/**
* Receive a piece of data from the server.
*
* @param app The application the data was intended for. Should be
* equal to our appId that we passed when the @ref DCOPClient was
* created.
* @param obj The name of the object to pass the data on to.
* @param fun The name of the function in the object to call.
* @param data The arguments for the function.
* @internal
*/
bool receive(const QCString &app, const QCString &obj,
const QCString &fun, const QByteArray& data,
QCString& replyType, QByteArray &replyData);
/**
* Normalizes the function signature @p fun.
*
* A normalized signature doesn't contain any unnecessary whitespace
* anymore. The remaining whitespace consists of single blanks only (0x20).
*
* Example for a normalized signature:
* <pre>
* "someFunction(QString,int)"
* </pre>
*
* When using @ref send() or @ref call(), normalization is done
* automatically for you.
*
*/
static QCString normalizeFunctionSignature( const QCString& fun );
/**
* Retrieve the @p appId of the last application that talked to us.
*/
QCString senderId() const;
/**
* Install object @p objId as application-wide default object.
*
* All app-wide messages that have not been processed by the dcopclient
* will be send further to @p objId.
*/
void setDefaultObject( const QCString& objId );
/**
* Retrieve the current default object or an empty string if no object is
* installed as default object.
*
* A default object receives application-wide messages that have not
* been processed by the @ref DCOPClient itself.
*/
QCString defaultObject() const;
/**
* Enable / disable the @ref applicationRegistered() / @ref applicationRemoved()
* signals.
*
* They are disabled by default.
*/
void setNotifications( bool enabled );
signals:
/**
* Indicates that the application @p appId has been registered with
* the server we are attached to.
*
* You need to call @ref setNotifications() first, to tell the @ref DCOPServer
* that you want to get these events
*/
void applicationRegistered( const QCString& appId );
/**
* Indicates that the formerly registered application @p appId has
* been removed.
*
* You need to call @ref setNotifications() first, to tell the @ref DCOPServer
* that you want to get these events
*/
void applicationRemoved( const QCString& appId );
/**
* Indicates that the process of establishing DCOP communications failed
* in some manner.
* Usually attached to a dialog box or some other visual
* aid.
*/
void attachFailed(const QString &msg);
public slots:
protected slots:
void processSocketData(int socknum);
protected:
private:
DCOPClientPrivate *d;
friend class DCOPObjectProxy;
void installObjectProxy( DCOPObjectProxy*);
void removeObjectProxy( DCOPObjectProxy*);
bool attachInternal( bool registerAsAnonymous = TRUE );
};
kdelibs'DCOPClient::DCOPClient() (./kdelibs/dcop/dcopclient.cpp:274)
DCOPClient::DCOPClient()
{
d = new DCOPClientPrivate;
d->parent = this;
d->iceConn = 0L;
d->majorOpcode = 0;
d->appId = 0;
d->notifier = 0L;
d->registered = false;
d->transactionList = 0L;
d->transactionId = 0;
}
kdelibs'DCOPClient::~DCOPClient() (./kdelibs/dcop/dcopclient.cpp:287)
DCOPClient::~DCOPClient()
{
if (d->iceConn)
if (IceConnectionStatus(d->iceConn) == IceConnectAccepted)
detach();
delete d->notifier;
delete d->transactionList;
delete d;
}
kdelibs'DCOPClient::setServerAddress() (./kdelibs/dcop/dcopclient.cpp:298)
void DCOPClient::setServerAddress(const QCString &addr)
{
delete DCOPClientPrivate::serverAddr;
DCOPClientPrivate::serverAddr = qstrdup( addr.data() );
}
kdelibs'DCOPClient::attach() (./kdelibs/dcop/dcopclient.cpp:304)
bool DCOPClient::attach()
{
return attachInternal( true );
}
kdelibs'DCOPClient::bindToApp() (./kdelibs/dcop/dcopclient.cpp:309)
void DCOPClient::bindToApp()
{
// check if we have a qApp instantiated. If we do,
// we can create a QSocketNotifier and use it for receiving data.
if (qApp) {
if ( d->notifier )
delete d->notifier;
d->notifier = new QSocketNotifier(socket(),
QSocketNotifier::Read, 0, 0);
connect(d->notifier, SIGNAL(activated(int)),
SLOT(processSocketData(int)));
}
}
kdelibs'DCOPClient::attachInternal() (./kdelibs/dcop/dcopclient.cpp:323)
bool DCOPClient::attachInternal( bool registerAsAnonymous )
{
char errBuf[1024];
if ( isAttached() )
detach();
extern int _IceLastMajorOpcode; // from libICE
if (_IceLastMajorOpcode < 1 )
registerXSM();
if ((d->majorOpcode = IceRegisterForProtocolSetup((char *) "DCOP", (char *) DCOPVendorString,
(char *) DCOPReleaseString, 1, DCOPVersions,
DCOPAuthCount, (char **) DCOPAuthNames,
DCOPClientAuthProcs, 0L)) < 0) {
emit attachFailed("Communications could not be established.");
return false;
}
// first, check if serverAddr was ever set.
if (!d->serverAddr) {
// here, we obtain the list of possible DCOP connections,
// and attach to them.
QString dcopSrv;
dcopSrv = ::getenv("DCOPSERVER");
if (dcopSrv.isNull()) {
QString fName = ::getenv("HOME");
fName += "/.DCOPserver";
QFile f(fName);
if (!f.open(IO_ReadOnly)) {
emit attachFailed("Could not read network connection list.");
return false;
}
QTextStream t(&f);
dcopSrv = t.readLine();
}
d->serverAddr = qstrdup( dcopSrv.latin1() );
}
if ((d->iceConn = IceOpenConnection((char*)d->serverAddr,
(IcePointer) this, False, d->majorOpcode,
sizeof(errBuf), errBuf)) == 0L) {
emit attachFailed(errBuf);
d->iceConn = 0;
return false;
}
IceSetShutdownNegotiation(d->iceConn, False);
int setupstat;
setupstat = IceProtocolSetup(d->iceConn, d->majorOpcode,
(IcePointer) d,
True, /* must authenticate */
&(d->majorVersion), &(d->minorVersion),
&(d->vendor), &(d->release), 1024, errBuf);
if (setupstat == IceProtocolSetupFailure ||
setupstat == IceProtocolSetupIOError) {
IceCloseConnection(d->iceConn);
emit attachFailed(errBuf);
return false;
} else if (setupstat == IceProtocolAlreadyActive) {
/* should not happen because 3rd arg to IceOpenConnection was 0. */
emit attachFailed("internal error in IceOpenConnection");
return false;
}
if (IceConnectionStatus(d->iceConn) != IceConnectAccepted) {
emit attachFailed("DCOP server did not accept the connection.");
return false;
}
bindToApp();
if ( registerAsAnonymous )
registerAs( "anonymous", true );
return true;
}
kdelibs'DCOPClient::detach() (./kdelibs/dcop/dcopclient.cpp:406)
bool DCOPClient::detach()
{
int status;
if (d->iceConn) {
IceProtocolShutdown(d->iceConn, d->majorOpcode);
status = IceCloseConnection(d->iceConn);
if (status != IceClosedNow)
return false;
else
d->iceConn = 0L;
}
delete d->notifier;
d->notifier = 0L;
d->registered = false;
return true;
}
kdelibs'DCOPClient::isAttached() (./kdelibs/dcop/dcopclient.cpp:424)
bool DCOPClient::isAttached() const
{
if (!d->iceConn)
return false;
return (IceConnectionStatus(d->iceConn) == IceConnectAccepted);
}
kdelibs'DCOPClient::registerAs() (./kdelibs/dcop/dcopclient.cpp:433)
QCString DCOPClient::registerAs( QCString appId, bool addPID )
{
QCString result;
// Detach before reregistering.
if ( isRegistered() ) {
detach();
}
if ( !isAttached() ) {
if ( !attachInternal( FALSE ) ) {
return result;
}
}
if (addPID) {
QCString pid;
pid.sprintf("-%d", getpid());
appId = appId + pid;
}
// register the application identifier with the server
QCString replyType;
QByteArray data, replyData;
QDataStream arg( data, IO_WriteOnly );
arg <<appId;
if ( call( "DCOPServer", "", "registerAs(QCString)", data, replyType, replyData ) ) {
QDataStream reply( replyData, IO_ReadOnly );
reply >> result;
}
d->appId = result;
d->registered = !result.isNull();
return result;
}
kdelibs'DCOPClient::isRegistered() (./kdelibs/dcop/dcopclient.cpp:468)
bool DCOPClient::isRegistered() const
{
return d->registered;
}
kdelibs'DCOPClient::appId() (./kdelibs/dcop/dcopclient.cpp:474)
QCString DCOPClient::appId() const
{
return d->appId;
}
kdelibs'DCOPClient::socket() (./kdelibs/dcop/dcopclient.cpp:480)
int DCOPClient::socket() const
{
if (d->iceConn)
return IceConnectionNumber(d->iceConn);
else
return 0;
}
kdelibs'DCOPClient::normalizeFunctionSignature() (./kdelibs/dcop/dcopclient.cpp:494)
QCString DCOPClient::normalizeFunctionSignature( const QCString& fun ) {
if ( fun.isEmpty() ) // nothing to do
return fun.copy();
QCString result( fun.size() );
char *from = fun.data();
char *to = result.data();
char *first = to;
char last = 0;
while ( TRUE ) {
while ( *from && isspace(*from) )
from++;
if ( last && isIdentChar( last ) && isIdentChar( *from ) )
*to++ = 0x20;
while ( *from && !isspace(*from) ) {
last = *from++;
*to++ = last;
}
if ( !*from )
break;
}
if ( to > first && *(to-1) == 0x20 )
to--;
*to = '\0';
result.resize( (int)((long)to - (long)result.data()) + 1 );
return result;
}
kdelibs'DCOPClient::senderId() (./kdelibs/dcop/dcopclient.cpp:522)
QCString DCOPClient::senderId() const
{
return d->senderId;
}
kdelibs'DCOPClient::send() (./kdelibs/dcop/dcopclient.cpp:528)
bool DCOPClient::send(const QCString &remApp, const QCString &remObjId,
const QCString &remFun, const QByteArray &data,
bool)
{
if ( !isAttached() )
return false;
DCOPMsg *pMsg;
QByteArray ba;
QDataStream ds(ba, IO_WriteOnly);
ds << d->appId << remApp << remObjId << normalizeFunctionSignature(remFun) << data.size();
IceGetHeader(d->iceConn, d->majorOpcode, DCOPSend,
sizeof(DCOPMsg), DCOPMsg, pMsg);
int datalen = ba.size() + data.size();
pMsg->length += datalen;
IceSendData( d->iceConn, ba.size(), (char *) ba.data() );
IceSendData( d->iceConn, data.size(), (char *) data.data() );
// IceFlush(d->iceConn);
if (IceConnectionStatus(d->iceConn) != IceConnectAccepted)
return false;
else
return true;
}
kdelibs'DCOPClient::send() (./kdelibs/dcop/dcopclient.cpp:559)
bool DCOPClient::send(const QCString &remApp, const QCString &remObjId,
const QCString &remFun, const QString &data,
bool)
{
QByteArray ba;
QDataStream ds(ba, IO_WriteOnly);
ds << data;
return send(remApp, remObjId, remFun, ba);
}
kdelibs'DCOPClient::process() (./kdelibs/dcop/dcopclient.cpp:569)
bool DCOPClient::process(const QCString &, const QByteArray &,
QCString&, QByteArray &)
{
return false;
}
kdelibs'DCOPClient::isApplicationRegistered() (./kdelibs/dcop/dcopclient.cpp:575)
bool DCOPClient::isApplicationRegistered( const QCString& remApp)
{
QCString replyType;
QByteArray data, replyData;
QDataStream arg( data, IO_WriteOnly );
arg << remApp;
int result = false;
if ( call( "DCOPServer", "", "isApplicationRegistered(QCString)", data, replyType, replyData ) ) {
QDataStream reply( replyData, IO_ReadOnly );
reply >> result;
}
return result;
}
kdelibs'DCOPClient::registeredApplications() (./kdelibs/dcop/dcopclient.cpp:589)
QCStringList DCOPClient::registeredApplications()
{
QCString replyType;
QByteArray data, replyData;
QCStringList result;
if ( call( "DCOPServer", "", "registeredApplications()", data, replyType, replyData ) ) {
QDataStream reply( replyData, IO_ReadOnly );
reply >> result;
}
return result;
}
kdelibs'DCOPClient::setNotifications() (./kdelibs/dcop/dcopclient.cpp:601)
void DCOPClient::setNotifications(bool enabled)
{
QByteArray data;
QDataStream ds(data, IO_WriteOnly);
ds << (Q_INT8) enabled;
QCString replyType;
QByteArray reply;
if (!call("DCOPServer", "", "setNotifications( bool )", data, replyType, reply))
qDebug("I couldn't enable notifications at the dcopserver!");
}
kdelibs'DCOPClient::receive() (./kdelibs/dcop/dcopclient.cpp:613)
bool DCOPClient::receive(const QCString &app, const QCString &objId,
const QCString &fun, const QByteArray &data,
QCString& replyType, QByteArray &replyData)
{
if ( !app.isEmpty() && app != d->appId && app[app.length()-1] != '*') {
qWarning("WEIRD! we somehow received a DCOP message w/a different appId");
return false;
}
if ( objId.isEmpty() ) {
if ( fun == "applicationRegistered(QCString)" ) {
QDataStream ds( data, IO_ReadOnly );
QCString r;
ds >> r;
emit applicationRegistered( r );
return true;
} else if ( fun == "applicationRemoved(QCString)" ) {
QDataStream ds( data, IO_ReadOnly );
QCString r;
ds >> r;
emit applicationRemoved( r );
return true;
}
if ( process( fun, data, replyType, replyData ) )
return true;
// fall through and send to defaultObject if available
if ( !d->defaultObject.isEmpty() && DCOPObject::hasObject( d->defaultObject ) ) {
if (DCOPObject::find( d->defaultObject )->process(fun, data, replyType, replyData))
return true;
}
// fall through and send to object proxies
}
d->transaction = false; // Assume no transaction.
if (!DCOPObject::hasObject(objId)) {
for ( DCOPObjectProxy* proxy = d->proxies.first(); proxy; proxy = d->proxies.next() ) {
if ( proxy->process( objId, fun, data, replyType, replyData ) )
return TRUE;
}
return false;
} else {
DCOPObject *objPtr = DCOPObject::find(objId);
if (!objPtr->process(fun, data, replyType, replyData)) {
// obj doesn't understand function or some other error.
return false;
}
}
return true;
}
kdelibs'DCOPClient::call() (./kdelibs/dcop/dcopclient.cpp:667)
bool DCOPClient::call(const QCString &remApp, const QCString &remObjId,
const QCString &remFun, const QByteArray &data,
QCString& replyType, QByteArray &replyData, bool)
{
if ( !isAttached() )
return false;
DCOPMsg *pMsg;
QByteArray ba;
QDataStream ds(ba, IO_WriteOnly);
ds << d->appId << remApp << remObjId << normalizeFunctionSignature(remFun) << data.size();
IceGetHeader(d->iceConn, d->majorOpcode, DCOPCall,
sizeof(DCOPMsg), DCOPMsg, pMsg);
int datalen = ba.size() + data.size();
pMsg->length += datalen;
IceSendData(d->iceConn, ba.size(), (char *) ba.data());
IceSendData(d->iceConn, data.size(), (char *) data.data());
if (IceConnectionStatus(d->iceConn) != IceConnectAccepted)
return false;
IceFlush (d->iceConn);
IceReplyWaitInfo waitInfo;
waitInfo.sequence_of_request = IceLastSentSequenceNumber(d->iceConn);
waitInfo.major_opcode_of_request = d->majorOpcode;
waitInfo.minor_opcode_of_request = DCOPCall;
ReplyStruct tmp;
tmp.replyType = &replyType;
tmp.replyData = &replyData;
tmp.replyId = 0;
waitInfo.reply = (IcePointer) &tmp;
Bool readyRet = False;
IceProcessMessagesStatus s;
do {
s = IceProcessMessages(d->iceConn, &waitInfo,
&readyRet);
if (s == IceProcessMessagesIOError) {
IceCloseConnection(d->iceConn);
qWarning("received an error processing data from DCOP server!");
return false;
}
} while (!readyRet);
return tmp.result;
}
kdelibs'DCOPClient::processSocketData() (./kdelibs/dcop/dcopclient.cpp:722)
void DCOPClient::processSocketData(int)
{
IceProcessMessagesStatus s = IceProcessMessages(d->iceConn, 0, 0);
if (s == IceProcessMessagesIOError) {
IceCloseConnection(d->iceConn);
qWarning("received an error processing data from the DCOP server!");
return;
}
}
kdelibs'DCOPClient::installObjectProxy() (./kdelibs/dcop/dcopclient.cpp:734)
void DCOPClient::installObjectProxy( DCOPObjectProxy* obj)
{
d->proxies.append( obj );
}
kdelibs'DCOPClient::removeObjectProxy() (./kdelibs/dcop/dcopclient.cpp:739)
void DCOPClient::removeObjectProxy( DCOPObjectProxy* obj)
{
d->proxies.removeRef( obj );
}
kdelibs'DCOPClient::setDefaultObject() (./kdelibs/dcop/dcopclient.cpp:744)
void DCOPClient::setDefaultObject( const QCString& objId )
{
d->defaultObject = objId;
}
kdelibs'DCOPClient::defaultObject() (./kdelibs/dcop/dcopclient.cpp:750)
QCString DCOPClient::defaultObject() const
{
return d->defaultObject;
}
DCOPClientTransaction *
kdelibs'DCOPClient::beginTransaction() (./kdelibs/dcop/dcopclient.cpp:756)
DCOPClient::beginTransaction()
{
if (!d->transactionList)
d->transactionList = new QList<DCOPClientTransaction>;
d->transaction = true;
DCOPClientTransaction *trans = new DCOPClientTransaction();
trans->senderId = d->senderId;
if (!d->transactionId) // transactionId should not be 0!
d->transactionId++;
trans->id = ++(d->transactionId);
d->transactionList->append( trans );
return trans;
}
Q_INT32
kdelibs'DCOPClient::transactionId() (./kdelibs/dcop/dcopclient.cpp:773)
DCOPClient::transactionId()
{
if (d->transaction)
return d->transactionId;
else
return 0;
}
void
kdelibs'DCOPClient::endTransaction() (./kdelibs/dcop/dcopclient.cpp:782)
DCOPClient::endTransaction( DCOPClientTransaction *trans, QCString& replyType,
QByteArray &replyData)
{
if ( !isAttached() )
return;
if ( !d->transactionList) {
qWarning("Transaction unknown: No pending transactions!");
return; // No pending transactions!
}
if ( !d->transactionList->removeRef( trans ) ) {
qWarning("Transaction unknown: Not on list of pending transactions!");
return; // Transaction
}
DCOPMsg *pMsg;
QByteArray ba;
QDataStream ds(ba, IO_WriteOnly);
ds << d->appId << trans->senderId << trans->id << replyType << replyData;
IceGetHeader(d->iceConn, d->majorOpcode, DCOPReplyDelayed,
sizeof(DCOPMsg), DCOPMsg, pMsg);
pMsg->length += ba.size();
IceSendData( d->iceConn, ba.size(), (char *) ba.data() );
delete trans;
}