diff --git a/harbour/ChangeLog b/harbour/ChangeLog index fbe406b921..900f4f2a0a 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,58 @@ The license applies to all entries newer than 2009-04-28. */ +2012-06-19 21:29 UTC-0800 Pritpal Bedi (bedipritpal@hotmail.com) + * contrib/hbqt/qtcore/hbqt_bind.cpp + + Implemented: Events, Slots, Destroyers on thread level. + Previously those were created per object level. This greatly + decreased the os-resource count and also simplifies the code. + Thanks to Przemek for the tip. + + + Implemented: release of all objects per thread level. + hbQT employs internal counter to identify threads. + All widgets are created in one global list which has + made it possible to use Qt's blocking widgets, like + QMessageBox, in Harbour MT applications. It seems that + Qt looks for the event processing only in main appln + thread and hence these widgets were not usable in + other threads. The testbed is hbqt/tests/demoqt.prg + which is now multithreaded. You check it with + menu option . + + + Formatting: in tracelog entries. + + * contrib/hbqt/qtcore/hbqt_hbqevents.cpp + - Commented out: a hack where QClosEvent was being treated + differently then other events. + + * contrib/hbqt/tests/demoqt.prg + * Parented: QMessageBox() ( Read below ) + + * contrib/hbide/idedocks.prg + - Removed: one hack which at begining was there to activate + QMainWindow's docking area resizable. + + * contrib/hbide/idemain.prg + + Changed: ::cWrkCodec to be "EN" by default. + It fixes recent regression in hbIDE for certain users. + + * contrib/hbide/idemisc.prg + * Parented: QMessageBox() should always be constructed with a + parent because of special handelling of blocking dialog + where parent is treated slightly different than other + Qt widgets. This fixes a long-standing bug in hbIDE where + appnl was rendered in indefinite loop when "X" button + was employed to terminate and confirm dialog would + not be terminated internally. + So for QMessageBox() and, to be on the safer side, all + widets derived from QDialog() should be constructed + with a parent and at the end be reparented with a + just-to-be-deleted-QWidget(), like: + oMB := QMessageBox( oParent ) + ... + oMB:setParent( QWidget() ) + RETURN something + 2012-06-19 16:24 UTC+0200 Viktor Szakats (harbour syenar.net) * config/win/watcom.mk ! fixed RC compilation for watcom diff --git a/harbour/contrib/hbide/idedocks.prg b/harbour/contrib/hbide/idedocks.prg index 5bc16cbd42..218d2ed64e 100644 --- a/harbour/contrib/hbide/idedocks.prg +++ b/harbour/contrib/hbide/idedocks.prg @@ -364,7 +364,6 @@ METHOD IdeDocks:buildDialog() ::oIde:oDlg := XbpDialog():new() ::oDlg:icon := hbide_image( "hbide" ) ::oDlg:title := "Harbour IDE" - ::oDlg:qtObject := hbide_getUI( "mainwindow" ) ::oDlg:create( , , , , , .f. ) ::oDlg:oWidget:setStyleSheet( GetStyleSheet( "QMainWindow", ::nAnimantionMode ) ) diff --git a/harbour/contrib/hbide/idemain.prg b/harbour/contrib/hbide/idemain.prg index 5adddcadca..4eb9b5cc66 100644 --- a/harbour/contrib/hbide/idemain.prg +++ b/harbour/contrib/hbide/idemain.prg @@ -284,7 +284,7 @@ CLASS HbIde DATA cWrkFolderLast INIT "" DATA cWrkProject INIT "" DATA cWrkTheme INIT "" - DATA cWrkCodec INIT "" + DATA cWrkCodec INIT "EN" DATA cWrkPathMk2 INIT hb_getenv( "HBIDE_DIR_HBMK2" ) DATA cWrkPathEnv INIT hb_DirBase() DATA cWrkEnvironment INIT "" diff --git a/harbour/contrib/hbide/idemisc.prg b/harbour/contrib/hbide/idemisc.prg index c73d7feab9..970093d586 100644 --- a/harbour/contrib/hbide/idemisc.prg +++ b/harbour/contrib/hbide/idemisc.prg @@ -217,60 +217,69 @@ FUNCTION hbide_posAndSize( qWidget ) /*----------------------------------------------------------------------*/ FUNCTION hbide_showWarning( cMsg, cInfo, cTitle, qParent ) - LOCAL oMB + LOCAL oMB, nRet DEFAULT cTitle TO "Information" DEFAULT qParent TO SetAppWindow():oWidget - oMB := QMessageBox() + oMB := QMessageBox( qParent ) oMB:setText( cMsg ) IF !empty( cInfo ) oMB:setInformativeText( cInfo ) ENDIF oMB:setIcon( QMessageBox_Critical ) - oMB:setParent( qParent ) oMB:setWindowFlags( Qt_Dialog ) oMB:setWindowTitle( cTitle ) - RETURN oMB:exec() + nRet := oMB:exec() + oMB:setParent( QWidget() ) + + RETURN nRet /*----------------------------------------------------------------------*/ FUNCTION hbide_getYesNo( cMsg, cInfo, cTitle ) - LOCAL oMB + LOCAL oMB, nRet DEFAULT cTitle TO "Option Please!" - oMB := QMessageBox() + oMB := QMessageBox( hbide_setIde():oDlg:oWidget ) oMB:setText( ""+ cMsg +"" ) IF !empty( cInfo ) oMB:setInformativeText( cInfo ) ENDIF oMB:setIcon( QMessageBox_Information ) oMB:setWindowTitle( cTitle ) + oMB:setWindowFlags( Qt_Dialog ) oMB:setStandardButtons( QMessageBox_Yes + QMessageBox_No ) - RETURN ( oMB:exec() == QMessageBox_Yes ) + nRet := oMB:exec() + + oMB:setParent( QWidget() ) + + RETURN ( nRet == QMessageBox_Yes ) /*----------------------------------------------------------------------*/ FUNCTION hbide_getYesNoCancel( cMsg, cInfo, cTitle ) - LOCAL oMB + LOCAL oMB, nRet DEFAULT cTitle TO "Option Please!" - oMB := QMessageBox() + oMB := QMessageBox( SetAppWindow():oWidget ) oMB:setText( ""+ cMsg +"" ) IF !empty( cInfo ) oMB:setInformativeText( cInfo ) ENDIF oMB:setIcon( QMessageBox_Information ) - oMB:setParent( SetAppWindow():oWidget ) oMB:setWindowFlags( Qt_Dialog ) oMB:setWindowTitle( cTitle ) oMB:setStandardButtons( QMessageBox_Yes + QMessageBox_No + QMessageBox_Cancel ) - RETURN oMB:exec() + nRet := oMB:exec() + oMB:setParent( QWidget() ) + + RETURN nRet /*----------------------------------------------------------------------*/ diff --git a/harbour/contrib/hbqt/qtcore/hbqt_bind.cpp b/harbour/contrib/hbqt/qtcore/hbqt_bind.cpp index c00b5b504e..d60f26f13d 100644 --- a/harbour/contrib/hbqt/qtcore/hbqt_bind.cpp +++ b/harbour/contrib/hbqt/qtcore/hbqt_bind.cpp @@ -55,6 +55,7 @@ #include "hbapi.h" #include "hbapiitm.h" #include "hbstack.h" +#include "hbthread.h" #include "hbvm.h" #include "hbapierr.h" @@ -63,65 +64,6 @@ #include "hbqt_hbqslots.h" #include "hbqt_hbqevents.h" - -typedef struct _HBQT_BIND -{ - void * qtObject; - void * hbObject; - PHBQT_DEL_FUNC pDelFunc; - int iFlags; - bool fDeleting; - char szClassName[ HB_SYMBOL_NAME_LEN + 1 ]; - HBQDestroyer * pDestroyer; - HBQSlots * pReceiverSlots; - HBQEvents * pReceiverEvents; - bool fEventFilterInstalled; - struct _HBQT_BIND * next; -} -HBQT_BIND, * PHBQT_BIND; - -typedef struct -{ - PHBQT_BIND s_hbqt_binds; -} HB_BIND_DATA, * PHB_BIND_DATA; - -#define __HBQT_WITH_MT_SUPPORT__NO - -#ifdef __HBQT_WITH_MT_SUPPORT__ - -static void hbqt_bindInit( void * cargo ) -{ - HB_TRACE( HB_TR_DEBUG, ( "....................................hbqt_bindInit............0............................." ) ); - ( ( PHB_BIND_DATA ) cargo )->s_hbqt_binds = NULL; - HB_TRACE( HB_TR_DEBUG, ( "....................................hbqt_bindInit............1............................." ) ); -} - -static void hbqt_bindRelease( void * cargo ) -{ - HB_TRACE( HB_TR_DEBUG, ( "....................................hbqt_bindRelease.........0............................." ) ); - PHBQT_BIND hbqt_bind; - - while( ( ( PHB_BIND_DATA ) cargo )->s_hbqt_binds ) - { - hbqt_bind = ( ( PHB_BIND_DATA ) cargo )->s_hbqt_binds; - HB_TRACE( HB_TR_DEBUG, ( "....................................hbqt_bindRelease( %p, %s )", hbqt_bind->qtObject, hbqt_bind->szClassName ) ); - hbqt_bindDestroyHbObject( hb_arrayFromId( NULL, hbqt_bind->hbObject ) ); - } - ( ( PHB_BIND_DATA ) cargo )->s_hbqt_binds = NULL; - HB_TRACE( HB_TR_DEBUG, ( "....................................hbqt_bindRelease.........1............................." ) ); -} - -static HB_TSD_NEW( s_bindData, sizeof( HB_BIND_DATA ), hbqt_bindInit, hbqt_bindRelease ); - -#define hbqt_bindGetData() ( ( ( PHB_BIND_DATA ) hb_stackGetTSD( &s_bindData ) )->s_hbqt_binds ) - -#else - -static PHB_BIND_DATA s_bindData = NULL; -#define hbqt_bindGetData() ( ( ( PHB_BIND_DATA ) &s_bindData )->s_hbqt_binds ) - -#endif - /* locks for MT mode, now just dummy definitions which checks * if all locks are correctly released. * @@ -144,6 +86,129 @@ static PHB_DYNS s_dynsym_SETSLOTS = NULL; static PHB_DYNS s_dynsym___EVENTS = NULL; static PHB_DYNS s_dynsym_SETEVENTS = NULL; +typedef struct _HBQT_BIND +{ + void * qtObject; + void * hbObject; + PHBQT_DEL_FUNC pDelFunc; + int iFlags; + bool fDeleting; + char szClassName[ HB_SYMBOL_NAME_LEN + 1 ]; + bool fEventFilterInstalled; + int iThreadId; + struct _HBQT_BIND * next; +} +HBQT_BIND, * PHBQT_BIND; + +typedef struct +{ + PHBQT_BIND s_hbqt_binds; +} HB_BIND_DATA, * PHB_BIND_DATA; + +typedef struct +{ + int iThreadId; + HBQDestroyer * pDestroyer; + HBQSlots * pReceiverSlots; + HBQEvents * pReceiverEvents; +} HB_BIND_THREADDATA, * PHB_BIND_THREADDATA; + +HB_FUNC_EXTERN( HB_THREADID ); + +static int s_bind_threadId = 0; + +static int hbqt_bindGetThreadId() +{ + HBQT_BIND_LOCK + s_bind_threadId++; + HBQT_BIND_UNLOCK + return s_bind_threadId; +} + +#define __HBQT_WITH_MT_SUPPORT__NO +#ifdef __HBQT_WITH_MT_SUPPORT__ +static void hbqt_bindInit( void * cargo ) +{ + HB_TRACE( HB_TR_DEBUG, ( "...hbqt_bindInit............0........." ) ); + ( ( PHB_BIND_DATA ) cargo )->s_hbqt_binds = NULL; + HB_TRACE( HB_TR_DEBUG, ( "...hbqt_bindInit............1........." ) ); +} +static void hbqt_bindRelease( void * cargo ) +{ + HB_TRACE( HB_TR_DEBUG, ( "...hbqt_bindRelease.........0........." ) ); + PHBQT_BIND hbqt_bind; + + while( ( ( PHB_BIND_DATA ) cargo )->s_hbqt_binds ) + { + hbqt_bind = ( ( PHB_BIND_DATA ) cargo )->s_hbqt_binds; + HB_TRACE( HB_TR_DEBUG, ( "...hbqt_bindRelease( %p, %s )", hbqt_bind->qtObject, hbqt_bind->szClassName ) ); + hbqt_bindDestroyHbObject( hb_arrayFromId( NULL, hbqt_bind->hbObject ) ); + } + ( ( PHB_BIND_DATA ) cargo )->s_hbqt_binds = NULL; + HB_TRACE( HB_TR_DEBUG, ( "...hbqt_bindRelease.........1........." ) ); +} +static HB_TSD_NEW( s_bindData, sizeof( HB_BIND_DATA ), hbqt_bindInit, hbqt_bindRelease ); +#define hbqt_bindGetData() ( ( ( PHB_BIND_DATA ) hb_stackGetTSD( &s_bindData ) )->s_hbqt_binds ) +#else +static PHB_BIND_DATA s_bindData = NULL; +#define hbqt_bindGetData() ( ( ( PHB_BIND_DATA ) &s_bindData )->s_hbqt_binds ) +#endif + + +static void hbqt_bindThreadInit( void * cargo ) +{ + PHB_BIND_THREADDATA pBindThreadData = ( ( PHB_BIND_THREADDATA ) cargo ); + + pBindThreadData->iThreadId = hbqt_bindGetThreadId(); + HB_TRACE( HB_TR_DEBUG, ( "...hbqt_bindThreadInit( %i )...STARTS",pBindThreadData->iThreadId ) ); + pBindThreadData->pDestroyer = new HBQDestroyer(); + pBindThreadData->pReceiverSlots = new HBQSlots(); + pBindThreadData->pReceiverEvents = new HBQEvents(); + HB_TRACE( HB_TR_DEBUG, ( "...hbqt_bindThreadInit( %i )...ENDS",pBindThreadData->iThreadId ) ); +} +static void hbqt_bindThreadRelease( void * cargo ) +{ + PHB_BIND_THREADDATA pBindThreadData = ( ( PHB_BIND_THREADDATA ) cargo ); + int id = pBindThreadData->iThreadId; + + HB_TRACE( HB_TR_DEBUG, ( "...hbqt_bindThreadRelease( %i )...STARTS", id ) ); + + QList deleteIt; + + PHBQT_BIND bind; + HBQT_BIND_LOCK + bind = hbqt_bindGetData(); + while( bind ) + { + if( bind->iThreadId == id ) + { + deleteIt << bind->hbObject; + } + bind = bind->next; + } + HBQT_BIND_UNLOCK + + while( ! deleteIt.isEmpty() ) + { + if( hbqt_bindIsHbObject( ( PHB_ITEM ) deleteIt.at( 0 ) ) ) + { + hbqt_bindDestroyHbObject( hb_arrayFromId( NULL, deleteIt.at( 0 ) ) ); + hb_itemRelease( ( PHB_ITEM ) deleteIt.at( 0 ) ); + } + deleteIt.removeAt( 0 ); + } + + delete pBindThreadData->pDestroyer; + delete pBindThreadData->pReceiverSlots; + delete pBindThreadData->pReceiverEvents; + + HB_TRACE( HB_TR_DEBUG, ( "...hbqt_bindThreadRelease( %i )...ENDS",id ) ); +} + +static HB_TSD_NEW( s_bindThreadData, sizeof( HB_BIND_THREADDATA ), hbqt_bindThreadInit, hbqt_bindThreadRelease ); +#define hbqt_bindGetThreadData() ( ( PHB_BIND_THREADDATA ) hb_stackGetTSD( &s_bindThreadData ) ) + + static void hbqt_bind_init( void * cargo ) { HB_SYMBOL_UNUSED( cargo ); @@ -165,9 +230,11 @@ static void hbqt_bind_exit( void * cargo ) PHB_ITEM hbqt_bindGetHbObject( PHB_ITEM pItem, void * qtObject, const char * szClassName, PHBQT_DEL_FUNC pDelFunc, int iFlags ) { + int id = hbqt_bindGetThreadData()->iThreadId; + char * pname = ( char * ) hb_xgrab( 200 ); char * pname1 = ( char * ) hb_xgrab( 200 ); - HB_TRACE( HB_TR_DEBUG, ( ".................HARBOUR_REQUEST_BIND_OBJECT( %p, %i, %s, %s, %s ).................", qtObject, iFlags, szClassName, hb_procname( 0, pname, HB_TRUE ), hb_procname( 1, pname1, HB_TRUE ) ) ); + HB_TRACE( HB_TR_DEBUG, ( "......HARBOUR_REQUEST_BIND_OBJECT( %p, %s, %i, %i, %s, %s )", qtObject, szClassName, iFlags, id, hb_procname( 0, pname, HB_TRUE ), hb_procname( 1, pname1, HB_TRUE ) ) ); hb_xfree( pname ); hb_xfree( pname1 ); @@ -188,7 +255,7 @@ PHB_ITEM hbqt_bindGetHbObject( PHB_ITEM pItem, void * qtObject, const char * szC { 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; } @@ -204,7 +271,9 @@ PHB_ITEM hbqt_bindGetHbObject( PHB_ITEM pItem, void * qtObject, const char * szC if( HB_IS_OBJECT( hb_stackReturnItem() ) && hb_vmRequestQuery() == 0 ) { if( pItem == NULL ) + { pItem = hb_itemNew( NULL ); + } pObject = hb_stackReturnItem(); if( pItem != pObject ) { @@ -219,10 +288,8 @@ PHB_ITEM hbqt_bindGetHbObject( PHB_ITEM pItem, void * qtObject, const char * szC bind->pDelFunc = pDelFunc; bind->iFlags = iFlags; bind->fDeleting = false; - bind->pDestroyer = new HBQDestroyer(); - bind->pReceiverSlots = new HBQSlots(); - bind->pReceiverEvents = new HBQEvents(); bind->fEventFilterInstalled = false; + bind->iThreadId = id; hb_strncpy( bind->szClassName, szClassName, HB_SIZEOFARRAY( bind->szClassName ) - 1 ); bind->next = hbqt_bindGetData(); hbqt_bindGetData() = bind; @@ -235,25 +302,23 @@ PHB_ITEM hbqt_bindGetHbObject( PHB_ITEM pItem, void * qtObject, const char * szC QObject * obj = ( QObject * ) qtObject; QString className = ( QString ) obj->metaObject()->className(); - if( ( ( className != "HBQSlots" ) && ( className != "HBQEvents" ) ) ) + if( pDelFunc != NULL ) { - if( pDelFunc != NULL ) - QObject::connect( obj, SIGNAL( destroyed(QObject*) ), bind->pDestroyer, SLOT( destroyer() ) ); - - 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 ); + QObject::connect( obj, SIGNAL( destroyed(QObject*) ), hbqt_bindGetThreadData()->pDestroyer, SLOT( destroyer() ) ); } + 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 { - HB_TRACE( HB_TR_DEBUG, ( "hbqt_bindGetHbObject( %p )", qtObject ) ); + HB_TRACE( HB_TR_DEBUG, ( "......hbqt_bindGetHbObject( %p )", qtObject ) ); } } } @@ -264,8 +329,10 @@ PHB_ITEM hbqt_bindGetHbObject( PHB_ITEM pItem, void * qtObject, const char * szC PHB_ITEM hbqt_bindSetHbObject( PHB_ITEM pItem, void * qtObject, const char * szClassName, PHBQT_DEL_FUNC pDelFunc, int iFlags ) { + int id = hbqt_bindGetThreadData()->iThreadId; + Q_UNUSED( szClassName ); - HB_TRACE( HB_TR_DEBUG, ( "ENTER hbqt_bindSetHbObject( %p, %s )", qtObject, szClassName ) ); + HB_TRACE( HB_TR_DEBUG, ( "......ENTER hbqt_bindSetHbObject( %p, %s )", qtObject, szClassName ) ); PHB_ITEM pObject = NULL; @@ -281,50 +348,141 @@ PHB_ITEM hbqt_bindSetHbObject( PHB_ITEM pItem, void * qtObject, const char * szC bind = hbqt_bindGetData(); pObject = hb_param( 0, HB_IT_OBJECT ); - if( 1 == 1 ) /* QUESTION: What is this? */ + if( pObject && hb_vmRequestQuery() == 0 ) { - if( pObject && hb_vmRequestQuery() == 0 ) + if( pItem == NULL ) { - if( pItem == NULL ) - pItem = hb_itemNew( NULL ); + pItem = hb_itemNew( NULL ); + } + if( pItem != pObject ) + { + hb_itemMove( pItem, pObject ); + pObject = pItem; + } - if( pItem != pObject ) + bind = ( PHBQT_BIND ) hb_xgrab( sizeof( HBQT_BIND ) ); + memset( bind, 0, sizeof( HBQT_BIND ) ); + bind->qtObject = qtObject; + bind->pDelFunc = pDelFunc; + bind->iFlags = iFlags; + bind->fDeleting = false; + bind->fEventFilterInstalled = false; + bind->iThreadId = id; + hb_strncpy( bind->szClassName, szClassName, HB_SIZEOFARRAY( bind->szClassName ) - 1 ); + bind->next = hbqt_bindGetData(); + hbqt_bindGetData() = bind; + + bind->hbObject = hb_arrayId( pObject ); + + if( iFlags & HBQT_BIT_QOBJECT ) + { + if( pDelFunc != NULL ) { - hb_itemMove( pItem, pObject ); - pObject = pItem; - } - - bind = ( PHBQT_BIND ) hb_xgrab( sizeof( HBQT_BIND ) ); - memset( bind, 0, sizeof( HBQT_BIND ) ); - bind->qtObject = qtObject; - bind->pDelFunc = pDelFunc; - bind->iFlags = iFlags; - bind->fDeleting = false; - bind->pDestroyer = new HBQDestroyer(); - bind->pReceiverSlots = new HBQSlots(); - bind->pReceiverEvents = new HBQEvents(); - bind->fEventFilterInstalled = false; - hb_strncpy( bind->szClassName, szClassName, HB_SIZEOFARRAY( bind->szClassName ) - 1 ); - bind->next = hbqt_bindGetData(); - hbqt_bindGetData() = bind; - - bind->hbObject = hb_arrayId( pObject ); - - if( iFlags & HBQT_BIT_QOBJECT ) - { - if( pDelFunc != NULL ) - QObject::connect( ( QObject * ) qtObject, SIGNAL( destroyed(QObject*) ), bind->pDestroyer, SLOT( destroyer() ) ); - - HB_TRACE( HB_TR_DEBUG, ( "hbqt_bindSetHbObject( QObject %p )...%s", qtObject, ( ( QObject * ) qtObject )->metaObject()->className() ) ); + QObject::connect( ( QObject * ) qtObject, SIGNAL( destroyed(QObject*) ), hbqt_bindGetThreadData()->pDestroyer, SLOT( destroyer() ) ); } + HB_TRACE( HB_TR_DEBUG, ( "......hbqt_bindSetHbObject( QObject %p )...%s", qtObject, ( ( QObject * ) qtObject )->metaObject()->className() ) ); } } HBQT_BIND_UNLOCK - HB_TRACE( HB_TR_DEBUG, ( "hbqt_bindSetHbObject returns PHB_ITEM = %p", pObject ) ); + HB_TRACE( HB_TR_DEBUG, ( "......hbqt_bindSetHbObject returns PHB_ITEM = %p", pObject ) ); return pObject; } +void hbqt_bindDestroyHbObject( PHB_ITEM pObject ) +{ + void * hbObject = hb_arrayId( pObject ); + + if( hbObject ) + { + PHBQT_BIND * bind_ptr, bind; + + HBQT_BIND_LOCK + bind_ptr = &( hbqt_bindGetData() ); + while( ( bind = * bind_ptr ) != NULL ) + { + if( bind->hbObject == hbObject ) + { + bool fDelQtObject = false; + + if( bind->iFlags & HBQT_BIT_OWNER ) + { + 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; + } + + HB_TRACE( HB_TR_DEBUG, ( ".........HARBOUR_DESTROY_BEGINS( %p, %s, %i )", bind->qtObject, bind->szClassName, bind->iFlags ) ); + * bind_ptr = bind->next; + + if( fDelQtObject ) + { + if( bind->pDelFunc != NULL ) + { + HB_TRACE( HB_TR_DEBUG, ( ".........HARBOUR_DESTROYING_ACTUAL_QT_OBJECT( %p, %s, %i )", bind->qtObject, bind->szClassName, bind->iFlags ) ); + 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( bind->iThreadId == 1 && ( ( 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 ) + { + HB_TRACE( HB_TR_DEBUG, ( ".........HARBOUR_DESTROYING_ACTUAL_QT_OBJECT_NAMED( %p, %s )", bind->qtObject, bind->szClassName ) ); + bind->fDeleting = true; + bind->pDelFunc( bind->qtObject, bind->iFlags ); + bind->fDeleting = false; + } + } + } + hb_xfree( bind ); + break; + } + bind_ptr = &bind->next; + } + HBQT_BIND_UNLOCK + } +} + +void hbqt_bindDestroyQtObject( void * qtObject ) +{ + HB_TRACE( HB_TR_DEBUG, ( "............QT_DESTROY_BEGINS( %p )..............", qtObject ) ); + if( qtObject && hb_vmRequestReenter() ) + { + PHBQT_BIND * bind_ptr, bind; + + HBQT_BIND_LOCK + bind_ptr = &( hbqt_bindGetData() ); + while( ( bind = * bind_ptr ) != NULL ) + { + if( bind->qtObject == qtObject ) + { + HB_TRACE( HB_TR_DEBUG, ( "............QT_DESTROYING( %p, %s )", qtObject, bind->szClassName ) ); + * bind_ptr = bind->next; + if( ! bind->fDeleting ) + { + hb_xfree( bind ); + HB_TRACE( HB_TR_DEBUG, ( "............QT_DESTROYED()" ) ); + } + break; + } + bind_ptr = &bind->next; + } + HBQT_BIND_UNLOCK + + hb_vmRequestRestore(); + } +} + HBQSlots * hbqt_bindGetReceiverSlotsByHbObject( PHB_ITEM pObject ) { HBQSlots * pReceiverSlot = NULL; @@ -339,7 +497,7 @@ HBQSlots * hbqt_bindGetReceiverSlotsByHbObject( PHB_ITEM pObject ) { if( bind->hbObject == hbObject ) { - pReceiverSlot = bind->pReceiverSlots; + pReceiverSlot = hbqt_bindGetThreadData()->pReceiverSlots; HB_TRACE( HB_TR_DEBUG, ( "hbqt_bindGetReceiverSlotByHbObject( %p )", bind->qtObject ) ); break; } @@ -364,11 +522,11 @@ HBQEvents * hbqt_bindGetReceiverEventsByHbObject( PHB_ITEM pObject ) { if( bind->hbObject == hbObject ) { - pReceiverEvents = bind->pReceiverEvents; + pReceiverEvents = hbqt_bindGetThreadData()->pReceiverEvents; if( ! bind->fEventFilterInstalled ) { bind->fEventFilterInstalled = true; - bind->pReceiverEvents->hbInstallEventFilter( pObject ); + hbqt_bindGetThreadData()->pReceiverEvents->hbInstallEventFilter( pObject ); } HB_TRACE( HB_TR_DEBUG, ( "hbqt_bindGetReceiverEventsByHbObject( %p )", bind->qtObject ) ); break; @@ -454,105 +612,6 @@ void * hbqt_bindGetQtObject( PHB_ITEM pObject ) return qtObject; } -void hbqt_bindDestroyHbObject( PHB_ITEM pObject ) -{ - void * hbObject = hb_arrayId( pObject ); - - if( hbObject ) - { - PHBQT_BIND * bind_ptr, bind; - - HBQT_BIND_LOCK - bind_ptr = &( hbqt_bindGetData() ); - while( ( bind = * bind_ptr ) != NULL ) - { - if( bind->hbObject == hbObject ) - { - bool fDelQtObject = false; - - if( bind->iFlags & HBQT_BIT_OWNER ) - { - 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; - } - - HB_TRACE( HB_TR_DEBUG, ( "..............HARBOUR_DESTROY_BEGINS( %p, %i ).............. %s", bind->qtObject, bind->iFlags, bind->szClassName ) ); - * bind_ptr = bind->next; - - delete bind->pReceiverSlots; - delete bind->pReceiverEvents; - if( fDelQtObject ) - { - if( bind->pDelFunc != NULL ) - { - HB_TRACE( HB_TR_DEBUG, ( ".......HARBOUR_DESTROYING_ACTUAL_QT_OBJECT( %p, %i ).............. %s", bind->qtObject, bind->iFlags, bind->szClassName ) ); - 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 ) - { - HB_TRACE( HB_TR_DEBUG, ( ".......HARBOUR_DESTROYING_ACTUAL_QT_OBJECT_NAMED( %p, %s )", bind->qtObject, bind->szClassName ) ); - bind->fDeleting = true; - bind->pDelFunc( bind->qtObject, bind->iFlags ); - bind->fDeleting = false; - } - } - } - delete bind->pDestroyer; - - hb_xfree( bind ); - break; - } - bind_ptr = &bind->next; - } - HBQT_BIND_UNLOCK - } -} - -void hbqt_bindDestroyQtObject( void * qtObject ) -{ - HB_TRACE( HB_TR_DEBUG, ( "....................................QT_DESTROY_BEGINS( %p )..............", qtObject ) ); - if( qtObject && hb_vmRequestReenter() ) - { - PHBQT_BIND * bind_ptr, bind; - - HBQT_BIND_LOCK - bind_ptr = &( hbqt_bindGetData() ); - 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; - } - bind_ptr = &bind->next; - } - HBQT_BIND_UNLOCK - - hb_vmRequestRestore(); - } -} - void hbqt_bindSetOwner( void * qtObject, HB_BOOL fOwner ) { PHBQT_BIND bind; diff --git a/harbour/contrib/hbqt/qtcore/hbqt_hbqevents.cpp b/harbour/contrib/hbqt/qtcore/hbqt_hbqevents.cpp index 65ecfb5a38..15a721c58e 100644 --- a/harbour/contrib/hbqt/qtcore/hbqt_hbqevents.cpp +++ b/harbour/contrib/hbqt/qtcore/hbqt_hbqevents.cpp @@ -183,10 +183,12 @@ bool HBQEvents::eventFilter( QObject * object, QEvent * event ) hb_itemRelease( pArray ); } } + #if 0 if( eventtype == QEvent::Close ) { stopTheEventChain = true; } + #endif } } hb_vmRequestRestore(); diff --git a/harbour/contrib/hbqt/tests/demoqt.prg b/harbour/contrib/hbqt/tests/demoqt.prg index dbf50ff720..cf07ecd356 100644 --- a/harbour/contrib/hbqt/tests/demoqt.prg +++ b/harbour/contrib/hbqt/tests/demoqt.prg @@ -74,8 +74,8 @@ STATIC oSys, oMenuSys, oActShow, oActHide /*----------------------------------------------------------------------*/ -FUNCTION My_Events( e ) - MsgInfo( "Pressed: " + hb_ntos( e:key() ) ) +FUNCTION My_Events( oWnd, e ) + MsgInfo( oWnd, "Pressed: " + hb_ntos( e:key() ) ) RETURN nil /*----------------------------------------------------------------------*/ @@ -114,7 +114,7 @@ PROCEDURE Main() oBtn := Build_PushButton( oDA, { 30,240 }, { 100,50 } ) oBtn:setStyleSheet( "background: #a00fff;" ) - oWnd:connect( QEvent_KeyPress, {|e| My_Events( e ) } ) + oWnd:connect( QEvent_KeyPress, {|e| My_Events( oWnd, e ) } ) oWnd:connect( QEvent_Close , {|| lExit := .t. } ) oWnd:Show() @@ -170,11 +170,11 @@ PROCEDURE ExecOneMore() aMenu := Build_MenuBar( oWnd ) aTool := Build_ToolBar( oWnd ) oLabel := Build_Label( oDA, { 30,190 }, { 300, 30 } ) - oBtn := Build_PushButton( oDA, { 30,240 }, { 100,50 }, "CLOSE", "This dialog will be closed now!", @lExit ) aGrid := Build_Grid( oDA, { 30, 30 }, { 450,150 } ) aTabs := Build_Tabs( oDA, { 510, 5 }, { 360, 400 } ) oProg := Build_ProgressBar( oDA, { 30,300 }, { 200,30 } ) aList := Build_ListBox( oDA, { 310,240 }, { 150, 100 } ) + oBtn := Build_PushButton( oDA, { 30,240 }, { 100,50 }, "CLOSE", "This dialog will be closed now!", @lExit ) oSBar := QStatusBar( oWnd ) oWnd:setStatusBar( oSBar ) @@ -257,7 +257,7 @@ STATIC FUNCTION Build_MenuBar( oWnd ) oMenu2:addSeparator() oActOther := oMenu2:addAction( "&Another Dialog" ) - oActOther:connect( "triggered(bool)", {|| ExecOneMore() } ) + oActOther:connect( "triggered(bool)", {|| hb_threadStart( {|| ExecOneMore( oWnd ) } ) } ) oMenuBar:addMenu( oMenu2 ) @@ -324,7 +324,7 @@ STATIC FUNCTION Build_PushButton( oWnd, aPos, aSize, cLabel, cMsg, lExit ) IF HB_ISLOGICAL( lExit ) oBtn:connect( "clicked()", {|| lExit := .t. } ) ELSE - oBtn:connect( "clicked()", {|| MsgInfo( cMsg ), lExit := .t. } ) + oBtn:connect( "clicked()", {|| MsgInfo( oWnd, cMsg ), lExit := .t. } ) ENDIF RETURN oBtn @@ -446,7 +446,7 @@ STATIC FUNCTION Build_Controls( oWnd ) LOCAL oEdit, oCheckBox, oComboBox, oSpinBox, oRadioButton oEdit := QLineEdit( oWnd ) - oEdit:connect( "returnPressed()", {|i| i := i, MsgInfo( oEdit:text() ) } ) + oEdit:connect( "returnPressed()", {|i| i := i, MsgInfo( oWnd, oEdit:text() ) } ) oEdit:move( 5, 10 ) oEdit:resize( 345, 30 ) oEdit:setMaxLength( 40 ) @@ -459,13 +459,13 @@ STATIC FUNCTION Build_Controls( oWnd ) oComboBox:addItem( "Third" ) oComboBox:addItem( "First" ) oComboBox:addItem( "Second" ) - oComboBox:connect( "currentIndexChanged(int)", {|i| i := i, MsgInfo( oComboBox:itemText( i ) ) } ) + oComboBox:connect( "currentIndexChanged(int)", {|i| i := i, MsgInfo( oWnd, oComboBox:itemText( i ) ) } ) oComboBox:move( 5, 60 ) oComboBox:resize( 345, 30 ) oComboBox:show() oCheckBox := QCheckBox( oWnd ) - oCheckBox:connect( "stateChanged(int)", {|i| i := i, MsgInfo( IF( i == 0,"Uncheckd","Checked" ) ) } ) + oCheckBox:connect( "stateChanged(int)", {|i| i := i, MsgInfo( oWnd, iif( i == 0,"Uncheckd","Checked" ) ) } ) oCheckBox:setText( "Testing CheckBox HbQt" ) oCheckBox:move( 5, 110 ) oCheckBox:resize( 345, 30 ) @@ -477,7 +477,7 @@ STATIC FUNCTION Build_Controls( oWnd ) oSpinBox:Show() oRadioButton := QRadioButton( oWnd ) - oRadioButton:connect( "clicked()", {|i| i := i, MsgInfo( "Checked" ) } ) + oRadioButton:connect( "clicked()", {|i| i := i, MsgInfo( oWnd, "Checked" ) } ) oRadioButton:Move( 5, 210 ) oRadioButton:ReSize( 345, 30 ) oRadioButton:Show() @@ -514,17 +514,17 @@ STATIC FUNCTION Build_Label( oWnd, aPos, aSize ) /*----------------------------------------------------------------------*/ -STATIC FUNCTION MsgInfo( cMsg ) +STATIC FUNCTION MsgInfo( oWnd, cMsg ) LOCAL oMB - oMB := QMessageBox() + oMB := QMessageBox( oWnd ) oMB:setInformativeText( cMsg ) oMB:setWindowTitle( "Harbour-QT" ) oMB:exec() - oMB := NIL + oMB:setParent( QWidget() ) - RETURN nil + RETURN NIL /*----------------------------------------------------------------------*/ @@ -540,8 +540,8 @@ STATIC FUNCTION FileDialog() /*----------------------------------------------------------------------*/ -STATIC FUNCTION Dialogs( cType ) - LOCAL oDlg //, oUrl +STATIC FUNCTION Dialogs( cType, oParent ) + LOCAL oDlg DO CASE CASE cType == "PageSetup" @@ -557,9 +557,10 @@ STATIC FUNCTION Dialogs( cType ) oDlg:setWindowTitle( "Harbour-QT Wizard to Show Slides etc." ) oDlg:exec() CASE cType == "Colors" - oDlg := QColorDialog() + oDlg := QColorDialog( oParent ) oDlg:setWindowTitle( "Harbour-QT Color Selection Dialog" ) oDlg:exec() + oDlg:setParent( QWidget() ) CASE cType == "WebPage" #if 0 // Till we resolve for oDlg:show() oDlg := QWebView()