i have add methode Flat in abstractbutton.prg

Moderator: Rathinagiri

JosK
Posts: 46
Joined: Tue Nov 08, 2011 11:38 pm

i have add methode Flat in abstractbutton.prg

Post by JosK » Sun Dec 18, 2011 3:25 pm

Today i have get the source from svn via tourtaise and compared it with my old source (JK\*.prg is old)
differents:
<source>

jk: Add Flat
***** abstractbutton.prg
METHOD Checked SETGET
METHOD PictAlignment SETGET
***** JK\abstractbutton.PRG
METHOD Checked SETGET
METHOD Flat SETGET
METHOD PictAlignment SETGET
*****

***** abstractbutton.prg
/*..............................................................................
PictAlignment
***** JK\abstractbutton.PRG
/*..............................................................................
Flat
..............................................................................*/
METHOD Flat( lValue ) CLASS ABSTRACTBUTTON

IF PCount() == 0
::lFlat := ::oQTObject:isFlat()
RETURN ::lFlat
ELSEIF PCOUNT() == 1 .AND. hb_IsLogical( lValue )
::oQTObject:setFlat( lValue )
::lFlat := lValue
ENDIF

RETURN NIL

jk: i do nothing with browse.prg but i think you must add some DATA (you don't find nNew, nDiff in parents but it is used in browse.prg (line 342=nNew)

**** JK\browse.PRG
DATA nCurrent INIT NIL
DATA nNew INIT NIL
DATA nDiff INIT NIL
DATA nMasterRecNo INIT NIL
DATA QAbstractItemModel INIT NIL
DATA nCellRowIndex INIT 0
DATA nCellColIndex INIT 0
DATA aStruct INIT NIL
***

jk: i have tested the new source (make the lib)
MyProgram give's a new error:
Error Base/42 Scope violation (protected): MAINWINDW:AKEYBOARDEVENTS
Called from MAINWINDOW:AKEYBOARDEVENTS(0)

I get this error because virtualgrid.prg is changed
In previous version aKeyBoardEvents was not protected and now it is.
(previous = 23/11/2011 en new = 18/12/2011)
so i have changed line 50 in virtualwindow and now the error is away (not protected)

ow .. another error:
error hbqt/100 Message not found:addtoobar: qwidget:addtoolbar
called from qwidget:addToolbar(0)
called from toolbar:new(91)
called from maaktoolbar(234) -> Myprg.prg
I have changed toolbar.prg in the past so that i also can add aToolbar to aTabpage.

My change to toolbar.prg is delete line 90 -92
//IF hb_IsObject( ::oParent )
// ::oParent:QtObject:addToolBar( ::oQTObject )
//ENDIF
After this change the error is away
</Source>
<MyPrg>
i use now virtualgrid.prg instead of jkgrid.prg
/* met frame
*/

#include "hmg.ch"
#include "hbqtgui.ch"
#include "hbgtinfo.ch"
#include "std.ch"

SET DATE TO ANSI
SET EPOCH TO 1950 //KAN OOK CENTURY DOEN MAAR DAN 4 POSITIES..
SET CENTURY OFF
SET WRAP ON && ref 'menu to ...'
SET TALK OFF &&
SET BELL OFF &&
SET DELETED ON &&
SET SAFETY OFF &&
SET HEADING OFF &&
SET DELIMITERS OFF &&
SET SCOREBOARD OFF && geen Num, Ins, enz op lijn 0.
SET INTENSITY ON
SET DELIMITERS OFF
SET EXACT OFF
SET CURSOR OFF //KENT HMG NIET daar std.ch
SET DELETED ON && alleen btw bestand word direct gepackt ivm reccount()
SET EXCLUSIVE ON
setcancel(.f.)
/*
SET AUTOOPEN OFF maakt de index ook open indien aangemaakt
SET AUTOORDER TO 1 driver dbfcdx ondersteunt dit
SET AUTOSHARE
//wel/niet index openen/aanmaken; werkt bij dbfcdx
//ordBagExt()
//OrdSetFocus()
//iNDEX ON CUSTID TAG ID TO CUSTOMER ->TAG WERKT NIET BIJ AUTOORDER=CUSTID
//Ordkey(2) returnt Uppler(lastName+FirstName)
*/


FUNCTION Main()

//Public oTP1,oTP2
//Public oTLB //oTabpageLayoutBox -> local in oTP1

HbQt_ErrorSys()
Request DBFCDX , DBFFPT
Rddsetdefault( "DBFCDX" )


wMain :=MaakMain("wMain")
oCW :=Widget():New("oCW",wMain)
oCW :CentralWidgetOF(wMain)
oLB :=LayoutBox():New("oLB",oCW,LAYOUT_TOPTOBOTTOM)
with object oTab:=Tab():New("oTab")
oTP1:=MaakTP1("oTP1",oTab)
oTP2:=MaakTP2("oTP2",oTab)

end
oLB:add(oTab)
oLB:SetLayout()
ON KEY F10 OF WMAIN ACTION {|| MSGSTOP("f10 binnen wmain")}
ON KEY F8 OF WMAIN ACTION {|| MSGSTOP( str( oTP1.oTLB:direction()))}
//0=l->r, 1=r-l, 2=t-b, 3=b-t, 4=form, 5=grid
ON KEY F9 OF WMAIN ACTION {|| if( (x:=oTP1.oTLB:Direction()) ==3, oTP1.oTLB:Directon(0), oTP1.oTLB:Direction(x+1) )}
//F9 heeft geen invloed op child olF onder oTLB
ON KEY F7 OF WMAIN ACTION {|| x:=oTP2.oBrowse:ColumnWidths(),x[2]:=800,oTP2.oBrowse:ColumnWidths(x),oTP2.oBrowse:Refresh() }
ON KEY F6 OF WMAIN ACTION {|| x:=oTP2.oBrowse:ColumnHeaders(),x[2]:="TEST",oTP2.oBrowse:ColumnHeaders(x),oTP2.oBrowse:Refresh() }
ON KEY F5 OF WMAIN ACTION {|| x:=oTP1.oBrowse:ColumnJustify(),x[4]:=BRW_RIGHT,oTP1.oBrowse:ColumnJustify(x),oTP1.oBrowse:Refresh() }
//o:ColumnJustify := { BRW_LEFT , BRW_RIGHT , BRW_CENTER , BRW_LEFT , BRW_RIGHT , BRW_CENTER , BRW_LEFT , BRW_RIGHT , BRW_CENTER , BRW_LEFT , BRW_RIGHT }
wMain:Activate()
Return NIL
***************************
STATIC FUNCTION MaakMain(c)
***************************
static o
if o==nil
o:= MAINWINDOW():New(c)
o:Title := "Maak Main Demo"
endif
return o
***************************************
STATIC FUNCTION MaakTab(c,oParent,nRow)
***************************************
local o
o:=Tab():New(c,oParent)
return o
***************************
FUNCTION MaakTP1(c,oParent)
***************************
local oTLB,oBrowse,oTB
static o
if o=Nil
//indien meerdere items op horizontaal is apart frame
// auto van 1/2 lines gaat niet lukken naar groot/klein scherm
o:=TabPage():New(c,oParent)
o:caption:="&Tabpage1"
oTLB:=LayoutBox():New("oTLB",o)
oTLB:direction(2) //t-b

oTB:=maakToolBar("oTB",o)

oBrowse:=MaakBrowse("oBrowse",o)

oLF:=Layoutform():New("oLF",oTLB)
oB1:=Button():New()
oB1:caption("Button1")
oT1:=TextBox():New()
oB2:=Button():New()
oB3:=MaakBtn("oB3")
oLF:add(oB1)
oLF:add(oT1)
oLF:add(oB2)
oLF:add(oB3)
oTLB:addlayout(oLF)
oTLB:add(oBrowse)
oTLB:add(oTB)
oTLB:stretch(1,20)
oTLB:stretch(2,80)
oTLB:setlayout()
endif
return o

************
STATIC FUNCTION MaakBtn(c,oParent)
************
static o
o:=Button():New(c,oParent)
o:MaxWidth :=300
o:Caption := "Current Language"
o:OnClick := { || Bt1_OnClick() }
RETURN o
************
STATIC FUNCTION Bt1_OnClick()
************
MsgInfo( "Current Language is " + hb_ValToExp( HMGAPP():Language() ), "Language" )
RETURN NIL

***************************
FUNCTION MaakTP2(c,oParent)
local oTLB,oBrowse
static o
//go top

if o=Nil
o:=TabPage():New(c,oParent)
o:caption:="&RekSchema"
oTLB:=LayoutBox():New("oTLB",o,LAYOUT_TOPTOBOTTOM)
oBrowse:=MaakBrowse("oBrowse",o)
oTLB:add(oBrowse)
oTLB:setlayout()
endif
return o
**********************
function MaakBrowse(c,oParent)
**********************
static o
static bColor := { || IF ( ordkeyno()/2 == INT(ordkeyno()/2) , { 222,222,222 } , { 255,255,255 } ) }
static fColor := { || IF ( ordkeyno()/2 == INT(ordkeyno()/2) , { 255,0,0 } , { 0,0,255 } ) }
use c:\hmg.4\svn\samples\t\demo alias demo
//o:=jkGrid():New(c,oParent)
o:=VirtualGrid():New(c,oParent)
/*
o:Row := 10
o:Col := 10
o:Width := 690
o:Height := 615
*/
o:WorkArea := 'demo'
//o:OnChange :={||MsgInfo( "Andere cell/regel geselecteerd!" )}
//o:ONDBLClick :={||MsgInfo( "We gaan cell editten!" )}


* 'First','Last','Street','City','State','Zip','Hire Date','Married' ,'Age', Salary' , 'Notes'}
* '1,2,3,4,5,6Zip,7H,8'Married',9Age',10Salary' , 11Notes'}
//kreeg een error er daarom columnHeader toegevoegd
o:ColumnHeaders := { 'First' , 'Last' , 'Street' , 'City' , 'State' , 'Zip' , 'HireDate' , 'Married' , 'Age' , 'Salary' , 'Notes' }
o:ColumnFields := { 'First' , 'Last' , 'Street' , 'City' , 'State' , 'Zip' , 'HireDate' , 'Married' , 'Age' , 'Salary' , 'Notes' }
o:ColumnWidths := { 150 , 150 , 150 , 150 , 150 , 150 , 150 , 150 , 150 , 150 , 150 }
// ColumnJustify {GRID_JTFY_LEFT,GRID_JTFY_RIGHT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_RIGHT,GRID_JTFY_LEFT}
// brw_left etc is idem als grid_jtfy_left
o:ColumnJustify := { BRW_LEFT , BRW_RIGHT , BRW_CENTER , BRW_LEFT , BRW_RIGHT , BRW_CENTER , BRW_LEFT , BRW_RIGHT , BRW_CENTER , BRW_LEFT , BRW_RIGHT }
o:DynamicBackColor := { bColor , bColor , bColor , bColor , bColor , bColor , bColor , bColor , bColor , bColor , bColor }
o:DynamicForeColor := { fColor , fColor , fColor , fColor , fColor , fColor , fColor , fColor , fColor , fColor , fColor }
o:DynamicDisplay := { { || UPPER(First) } , NIL , NIL , NIL , NIL , NIL , NIL , { || IF(married,'Married','Not Married' ) } , NIL , NIL , NIL }
o:OnHeadClick := { { || MsgInfo( 'Click 1' ) } , , { || MsgInfo( 'Click 3' ) } , { || MsgInfo( 'Click 4' ) } , { || MsgInfo( 'Click 5' ) } , { || MsgInfo( 'Click 6' ) } , { || MsgInfo( 'Click 7' ) } , { || MsgInfo( '8' ) } , ,}
o:HeaderImages := { 'new.png' , 'open.png' , 'paste.png' , 'save.png' , 'new.png' , 'open.png' , 'paste.png' , 'save.png' , 'new.png' , 'open.png' , 'paste.png' }
o:lVScrollBar := .f.
//1.1= textbox,checkbox
//1.2=nummeric,date,character
//1.3=imputmask
//1.4=format alleen bij nummeric
// justify via andere array
//1="checkbox", caption=2of3,onchange=2of3 hij checkt op wel/niet block!?
//1="datepicker",2="UPDOWN" else updown=f
//1="spinner",2=RangeMin, 3=RangeMax
//1="combobox",2=items=array

o:ColumnControls :={{'TEXTBOX','CHARACTER'},;
{'TEXTBOX','CHARACTER'},;
{'TEXTBOX','CHARACTER','@K'},;
{"SPINNER",1,1000},;
{"COMBOBOX",{"January","February","March","April","May","June","July","August","September","October","November","December"}},;
{'TEXTBOX','CHARACTER',"@K"},;
{"DATEPICKER","UpDown"},;
{'CHECKBOX','Yes','No'},;
{'TEXTBOX','NUMERIC','99'},;
{'TEXTBOX','NUMERIC','999.99'},;
{'TEXTBOX','CHARACTER'};
}
o:MultiSelect := .F. //bij true = geen edit , alleen display
o:AllowEdit := .T. //alleen indien columnControls is ingevuld
o:Lines := .F.
o:VScrollBar := .F.
o:ColumnWhen := { { || UPPER(LEFT(first,1) ) == 'A' } ,{||.f.};
, , , , , , , , , , , }
//msgstop wordt bij opbouwen scherm bij iedere regel getoond
//bij when en browse problem want werd bij iedere regel werd when uitgevoerd; ook bij opbouwen scherm
//er moet een block in staan want anders error na intoetsen key
//o:ColumnWhen := { { || UPPER(LEFT(first,1) ) == 'A' } , , , , , , , , , , }
//o:ColumnValid := { { || !EMPTY(memvar.demo.first) } , , , , , , , , , { || demo->salary > 100 } , }
o:ColumnValid := { { || !EMPTY(demo.first) } , , , , , , , , , { || demo->salary > 100 } , }
o:ValidMessages := { "First name can't be EMPTY" , , , , , , , , , "Salary mus be greater than 100" , }
x1:=len(o:ColumnControls())
x2:=len(o:ColumnValid())
x3:=len(o:ValidMessages())
if x1#x2.or.x1#x3
msgstop("x1="+str(x1) + " x2="+str(x2)+ " x3="+str(x3))
endif
return o
********************************
function maakToolBar(c,oParent)
********************************
static o
if o==NIL
o:=Toolbar():New(c,oParent)
* via methode atObject:addToolBar en oParent=Tab heeft deze niet.
* opgelost via aanpassen toolbar.prg in methode new del addtoolbar
o:MOVEABLE := .F.
//oTB:TBARPLACE:= Qt_RightToolBarArea
with Object TOOLBUTTON():New("TB1",o)
:Caption := "Save"
:Picture := "save.png"
:OnClick := {|| MsgInfo( "Save!" )}
:ToolTip := "ToolTip"
end
with Object TOOLBUTTON():New("TB2",o)
:Caption := "AutoUser"
:Picture := "save.png"
:OnClick := {|| AutoUser()}
:ToolTip := "ToolTip"
end
with Object TOOLBUTTON():New("TB3",o)
:Caption := "UserNamer"
:Picture := "save.png"
:OnClick := {|| msgstop(NetName() + " # " + hb_UserName()) }

:ToolTip := "ToolTip"
end
end
return o
/*

aDgbSrt:={"BeginBalans","Kas","Bank/Giro","Memoriaal","Debiteuren",
"Crediteuren,"Leningen","Afschrijvingen","Periode 13"}
aRekSch:={"Kas",BV"
aRekBV :=aAdd{{"Kas","Bank",
aRekVOF:={{"Kas","Bank",

define HEADER=
aDGB:={ {"dgbnaam","C",30,0}

aAdd(aDGB,{
*/

function AutoUser()
local i,x
begin sequence
select 2
dbcreate( "testauto", { {"USERID", "+", 4, 0 }, { "NAME", "C", 20, 0 } } )
use testauto alias testauto
for i:=1 to 10
dbappend()
if (i % 3) == 0
x:=testauto->UserId
else
replace name with "test"
endif
//hij zet in veld userid het nummer 1 t/m ..
// via dbu kan ik deze niet benaderen wel via hmgide > idedbu
next
end sequence
select 1
//dbgotop()
//browse()
msgInfo(x)
return .t.



/*

o:ColumnHeaders := { 'First' , 'Last' , 'Street' , 'City' , 'State' , 'Zip' , 'HireDate' , 'Married' , 'Age' , 'Salary' , 'Notes' }
o:ColumnFields := { 'First' , 'Last' , 'Street' , 'City' , 'State' , 'Zip' , 'HireDate' , 'Married' , 'Age' , 'Salary' , 'Notes' }
o:ColumnWidths := { 150 , 150 , 150 , 150 , 150 , 150 , 150 , 150 , 150 , 150 , 150 }
// ColumnJustify {GRID_JTFY_LEFT,GRID_JTFY_RIGHT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_LEFT,GRID_JTFY_RIGHT,GRID_JTFY_LEFT}
// brw_left etc is idem als grid_jtfy_left
o:ColumnJustify := { BRW_LEFT , BRW_RIGHT , BRW_CENTER , BRW_LEFT , BRW_RIGHT , BRW_CENTER , BRW_LEFT , BRW_RIGHT , BRW_CENTER , BRW_LEFT , BRW_RIGHT }
o:DynamicBackColor := { bColor , bColor , bColor , bColor , bColor , bColor , bColor , bColor , bColor , bColor , bColor }
o:DynamicForeColor := { fColor , fColor , fColor , fColor , fColor , fColor , fColor , fColor , fColor , fColor , fColor }
o:DynamicDisplay := { { || UPPER(First) } , NIL , NIL , NIL , NIL , NIL , NIL , { || IF(married,'Married','Not Married' ) } , NIL , NIL , NIL }
o:OnHeadClick := { { || MsgInfo( 'Click 1' ) } , , { || MsgInfo( 'Click 3' ) } , { || MsgInfo( 'Click 4' ) } , { || MsgInfo( 'Click 5' ) } , { || MsgInfo( 'Click 6' ) } , { || MsgInfo( 'Click 7' ) } , { || MsgInfo( '8' ) } , ,}
o:HeaderImages := { 'new.png' , 'open.png' , 'paste.png' , 'save.png' , 'new.png' , 'open.png' , 'paste.png' , 'save.png' , 'new.png' , 'open.png' , 'paste.png' }
o:lVScrollBar := .f.
//1.1= textbox,checkbox
//1.2=nummeric,date,character
//1.3=imputmask
//1.4=format alleen bij nummeric
// justify via andere array
//1="checkbox", caption=2of3,onchange=2of3 hij checkt op wel/niet block!?
//1="datepicker",2="UPDOWN" else updown=f
//1="spinner",2=RangeMin, 3=RangeMax
//1="combobox",2=items=array

o:ColumnControls :={{'TEXTBOX','CHARACTER'},;
{'TEXTBOX','CHARACTER'},;
{'TEXTBOX','CHARACTER','@K'},;
{"SPINNER",1,1000},;
{"COMBOBOX",{"January","February","March","April","May","June","July","August","September","October","November","December"}},;
{'TEXTBOX','CHARACTER',"@K"},;
{"DATEPICKER","UpDown"},;
{'CHECKBOX','Yes','No'},;
{'TEXTBOX','NUMERIC','99'},;
{'TEXTBOX','NUMERIC','999.99'},;
{'TEXTBOX','CHARACTER'};
}
o:MultiSelect := .F. //bij true = geen edit , alleen display
o:AllowEdit := .T. //alleen indien columnControls is ingevuld
o:Lines := .F.
o:VScrollBar := .F.
o:ColumnWhen := { { || UPPER(LEFT(first,1) ) == 'A' } ,{||.f.};

*/
</MyPrg>

JosK
Posts: 46
Joined: Tue Nov 08, 2011 11:38 pm

Post by JosK » Sun Dec 18, 2011 3:27 pm

if you run my program you don't see a underline (&TabPage1 / &RekSchema)
after you do Alt-T you see the underline.

JosK
Posts: 46
Joined: Tue Nov 08, 2011 11:38 pm

Post by JosK » Sun Dec 18, 2011 3:38 pm

after runnen and pushing PGUP, LEFT, UP in the virtualgrid i get the error:

Error Base/1004 No exported method:Eval
Called from (b)Eval(0)
Called from VirualGrid:DoKeyBoardEvents(978)
Called from (b)virtualgrid_create(371)
..

Ricci
Posts: 255
Joined: Thu Nov 19, 2009 2:23 pm

Post by Ricci » Sun Dec 18, 2011 6:34 pm

Sorry Josk, but your code is nearly unreadable.
Without placing it into a

Code: Select all

 ... [/code ] block and using indent to structure the code it´s too exhausting.

That´s the way it should look like:
[code]
METHOD Flat( lValue ) CLASS ABSTRACTBUTTON

   IF PCount() == 0
      ::lFlat := ::oQTObject:isFlat()
      RETURN ::lFlat
   ELSEIF PCOUNT() == 1 .AND. hb_IsLogical( lValue )
      ::oQTObject:setFlat( lValue )
      ::lFlat := lValue
   ENDIF

RETURN NIL
Do you see the difference in readability?

JosK
Posts: 46
Joined: Tue Nov 08, 2011 11:38 pm

Post by JosK » Sun Dec 18, 2011 8:34 pm

Sorry Ricci,

I do copy/paste and then the indent is away.

I have done <source> </source> and <myprg> </endprg> but this doesn't work ...
so next time i wil use <code> </code>

i was hoping you copy/paste myprg and try to compile and run.

My problems are:
1. browse.prg; missing lines Data nNew and Data nDiff
DATA nCurrent INIT NIL
DATA nNew INIT NIL
DATA nDiff INIT NIL
DATA nMasterRecNo INIT NIL
DATA QAbstractItemModel INIT NIL
DATA nCellRowIndex INIT 0
DATA nCellColIndex INIT 0
DATA aStruct INIT NIL

2. toolbar.prg
I have changed toolbar.prg in the past so that i also can add aToolbar to aTabpage.
With the new toolbar.prg i get the error:

error hbqt/100 Message not found:addtoobar: qwidget:addtoolbar
called from qwidget:addToolbar(0)
called from toolbar:new(91)
called from maaktoolbar(234) -> Myprg.prg

My change to toolbar.prg is delete line 90 -92
//IF hb_IsObject( ::oParent )
// ::oParent:QtObject:addToolBar( ::oQTObject )
//ENDIF
After this change the error is away

3. virtualwindow.prg
jk: i have tested the new source (make the lib)
MyProgram give's a new error:
Error Base/42 Scope violation (protected): MAINWINDW:AKEYBOARDEVENTS
Called from MAINWINDOW:AKEYBOARDEVENTS(0)

I get this error because virtualgrid.prg is changed
In previous version aKeyBoardEvents was not protected and now it is.
(previous = 23/11/2011 en new = 18/12/2011)
so i have changed line 50 in virtualwindow and now the error is away (not protected)

4. this has, problebly, to do with 3.
If i run myPrg and do pgup/pgdn with the virtualgrid is get the error:

Error Base/1004 No exported method:Eval
Called from (b)Eval(0)
Called from VirualGrid:DoKeyBoardEvents(978)
Called from (b)virtualgrid_create(371)

I didn't get this error wen i run myPrg with the older version.
... i see a difference.
- When i change line 50 en delete the word protected //
- When i use in MyPrg -> function MaakBrowse -> o:=VirtualGrid() i get the error.
- When i use in MyPrg -> function MaakBrowse -> o:=JkGrid() i get no error when i do PGUP/PGDN/Left/Right
So there is still a importend difference between VirtualGrid.prg an jkGrid.prg


5. if you run myPrg you don't see a underline (&TabPage1 / &RekSchema)
after you do Alt-T you see the underline.


Here i jkGrid.prg (copy from virtualgrid.prg)
I have jkgrid.prg placed in \source and added jkgrid.prg in hmg.hbp

Code: Select all

 *
 * $Id: virtualgrid.prg 806 2011-11-22 12:14:57Z fperillo $
 */

/*
 * HMG Source Code
 *
 * Copyright 2010 Carlos Bacco <carlosbacco at gmail.com>
 * www - http://harbour-project.org
 *
 * Copyright 2002-2010 Roberto Lopez <mail.box.hmg@gmail.com>
 * http://sites.google.com/site/hmgweb/
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or( at your option ) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License FOR more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this software; see the file COPYING. IF not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA( or
 * visit the web site http://www.gnu.org/ ).
 *
 * As a special exception, you have permission FOR additional uses of the text
 * contained in this release of HMG.
 *
 * The exception is that, IF you link the HMG library with other
 * files to produce an executable, this does not by itself cause the resulting
 * executable to be covered by the GNU General Public License.
 * Your use of that executable is in no way restricted on account of linking the
 * HMG library code into it.
 */

#include "hbclass.ch"
#include "common.ch"
#include "hbqtgui.ch"
#include "hmg.ch"


/*----------------------------------------------------------------------*/

CLASS JKGRID FROM ABSTRACTGRID

   * Internal Data

   DATA cClass                                    INIT   "VIRTUALGRID"
   DATA QAbstractItemModel                        INIT   NIL
   DATA nCellRowIndex                             INIT   0
   DATA nCellColIndex                             INIT   0
   DATA aStruct                                   INIT   {}
   DATA QHeaderView                               INIT   NIL
   DATA oSize                                     INIT   NIL
   DATA nCX                                       INIT   0
   DATA nCY                                       INIT   0
   DATA QAbstractItemDelegate                     INIT   NIL
   DATA QItemSelectionModel                       INIT   NIL
   DATA nCurrent                                  INIT   NIL
   DATA nNew                                      INIT   NIL
   DATA nDiff                                     INIT   NIL
   DATA nMasterItemNo                             INIT   NIL
   DATA nMasterRecNo                              INIT   NIL
   DATA nItemCount                                INIT   0
   DATA nRecordCount                              INIT   0
   DATA oQHeaderView                              INIT   NIL
   DATA nValue                                    INIT   NIL
   DATA xValue                                    INIT   NIL

   DATA lCellNavigation                           INIT   NIL
   DATA nLockColumns                              INIT   NIL

   * Data Variables FOR in-place edit

   DATA oCurrentWidget                            INIT   NIL
   DATA xOldValue                                 INIT   NIL
   DATA lCellActive                               INIT   .F.
   DATA lCellChangeActive                         INIT   .F.
   DATA oCellQTObject                             INIT   NIL
   DATA nOldRow                                   INIT   0
   DATA lReturnValueOnEnter                       INIT   .F.
   DATA bOnInitCellEditor                         INIT   NIL

   * Properties

   METHOD Value                                   SETGET
   METHOD CellNavigation                          SETGET
   METHOD LockColumns                             SETGET
   METHOD MultiSelect                             SETGET
   METHOD ItemCount                               SETGET
   METHOD ColumnControls                          SETGET
   METHOD Cell                                    SETGET
   METHOD Item                                    SETGET
   METHOD Items                                   SETGET

   * Events
   METHOD OnChange                                SETGET

   * Methods
   METHOD New
   METHOD Create
   METHOD OnSave
   METHOD OnSelect
   METHOD setItemPos
   METHOD setRecordPos

   METHOD AddColumn
   METHOD DeleteColumn
   METHOD DeleteItem
   METHOD DeleteAllItems
   METHOD AddItem
   METHOD Refresh

   *  FOR inplace edit
   METHOD DoKeyBoardEvents                        SETGET
   METHOD DefineCellcontrol                       SETGET
   METHOD DoCellKeyBoardEvents                    SETGET
   METHOD CellDoubleClicked                       SETGET
   METHOD CloseCell

ENDCLASS

/*----------------------------------------------------------------------*/
*                           Properties
/*----------------------------------------------------------------------*/

METHOD Value( xValue ) CLASS JKGRID
   LOCAL aValue := {}
   LOCAL oModelIndex, i, j, nCurrentArea

   IF ! ::lCreated
      ::xValue := xValue
      RETURN Self
   ENDIF

   DO CASE
   CASE ::nMODE == ARRAY_MODE
      IF Pcount() == 0
         IF LEN( ::aItems ) == 0
            IF ::lCellNavigation .OR. ::lMultiSelect
               RETURN {}
            ELSE
               RETURN 0
            ENDIF
         ENDIF
         IF ::lCellNavigation
            IF !::lMultiSelect  // cellnavigation ON MultiSelect OFF
               oModelIndex := ::QItemSelectionModel:currentIndex()
               RETURN { oModelIndex:row() + 1, oModelIndex:column() + 1 }
            ELSE // cellnavigation ON MultiSelect ON
            * Not Implemeted QModelIndexList Therefore dirtyway
*  *           oModelIndexList := QModelIndexList( ::oQTObject:selectedIndexes() )
*  *           FOR i := 0 to oModelIndexList:Size() - 1
*  *              oModelIndex := QModelIndex( oModelIndexList:At( i ) )
*  *              nRow := oModelIndex:Row() + 1
*  *              nCol := oModelIndex:Column() + 1
*  *              aAdd( aValue,{nRow,nCol} )
*  *           NEXT i
               FOR i := 1 TO LEN( ::aItems )
                  FOR j := 1 TO LEN ( ::aItems[ i ] )
                     oModelIndex := ::QAbstractItemModel:index( i - 1, j - 1, QModelIndex() )
                     IF ::QItemSelectionModel:isSelected( oModelIndex )
                        aadd( aValue, {i,j} )
                     ENDIF
                  NEXT j
               NEXT i
               RETURN aValue
            ENDIF
         ELSE
            IF !::lMultiSelect // cellnavigation OFF MultiSelect OFF
               ::setItemPos( ::nCy )
               RETURN ::nMasterItemNo
            ELSE // cellnavigation OFF MultiSelect ON
            *  QModelIndexList not yet implemented Hence dirty way
*  *           oModelIndexList := QModelIndexList( ::oQTObject:selectedIndexes() )
*  *           FOR i := 0 to oModelIndexList:Size() - 1
*  *              oModelIndex := QModelIndex( oModelIndexList:At( i ) )
*  *              nRow := oModelIndex:Row() + 1
*  *              IF aScan( aValue,nRow ) == 0
*  *                 aAdd( aValue,nRow )
*  *              ENDIF
*  *           NEXT i
               FOR i := 1 TO LEN( ::aItems )
                  FOR j := 1 TO LEN ( ::aItems[ i ] )
                     oModelIndex := ::QAbstractItemModel:index( i - 1, j - 1, QModelIndex() )
                     IF ::QItemSelectionModel:isSelected( oModelIndex )
                        IF aScan( aValue,i ) == 0
                           aAdd( aValue,i )
                        ENDIF
                     ENDIF
                  NEXT j
               NEXT i
               RETURN aValue
            ENDIF
         ENDIF
      ELSEIF Pcount() == 1
         IF ::lCellNavigation
            IF !::lMultiSelect  // CellNavigation ON MultiSelect OFF
               oModelIndex := ::QAbstractItemModel:index( xValue[1] - 1, xValue[2] - 1, QModelIndex() )
               ::oQTObject:setCurrentIndex( oModelIndex )
            ELSE // CellNavigation ON MultiSelect ON
               ::oQTObject:ClearSelection()
               FOR i := 1 to len( xValue )
                  oModelIndex := ::QAbstractItemModel:index( xValue[i,1] - 1, xValue[i,2] - 1, QModelIndex() )
                  ::QItemSelectionModel:select( oModelIndex, 0x0002 )
               NEXT i
               ::oQTObject:setSelectionModel( ::QItemSelectionModel )
            ENDIF
         ELSE
            IF !::lMultiSelect // CellNavigation OFF MultiSelect OFF
               ::oQTObject:selectRow( xValue - 1 )
            ELSE // CellNavigation OFF MultiSelect ON
               ::oQTObject:ClearSelection()
               FOR i := 1 TO len( xValue )
                  FOR j := 1 TO LEN( ::aItems[ xValue[ i ] ] )
                     oModelIndex := ::QAbstractItemModel:index( xValue[i] - 1, j - 1,  QModelIndex() )
                     ::QItemSelectionModel:select( oModelIndex, 0x0002 )
                  NEXT j
               NEXT i
               ::oQTObject:setSelectionModel( ::QItemSelectionModel )
            ENDIF
         ENDIF
      ENDIF
   CASE ::nMode == DATA_MODE

/* PLEASE BE CAREFUL: NEVER USE A MSGINFO HERE ! */
/* when msginfo exists, Qt redraws the screen and recno()/ordkeyno()/etc ARE WRONG */

      IF Pcount() == 0
         ::setRecordPos( ::nCy )
         RETURN ::nMasterRecNo
      ELSEIF Pcount() == 1
         IF empty( &( ::cWorkArea )->( dbFilter() ) )
            &( ::cWorkArea )->( dbGoTo( xValue ) )
            ::oQTObject:setCurrentIndex( ::QAbstractItemModel:index( &( ::cWorkArea )->( OrdKeyNo() ) - 1 , ::nCX , QModelIndex() ) )
         ELSE
            nCurrentArea := Select()
            dbselectarea( ::cWorkArea )
            dbGoTop()
            DO WHILE .not. eof()
               IF recno() == xValue
                  ::oQTObject:setCurrentIndex( ::QAbstractItemModel:index( i - 1 , ::nCX , QModelIndex() ) )
                  EXIT
               ENDIF
               i++
               skip
            ENDDO
            dbselectarea( nCurrentArea )
         ENDIF
      ENDIF
   ENDCASE
   ::xValue := xValue
   RETURN Self

/*----------------------------------------------------------------------*/

/*----------------------------------------------------------------------*/
*                               Events
/*----------------------------------------------------------------------*/

/*----------------------------------------------------------------------*/
*                              Methods
/*----------------------------------------------------------------------*/

/*..............................................................................
   New
..............................................................................*/
METHOD New( cName, oParent ) CLASS JKGRID

   ::aItems := {}
   ::aColumnHeaders := {}

   Super:New( cName, oParent )

   IF hb_IsObject( ::oParent ) 
      ::oQtObject := QTableView( ::oParent:QtParent )  //QTableView( ::oParent:QtObject )
   ELSE
      ::oQtObject := QTableView()
   ENDIF

   ::oQtFont     := ::oQtObject:font()
   ::oQtObject:setFocusPolicy( Qt_StrongFocus )
//   ::oQtObject:setAutoFillBackground( .T. )

// default cell navigation and multiselect .F.
   ::CellNavigation := .F.
   ::MultiSelect    := .F.
   ::showHeaders    := .F.
   ::showColHeader( .T. )

   RETURN Self

/*----------------------------------------------------------------------*/

METHOD Create() CLASS JKGRID
   LOCAL i

   ::oSize := QSize( 24,24 )

   ::lCreated := .T.
   DO CASE
   CASE ::nMode == DATA_MODE
      IF empty( ::aColumnFields  )   .and. ;
         empty( ::aColumnHeaders )   .and. ;
         empty( ::aColumnWidths  )   .and. ;
         hb_IsChar( ::cWorkArea )        

         ::aStruct := &( ::cWorkArea )->( DBStruct() )
         ::aColumnFields  := {}
         ::aColumnHeaders := {}
         FOR i := 1 to len( ::aStruct )
            aadd( ::aColumnFields , ::aStruct[i,1] )
            aadd( ::aColumnHeaders, ::aStruct[i,1] )
         NEXT i
      ELSE

         ::aStruct := {}
         FOR i := 1 to len( ::aColumnFields )
            aadd( ::aStruct , { ::aColumnFields [i] , Type( ::aColumnFields [i]) , fieldlen( FieldPos( ::aColumnFields[i] ) ), FieldDec( FieldPos( ::aColumnFields[i] ) ) } )

         NEXT i
      ENDIF
   CASE ::nMode == ARRAY_MODE
      ::aStruct := {}
      FOR i := 1 to len( ::aColumnHeaders )
         IF hb_IsArray( ::aColumnControls ) 
            DO CASE
            CASE upper( ::aColumnControls [i, 1] ) == 'TEXTBOX'
               DO CASE
               CASE upper( ::aColumnControls [i, 2] ) == 'CHARACTER'
                  aadd( ::aStruct , { ::aColumnHeaders [i] , 'C' , 0 , 0 } )
               CASE upper( ::aColumnControls [i, 2] ) == 'NUMERIC'
                  aadd( ::aStruct , { ::aColumnHeaders [i] , 'N' , 0 , 0 } )
               CASE upper( ::aColumnControls [i, 2] ) == 'DATE'
                  aadd( ::aStruct , { ::aColumnHeaders [i] , 'D' , 0 , 0 } )
               ENDCASE
            CASE upper( ::aColumnControls [i, 1] ) == 'COMBOBOX'
               aadd( ::aStruct , { ::aColumnHeaders [i] , 'C' , 0 , 0 } )
            CASE upper( ::aColumnControls [i, 1] ) == 'DATEPICKER'
               aadd( ::aStruct , { ::aColumnHeaders [i] , 'D' , 0 , 0 } )
            CASE upper( ::aColumnControls [i, 1] ) == 'SPINNER'
               aadd( ::aStruct , { ::aColumnHeaders [i] , 'N' , 0 , 0 } )
            CASE upper( ::aColumnControls [i, 1] ) == 'CHECKBOX'
               aadd( ::aStruct , { ::aColumnHeaders [i] , 'L' , 0 , 0 } )
            ENDCASE
         ELSE
            IF LEN( ::aItems ) > 0
               aadd( ::aStruct , { ::aColumnHeaders [i] , VALTYPE(::aItems[1,i]) , 0 , 0 } )
            ELSE
               aadd( ::aStruct , { ::aColumnHeaders [i] , 'C' , 0 , 0 } )
            ENDIF
         ENDIF
      NEXT i
   ENDCASE


   ::QAbstractItemModel := HBQAbstractItemModel( {| t, r, x, y| ::OnQueryData( ::aStruct , t, r, x, y ) } )
   ::oQTObject:setModel( ::QAbstractItemModel )

   ::QItemSelectionModel := ::oQTObject:selectionModel()
   ::QItemSelectionModel:connect( "currentChanged(QModelIndex,QModelIndex)", {| n | ::OnSelect( n ) } )

   ::oQTObject:verticalHeader():setDefaultSectionSize( 24 )

   ::QAbstractItemDelegate := ::oQTObject:itemDelegate()
   ::QAbstractItemDelegate:connect( "commitData(QWidget*)", {| w | ::OnSave( w ) } )

   ::oQTObject:connect( "doubleClicked(QModelIndex)", {| n | ::CellDoubleClicked( n )} )
   ::oQTObject:connect( QEvent_KeyPress , {|e|::DoKeyBoardEvents( e )} )

   ::oQHeaderView := QHeaderView( ::oQTObject:horizontalHeader() )
   IF hb_IsArray( ::bOnHeadClick ) 
      ::oQHeaderView:disconnect( "sectionClicked(int)" )
      ::oQHeaderView:connect( "sectionClicked(int)",{|i| if( hb_IsBlock( ::bOnHeadClick[i+1] ), Eval( ::bOnHeadClick[i+1] ),nil ) } )
   ENDIF

   ::QAbstractItemModel := HBQAbstractItemModel( {| t, r, x, y| ::OnQueryData( ::aStruct , t, r, x, y ) } )
   ::oQTObject:setModel( ::QAbstractItemModel )

   ::QItemSelectionModel := ::oQTObject:selectionModel()
   ::QItemSelectionModel:connect( "currentChanged(QModelIndex,QModelIndex)", {| n | ::OnSelect( n ) } )
   ::Refresh()

   FOR i := 1 To Len( ::aStruct )
      IF valtype( ::aColumnWidths ) = 'U'
         ::oQtObject:setColumnWidth( i - 1, ::aStruct[ i, 3 ] * 6 + 60 )
      ELSE
         ::oQtObject:setColumnWidth( i - 1, ::aColumnWidths [i] )
      ENDIF
   NEXT

   IF ::nMode == DATA_MODE
      ::nCurrent := 1
      &( ::cWorkArea )->( dbGoTop() )
      ::nMasterRecNo := &( ::cWorkArea )->( recno() )
   ELSE
      IF VALTYPE( ::xValue ) != 'U'
         ::Value := ::xValue
      ENDIF
   ENDIF

   IF hb_IsArray( ::aColumnControls ) 
      IF LEN( ::aColumnControls ) > 0
         ::oQTObject:setEditTriggers( 0 )
      ENDIF
   ELSE
      IF ::lAllowEdit
         msgQuit( "Can't edit cells without setting their type.<br><br>Editing disabled", "Unsupported" )
         ::oQTObject:setEditTriggers( 0 )
      ENDIF
   ENDIF

   IF ::Visible() 
      ::oQtObject:show()
   ENDIF

   RETURN Self

/*----------------------------------------------------------------------*/

METHOD OnSave( pWidget ) CLASS JKGRID
   LOCAL cData 
   LOCAL nCurrentArea, mVar
   LOCAL aStru := ::aStruct
   LOCAL nCX := ::nCX
   LOCAL nCY := ::nCY


   cData := pWidget:text()

   DO CASE
   CASE ::nMode == DATA_MODE
      ::setRecordPos( nCY )
      IF hb_IsArray( ::aColumnValid ) 
         IF hb_IsBlock( ::aColumnValid [nCX + 1] )
            mVar := 'MemVar' + ::cWorkArea + aStru [ nCX+1 ] [ 1 ]
            DO CASE
            CASE type( aStru [ nCX+1 ] [ 1 ] ) == 'C'
               &mVar := cData
            CASE type( aStru [ nCX+1 ] [ 1 ] ) == 'N'
               &mVar := val( cData )
            CASE type( aStru [ nCX+1 ] [ 1 ] ) == 'L'
               &mVar := if( upper( alltrim( cData ) ) == 'Y' , .T. , .F. )
            CASE  type( aStru [ nCX+1 ] [ 1 ] ) == 'D'
               &mVar := ctod( cData )
            ENDCASE
         ENDIF
         IF ! eval( ::aColumnValid [nCX + 1] ) 
            IF hb_IsArray( ::aValidMessages ) 
               IF hb_IsChar( ::aValidMessages [ nCX + 1 ] ) 
                  MsgStop( ::aValidMessages [ nCX + 1 ] )
               ELSE
                  MsgStop( 'Invalid Input!' )
               ENDIF
            ELSE
               MsgStop( 'Invalid Input!' )
            ENDIF
            RETURN NIL
         ENDIF
      ENDIF
      SWITCH aStru[ nCX + 1, 2 ]
      CASE "C"
         nCurrentArea := Select()
         dbselectarea( ::cWorkArea )
         replace &( aStru [ nCX+1 ] [ 1 ] ) with AllTrim( cData )
         dbselectarea( nCurrentArea )
         EXIT
      CASE "N"
         nCurrentArea := Select()
         dbselectarea( ::cWorkArea )
         replace &( aStru [ nCX+1 ] [ 1 ] ) with Val( cData )
         dbselectarea( nCurrentArea )
         EXIT
      CASE "L"
         nCurrentArea := Select()
         dbselectarea( ::cWorkArea )
         replace &( aStru [ nCX+1 ] [ 1 ] ) with Left( cData, 1 ) $ "YyTt"
         dbselectarea( nCurrentArea )
         EXIT
      CASE "D"
         nCurrentArea := Select()
         dbselectarea( ::cWorkArea )
         replace &( aStru [ nCX+1 ] [ 1 ] ) with CToD( cData )
         dbselectarea( nCurrentArea )
         EXIT
      ENDSWITCH
   CASE ::nMode == ARRAY_MODE
      ::setItemPos( nCY )
      IF hb_IsArray( ::aColumnValid ) 
         IF hb_IsBlock( ::aColumnValid [nCX + 1] ) 
            IF ! eval( ::aColumnValid [nCX + 1] ) 
               IF hb_IsArray( ::aValidMessages ) 
                  IF hb_IsChar( ::aValidMessages [ nCX + 1 ] ) 
                     MsgStop( ::aValidMessages [ nCX + 1 ] )
                  ELSE
                     MsgStop( 'Invalid Input!' )
                  ENDIF
               ELSE
                  MsgStop( 'Invalid Input!' )
               ENDIF
               RETURN NIL
            ENDIF
         ENDIF
      ELSE
         DO CASE
         CASE aStru [ nCX+1 ] [ 2 ]  == 'C'
            ::aItems [ nCY+1 ] [ nCX + 1 ] := cData
         CASE aStru [ nCX+1 ] [ 2 ]  == 'N'
            ::aItems [ nCY+1 ] [ nCX + 1 ] := val( cData )
         CASE aStru [ nCX+1 ] [ 2 ]  == 'L'
            ::aItems [ nCY+1 ] [ nCX + 1 ] := if( upper( alltrim( cData ) ) == 'Y' .OR. upper( alltrim( cData ) ) == 'T' , .T. , .F. )
         CASE aStru [ nCX+1 ] [ 2 ]  == 'D'
            ::aItems [ nCY+1 ] [ nCX + 1 ] := ctod( cData )
         ENDCASE
      ENDIF
   ENDCASE

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD onSelect( qModelIndex ) CLASS JKGRID
   LOCAL xValue, oModelIndex, nNewRow, nNewCol

   ::nCX := qModelIndex:column()
   ::nCY := qModelIndex:row()
   IF ::lCellActive .and. .not. ::lCellChangeActive
      nNewRow := ::nCY + 1
      nNewCol := ::nCX + 1
      IF nNewRow == ::nCellRow .and. nNewCol == ::nCellCol
         * Nothing Doing
         RETURN NIL
      ENDIF
      xValue := ::oCurrentWidget:Value
      IF hb_IsArray( ::aColumnValid ) 
         IF hb_IsBlock( ::aColumnValid[ ::nCellCol ] ) 
            * Restore the cell cursor to old place until columnvalid is ok
            ::lCellChangeActive := .T.
            oModelIndex := ::QAbstractItemModel:index( ::nCellRow - 1, ::nCellCol - 1, QModelIndex() )
            ::oQTObject:setCurrentIndex( oModelIndex )
            IF !Eval( ::aColumnValid[ ::nCellCol ] )
                ::oCellQTObject:setFocus()
                ::lCellChangeActive := .F.
               RETURN NIL
            ENDIF
         ENDIF
      ENDIF
      ::CloseCell( xValue )
      ::oQTObject:reset()
*      ::QAbstractItemModel:reset()
      oModelIndex := ::QAbstractItemModel:index( nNewRow - 1, nNewCol - 1, QModelIndex() )
      ::oQTObject:setCurrentIndex( oModelIndex )
      ::oQTObject:setFocus()
      ::lCellChangeActive := .F.
   ENDIF
   IF ValType( ::bOnChange ) != 'U' .AND. .NOT. ::lCellChangeActive .AND. ::lCreated
      nNewRow := ::nCY
      IF !::lCellNavigation // QT gives signal FOR change in columns even in a full row selection mode
         IF nNewRow != ::nOldRow
            Eval( ::bOnChange )
            ::nOldRow := nNewRow
         ENDIF
      ELSE
         Eval( ::bOnChange )
      ENDIF
   ENDIF

   RETURN Self

/*----------------------------------------------------------------------*/

METHOD setItemPos( nValue ) CLASS JKGRID

	IF PCOUNT() == 1 .AND. hb_IsNumeric( nValue )	 
	   ::nCurrent := nValue + 1
	
	   ::nMasterItemNo := nValue + 1
	ENDIF
		
   RETURN Self

/*----------------------------------------------------------------------*/

METHOD setRecordPos( nValue ) CLASS JKGRID

	IF PCOUNT() == 1 .AND. hb_IsNumeric( nValue )	 
	   &( ::cWorkArea )->( dbGoTo( ::nMasterRecNo ) )
	
	   if( nValue + 1 ) == 1
	      &( ::cWorkArea )->( dbGoTop() )
	      ::nCurrent := nValue + 1
	
	   ELSEIF( nValue + 1 ) > ::nRecordCount - 100                     //  Why 100 ??? Ricci
	      &( ::cWorkArea )->( dbGoBottom() )
	      &( ::cWorkArea )->( dbskip( ( nValue + 1 ) - ::nRecordCount ) )
	      ::nCurrent := nValue + 1
	   ELSE
	      ::nNew := nValue + 1
	      ::nDiff :=  ::nNew - ::nCurrent
	      IF ::ndiff <> 0
	         &( ::cWorkArea )->( dbSkip( ::nDiff ) )
	         ::nCurrent := ::nNew
	      ENDIF
	   ENDIF
	   ::nMasterRecNo := &( ::cWorkArea )->( recno() )
   ENDIF

   RETURN Self

/*----------------------------------------------------------------------*/
METHOD CellNavigation( lValue ) CLASS JKGRID

   IF Pcount() == 0
      RETURN ::lCellNavigation
   ELSEIF PCOUNT() == 1 .AND. hb_IsLogical( lValue )
      ::lCellNavigation := lValue
      IF !::lCellNavigation
         ::oQTObject:setSelectionBehavior( QAbstractItemView_SelectRows )
      ELSE
         ::oQTObject:setSelectionBehavior( QAbstractItemView_SelectItems )
      ENDIF
   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD LockColumns( nValue ) CLASS JKGRID

   IF Pcount() == 0
      RETURN ::nLockColumns
   ELSEIF PCOUNT() == 1 .AND. hb_IsNumeric( nValue )
      ::nLockColumns := nValue
   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD MultiSelect( lValue ) CLASS JKGRID

   IF Pcount() == 0
      IF ::oQTObject:selectionmode() == 3
         RETURN .t.
      ELSE
         RETURN .f.
      ENDIF
   ELSEIF PCOUNT() == 1 .AND. hb_IsLogical( lValue )
      IF lValue
         * Multiselect is not allowed in DATA_MODE
         IF ::nMode == ARRAY_MODE
            ::oQTObject:setselectionmode( 3 )
            * Not to allow edit while in multiselect mode
            ::lAllowEdit := .f.
         ENDIF
      ELSE
         ::oQTObject:setSelectionMode( 1 )
      ENDIF
      ::lMultiSelect := lValue
      IF ::lCreated
         ::Refresh()
      ENDIF
   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD ItemCount() CLASS JKGRID

	IF ::nMode == ARRAY_MODE
	   RETURN len( ::aItems )
	ENDIF

	RETURN NIL

/*----------------------------------------------------------------------*/

METHOD ColumnControls( aValue ) CLASS JKGRID

   IF Pcount() == 0
      RETURN ::aColumnControls
   ELSEIF PCOUNT() == 1 .AND. hb_IsArray( aValue )
      ::aColumnControls := aValue
   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD Cell( nRow , nCol , xValue ) CLASS JKGRID

   IF PCOUNT() == 2 .AND. hb_IsNumeric( nRow ) .AND. hb_IsNumeric( nCol )
      IF ::nMode == ARRAY_MODE
         RETURN ::aItems[ nRow, nCol ]
      ENDIF
   ELSEIF PCOUNT() == 3 .AND. hb_IsNumeric( nRow ) .AND. hb_IsNumeric( nCol )
      IF ::nMode == ARRAY_MODE
         ::aItems[ nRow,nCol ] := xValue
         IF ! ::lCellActive
            ::Refresh()
         ENDIF
      ENDIF
   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD Item( nRow , xValue ) CLASS JKGRID

   LOCAL i
   * Item method is allowed only in array mode
   IF .NOT. ::nMode == ARRAY_MODE
      RETURN NIL
   ENDIF

   IF PCOUNT() == 1 .AND. hb_IsNumeric( nRow )
      RETURN ::aItems[ nRow ]
   ELSEIF PCOUNT() == 2 .AND. hb_IsNumeric( nRow )
      FOR i := 1 TO LEN( ::aItems[ nRow ] )
         IF LEN( xValue ) >= i
            ::aItems[ nRow,i ] := xValue[i]
         ENDIF
      NEXT
      ::Refresh()
   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD AddColumn( nColIndex , cCaption , nWidth , nJustify, cHeaderImage ) CLASS JKGRID
   LOCAL i

   * AddColumn method is allowed only in array mode
   IF .NOT. ::nMode == ARRAY_MODE
      RETURN NIL
   ENDIF

   IF PCOUNT() >= 3 .AND. hb_IsNumeric( nColIndex ) .AND. hb_IsChar( cCaption ) .AND. hb_IsNumeric( nWidth ) 

      aSize( ::aStruct, LEN( ::aStruct ) + 1 )
      aIns( ::aStruct,nColIndex )
      ::aStruct[nColIndex] := { cCaption, 'C', 20, 0 }

      aSize( ::aColumnHeaders,len( ::aColumnHeaders )+1 )
      aIns( ::aColumnHeaders,nColIndex )
      ::aColumnHeaders[nColIndex] := cCaption

      aSize( ::aColumnWidths,len( ::aColumnWidths )+1 )
      aIns( ::aColumnWidths,nColIndex )
      ::aColumnWidths[nColIndex] := nWidth

      aSize( ::aColumnJustify,len( ::aColumnJustify )+1 )
      aIns( ::aColumnJustify,nColIndex )
      ::aColumnJustify[nColIndex] := nJustify

      IF ValType( ::aHeaderImages ) != 'U'
         aSize( ::aHeaderImages,len( ::aHeaderImages )+1 )
         aIns( ::aHeaderImages,nColIndex )
         aSize( ::aHeaderPixmaps,len( ::aHeaderPixmaps )+1 )
         aIns( ::aHeaderPixmaps,nColIndex )
         ::aHeaderImages[nColIndex] := cHeaderImage
         ::aHeaderPixmaps[nColIndex] := QPixmap( ::aHeaderImages[nColIndex] )
      ENDIF

      FOR i := 1 To Len( ::aStruct )
         IF valtype( ::aColumnHeaders ) = 'U'   ;
            .and.               ;
            valtype( ::aColumnWidths ) = 'U'
            ::oQtObject:setColumnWidth( i - 1, ::aStruct[ i, 3 ] * 6 + 60 )
         ELSE
            ::oQtObject:setColumnWidth( i - 1, ::aColumnWidths [i] )
         ENDIF
      NEXT

      aSize( ::aItems, 0)

      ::Refresh()

   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD DeleteColumn( nCol ) CLASS JKGRID
   LOCAL i

   * DeleteColumn method is allowed only in array mode
   IF .NOT. ::nMode == ARRAY_MODE
      RETURN NIL
   ENDIF


   IF PCOUNT() == 1 .and. hb_IsNumeric( nCol ) .and. nCol < len( ::aStruct )

      aSize( ::aItems, 0)

      ::Refresh()

      aDel( ::aStruct,nCol )
      aSize( ::aStruct,len( ::aStruct )-1 )

      aDel( ::aColumnHeaders,nCol )
      aSize( ::aColumnHeaders,len( ::aColumnHeaders )-1 )

      aDel( ::aColumnJustify,nCol )
      aSize( ::aColumnJustify,len( ::aColumnJustify )-1 )

      aDel( ::aColumnWidths,nCol )
      aSize( ::aColumnWidths,len( ::aColumnWidths )-1 )

      IF ValType( ::aHeaderImages ) != 'U'
         aDel( ::aHeaderImages,nCol )
         aSize( ::aHeaderImages,len( ::aHeaderImages )-1 )
         aDel( ::aHeaderPixmaps,nCol )
         aSize( ::aHeaderPixmaps,len( ::aHeaderPixmaps )-1 )
      ENDIF

      FOR i := 1 To Len( ::aStruct )
         IF valtype( ::aColumnHeaders ) = 'U'   ;
            .and.               ;
            valtype( ::aColumnWidths ) = 'U'
            ::oQtObject:setColumnWidth( i - 1, ::aStruct[ i, 3 ] * 6 + 60 )
         ELSE
            ::oQtObject:setColumnWidth( i - 1, ::aColumnWidths [i] )
         ENDIF
      NEXT

      ::Refresh()

   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD DeleteItem( nRow ) CLASS JKGRID

	IF PCOUNT() == 1 .AND. hb_IsNumeric( nRow )
	   * DeleteItem method is allowed only in array mode
	   IF .NOT. ::nMode == ARRAY_MODE
	      RETURN NIL
	   ENDIF
	
	   aDel( ::aItems, nRow)
	   aSize( ::aItems, LEN( ::aItems ) - 1 )
	   ::Refresh()
   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD DeleteAllItems() CLASS JKGRID

   * DeleteAllItems method is allowed only in array mode
   IF .NOT. ::nMode == ARRAY_MODE
      RETURN NIL
   ENDIF

   aSize( ::aItems, 0 )
   ::Refresh()

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD AddItem( aValue ) CLASS JKGRID

	IF PCOUNT() == 1 .AND. hb_IsArray( aValue )
	   * AddItem method is allowed only in array mode
	   IF .NOT. ::nMode == ARRAY_MODE
	      RETURN NIL
	   ENDIF
	
	   aadd( ::aItems, aValue )
	   ::Refresh()
   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD ITEMS( aValue ) CLASS JKGRID

   * Items method is allowed only in array mode
   IF .NOT. ::nMode == ARRAY_MODE
      msgquit( "virtualgrid:items() not in ARRAY_MODE" )
      RETURN NIL
   ENDIF

   IF Pcount() == 0
      RETURN ::aItems
   ELSEIF PCOUNT() == 1 .AND. hb_IsArray( aValue )
      ::aItems := aClone( aValue )
      ::Refresh()
   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD OnChange( bValue ) CLASS JKGRID

   IF Pcount() == 0
      RETURN ::bOnChange
   ELSEIF PCOUNT() == 1 .AND. hb_IsBlock( bValue )
      ::bOnChange := bValue
   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD CellDoubleClicked( qModelIndex ) CLASS JKGRID

   LOCAL nNewRow,nNewCol

   nNewRow := qModelIndex:row() + 1
   nNewCol := qModelIndex:column() + 1
*  If already cell edit is in process, don't process anything here
   IF ::lCellActive
      RETURN NIL
   ENDIF
   * process on dblclick event IF any
   IF ValType( ::bOnDblClick ) != 'U'
      Eval( ::bOnDblClick )
   ENDIF
   * FOR inplace edit
   IF !::lAllowEdit .or. ::lMultiSelect
      * Nothing doing
      RETURN NIL
   ELSE
      IF ValType( ::aColumnControls ) == 'U'  // no inplace edit required.
         RETURN NIL
      ENDIF
   ENDIF
   ::nCellRow := nNewRow
   ::nCellCol := nNewCol
   IF hb_IsArray( ::aColumnWhen ) 
      IF hb_IsBlock( ::aColumnWhen[ ::nCellCol ] ) 
         IF !Eval( ::aColumnWhen[ ::nCellCol ] )
            RETURN .T.
         ENDIF
      ENDIF
   ENDIF
   * Inplace edit area
   ::DefineCellControl()

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD DoKeyBoardEvents( e ) CLASS JKGRID

   LOCAL oKeyEvent := e
   LOCAL nKey := oKeyEvent:key()
   LOCAL nModifiers := oKeyEvent:modifiers()
   IF ::lCellActive //Already cell edit is in process, so don't process any key here
      //functie-toetsen zou moeten mogen ?      
      RETURN .T.
   ENDIF
   IF !::lAllowEdit .or. ::lMultiSelect
   * Nothing doing
      RETURN .F.
   ELSE
      IF ValType( ::aColumnControls ) == 'U'  // no inplace edit required.
         RETURN .T.
      ENDIF
   ENDIF
   ::nCellRow := ::nCY + 1
   ::nCellCol := ::nCX + 1
   IF hb_IsArray( ::aColumnWhen ) 
      IF hb_isBlock(::aColumnWhen[::nCellCol])
         IF !Eval( ::aColumnWhen[::nCellCol] )
            IF ::nCellCol == len( ::aColumnWhen )
               RETURN .F.
            ELSE
               ::nCellCol++    // to navigate to NEXT cell IF columnwhen is not allowed
            ENDIF   
         ENDIF
      ENDIF
   ENDIF
   * Inplace edit area
   If( nKey == Qt_Key_Return .and. nModifiers == Qt_NoModifier ) .or.( nKey == Qt_Key_Enter .and. nModifiers == Qt_KeypadModifier ) .or.( nKey == Qt_Key_F2 .and. nModifiers == Qt_NoModifier )
      ::DefineCellControl()
   ENDIF

   RETURN .F.

/*----------------------------------------------------------------------*/

METHOD DefineCellControl CLASS JKGRID

   LOCAL oModelIndex, nCurrentArea

   * Preserve old value to restore IF escape key is pressed or editing cancelled.
   DO CASE
   CASE ::nMode == DATA_MODE
      ::setRecordPos( ::nCellRow - 1 )
      nCurrentArea := Select()
      dbselectarea( ::cWorkArea )
      ::xOldValue := &( ::cWorkArea )->( &( ::aStruct [ ::nCellCol ] [ 1 ] ) )
      dbselectarea( nCurrentArea )
   CASE ::nMode == ARRAY_MODE
           ::xOldValue := ::Cell( ::nCellRow, ::nCellCol )
   ENDCASE  //er stond ENDCASEw 

   ::s_lGridCellFlag := .t.
   DO CASE
   CASE upper( alltrim( ::aColumnControls[::nCellCol][1] ) ) == 'TEXTBOX'
      ::oCurrentWidget := TextBox():New()
      * Finding the datatype and textbox type
      DO CASE
      CASE upper( alltrim( ::aColumnControls[::nCellCol][2] ) ) == 'NUMERIC'
         ::oCurrentWidget:DataType := TXT_NUMERIC
      CASE upper( alltrim( ::aColumnControls[::nCellCol][2] ) ) == 'DATE'
         ::oCurrentWidget:DataType := TXT_DATE
      OTHERWISE
         ::oCurrentWidget:DataType := TXT_CHARACTER
      ENDCASE
      IF !::oCurrentWidget:DataType == TXT_DATE
         IF len( ::aColumnControls[::nCellCol] ) > 2
            IF ValType( ::aColumnControls[::nCellCol] [3] ) != 'U'
               IF Len( alltrim( ::aColumnControls[::nCellCol][3] ) ) > 0 // inputmask
                  ::oCurrentWidget:InputMask := ::aColumnControls[::nCellCol][3]
               ENDIF
            ENDIF
            IF ::oCurrentWidget:DataType == TXT_NUMERIC
               IF len( ::aColumnControls[::nCellCol] ) > 3
                  IF ValType( ::aColumnControls[::nCellCol][4] ) != 'U'
                     IF Len( alltrim( ::aColumnControls[::nCellCol][4] ) ) > 0 // format
                        ::oCurrentWidget:Format := ::aColumnControls[::nCellCol][4]
                     ENDIF
                  ENDIF
               ENDIF
            ENDIF
         ENDIF
      ENDIF
      * Right align the cell if column justification is right
      IF valtype( ::aColumnJustify ) <> 'U'
         IF ::aColumnJustify[::nCellCol] == GRID_JTFY_RIGHT
            ::oCurrentWidget:Alignment := TXT_RIGHT
         ENDIF
      ENDIF
   CASE upper( alltrim( ::aColumnControls[::nCellCol][1] ) ) == 'CHECKBOX'
      ::oCurrentWidget := CheckBox():New()
      * set the initial value to edit ie., old value
      ::oCurrentWidget:Caption := if( ::xOldValue,::aColumnControls[::nCellCol][2],::aColumnControls[::nCellCol][3] )
      ::oCurrentWidget:OnChange := {|| If( ::oCurrentWidget:Value,::oCurrentWidget:Caption := ::aColumnControls[::nCellCol][2],::oCurrentWidget:Caption := ::aColumnControls[::nCellCol][3] )}
   CASE upper( alltrim( ::aColumnControls[::nCellCol][1] ) ) == 'DATEPICKER'
      ::oCurrentWidget := DatePicker():New()
      * set the initial value to edit ie., old value
      IF upper( alltrim( ::aColumnControls[::nCellCol][2] ) ) == 'UPDOWN'
         ::oCurrentWidget:UpDown := .t.
      ELSE
         ::oCurrentWidget:UpDown := .f.
      ENDIF
   CASE upper( alltrim( ::aColumnControls[::nCellCol][1] ) ) == 'SPINNER'
      ::oCurrentWidget := Spinner():New()
      * set the initial value to edit ie., old value
      ::oCurrentWidget:RangeMin := ::aColumnControls[::nCellCol][2]
      ::oCurrentWidget:RangeMax := ::aColumnControls[::nCellCol][3]
   CASE upper( alltrim( ::aColumnControls[::nCellCol][1] ) ) == 'COMBOBOX'
      * ComboBox creation & initialization started
      ::oCurrentWidget := ComboBox():New()
      * set the initial value to edit ie., old value
      ::oCurrentWidget:Items := ::aColumnControls[::nCellCol][2]
   ENDCASE
   * set the initial value to edit ie., old value
   ::oCurrentWidget:Value := ::xOldValue

   IF upper( alltrim( ::aColumnControls[::nCellCol][1] ) ) == 'TEXTBOX'
      * To set the inputmask & format
      ::oCurrentWidget:Create()
      // ::oCellQTObject:selectAll()
   ENDIF

   * store qt object and set the same to the cell of the grid
   ::s_lGridCellFlag := .f.
   ::oCellQTObject := ::oCurrentWidget:QTObject
   ::oCellQTObject:setAutoFillBackground( .t. )
   * connect keypress event of the datepicker FOR processing enter and escape key
   ::oCellQTObject:connect( QEvent_KeyPress , {|e|::DoCellKeyBoardEvents( e )} )

   oModelIndex := ::QAbstractItemModel:index( ::nCellRow - 1, ::nCellCol - 1, QModelIndex() )
   ::oQTObject:setIndexWidget( oModelIndex, ::oCellQTObject )
   * cell is activated
   ::lCellActive := .T.
   ::oCellQTObject:setFocus()

   if ::bOnInitCellEditor  !=  NIL
        eval( ::bOnInitCellEditor, Self, ::oCurrentWidget, ::aColumnControls[::nCellCol][1] )
   endif

   RETURN NIL

/*----------------------------------------------------------------------*/

METHOD DoCellKeyBoardEvents( e ) Class JKGRID
    //flags en enum QT::KeyboardModifiers : QT_NoModifier = geen shift, ctrl, alt, keypad en geen meta (meta is bijvb start mail)
    

   LOCAL oKeyEvent := e
   LOCAL nKey := oKeyEvent:key()
   LOCAL nModifiers := oKeyEvent:modifiers()
   LOCAL xValue
   LOCAL oModelIndex, nRecNo , nArea

  
   /*
   *  dit was voor de help/f10 !?
   *  ook insert bInsToggle
    if(jkBlock:=setkey(nkey) !=NIL)
      eval(jkBlock, procname(1), procline(1),'')
      //was loop maar hier return .f. 
      // de eval is uitgevoerd en we willen nieuwe nKey
      return .f.
    endif
   */
   
   DO CASE
   CASE nKey == Qt_Key_Escape //.and. nModifiers == Qt_NoModifier
      ::lCellActive := .F.
      ::oCellQTObject:close()
      ::oQTObject:reset()
      oModelIndex := ::QAbstractItemModel:index( ::nCellRow - 1, ::nCellCol - 1, QModelIndex() )
      ::oQTObject:setCurrentIndex( oModelIndex )
      ::oQTObject:setFocus()
   CASE(nKey == Qt_Key_Up).or.;
       (nKey == Qt_Key_Down).or.;
       (nKey == Qt_Key_Right).or.;
       (nKey == Qt_Key_Left).or.;
       (nKey == Qt_Key_Home).or.;
       (nKey == Qt_Key_PageDown).or.;
       (nKey == Qt_Key_PageUp).or.;
       (nKey == Qt_Key_PageUp)
       return .f.
   CASE (nKey == Qt_Key_Return .and. nModifiers == Qt_NoModifier ) .or. ( nKey == Qt_Key_Enter .and. nModifiers == Qt_KeypadModifier )
      * na enter op veld krijg je de edit mode
      xValue := ::oCurrentWidget:Value
      IF hb_IsArray( ::aColumnValid ) 
         IF hb_IsBlock( ::aColumnValid[ ::nCellCol ] ) 
            IF !Eval( ::aColumnValid[ ::nCellCol ] )
               RETURN .T.
            ENDIF
         ENDIF
      ENDIF
      ::CloseCell( xValue )
      * Move on to the next cell
      IF ::nCellCol < LEN( ::aColumnControls )
         ::nCellCol++
      ELSE
         DO CASE
         CASE ::nMode == ARRAY_MODE
            IF ::nCellRow < LEN( ::aItems )
               ::nCellRow++
               ::nCellCol := 1
            ENDIF
         CASE ::nMode == DATA_MODE
            IF ( empty( &( ::cWorkArea )->( dbFilter() ) ) ) .and.( .Not. Set( _SET_DELETED ) )
               ::nRecordCount := &( ::cWorkArea )->( OrdKeyCount() )
            ELSE
               nArea := Select()
               nRecNo := recno()
               dbSelectArea( ::cWorkArea )
               COUNT TO ::nRecordCount
               dbSelectArea( nArea )
               dbgoto( nRecNo )
            ENDIF
            //jk IF ::nCellRow < LEN( ::nRecordCount )
            IF ::nCellRow < ::nRecordCount   
               ::nCellRow++
               ::nCellCol := 1
            ELSE
               //msg add line ?   
            ENDIF
         ENDCASE
      ENDIF
      ::oQTObject:reset()
      oModelIndex := ::QAbstractItemModel:index( ::nCellRow - 1, ::nCellCol - 1, QModelIndex() )
      ::oQTObject:setCurrentIndex( oModelIndex )  //jk: kreeg ERROR na RETURN input laatste veld; RETURN en NoModifiers (numlock stond aan maar valt niet onder NoModi
      ::oQTObject:setFocus()
      RETURN ::lReturnValueOnEnter
   CASE nModifiers == Qt_NoModifier .or. nModifiers == Qt_KeypadModifier 
     * geen alt/shift/meta dit gaan we nog wel wijzigen
   ENDCASE

   RETURN .F.

/*----------------------------------------------------------------------*/

METHOD Refresh() CLASS JKGRID

   IF ::lCreated  .and. ! ::lCellActive
      ::QAbstractItemModel:reset()
   ENDIF

   RETURN NIL

/*----------------------------------------------------------------------*/
METHOD CloseCell( xValue ) CLASS JKGRID

   LOCAL nCurrentArea
   DO CASE
   CASE ::nMode == ARRAY_MODE
      ::Cell( ::nCellRow,::nCellCol,xValue )
   CASE ::nMode == DATA_MODE
      ::setRecordPos( ::nCellRow - 1 )
      nCurrentArea := Select()
      dbselectarea( ::cWorkArea )
      replace &( ::aStruct [ ::nCellCol ] [ 1 ] ) with xValue
      dbselectarea( nCurrentArea )
   ENDCASE
   ::lCellActive := .F.
   ::oCellQTObject:close()
   * To remove the widget from QTableView

   RETURN NIL
   
/*----------------------------------------------------------------------*/

JosK
Posts: 46
Joined: Tue Nov 08, 2011 11:38 pm

Post by JosK » Sun Dec 18, 2011 9:17 pm

i have found the difference between jkGrid and virtual grid

Error Base/1004 No exported method:Eval
Called from (b)Eval(0)
Called from VirualGrid:DoKeyBoardEvents(978)
Called from (b)virtualgrid_create(371)

line 978 in virtualgrid and also in jkgrid.prg
is the eval of aColumnWhen

o:ColumnWhen := { { || UPPER(LEFT(first,1) ) == 'A' } ,{||.f.};
, , , , , , , , , , , }

in Virtualgrid.prg you must add
IF hb_isBlock(::aColumnWhen[::nCellCol])
because you can see in o:ColumnWhen that thirdt, fourth is not a block.

Code: Select all

::nCellCol := ::nCX + 1
   IF hb_IsArray( ::aColumnWhen ) 
      IF hb_isBlock(::aColumnWhen[::nCellCol])
         IF !Eval( ::aColumnWhen[::nCellCol] )
            IF ::nCellCol == len( ::aColumnWhen )
               RETURN .F.
            ELSE
               ::nCellCol++    // to navigate to NEXT cell IF columnwhen is not allowed
            ENDIF   
         ENDIF
      ENDIF
   ENDIF
   * Inplace edit area
   If( nKey == Qt_Key_Return .and. nModifiers == Qt_NoModifier ) .or.( nKey == Qt_Key_Enter .and. nModifiers == Qt_KeypadModifier ) .or.( nKey == Qt_Key_F2 .and. nModifiers == Qt_NoModifier )
      ::DefineCellControl()
   ENDIF

   RETURN .F.
[/code ]

Ricci
Posts: 255
Joined: Thu Nov 19, 2009 2:23 pm

Post by Ricci » Sun Dec 18, 2011 9:41 pm

Josk, changing the sources without being part of the developer team can be frustrating.
When you change a class for your own without knowing that another one doing some other changes on the same source, then all your work may be lost at the next update.

One tip: sometimes it is better to use inheritance and overloading instead of working with the whole class code. You write a demo, add the inheritated class code at the end and present it to the developer team. If it´s useful and stable it can simply be included into the parent class.

The other way: you become part of the developer team. There you write your ideas to the other developers and ask for locking of the sources you are going to change. Then nobody else will do changes to theses sources until you are finished.

Both ways prevent new classes and parallel development.

mrduck
Posts: 497
Joined: Fri Sep 10, 2010 5:22 pm

Post by mrduck » Sun Dec 18, 2011 9:51 pm

Ricci wrote: When you change a class for your own without knowing that another one doing some other changes on the same source, then all your work may be lost at the next update.
Already told him, and also explained how to do it properly... He changed ONE method and could use inheritance without "forking"... because doing what he did is equal to forking... with all the consequences...



So, JosK, please follow my example in the other thread I posted a couple of days ago and change JKGrid to inherit from VIRTUALGRID ! It will save you a lot of pain when some internal code is changed !!!
PLEASE follow what I and Ricci are saying, you will thank us later, believe us please !

JosK
Posts: 46
Joined: Tue Nov 08, 2011 11:38 pm

Post by JosK » Sun Dec 18, 2011 10:34 pm

Okay. sorry, i'm not at all an expert.

I had make a copy from virtualgrid to jkGrid because i didn't want to mess with your'e code.
(replace all "virtualgrid" with "jkGrid" within the copy of virtualgrid)

I have made some changes also to toolbar.prg and other sources as you can see in this forum. I don't upload these files ... i just report my remarks.

I thought it was easier for you if i reported the changes the way i do.

And i think that MyPrg.prg a nice example is for other peoples who want to work with hmg.4
I think it's a different style as the examples that comes with hmg.4

JosK
Posts: 46
Joined: Tue Nov 08, 2011 11:38 pm

Post by JosK » Sun Dec 18, 2011 10:49 pm

I know about inheritance and overloading.

The things that i have changed are bugs.
(virtualgrid, toolbar, browse, ..)

please read my posts in this form (under i have add methode flat in abstractbutton.prg .)


*BUG in Virtalgrid .. see my previous post ..
in Virtualgrid.prg you must add
IF hb_isBlock(::aColumnWhen[::nCellCol])
because you can see in o:ColumnWhen that thirdt, fourth is not a block.

Post Reply