On Mon, 12 Apr 2010, Szak�ts Viktor wrote:

Hi,

> > Hi Viktor, I was about to send this message to the list when I had a
> > shocking vision....
> > In postgres.c it is NORMAL to discriminate between objects... there is
> > no use in passing type X instead of type Y and it must be avoided and
> > RTE is good.....
> > But in Qt we have a HIERARCHY !
> > It is perfectly normal to pass a QPushButton to a function that
> > expects a QObject !!!!!!!!!! since QObject is a super-class !
> > Since we don't store the object hierarchy Pritpal just checks that
> > ClassName() starts with a Q or HB .... and keeps the finger crossed...
> That's even worse than handling everything as the base class.
[...]
> First I think we need to make sure we can identify the 
> class of every GC allocated objects. If we can do this, 
> we may make the next step and properly filter accepted 
> parameters. For this we also need to maintain the layout 
> of the QT class hierarchy. This raises other issues, like 
> how to keep this in sync with QT version. This information 
> BTW is already maintained in HBQT on the .prg level.
> So you could make sth like:
[...]

Half year ago I committed to this list code which realize it:
http://lists.harbour-project.org/pipermail/harbour/2009-October/026490.html

It was example with few typos (see the above thread).
Below is cleaned version which also uses explicit casting.
It fully resolve the problem of casting to ancestors classes
when pointer to QT object is extracted from HVM item with
full validation. Please also note that it does not need any
global replication of QT hierarchy. Just simply each class
can independently decide which casting to ancestor is allowed
by registering itself in the ancestors wrappers using
qt_childregister_<class>() function.
It also does not need metaObject or similar tricks.
All what you need is using such code for all QT classes wrappers.

best regards,
Przemek





/* global declaration */
typedef void * ( * QT_PARAM_FUNC ) ( int, HB_BOOL );
typedef struct _QT_PARAM_INFO
{
   QT_PARAM_FUNC            pFunc;
   struct _QT_PARAM_INFO  * pNext;
   HB_BOOL                  fInited;
} QT_PARAM_INFO;

/* this function is part of QDialog wrapper */
extern void qt_childregister_QDialog( QT_PARAM_INFO * paramInfo );

/* public functions in other class wrappers */
extern QWidget * hbqt_par_QWidget( int iParam, HB_BOOL fError );
extern QPrinter * hbqt_par_QPrinter( int iParam, HB_BOOL fError );

/* public function in this class wrapper */
extern QPageSetupDialog * hbqt_par_QPageSetupDialog( int iParam,
                                                     HB_BOOL fError );
extern void qt_childregister_QPageSetupDialog( QT_PARAM_INFO * paramInfo );

/*** QPageSetupDialog.cpp ***/

static HB_GARBAGE_FUNC( release_QPageSetupDialog )
{
   QPointer< QPageSetupDialog > * pObj =
                              ( QPointer< QPageSetupDialog > * ) Cargo;
   QPageSetupDialog * obj = * pObj;

   if( obj )
   {
      *pObj = NULL;
      delete obj;
   }
}

static const HB_GC_FUNCS s_gcQPageSetupDialog =
{
   release_QPageSetupDialog,
   hb_gcDummyMark
};

static QT_PARAM_INFO s_paramInfo_QDialog;
static QT_PARAM_INFO * s_paramList = NULL;

/* public function use by descendant classes to register their
 * param functions
 */
void qt_childregister_QPageSetupDialog( QT_PARAM_INFO * paramInfo )
{
   if( !paramInfo->fInited )
   {
      /* TODO: add MT protection in fianl version,
               ignore it in devel code */
      paramInfo->fInited = HB_TRUE;
      paramInfo->pNext = s_paramList;
      s_paramList = paramInfo;
   }
}

/* public function which extracts pointer to QPageSetupDialog object
 * from given HVM parameter. This parameter may contain also any
 * descendant class which register its param function using
 * qt_childregister_QPageSetupDialog().
 */
QPageSetupDialog * hbqt_par_QPageSetupDialog( int iParam, HB_BOOL fError )
{
   QPointer< QPageSetupDialog > * pObj;
   QPageSetupDialog * obj = NULL;

   pObj = ( QPointer< QPageSetupDialog > * )
                              hb_parptrGC( &s_gcQPageSetupDialog, iParam );
   if( pObj == NULL )
   {
      /* Not a QPageSetupDialog pointer item, check all registered
       * descendant classes
       */
      QT_PARAM_INFO * paramInfo = s_paramList;
      while( paramInfo )
      {
         obj = ( QPageSetupDialog * ) paramInfo->pFunc( iParam, HB_FALSE );
         if( obj )
            return obj;
         paramInfo = paramInfo->pNext;
      }
   }

   if( pObj == NULL )
   {
      if( fError )
      {
         /* RT ERROR - wrong parameter */
      }
   }
   else
   {
      obj = * pObj;
      if( obj == NULL && fError )
      {
         /* RT ERROR - object deleted by other code */
      }
   }

   return obj;
}

static QDialog * hbqt_par_QPageSetupDialogAsQDialog( int iParam,
                                                     HB_BOOL fError )
{
   QPageSetupDialog * obj = hbqt_par_QPageSetupDialog( iParam, fError );
   return ( QDialog * ) obj;
}

static QPointer< QPageSetupDialog > * qt_alloc_QPageSetupDialog( 
QPageSetupDialog * obj )
{
   QPointer< QPageSetupDialog > * pObj;

   if( !s_paramInfo_QDialog.fInited )
   {
      /* First call - register in parent class our param function */
      s_paramInfo_QDialog.pFunc = ( QT_PARAM_FUNC )
                                  hbqt_par_QPageSetupDialogAsQDialog;
      qt_childregister_QDialog( &s_paramInfo_QDialog );

      /* if class inherits directly from more then one classes
       * (multiinheritance) then for each parent class register
       * coresponding s_paramInfo_<X> parameter
       */
   }

   pObj = ( QPointer< QPageSetupDialog > * )
            memset( hb_gcAllocate( sizeof( QPointer< QPageSetupDialog > ),
                                   &s_gcQPageSetupDialog ),
                    0, sizeof( QPointer< QPageSetupDialog > ) );
   * pObj = obj;

   return pObj;
}

/* PRG class functions */

HB_FUNC( QT_QPAGESETUPDIALOG )
{
   QPageSetupDialog * obj = NULL;

   if( hb_pcount() >= 2 )
   {
      QPrinter * qp = hbqt_par_QPrinter( 1, HB_TRUE );
      if( qp )
      {
         QWidget * qw = hbqt_par_QWidget( 2, HB_TRUE );
         if( qw )
            obj = new QPageSetupDialog( qp, qw );
      }
   }
   else
      obj = new QPageSetupDialog( hbqt_par_QWidget( 1, HB_TRUE ) );

   if( obj )
      hb_retptrGC( qt_alloc_QPageSetupDialog( obj ) );
}

HB_FUNC( QT_QPAGESETUPDIALOG_EXEC )
{
   QPageSetupDialog * obj = hbqt_par_QPageSetupDialog( 1, HB_TRUE );

   if( obj )
      hb_retni( obj->exec() );
}

[...]
_______________________________________________
Harbour mailing list (attachment size limit: 40KB)
Harbour@harbour-project.org
http://lists.harbour-project.org/mailman/listinfo/harbour

Reply via email to