From 8f4cd3929ac4f3669f9e25e91a7b84fcc40042f3 Mon Sep 17 00:00:00 2001 From: Pritpal Bedi Date: Thu, 7 Jun 2012 02:04:20 +0000 Subject: [PATCH] 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. --- harbour/ChangeLog | 22 +++++++++ harbour/contrib/hbqt/qtcore/hbqt_bind.cpp | 58 +++++++++++++++++------ harbour/contrib/hbqt/tests/qtrevamp.prg | 46 ++++++++++++++++-- 3 files changed, 106 insertions(+), 20 deletions(-) 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 +