Qt 4.8
qcopchannel_qws.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qcopchannel_qws.h"
43 
44 #ifndef QT_NO_COP
45 
46 #include "qwsdisplay_qws.h"
47 #include "qwscommand_qws_p.h"
48 #include "qwindowsystem_qws.h"
49 #include "qwindowsystem_p.h"
50 #include "qlist.h"
51 #include "qmap.h"
52 #include "qdatastream.h"
53 #include "qpointer.h"
54 #include "qmutex.h"
55 
56 #include "qdebug.h"
57 
59 
62 
64 {
65 public:
67  QCopServerRegexp( const QCopServerRegexp& other );
68 
72 };
73 
75 {
76  this->channel = channel;
77  this->client = client;
79 }
80 
82 {
83  channel = other.channel;
84  client = other.client;
85  regexp = other.regexp;
86 }
87 
90 
93 
94 Q_GLOBAL_STATIC(QMutex, qcopClientMapMutex)
95 
96 // Determine if a channel name contains wildcard characters.
97 static bool containsWildcards( const QString& channel )
98 {
99  return channel.contains(QLatin1Char('*'));
100 }
101 
103 {
104 public:
106 };
107 
158  QObject(parent)
159 {
160  init(channel);
161 }
162 
163 #ifdef QT3_SUPPORT
164 
169  QObject(parent)
170 {
172  init(channel);
173 }
174 #endif
175 
176 void QCopChannel::init(const QString& channel)
177 {
178  d = new QCopChannelPrivate;
179  d->channel = channel;
180 
181  if (!qt_fbdpy) {
182  qFatal("QCopChannel: Must construct a QApplication "
183  "before QCopChannel");
184  return;
185  }
186 
187  {
188  QMutexLocker locker(qcopClientMapMutex());
189 
190  if (!qcopClientMap)
191  qcopClientMap = new QCopClientMap;
192 
193  // do we need a new channel list ?
194  QCopClientMap::Iterator it = qcopClientMap->find(channel);
195  if (it != qcopClientMap->end()) {
196  it.value().append(this);
197  return;
198  }
199 
200  it = qcopClientMap->insert(channel, QList< QPointer<QCopChannel> >());
201  it.value().append(QPointer<QCopChannel>(this));
202  }
203 
204  // inform server about this channel
205  qt_fbdpy->registerChannel(channel);
206 }
207 
214 {
215  if(qcopClientMap)
216  for(QCopClientMap::Iterator iter = qcopClientMap->begin();
217  iter != qcopClientMap->end();
218  ++iter)
219  qt_fbdpy->registerChannel(iter.key());
220 }
221 
233 {
234  QMutexLocker locker(qcopClientMapMutex());
235  QCopClientMap::Iterator it = qcopClientMap->find(d->channel);
236  Q_ASSERT(it != qcopClientMap->end());
237  it.value().removeAll(this);
238  // still any clients connected locally ?
239  if (it.value().isEmpty()) {
242  s << d->channel;
243  if (qt_fbdpy)
244  send(QLatin1String(""), QLatin1String("detach()"), data);
245  qcopClientMap->remove(d->channel);
246  }
247 
248  delete d;
249 }
250 
258 {
259  return d->channel;
260 }
261 
289 void QCopChannel::receive(const QString& msg, const QByteArray &data)
290 {
291  emit received(msg, data);
292 }
293 
314 bool QCopChannel::isRegistered(const QString& channel)
315 {
318  s << channel;
319  if (!send(QLatin1String(""), QLatin1String("isRegistered()"), data))
320  return false;
321 
323  bool known = e->message == "known";
324  delete e;
325  return known;
326 }
327 
333 bool QCopChannel::send(const QString& channel, const QString& msg)
334 {
336  return send(channel, msg, data);
337 }
338 
367 bool QCopChannel::send(const QString& channel, const QString& msg,
368  const QByteArray &data)
369 {
370  if (!qt_fbdpy) {
371  qFatal("QCopChannel::send: Must construct a QApplication "
372  "before using QCopChannel");
373  return false;
374  }
375 
376  qt_fbdpy->sendMessage(channel, msg, data);
377 
378  return true;
379 }
380 
396 {
397  if (!qt_fbdpy) {
398  qFatal("QCopChannel::flush: Must construct a QApplication "
399  "before using QCopChannel");
400  return false;
401  }
402 
404 
405  return true;
406 }
407 
409  Q_OBJECT
410 
411 public:
412  void emitNewChannel(const QString& channel);
413  void emitRemovedChannel(const QString& channel);
414 
415  signals:
416  void newChannel(const QString& channel);
417  void removedChannel(const QString& channel);
418 };
419 
421  emit newChannel(channel);
422 }
423 
425  emit removedChannel(channel);
426 }
427 
437 {
438  if (!qcopServerMap)
439  qcopServerMap = new QCopServerMap;
440 
441  // do we need a new channel list ?
442  QCopServerMap::Iterator it = qcopServerMap->find(ch);
443  if (it == qcopServerMap->end())
444  it = qcopServerMap->insert(ch, QList<QWSClient*>());
445 
446  // If the channel name contains wildcard characters, then we also
447  // register it on the server regexp matching list.
448  if (containsWildcards( ch )) {
449  QCopServerRegexp item(ch, cl);
450  if (!qcopServerRegexpList)
451  qcopServerRegexpList = new QCopServerRegexpList;
452  qcopServerRegexpList->append( item );
453  }
454 
455  // If this is the first client in the channel, announce the channel as being created.
456  if (it.value().count() == 0) {
457  QWSServerSignalBridge* qwsBridge = new QWSServerSignalBridge();
458  connect(qwsBridge, SIGNAL(newChannel(QString)), qwsServer, SIGNAL(newChannel(QString)));
459  qwsBridge->emitNewChannel(ch);
460  delete qwsBridge;
461  }
462 
463  it.value().append(cl);
464 }
465 
475 {
476  if (!qcopServerMap)
477  return;
478 
479  QCopServerMap::Iterator it = qcopServerMap->begin();
480  for (; it != qcopServerMap->end(); ++it) {
481  if (it.value().contains(cl)) {
482  it.value().removeAll(cl);
483  // If this was the last client in the channel, announce the channel as dead.
484  if (it.value().count() == 0) {
485  QWSServerSignalBridge* qwsBridge = new QWSServerSignalBridge();
486  connect(qwsBridge, SIGNAL(removedChannel(QString)), qwsServer, SIGNAL(removedChannel(QString)));
487  qwsBridge->emitRemovedChannel(it.key());
488  delete qwsBridge;
489  }
490  }
491  }
492 
493  if (!qcopServerRegexpList)
494  return;
495 
496  QCopServerRegexpList::Iterator it2 = qcopServerRegexpList->begin();
497  while(it2 != qcopServerRegexpList->end()) {
498  if ((*it2).client == cl)
499  it2 = qcopServerRegexpList->erase(it2);
500  else
501  ++it2;
502  }
503 }
504 
515  const QString& msg, const QByteArray &data)
516 {
517  // internal commands
518  if (ch.isEmpty()) {
519  if (msg == QLatin1String("isRegistered()")) {
520  QString c;
521  QDataStream s(data);
522  s >> c;
523  bool known = qcopServerMap && qcopServerMap->contains(c)
524  && !((*qcopServerMap)[c]).isEmpty();
525  // Yes, it's a typo, it's not user-visible, and we choose not to fix it for compatibility
526  QLatin1String ans = QLatin1String(known ? "known" : "unknown");
528  ans, data, true);
529  return;
530  } else if (msg == QLatin1String("detach()")) {
531  QString c;
532  QDataStream s(data);
533  s >> c;
534  Q_ASSERT(qcopServerMap);
535  QCopServerMap::Iterator it = qcopServerMap->find(c);
536  if (it != qcopServerMap->end()) {
537  //Q_ASSERT(it.value().contains(cl));
538  it.value().removeAll(cl);
539  if (it.value().isEmpty()) {
540  // If this was the last client in the channel, announce the channel as dead
541  QWSServerSignalBridge* qwsBridge = new QWSServerSignalBridge();
542  connect(qwsBridge, SIGNAL(removedChannel(QString)), qwsServer, SIGNAL(removedChannel(QString)));
543  qwsBridge->emitRemovedChannel(it.key());
544  delete qwsBridge;
545  qcopServerMap->erase(it);
546  }
547  }
548  if (qcopServerRegexpList && containsWildcards(c)) {
549  // Remove references to a wildcarded channel.
551  = qcopServerRegexpList->begin();
552  while(it != qcopServerRegexpList->end()) {
553  if ((*it).client == cl && (*it).channel == c)
554  it = qcopServerRegexpList->erase(it);
555  else
556  ++it;
557  }
558  }
559  return;
560  }
561  qWarning("QCopChannel: unknown internal command %s", qPrintable(msg));
563  QLatin1String("bad"), data);
564  return;
565  }
566 
567  if (qcopServerMap) {
568  QList<QWSClient*> clist = qcopServerMap->value(ch);
569  for (int i=0; i < clist.size(); ++i) {
570  QWSClient *c = clist.at(i);
571  QWSServerPrivate::sendQCopEvent(c, ch, msg, data);
572  }
573  }
574 
575  if(qcopServerRegexpList && !containsWildcards(ch)) {
576  // Search for wildcard matches and forward the message on.
577  QCopServerRegexpList::ConstIterator it = qcopServerRegexpList->constBegin();
578  for (; it != qcopServerRegexpList->constEnd(); ++it) {
579  if ((*it).regexp.exactMatch(ch)) {
580  QByteArray newData;
581  {
584  stream << ch;
585  stream << msg;
586  stream << data;
587  // Stream is flushed and closed at this point.
588  }
590  ((*it).client, (*it).channel,
591  QLatin1String("forwardedMessage(QString,QString,QByteArray)"),
592  newData);
593  }
594  }
595  }
596 }
597 
606 void QCopChannel::sendLocally(const QString& ch, const QString& msg,
607  const QByteArray &data)
608 {
609  Q_ASSERT(qcopClientMap);
610 
611  // filter out internal events
612  if (ch.isEmpty())
613  return;
614 
615  // feed local clients with received data
617  {
618  QMutexLocker locker(qcopClientMapMutex());
619  clients = (*qcopClientMap)[ch];
620  }
621  for (int i = 0; i < clients.size(); ++i) {
622  QCopChannel *channel = (QCopChannel *)clients.at(i);
623  if ( channel )
624  channel->receive(msg, data);
625  }
626 }
627 
629 
630 #include "qcopchannel_qws.moc"
631 
632 #endif
void emitNewChannel(const QString &channel)
void registerChannel(const QString &channel)
unsigned char c[8]
Definition: qnumeric_p.h:62
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static bool flush()
Flushes all queued messages to the registered listeners.
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
static QString fromAscii(const char *, int size=-1)
Returns a QString initialized with the first size characters from the string str. ...
Definition: qstring.cpp:4276
static void sendQCopEvent(QWSClient *c, const QString &ch, const QString &msg, const QByteArray &data, bool response=false)
The QRegExp class provides pattern matching using regular expressions.
Definition: qregexp.h:61
static QCopServerRegexpList * qcopServerRegexpList
#define it(className, varName)
Q_GUI_EXPORT QWSDisplay * qt_fbdpy
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
void emitRemovedChannel(const QString &channel)
iterator begin()
Returns an STL-style iterator pointing to the first item in the list.
Definition: qlist.h:267
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qlist.h:269
The QList::const_iterator class provides an STL-style const iterator for QList and QQueue...
Definition: qlist.h:228
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
static bool send(const QString &channel, const QString &msg)
This is an overloaded member function, provided for convenience. It differs from the above function o...
iterator find(const Key &key)
Returns an iterator pointing to the item with key key in the map.
Definition: qmap.h:618
void received(const QString &msg, const QByteArray &data)
This signal is emitted whenever this object&#39;s channel receives new messages (i.
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
void init(const QString &channel)
QWSQCopMessageEvent * waitForQCopResponse()
The QPointer class is a template class that provides guarded pointers to QObject. ...
Definition: qpointer.h:54
void setObjectName(const QString &name)
Definition: qobject.cpp:1112
static void sendLocally(const QString &ch, const QString &msg, const QByteArray &data)
Client side: distribute received event to the QCop instance managing the channel. ...
T & value() const
Returns a modifiable reference to the current item&#39;s value.
Definition: qmap.h:251
#define SIGNAL(a)
Definition: qobjectdefs.h:227
QMap< QString, QList< QWSClient * > > QCopServerMap
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static FILE * stream
static bool isEmpty(const char *str)
QCopChannelPrivate * d
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:270
const char * name
const T value(const Key &key) const
Returns the value associated with the key key.
Definition: qmap.h:499
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
Definition: qglobal.h:1968
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
iterator Iterator
Qt-style synonym for QMap::iterator.
Definition: qmap.h:388
Q_CORE_EXPORT void qWarning(const char *,...)
static const char * data(const QByteArray &arr)
static bool containsWildcards(const QString &channel)
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
static void answer(QWSClient *cl, const QString &ch, const QString &msg, const QByteArray &data)
Server side: transmit the message to all clients registered to the specified channel.
QString channel() const
Returns the name of this object&#39;s channel.
static void detach(QWSClient *cl)
Server side: unsubscribe cl from all channels.
static QCopClientMap * qcopClientMap
#define Q_OBJECT
Definition: qobjectdefs.h:157
The QList::iterator class provides an STL-style non-const iterator for QList and QQueue.
Definition: qlist.h:181
iterator begin()
Returns an STL-style iterator pointing to the first item in the map.
Definition: qmap.h:372
int remove(const Key &key)
Removes all the items that have the key key from the map.
Definition: qmap.h:662
Q_CORE_EXPORT void qFatal(const char *,...)
iterator erase(iterator pos)
Removes the item associated with the iterator pos from the list, and returns an iterator to the next ...
Definition: qlist.h:464
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
The QMap::iterator class provides an STL-style non-const iterator for QMap and QMultiMap.
Definition: qmap.h:233
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the map...
Definition: qmap.h:375
iterator insert(const Key &key, const T &value)
Inserts a new item with the key key and a value of value.
Definition: qmap.h:559
Q_INVOKABLE QObject(QObject *parent=0)
Constructs an object with parent object parent.
Definition: qobject.cpp:753
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
QMap< QString, QList< QPointer< QCopChannel > > > QCopClientMap
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
QCopServerRegexp(const QString &channel, QWSClient *client)
bool contains(const Key &key) const
Returns true if the map contains an item with key key; otherwise returns false.
Definition: qmap.h:553
static QCopServerMap * qcopServerMap
The QCopChannel class provides communication capabilities between clients in Qt for Embedded Linux...
iterator erase(iterator it)
Removes the (key, value) pair pointed to by the iterator pos from the map, and returns an iterator to...
Definition: qmap.h:717
virtual ~QCopChannel()
Destroys this QCopChannel object.
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:71
virtual void receive(const QString &msg, const QByteArray &data)
Processes the incoming message and data.
static void registerChannel(const QString &ch, QWSClient *cl)
Server side: subscribe client cl on channel ch.
QList< QCopServerRegexp > QCopServerRegexpList
#define signals
Definition: qobjectdefs.h:69
#define qPrintable(string)
Definition: qglobal.h:1750
QCopChannel(const QString &channel, QObject *parent=0)
Constructs a QCopChannel object for the specified channel, with the given parent. ...
The QWSClient class encapsulates a client process in Qt for Embedded Linux.
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
The QMap class is a template class that provides a skip-list-based dictionary.
Definition: qdatastream.h:67
QWSServer Q_GUI_EXPORT * qwsServer
void sendMessage(const QString &channel, const QString &msg, const QByteArray &data)
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
static bool isRegistered(const QString &channel)
Queries the server for the existence of the given channel.
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:272
static void reregisterAll()