Пример #1
0
PyObject *PythonQtMemberFunction_Call(PythonQtSlotInfo* info, PyObject* m_self, PyObject *args, PyObject *kw)
{
  if (PyObject_TypeCheck(m_self, &PythonQtInstanceWrapper_Type)) {
    PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) m_self;
    if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
      QString error = QString("Trying to call '") + info->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
      PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
      return NULL;
    } else {
      return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
    }
  } else if (m_self->ob_type == &PythonQtClassWrapper_Type) {
    PythonQtClassWrapper* type = (PythonQtClassWrapper*) m_self;
    if (info->isClassDecorator()) {
      return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
    } else {
      // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
      Py_ssize_t argc = PyTuple_Size(args);
      if (argc>0) {
        PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
        if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
          && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
          PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
          if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
            QString error = QString("Trying to call '") + info->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
            PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
            return NULL;
          }
          // strip the first argument...
          PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
          PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
          Py_DECREF(newargs);
          return result;
        } else {
          // first arg is not of correct type!
          QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
          PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
          return NULL;
        }
      } else {
        // wrong number of args
        QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
        PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
        return NULL;
      }
    }
  }
  return NULL;
}
static PyObject* PythonQtInstanceWrapper_binaryfunc(PyObject* self, PyObject* other, const QByteArray& opName, const QByteArray& fallbackOpName = QByteArray())
{
  // since we disabled type checking, we can receive any object as self, but we currently only support
  // different objects on the right. Otherwise we would need to generate __radd__ etc. methods.
  if (!PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
    QString error = "Unsupported operation " + opName + "(" + self->ob_type->tp_name + ", " +  other->ob_type->tp_name + ")";
    PyErr_SetString(PyExc_ArithmeticError, error.toLatin1().data());
    return NULL;
  }
  PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
  PyObject* result = NULL;
  PythonQtMemberInfo opSlot = wrapper->classInfo()->member(opName);
  if (opSlot._type == PythonQtMemberInfo::Slot) {
    // TODO get rid of tuple
    PyObject* args = PyTuple_New(1);
    Py_INCREF(other);
    PyTuple_SET_ITEM(args, 0, other);
    result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
    Py_DECREF(args);
    if (!result && !fallbackOpName.isEmpty()) {
      // try fallback if we did not get a result
      result = PythonQtInstanceWrapper_binaryfunc(self, other, fallbackOpName);
    }
  }
  return result;
}
static PyObject* PythonQtInstanceWrapper_invert(PythonQtInstanceWrapper* wrapper)
{
  PyObject* result = NULL;
  static QByteArray memberName = "__invert__";
  PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
  if (opSlot._type == PythonQtMemberInfo::Slot) {
    result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
  }
  return result;
}
Пример #4
0
PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
{
  PythonQtMemberInfo deleteSlot = self->classInfo()->member("py_delete");
  if (deleteSlot._type == PythonQtMemberInfo::Slot) {
    // call the py_delete slot instead of internal C++ destructor...
    PyObject* resultObj = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, deleteSlot._slot, NULL, NULL, self->_wrappedPtr);
    Py_XDECREF(resultObj);
  } else {
    PythonQtInstanceWrapper_deleteObject(self, true);
  }
  Py_INCREF(Py_None);
  return Py_None;
}
static int PythonQtInstanceWrapper_nonzero(PythonQtInstanceWrapper* wrapper)
{
  int result = (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
  if (result) {
    static QByteArray memberName = "__nonzero__";
    PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
    if (opSlot._type == PythonQtMemberInfo::Slot) {
      PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
      if (resultObj == Py_False) {
        result = 0;
      }
      Py_XDECREF(resultObj);
    }
  }
  return result;
}
int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
{
  if (args == PythonQtPrivate::dummyTuple()) {
    // we are called from the internal PythonQt API, so our data will be filled later on...
    return 0;
  }

  // we are called from python, try to construct our object
  if (self->classInfo()->constructors()) {
    void* directCPPPointer = NULL;
    PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
    if (PyErr_Occurred()) {
      return -1;
    }
    if (directCPPPointer) {
      // change ownershipflag to be owned by PythonQt
      self->_ownedByPythonQt = true;
      self->_useQMetaTypeDestroy = false;
      if (self->classInfo()->isCPPWrapper()) {
        self->_wrappedPtr = directCPPPointer;
        // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
      } else {
        self->setQObject((QObject*)directCPPPointer);
      }
      // register with PythonQt
      PythonQt::priv()->addWrapperPointer(directCPPPointer, self);

      PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
      if (cb) {
        // if we are a derived python class, we set the wrapper
        // to activate the shell class, otherwise we just ignore that it is a shell...
        // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
        // which is the case for all non-python derived types
        if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
          // set the wrapper and remember that we have a shell instance!
          (*cb)(directCPPPointer, self);
          self->_isShellInstance = true;
        }
      }
    }
  } else {
    QString error = QString("No constructors available for ") + self->classInfo()->className();
    PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
    return -1;
  }
  return 0;
}
PyObject *PythonQtMetaObjectWrapper_call(PyObject *func, PyObject *args, PyObject *kw) {
  PythonQtMetaObjectWrapper* wrapper = (PythonQtMetaObjectWrapper*)func;
  PyObject* result = NULL;
  QString error;
  PyObject* err = NULL;
  if (wrapper->_info->constructors()) {
    result = PythonQtSlotFunction_CallImpl(NULL, wrapper->_info->constructors(), args, kw);
    err = PyErr_Occurred();
  }
  if (!result) {
    QObject* v = NULL;
    QListIterator<PythonQtConstructorHandler*> it(PythonQt::self()->constructorHandlers());
    while (!v && it.hasNext()) {
      v = it.next()->create(wrapper->_info->metaObject(), args, kw, error);
    }
    if (v) {
      result = PythonQt::priv()->wrapQObject(v);
    }
  }
  if (result) {
    // change ownershipflag to be owned by PythonQt
    if (result->ob_type == &PythonQtWrapper_Type) {
      ((PythonQtWrapper*)result)->_ownedByPythonQt = true;
    }
  } else {
    if (!wrapper->_info->constructors()) {
      if (!err) {
        if (error.isEmpty()) {
          error = QString("No constructors available for ") + wrapper->_info->className();
        }
        PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
      }
    }
  }
  return result;
}
Пример #8
0
static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wrapper, PyObject* other, int code)
{
  bool validPtrs = false;
  bool areSamePtrs = false;
  if (PyObject_TypeCheck((PyObject*)wrapper, &PythonQtInstanceWrapper_Type)) {
    if (PyObject_TypeCheck(other, &PythonQtInstanceWrapper_Type)) {
      validPtrs = true;
      PythonQtInstanceWrapper* w1 = wrapper;
      PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)other;
      // check pointers directly
      if (w1->_wrappedPtr != NULL) {
        if (w1->_wrappedPtr == w2->_wrappedPtr) {
          areSamePtrs = true;
        }
      } else if (w1->_obj == w2->_obj) {
        areSamePtrs = true;
      }
    } else if (other == Py_None) {
      validPtrs = true;
      if (wrapper->_obj || wrapper->_wrappedPtr) {
        areSamePtrs = false;
      } else {
        areSamePtrs = true;
      }
    }
  }

  if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) {
    // shortcut if richcompare is not supported:
    if (validPtrs && code == Py_EQ) {
      return PythonQtConv::GetPyBool(areSamePtrs);
    } else if (validPtrs && code == Py_NE) {
      return PythonQtConv::GetPyBool(!areSamePtrs);
    }
    Py_INCREF(Py_NotImplemented);
    return Py_NotImplemented;
  }

  QByteArray memberName;
  switch (code) {
  case Py_LT:
    {
      static QByteArray name = "__lt__";
      memberName = name;
    }
    break;

  case Py_LE:
    {
      static QByteArray name = "__le__";
      memberName = name;
    }
    break;

  case Py_EQ:
    {
      static QByteArray name = "__eq__";
      memberName = name;
    }
    break;

  case Py_NE:
    {
      static QByteArray name = "__ne__";
      memberName = name;
    }
    break;

  case Py_GT:
    {
      static QByteArray name = "__gt__";
      memberName = name;
    }
    break;

  case Py_GE:
    {
      static QByteArray name = "__ge__";
      memberName = name;
    }
    break;
  }

  PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
  if (opSlot._type == PythonQtMemberInfo::Slot) {
    // TODO get rid of tuple
    PyObject* args = PyTuple_New(1);
    Py_INCREF(other);
    PyTuple_SET_ITEM(args, 0, other);
    PyObject* result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
    Py_DECREF(args);
    if (result == NULL) {
      // special handling of EQ and NE, if call fails we just return EQ == false / NE == true.
      if (code == Py_EQ) {
        PyErr_Clear();
        Py_INCREF(Py_False);
        return Py_False;
      } else if (code == Py_NE) {
        PyErr_Clear();
        Py_INCREF(Py_True);
        return Py_True;
      }
    }
    return result;
  } else {
    // not implemented, let python try something else!
    Py_INCREF(Py_NotImplemented);
    return Py_NotImplemented;
  }
}
Пример #9
0
int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
{
  if (args == PythonQtPrivate::dummyTuple()) {
    // we are called from the internal PythonQt API, so our data will be filled later on...
    return 0;
  }

  // we are called from python, try to construct our object
  if (self->classInfo()->constructors()) {
    void* directCPPPointer = NULL;
    PythonQtPassThisOwnershipType ownership;
    PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer, &ownership);
    if (PyErr_Occurred()) {
      return -1;
    }
    if (directCPPPointer) {
      // if this object is reference counted, we ref it:
      PythonQtVoidPtrCB* refCB = self->classInfo()->referenceCountingRefCB();
      if (refCB) {
        (*refCB)(directCPPPointer);
      }
      // change ownership flag to be owned by PythonQt
      self->_ownedByPythonQt = true;
      self->_useQMetaTypeDestroy = false;
      bool isQObject = !self->classInfo()->isCPPWrapper();
      if (!isQObject) {
        self->_wrappedPtr = directCPPPointer;
        // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
      } else {
        self->setQObject((QObject*)directCPPPointer);
      }
      // register with PythonQt
      PythonQt::priv()->addWrapperPointer(directCPPPointer, self);

      PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
      if (cb) {
        // if we are a derived python class, we set the wrapper
        // to activate the shell class, otherwise we just ignore that it is a shell...
        // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
        // which is the case for all non-python derived types
        if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
          // set the wrapper and remember that we have a shell instance!
          (*cb)(directCPPPointer, self);
          self->_isShellInstance = true;
        }
      }
      // if the constructor has a PythonQtPassThisOwnership parameter and that owner is not NULL,
      // this wrapper is immediately owned by CPP
      // (Example: QGraphicsItem(QGraphicsItem* parent), if parent != NULL, ownership needs to be passed
      //  to C++ immediately)
      // Alternatively, if it is a QObject and the object already has a parent when it is constructed,
      // the ownership should be moved to C++ as well, so that the shell instance stays alive.
      if (ownership == PassOwnershipToCPP ||
          (isQObject && self->_obj && self->_obj->parent())) {
        self->passOwnershipToCPP();
      }
    }
  } else {
    QString error = QString("No constructors available for ") + self->classInfo()->className();
    PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
    return -1;
  }
  return 0;
}