diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 39f7d70fee..f18642207f 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,28 @@ The license applies to all entries newer than 2009-04-28. */ +2012-06-06 18:54 UTC-0800 Pritpal Bedi (bedipritpal@hotmail.com) + * contrib/hbqt/qtcore/hbqt_bind.cpp + * Struggled: to set pointer arithmatic to be used properly. + Also at times Qt returns different type instead of one + defined in documentation, but referred in description part only. + For example, a popup menu returns null instead of QAction if + no item is selected or user pressed escape. This is not + possible to manage such instances in present engine. For + this reason only :isValidPointer() method was introduced. + In REVAMPED hbQT this is different. So to test it, the only + way to ascertain is if the Harbour class name is of same type. + + * contrib/hbqt/tests/qtrevamp.prg + + Added: popup menu option to demonstrate what happens + at the background, if tracelog is activated. + + ; NOTE: I am not from C or C++ background at all, so some things + may not be as elegant as those should be when viewed from + source point of view. Also trace entries are left in the + code, though under DEBUG mode, which will be cleaned once + code settles down. + 2012-06-07 00:43 UTC+0200 Viktor Szakats (harbour syenar.net) * contrib/xhb/bkgtsks.c % cleanup missed in prev diff --git a/harbour/contrib/hbqt/qtcore/hbqt_bind.cpp b/harbour/contrib/hbqt/qtcore/hbqt_bind.cpp index ebc9807764..c4eece35b2 100644 --- a/harbour/contrib/hbqt/qtcore/hbqt_bind.cpp +++ b/harbour/contrib/hbqt/qtcore/hbqt_bind.cpp @@ -129,6 +129,9 @@ PHB_ITEM hbqt_bindGetHbObject( PHB_ITEM pItem, void * qtObject, PHB_SYMB pClassF PHBQT_BIND bind; PHB_ITEM pObject = NULL; + if( qtObject == NULL ) + return pObject; + HBQT_BIND_LOCK bind = s_hbqt_binds; while( bind ) @@ -176,9 +179,11 @@ PHB_ITEM hbqt_bindGetHbObject( PHB_ITEM pItem, void * qtObject, PHB_SYMB pClassF { if( s_destroyer == NULL ) s_destroyer = new HBQDestroyer(); - - QObject::connect( ( QObject * ) qtObject, SIGNAL(destroyed(QObject*)), s_destroyer, SLOT(destroyer()) ); - HB_TRACE( HB_TR_DEBUG, ( "hbqt_bindGetHbObject( %p )...%s", qtObject, ( ( QObject * ) qtObject )->metaObject()->className() ) ); + if( qtObject != NULL ) + { + QObject::connect( ( QObject * ) qtObject, SIGNAL(destroyed(QObject*)), s_destroyer, SLOT(destroyer()) ); + HB_TRACE( HB_TR_DEBUG, ( "hbqt_bindGetHbObject( %p )...%s", qtObject, ( ( QObject * ) qtObject )->metaObject()->className() ) ); + } } else { @@ -239,47 +244,70 @@ void hbqt_bindDestroyHbObject( PHB_ITEM pObject ) if( bind->hbObject == hbObject ) { found = HB_TRUE; - + bool fObject = bind->iFlags & HBQT_BIT_QOBJECT; + QObject * obj = NULL; + const char * classname = NULL; + if( fObject ) + { + obj = ( QObject * ) bind->qtObject; + classname = obj->metaObject()->className(); + } + if( bind->iFlags & HBQT_BIT_OWNER ) { - if( bind->iFlags & HBQT_BIT_QOBJECT ) + if( fObject ) { - HB_TRACE( HB_TR_DEBUG, ( "..............HARBOUR_ABOUT_TO_DESTROY( %p )...%s", bind->qtObject, ( ( QObject * ) bind->qtObject )->metaObject()->className() ) ); - QObject * obj = ( QObject * ) bind->qtObject; + HB_TRACE( HB_TR_DEBUG, ( "..............HARBOUR_ABOUT_TO_DESTROY_%s( %p )", classname, obj ) ); if( obj ) { - if( ! ( obj->metaObject()->className() == ( const char * ) "QAction" ) ) + if( classname != ( const char * ) "QAction" ) { if( obj->parent() == NULL ) { - HB_TRACE( HB_TR_DEBUG, ( "HARBOUR_DESTROYED( %p )...%s", obj, obj->metaObject()->className() ) ); bind->fDeleting = true; bind->pDelFunc( obj, bind->iFlags ); * bind_ptr = bind->next; hb_xfree( bind ); + HB_TRACE( HB_TR_DEBUG, ( "HARBOUR_DESTROYED_%s( %p )", classname, obj ) ); } } } + else + { + * bind_ptr = bind->next; + hb_xfree( bind ); + HB_TRACE( HB_TR_DEBUG, ( "HARBOUR_DESTROYED_QTObjIsNull_%s( %p )", classname, obj ) ); + } } else { - HB_TRACE( HB_TR_DEBUG, ( "HARBOUR_DESTROYED( %p )", bind->qtObject ) ); - bind->pDelFunc( bind->qtObject, bind->iFlags ); + void * oobj = bind->qtObject; * bind_ptr = bind->next; + bind->pDelFunc( bind->qtObject, bind->iFlags ); hb_xfree( bind ); + HB_TRACE( HB_TR_DEBUG, ( "HARBOUR_DESTROYED( %p )", oobj ) ); + Q_UNUSED( oobj ); } } else { - HB_TRACE( HB_TR_DEBUG, ( "HARBOUR_DESTROYED_NO_OWNER( %p )", bind->qtObject ) ); + if( fObject ) + { + HB_TRACE( HB_TR_DEBUG, ( "HARBOUR_DESTROYED_NOT_OWNED_BY_HHARBOUR( %p )...%s", bind->qtObject, obj->metaObject()->className() ) ); + } + else + { + HB_TRACE( HB_TR_DEBUG, ( "HARBOUR_DESTROYED_NOT_OWNED_BY_HHARBOUR( %p )", bind->qtObject ) ); + } * bind_ptr = bind->next; hb_xfree( bind ); } - break; + break; } bind_ptr = &bind->next; } HBQT_BIND_UNLOCK + if( ! found ) { HB_TRACE( HB_TR_DEBUG, ( "..............HARBOUR_DESTROYING_NOT_FOUND_ARRAYID( %p )", hbObject ) ); @@ -299,17 +327,17 @@ void hbqt_bindDestroyQtObject( void * qtObject ) { if( bind->qtObject == qtObject ) { + * bind_ptr = bind->next; if( ! bind->fDeleting ) { if( bind->iFlags & HBQT_BIT_QOBJECT ) { - HB_TRACE( HB_TR_DEBUG, ( "QT_DESTROYED( %p ).............%s", bind->qtObject, ( ( QObject * ) bind->qtObject )->metaObject()->className() ) ); + HB_TRACE( HB_TR_DEBUG, ( "QT_DESTROYED_%s( %p )", ( ( QObject * ) bind->qtObject )->metaObject()->className(), bind->qtObject ) ); } else { HB_TRACE( HB_TR_DEBUG, ( "QT_DESTROYED( %p )", bind->qtObject ) ); } - * bind_ptr = bind->next; hb_xfree( bind ); } break; diff --git a/harbour/contrib/hbqt/tests/qtrevamp.prg b/harbour/contrib/hbqt/tests/qtrevamp.prg index f51343f9af..c5a9c30ec6 100644 --- a/harbour/contrib/hbqt/tests/qtrevamp.prg +++ b/harbour/contrib/hbqt/tests/qtrevamp.prg @@ -3,6 +3,9 @@ */ +#include "hbtrace.ch" + + FUNCTION Main() LOCAL oWnd @@ -38,15 +41,15 @@ STATIC FUNCTION BuildMenuBar( oWnd ) // oMenu1 := QMenu( oMenuBar ) // - oMenu1:setTitle( "&Dialogs" ) + oMenu1:setTitle( "&Options" ) oItemIns := QAction( oMenu1 ) oItemIns:setText( "&MessageBox()" ) oItemIns:connect( "triggered()", {|| DlgMBox( "Yes" ) } ) oItemMod := QAction( oMenu1 ) - oItemMod:setText( "&FileDialog()" ) - oItemMod:connect( "triggered()", {|| DlgFiles( "*.prg" ) } ) + oItemMod:setText( "&ContextMenu()" ) + oItemMod:connect( "triggered()", {|| ContextMenu( oWnd ) } ) oMenu1:addAction( oItemIns ) oMenu1:addAction( oItemMod ) @@ -62,8 +65,8 @@ FUNCTION AddLabel( oWnd ) LOCAL oL oL := QLabel( oWnd ) - oL:move( 180,95 ) - oL:setText( "Harbour Qt" ) + oL:move( 155,95 ) + oL:setText( "Harbour Qt Revamped" ) // oL is local, still it is visible to the appln throughout. // Also memory is released automatically once its parent @@ -100,3 +103,36 @@ FUNCTION DlgFiles( cMask ) RETURN cMask + +FUNCTION ContextMenu( oWnd ) + LOCAL qMenu, qAct + + qMenu := QMenu() + + qMenu:addAction( "Copy" ) + qMenu:addAction( "Select All" ) + qMenu:addAction( "Clear" ) + qMenu:addAction( "Print" ) + qMenu:addAction( "Save as..." ) + qMenu:addSeparator() + qMenu:addAction( "Find" ) + + qAct := qMenu:exec( oWnd:mapToGlobal( QPoint( 10,10 ) ) ) + + // The test below is neccessary because Qt returns NULL in case + // user clicks anything except a menu item. Theoretically, Qt + // should have returned a QAction. + // + IF __objGetClsName( qAct ) == "QAction" + IF hb_isString( qAct:text() ) + //... + ENDIF + ENDIF + + // qMenu is a local variable and is carries no parent, + // which should be like this for any context menu, + // The memory is released, along its actions, when + // RETURN is hit. + + RETURN NIL +