text: /****************************************************************************
  **
  ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
  ** All rights reserved.
  ** Contact: Nokia Corporation (qt-info@nokia.com)
  **
  ** This file is part of the QtCore module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
  ** This file may be used under the terms of the GNU Lesser General Public
  ** License version 2.1 as published by the Free Software Foundation and
  ** appearing in the file LICENSE.LGPL included in the packaging of this
  ** file. Please review the following information to ensure the GNU Lesser
  ** General Public License version 2.1 requirements will be met:
  ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  **
  ** In addition, as a special exception, Nokia gives you certain additional
  ** rights. These rights are described in the Nokia Qt LGPL Exception
  ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  **
  ** GNU General Public License Usage
  ** Alternatively, this file may be used under the terms of the GNU General
  ** Public License version 3.0 as published by the Free Software Foundation
  ** and appearing in the file LICENSE.GPL included in the packaging of this
  ** file. Please review the following information to ensure the GNU General
  ** Public License version 3.0 requirements will be met:
  ** http://www.gnu.org/copyleft/gpl.html.
  **
  ** Other Usage
  ** Alternatively, this file may be used in accordance with the terms and
  ** conditions contained in a signed written agreement between you and Nokia.
  **
  **
  **
  **
  **
  ** $QT_END_LICENSE$
  **
  ****************************************************************************/
  
  #ifndef QOBJECT_P_H
  #define QOBJECT_P_H
  
  //
  //  W A R N I N G
  //  -------------
  //
  // This file is not part of the Qt API.  It exists for the convenience
  // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp.  This header
  // file may change from version to version without notice, or even be removed.
  //
  // We mean it.
  //
  
  #include "QtCore/qobject.h"
  #include "QtCore/qpointer.h"
  #include "QtCore/qcoreevent.h"
  #include "QtCore/qlist.h"
  #include "QtCore/qvector.h"
  #include "QtCore/qreadwritelock.h"
  #include "QtCore/qvariant.h"
  
  QT_BEGIN_NAMESPACE
  
  class QVariant;
  class QThreadData;
  class QObjectConnectionListVector;
  namespace QtSharedPointer { struct ExternalRefCountData; }
  
  /* mirrored in QtTestLib, DON'T CHANGE without prior warning */
  struct QSignalSpyCallbackSet
  {
      typedef void (*BeginCallback)(QObject *caller, int method_index, void **argv);
      typedef void (*EndCallback)(QObject *caller, int method_index);
      BeginCallback signal_begin_callback,
                      slot_begin_callback;
      EndCallback signal_end_callback,
                  slot_end_callback;
  };
  void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set);
  
  extern QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set;
  
  enum { QObjectPrivateVersion = QT_VERSION };
  
  class Q_CORE_EXPORT QAbstractDeclarativeData
  {
  public:
      static void (*destroyed)(QAbstractDeclarativeData *, QObject *);
      static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *);
      static void (*objectNameChanged)(QAbstractDeclarativeData *, QObject *);
  };
  
  class Q_CORE_EXPORT QObjectPrivate : public QObjectData
  {
      Q_DECLARE_PUBLIC(QObject)
  
  public:
      struct ExtraData
      {
          ExtraData() {}
  #ifndef QT_NO_USERDATA
          QVector<QObjectUserData *> userData;
  #endif
          QList<QByteArray> propertyNames;
          QList<QVariant> propertyValues;
      };
  
      struct Connection
      {
          QObject *sender;
          QObject *receiver;
          int method;
          uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
          QBasicAtomicPointer<int> argumentTypes;
          // The next pointer for the singly-linked ConnectionList
          Connection *nextConnectionList;
          //senders linked list
          Connection *next;
          Connection **prev;
          ~Connection();
      };
      // ConnectionList is a singly-linked list
      struct ConnectionList {
          ConnectionList() : first(0), last(0) {}
          Connection *first;
          Connection *last;
      };
  
      struct Sender
      {
          QObject *sender;
          int signal;
          int ref;
      };
  
  
      QObjectPrivate(int version = QObjectPrivateVersion);
      virtual ~QObjectPrivate();
      void deleteChildren();
  
      void setParent_helper(QObject *);
      void moveToThread_helper();
      void setThreadData_helper(QThreadData *currentData, QThreadData *targetData);
      void _q_reregisterTimers(void *pointer);
  
      bool isSender(const QObject *receiver, const char *signal) const;
      QObjectList receiverList(const char *signal) const;
      QObjectList senderList() const;
  
      void addConnection(int signal, Connection *c);
      void cleanConnectionLists();
  
  #ifdef QT3_SUPPORT
      void sendPendingChildInsertedEvents();
      void removePendingChildInsertedEvents(QObject *child);
  #endif
  
      static inline Sender *setCurrentSender(QObject *receiver,
                                      Sender *sender);
      static inline void resetCurrentSender(QObject *receiver,
                                     Sender *currentSender,
                                     Sender *previousSender);
      static int *setDeleteWatch(QObjectPrivate *d, int *newWatch);
      static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch);
      static void clearGuards(QObject *);
  
      static QObjectPrivate *get(QObject *o) {
          return o->d_func();
      }
  
      int signalIndex(const char *signalName) const;
      inline bool isSignalConnected(uint signalIdx) const;
  
  public:
      QString objectName;
      ExtraData *extraData;    // extra data set by the user
      QThreadData *threadData; // id of the thread that owns the object
  
      QObjectConnectionListVector *connectionLists;
  
      Connection *senders;     // linked list of connections connected to this object
      Sender *currentSender;   // object currently activating the object
      mutable quint32 connectedSignals[2];
  
  #ifdef QT3_SUPPORT
      QList<QObject *> pendingChildInsertedEvents;
  #else
      // preserve binary compatibility with code compiled without Qt 3 support
      // keeping the binary layout stable helps the Qt Creator debugger
      void *unused;
  #endif
  
      QList<QPointer<QObject> > eventFilters;
      union {
          QObject *currentChildBeingDeleted;
          QAbstractDeclarativeData *declarativeData; //extra data used by the declarative module
      };
  
      // these objects are all used to indicate that a QObject was deleted
      // plus QPointer, which keeps a separate list
      QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
      int *deleteWatch;
  };
  
  
  /*! \internal
  
    Returns true if the signal with index \a signal_index from object \a sender is connected.
    Signals with indices above a certain range are always considered connected (see connectedSignals
    in QObjectPrivate). If a signal spy is installed, all signals are considered connected.
  
    \a signal_index must be the index returned by QObjectPrivate::signalIndex;
  */
  inline bool QObjectPrivate::isSignalConnected(uint signal_index) const
  {
      return signal_index >= sizeof(connectedSignals) * 8
          || (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f))
          || qt_signal_spy_callback_set.signal_begin_callback
          || qt_signal_spy_callback_set.signal_end_callback);
  }
  
  inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver,
                                                           Sender *sender)
  {
      Sender *previousSender = receiver->d_func()->currentSender;
      receiver->d_func()->currentSender = sender;
      return previousSender;
  }
  
  inline void QObjectPrivate::resetCurrentSender(QObject *receiver,
                                          Sender *currentSender,
                                          Sender *previousSender)
  {
      // ref is set to zero when this object is deleted during the metacall
      if (currentSender->ref == 1)
          receiver->d_func()->currentSender = previousSender;
      // if we've recursed, we need to tell the caller about the objects deletion
      if (previousSender)
          previousSender->ref = currentSender->ref;
  }
  
  
  Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE);
  Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE);
  
  class QSemaphore;
  class Q_CORE_EXPORT QMetaCallEvent : public QEvent
  {
  public:
      QMetaCallEvent(int id, const QObject *sender, int signalId,
                     int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0);
      ~QMetaCallEvent();
  
      inline int id() const { return id_; }
      inline const QObject *sender() const { return sender_; }
      inline int signalId() const { return signalId_; }
      inline void **args() const { return args_; }
  
      virtual int placeMetaCall(QObject *object);
  
  private:
      int id_;
      const QObject *sender_;
      int signalId_;
      int nargs_;
      int *types_;
      void **args_;
      QSemaphore *semaphore_;
  };
  
  class QBoolBlocker
  {
  public:
      inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;}
      inline ~QBoolBlocker(){block = reset; }
  private:
      bool &block;
      bool reset;
  };
  
  void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o);
  
  
  struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QMetaObject
  {
      virtual ~QAbstractDynamicMetaObject() {}
      virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; }
      virtual int createProperty(const char *, const char *) { return -1; }
  };
  
  QT_END_NAMESPACE
  
  #endif // QOBJECT_P_H
  