i have add methode Flat in abstractbutton.prg
Moderator: Rathinagiri
i have add methode Flat in abstractbutton.prg
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"
icture := "save.png"
:OnClick := {|| MsgInfo( "Save!" )}
:ToolTip := "ToolTip"
end
with Object TOOLBUTTON():New("TB2",o)
:Caption := "AutoUser"
icture := "save.png"
:OnClick := {|| AutoUser()}
:ToolTip := "ToolTip"
end
with Object TOOLBUTTON():New("TB3",o)
:Caption := "UserNamer"
icture := "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>
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"
icture := "save.png"
:OnClick := {|| MsgInfo( "Save!" )}
:ToolTip := "ToolTip"
end
with Object TOOLBUTTON():New("TB2",o)
:Caption := "AutoUser"
icture := "save.png"
:OnClick := {|| AutoUser()}
:ToolTip := "ToolTip"
end
with Object TOOLBUTTON():New("TB3",o)
:Caption := "UserNamer"
icture := "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>
Re: i have add methode Flat in abstractbutton.prg
if you run my program you don't see a underline (&TabPage1 / &RekSchema)
after you do Alt-T you see the underline.
after you do Alt-T you see the underline.
Re: i have add methode Flat in abstractbutton.prg
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)
..
Error Base/1004 No exported method:Eval
Called from (b)Eval(0)
Called from VirualGrid:DoKeyBoardEvents(978)
Called from (b)virtualgrid_create(371)
..
Re: i have add methode Flat in abstractbutton.prg
Sorry Josk, but your code is nearly unreadable.
Without placing it into a
Do you see the difference in readability?
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
Re: i have add methode Flat in abstractbutton.prg
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
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
/*----------------------------------------------------------------------*/
Re: i have add methode Flat in abstractbutton.prg
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.
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 ]
Re: i have add methode Flat in abstractbutton.prg
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.
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.
Re: i have add methode Flat in abstractbutton.prg
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...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.
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 !
Re: i have add methode Flat in abstractbutton.prg
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
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
Re: i have add methode Flat in abstractbutton.prg
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.
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.