Page 1 of 1

Como refrescar Intems de un de Tree en un Xbrose

PostPosted: Tue Mar 02, 2021 1:24 am
by checo176
Estimados amigos, espero se encuentren todos bien de salud. Necesito de su ayuda ya que me he quebrado la cabeza para actualizar los Ítems que han sido modificados en un Tree de un Xbrowse que uso para Indexar bases de datos. Sólo me funciona el refresco cuando cambio solo un Ítem del Tree, no así cuando uso la función de marcado para todos los Ítem del Tree, ya que solo me refresca el Ítem que seleccioné, pero no así sus Ítems debajo, siendo que la información de la columna a mostrar cambio, ya sea a .T. o .F., mostrando el Bitmaps, respectivo del Ítem.

A continuación les dejo algunas imágenes, para que puedan entender la solución que estoy buscando

Acá la ventana con el arbol inicial, antes de abrirse:

Image

Luego el Tree abierto:

Image

Cuando hago doble click sobre alguno de los Items del Tree, se marcan y refrescan sin problemas

Image

Luego aca tengo mi problema, al marcar la columna de la cabecera del Árbol, de modo de seleccionar en forma simultánea todos los Ítem de esa rama del Tree, solo puedo refrescar el Ítem de la cabecera de la rama, no así los items, ya que no los puedo refrescar, aunque la función si trabaja bien y cambia a .f. o .t., según sea el caso a toda la familia en la base de Datos. Intenté usar el Método obrw:otree:Refresh() y me da error, pero si uso [b]]obrw:Refresh()[/b, solo se refresca el Ítem que seleccioné del árbol. como pasa al seleccionar los items individual de la rama, como se mostró arriba.

Image

Acá les muestro parte de la línea de código que uso para hacer lo anterior:


Code: Select all  Expand view
function Indexa(oWndMain)

   local oWnd, oCol
   local oRs, oRsTot
   local oTree, oItem
   local oBold, bFont
   local nMethod := 1
   local oBrw, oChild
   local oDlg, oBIndex, FntArial
   local cAlias := cGetNewAlias( "FBD" )
   local cDbName  := ""
   local cNtxName := ""
   local oDbName, oNtxName
   local cItem  := "Bases de Datos"
   local aGradBarMet:= { { 1/2, nRGB( 224, 255, 255), nRGB( 135, 206, 250 )  } , ;
                         { 1/2, nRGB( 030, 144, 255), nRGB( 000, 255, 255 ) } }
   local aGradRowSel:= {{ 1, RGB(000,191, 255), RGB(224,255,255)}}
   local aGradBarSel:= {{ 1, RGB(030,144,255) , RGB(000,255, 255) } }


   FW_SetUnicode( .T. )
   FW_TouchFriendly( .T. )

   CheckBDCdx()
   FBD->( OrdSetFocus( "FBDIND2" ), DBGoTop() )
   if FilLock(5)
      Replace FBD->INDEXA_FBD with .f. ALL
   endif
   commit
   unlock

   go top  
   SetBalloon( .t. )
   SetGetColorFocus()

   lSmallScr   := ( sqrt( screenwidthmm() ^ 2 + screenheightmm() ^ 2 ) / 25.4 < 12 )

   
  DEFINE FONT oBold NAME "TAHOMA" SIZE 0,-12 BOLD
 
  DEFINE WINDOW oWnd MDICHILD OF oWndMain TITLE "Indexacion Base de Datos"  
 
   @ 0,0 XBROWSE oBrw  OF oWnd ;
         COLUMNS "Descripcion"   ;
         JUSTIFY AL_LEFT,AL_LEFT, AL_CENTER ;
         LINES CELL AUTOCOLS  FASTEDIT
         
      oTree := BuildTree()
      oBrw:SetTree( oTree, { "OPEN", "CLOSE", "DATABASE" } )
           
      ADD TO oBrw DATA oBrw:oTreeItem:Cargo[ 1 ]  TITLE "Base de Datos" SIZE 100
      ADD TO oBrw DATA oBrw:oTreeItem:Cargo[ 2 ]  TITLE "Indexar"       SIZE 60
     
   WITH OBJECT oBrw:Indexar
         :AddResource("ON")
         :AddResource("OFF")
         :bBmpData   := { || iif( oBrw:oTreeItem:Cargo[ 2 ]= .T., 1, 2) }
         :bStrData   := " "
   END        
   WITH OBJECT oBrw

      :nStretchCol      := STRETCHCOL_WIDEST
      :nColDividerStyle := LINESTYLE_RAISED
      :nRowDividerStyle := LINESTYLE_RAISED
      :nMarqueeStyle    := MARQSTYLE_HIGHLROWMS

      :LAllowColSwapping   := .f.
      :lHScroll             := .f.
     
      :lColDividerComplete := .f.
      :lAllowRowSizing     := .f.
      :lAllowColHiding     := .f.
      :lKineticBrw         := .f.
      :nRowHeight          := 24
      :nHeaderHeight       := 22
     
      :bLDblClick       := {|nRow,nCol| EditBrowse(nRow,nCol,oBrw, oDlg, oTree) }
      :bClrRowFocus     := { || { CLR_BLACK, aGradRowSel/*RGB(185,220,255)*/ } }
      :bClrStd          := {|| { nRGB( 0, 0, 0), nRGB(255,248,220) } } // colores para lineas normales
      :bClrSel          := {|| { nRGB( 0, 0, 0), aGradRowSel } } // para barra de linea selecc cuando el control no tiene el foco
      :bClrSelFocus     := { || { CLR_BLACK, aGradBarSel } } // para barra de linea selecc cuando el control tiene el foco          
 
      :aCols[ 1 ]:cHeader  := "Descripcion"
      :CreateFromCode()

   END

   oWnd:oClient   := oBrw
   
   BtnBar( oBrw)
   oWnd:bPostEnd  := { || ( cAlias )->( DBCLOSEAREA() ) }
 
   ACTIVATE WINDOW oWnd ON INIT ( oBrw:SetFocus() )  
   
return nil



Code: Select all  Expand view
static function BuildTree()

   local oTree, cFamiBD

   TREE oTree
      while ! Eof()
         if Empty( cFamiBD )
            _TreeItem( FBD->FAMIBD_FBD ):Cargo := { Space( 13 ), .F. }
            TREE
            cFamiBD = FBD->FAMIBD_FBD
         else
            if cFamiBD != FBD->FAMIBD_FBD
               ENDTREE
               cFamiBD = FBD->FAMIBD_FBD
               _TreeItem( FBD->FAMIBD_FBD ):Cargo := { Space( 13 ), .F. }
               TREE
            endif  
         endif  
         if FBD->FAMIBD_FBD == cFamiBD
            _TreeItem( FBD->DESCRI_FBD ):Cargo := { FBD->NOMBD_FBD, FBD->INDEXA_FBD }
         endif  
         SKIP
      enddo
      ENDTREE
   ENDTREE

   GO TOP

return oTree


Code: Select all  Expand view
STATIC FUNCTION EditBrowse(nRow, nCol, oBrw, oDlg, oTree)

     LOCAL xVar, nRecno := RecNo()
     LOCAL nColPos  := 0 ,;
           nColInit := 0 ,;
           nColGet  := 0 ,;
         lAppend  := .f.

     lFin := cBrowse(3, oBrw)
//     oBrw:oTree:Refresh()
     
return nil

//------------------------------------------------------------//

static Function cBrowse(nColGet, oBrw)

   LOCAL xVar, nRecno, lEscape := .f., nTotal := 0
   LOCAL cFamiBD:= oBrw:Descripcion:Value()
   LOCAL cNomBD := oBrw:oTreeItem:Cargo[ 1 ]


   if nColGet = 3
      Select FBD
      FBD->( OrdSetFocus( "FBDIND1" ), DBGoTop() )
      if !EMPTY(cNombD)
        IF  DbSeek ( cNomBD )
            msgstop(FBD->NomBD_FBD)
         IF FBD->Indexa_FBD = .f.
            if FilLock(5)
               FBD->Indexa_FBD = .t.
               oBrw:oTreeItem:Cargo := { oBrw:oTreeItem:Cargo[ 1 ] , .T. }
               oBrw:Refresh()
            endif
           
         ELSE
            if FilLock(5)
               FBD->Indexa_FBD = .f.
               oBrw:oTreeItem:Cargo := { oBrw:oTreeItem:Cargo[ 1 ] , .F. }
               oBrw:Refresh()
            endif
         ENDIF
        ENDIF
        commit
        unlock
      else
        SET FILTER TO FamiBD_FBD = cFamiBD
        FBD->(DbGoTop())
        Do  while !EOF()
        msgstop(FBD->NomBD_FBD)
//            IF  DbSeek ( cNomBD )
               IF FBD->Indexa_FBD = .f.
                  if FilLock(5)
                     FBD->Indexa_FBD = .t.
                     oBrw:oTreeItem:Cargo := { oBrw:oTreeItem:Cargo[ 1 ] , .T. }
//                     oBrw:Refresh()
                  endif
               ELSE
                  if FilLock(5)
                     FBD->Indexa_FBD = .f.
                     oBrw:oTreeItem:Cargo := { oBrw:oTreeItem:Cargo[ 1 ] , .F. }                    
                  endif
               ENDIF
//            ENDIF
            commit
            unlock
            DBskip()
        Enddo
        BuildTree()
        oBrw:Refresh()
        set filter to
      endif
   endif

   oBrw:SetFocus()

   oBrw:DrawSelect()  

RETURN lEscape



les agradezco de ante mano su apoyo y orientación.

Un gran abrazo

Como refrescar Items de un de Tree en un Xbrowse "SOLUCIONAD

PostPosted: Fri Apr 02, 2021 12:38 am
by checo176
Estimados amigos, quería compartir con todos Uds. la solución sugerida por nuestro gran amigo Rao, quien gracias a su ayuda me ha dado la solución a mi manejo de selección y refresco de Ítems de un Tree dentro de un xBrowse. Con la ayuda de Rao finalmente pude lograr una mejor solución a la que esperaba hacer y lograr una mejor perfomance de mi Sistema, en el módulo de Re Indexación de Indices, al permitirme ahora seleccionar el encabezado del Grupo de Ítems y marcar a todos los Ítems de ese grupo, como también cambiar el color de la cabecera del Grupo como los Ítems marcados, de ese modo poder visualizar que Grupo que tiene todos sus Ítems marcados, cuando tengo el Árbol cerrado.

xBrowse mostrando sus grupos cerrados
Image

xBrowse con el 1er grupo abierto y sin selección de sus Ítems
Image

xBrowse con la selección de un solo Ítem
Image

xBrowse con la selección de todo el Grupo, haciendo doble click en la casilla de la cabecera del Grupo o presionando el botón "IndexGroup", se aprecia el cambio de color también de la línea del Grupo contenedor.
Image

xBrowse con su árbol cerrado y mostrando los Grupos que tienen la selección de todos sus Ítems
Image

El código sugerido por Rao para poder realizar esto, es el siguiente:
Code: Select all  Expand view
#include "fivewin.ch"

REQUEST DBFCDX

//----------------------------------------------------------------------------//

function Main()

   local oDlg, oFont, oBrw, oCol, bIndexBlock

   USE FBASEDATOS NEW EXCLUSIVE VIA "DBFCDX"
   SET ORDER TO TAG FBDIND2
   GO TOP

   DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-14
   DEFINE DIALOG oDlg SIZE 550,600 PIXEL TRUEPIXEL FONT oFont

   @ 80,20 XBROWSE oBrw SIZE -20,-20 PIXEL OF oDlg ;
      ALIAS "FBASEDATOS" ;
      COLUMNS "FAMIBD_FBD", "DESCRI_FBD", "NOMBD_FBD","INDEXA_FBD" ;
      HEADERS "Group", "Description", "DBF", "INDEX" ;
      LINES NOBORDER

   WITH OBJECT oBrw
      :lHScroll := .f.
      WITH OBJECT :Index
         :SetCheck()
      END
      :SetTree( 2, { FWDArrow(), FWRArrow(), "c:\fwh\bitmaps\new2.bmp" } )
      :oTree:OpenAll()
      WITH OBJECT :Index
         bIndexBlock := :bEditValue
         :bEditValue := { |x| If( oBrw:oTreeItem:nLevel == 1, IsGroupIndexed( oBrw ), Eval( bIndexBlock, x ) ) }
         :bLDClickData := { || If( oBrw:oTreeItem:nLevel == 1, IndexGroup( oBrw ), IndexOne( oBrw ) ) }
      END
      :bKeyChar   := { |k| If( k == 32, ( If( oBrw:oTreeItem:nLevel == 1, IndexGroup( oBrw ), IndexOne( oBrw ) ), 0 ), nil ) }
      :bClrStd    := { || { CLR_BLACK, If( oBrw:oTreeItem:nLevel == 1, ;
                            If( oBrw:Index:Value, 0x60ff60, 0XB0ffB0 ), ;
                            If( oBrw:Index:Value, 0xaeffff, CLR_WHITE ) ) } }

      :nStretchCol   := 1
      //
      :CreateFromCode()
   END

   @ 20, 20 BUTTON "IndexOne"  SIZE 200,40 PIXEL OF oDlg ACTION ( oBrw:cAlias )->( IndexOne( oBrw ) )
   @ 20,240 BUTTON "IndexGroup" SIZE 200,40 PIXEL OF oDlg ACTION ( oBrw:cAlias )->( IndexGroup( oBrw ) )

   ACTIVATE DIALOG oDlg CENTERED
   RELEASE FONT oFont

return nil

//----------------------------------------------------------------------------//

static function IndexOne( oBrw )

   local cDbf  := FIELD->NOMBD_FBD

   if !Empty( cDbf )
      // Do your work here and set the value of the field INDEXA_FBD
      FIELD->INDEXA_FBD := !FIELD->INDEXA_FBD
      oBrw:Refresh()
   endif

return nil

//----------------------------------------------------------------------------//

static function IndexGroup( oBrw )

   local nSaveRec := RECNO()
   local cGroup   := UPPER( If( oBrw:oTreeItem:nLevel == 1, oBrw:oTreeItem:cPrompt, FIELD->FAMIBD_FBD ) )

   Go Top
   if ( DBSEEK( cGroup ) )
      do while UPPER( FIELD->FAMIBD_FBD ) == cGroup
         // do your work here and set INDEXA_FBD
         FIELD->INDEXA_FBD := !FIELD->INDEXA_FBD
         DBSKIP( 1 )
      enddo
      DBSKIP( 1 )
   endif

   DBGOTO( nSaveRec )
   oBrw:Refresh()

return nil

//----------------------------------------------------------------------------//

static function IsGroupIndexed( oBrw )

   local lRet  := .t.
   local nSaveRec := RECNO()
   local cGroup   := UPPER( If( oBrw:oTreeItem:nLevel == 1, oBrw:oTreeItem:cPrompt, FIELD->FAMIBD_FBD ) )

   Go Top
   if ( DBSEEK( cGroup ) )
      do while UPPER( FIELD->FAMIBD_FBD ) == cGroup
         // do your work here and set INDEXA_FBD
         if !FIELD->INDEXA_FBD
            lRet  := .f.
            EXIT
         endif
         DBSKIP( 1 )
      enddo
   endif

   DBGOTO( nSaveRec )

return lRet


Finalmente al ingresar este código en mi sistema pude lograr la siguiente imagen, del módulo de Re Indexación de Base de datos:

Image


Espero que esta idea innovadora pueda a alguien servirle de ayuda, la cual quise compartir con todos Uds. Finalmente no quisiera dejar de darle las gracias a Rao por su inmenso apoyo incondicional con todos nosotros, siempre esta dispuesto a ayudarnos y guiarnos cuando lo necesitamos.

Un abrazo cariñoso y feliz fin de Semana Santa.