diff --git a/harbour/ChangeLog b/harbour/ChangeLog index a2790643db..5ed2a0a72d 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,20 @@ past entries belonging to author(s): Viktor Szakats. */ +2009-07-14 13:50 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) + * contrib/hbxbp/xbpdialog.prg + * contrib/hbxbp/xbpgeneric.prg + ! Changed the way AppEvent() eventloop was being executed. + Not it is more near to Xbase++, not 100% but near. + CPU consumption is reduced to 2-3 percent. + + * contrib/hbxbp/xbprtf.prg + + Implemented more XbpRTF() features. + + * contrib/hbxbp/tests/demoxbp.prg + + Demonstrated more XbpRtf() features. + Play with Rtf tab. + 2009-07-14 22:42 UTC+0200 Viktor Szakats (harbour.01 syenar.hu) * config/hpux/gcc.cf * config/darwin/gcc.cf diff --git a/harbour/contrib/hbxbp/tests/demoxbp.prg b/harbour/contrib/hbxbp/tests/demoxbp.prg index 4ef3223ddd..b4cf36cfa4 100644 --- a/harbour/contrib/hbxbp/tests/demoxbp.prg +++ b/harbour/contrib/hbxbp/tests/demoxbp.prg @@ -86,8 +86,8 @@ PROCEDURE Main() PROCEDURE BuildADialog() LOCAL oDlg, mp1, mp2, oXbp, nEvent, aSize, aTabs, oDa LOCAL nThread := ThreadID() - LOCAL cThread := hb_ntos( nThread ) - LOCAL aPP, oHtm + //LOCAL cThread := hb_ntos( nThread ) + LOCAL oHtm /* Create Application Window */ oDlg := GuiStdDialog( "Harbour - Xbase++ - QT Dialog [ "+ hb_ntos( nThread )+" ]" ) @@ -172,13 +172,15 @@ PROCEDURE BuildADialog() /* Enter Xbase++ Event Loop - working */ DO WHILE .t. nEvent := AppEvent( @mp1, @mp2, @oXbp ) + IF ( nEvent == xbeP_Close ) .OR. ( nEvent == xbeP_Keyboard .and. mp1 == xbeK_ESC ) -hb_outDebug( " WOW " ) +hb_outdebug( " WOW " ) EXIT ELSEIF nEvent == xbeP_Keyboard .and. mp1 == xbeK_F1 oHtm:setHTML( '
'+;
'This HTML content is pushed dynamically with
:setHTML().' )
ENDIF
+
oXbp:handleEvent( nEvent, mp1, mp2 )
ENDDO
@@ -326,7 +328,7 @@ STATIC FUNCTION Build_MenuBar( oDlg )
oSubMenu:setColorFG( GraMakeRGBColor( { 255, 1, 1 } ) )
#ifdef __HARBOUR__
- #if 0
+ #if 1
oSubMenu := XbpMenu():new( oMenuBar ):create()
oSubMenu:title := "~Dialogs"
#if 1 /* T H R E D E D D I A L O G */
@@ -903,7 +905,7 @@ PROCEDURE FieldStruct( oItem, aField )
/*----------------------------------------------------------------------*/
FUNCTION Build_Statics( oWnd )
- LOCAL oGrp,oLbl, oLin, oBox, oBmp, oBmp1
+ LOCAL oGrp,oLbl, oLin, oBox, oBmp
LOCAL nC1 := 10, nC2 := 45, nC3 := 110, nC4 := 175
LOCAL nW := 50, nH := 50, nG := 10
LOCAL nT := 60
@@ -1115,23 +1117,7 @@ FUNCTION Build_Bitmap( oWnd )
LOCAL nFrmts := { XBPBMP_FORMAT_PNG, XBPBMP_FORMAT_GIF, XBPBMP_FORMAT_JPG, ;
XBPBMP_FORMAT_JPG, XBPBMP_FORMAT_WIN3X }
- aFltr := {}
- aadd( aFltr, { "Windows Bitmap ", "*.bmp" } )
- aadd( aFltr, { "Graphic Interchange Format ", "*.gif" } )
- aadd( aFltr, { "Joint Photographic Experts ", "*.jpg; *.jpeg" } )
- aadd( aFltr, { "Portable Network Graphics ", "*.png" } )
- aadd( aFltr, { "Portable Pixmap ", "*.ppm" } )
- aadd( aFltr, { "Tagged Image File Format ", "*.tiff" } )
- aadd( aFltr, { "X11 Bitmap ", "*.xbm" } )
- aadd( aFltr, { "X11 Pixmap ", "*.xpm" } )
- aeval( aFltr, {|e_,i| aFltr[ i,1 ] := trim( e_[ 1 ] ) } )
-
- oDlg := XbpFileDialog():new( oWnd, , {10,10} )
- oDlg:title := "Select an image to be converted"
- oDlg:fileFilters := aFltr
- oDlg:create()
-
- cFile := oDlg:open( hb_DirBase(), , .f. )
+ cFile := GetAnImageFile( oWnd, "Select an image to be converted" )
IF !empty( cFile )
oBmp := XbpBitmap():new():create()
@@ -1166,6 +1152,30 @@ FUNCTION Build_Bitmap( oWnd )
/*----------------------------------------------------------------------*/
+FUNCTION GetAnImageFile( oWnd, cTitle )
+ LOCAL aFltr := {}
+
+ DEFAULT cTitle TO "Select an Image"
+
+ aadd( aFltr, { "Portable Network Graphics ", "*.png" } )
+ aadd( aFltr, { "Windows Bitmap ", "*.bmp" } )
+ aadd( aFltr, { "Graphic Interchange Format ", "*.gif" } )
+ aadd( aFltr, { "Joint Photographic Experts ", "*.jpg; *.jpeg" } )
+ aadd( aFltr, { "Portable Pixmap ", "*.ppm" } )
+ aadd( aFltr, { "Tagged Image File Format ", "*.tiff" } )
+ aadd( aFltr, { "X11 Bitmap ", "*.xbm" } )
+ aadd( aFltr, { "X11 Pixmap ", "*.xpm" } )
+ aeval( aFltr, {|e_,i| aFltr[ i,1 ] := trim( e_[ 1 ] ) } )
+
+ oDlg := XbpFileDialog():new( oWnd, , {10,10} )
+ oDlg:title := cTitle
+ oDlg:fileFilters := aFltr
+ oDlg:create()
+
+ RETURN oDlg:open( hb_DirBase(), , .f. )
+
+/*----------------------------------------------------------------------*/
+
FUNCTION Build_FontDialog( oWnd )
LOCAL oDlg
@@ -1222,42 +1232,63 @@ FUNCTION Build_PrintDialog( oWnd )
FUNCTION Build_Rtf( oWnd )
LOCAL oRTF, oBtn
LOCAL sz_:= oWnd:currentSize()
+ LOCAL nW := 50, nG := 8, nH := 20, nT := sz_[2]-55
- oBtn := XbpPushButton():new( oWnd, , {10,sz_[2]-70}, {50,35} )
+ oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*0, nT}, {nW,nH} )
oBtn:caption := 'Image'
oBtn:create()
oBtn:activate := {|| RtfInsertImage( oRtf ) }
- oBtn := XbpPushButton():new( oWnd, , {10+60,sz_[2]-70}, {50,35} )
+ oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*1, nT}, {nW,nH} )
oBtn:caption := 'Undo'
oBtn:create()
oBtn:activate := {|| oRtf:undo() }
- oBtn := XbpPushButton():new( oWnd, , {10+120,sz_[2]-70}, {50,35} )
+ oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*2, nT}, {nW,nH} )
oBtn:caption := 'Redo'
oBtn:create()
#ifdef __HARBOUR__
oBtn:activate := {|| oRtf:redo() }
#endif
- oBtn := XbpPushButton():new( oWnd, , {10+180,sz_[2]-70}, {50,35} )
+ oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*3, nT}, {nW,nH} )
oBtn:caption := 'ULine'
oBtn:create()
oBtn:activate := {|| oRtf:selUnderline := .t. }
- oBtn := XbpPushButton():new( oWnd, , {10+240,sz_[2]-70}, {50,35} )
+ oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*4, nT}, {nW,nH} )
oBtn:caption := 'Bold'
oBtn:create()
oBtn:activate := {|| oRtf:selBold := .t. }
- oBtn := XbpPushButton():new( oWnd, , {10+295,sz_[2]-70}, {45,35} )
+ oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*5, nT}, {nW,nH} )
oBtn:caption := 'Italic'
oBtn:create()
oBtn:activate := {|| oRtf:selItalic := .t. }
+ oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*0, nT-25}, {nW,nH} )
+ oBtn:caption := 'Load'
+ oBtn:create()
+ oBtn:activate := {|| RtfLoadDocument( oRtf ) }
+ oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*1, nT-25}, {nW,nH} )
+ oBtn:caption := 'Save'
+ oBtn:create()
+ oBtn:activate := {|| RtfSaveDocument( oRtf ) }
+
+ oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*2, nT-25}, {nW,nH} )
+ oBtn:caption := 'Font++'
+ oBtn:create()
+ oBtn:activate := {|x| x := oRTF:selFontSize, IF( x == 0, x := 11, ), oRTF:selFontSize := x+1 }
+
+ oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*3, nT-25}, {nW,nH} )
+ oBtn:caption := 'Font--'
+ oBtn:create()
+ oBtn:activate := {|x| x := oRTF:selFontSize, IF( x == 0, x := 11, ), oRTF:selFontSize := x-1 }
+
+ //------------------------//
oRTF := XbpRtf():new( oWnd )
- oRTF:create( , , { 10,10 }, { sz_[ 1 ]-23, sz_[ 2 ]-90 } )
+ oRTF:create( , , { 10,10 }, { sz_[ 1 ]-23, sz_[ 2 ]-100 } )
oRTF:setColorBG( GraMakeRGBColor( {255,255,200} ) )
oRTF:setFontCompoundName( "12.Times" )
@@ -1296,24 +1327,72 @@ FUNCTION Build_Rtf( oWnd )
oRTF:SelItalic := .T.
// oRTF:SelStrikeThru := .T. /* OK */
oRTF:SelUnderline := .T.
- oRTF:selAlignment := 2 //XBPRTF_SELALIGN_RIGHT
+ oRTF:selAlignment := XBPRTF_ALIGN_CENTER
// Reset the text cursor
//
oRTF:SelStart := Len( oRTF:Text )
- oRTF:insertImage( 'copy.png' )
RETURN nil
/*----------------------------------------------------------------------*/
STATIC FUNCTION RtfInsertImage( oRtf )
+ #ifdef __HARBOUR__
+ LOCAL cFile
// Proivide a selection dialog
- oRtf:insertImage( "abs3.png" )
+ cFile := GetAnImageFile( oRtf, 'Select Image to be Inserted' )
+ IF empty( cFile )
+ oRtf:insertImage( "abs3.png" )
+ ELSE
+ oRtf:insertImage( cFile )
+ ENDIF
+ #endif
+ RETURN nil
+
+/*----------------------------------------------------------------------*/
+
+STATIC FUNCTION RtfLoadDocument( oRTF )
+ LOCAL oDlg, cFile, aFiltr := {}
+
+ aadd( aFiltr, { "All Files", "*.*" } )
+ aadd( aFiltr, { "Text File", "*.txt" } )
+ aadd( aFiltr, { "RTF File" , "*.htm; *.html" } )
+
+ oDlg := XbpFileDialog():new():create( oRTF, , { 10,10 } )
+ oDlg:title := "Open an RTF Document"
+ oDlg:center := .t.
+ oDlg:fileFilters := aFiltr
+ oDlg:setColorBG( GraMakeRGBColor( { 255,255,200 } ) )
+
+ cFile := oDlg:open()
+ IF !empty( cFile )
+ oRTF:loadFile( cFile )
+ ENDIF
RETURN nil
/*----------------------------------------------------------------------*/
+STATIC FUNCTION RtfSaveDocument( oRTF )
+ LOCAL oDlg, cFile, aFiltr := {}
+
+ aadd( aFiltr, { "RTF File" , "*.htm; *.html" } )
+ aadd( aFiltr, { "Text File", "*.txt" } )
+
+ oDlg := XbpFileDialog():new():create( oRTF, , { 10,10 } )
+ oDlg:title := "Open an RTF Document"
+ oDlg:center := .t.
+ oDlg:fileFilters := aFiltr
+ oDlg:setColorBG( GraMakeRGBColor( { 255,200,200 } ) )
+
+ cFile := oDlg:saveAs()
+ IF !empty( cFile )
+ oRTF:saveFile( cFile )
+ ENDIF
+
+ RETURN nil
+
+/*----------------------------------------------------------------------*/
diff --git a/harbour/contrib/hbxbp/xbpdialog.prg b/harbour/contrib/hbxbp/xbpdialog.prg
index 8bef57c2ae..2cb0b6438f 100644
--- a/harbour/contrib/hbxbp/xbpdialog.prg
+++ b/harbour/contrib/hbxbp/xbpdialog.prg
@@ -146,6 +146,9 @@ METHOD XbpDialog:create( oParent, oOwner, aPos, aSize, aPresParams, lVisible )
SetAppWindow( Self )
+ /* Thread specific event buffer */
+ InitializeEventBuffer()
+
/* Install Event Loop per Dialog Basis */
/* Limitng */
::oEventLoop := QEventLoop():new( ::pWidget )
diff --git a/harbour/contrib/hbxbp/xbpgeneric.prg b/harbour/contrib/hbxbp/xbpgeneric.prg
index 5f3c2c84e5..26da45c953 100644
--- a/harbour/contrib/hbxbp/xbpgeneric.prg
+++ b/harbour/contrib/hbxbp/xbpgeneric.prg
@@ -80,10 +80,11 @@
STATIC ts_mutex
STATIC oApp
-STATIC aEventLoop := {}
-STATIC ts_events
-//THREAD STATIC ts_events
+THREAD STATIC aEventLoop := {}
+
+//STATIC ts_events
+THREAD STATIC ts_events
THREAD STATIC nEventIn := 0
THREAD STATIC nEventOut := 0
@@ -97,80 +98,82 @@ THREAD STATIC oEventLoop
/*----------------------------------------------------------------------*/
INIT PROCEDURE Qt_Start()
+
+ ts_mutex := hb_mutexCreate()
+ oDummy := XbpObject():new()
+
qt_qapplication()
oApp := QApplication():new()
RETURN
+/*----------------------------------------------------------------------*/
+
EXIT PROCEDURE Qt_End()
qt_qapplication_quit()
RETURN
+/*----------------------------------------------------------------------*/
+/*
+ * Will be called from XbpDialog() | XbpCRT()
+ */
+FUNCTION InitializeEventBuffer()
+
+ IF empty( ts_events )
+ ts_events := array( EVENT_BUFFER )
+ aeval( ts_events, {|e,i| e := e, ts_events[ i ] := { 0, NIL, NIL, NIL, -9999 } } )
+ ENDIF
+//xbp_debug( len( ts_events ) )
+ RETURN nil
+
/*----------------------------------------------------------------------*/
/*
* Internal to the XbpParts , Must NOT be called from Application Code
*/
FUNCTION SetAppEvent( nEvent, mp1, mp2, oXbp )
- //hb_mutexLock( ts_mutex )
-
IF ++nEventIn > EVENT_BUFFER
nEventIn := 1
ENDIF
- ts_events[ nEventIn ] := { nEvent, mp1, mp2, oXbp, ThreadID() }
+//xbp_debug( "SetAppEvent ... ", threadID(), nEventIn )
- //hb_mutexUnLock( ts_mutex )
+ ts_events[ nEventIn,1 ] := nEvent
+ ts_events[ nEventIn,2 ] := mp1
+ ts_events[ nEventIn,3 ] := mp2
+ ts_events[ nEventIn,4 ] := oXbp
+ ts_events[ nEventIn,5 ] := ThreadID()
RETURN nil
/*----------------------------------------------------------------------*/
-FUNCTION AppEvent( mp1, mp2, oXbp )
- LOCAL nEvent, n
+FUNCTION AppEvent( mp1, mp2, oXbp, nTimeout )
+ LOCAL nEvent //, n
- //hb_idleSleep( 0.1 ) /* May be we need QT based mechanism */
-
- #if 0
- //hb_mutexLock( ts_mutex )
- oApp:processEvents()
- //hb_mutexUnLock( ts_mutex )
- #else
- /* Event Loop - Can be one per Application */
-
- //oAppWindow:oEventLoop:processEvents()
- //hb_mutexLock( ts_mutex )
-
- IF( n := ascan( aEventLoop, {|e_| e_[ 2 ] == threadID() } ) ) > 0
- //hb_outDebug( "<<<<<<<<<<<< "+hb_ntos( threadID() ) )
- aEventLoop[ n,1 ]:processEvents()
- //hb_outDebug( ">>>>>>>>>>>>.... "+hb_ntos( threadID() ) )
- ENDIF
-
- //hb_mutexUnLock( ts_mutex )
- #endif
-
- //hb_mutexLock( ts_mutex )
+ DEFAULT nTimeout TO 0
IF ++nEventOut > EVENT_BUFFER
nEventOut := 1
ENDIF
+//xbp_debug( " AppEvent ... ", threadID(), nEventOut )
+ DO WHILE .t.
+ aEventLoop[ 1,1 ]:processEvents_1( 0, 200 )
- IF empty( ts_events[ nEventOut ] ) .OR. ts_events[ nEventOut,5 ] <> ThreadID()
- //nEventOut-- /* Stay back and ensure that no event is missed */
- nEvent := 0
- mp1 := NIL
- mp2 := NIL
- oXbp := oDummy
- ELSE
- //hb_outDebug( str( threadID() )+' '+ str( ts_events[ nEventOut,5 ] ) )
- nEvent := ts_events[ nEventOut,1 ]
- mp1 := ts_events[ nEventOut,2 ]
- mp2 := ts_events[ nEventOut,3 ]
- oXbp := ts_events[ nEventOut,4 ]
- ts_events[ nEventOut ] := NIL
- ENDIF
+ IF ts_events[ nEventOut,5 ] == ThreadID()
+ nEvent := ts_events[ nEventOut,1 ]
+ mp1 := ts_events[ nEventOut,2 ]
+ mp2 := ts_events[ nEventOut,3 ]
+ oXbp := ts_events[ nEventOut,4 ]
+
+ ts_events[ nEventOut,5 ] := -9999 /* an arbirary value never reached by ThreadID() */
+
+ EXIT
+ ENDIF
+
+ hb_idleSleep( 0.01 ) /* Releases CPU cycles */
+ ENDDO
+//( "..........................", threadID() )
- //hb_mutexUnLock( ts_mutex )
RETURN nEvent
/*----------------------------------------------------------------------*/
@@ -180,16 +183,6 @@ FUNCTION SetAppWindow( oXbp )
//hb_outDebug( str( threadId() )+' 0' )
- IF empty( ts_mutex )
- ts_mutex := hb_mutexCreate()
- ENDIF
- IF empty( ts_events )
- ts_events := array( EVENT_BUFFER )
- ENDIF
- IF empty( oDummy )
- oDummy := XbpObject():new()
- ENDIF
-
oldAppWindow := oAppWindow
IF hb_isObject( oXbp )
@@ -286,11 +279,11 @@ FUNCTION SetEventFilter()
FUNCTION AddEventLoop( oEventLoop )
- hb_mutexLock( ts_mutex )
+ //hb_mutexLock( ts_mutex )
aadd( aEventLoop, { oEventLoop, threadID() } )
- hb_mutexUnLock( ts_mutex )
+ //hb_mutexUnLock( ts_mutex )
RETURN nil
diff --git a/harbour/contrib/hbxbp/xbprtf.prg b/harbour/contrib/hbxbp/xbprtf.prg
index b52c283abb..118e92b7f3 100644
--- a/harbour/contrib/hbxbp/xbprtf.prg
+++ b/harbour/contrib/hbxbp/xbprtf.prg
@@ -208,6 +208,8 @@ METHOD XbpRtf:exeBlock( nEvent, p1 )
::changed := .t. // .f. only at save
::change()
CASE nEvent == 7 /* Xbase++ Implements */
+ ::oTextCursor:configure( ::oWidget:textCursor() )
+ ::oCurCursor := ::oTextCursor
::selChange()
ENDCASE
@@ -230,7 +232,9 @@ METHOD XbpRtf:destroy()
METHOD XbpRtf:loadFile( cFile )
- HB_SYMBOL_UNUSED( cFile )
+ IF file( cFile )
+ ::oWidget:setText( memoread( cFile ) )
+ ENDIF
RETURN Self
@@ -238,7 +242,11 @@ METHOD XbpRtf:loadFile( cFile )
METHOD XbpRtf:saveFile( cFile )
- HB_SYMBOL_UNUSED( cFile )
+ IF ( '.txt' $ lower( cFile ) )
+ memowrit( cFile, ::oWidget:toPlainText() )
+ ELSE
+ memowrit( cFile, ::oWidget:toHTML() )
+ ENDIF
RETURN Self
@@ -277,8 +285,8 @@ METHOD XbpRtf:find( cSearchString, nStart, nEnd, nOptions )
IF hb_isChar( cSearchString )
::oTextDocument:pPtr := ::oWidget:document()
- ::oTextCursor:pPtr := ::oTextDocument:find_2( cSearchString )
- ::oCurCursor := ::oTextCursor
+ ::oTextCursor:pPtr := ::oTextDocument:find_2( cSearchString )
+ ::oCurCursor := ::oTextCursor
ENDIF
RETURN nPos
@@ -483,10 +491,10 @@ METHOD XbpRtf:selFontSize( ... ) // 0
LOCAL xRet := 0
LOCAL aP := hb_aParams()
- IF len( aP ) >= 1 .and. hb_isNumeric( aP[ 1 ] )
- ::oTextCharFormat:pPtr := ::oCurCursor:charFormat()
- IF ::oTextCharFormat:isValid()
- xRet := ::oTextCharFormat:fontPointSize()
+ ::oTextCharFormat:pPtr := ::oCurCursor:charFormat()
+ IF ::oTextCharFormat:isValid()
+ xRet := ::oTextCharFormat:fontPointSize()
+ IF len( aP ) >= 1 .and. hb_isNumeric( aP[ 1 ] )
::oTextCharFormat:setFontPointSize( aP[ 1 ] )
::oCurCursor:setCharFormat( QT_PTROF( ::oTextCharFormat ) )
ENDIF