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 <Dialog><Another Dialog>.

    + 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
This commit is contained in:
Pritpal Bedi
2012-06-20 05:03:46 +00:00
parent de6cb99086
commit 3e549d0027
7 changed files with 365 additions and 243 deletions

View File

@@ -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 <Dialog><Another Dialog>.
+ 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

View File

@@ -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 ) )

View File

@@ -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 ""

View File

@@ -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( "<b>"+ cMsg +"</b>" )
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( "<b>"+ cMsg +"</b>" )
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
/*----------------------------------------------------------------------*/

View File

@@ -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<PHB_ITEM> 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;

View File

@@ -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();

View File

@@ -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()