diff --git a/harbour/ChangeLog b/harbour/ChangeLog index c85bfea80b..099739cea3 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,26 @@ The license applies to all entries newer than 2009-04-28. */ +2012-06-16 18:06 UTC-0800 Pritpal Bedi (bedipritpal@hotmail.com) + * contrib/hbxbp/xbpdialog.prg + + Added: Main application windows object name as "PleseDoNotDelete" + + * contrib/hbxbp/xbplistbox.prg + - Removed: traces from prev commit. + + * contrib/hbqt/qtcore/hbqt_hbqevents.cpp + * contrib/hbqt/qtcore/hbqt_hbqslots.cpp + ! Fixed: a couple of potential memory leaks. + + * contrib/hbqt/qtcore/hbqt_bind.cpp + + Implemented: Thread safe global list. Now objects are released + in a proper manner. + + + Added: a hack not to delete a QMainWindow if its name is + "PleaseDoNotDelete". It is scheduled to be removed + once it is resolved that why on certain circumstances, if + a QMainWindow is deleted, it results in GPF. + 2012-06-17 02:51 UTC+0200 Viktor Szakats (harbour syenar.net) * contrib/hbrun/hbrun.hbp * restored to embed headers in hbrun diff --git a/harbour/contrib/hbqt/qtcore/hbqt_bind.cpp b/harbour/contrib/hbqt/qtcore/hbqt_bind.cpp index 5c244f6bcd..617c385828 100644 --- a/harbour/contrib/hbqt/qtcore/hbqt_bind.cpp +++ b/harbour/contrib/hbqt/qtcore/hbqt_bind.cpp @@ -62,6 +62,7 @@ #include "hbqt.h" #include "hbqt_destroyer.h" +#include #ifndef QT_VERSION /* workaround for missing QT headers - for test only */ @@ -84,6 +85,35 @@ typedef struct _HBQT_BIND } HBQT_BIND, * PHBQT_BIND; +typedef struct +{ + PHBQT_BIND s_hbqt_binds; +} HB_SK_DATA, * PHB_SK_DATA; + +static void hbqt_bindInit( void * cargo ) +{ + ( ( PHB_SK_DATA ) cargo )->s_hbqt_binds = NULL; +} + +static void hbqt_bindRelease( void * cargo ) +{ + HB_TRACE( HB_TR_DEBUG, ( "....................................hbqt_bindRelease......................................" ) ); + PHBQT_BIND hbqt_bind; + + while( ( ( PHB_SK_DATA ) cargo )->s_hbqt_binds ) + { + hbqt_bind = ( ( PHB_SK_DATA ) cargo )->s_hbqt_binds; + hbqt_bindDestroyHbObject( hb_arrayFromId( NULL, hbqt_bind->hbObject ) ); + } + + ( ( PHB_SK_DATA ) cargo )->s_hbqt_binds = NULL; +} + +static HB_TSD_NEW( s_skData, sizeof( HB_SK_DATA ), hbqt_bindInit, hbqt_bindRelease ); + +#define hbqt_bindGetData() ( ( PHB_SK_DATA ) hb_stackGetTSD( &s_skData ) ) + + /* locks for MT mode, now just dummy definitions which checks * if all locks are correctly released. */ @@ -97,7 +127,6 @@ void hbqt_bindDelEvents( PHB_ITEM pSenderObject ); int __hbqt_bindItemsInGlobalList(); int hbqt_bindIsHbObject( PHB_ITEM pObject ); -static PHBQT_BIND s_hbqt_binds = NULL; static HBQDestroyer * s_destroyer = NULL; static PHB_DYNS s_dynsym_NEW = NULL; @@ -119,49 +148,6 @@ static void hbqt_bind_init( void* cargo ) s_dynsym_SETEVENTS = hb_dynsymGetCase( "SETEVENTS" ); } - -/* we need to release all the PHB_ITEM that are still in the GLL - * we are now using a linked list and releasing an item may change the GLL - * so I first store the PHB_ITEM addresses in a QList - * and then I ask to remove them from the GLL... if already removed no problem - */ -static void hbqt_bind_exit( void* cargo ) -{ - HB_SYMBOL_UNUSED( cargo ); - - PHBQT_BIND bind; - QList deleteIt; - - HBQT_BIND_LOCK - bind = s_hbqt_binds; - while ( bind ) - { - HB_TRACE( HB_TR_DEBUG, ( "Item on GList %p %s", bind->qtObject, bind->szClassName ) ); - deleteIt << bind->hbObject; - bind = bind->next; - } - HBQT_BIND_UNLOCK - -#ifdef HBQT_FORCE_RELEASE_GLL - HB_TRACE( HB_TR_DEBUG, ( "onExit before" ) ); - while( ! deleteIt.isEmpty() ) - { - HB_TRACE( HB_TR_DEBUG, ( "onExit check" ) ); - - if( hbqt_bindIsHbObject( ( PHB_ITEM ) deleteIt.at( 0 ) ) ) - { - hbqt_bindDestroyHbObject( hb_arrayFromId( NULL, deleteIt.at( 0 ) ) ); - HB_TRACE( HB_TR_DEBUG, ( "onExit itemRelease" ) ); - hb_itemRelease( ( PHB_ITEM ) deleteIt.at( 0 ) ); - } - deleteIt.removeAt( 0 ); - } - HB_TRACE( HB_TR_DEBUG, ( "onExit after" ) ); -#endif - - HB_TRACE( HB_TR_DEBUG, ( "Exiting with %d items on GList", __hbqt_bindItemsInGlobalList() ) ); -} - PHB_ITEM hbqt_bindGetHbObject( PHB_ITEM pItem, void * qtObject, const char * szClassName, PHBQT_DEL_FUNC pDelFunc, int iFlags ) { char * pname = ( char * ) hb_xgrab( 200 ); @@ -182,12 +168,12 @@ PHB_ITEM hbqt_bindGetHbObject( PHB_ITEM pItem, void * qtObject, const char * szC PHBQT_BIND bind; HBQT_BIND_LOCK - bind = s_hbqt_binds; + bind = hbqt_bindGetData()->s_hbqt_binds; while( bind ) { if( bind->qtObject == qtObject ) { - HB_TRACE( HB_TR_DEBUG, ( "hbqt_bindGetHbObject( %p ):if( bind->qtObject == qtObject )", qtObject ) ); + HB_TRACE( HB_TR_DEBUG, ( "...hbqt_bindGetHbObject( %p ):if( bind->qtObject == qtObject )", qtObject ) ); pObject = hb_arrayFromId( pItem, bind->hbObject ); break; } @@ -219,27 +205,35 @@ PHB_ITEM hbqt_bindGetHbObject( PHB_ITEM pItem, void * qtObject, const char * szC bind->iFlags = iFlags; bind->fDeleting = false; hb_strncpy( bind->szClassName, szClassName, HB_SIZEOFARRAY( bind->szClassName ) - 1 ); - bind->next = s_hbqt_binds; - s_hbqt_binds = bind; + bind->next = hbqt_bindGetData()->s_hbqt_binds; + hbqt_bindGetData()->s_hbqt_binds = bind; } bind->hbObject = hb_arrayId( pObject ); if( iFlags & HBQT_BIT_QOBJECT ) { + QObject * obj = ( QObject * ) qtObject; + QString className = ( QString ) obj->metaObject()->className(); + if( s_destroyer == NULL ) s_destroyer = new HBQDestroyer(); - if( pDelFunc != NULL ) - QObject::connect( ( QObject * ) qtObject, SIGNAL( destroyed(QObject*) ), s_destroyer, SLOT( destroyer() ) ); - HB_TRACE( HB_TR_DEBUG, ( "hbqt_bindGetHbObject( %p )...%s", qtObject, szClassName ) ); - hb_vmPushDynSym( s_dynsym_SETSLOTS ); /* initializes __Slots hash */ - hb_vmPush( pObject ); - hb_vmSend( 0 ); + if( ( className != "HBQSlots" ) && ( className != "HBQEvents" ) ) + { + if( pDelFunc != NULL ) + QObject::connect( obj, SIGNAL( destroyed(QObject*) ), s_destroyer, SLOT( destroyer() ) ); - hb_vmPushDynSym( s_dynsym_SETEVENTS ); /* initializes __Events hash */ - hb_vmPush( pObject ); - hb_vmSend( 0 ); + HB_TRACE( HB_TR_DEBUG, ( "hbqt_bindGetHbObject_connected_to_destroy()( %p )...%s", qtObject, szClassName ) ); + + hb_vmPushDynSym( s_dynsym_SETSLOTS ); /* initializes __Slots hash */ + hb_vmPush( pObject ); + hb_vmSend( 0 ); + + hb_vmPushDynSym( s_dynsym_SETEVENTS ); /* initializes __Events hash */ + hb_vmPush( pObject ); + hb_vmSend( 0 ); + } } else { @@ -268,7 +262,7 @@ PHB_ITEM hbqt_bindSetHbObject( PHB_ITEM pItem, void * qtObject, const char * szC PHBQT_BIND bind; HBQT_BIND_LOCK - bind = s_hbqt_binds; + bind = hbqt_bindGetData()->s_hbqt_binds;; pObject = hb_param( 0, HB_IT_OBJECT ); if( 1 == 1 ) /* QUESTION: What is this? */ @@ -291,8 +285,8 @@ PHB_ITEM hbqt_bindSetHbObject( PHB_ITEM pItem, void * qtObject, const char * szC bind->iFlags = iFlags; bind->fDeleting = false; hb_strncpy( bind->szClassName, szClassName, HB_SIZEOFARRAY( bind->szClassName ) - 1 ); - bind->next = s_hbqt_binds; - s_hbqt_binds = bind; + bind->next = hbqt_bindGetData()->s_hbqt_binds; + hbqt_bindGetData()->s_hbqt_binds = bind; bind->hbObject = hb_arrayId( pObject ); @@ -325,7 +319,7 @@ PHB_ITEM hbqt_bindGetHbObjectByQtObject( void * qtObject ) PHBQT_BIND bind; HBQT_BIND_LOCK - bind = s_hbqt_binds; + bind = hbqt_bindGetData()->s_hbqt_binds; while( bind ) { if( bind->qtObject == qtObject ) @@ -345,7 +339,7 @@ int hbqt_bindIsHbObject( PHB_ITEM pObject ) PHBQT_BIND bind; HBQT_BIND_LOCK - bind = s_hbqt_binds; + bind = hbqt_bindGetData()->s_hbqt_binds; while( bind ) { HB_TRACE( HB_TR_DEBUG, ( "hbqt_bindIsHbObject( %p )", bind->qtObject ) ); @@ -373,7 +367,7 @@ void * hbqt_bindGetQtObject( PHB_ITEM pObject ) PHBQT_BIND bind; HBQT_BIND_LOCK - bind = s_hbqt_binds; + bind = hbqt_bindGetData()->s_hbqt_binds; while( bind ) { HB_TRACE( HB_TR_DEBUG, ( "hbqt_bindGetQtObject( %p )", bind->qtObject ) ); @@ -399,7 +393,7 @@ void hbqt_bindDestroyHbObject( PHB_ITEM pObject ) PHBQT_BIND * bind_ptr, bind; HBQT_BIND_LOCK - bind_ptr = &s_hbqt_binds; + bind_ptr = &( hbqt_bindGetData()->s_hbqt_binds ); while( ( bind = * bind_ptr ) != NULL ) { if( bind->hbObject == hbObject ) @@ -411,12 +405,8 @@ void hbqt_bindDestroyHbObject( PHB_ITEM pObject ) if( bind->iFlags & HBQT_BIT_QOBJECT ) { if( ( ( QObject * ) bind->qtObject )->metaObject()->className() != ( const char * ) "QAction" ) - { if( ( ( QObject * ) bind->qtObject )->parent() == NULL ) - { fDelQtObject = true; - } - } } else fDelQtObject = true; @@ -429,18 +419,26 @@ void hbqt_bindDestroyHbObject( PHB_ITEM pObject ) if( bind->pDelFunc != NULL ) { HB_TRACE( HB_TR_DEBUG, ( ".......HARBOUR_DESTROYING_ACTUAL_QT_OBJECT( %p, %i ).............. %s", bind->qtObject, bind->iFlags, bind->szClassName ) ); - if( hb_vmRequestReenter() ) + if( bind->iFlags & HBQT_BIT_QOBJECT ) + { + HB_TRACE( HB_TR_DEBUG, ( ".......HARBOUR_DESTROYING_ACTUAL_QT_OBJECT_NAMED( %p, %s )..............", bind->qtObject, ( ( QObject * ) bind->qtObject )->objectName().toAscii().data() ) ); + if( ( QString ) ( ( QObject * ) bind->qtObject )->metaObject()->className() == "QMainWindow" ) + { + if( ( ( QObject * ) bind->qtObject )->objectName() == "PleaseDoNotDelete" ) /* This is a hack: will be removed a bit later */ + fDelQtObject = false; + } + else if( ( QString ) ( ( QObject * ) bind->qtObject )->metaObject()->className() == "QDesktopWidget" ) + fDelQtObject = false; + } + if( fDelQtObject ) { bind->fDeleting = true; bind->pDelFunc( bind->qtObject, bind->iFlags ); bind->fDeleting = false; - - hb_vmRequestRestore(); } } } hb_xfree( bind ); - break; } bind_ptr = &bind->next; @@ -457,17 +455,17 @@ void hbqt_bindDestroyQtObject( void * qtObject ) PHBQT_BIND * bind_ptr, bind; HBQT_BIND_LOCK - bind_ptr = &s_hbqt_binds; + bind_ptr = &( hbqt_bindGetData()->s_hbqt_binds ); while( ( bind = * bind_ptr ) != NULL ) { if( bind->qtObject == qtObject ) { HB_TRACE( HB_TR_DEBUG, ( "........................QT_DESTROYING( %p ).....%s ... fDeleting=%s", qtObject, bind->szClassName, bind->fDeleting ? "YES" : "NO" ) ); - * bind_ptr = bind->next; if( ! bind->fDeleting ) { hb_xfree( bind ); + HB_TRACE( HB_TR_DEBUG, ( "........................QT_DESTROYED()" ) ); } break; } @@ -485,7 +483,7 @@ void hbqt_bindSetOwner( void * qtObject, HB_BOOL fOwner ) PHBQT_BIND bind; HBQT_BIND_LOCK - bind = s_hbqt_binds; + bind = hbqt_bindGetData()->s_hbqt_binds; while( bind ) { if( bind->qtObject == qtObject ) @@ -809,7 +807,7 @@ int __hbqt_bindItemsInGlobalList( void ) PHBQT_BIND bind; HBQT_BIND_LOCK - bind = s_hbqt_binds; + bind = hbqt_bindGetData()->s_hbqt_binds; while( bind ) { i++; @@ -827,7 +825,6 @@ HB_FUNC( __HBQT_ITEMSINGLOBALLIST ) HB_CALL_ON_STARTUP_BEGIN( _hbqt_bind_init_ ) hb_vmAtInit( hbqt_bind_init, NULL ); - hb_vmAtExit( hbqt_bind_exit, NULL ); HB_CALL_ON_STARTUP_END( _hbqt_bind_init_ ) #if defined( HB_PRAGMA_STARTUP ) diff --git a/harbour/contrib/hbqt/qtcore/hbqt_hbqevents.cpp b/harbour/contrib/hbqt/qtcore/hbqt_hbqevents.cpp index 6c6cacc792..6029a91690 100644 --- a/harbour/contrib/hbqt/qtcore/hbqt_hbqevents.cpp +++ b/harbour/contrib/hbqt/qtcore/hbqt_hbqevents.cpp @@ -181,8 +181,11 @@ bool HBQEvents::eventFilter( QObject * object, QEvent * event ) if( hb_vmRequestQuery() == 0 ) { PHB_ITEM pItem = hbqt_bindGetHbObject( NULL, ( void * ) event, ( s_lstCreateObj.at( eventId ) ), NULL, HBQT_BIT_NONE ); - stopTheEventChain = ( bool ) hb_itemGetL( hb_vmEvalBlockV( hb_arrayGetItemPtr( pArray, 1 ), 1, pItem ) ); - hb_itemRelease( pItem ); + if( pItem ) + { + stopTheEventChain = ( bool ) hb_itemGetL( hb_vmEvalBlockV( hb_arrayGetItemPtr( pArray, 1 ), 1, pItem ) ); + hb_itemRelease( pItem ); + } } hb_itemRelease( pArray ); } diff --git a/harbour/contrib/hbqt/qtcore/hbqt_hbqslots.cpp b/harbour/contrib/hbqt/qtcore/hbqt_hbqslots.cpp index 2031084ff1..a9ed4a149a 100644 --- a/harbour/contrib/hbqt/qtcore/hbqt_hbqslots.cpp +++ b/harbour/contrib/hbqt/qtcore/hbqt_hbqslots.cpp @@ -267,24 +267,27 @@ int HBQSlots::qt_metacall( QMetaObject::Call c, int id, void ** arguments ) if( hb_vmRequestReenter() ) { PHB_ITEM hbObject = hbqt_bindGetHbObjectByQtObject( object ); - PHB_ITEM p = hbqt_bindGetSlots( hbObject, id ); - hb_itemRelease( hbObject ); - if( p ) + if( hbObject ) { - if( parameterCount == 0 ) + PHB_ITEM p = hbqt_bindGetSlots( hbObject, id ); + hb_itemRelease( hbObject ); + if( p ) { - hb_evalBlock0( hb_arrayGetItemPtr( p, 1 ) ); - } - else - { - int paramId = s_argCombinations.indexOf( paramString ); - PHBQT_SLOT_FUNC pCallback = s_pCallback.at( paramId ); - if( pCallback ) + if( parameterCount == 0 ) { - pCallback( ( PHB_ITEM * ) hb_arrayGetItemPtr( p, 1 ), arguments, pList ); + hb_evalBlock0( hb_arrayGetItemPtr( p, 1 ) ); } + else + { + int paramId = s_argCombinations.indexOf( paramString ); + PHBQT_SLOT_FUNC pCallback = s_pCallback.at( paramId ); + if( pCallback ) + { + pCallback( ( PHB_ITEM * ) hb_arrayGetItemPtr( p, 1 ), arguments, pList ); + } + } + hb_itemRelease( p ); } - hb_itemRelease( p ); } hb_vmRequestRestore(); } diff --git a/harbour/contrib/hbxbp/xbpdialog.prg b/harbour/contrib/hbxbp/xbpdialog.prg index 914a9ba9e2..c04dd64ae0 100644 --- a/harbour/contrib/hbxbp/xbpdialog.prg +++ b/harbour/contrib/hbxbp/xbpdialog.prg @@ -159,11 +159,11 @@ METHOD XbpDialog:create( oParent, oOwner, aPos, aSize, aPresParams, lVisible ) ELSE IF ::taskList ::oWidget := QMainWindow() + ::oWidget:setObjectName( "PleaseDoNotDelete" ) ELSE - ::oWidget := QMainWindow( SetAppWindow():oWidget ) + ::oWidget := QMainWindow( SetAppWindow():oWidget ) /* Why it was wanted */ ENDIF ::oWidget:setMouseTracking( .t. ) - ::oWidget:setObjectName( "mainWindow" ) ENDIF IF !empty( ::qtObject ) @@ -443,8 +443,6 @@ CLASS XbpDrawingArea INHERIT XbpWindow METHOD init( oParent, oOwner, aPos, aSize, aPresParams, lVisible ) METHOD create( oParent, oOwner, aPos, aSize, aPresParams, lVisible ) - DATA oBrush - ENDCLASS /*----------------------------------------------------------------------*/ @@ -467,13 +465,8 @@ METHOD XbpDrawingArea:create( oParent, oOwner, aPos, aSize, aPresParams, lVisibl IF ! empty( ::qtObject ) ::oWidget := ::qtObject:oWidget ELSE - #if 0 - ::oWidget := QWidget() - #else ::oWidget := QMdiArea() - ::oBrush := QApplication():palette():button() - ::oWidget:setBackground( ::oBrush ) - #endif + ::oWidget:setBackground( QApplication():palette():button() ) ENDIF ::oWidget:setMouseTracking( .T. ) @@ -482,7 +475,7 @@ METHOD XbpDrawingArea:create( oParent, oOwner, aPos, aSize, aPresParams, lVisibl ::setQtProperty() /* Using it for one-to-one style sheet management */ - ::oParent:addChild( SELF ) + ::oParent:addChild( Self ) RETURN Self diff --git a/harbour/contrib/hbxbp/xbplistbox.prg b/harbour/contrib/hbxbp/xbplistbox.prg index 0aec377b00..e6ee265117 100644 --- a/harbour/contrib/hbxbp/xbplistbox.prg +++ b/harbour/contrib/hbxbp/xbplistbox.prg @@ -255,7 +255,6 @@ METHOD XbpListBox:getItemIndex( pItm ) METHOD XbpListBox:execSlot( cSlot, p ) LOCAL qPos, qItm, nIndex, n, qPt - HB_TRACE( HB_TR_ALWAYS, "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM" ) IF cSlot == "customContextMenuRequested(QPoint)" IF HB_ISBLOCK( ::hb_contextMenu ) @@ -284,11 +283,8 @@ METHOD XbpListBox:execSlot( cSlot, p ) ::nCurSelected := p + 1 EXIT CASE "itemClicked(QListWidgetItem*)" - HB_TRACE( HB_TR_ALWAYS, "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM" ) ::toggleSelected( nIndex ) - HB_TRACE( HB_TR_ALWAYS, "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM" ) ::itemMarked() - HB_TRACE( HB_TR_ALWAYS, "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM" ) EXIT CASE "itemDoubleClicked(QListWidgetItem*)" ::itemSelected()