FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour xbrowse, dbf and codeblock
Posts: 104
Joined: Tue Feb 09, 2021 04:20 PM
xbrowse, dbf and codeblock
Posted: Thu Jan 23, 2025 01:49 AM


Using DBF.
When define a codeblock for skip, xbrowse update fail.
   @ 70, 10 XBROWSE xControl ;
      DATASOURCE Alias() ;
      SIZE nDlgWidth - 24, nDlgHeight - 100 PIXEL ;
      OF xDlg ;
      ON DBLCLICK ( (nRow), (nCol), (nFlags), FWBrowseENTER( xDlg, xControl ) )

   WITH OBJECT xControl
      :SetRdd()
      :bGoTop    := { || ( nSelect )->( FazBrowseTop() ) }
      :bGoBottom := { || ( nSelect )->( FazBrowseBottom() ) }
      :bSkip     := { | n | ( nSelect )->( FazBrowseSkip( n ) ) }
      //:bBof      := { || Bof() }
      //:bEof      := { || Eof() }
      //:bBookMark := { | n | iif( n == nil, RecNo(), DbGoto( n ) ) }
   ENDWITH
   ...
   STATIC FUNCTION FazBrowseSkip( nSkip )

   LOCAL nSkipped := 0

   IF Empty( nSkip  )
      RETURN 0
   ENDIF
   IF nSkip > 0
      DO WHILE nSkipped < nSkip
         SKIP
         IF Eof()
            SKIP -1
            EXIT
         ENDIF
         nSkipped++
      ENDDO
   ELSE
      DO WHILE nSkipped > nSkip
         SKIP -1
         IF Bof()
            SKIP
            EXIT
         ENDIF
         nSkipped--
      ENDDO
   ENDIF

   RETURN nSkipped

José M. C. Quintas Brazil

gtwvg, fivewin 25.12, hwgui, mingw 15.2 (32 bits)

Posts: 10733
Joined: Sun Nov 19, 2006 05:22 AM
Re: xbrowse, dbf and codeblock
Posted: Thu Jan 23, 2025 05:32 AM
To create xBrowse, this is enough
   @ 70, 10 XBROWSE xControl ;
      DATASOURCE Alias() ;
      SIZE nDlgWidth - 24, nDlgHeight - 100 PIXEL ;
      OF xDlg ;
      ON DBLCLICK ( (nRow), (nCol), (nFlags), FWBrowseENTER( xDlg, xControl ) )
XBrowse automatically generates all navigation codeblocks internally and correctly for all known datasources like arrays, hashes, dbf, ado-recordsets and all other known classes.

Please do not write our own navigation codeblocks.

Also, another small note:
      SIZE nDlgWidth - 24, nDlgHeight - 100 PIXEL ;
You can simply write
 SIZE -24,-100 PIXEL
This works even when the dialog is resized

Finally, end with
xControl:CreateFromCode()
Regards



G. N. Rao.

Hyderabad, India
Posts: 104
Joined: Tue Feb 09, 2021 04:20 PM
Re: xbrowse, dbf and codeblock
Posted: Thu Jan 23, 2025 12:28 PM
nageswaragunupudi wrote: XBrowse automatically generates all navigation codeblocks internally and correctly for all known datasources like arrays, hashes, dbf, ado-recordsets and all other known classes.
Please do not write our own navigation codeblocks.
Yes, for a standard navigation.
What to do when I need a not default navigation for dbf?
I think codeblocks are available on xbrowse to do things like this, in same way as harbour tbrowse.
Am I wrong ?

José M. C. Quintas Brazil

gtwvg, fivewin 25.12, hwgui, mingw 15.2 (32 bits)

Posts: 10733
Joined: Sun Nov 19, 2006 05:22 AM
Re: xbrowse, dbf and codeblock
Posted: Thu Jan 23, 2025 01:25 PM
These are the default codeblocks for a normal DBF.
::bGoTop    := {|| ( ::cAlias )->( DbGoTop() ) }
::bGoBottom := {|| ( ::cAlias )->( DbGoBottom() ) }
::bSkip     := {| n | ( ::cAlias )->( DbSkipper( IfNil( n, 1 ) ) ) }
::bBof      := {|| ( ::cAlias )->( Bof() ) }
::bEof      := {|| ( ::cAlias )->( Eof() ) }
::bBookMark := {| n | iif( n == nil
                          ( ::cAlias )->( RecNo() )
                          ( ::cAlias )->( DbGoto( n );
                         ) ) }

::bKeyNo    := {| n | iif( n == nil
                         ( ::cAlias )->( OrdKeyNo() )
                         ( ::cAlias )->( OrdKeyGoto( n );
                         ) ) }
::bKeyCount := {|| ( ::cAlias )->( If( eof() .and. bof(), 0, OrdKeyCount() ) ) }
Note: There are minor variations for SQLRDD, ADS, Large DBFCDX

If we need a different navigational behavior, we need to change these codeblocks consistent with each other.
Regards



G. N. Rao.

Hyderabad, India
Posts: 104
Joined: Tue Feb 09, 2021 04:20 PM
Re: xbrowse, dbf and codeblock
Posted: Thu Jan 23, 2025 02:17 PM
On a first momment anything is wrong.
   WITH OBJECT xControl
      :SetRdd()
      :bGoTop    := {|| ( :cAlias )->( DbGoTop() ) }
      :bGoBottom := {|| ( :cAlias )->( DbGoBottom() ) }
      :bSkip     := {| n | ( :cAlias )->( DbSkipper( IfNil( n, 1 ) ) ) }
      :bBof      := {|| ( :cAlias )->( Bof() ) }
      :bEof      := {|| ( :cAlias )->( Eof() ) }
      :bBookMark := {| n | iif( n == nil,;
         ( :cAlias )->( RecNo() ),;
         ( :cAlias )->( DbGoto( n );
         ) ) }

      //:bGoTop    := { || ( nSelect )->( FazBrowseTop() ) }
      //:bGoBottom := { || ( nSelect )->( FazBrowseBottom() ) }
      //:bSkip     := { | n | ( nSelect )->( FazBrowseSkip( n ) ) }
      //:bBof      := { || Bof() }
      //:bEof      := { || Eof() }
      //:bBookMark := { | n | iif( n == nil, RecNo(), DbGoto( n ) ) }
   ENDWITH
With same codeblocks, it is expected same result.

Will test again, may be harbour behaviour about WITH OBJECT construction/execution
I discover about this some months ago, after began to use fivewin.

José M. C. Quintas Brazil

gtwvg, fivewin 25.12, hwgui, mingw 15.2 (32 bits)

Posts: 10733
Joined: Sun Nov 19, 2006 05:22 AM
Re: xbrowse, dbf and codeblock
Posted: Thu Jan 23, 2025 02:25 PM
Note:
The codeblock bSkip uses the function:
nSkipped := DbSkipper( nRecs ) // xHarbour
nSkipped := __DbSkipper( nRecs ) // Harbour

The functionality is similar to this function
function MyDbfSkipper( nRecs )

   local nKeyFrom := OrdKeyNo()
   
   DBSKIP( nRecs )
   if Eof()
      DbGoBottom()
   elseif Bof(
      DbGoTop()
   endif
   
return OrdKeyNo() - nKeyFrom
Regards



G. N. Rao.

Hyderabad, India
Posts: 104
Joined: Tue Feb 09, 2021 04:20 PM
Re: xbrowse, dbf and codeblock
Posted: Thu Jan 23, 2025 02:42 PM
Yes
It is it !
Harbour behaviour using WITH OBJECT !
Check this code:
#include "hbclass.ch"

PROCEDURE Main()

   LOCAL a, b, x

   SetMode(30,100)
   CLS

   a := AnyClass():New()
   b := AnyClass():New()

   WITH OBJECT a
      :Value := 10
      x := { || :Value } // created here, seems a:Value
   ENDWITH
   WITH OBJECT b
      ? a:Value
      ? b:Value
      ? eval( x ) // executed here, results b:Value
   ENDWITH
   Inkey(0)

   RETURN

CREATE CLASS AnyClass

   VAR Value INIT 0

   ENDCLASS
seems that result will be 10, 10, 0
but result is 10, 0, 0

x is created inside WITH a, but do not have defined object, it is not a:value
when used inside WITH b, x return b:value not a:value
The same occurs when define codeblocks for xbrowse.

Solution is to use full name.
WITH OBJECT need caution when creating codeblock.
I forgot about this.

This works ok, with full name.
   WITH OBJECT xControl
      xControl:SetRdd()
      xControl:bGoTop    := {|| ( xControl:cAlias )->( DbGoTop() ) }
      xControl:bGoBottom := {|| ( xControl:cAlias )->( DbGoBottom() ) }
      xControl:bSkip     := {| n | ( xControl:cAlias )->( DbSkipper( IfNil( n, 1 ) ) ) }
      xControl:bBof      := {|| ( xControl:cAlias )->( Bof() ) }
      xControl:bEof      := {|| ( xControl:cAlias )->( Eof() ) }
      xControl:bBookMark := {| n | iif( n == nil,;
         ( xControl:cAlias )->( RecNo() ),;
         ( xControl:cAlias )->( DbGoto( n );
         ) ) }

José M. C. Quintas Brazil

gtwvg, fivewin 25.12, hwgui, mingw 15.2 (32 bits)

Posts: 104
Joined: Tue Feb 09, 2021 04:20 PM
Re: xbrowse, dbf and codeblock
Posted: Thu Jan 23, 2025 03:32 PM
Extra comment:

May be this expains why a external database works, and internal may not.
As example using mysql.

Internal
WITH OBJECT xbrowse
   :bGoTop := { || :Rs:MoveFirst() } // may use wrong object, anything:Rs:MoveFirst()
ENDWITH
External
WITH OBJECT xBrowse
   :bGoTop := RS:MoveNext() // use right object, RS
ENDWITH
I had same problem using ADO, but I forgot about this.
Not easy to remember issues on not common situations.
May be interesting to include about this on documentation of xbrowse, and on source code too.
   // Code-blocks for navitation
   // Caution: Use allways full name for codeblocks, WITH OBJECT may fail

   DATA bGoTop,;     // codeblock for going to first row
        bGoBottom,;  // codeblock for going to last row
        bSkip,;      // codeblock for skiping rows, it receives the number of rows

José M. C. Quintas Brazil

gtwvg, fivewin 25.12, hwgui, mingw 15.2 (32 bits)

Posts: 104
Joined: Tue Feb 09, 2021 04:20 PM
Re: xbrowse, dbf and codeblock
Posted: Fri Jan 24, 2025 12:44 PM
Another thing is a visible bug on xbrowse.
      xControl:bSkip     := {| n | ( xControl:cAlias )->( DbSkipper( IfNil( n, 1 ) ) ) }
Xbrowse requires to skip NIL records.
When xbrowse requires NIL records, it is needed to change to 1.
METHOD Skip( n ) CLASS TXBrowse

   local nStart
   local nSkipped := 0

   if !::lClosed
      TRY
         if Empty( ::aFilter )
            nSkipped := Eval( ::bSkip, n, Self )
         else
            nStart      := ::nFltRow
            ::GoFltRow( ::nFltRow + IfNil( n, 1 ) )
            nSkipped    := ::nFltRow - nStart
         endif
      CATCH
         ::nLen      := 0
         ::lClosed   := .t.
      END
   endif

return nSkipped
Looking to method skip, one more test about Nil

Could be changed to
hb_Default( @n, 1 )
If needed for xharbour:
FUNCTION hb_Default( a, b )
   IF valType( a ) != ValType( b )
       a := b
     ENDIF
     RETURN Nil
New source
METHOD Skip( n ) CLASS TXBrowse

   local nStart
   local nSkipped := 0

   if !::lClosed
      TRY
         hb_Default( @n, 1 )
         if Empty( ::aFilter )
            nSkipped := Eval( ::bSkip, n, Self )
         else
            nStart      := ::nFltRow
            ::GoFltRow( ::nFltRow + n )
            nSkipped    := ::nFltRow - nStart
         endif
      CATCH
         ::nLen      := 0
         ::lClosed   := .t.
      END
   endif

return nSkipped
Not sure if it is needed the TRY/CATCH.
This is the reason why we see xbrowse fail, but do not know that anything is wrong on bSkip codeblock. (as example the Nil)

José M. C. Quintas Brazil

gtwvg, fivewin 25.12, hwgui, mingw 15.2 (32 bits)

Posts: 10733
Joined: Sun Nov 19, 2006 05:22 AM
Re: xbrowse, dbf and codeblock
Posted: Sat Jan 25, 2025 02:13 AM
Thanks for your concern and efforts.

1)
seems that result will be 10, 10, 0
but result is 10, 0, 0
Looking at the code, any programmer should expect the result to be 10,0,0 and in fact the result is 10,0,0.

2)
WITH OBJECT xbrowse
:bGoTop := { || :Rs:MoveFirst() } // may use wrong object, anything:Rs:MoveFirst()
ENDWITH
Please check again. XBrowse program does not have any such defective code.

In contrast,
::bGoTop := { || ::oRs:MoveFirst() }
This works perfectly.

Not only XBrowse, there is no module in FWH using such defective code.

3)
May be interesting to include about this on documentation of xbrowse, and on source code too.
// Code-blocks for navitation
// Caution: Use allways full name for codeblocks, WITH OBJECT may fail[/quote]

This is nothing specific to xBrowse or Fivewin. This is what every (x)Harbour programmer is expected to know.

4)
This is the reason why we see xbrowse fail, but do not know that anything is wrong on bSkip codeblock. (as example the Nil)
XBrowse never fails on Skip().
We do not expect any programmer to use non numeric values.

5)
We appreciate that a function like hb_default is safer than IfNil.

6)
we see xbrowse fail
To the best of our knowledge and experience, xbrowse never fails on such issues.
If you find that XBrowse is failing at times, you may like to help FWH and our community by providing a sample program to demonstrate such a failure.

Thanks again for your interest and time to help improve xbrowse.
Regards



G. N. Rao.

Hyderabad, India
Posts: 104
Joined: Tue Feb 09, 2021 04:20 PM
Re: xbrowse, dbf and codeblock
Posted: Tue Jan 28, 2025 10:44 PM
nageswaragunupudi wrote: Please check again. XBrowse program does not have any such defective code.
That was only a sample about harbour behaviour, comparing internal and external use.
WITH OBJECT xBrowse
   :bGoTop := { || :oRs:MoveFirst() } // internal may fail, not defined main object on codeblock
   :bGoTop := { || xBrowse:oRs:MoveFirst() } // internal ok, main object on codeblock is defined
   :bGoTop := { || oRs:MoveFirst() } // external ok, main object on codeblock is defined
ENDWITH

José M. C. Quintas Brazil

gtwvg, fivewin 25.12, hwgui, mingw 15.2 (32 bits)

Continue the discussion