Esempio n. 1
0
SmokeObject * SmokeObject::fromPtr(void *ptr, const Class *klass,
                                   bool allocated, bool copy)
{
  if (!klass)
    error("Attempt to create SmokeObject with NULL class");
  if (!ptr)
    error("Attempt to create SmokeObject with NULL pointer");
  SmokeObject *so = instances[ptr];
  if (!so) {
    so = new SmokeObject(ptr, klass, allocated);
#ifdef MEM_DEBUG
    qDebug("%p: created for %p (%s)", so, ptr, klass->name());
#endif
    // record this ASAP, resolveClassId() needs it for virtual callbacks
    if (allocated) // do not record unallocated; not informed when deleted
      instances[so->ptr()] = so;
#ifdef MEM_DEBUG
    else qDebug("%p: unallocated, not registering pointer", so);
#endif
    so->cast(Class::fromSmokeId(so->smoke(), so->module()->resolveClassId(so)));
    /* it seems that all multiple inheritance in Qt goes through
       QObject or QEvent, so we can catch offset pointers at run-time */
    // FIXME: what happens with other libraries? take QtRuby approach?
#ifdef MEM_DEBUG
    if (allocated && so->klass() != klass)
      qDebug("%p: class switch %s::%s -> %s::%s", so,
             klass->smokeBase()->smoke()->moduleName(),
             klass->name(), so->klass()->smokeBase()->smoke()->moduleName(),
             so->klass()->name());
#endif    
    if (so->ptr() != ptr) { // must be multiple inheritance, recache
      SmokeObject *tmp_so = instances[so->ptr()];
#ifdef MEM_DEBUG
      qDebug("%p: multiple inheritance detected, switch to %p", so, so->ptr());
#endif
      if (tmp_so) {
#ifdef MEM_DEBUG
      qDebug("%p: replaced with existing %p", so, tmp_so);
#endif
        delete so;
        so = tmp_so;
        copy = false; // don't think we every want to copy here
      } else instances[so->ptr()] = so;
      instances.remove(ptr);
    }
    if (copy) { // copy the data
      void *tmp_ptr = so->ptr();
      so->_ptr = so->clonePtr(); 
      instances[so->ptr()] = so; // update the instances hash after cloning
      instances.remove(tmp_ptr);
#ifdef MEM_DEBUG
      qDebug("%p: copied to %p", so, so->ptr());
#endif
      so->_allocated = true;
    }
  }
  return so;
}
Esempio n. 2
0
Method*
MocClass::findMethod(const MethodCall& call) const {
  Method *method = _delegate->findMethod(call);
  if (method)
    return(method);
  SmokeObject *o = call.target();
  /* only QObjects have meta methods */
  if (o && o->ptr() && o->instanceOf("QObject") && o->klass() == this) {
    /* unwrap the call */
    QObject * qobject = reinterpret_cast<QObject *>(o->castPtr("QObject"));
    const QMetaObject * meta = qobject->metaObject();
    /* get the method id */
    int id = findMethodId(o->smoke(), meta, call.method()->name(), call.args());
    if (id >= 0)
      method = new MocMethod(o->smoke(), meta, id);
  }
  return method;
}
Esempio n. 3
0
QVariant qvariant_from_sexp(SEXP rvalue, int index) {
  QVariant variant;
  if (index == -1) {
    /* If a particular element is not selected, then non-lists of
       length one are considered scalars. Otherwise, collections.
       Except for raw vectors, which are naturally QByteArrays.
    */
    if (TYPEOF(rvalue) == RAWSXP)
      return QVariant(from_sexp<QByteArray>(rvalue));
    else if (TYPEOF(rvalue) == VECSXP || length(rvalue) > 1) {
      SEXP rlist = coerceVector(rvalue, VECSXP);
      if (getAttrib(rvalue, R_NamesSymbol) != R_NilValue)
        variant = asQVariantOfType(rlist, QMetaType::QVariantMap);
      else variant = asQVariantOfType(rlist, QMetaType::QVariantList);
      return variant;
    }
    index = 0;
  }
  switch(TYPEOF(rvalue)) {
  case RAWSXP:
    variant = qVariantFromValue(RAW(rvalue)[index]);
    break;
  case LGLSXP:
    // Rprintf("Logical\n");
    // FIXME: by converting to 'bool' all NA become TRUE
    variant = QVariant((bool)LOGICAL(rvalue)[index]);
    break;
  case REALSXP:
    // Rprintf("Real\n");
    variant = QVariant(REAL(rvalue)[index]);
    break;
  case INTSXP:
    // Rprintf("Integer\n");
    {
      SEXP levels;
      if ((levels = getAttrib(rvalue, R_LevelsSymbol)) != R_NilValue) {
        int level = INTEGER(rvalue)[index];
        SEXP level_str = NA_STRING;
        /*Rprintf("getting level: %d\n", level);*/
        if (level != NA_INTEGER)
          level_str = STRING_ELT(levels, level - 1);
        variant = QVariant(sexp2qstring(level_str));
      } else variant = QVariant(INTEGER(rvalue)[index]);
      break;
    }
  case STRSXP:
    // Rprintf("String\n");
    variant = QVariant(sexp2qstring(STRING_ELT(rvalue, index)));
    break;
  case EXTPTRSXP:
    // Rprintf("External pointer\n");
    variant = qVariantFromValue(unwrapPointer(rvalue, void));
    break;
  case VECSXP:
    variant = from_sexp<QVariant>(VECTOR_ELT(rvalue, index));
    break;
  case ENVSXP: {
    SmokeObject *so = SmokeObject::fromSexp(rvalue);
    if (so->instanceOf("QWidget"))
      variant =
        qVariantFromValue(reinterpret_cast<QWidget *>(so->castPtr("QWidget")));
    else if (so->instanceOf("QObject"))
      variant =
        qVariantFromValue(reinterpret_cast<QObject *>(so->castPtr("QObject")));
    else {
      QMetaType::Type type = (QMetaType::Type) QMetaType::type(so->className());
      if (type)
        variant = asQVariantOfType(rvalue, type, false);
      else variant = qVariantFromValue(so->ptr());
    }
  }
    break;
  case NILSXP: // invalid QVariant
    break;
  default:
    error("Converting to QVariant: unhandled R type");
  }
  return variant;
}