bring Qt3 library back. Some apps that are not in the KDE trunk are using it.
[platform/upstream/dbus.git] / qt3 / message.cpp
1 /* -*- mode: C++; c-file-style: "gnu" -*- */
2 /* message.cpp: Qt wrapper for DBusMessage
3  *
4  * Copyright (C) 2003  Zack Rusin <zack@kde.org>
5  *
6  * Licensed under the Academic Free License version 2.0
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23 #include "message.h"
24
25 #include <qmap.h>
26
27 #include <cstdlib>
28
29 namespace DBusQt {
30
31 struct Message::iterator::IteratorData {
32   DBusMessageIter *iter;
33   QVariant         var;
34   bool             end;
35   DBusMessage     *mesg;
36 };
37
38 /**
39  * Iterator.
40  */
41 Message::iterator::iterator()
42 {
43   d = new IteratorData;
44   d->iter = 0; d->end = true;
45 }
46
47 /**
48  * Constructs iterator for the message.
49  * @param msg message whose fields we want to iterate
50  */
51 Message::iterator::iterator( DBusMessage* msg )
52 {
53   d = new IteratorData;
54   d->mesg = msg;
55   d->iter = static_cast<DBusMessageIter *>( malloc( sizeof(DBusMessageIter) ) );
56   dbus_message_iter_init( d->mesg, d->iter );
57   if ( !d->iter ) {
58     qDebug("No iterator??");
59   }
60   fillVar();
61   d->end = false;
62 }
63
64 /**
65  * Copy constructor for the iterator.
66  * @param itr iterator
67  */
68 Message::iterator::iterator( const iterator& itr )
69 {
70   d = new IteratorData;
71   d->iter = itr.d->iter;
72   d->var  = itr.d->var;
73   d->end  = itr.d->end;
74 }
75
76 /**
77  * Destructor.
78  */
79 Message::iterator::~iterator()
80 {
81   free( d->iter );
82   delete d; d=0;
83 }
84
85 /**
86  * Creates an iterator equal to the @p itr iterator
87  * @param itr other iterator
88  * @return
89  */
90 Message::iterator&
91 Message::iterator::operator=( const iterator& itr )
92 {
93   IteratorData *tmp = new IteratorData;
94   tmp->iter = itr.d->iter;
95   tmp->var  = itr.d->var;
96   tmp->end  = itr.d->end;
97   delete d; d=tmp;
98   return *this;
99 }
100
101 /**
102  * Returns the constant QVariant held by the iterator.
103  * @return the constant reference to QVariant held by this iterator
104  */
105 const QVariant&
106 Message::iterator::operator*() const
107 {
108   return d->var;
109 }
110
111 /**
112  * Returns the QVariant held by the iterator.
113  * @return reference to QVariant held by this iterator
114  */
115 QVariant&
116 Message::iterator::operator*()
117 {
118   return d->var;
119 }
120
121 /**
122  * Moves to the next field and return a reference to itself after
123  * incrementing.
124  * @return reference to self after incrementing
125  */
126 Message::iterator&
127 Message::iterator::operator++()
128 {
129   if ( d->end )
130     return *this;
131
132   if (  dbus_message_iter_next( d->iter ) ) {
133     fillVar();
134   } else {
135     d->end = true;
136     d->var = QVariant();
137   }
138   return *this;
139 }
140
141 /**
142  * Moves to the next field and returns self before incrementing.
143  * @return self before incrementing
144  */
145 Message::iterator
146 Message::iterator::operator++(int)
147 {
148   iterator itr( *this );
149   operator++();
150   return itr;
151 }
152
153 /**
154  * Compares this iterator to @p it iterator.
155  * @param it the iterator to which we're comparing this one to
156  * @return true if they're equal, false otherwise
157  */
158 bool
159 Message::iterator::operator==( const iterator& it )
160 {
161   if ( d->end == it.d->end ) {
162     if ( d->end == true ) {
163       return true;
164     } else {
165       return d->var == it.d->var;
166     }
167   } else
168     return false;
169 }
170
171 /**
172  * Compares two iterators.
173  * @param it The other iterator.
174  * @return true if two iterators are not equal, false
175  *         otherwise
176  */
177 bool
178 Message::iterator::operator!=( const iterator& it )
179 {
180   return !operator==( it );
181 }
182
183 QVariant Message::iterator::marshallBaseType( DBusMessageIter* i )
184 {
185   QVariant ret;
186   switch (dbus_message_iter_get_arg_type(i)) {
187   case DBUS_TYPE_INT32:
188     {
189       dbus_int32_t v;
190       dbus_message_iter_get_basic (i, &v);
191       ret = QVariant( v );
192     }
193     break;
194   case DBUS_TYPE_UINT32:
195     {
196       dbus_uint32_t v;
197       dbus_message_iter_get_basic (i, &v);
198       ret = QVariant( v );
199     }
200     break;
201   case DBUS_TYPE_DOUBLE:
202     {
203       double v;
204       dbus_message_iter_get_basic (i, &v);
205       ret = QVariant( v );
206     }
207     break;
208   case DBUS_TYPE_STRING:
209     {
210       const char *v;
211       dbus_message_iter_get_basic (i, &v);
212       ret = QVariant( v );
213     }
214     break;
215   default:
216     ret = QVariant();
217     break;
218   }
219   return ret;
220 }
221
222 /**
223  * Fills QVariant based on what current DBusMessageIter helds.
224  */
225 void
226 Message::iterator::fillVar()
227 {
228   switch ( dbus_message_iter_get_arg_type( d->iter ) ) {
229   case DBUS_TYPE_INT32:
230   case DBUS_TYPE_UINT32:
231   case DBUS_TYPE_DOUBLE:
232   case DBUS_TYPE_STRING:
233     d->var = marshallBaseType( d->iter );
234     break;
235   case DBUS_TYPE_ARRAY: {
236     switch ( dbus_message_iter_get_element_type( d->iter ) ) {
237     case DBUS_TYPE_STRING: {
238       QStringList tempList;
239       DBusMessageIter sub;
240       dbus_message_iter_recurse (d->iter, &sub);
241       while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID)
242         {
243           const char *v;
244           dbus_message_iter_get_basic (&sub, &v);
245           tempList.append( QString( v ) );
246           dbus_message_iter_next (&sub);
247         }
248       d->var = QVariant( tempList );
249       break;
250     }
251     default:
252       qDebug( "Array of type not implemented" );
253       d->var = QVariant();
254       break;
255     }
256     break;
257   }
258 #if 0
259   /* DICT is gone for now, but expected to be reintroduced, or else
260    * reintroduced as a flag on the introspection data that can
261    * apply to array of struct of two fields
262    */
263   case DBUS_TYPE_DICT: {
264     qDebug( "Got a hash!" );
265     QMap<QString, QVariant> tempMap;
266     DBusMessageIter dictIter;
267     dbus_message_iter_init_dict_iterator( d->iter, &dictIter );
268     do {
269       char *key = dbus_message_iter_get_dict_key( &dictIter );
270       tempMap[key] = marshallBaseType( &dictIter );
271       dbus_free( key );
272       dbus_message_iter_next( &dictIter );
273     } while( dbus_message_iter_has_next( &dictIter ) );
274     d->var = QVariant( tempMap );
275     break;
276     qDebug( "Hash/Dict type not implemented" );
277     d->var = QVariant();
278     break;
279   }
280 #endif
281   default:
282     qDebug( "not implemented" );
283     d->var = QVariant();
284     break;
285   }
286 }
287
288 /**
289  * Returns a QVariant help by this iterator.
290  * @return QVariant held by this iterator
291  */
292 QVariant
293 Message::iterator::var() const
294 {
295   return d->var;
296 }
297
298 struct Message::Private {
299   DBusMessage *msg;
300 };
301
302 Message::Message( DBusMessage *m )
303 {
304   d = new Private;
305   d->msg = m;
306 }
307
308 /**
309  *
310  */
311 Message::Message( int messageType )
312 {
313   d = new Private;
314   d->msg = dbus_message_new( messageType );
315 }
316
317 /**
318  * Constructs a new Message with the given service and name.
319  * @param service service service that the message should be sent to
320  * @param name name of the message
321  */
322 Message::Message( const QString& service, const QString& path,
323                   const QString& interface, const QString& method )
324 {
325   d = new Private;
326   d->msg = dbus_message_new_method_call( service.latin1(), path.latin1(),
327                                          interface.latin1(), method.latin1() );
328 }
329
330 /**
331  * Constructs a message that is a reply to some other
332  * message.
333  * @param name the name of the message
334  * @param replayingTo original_message the message which the created
335  * message is a reply to.
336  */
337 Message::Message( const Message& replayingTo )
338 {
339   d = new Private;
340   d->msg = dbus_message_new_method_return( replayingTo.d->msg );
341 }
342
343 Message:: Message( const QString& path, const QString& interface,
344                    const QString& name )
345 {
346   d = new Private;
347   d->msg = dbus_message_new_signal( path.ascii(), interface.ascii(),
348                                     name.ascii() );
349 }
350
351 Message::Message( const Message& replayingTo, const QString& errorName,
352                   const QString& errorMessage )
353 {
354   d = new Private;
355   d->msg = dbus_message_new_error( replayingTo.d->msg, errorName.utf8(),
356                                    errorMessage.utf8() );
357 }
358
359 Message Message::operator=( const Message& other )
360 {
361   //FIXME: ref the other.d->msg instead of copying it?
362 }
363 /**
364  * Destructs message.
365  */
366 Message::~Message()
367 {
368   if ( d->msg ) {
369     dbus_message_unref( d->msg );
370   }
371   delete d; d=0;
372 }
373
374 int Message::type() const
375 {
376   return dbus_message_get_type( d->msg );
377 }
378
379 void Message::setPath( const QString& path )
380 {
381   dbus_message_set_path( d->msg, path.ascii() );
382 }
383
384 QString Message::path() const
385 {
386   return dbus_message_get_path( d->msg );
387 }
388
389 void Message::setInterface( const QString& iface )
390 {
391   dbus_message_set_interface( d->msg, iface.ascii() );
392 }
393
394 QString Message::interface() const
395 {
396   return dbus_message_get_interface( d->msg );
397 }
398
399 void Message::setMember( const QString& member )
400 {
401   dbus_message_set_member( d->msg, member.ascii() );
402 }
403
404 QString Message::member() const
405 {
406   return dbus_message_get_member( d->msg );
407 }
408
409 void Message::setErrorName( const QString& err )
410 {
411   dbus_message_set_error_name( d->msg, err );
412 }
413
414 QString Message::errorName() const
415 {
416   return dbus_message_get_error_name( d->msg );
417 }
418
419 void Message::setDestination( const QString& dest )
420 {
421   dbus_message_set_destination( d->msg, dest );
422 }
423
424 QString Message::destination() const
425 {
426   return dbus_message_get_destination( d->msg );
427 }
428
429 /**
430  * Sets the message sender.
431  * @param sender the sender
432  * @return false if unsuccessful
433  */
434 bool
435 Message::setSender( const QString& sender )
436 {
437   return dbus_message_set_sender( d->msg, sender.latin1() );
438 }
439
440 /**
441  * Returns sender of this message.
442  * @return sender
443  */
444 QString
445 Message::sender() const
446 {
447   return dbus_message_get_sender( d->msg );
448 }
449
450 QString Message::signature() const
451 {
452   return dbus_message_get_signature( d->msg );
453 }
454
455
456 /**
457  * Returns the starting iterator for the fields of this
458  * message.
459  * @return starting iterator
460  */
461 Message::iterator
462 Message::begin() const
463 {
464   return iterator( d->msg );
465 }
466
467 /**
468  * Returns the ending iterator for the fields of this
469  * message.
470  * @return ending iterator
471  */
472 Message::iterator
473 Message::end() const
474 {
475   return iterator();
476 }
477
478 /**
479  * Returns the field at position @p i
480  * @param i position of the wanted field
481  * @return QVariant at position @p i or an empty QVariant
482  */
483 QVariant
484 Message::at( int i )
485 {
486   iterator itr( d->msg );
487
488   while ( i-- ) {
489     if ( itr == end() )
490       return QVariant();//nothing there
491     ++itr;
492   }
493   return *itr;
494 }
495
496 /**
497  * The underlying DBusMessage of this class.
498  * @return DBusMessage pointer.
499  */
500 DBusMessage*
501 Message::message() const
502 {
503   return d->msg;
504 }
505
506 Message& Message::operator<<( bool b )
507 {
508   const dbus_bool_t right_size_bool = b;
509   dbus_message_append_args( d->msg, DBUS_TYPE_BOOLEAN, &right_size_bool,
510                             DBUS_TYPE_INVALID );
511 }
512
513 Message& Message::operator<<( Q_INT8 byte )
514 {
515   dbus_message_append_args( d->msg, DBUS_TYPE_BYTE, &byte,
516                             DBUS_TYPE_INVALID );
517 }
518
519 Message& Message::operator<<( Q_INT32 num )
520 {
521   dbus_message_append_args( d->msg, DBUS_TYPE_INT32, &num,
522                             DBUS_TYPE_INVALID );
523 }
524
525 Message& Message::operator<<( Q_UINT32 num )
526 {
527   dbus_message_append_args( d->msg, DBUS_TYPE_UINT32, &num,
528                             DBUS_TYPE_INVALID );
529 }
530
531 Message& Message::operator<<( Q_INT64 num )
532 {
533   dbus_message_append_args( d->msg, DBUS_TYPE_INT64, &num,
534                             DBUS_TYPE_INVALID );
535 }
536
537 Message& Message::operator<<( Q_UINT64 num )
538 {
539   dbus_message_append_args( d->msg, DBUS_TYPE_UINT64, &num,
540                             DBUS_TYPE_INVALID );
541 }
542
543 Message& Message::operator<<( double num )
544 {
545   dbus_message_append_args( d->msg, DBUS_TYPE_DOUBLE, &num,
546                             DBUS_TYPE_INVALID );
547 }
548
549 Message& Message::operator<<( const QString& str )
550 {
551   const char *u = str.utf8();
552   dbus_message_append_args( d->msg, DBUS_TYPE_STRING, &u,
553                             DBUS_TYPE_INVALID );
554 }
555
556 Message& Message::operator<<( const QVariant& custom )
557 {
558   //FIXME: imeplement
559 }
560
561 }