~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to kde/src/canvasobjectmanager.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (C) 2013-2014 by Savoir-Faire Linux                         *
 
3
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>*
 
4
 *                                                                         *
 
5
 *   This program is free software; you can redistribute it and/or modify  *
 
6
 *   it under the terms of the GNU General Public License as published by  *
 
7
 *   the Free Software Foundation; either version 3 of the License, or     *
 
8
 *   (at your option) any later version.                                   *
 
9
 *                                                                         *
 
10
 *   This program is distributed in the hope that it will be useful,       *
 
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 
13
 *   GNU General Public License for more details.                          *
 
14
 *                                                                         *
 
15
 *   You should have received a copy of the GNU General Public License     *
 
16
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
 
17
 **************************************************************************/
 
18
#include "canvasobjectmanager.h"
 
19
 
 
20
//Qt
 
21
#include <QtCore/QDebug>
 
22
#include <QtCore/QTimer>
 
23
#include <QtGui/QApplication>
 
24
 
 
25
//X11
 
26
#ifdef Q_WS_X11
 
27
// #include <xcb/xcb.h>
 
28
// #include <xcb/xcb_atom.h>
 
29
#endif
 
30
 
 
31
//KDE
 
32
#include <KNotification>
 
33
#include <KLocale>
 
34
 
 
35
//SFLPhone
 
36
#include <klib/tipmanager.h>
 
37
#include <widgets/tips/tipcollection.h>
 
38
#include "sflphone.h"
 
39
 
 
40
 
 
41
CanvasObjectManager::Object CanvasObjectManager::m_slEvents[EVENT_COUNT] = { CanvasObjectManager::Object::NoObject };
 
42
 
 
43
#define OBJ_DEF(obj) elements[static_cast<int>(obj)]
 
44
#define _(NAME) CanvasObjectManager::Object##NAME::
 
45
#define E CanvasEvent
 
46
const CanvasObjectManager::CanvasElement CanvasObjectManager::elements[ELEMENT_COUNT] = {
 
47
   /*                  ObjectType       ObjectLifeCycle        ObjectPriority             IN-EVENT                   OUT-EVENT         STACK   NOTIFY */
 
48
   /*0 NoObject     */ {_(Type)OBJECT , _(LifeCycle)STATIC , _(Priority)NO_PRIORITY, E::NONE                    , E::ANY               , false , false  , false},
 
49
   /*1 DialInfo     */ {_(Type)OBJECT , _(LifeCycle)STATIC , _(Priority)LOW        , E::NO_CALLS                , E::ANY               , false , false  , false},
 
50
   /*2 EndCall      */ {_(Type)OBJECT , _(LifeCycle)TIMED  , _(Priority)LOW        , E::CALL_ENDED              , E::ANY               , false , true   , false},
 
51
   /*3 Ringing      */ {_(Type)OBJECT , _(LifeCycle)EVENT  , _(Priority)MEDIUM     , E::CALL_RINGING            , E::CALL_STATE_CHANGED
 
52
                                                                                                                 | E::CALL_ENDED
 
53
                                                                                                                 | E::CALL_BUSY        , true  , false  , false},
 
54
   /*4 Network      */ {_(Type)OBJECT , _(LifeCycle)EVENT  , _(Priority)MEDIUM     , E::NETWORK_ERROR           , E::NETWORK_BACK
 
55
                                                                                                                 |E::REGISTERED_ACCOUNT
 
56
                                                                                                                 |E::CALL_RINGING      , false , true   , false},
 
57
   /*5 AutoComplete */ {_(Type)WIDGET , _(LifeCycle)EVENT  , _(Priority)HIGH       , E::CALL_DIALING_CHANGED    , E::CALL_STATE_CHANGED
 
58
                                                                                                                 | E::CALL_ENDED
 
59
                                                                                                                 | E::CALL_RINGING
 
60
                                                                                                                 | E::CALL_BUSY        , false , false  , true },
 
61
   /*6 DropInfo     */ {_(Type)OBJECT , _(LifeCycle)EVENT  , _(Priority)MEDIUM     , E::DRAG_ENTER|E::DRAG_MOVE , E::DRAG_LEAVE|E::DROP, false , false  , false},
 
62
   /*7 ConfInfo     */ {_(Type)OBJECT , _(LifeCycle)EVENT  , _(Priority)LOW        , E::CALL_COUNT_CHANGED      , E::ANY               , false , false  , false},
 
63
   /*8 AccountDown  */ {_(Type)OBJECT , _(LifeCycle)EVENT  , _(Priority)HIGH       , E::UNREGISTERED_ACCOUNT    , E::ANY               , false , true   , false},
 
64
};
 
65
#undef _
 
66
#undef E
 
67
 
 
68
void CanvasObjectManager::hInitEvents() {
 
69
   static bool init = false;
 
70
   if (!init) {
 
71
      for (int i=0;i<EVENT_COUNT-1;i++) {
 
72
         for (int j=1;j<ELEMENT_COUNT;j++) {
 
73
            if (OBJ_DEF(j).inEvent & (0x01<<i))
 
74
               CanvasObjectManager::m_slEvents[i+1] = static_cast<CanvasObjectManager::Object>(j);
 
75
         }
 
76
      }
 
77
      init = true;
 
78
   }
 
79
}
 
80
 
 
81
CanvasObjectManager::CanvasObjectManager(QObject* parent) : QObject(parent),m_DisableTransition(false),
 
82
m_CurrentObject(CanvasObjectManager::Object::NoObject),m_NextObject(CanvasObjectManager::Object::NoObject)
 
83
,m_pTimer(nullptr),m_CurrentState(ObjectState::NO_OBJECT),m_Minimized(false)
 
84
{
 
85
   hInitEvents();
 
86
 
 
87
//    m_DisableTransition = true;
 
88
   connect(TipCollection::manager(),SIGNAL(transitionStarted(QAbstractAnimation::Direction,QAbstractAnimation::State)),
 
89
      this,SLOT(slotTransitionEvents(QAbstractAnimation::Direction,QAbstractAnimation::State)));
 
90
 
 
91
 
 
92
   //TODO remove
 
93
//    testEventToEvent    ();
 
94
//    testEvenToObject    ();
 
95
//    testFirstInEvent    ();
 
96
//    testObjectPriority  ();
 
97
//    testObjectDiscarding();
 
98
}
 
99
 
 
100
CanvasObjectManager::~CanvasObjectManager()
 
101
{
 
102
   //Nothing to do
 
103
}
 
104
 
 
105
///This function take a *SINGLE* flag as parameter, return corresponding object
 
106
CanvasObjectManager::Object CanvasObjectManager::eventToObject(CanvasEvent event) const
 
107
{
 
108
   const int power = eventFlagToIndex(event);
 
109
   return m_slEvents[power];
 
110
}
 
111
 
 
112
///This function take a *MULTIPLE* flag as parameter, return corresponding object
 
113
QList<CanvasObjectManager::Object> CanvasObjectManager::eventsToObjects(CanvasEvent events) const
 
114
{
 
115
   Q_UNUSED(events);
 
116
   //TODO
 
117
   return QList<CanvasObjectManager::Object>();
 
118
}
 
119
 
 
120
///Get the first event triggering an object (for testing purpose only)
 
121
CanvasObjectManager::CanvasEvent CanvasObjectManager::firstInEvent( Object object ) const
 
122
{
 
123
   if (!OBJ_DEF(object).inEvent)
 
124
      return CanvasObjectManager::CanvasEvent::NONE;
 
125
 
 
126
   for (int power=0;power<EVENT_COUNT-1;power++) {
 
127
      if (m_slEvents[power+1] == object)
 
128
         return static_cast<CanvasObjectManager::CanvasEvent>(0x01<<power);
 
129
   }
 
130
   return CanvasObjectManager::CanvasEvent::NONE;
 
131
}
 
132
 
 
133
 
 
134
CanvasObjectManager::CanvasEvent CanvasObjectManager::eventIndexToFlag(int index) const
 
135
{
 
136
   if (!index || index > EVENT_COUNT-1)
 
137
      return CanvasEvent::NONE;
 
138
   return index==1?CanvasEvent::ANY:static_cast<CanvasEvent>(0x01<<(index-1));
 
139
}
 
140
 
 
141
int CanvasObjectManager::eventFlagToIndex(CanvasObjectManager::CanvasEvent events) const
 
142
{
 
143
   if (!events)
 
144
      return 0;
 
145
   else if (events == CanvasEvent::ANY)
 
146
      return 1;
 
147
   else {
 
148
      for (int power = EVENT_COUNT;power;power--)
 
149
         if (events & (0x01<<power)) return power+1;
 
150
   }
 
151
   return 0;
 
152
}
 
153
 
 
154
void CanvasObjectManager::initiateOutTransition(bool skipAnimation)
 
155
{
 
156
//    qDebug() << "IN OUT" << (int)m_NextObject << (int)m_CurrentObject;
 
157
   if (m_NextObject != m_CurrentObject) {
 
158
      if (m_DisableTransition || skipAnimation) {
 
159
         if (m_pTimer && m_pTimer->isActive())
 
160
            m_pTimer->stop();
 
161
         m_CurrentObject = m_NextObject;
 
162
         TipCollection::manager()->hideCurrentTip(true);
 
163
         m_NextObject    = CanvasObjectManager::Object::NoObject;
 
164
      }
 
165
      else {
 
166
         //TODO
 
167
         if (m_CurrentObject != Object::NoObject) {
 
168
            switch (OBJ_DEF(m_CurrentObject).type) {
 
169
               case ObjectType::OBJECT: {
 
170
                  //If hideCurrentTip return true, then act as if the transition was over
 
171
//                   qDebug() << "\n\n\nMMMMM" << OBJ_DEF(m_CurrentObject).skipAnimation << (int)m_NextObject;
 
172
                  if (TipCollection::manager()->hideCurrentTip(OBJ_DEF(m_NextObject).skipAnimation)) {
 
173
      //                qDebug() << "PROBLEM";
 
174
                     m_CurrentObject = m_NextObject;
 
175
                     m_NextObject    = CanvasObjectManager::Object::NoObject;
 
176
                  }
 
177
                  } break;
 
178
               case ObjectType::WIDGET: {
 
179
//                   qDebug() << "OUT WIDGET";
 
180
                  QWidget* w = TipCollection::canvasWidgetsToTip(m_CurrentObject);
 
181
                  if (w) {
 
182
                     w->setVisible(false);
 
183
                     m_CurrentObject = m_NextObject;
 
184
                     m_NextObject    = CanvasObjectManager::Object::NoObject;
 
185
                  }
 
186
                  } break;
 
187
   //             qDebug() << "SHOULD HIDE TIP" << (int)m_NextObject;
 
188
            };
 
189
         }
 
190
      }
 
191
   }
 
192
}
 
193
 
 
194
void CanvasObjectManager::initiateInTransition(Object nextObj,const QString& message)
 
195
{
 
196
//    qDebug() << "HERE" << (int)m_CurrentState << m_DisableTransition << (int)nextObj;
 
197
   if (nextObj != m_CurrentObject) {
 
198
      if (m_DisableTransition || m_CurrentState == ObjectState::NO_OBJECT) {
 
199
         if (m_pTimer && m_pTimer->isActive())
 
200
            m_pTimer->stop();
 
201
         m_CurrentObject = nextObj;
 
202
         nextObj = CanvasObjectManager::Object::NoObject;
 
203
         switch (OBJ_DEF(m_CurrentObject).type) {
 
204
            case ObjectType::OBJECT: {
 
205
               Tip* currentTip = TipCollection::canvasObjectToTip(m_CurrentObject);
 
206
               if (currentTip) {
 
207
                  if (OBJ_DEF(m_CurrentObject).lifeCycle == ObjectLifeCycle::TIMED && currentTip->timeout()) {
 
208
                     if (!m_pTimer) {
 
209
                        m_pTimer = new QTimer(this);
 
210
                        m_pTimer->setSingleShot(true);
 
211
                        connect(m_pTimer,SIGNAL(timeout()),this,SLOT(slotTimeout()));
 
212
                     }
 
213
                     if (!message.isEmpty()) {
 
214
                        currentTip->setText(message);
 
215
                     }
 
216
                     m_pTimer->setInterval(currentTip->timeout());
 
217
                     m_pTimer->start();
 
218
                  }
 
219
                  //If the window is minimized, use system notification
 
220
                  const QString m = message.isEmpty()?currentTip->text():message;
 
221
                  if (m_Minimized && !m.isEmpty())
 
222
                     KNotification::event(KNotification::Notification, i18n("SFLPhone"), m);
 
223
                  //If the window is not focused and the object request notification, use system
 
224
                  //disabled as it is not implemented by many top tier window managers
 
225
#ifdef Q_WS_X11
 
226
// Doesn't work on most window managers
 
227
//                   static xcb_connection_t *c = nullptr;
 
228
//                   if (c || (c = xcb_connect(nullptr,nullptr))) {
 
229
//                      xcb_window_t win = SFLPhone::app()->winId();
 
230
//                      xcb_generic_error_t *error;
 
231
//                      xcb_intern_atom_cookie_t cookie = xcb_intern_atom(c, 0, strlen("_NET_WM_STATE_FOCUSED"), "_NET_WM_STATE_FOCUSED");
 
232
//                      xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(c, cookie, &error);
 
233
//                      static xcb_atom_t _NET_WM_STATE_FOCUSED = reply->atom;
 
234
//                      xcb_get_property_cookie_t propC = xcb_get_property_unchecked(c, false, win,_NET_WM_STATE_FOCUSED, XCB_GET_PROPERTY_TYPE_ANY, 0, 1);
 
235
//                      xcb_get_property_reply_t *replyP = xcb_get_property_reply(c, propC, NULL);
 
236
//                      if (replyP) {
 
237
//                         bool isFocused = *((bool*)xcb_get_property_value(replyP));
 
238
//                         qDebug() << "\n\n\nClient is focused" <<isFocused;
 
239
//                         free(replyP);
 
240
//                      }
 
241
//                      free(reply);
 
242
//                      qDebug() << "\n\nNOTIF" << QApplication::activeWindow() << OBJ_DEF(m_CurrentObject).systemNotification;
 
243
//                      if (!QApplication::activeWindow() && OBJ_DEF(m_CurrentObject).systemNotification) {
 
244
//                         KNotification::event(KNotification::Notification, i18n("SFLPhone"), message.isEmpty()?currentTip->text():message);
 
245
//                      }
 
246
//                   }
 
247
#endif
 
248
               }
 
249
               TipCollection::manager()->setCurrentTip(currentTip);
 
250
 
 
251
 
 
252
               } break;
 
253
            case ObjectType::WIDGET:
 
254
               QWidget* w = TipCollection::canvasWidgetsToTip(m_CurrentObject);
 
255
               if (w) {
 
256
                  w->setVisible(true);
 
257
               }
 
258
               break;
 
259
         };
 
260
      }
 
261
      else {
 
262
//          qDebug() << "CURRENT IS VISIBLE" <<(int)m_CurrentObject << "next" << (int)nextObj;
 
263
         m_NextObject = nextObj;
 
264
         initiateOutTransition();
 
265
      }
 
266
   }
 
267
}
 
268
 
 
269
bool CanvasObjectManager::newEvent(CanvasEvent events, const QString& message)
 
270
{
 
271
//    qDebug() << "NEW EVENT" << events << message << (int)m_CurrentState << (int)m_CurrentObject << (OBJ_DEF(m_CurrentObject).outEvent & events);
 
272
 
 
273
   const bool singleEvent = (events & (events - 1)) == 0;
 
274
   CanvasObjectManager::Object nextObj = eventToObject(events);
 
275
 
 
276
   //First, notify the current object of the new event, it may be discarded
 
277
   if (m_CurrentObject != CanvasObjectManager::Object::NoObject && OBJ_DEF(m_CurrentObject).outEvent & events) {
 
278
//       qDebug() << "OUT (dsfsdf)";
 
279
      initiateOutTransition(singleEvent && OBJ_DEF(nextObj).skipAnimation);
 
280
   }
 
281
 
 
282
   //Detect if there is multiple flags set
 
283
   if (singleEvent) {
 
284
//       qDebug() << "IS SINGLE" << (OBJ_DEF(nextObj).priority >= OBJ_DEF(m_CurrentObject).priority) << (int)nextObj << (int)m_CurrentObject << (int) m_CurrentState;
 
285
      if (OBJ_DEF(nextObj).priority >= OBJ_DEF(m_CurrentObject).priority || m_CurrentState == ObjectState::TRANSITION_OUT) {
 
286
//          qDebug() << "In IF";
 
287
         initiateInTransition(nextObj,message);
 
288
         return true;
 
289
      }
 
290
   }
 
291
   else {
 
292
      QList<CanvasObjectManager::Object> nextObjs = CanvasObjectManager::eventsToObjects(events);
 
293
      CanvasObjectManager::Object highestPriorityNextObj = CanvasObjectManager::Object::NoObject;
 
294
      foreach(const CanvasObjectManager::Object& nextObj, nextObjs) {
 
295
         if (OBJ_DEF(nextObj).priority > OBJ_DEF(highestPriorityNextObj).priority)
 
296
            highestPriorityNextObj = nextObj;
 
297
      }
 
298
      if (highestPriorityNextObj != CanvasObjectManager::Object::NoObject) {
 
299
         initiateInTransition(highestPriorityNextObj,message);
 
300
         return true;
 
301
//          qDebug() << "ret";
 
302
      }
 
303
   }
 
304
//    qDebug() << "ret";
 
305
   return false;
 
306
}
 
307
 
 
308
void CanvasObjectManager::reset()
 
309
{
 
310
   if (m_CurrentObject != CanvasObjectManager::Object::NoObject) {
 
311
      //TODO
 
312
   }
 
313
   if (m_pTimer && m_pTimer->isActive())
 
314
      m_pTimer->stop();
 
315
   m_CurrentObject = CanvasObjectManager::Object::NoObject;
 
316
   TipCollection::manager()->hideCurrentTip(true);
 
317
}
 
318
 
 
319
bool CanvasObjectManager::operator<<(CanvasEvent events)
 
320
{
 
321
   return newEvent(events);
 
322
}
 
323
 
 
324
CanvasObjectManager::Object CanvasObjectManager::currentObject() const
 
325
{
 
326
   return m_CurrentObject;
 
327
}
 
328
 
 
329
CanvasObjectManager::Object CanvasObjectManager::nextObject   () const
 
330
{
 
331
   return m_NextObject;
 
332
}
 
333
 
 
334
 
 
335
 
 
336
void CanvasObjectManager::slotTimeout()
 
337
{
 
338
   //Hide the canvas object, stopping the countdown should be handled elsewhere
 
339
   initiateOutTransition();
 
340
}
 
341
 
 
342
void CanvasObjectManager::slotTransitionEvents(QAbstractAnimation::Direction direction, QAbstractAnimation::State state)
 
343
{
 
344
//    qDebug() << "IN TRANSITION EVENT" << direction << state;
 
345
   switch(state) {
 
346
      case QAbstractAnimation::Stopped:
 
347
         if (m_CurrentObject == Object::NoObject) {
 
348
            m_CurrentState = ObjectState::NO_OBJECT;
 
349
//             qDebug() << "HERE4" << (int)m_NextObject;
 
350
            if (m_NextObject != Object::NoObject) {
 
351
               initiateInTransition(m_NextObject);
 
352
               m_NextObject = Object::NoObject;
 
353
            }
 
354
         }
 
355
         else
 
356
            switch (direction) {
 
357
               case QAbstractAnimation::Forward:
 
358
                  m_CurrentState = ObjectState::VISIBLE;
 
359
//                   qDebug() << "HERE2";
 
360
                  break;
 
361
               case QAbstractAnimation::Backward:
 
362
                  m_CurrentState = ObjectState::NO_OBJECT;
 
363
//                   qDebug() << "HERE3" << (int) m_NextObject;
 
364
                  initiateInTransition(m_NextObject);
 
365
                  m_NextObject = Object::NoObject;
 
366
                  break;
 
367
            };
 
368
         break;
 
369
      case QAbstractAnimation::Paused:
 
370
         //TODO
 
371
         break;
 
372
      case QAbstractAnimation::Running:
 
373
         switch (direction) {
 
374
            case QAbstractAnimation::Forward:
 
375
               m_CurrentState = ObjectState::TRANSITION_IN;
 
376
               break;
 
377
            case QAbstractAnimation::Backward:
 
378
               m_CurrentState = ObjectState::TRANSITION_OUT;
 
379
               break;
 
380
         };
 
381
         break;
 
382
   };
 
383
}
 
384
 
 
385
void CanvasObjectManager::slotMinimized(bool isMinimized)
 
386
{
 
387
   m_Minimized = isMinimized;
 
388
}
 
389
 
 
390
 
 
391
 
 
392
 
 
393
 
 
394
 
 
395
 
 
396
 
 
397
 
 
398
bool CanvasObjectManager::testEventToEvent() const
 
399
{
 
400
   /* This test is to validate the the event table is correctly generated
 
401
    * from the structured elements transition table ("elements"). Each
 
402
    * event can be mapped to ONE AND ONLY ONE canvas object
 
403
    *
 
404
    * INPUT:  element structure
 
405
    * OUTPUT: events
 
406
    */
 
407
 
 
408
   hInitEvents();
 
409
 
 
410
   bool success = true;
 
411
 
 
412
   for (int j=0;j<ELEMENT_COUNT;j++) {
 
413
      CanvasObjectManager::Object obj = static_cast<CanvasObjectManager::Object>(j);
 
414
      const CanvasElement& element = OBJ_DEF(j);
 
415
      for (int power=0;power<EVENT_COUNT;power++) {
 
416
         if (element.inEvent & (0x01<<power)) {
 
417
            if (m_slEvents[power+1] != obj) {
 
418
               qDebug() << "testEventToEvent failed, event:" << power << "should map to:"
 
419
                  << j << "but map to" << (int)m_slEvents[power+1];
 
420
               success = false;
 
421
            }
 
422
         }
 
423
      }
 
424
   }
 
425
   qDebug() << "\n\n\ntestEventToEvent" << success;
 
426
   return success;
 
427
}
 
428
 
 
429
bool CanvasObjectManager::testEvenToObject() const
 
430
{
 
431
   /* This test validate the translation between events and object.
 
432
    * 
 
433
    * INPUT: events
 
434
    * OUTPUT: objects
 
435
    */
 
436
 
 
437
   hInitEvents();
 
438
 
 
439
   bool success = true;
 
440
 
 
441
   //0 is none and 1 any, so those need to be tested separately
 
442
   for (int index=2;index<EVENT_COUNT;index++) {
 
443
      CanvasObjectManager::CanvasEvent ev = eventIndexToFlag(index);
 
444
      if (eventToObject(ev) != m_slEvents[index]) {
 
445
         qDebug() << "testEvenToObject failed, power map to " << (int) m_slEvents[index]
 
446
            << "but eventToObject return" << (int)eventToObject(ev);
 
447
         success = false;
 
448
      }
 
449
   }
 
450
 
 
451
   qDebug() << "\n\n\ntestEvenToObject" << success;
 
452
 
 
453
   return success;
 
454
}
 
455
 
 
456
 
 
457
bool CanvasObjectManager::testFirstInEvent() const
 
458
{
 
459
   bool success = true;
 
460
   for (int j=0;j<ELEMENT_COUNT;j++) {
 
461
      CanvasObjectManager::CanvasEvent ev = firstInEvent(static_cast<CanvasObjectManager::Object>(j));
 
462
      if ((!(OBJ_DEF(j).inEvent & ev)) && OBJ_DEF(j).inEvent) {
 
463
         qDebug() << "testFirstInEvent failed" << j << "event is " << ev << " valid events:" << OBJ_DEF(j).inEvent;
 
464
         success = false;
 
465
      }
 
466
   }
 
467
   qDebug() << "\n\n\ntestFirstInEvent" << success;
 
468
   return success;
 
469
}
 
470
 
 
471
bool CanvasObjectManager::testObjectPriority()
 
472
{
 
473
   /* This test validate every possible transition to see if the event
 
474
    * always end up changing the currentObject to something of higher priority
 
475
    * 
 
476
    */
 
477
   m_DisableTransition = true;
 
478
   bool success = true;
 
479
   for (int j=0;j<ELEMENT_COUNT;j++) {
 
480
      CanvasObjectManager::Object obj = static_cast<CanvasObjectManager::Object>(j);
 
481
      for (int i=0;i<ELEMENT_COUNT;i++) {
 
482
         CanvasObjectManager::Object next = static_cast<CanvasObjectManager::Object>(i);
 
483
         reset();
 
484
         initiateInTransition(obj);
 
485
         if(obj!=m_CurrentObject) {
 
486
            qDebug() << "Current object mismatch";
 
487
            success = false;
 
488
         }
 
489
         Q_ASSERT(obj == m_CurrentObject);
 
490
         const bool overrideObj = newEvent(firstInEvent(next));
 
491
         if ((OBJ_DEF(next).priority >= OBJ_DEF(obj).priority) != overrideObj && !(obj != CanvasObjectManager::Object::NoObject && OBJ_DEF(obj).outEvent & firstInEvent(next))) {
 
492
            qDebug() << "PRE" << OBJ_DEF(obj).outEvent << firstInEvent(next) << (OBJ_DEF(obj).outEvent&&firstInEvent(next));
 
493
            qDebug() << "testObjectPriority failed" << (int)next << ((overrideObj)?"override":"doesn't override")
 
494
               << (int)obj << "current priority:" << OBJ_DEF(obj).priority << "next priority" << OBJ_DEF(next).priority << "..." << (int)m_CurrentObject;
 
495
            success = false;
 
496
         }
 
497
      }
 
498
   }
 
499
   qDebug() << "\n\n\ntestObjectPriority" << success;
 
500
   return success;
 
501
}
 
502
 
 
503
bool CanvasObjectManager::testObjectDiscarding()
 
504
{
 
505
   /* This test validate if every objects is discarded by the right events
 
506
    * 
 
507
    * 
 
508
    */
 
509
   m_DisableTransition = true;
 
510
   bool success = true;
 
511
 
 
512
   //First, lets test "ANY"
 
513
   for (int j=0;j<ELEMENT_COUNT;j++) {
 
514
      if (OBJ_DEF(j).outEvent == CanvasEvent::ANY) {
 
515
         for (int index=1;index<EVENT_COUNT;index++) {
 
516
            const CanvasEvent event = eventIndexToFlag(index);
 
517
            CanvasObjectManager::Object next = static_cast<CanvasObjectManager::Object>(j);
 
518
            reset();
 
519
            initiateInTransition(next);
 
520
            newEvent(static_cast<CanvasEvent>(event));
 
521
            if ((next == currentObject() && m_slEvents[index] != next)
 
522
               && !(next == currentObject() && currentObject() == CanvasObjectManager::Object::NoObject )) {
 
523
               qDebug() << "testObjectDiscarding failed with ANY, was" << j << "is" << (int)m_CurrentObject << event << (event == CanvasEvent::ANY);
 
524
               success = false;
 
525
            }
 
526
         }
 
527
      }
 
528
   }
 
529
 
 
530
   for (int j=0;j<ELEMENT_COUNT;j++) {
 
531
      if (OBJ_DEF(j).outEvent != CanvasEvent::ANY) {
 
532
         for (int index=2;index<EVENT_COUNT;index++) {
 
533
            CanvasObjectManager::Object next = static_cast<CanvasObjectManager::Object>(j);
 
534
            reset();
 
535
            initiateInTransition(next);
 
536
            const CanvasEvent event = eventIndexToFlag(index);
 
537
            newEvent(static_cast<CanvasEvent>(event));
 
538
            if ( OBJ_DEF(next).outEvent & event && next == currentObject() ) {
 
539
               qDebug() << "ntestObjectDiscarding failed, event #" << index << "should discard" << (int)next;
 
540
               success = false;
 
541
            }
 
542
         }
 
543
      }
 
544
   }
 
545
 
 
546
   qDebug() << "\n\n\ntestObjectDiscarding"<<success;
 
547
   return false;
 
548
}
 
549
 
 
550
#undef OBJ_DEF