3
image create bitmap ::img::arrow_left \
4
-file [file join $::config::installDir arrow-left.xbm] \
6
image create bitmap ::img::arrow_right \
7
-file [file join $::config::installDir arrow-right.xbm] \
9
image create bitmap ::img::arrow_home \
10
-file [file join $::config::installDir arrow-home.xbm] \
12
image create bitmap ::img::arrow_end \
13
-file [file join $::config::installDir arrow-end.xbm] \
18
protected common windowList {}
19
public variable window {}
20
protected variable parent
21
public variable formName
22
protected variable noteBook
23
protected variable formDef
24
protected variable attribDef
25
protected variable attribList
26
protected variable modAttribList
27
protected variable tabList {}
28
protected variable tabObject
30
proc closeAllWindows {} {
31
foreach window $windowList {
37
constructor {c_parent c_formName} {
39
set formName $c_formName
45
foreach tab $tabList {
48
set indexDeleted [lsearch -exact $windowList $window]
49
set windowList [lreplace $windowList $indexDeleted $indexDeleted]
53
protected method setupWindow {} {
54
set window [toplevel [appendToPath $parent [namespace tail $this]]]
55
lappend windowList $window
56
wm geometry $window [join $::geometry::form {x}]
57
set noteBook [ttk::notebook $window.nb -takefocus 0]
58
set tabOpen [OpenTab "#auto" $noteBook $this]
59
addNotebookTab $noteBook [$tabOpen cget -widget] tabOpen
60
lappend tabList $tabOpen
61
set tabObject([$tabOpen cget -widget]) $tabOpen
62
pack $noteBook -side top -expand 1 -fill both
63
pack [ttk::sizegrip ${window}.sg] -side top -anchor e
64
ttk::notebook::enableTraversal $noteBook
65
bind $noteBook <<NotebookTabChanged>> [list $this onTabChange]
66
set tpOnly [bindToplevelOnly $window <Destroy> [list delete object $this]]
67
bind $tpOnly <Configure> {set ::geometry::form {%w %h}}
71
public method removeTab {removedTab} {
72
set indexDeleted [lsearch -exact $tabList $removedTab]
73
if {$indexDeleted >= 0} then {
74
set tabList [lreplace $tabList $indexDeleted $indexDeleted]
76
delete object $removedTab
77
if {[llength $tabList] == 0} then {
80
[lindex $tabList end] setTabLock 0
85
public method deleteTabsAbove {tab} {
86
set thisTabIdx [lsearch -exact $tabList $tab]
87
foreach tabAbove [lrange $tabList [expr $thisTabIdx + 1] end] {
88
delete object $tabAbove
90
set tabList [lrange $tabList 0 $thisTabIdx]
94
public method newFormTab {newFormName formDefDict history} {
95
[lindex $tabList end] setTabLock 1
96
set newTab [FormTab "#auto" $noteBook $this $newFormName \
97
$formDefDict $history]
98
lappend tabList $newTab
99
set widget [$newTab cget -widget]
100
set tabObject($widget) $newTab
101
$noteBook add $widget -text $newFormName
102
$noteBook select $widget
106
public method getTabList {} {
110
public method onTabChange {} {
111
set selectedTab $tabObject([$noteBook select])
112
focus [$noteBook select]
113
$selectedTab tabSelected
117
public method setMenubar {menubar} {
118
$window configure -menu $menubar
122
public method setTitle {title} {
123
wm title $window $title
130
public variable widget
131
protected variable parent
132
protected variable formWindow
133
public variable formWinPath
134
protected variable formName
135
protected variable menubar
136
protected variable mnForm
137
protected variable title
138
protected variable tabLock 0
139
protected variable tabStatus
140
protected variable btnCloseTab
141
protected variable btnUnlockTab
142
protected variable tabStatBar
144
constructor {c_parent c_formWindow c_formName} {
146
set formWindow $c_formWindow
147
set formName $c_formName
148
set formWinPath [$formWindow cget -window]
149
set widget [ttk::frame [appendToPath $parent [namespace tail $this]] \
151
set tabStatBar [ttk::frame $widget.sb]
152
set tabStatus [ttk::label $tabStatBar.lbl -text {} \
154
set btnCloseTab [defineButton $tabStatBar.btnClose $widget \
155
btnCloseTab [list $this closeTab]]
156
$btnCloseTab configure -style SButton
157
set btnUnlockTab [defineButton $tabStatBar.btnUnlock $widget \
158
btnUnlockTab [list $this unlockTab]]
159
$btnUnlockTab configure -style SButton
160
$btnUnlockTab state {disabled}
161
grid $tabStatus -column 0 -row 0
162
grid $btnUnlockTab -column 1 -row 0 -pady {5 5}
163
grid $btnCloseTab -column 2 -row 0 -pady {5 5}
164
grid columnconfigure $tabStatBar 0 -weight 1
165
pack $tabStatBar -side top -fill x
166
set menubar [menu [appendToPath $formWinPath \
167
mb[namespace tail $this]] -tearoff 0]
168
set mnForm [menu $menubar.mnForm -tearoff 0]
169
addMenuItem $mnForm mnuUnlockTab command [list $this unlockTab]
170
$mnForm entryconfigure 0 -state disabled -accelerator {Esc}
171
addMenuItem $mnForm mnuCloseTab command [list $this closeTab]
172
$mnForm entryconfigure 1 -accelerator {Esc}
173
$mnForm add separator
174
addMenuItem $mnForm mnuCloseForm command [list destroy $formWinPath]
175
addMenuItem $menubar mnuForm cascade $mnForm
176
set title "pfm - [$::dbObject cget -dbname]: $formName"
177
bind $widget <KeyPress-Escape> [list $this onEscape]
182
# $formWindow tabDestroyed [namespace tail $this]
187
public method tabSelected {} {
188
$formWindow setMenubar $menubar
189
$formWindow setTitle $title
193
public method onEscape {} {
194
if {!$tabLock} then {
202
public method unlockTab {} {
203
$formWindow deleteTabsAbove [namespace tail $this]
208
public method closeTab {} {
209
$formWindow removeTab [namespace tail $this]
213
public method setTabLock {state} {
216
$tabStatus configure -text [mc lbTabLocked]
217
$btnCloseTab state {disabled}
218
$btnUnlockTab state {!disabled}
219
$mnForm entryconfigure 0 -state normal
220
$mnForm entryconfigure 1 -state disabled
222
$tabStatus configure -text {}
223
$btnCloseTab state {!disabled}
224
$btnUnlockTab state {disabled}
225
$mnForm entryconfigure 0 -state disabled
226
$mnForm entryconfigure 1 -state normal
228
$this propagateTabLock $state
236
protected variable formDef
237
protected variable attribDef
238
protected variable attribList
239
protected variable modAttribList
240
protected variable whereSelected 1
241
protected variable txt
242
protected variable btnRun
243
protected variable rbWhere
244
protected variable rbOrderby
245
protected variable pasteValueMenu 0
246
protected variable listBoxList {}
248
constructor {c_parent c_formWindow} \
249
{GenTab::constructor $c_parent $c_formWindow [$c_formWindow cget -formName]} {
250
getFormDef $::dbObject $formName $formWinPath formDef
251
getAttribDef $::dbObject $formName $formWinPath \
252
attribDef attribList modAttribList
260
protected method setupWidget {} {
262
set mnPasteName [menu $menubar.mnPasteName -tearoff 0]
263
foreach attrib $attribList {
264
$mnPasteName add command -label $attrib \
265
-command [list $this pasteName $attrib]
267
set mnPasteValue [menu $menubar.mnPasteValue -tearoff 0]
269
foreach attrib $attribList {
270
if {$attribDef($attrib,typeofget) in {tgLink tgList}} then {
271
$mnPasteValue add command -label $attrib \
272
-command [list $this pasteValue $attrib]
276
addMenuItem $menubar mnuPasteName cascade $mnPasteName
277
addMenuItem $menubar mnuPasteValue cascade $mnPasteValue
278
if {!$pasteValueMenu} then {
279
$menubar entryconfigure 2 -state disabled
281
set frmQuery [ttk::frame $widget.frmquery]
282
foreach field {Query Where Orderby} {
283
set txt($field) [text $frmQuery.txt$field -width 1 -height 1 \
285
set vsb($field) [ttk::scrollbar $frmQuery.vsb$field \
286
-orient vertical -command [list $txt($field) yview]]
287
$txt($field) configure -yscrollcommand [list $vsb($field) set]
289
$txt(Query) configure -takefocus 0
290
$txt(Query) insert end "SELECT $formDef(sqlselect)\n"
291
$txt(Query) insert end "FROM $formDef(sqlfrom)\n"
292
if {$formDef(groupby) ne {}} then {
293
$txt(Query) insert end "GROUP BY $formDef(groupby)\n"
295
if {$formDef(sqllimit) ne {}} then {
296
$txt(Query) insert end "LIMIT $formDef(sqllimit)\n"
298
$txt(Query) configure -state disabled \
299
-background $::readonlyBackground
300
if {$formDef(sqlorderby) ne {}} then {
301
$txt(Orderby) insert end $formDef(sqlorderby)
303
set rbWhere [ttk::radiobutton $frmQuery.rbWhere \
304
-text WHERE -underline 0 -variable [scope whereSelected] \
305
-value 1 -command [list focus $txt(Where)] -takefocus 0]
306
if {$formDef(groupby) ne {}} then {
307
$rbWhere configure -text HAVING
309
set rbOrderby [ttk::radiobutton $frmQuery.rbOrderby \
310
-text {ORDER BY} -underline 0 -variable [scope whereSelected] \
311
-value 0 -command [list focus $txt(Orderby)] -takefocus 0]
312
grid $txt(Query) -column 0 -columnspan 2 -row 0 -sticky wens
313
grid $vsb(Query) -column 2 -row 0 -sticky ns
314
grid $rbWhere -column 0 -row 1 -sticky n
315
grid $txt(Where) -column 1 -row 1 -sticky wens
316
grid $vsb(Where) -column 2 -row 1 -sticky ns
317
grid $rbOrderby -column 0 -row 2 -sticky n
318
grid $txt(Orderby) -column 1 -row 2 -sticky wens
319
grid $vsb(Orderby) -column 2 -row 2 -sticky ns
320
grid columnconfigure $frmQuery 1 -weight 1
321
grid rowconfigure $frmQuery 0 -weight 2
323
grid rowconfigure $frmQuery $row -weight 1
325
bind $txt(Where) <FocusIn> [list set [scope whereSelected] 1]
326
bind $txt(Orderby) <FocusIn> [list set [scope whereSelected] 0]
328
set btnRun [defineButton $frmQuery.btnRun $widget btnRun \
330
grid $btnRun -column 0 -columnspan 3 -row 3 -sticky e \
331
-pady {10 10} -padx {10 10}
332
pack $frmQuery -side top -expand 1 -fill both
333
# The following makes $widget receive all events that are sent
334
# to its children. This makes it possible to bind keyboard
335
# shortcuts that apply to the frame of this tab only
336
recursiveAppendTag $widget $widget
337
if {$formDef(groupby) ne {}} then {
338
bind $widget <Alt-KeyPress-h> \
339
[list $rbWhere instate {!disabled} [list $rbWhere invoke]]
341
bind $widget <Alt-KeyPress-w> \
342
[list $rbWhere instate {!disabled} [list $rbWhere invoke]]
344
bind $widget <Alt-KeyPress-o> \
345
[list $rbOrderby instate {!disabled} [list $rbOrderby invoke]]
349
public method propagateTabLock {state} {
351
$rbWhere state {disabled}
352
$rbOrderby state {disabled}
353
$txt(Where) configure -state disabled
354
$txt(Orderby) configure -state disabled
355
$btnRun state {disabled}
356
$menubar entryconfigure 1 -state disabled
357
$menubar entryconfigure 2 -state disabled
359
$rbWhere state {!disabled}
360
$rbOrderby state {!disabled}
361
$txt(Where) configure -state normal
362
$txt(Orderby) configure -state normal
363
$btnRun state {!disabled}
364
$menubar entryconfigure 1 -state normal
365
if {$pasteValueMenu} then {
366
$menubar entryconfigure 2 -state normal
372
public method onRun {} {
374
set formDef(sqlwhere) [string trim [$txt(Where) get 1.0 end]]
375
set formDef(sqlorderby) [string trim [$txt(Orderby) get 1.0 end]]
377
set history [dict create from {} link {} to [mc histOpenForm $formName]]
378
$formWindow newFormTab $formName [array get formDef] [list $history]
382
public method pasteName {attrib} {
383
if {$whereSelected} then {
384
$txt(Where) insert insert "\"${attrib}\""
386
$txt(Orderby) insert insert "\"${attrib}\""
391
public method pasteValue {attrib} {
392
switch -- $attribDef($attrib,typeofget) {
394
set query $attribDef($attrib,sqlselect)
397
set query "SELECT value, description FROM pfm_value "
398
append query "WHERE valuelist = '$attribDef($attrib,valuelist)' "
399
append query "ORDER BY value"
405
if {[$::dbObject select_query_list $query numTuples headerList valueList errMsg]} then {
406
set lsbTitle [mc selectValueFor $attrib]
407
set lsb [ListBox "#auto" $formWinPath $lsbTitle $headerList \
409
lappend listBoxList [list $lsb $attrib]
410
if {[$lsb wait result]} then {
411
if {$attribDef($attrib,typeofattrib) eq {taQuoted}} then {
412
set value "'[lindex $result 0]'"
414
set value [lindex $result 0]
416
if {$whereSelected} then {
417
$txt(Where) insert insert $value
419
$txt(Orderby) insert insert $value
422
set lsbToRemove [lsearch -exact -index 0 $listBoxList $lsb]
423
set listBoxList [lreplace $listBoxList $lsbToRemove $lsbToRemove]
425
pfm_message $errMsg $formWinPath
430
public method deleteAllListBoxes {} {
431
foreach lsb $listBoxList {
432
[lindex $lsb 0] destroyWindow
441
protected variable formDef
442
protected variable history
443
protected variable attribDef
444
protected variable attribList
445
protected variable modAttribList
446
protected variable linkDef
447
protected variable lastLink
448
protected variable frmHistory
449
protected variable txtHistory
450
protected variable canvas
451
protected variable frmForm
452
protected variable frmButtons
453
protected variable btnArray
454
protected variable btnSelect
455
protected variable txtMessages
456
protected variable control
457
protected variable formState {browse}
458
protected variable statusbar
459
protected variable sbNr
460
protected variable sbStatus
461
protected variable buffer
462
protected variable record
463
protected variable recordIdx
464
protected variable textEditList
465
protected variable listBoxList
466
protected variable matchCase 0
467
protected variable searchPattern
468
protected variable searchAttribute
469
protected variable searchFrame {}
472
constructor {c_parent c_formWindow c_formName formDefDict c_history} \
473
{GenTab::constructor $c_parent $c_formWindow $c_formName} {
474
array set formDef $formDefDict
475
set history $c_history
476
set textEditList(0) {}
477
set textEditList(1) {}
479
getAttribDef $::dbObject $formName $formWinPath \
480
attribDef attribList modAttribList
481
getLinkDef $::dbObject $formName $formWinPath linkDef lastLink
483
# "record" is a Tcl array which always contains the current
484
# record. Originally, the array elements record($attrib) were
485
# bound to the entry widgets of the form and the element names
486
# were the attribute names. However, a bug in Itcl caused the
487
# attribute value not to be displayed if the attribute name
488
# consists of more than one word. Therefore, the following work
489
# around is implemented. Instead of record($attrib),
490
# record($recordIdx($attrib)) is bound to the form's entry
491
# widgets where recordIdx acts as a conversion table which maps
492
# the attribute names ($attrib) to integers.
493
# recordIdx is initialised here.
495
foreach attrib $attribList {
496
set recordIdx($attrib) $index
500
set buffer [FormBuf "#auto" [array get formDef] [array get attribDef] \
501
$this $attribList $modAttribList]
502
$buffer getFirstRecord record recNr status
503
updateStatusBar $recNr $status
508
delete object $buffer
515
public method propagateTabLock {state} {
517
if {$formDef(view) eq {f}} then {
518
foreach op {Update Add Delete} {
519
$btnArray($op) state {disabled}
523
for {set link 0} {$link <= $lastLink} {incr link} {
524
$btnArray($link) state {disabled}
527
bind $widget <KeyPress-Next> {}
528
bind $widget <KeyPress-Prior> {}
529
bind $widget <KeyPress-Right> {}
530
bind $widget <KeyPress-Left> {}
531
bind $widget <KeyPress-Home> {}
532
bind $widget <KeyPress-End> {}
533
foreach btn {Home Prev Next End} {
534
$btnArray($btn) state {disabled}
536
bind $widget <KeyPress-F3> {}
537
if {$searchFrame ne {}} then {
538
foreach op {FindNext Hide} {
539
$btnArray($op) state {disabled}
543
if {$formDef(view) eq {f}} then {
544
foreach op {Update Add Delete} {
545
$btnArray($op) state {!disabled}
548
for {set link 0} {$link <= $lastLink} {incr link} {
549
$btnArray($link) state {!disabled}
552
bind $widget <KeyPress-Next> [list $this nextRecord]
553
bind $widget <KeyPress-Prior> [list $this prevRecord]
554
bind $widget <KeyPress-Right> [list $this nextRecord]
555
bind $widget <KeyPress-Left> [list $this prevRecord]
556
bind $widget <KeyPress-Home> [list $this firstRecord]
557
bind $widget <KeyPress-End> [list $this lastRecord]
558
foreach btn {Home Prev Next End} {
559
$btnArray($btn) state {!disabled}
561
bind $widget <KeyPress-F3> [list $this searchForRecord]
562
if {$searchFrame ne {}} then {
563
foreach op {FindNext Hide} {
564
$btnArray($op) state {!disabled}
571
public method mouseWheel {platform arg} {
584
set mouse_x [winfo pointerx $formWinPath]
585
set mouse_y [winfo pointery $formWinPath]
586
set x1 [winfo rootx $frmForm]
587
set y1 [winfo rooty $frmForm]
588
set x2 [expr $x1 + [winfo width $frmForm]]
589
set y2 [expr $y1 + [winfo height $frmForm]]
590
if {($x1 <= $mouse_x) && ($mouse_x <= $x2) && \
591
($y1 <= $mouse_y) && ($mouse_y <= $y2)} then {
592
$canvas yview scroll $direction unit
597
public method scrollForm {i} {
599
# Scroll form such that attribute i is visible in the middle
602
# Let: n1 be index of first visible attribute before scrolling
603
# n2 be index of last visible attribute before scrolling
604
# nn1 be index of first visible attribute after scrolling
605
# nn2 be index of last visible attribute after scrolling
606
# f1 = 1st fraction returned by yview before scrolling (known)
607
# f2 = 2nd fraction returned by yview before scrolling (known)
608
# nf1 = 1st fraction to be given to yview for scrolling
609
# nf2 = 2nd fraction returned by yview after scrolling
610
# n = nr of attributes on form (known)
611
# i = index of attribute with input focus (arg of function)
612
# s = number of visible attributes on screen
618
# f1 = (y-coord of first visible horizontal line)
619
# /(height of canvas)
621
# f2 = (y-coord of last visible horizontal line)
622
# /(height of canvas)
624
# -- to take into account the empty space at top and bottom
625
# -- we assume 2 dummy attributes, one at top (index "-1"),
626
# -- one at bottom (index "n")
627
# n1 = (n + 2) * f1 - 1
628
# n2 = (n + 2) * f2 - 1
630
# = (n + 2) * (f2 - f1) + 1 (1)
631
# Afters scrolling, same relationship:
632
# nn1 = (n + 2) * nf1 - 1
633
# nn2 = (n + 2) * nf2 - 1
634
# s = (n + 2) * (nf2 - nf1) + 1 (2)
635
# After scrolling we want i to be in the middle between nn1 and nn2
637
# = (nf1 + nf2) * (n + 2)/2 - 1 (3)
638
# s we can calculate with (1)
639
# From (2) and (3) it follows:
640
# nf1 = (2*i - s + 3)/(2 * (n + 2))
642
set n [llength $attribList]
643
set yviewList [$canvas yview]
644
set f1 [lindex $yviewList 0]
645
set f2 [lindex $yviewList 1]
646
set s [expr ($n + 2) * ($f2 - $f1) + 1.0]
647
set nf1 [expr (2.0*$i - $s + 3.0)/(2.0 * ($n + 2.0))]
654
$canvas yview moveto $nf1
658
public method showError {message} {
659
$txtMessages configure -state normal
660
$txtMessages insert end "${message}\n" red
662
$txtMessages configure -state disabled
667
public method showQuery {intro query result resultColor} {
668
$txtMessages configure -state normal
669
$txtMessages insert end "${intro}\n" blue
670
$txtMessages insert end "${query}\n"
671
$txtMessages insert end "${result}\n" $resultColor
673
$txtMessages configure -state disabled
674
if {$resultColor eq {red}} then {
680
public method firstRecord {} {
681
if {(!$tabLock) && ($formState eq {browse})} then {
682
$buffer getFirstRecord record recNr status
683
updateStatusBar $recNr $status
689
public method lastRecord {} {
690
if {(!$tabLock) && ($formState eq {browse})} then {
691
$buffer getLastRecord record recNr status
692
updateStatusBar $recNr $status
698
public method nextRecord {} {
699
if {(!$tabLock) && ($formState eq {browse})} then {
700
$buffer getNextRecord record recNr status
701
updateStatusBar $recNr $status
707
public method prevRecord {} {
708
if {(!$tabLock) && ($formState eq {browse})} then {
709
$buffer getPrevRecord record recNr status
710
updateStatusBar $recNr $status
716
public method onExpand {attrib} {
717
if {$formState eq {browse}} then {
722
set textEdit [TextEdit "#auto" $formWinPath $attrib \
723
$record($recordIdx($attrib)) $readOnly]
724
lappend textEditList($readOnly) [list $textEdit $attrib]
725
$textEdit defineCallBack \
726
[list $this textEditCallBack $textEdit $attrib $readOnly]
730
public method textEditCallBack {textEdit attrib readOnly} {
731
$textEdit getText record($recordIdx($attrib))
732
set itemToRemove [lsearch -exact -index 0 \
733
$textEditList($readOnly) $textEdit]
734
set textEditList($readOnly) [lreplace $textEditList($readOnly) \
735
$itemToRemove $itemToRemove]
739
public method onUpdate {} {
740
if {[$buffer getStatus] ni {statAfterLast statNotAdded statDeleted}} then {
741
# deleteAllTextEdits 1
742
set reloaded [$buffer reloadRecord record recNr status]
743
updateStatusBar $recNr $status
745
if {$reloaded} then {
748
pfm_message [mc reloadFailed] $formWinPath
754
public method onAdd {} {
755
# deleteAllTextEdits 1
756
foreach attrib $modAttribList {
757
if {$attribDef($attrib,default) ne {}} then {
758
if {[string index $attribDef($attrib,default) 0] eq {=}} then {
759
set query [string range $attribDef($attrib,default) 1 end]
760
if {[$::dbObject select_query_list $query numTuples \
761
namesList tuples errMsg]} then {
762
showQuery [mc getDefaultValue $attrib] \
763
$query [mc queryOK] green
764
if {$numTuples == 1} then {
765
set record($recordIdx($attrib)) [lindex $tuples 0 0]
767
showError [mc defaultNumTuplesErr $attrib $numTuples]
770
showQuery [mc getDefaultValue $attrib] \
774
set record($recordIdx($attrib)) $attribDef($attrib,default)
782
public method onDelete {} {
783
if {[$buffer getStatus] ni {statAfterLast statNotAdded statDeleted}} then {
784
# deleteAllTextEdits 1
785
set reloaded [$buffer reloadRecord record recNr status]
786
updateStatusBar $recNr $status
787
if {$status ni {statAfterLast statNotAdded statDeleted}} then {
788
set arg [dict create \
789
parent $formWinPath \
790
title [mc questionDeleteTitle] \
791
message [mc questionDeleteMessage] \
793
defaultButton btnNo \
794
buttonList {btnYes btnNo}]
795
set dlg [GenDialog "#auto" $arg]
796
if {[$dlg wait] eq {btnYes}} then {
797
$buffer deleteRecord record recNr status
798
updateStatusBar $recNr $status
806
public method onOK {} {
807
if {[llength $textEditList(0)] > 0} then {
809
foreach item $textEditList(0) {
810
append attributes "[lindex $item 1]\n"
812
pfm_message [mc editWindowsOpen $attributes] $formWinPath
814
if {[llength $listBoxList] > 0} then {
816
foreach item $listBoxList {
817
append attributes "[lindex $item 1]\n"
819
pfm_message [mc listBoxOpen $attributes] $formWinPath
821
switch -- $formState {
823
$buffer updateRecord record
824
$buffer reloadRecord record recNr status
825
updateStatusBar $recNr $status
829
if {[$buffer addRecord record]} then {
830
$buffer reloadRecord record recNr status
831
updateStatusBar $recNr $status
834
updateStatusBar {} statNotAdded
845
public method onCancel {} {
849
$buffer getCurRecord record recNr status
850
updateStatusBar $recNr $status
854
public method onSelect {attrib} {
855
switch -- $attribDef($attrib,typeofget) {
857
set query $attribDef($attrib,sqlselect)
860
set query "SELECT value, description FROM pfm_value "
861
append query "WHERE valuelist = '$attribDef($attrib,valuelist)' "
862
append query "ORDER BY value"
868
if {[$::dbObject select_query_list $query numTuples headerList valueList errMsg]} then {
869
set lsbTitle [mc selectValueFor $attrib]
870
set selected [lsearch -exact -index 0 $valueList $record($recordIdx($attrib))]
871
if {$selected < 0} then {
874
set lsb [ListBox "#auto" $formWinPath $lsbTitle $headerList \
875
$valueList $selected]
876
lappend listBoxList [list $lsb $attrib]
877
if {[$lsb wait result]} then {
878
set record($recordIdx($attrib)) [lindex $result 0]
880
set lsbToRemove [lsearch -exact -index 0 $listBoxList $lsb]
881
set listBoxList [lreplace $listBoxList $lsbToRemove $lsbToRemove]
883
pfm_message $errMsg $formWinPath
888
public method followLink {link} {
890
([$buffer getStatus] ni {statDeleted statAfterLast statNotAdded})} then {
893
foreach attrib $linkDef($link,displayattrib) {
894
lappend displayValues $record($recordIdx($attrib))
896
set displayValues [join $displayValues {, }]
897
append from " (${displayValues})"
898
set to "$linkDef($link,toform)"
899
set newEntry [dict create from $from link \
900
$linkDef($link,linkname) to $linkDef($link,toform)]
901
set newhistory $history
902
lappend newhistory $newEntry
903
array unset toformDef
904
if {[getFormDef $::dbObject $linkDef($link,toform) \
905
$formWinPath toformDef]} then {
906
set toformDef(sqlwhere) [expandSqlWhere $link]
907
# Next statement added for bug 1072
908
set toformDef(sqlorderby) $linkDef($link,orderby)
909
$formWindow newFormTab $linkDef($link,toform) \
910
[array get toformDef] $newhistory
916
public method onSearch {attrib} {
917
if {$searchFrame eq {}} then {
918
set searchFrame [setupsearchbar $frmHistory $attrib]
919
pack $searchFrame -side top -fill x
921
set searchAttribute $attrib
926
public method onSearchHide {} {
927
if {$searchFrame ne {}} then {
930
focus [tk_focusNext [focus]]
935
public method searchForRecord {} {
936
if {($formState eq {browse}) && ($searchFrame ne {}) && !$tabLock} then {
937
$buffer searchRecord $searchAttribute \
938
"*${searchPattern}*" $matchCase
939
$buffer getCurRecord record recNr status
940
updateStatusBar $recNr $status
946
public method onHelp {} {
947
set query "SELECT help FROM pfm_form WHERE name = '${formName}'"
948
if {[$::dbObject select_query_list $query numTuples \
949
names tuples errMsg]} then {
950
if {$numTuples == 1} then {
951
set txtEdit [TextEdit "#auto" $formWinPath \
952
[mc formHelp $formName] [lindex $tuples 0 0] 1]
955
pfm_message $errMsg $formWinPath
960
protected method setupWidget {} {
962
set vpanes [ttk::panedwindow $widget.vpanes -orient vertical]
963
set frmHistory [historyPane $vpanes]
964
set hpanes [ttk::panedwindow $vpanes.hpanes -orient horizontal]
965
set frmForm [formPane $hpanes]
966
set frmLink [linkPane $hpanes]
967
$hpanes add $frmForm -weight 6
968
$hpanes add $frmLink -weight 1
969
set frmMessages [messagePane $vpanes]
970
$vpanes add $frmHistory -weight 1
971
$vpanes add $hpanes -weight 3
972
$vpanes add $frmMessages -weight 1
973
pack $vpanes -side top -expand 1 -fill both
974
recursiveAppendTag $widget $widget
976
set bbox [$canvas bbox all]
977
set rightEdge [expr [lindex $bbox 2] + 20]
978
set bottomEdge [expr [lindex $bbox 3] + 20]
979
$canvas configure -scrollregion [list 0 0 $rightEdge $bottomEdge]
980
bind $widget <KeyPress-Next> [list $this nextRecord]
981
bind $widget <KeyPress-Prior> [list $this prevRecord]
982
bind $widget <KeyPress-Right> [list $this nextRecord]
983
bind $widget <KeyPress-Left> [list $this prevRecord]
984
bind $widget <KeyPress-Home> [list $this firstRecord]
985
bind $widget <KeyPress-End> [list $this lastRecord]
986
bind $widget <KeyPress-Up> {focus [tk_focusPrev [focus]]}
987
bind $widget <KeyPress-Down> {focus [tk_focusNext [focus]]}
992
protected method setupMenus {} {
993
set mnRecord [menu $menubar.record -tearoff 0]
994
foreach op {Update Add Delete} {
995
addMenuItem $mnRecord mnu${op}Record command [list $this on$op]
997
set mnGoTo [menu $menubar.goto -tearoff 0]
998
foreach dir {next prev first last} {
999
addMenuItem $mnGoTo mnuGoTo$dir command [list $this ${dir}Record]
1001
$mnGoTo entryconfigure 0 -accelerator {PgDn}
1002
$mnGoTo entryconfigure 1 -accelerator {PgUp}
1003
$mnGoTo entryconfigure 2 -accelerator {Home}
1004
$mnGoTo entryconfigure 3 -accelerator {End}
1005
set mnSearch [menu $menubar.search -tearoff 0]
1006
foreach attrib $attribList {
1007
$mnSearch add command -label $attrib \
1008
-command [list $this onSearch $attrib]
1010
$mnSearch add separator
1011
$mnSearch add checkbutton \
1012
-label [lindex [mcunderline mnuSearchCase] 0] \
1013
-underline [lindex [mcunderline mnuSearchCase] 1] \
1014
-variable [scope matchCase] -onvalue 1 -offvalue 0 \
1015
-indicatoron 1 -selectcolor black
1016
$mnSearch add separator
1017
addMenuItem $mnSearch mnuSearchHide command [list $this onSearchHide]
1018
addMenuItem $menubar mnuRecordMenu cascade $mnRecord
1019
addMenuItem $menubar mnuGoToMenu cascade $mnGoTo
1020
addMenuItem $menubar mnuSearchMenu cascade $mnSearch
1021
addMenuItem $menubar mnuFormHelp command [list $this onHelp]
1022
if {$formDef(view) eq {t}} then {
1023
$menubar entryconfigure 1 -state disabled
1028
protected method enableBrowseMenus {} {
1029
if {$formDef(view) eq {f}} then {
1030
$menubar entryconfigure 1 -state normal
1032
foreach item {2 3} {
1033
$menubar entryconfigure $item -state normal
1038
protected method disableBrowseMenus {} {
1039
foreach item {1 2 3} {
1040
$menubar entryconfigure $item -state disabled
1045
protected method historyPane {parent} {
1046
set frm [ttk::frame $parent.frmhistory]
1047
set frm2 [ttk::frame $frm.frm2]
1048
set txtHistory [text $frm2.txt -width 1 -height 1 \
1049
-takefocus 0 -state disabled]
1050
set vsbHistory [ttk::scrollbar $frm2.vsb -orient vertical \
1051
-command [list $txtHistory yview]]
1052
$txtHistory configure -yscrollcommand [list $vsbHistory set]
1053
$txtHistory tag configure blue -foreground {medium blue}
1054
$txtHistory tag configure red -foreground {red3}
1055
$txtHistory tag configure green -foreground {green4}
1056
pack $txtHistory -side left -expand 1 -fill both
1057
pack $vsbHistory -side left -fill y
1058
pack $frm2 -side top -expand 1 -fill both
1062
protected method formPane {parent} {
1064
set frmForm [ttk::frame $parent.frmform -borderwidth 1 -relief raised]
1066
set statusbar [ttk::frame $frmForm.sb]
1067
set frmRecNr [ttk::frame $statusbar.frmRecNr]
1068
set btnArray(Home) [ttk::button $frmRecNr.btnHome -image ::img::arrow_home \
1069
-command [list $this firstRecord] -style SButton -takefocus 0]
1070
set btnArray(Prev) [ttk::button $frmRecNr.btnPrev -image ::img::arrow_left \
1071
-command [list $this prevRecord] -style SButton -takefocus 0]
1072
set sbNr [ttk::label $frmRecNr.sbnr -text {0/0} \
1074
set btnArray(Next) [ttk::button $frmRecNr.btnNext -image ::img::arrow_right \
1075
-command [list $this nextRecord] -style SButton -takefocus 0]
1076
set btnArray(End) [ttk::button $frmRecNr.btnEnd -image ::img::arrow_end \
1077
-command [list $this lastRecord] -style SButton -takefocus 0]
1078
pack $btnArray(Home) -side left
1079
pack $btnArray(Prev) -side left
1080
pack $sbNr -side left -padx {8 8}
1081
pack $btnArray(Next) -side left
1082
pack $btnArray(End) -side left
1083
set sbForm [ttk::label $statusbar.sbform -text $formName \
1084
-foreground {medium blue}]
1085
set sbStatus [ttk::label $statusbar.sbStatus -text {state}]
1086
grid $frmRecNr -column 0 -row 0 -sticky w
1087
grid $sbForm -column 1 -row 0
1088
grid $sbStatus -column 2 -row 0 -sticky e
1089
grid columnconfigure $statusbar 0 -weight 1
1090
grid columnconfigure $statusbar 1 -weight 1
1091
grid columnconfigure $statusbar 2 -weight 1
1092
set frmBody [ttk::frame $frmForm.frmbody -borderwidth 2 \
1094
set canvas [canvas $frmBody.canvas -width 100 -height 100]
1095
set canvsb [ttk::scrollbar $frmBody.vsb -orient vertical \
1096
-command [list $canvas yview]]
1097
$canvas configure -yscrollcommand [list $canvsb set]
1098
set embWindow [formControls $canvas]
1099
$canvas create window 20 20 -window $embWindow -anchor nw
1100
pack $canvas -side left -expand 1 -fill both
1101
pack $canvsb -side left -fill y
1102
pack $statusbar -side top -fill x
1103
pack $frmBody -side top -expand 1 -fill both
1104
if {$formDef(view) eq {f}} then {
1105
set frmButtons [ttk::frame $frmForm.frmbtns]
1106
foreach op {Update Add Delete OK Cancel} {
1107
set btnArray($op) [defineButton $frmButtons.btn$op $widget btn$op \
1109
$btnArray($op) configure -style SButton
1112
foreach op {Update Add Delete} {
1113
grid $btnArray($op) -column $col -row 0 -pady {5 5}
1116
foreach op {OK Cancel} {
1117
$btnArray($op) state {disabled}
1119
grid anchor $frmButtons center
1120
pack $frmButtons -side top -fill x
1122
switch -- $tcl_platform(platform) {
1124
bind $widget <MouseWheel> [list $this mouseWheel windows %D]
1128
# On X Window system, mouse wheel sends <4> and <5> events.
1129
bind $widget <4> [list $this mouseWheel unix -1]
1130
bind $widget <5> [list $this mouseWheel unix 1]
1136
protected method formControls {parent} {
1137
set frame [ttk::frame $parent.controls]
1139
foreach attrib $attribList {
1140
set lbl [ttk::label $frame.lbl$row -text $attrib -takefocus 0]
1141
set record($recordIdx($attrib)) {}
1142
set control($attrib) [entry $frame.ent$row -width 35 \
1143
-textvariable [scope record($recordIdx($attrib))]]
1144
$control($attrib) configure -state {readonly}
1145
bind $control($attrib) <FocusIn> [list $this scrollForm $row]
1146
set btn [defineButton $frame.btn$row $control($attrib) \
1147
btnExpand [list $this onExpand $attrib]]
1148
$btn configure -style SButton
1149
if {$attribDef($attrib,typeofget) in {tgList tgLink}} then {
1150
set btnSelect($attrib) [defineButton $frame.sel$row \
1151
$control($attrib) btnSelect \
1152
[list $this onSelect $attrib]]
1153
$btnSelect($attrib) state {disabled}
1154
$btnSelect($attrib) configure -style SButton
1155
bind $control($attrib) <KeyPress-Return> \
1156
[list $btnSelect($attrib) instate {!disabled} \
1157
[list $btnSelect($attrib) invoke]]
1158
grid $lbl -column 0 -row $row -sticky w
1159
grid $control($attrib) -column 1 -row $row -sticky wens
1160
grid $btnSelect($attrib) -column 2 -row $row -sticky we
1161
grid $btn -column 3 -row $row
1163
grid $lbl -column 0 -row $row -sticky w
1164
grid $control($attrib) -column 1 -columnspan 2 \
1165
-row $row -sticky wens
1166
grid $btn -column 3 -row $row
1170
focus $control([lindex $attribList 0])
1174
protected method linkPane {parent} {
1175
set frmLink [ttk::frame $parent.frmlink -borderwidth 1 -relief raised]
1177
set frmTitle [ttk::frame $frmLink.frmtitle]
1178
set lbTitle [ttk::label $frmTitle.lbl -text [mc lbLinks]]
1179
pack $lbTitle -side top
1180
set linksBody [ttk::frame $frmLink.body -borderwidth 2 \
1182
for {set link 0} {$link<= $lastLink} {incr link} {
1183
set btnNr [expr $link + 1]
1184
set btnArray($link) [ttk::button $linksBody.btn$btnNr \
1185
-text "${btnNr}: $linkDef($link,linkname)" \
1186
-takefocus 0 -style LButton -underline 0 \
1187
-command [list $this followLink $link]]
1188
grid $btnArray($link) -column 0 -row $link -sticky we
1189
if {$btnNr < 10} then {
1190
bind $widget <Alt-KeyPress-$btnNr> \
1191
[list after 200 [list $btnArray($link) instate {!disabled} \
1192
[list $btnArray($link) invoke]]]
1195
grid anchor $linksBody center
1196
pack $frmTitle -side top -fill x
1197
pack $linksBody -side top -expand 1 -fill both
1201
protected method messagePane {parent} {
1202
set frmMessages [ttk::frame $parent.frmmsg]
1203
set txtMessages [text $frmMessages.txt -width 1 -height 1 -takefocus 0]
1204
set vsb [ttk::scrollbar $frmMessages.vsb -orient vertical \
1205
-command [list $txtMessages yview]]
1206
$txtMessages configure -yscrollcommand [list $vsb set]
1207
$txtMessages tag configure blue -foreground {medium blue}
1208
$txtMessages tag configure red -foreground {red3}
1209
$txtMessages tag configure green -foreground {green4}
1210
pack $txtMessages -side left -expand 1 -fill both
1211
pack $vsb -side left -fill y
1215
protected method setupsearchbar {parent attrib} {
1216
set searchAttribute $attrib
1217
set frm [ttk::frame $parent.frmsearch]
1218
set searchFor [ttk::label $frm.lb1 -text [mc lbSearchFor]]
1219
set searchEntry [entry $frm.entry \
1220
-textvariable [scope searchPattern]]
1221
set searchIn [ttk::label $frm.lb2 -text [mc lbSearchIn]]
1222
set searchCombo [ttk::combobox $frm.combo -values $attribList \
1223
-textvariable [scope searchAttribute] -takefocus 0]
1224
set btnArray(FindNext) [defineButton $frm.btnFindNext $widget \
1225
btnFindNext [list $this searchForRecord]]
1226
$btnArray(FindNext) configure -style SButton
1227
bind $widget <KeyPress-F3> [list $this searchForRecord]
1228
set btnCase [defineCheckbutton $frm.btncase $widget \
1229
btnMatchCase {} [scope matchCase] 1 0]
1230
set btnArray(Hide) [defineButton $frm.btnHide $widget \
1231
btnHide [list $this onSearchHide]]
1232
$btnArray(Hide) configure -style SButton
1233
recursiveAppendTag $frm $widget
1234
grid $searchIn -column 0 -row 0 -sticky w
1235
grid $searchCombo -column 1 -row 0 -sticky we
1236
grid $searchFor -column 2 -row 0 -sticky w
1237
grid $searchEntry -column 3 -row 0 -sticky we
1238
grid $btnArray(FindNext) -column 4 -row 0 -sticky e
1239
grid $btnCase -column 5 -row 0 -sticky w
1240
grid $btnArray(Hide) -column 6 -row 0 -sticky w
1241
grid columnconfigure $frm {1 3} -weight 1
1242
bind $searchEntry <KeyPress-Return> [list $this searchForRecord]
1247
protected method updateStatusBar {recNr status} {
1248
$sbNr configure -text $recNr
1249
setRecordStatus $status
1253
protected method setRecordStatus {status} {
1266
set colour {medium blue}
1273
$sbStatus configure -text [mc $status] -foreground $colour
1277
protected method expandSqlWhere {link} {
1278
set expandWhere $linkDef($link,sqlwhere)
1279
set first [string first "\$(" $expandWhere]
1280
while {$first >= 0} {
1281
set last [string first ")" $expandWhere $first]
1282
set parName [string range $expandWhere [expr $first + 2] [expr $last -1]]
1283
if {[info exists record($recordIdx($parName))]} then {
1284
set parameter [string map {' ''} $record($recordIdx($parName))]
1285
set expandWhere [string replace $expandWhere $first $last $parameter]
1288
[mc expandSqlWhereErr $linkDef($link,linkname) $parName $formName] \
1291
set first [string first "\$(" $expandWhere $last]
1296
protected method showHistory {} {
1297
$txtHistory configure -state normal
1298
$txtHistory delete 1.0 end
1300
# first entry doesn't have 'from' and 'link'. Therefore, next loop
1301
# starts from 2nd entry
1302
foreach entry [lrange $history 1 end] {
1303
set from [dict get $entry from]
1304
$txtHistory insert end "${indent}${from}\n" blue
1305
set link [dict get $entry link]
1306
$txtHistory insert end \
1307
"${indent} | ${link}\n${indent} v\n" green
1310
# The 'to' only has to be printed for the last entry. Therefoe,
1311
# it is outside the previous loop
1312
set lastEntry [lindex $history end]
1313
$txtHistory insert end "${indent}[dict get $lastEntry to]" blue
1315
$txtHistory configure -state disabled
1319
protected method setFormState {newstate} {
1320
set formState $newstate
1321
switch -- $newstate {
1329
setRecordStatus statUpdating
1336
setRecordStatus statAdding
1346
protected method disableLinkButtons {} {
1347
for {set link 0} {$link <= $lastLink} {incr link} {
1348
$btnArray($link) state {disabled}
1353
protected method enableLinkButtons {} {
1354
for {set link 0} {$link <= $lastLink} {incr link} {
1355
$btnArray($link) state {!disabled}
1360
protected method disableEditButtons {} {
1361
foreach op {OK Cancel} {
1362
$btnArray($op) state {disabled}
1363
if {$btnArray($op) in [grid slaves $frmButtons]} then {
1364
grid forget $btnArray($op)
1367
bind $widget <KeyPress-Escape> [list $this onEscape]
1369
foreach op {Update Add Delete} {
1370
$btnArray($op) state {!disabled}
1371
if {$btnArray($op) ni [grid slaves $frmButtons]} then {
1372
grid $btnArray($op) -column $col -row 0 -pady {5 5}
1376
for {set link 0} {$link <= $lastLink} {incr link} {
1377
$btnArray($link) state {!disabled}
1382
protected method enableEditButtons {} {
1383
foreach op {Update Add Delete} {
1384
$btnArray($op) state {disabled}
1385
if {$btnArray($op) in [grid slaves $frmButtons]} then {
1386
grid forget $btnArray($op)
1390
foreach op {OK Cancel} {
1391
$btnArray($op) state {!disabled}
1392
if {$btnArray($op) ni [grid slaves $frmButtons]} then {
1393
grid $btnArray($op) -column $col -row 0 -pady {5 5}
1397
bind $widget <KeyPress-Escape> [list $this onCancel]
1398
for {set link 0} {$link <= $lastLink} {incr link} {
1399
$btnArray($link) state {disabled}
1404
protected method enableEditControls {} {
1405
foreach attrib $modAttribList {
1406
if {$attribDef($attrib,typeofget) ni {tgList tgLink tgReadOnly}} {
1407
$control($attrib) configure -state normal
1409
if {$attribDef($attrib,typeofget) ne {tgReadOnly}} then {
1410
$btnSelect($attrib) state {!disabled}
1417
protected method disableEditControls {} {
1418
foreach attrib $modAttribList {
1419
if {$attribDef($attrib,typeofget) ni {tgList tgLink tgReadOnly}} {
1420
$control($attrib) configure -state readonly
1422
if {$attribDef($attrib,typeofget) ne {tgReadOnly}} then {
1423
$btnSelect($attrib) state {disabled}
1430
protected method updateAllTextEdits {readonly} {
1431
foreach item $textEditList($readonly) {
1432
[lindex $item 0] setText record($recordIdx([lindex $item 1]))
1437
protected method deleteAllTextEdits {readOnly} {
1438
foreach item $textEditList($readOnly) {
1439
[lindex $item 0] destroyWindow
1441
set textEditList($readOnly) {}
1445
protected method deleteAllListBoxes {} {
1446
foreach item $listBoxList {
1447
[lindex $item 0] destroyWindow
1456
protected variable formDef
1457
protected variable attribDef
1458
protected variable attribList
1459
protected variable modAttribList
1460
protected variable formTab
1461
protected variable buffer
1462
protected variable status
1463
protected variable bufferFilled 0
1464
protected variable curRecord
1465
protected variable lastRecord
1466
protected variable lastChunk
1467
protected variable offset
1468
protected variable recordIdx
1470
constructor {c_formDef c_attribDef c_formTab c_attribList c_modAttribList} {
1471
array set formDef $c_formDef
1472
array set attribDef $c_attribDef
1473
set attribList $c_attribList
1474
set modAttribList $c_modAttribList
1475
set formTab $c_formTab
1477
# The same calculation is done in the constructor of class FormTab.
1478
# See there for more information.
1480
foreach attrib $attribList {
1481
set recordIdx($attrib) $index
1491
proc quoteIfNecessary {tablename} {
1492
# Procedure added for bug 1071
1494
if {[string first $double $tablename] >= 0} then {
1495
# If tablename already contains double quotes, just leave it
1497
set result $tablename
1499
# replace . with "." and enclose everything in double quotes
1501
set quotedDot "\".\""
1502
set result [string map [list $dot $quotedDot] $tablename]
1503
set result "${double}${result}${double}"
1505
# puts stdout $result
1509
public method getFirstRecord {recordName recNrName statusName} {
1510
upvar $recordName record
1511
upvar $recNrName recNr
1512
upvar $statusName recordStatus
1513
if {(!$bufferFilled) || ($offset != 0)} then {
1517
getCurRecord record recNr recordStatus
1521
public method getNextRecord {recordName recNrName statusName} {
1522
upvar $recordName record
1523
upvar $recNrName recNr
1524
upvar $statusName recordStatus
1525
if {$curRecord <= [expr $lastRecord - 2]} then {
1528
if {!$lastChunk} then {
1532
set curRecord $lastRecord
1535
getCurRecord record recNr recordStatus
1539
public method getPrevRecord {recordName recNrName statusName} {
1540
upvar $recordName record
1541
upvar $recNrName recNr
1542
upvar $statusName recordStatus
1543
if {$curRecord >= 1} then {
1546
if {$offset > 0} then {
1548
set curRecord [expr $lastRecord - 1]
1551
getCurRecord record recNr recordStatus
1555
public method getLastRecord {recordName recNrName statusName} {
1556
upvar $recordName record
1557
upvar $recNrName recNr
1558
upvar $statusName recordStatus
1559
while {!$lastChunk} {
1562
set curRecord [expr $lastRecord - 1]
1563
if {$curRecord < 0} then {
1566
getCurRecord record recNr recordStatus
1570
public method getCurRecord {recordName recNrName statusName} {
1571
upvar $recordName record
1572
upvar $recNrName recNr
1573
upvar $statusName recordStatus
1575
foreach attrib $attribList {
1576
set record($recordIdx($attrib)) $buffer($curRecord,$attrib)
1578
set recordStatus $status($curRecord)
1579
# set recNr [expr $curRecord + $offset + 1]
1580
if {$lastChunk} then {
1581
set recNr "[expr $curRecord + $offset + 1]/[expr $lastRecord + $offset]"
1583
set recNr "[expr $curRecord + $offset + 1]/?"
1588
public method searchRecord {attribute pattern matchCase} {
1589
if {($curRecord == $lastRecord) && $lastChunk} then {
1593
set startSearch [expr $curRecord + 1]
1596
while {$searching} {
1598
for {set tuple $startSearch} {$tuple < $lastRecord} {incr tuple} {
1599
if {$matchCase} then {
1600
set found [string match $pattern \
1601
$buffer($tuple,$attribute)]
1603
set found [string match -nocase $pattern \
1604
$buffer($tuple,$attribute)]
1607
set curRecord $tuple
1614
if {!$lastChunk} then {
1619
set curRecord $lastRecord
1626
public method getStatus {} {
1627
return $status($curRecord)
1630
public method deleteRecord {recordName recNrName statusName} {
1631
upvar $recordName record
1632
upvar $recNrName recNr
1633
upvar $statusName recordStatus
1634
set command "DELETE FROM [quoteIfNecessary $formDef(tablename)]"
1635
append command "\nWHERE [identCurRecord 0]"
1636
if {[$::dbObject send_command $command errMsg]} then {
1637
foreach attrib $attribList {
1638
set buffer($curRecord,$attrib) {}
1639
set status($curRecord) statDeleted
1641
$formTab showQuery [mc deleteRecord] $command [mc commandOK] green
1643
$formTab showQuery [mc deleteRecord] $command $errMsg red
1645
getCurRecord record recNr recordStatus
1649
public method addRecord {recordName} {
1650
upvar $recordName record
1651
set query "INSERT INTO [quoteIfNecessary $formDef(tablename)]"
1654
foreach attrib $modAttribList {
1655
lappend attribSpec "\"${attrib}\""
1656
set value $record($recordIdx($attrib))
1657
if {$attribDef($attrib,typeofget) eq {tgExpression}} then {
1658
set value [expr $value]
1660
if {$attribDef($attrib,typeofattrib) eq {taQuoted}} then {
1661
set value "'[string map {{'} {''}} ${value}]'"
1663
lappend valueList $value
1665
append query " ([join $attribSpec {, }])"
1666
append query "\nVALUES ([join $valueList {, }])"
1667
if {[$::dbObject send_command $query errMsg]} then {
1669
$formTab showQuery [mc addRecord] $query [mc commandOK] green
1670
set curRecord $lastRecord
1672
foreach attrib $modAttribList {
1673
set buffer($curRecord,$attrib) $record($recordIdx($attrib))
1675
set status($curRecord) statAdded
1676
foreach attrib $attribList {
1677
set buffer($lastRecord,$attrib) {}
1679
set status($lastRecord) statAfterLast
1681
$formTab showQuery [mc addRecord] $query $errMsg red
1687
public method updateRecord {recordName} {
1688
upvar $recordName record
1689
if {[transactionCommand [mc startTransaction] {START TRANSACTION}]} then {
1690
if {[selectForUpdate]} then {
1691
if {[basicUpdateRecord record]} then {
1692
if {[transactionCommand [mc commitTransaction] {COMMIT}]} then {
1694
foreach attrib $modAttribList {
1695
set buffer($curRecord,$attrib) $record($recordIdx($attrib))
1697
set status($curRecord) statUpdated
1703
transactionCommand [mc rollBack] {ROLLBACK}
1707
transactionCommand [mc rollBack] {ROLLBACK}
1715
protected method basicUpdateRecord {recordName} {
1716
upvar $recordName record
1718
foreach attrib $modAttribList {
1719
if {$record($recordIdx($attrib)) ne $buffer($curRecord,$attrib)} then {
1720
set value $record($recordIdx($attrib))
1721
if {$attribDef($attrib,typeofget) eq {tgExpression}} then {
1722
set value [expr $value]
1724
if {$attribDef($attrib,typeofattrib) eq {taQuoted}} then {
1725
set value "'[string map {{'} {''}} ${value}]'"
1727
lappend updateList "\"${attrib}\" = $value"
1730
if {[llength $updateList] > 0} then {
1731
set command "UPDATE [quoteIfNecessary $formDef(tablename)]"
1732
append command "\nSET [join $updateList {, }]"
1733
append command "\nWHERE [identCurRecord 0]"
1734
if {[$::dbObject send_command $command errMsg]} then {
1736
$formTab showQuery [mc updateRecord] $command \
1737
[mc commandOK] green
1740
$formTab showQuery [mc updateRecord] $command \
1745
$formTab showError [mc noUpdates]
1750
protected method selectForUpdate {} {
1752
foreach attrib $modAttribList {
1753
lappend sqlattrib "\"${attrib}\""
1755
set sqlattrib [join $sqlattrib {, }]
1756
set query "SELECT $sqlattrib"
1757
append query "\nFROM [quoteIfNecessary $formDef(tablename)]"
1758
append query "\nWHERE [identCurRecord 0] FOR UPDATE"
1759
if {[$::dbObject select_query_list $query numTuples namesList \
1760
resultList errMsg]} then {
1761
switch -- $numTuples {
1765
foreach attrib $namesList {
1766
if {$buffer($curRecord,$attrib) ne [lindex $resultList 0 $idx]} then {
1773
$formTab showQuery [mc selectForUpdate] $query [mc queryOK] green
1776
foreach attrib $namesList {
1777
set buffer($curRecord,$attrib) [lindex $resultList 0 $idx]
1778
set status($curRecord) statNotModified
1781
$formTab showQuery [mc selectForUpdate] $query \
1782
[mc recordModified] red
1783
pfm_message [mc recordModified] [$formTab cget -formWinPath]
1788
$formTab showQuery [mc selectForUpdate] $query \
1789
[mc recordDeleted] red
1790
pfm_message [mc recordDeleted] [$formTab cget -formWinPath]
1794
$formTab showQuery [mc selectForUpdate] $query \
1795
[mc wrongNumTuples $numTuples] red
1796
pfm_message [mc wrongNumTuples $numTuples] \
1797
[$formTab cget -formWinPath]
1802
$formTab showQuery [mc selectForUpdate] $query $errMsg red
1803
pfm_message $errMsg [$formTab cget -formWinPath]
1808
protected method transactionCommand {intro command} {
1809
if {[$::dbObject send_command $command errMsg]} then {
1810
$formTab showQuery $intro $command [mc commandOK] green
1813
$formTab showQuery $intro $command $errMsg red
1819
public method reloadRecord {recordName recNrName statusName} {
1820
upvar $recordName record
1821
upvar $recNrName recNr
1822
upvar $statusName recordStatus
1823
set query "SELECT $formDef(sqlselect)"
1824
append query "\nFROM $formDef(sqlfrom) "
1825
if {$formDef(groupby) eq {}} then {
1826
append query "\nWHERE [identCurRecord 1]"
1828
append query "\nGROUP BY $formDef(groupby) "
1829
append query "\nHAVING [identCurRecord 1]"
1831
if {[$::dbObject select_query_list $query numTuples namesList \
1832
resultList errMsg]} then {
1833
switch -- $numTuples {
1836
foreach attrib $namesList {
1837
set buffer($curRecord,$attrib) [lindex $resultList 0 $idx]
1840
$formTab showQuery [mc reloadRecord] $query [mc queryOK] green
1844
$formTab showQuery [mc reloadRecord] $query \
1845
[mc recordDeleted] red
1846
foreach attrib $attribList {
1847
set buffer($curRecord,$attrib) {}
1849
set status($curRecord) statDeleted
1853
$formTab showQuery [mc reloadRecord] $query \
1854
[mc wrongNumTuples $numTuples] red
1859
$formTab showQuery [mc reloadRecord] $query $errMsg red
1862
getCurRecord record recNr recordStatus
1866
protected method identCurRecord {withTable} {
1868
set table [quoteIfNecessary $formDef(tablename)]
1869
foreach pkey $formDef(pkey) {
1870
if {$attribDef($pkey,typeofattrib) eq {taQuoted}} then {
1871
set value "'[string map {{'} {''}} $buffer($curRecord,$pkey)]'"
1873
set value $buffer($curRecord,$pkey)
1875
if {$withTable} then {
1876
lappend whereClause "(${table}.\"${pkey}\" = $value)"
1878
lappend whereClause "(\"${pkey}\" = $value)"
1881
return [join $whereClause { AND }]
1884
protected method loadDataChunk {arg} {
1890
if {$formDef(sqllimit) ne {}} then {
1891
incr offset $formDef(sqllimit)
1895
if {$formDef(sqllimit) ne {}} then {
1896
incr offset -$formDef(sqllimit)
1897
if {$offset < 0} then {
1903
set query "SELECT $formDef(sqlselect)"
1904
append query "\nFROM $formDef(sqlfrom)"
1905
if {$formDef(groupby) ne {}} then {
1906
append query "\nGROUP BY $formDef(groupby)"
1907
if {$formDef(sqlwhere) ne {}} then {
1908
append query "\nHAVING $formDef(sqlwhere)"
1911
if {$formDef(sqlwhere) ne {}} then {
1912
append query "\nWHERE $formDef(sqlwhere)"
1915
if {$formDef(sqlorderby) ne {}} then {
1916
append query "\nORDER BY $formDef(sqlorderby)"
1918
if {$formDef(sqllimit) ne {}} then {
1919
append query "\nLIMIT $formDef(sqllimit) OFFSET $offset"
1923
if {[$::dbObject select_query $query lastRecord buffer errMsg]} then {
1924
if {$formDef(sqllimit) ne {}} then {
1925
set lastChunk [expr $lastRecord < $formDef(sqllimit)]
1929
if {[checkResult errMsg]} then {
1930
$formTab showQuery [mc loadDataChunk] $query [mc queryOK] green
1932
$formTab showQuery [mc loadDataChunk] $query $errMsg red
1938
$formTab showQuery [mc loadDataChunk] $query $errMsg red
1941
for {set tuple 0} {$tuple < $lastRecord} {incr tuple} {
1942
set status($tuple) statNotModified
1944
foreach attrib $attribList {
1945
set buffer($lastRecord,$attrib) {}
1947
set status($lastRecord) statAfterLast
1951
protected method checkResult {errMsgName} {
1952
upvar $errMsgName errMsg
1955
if {$lastRecord > 0} then {
1956
foreach attrib $attribList {
1957
if {![info exists buffer(0,$attrib)]} then {
1959
append errMsg "[mc attribMissing $attrib]\n"
1960
for {set tuple 0} {$tuple < $lastRecord} {incr tuple} {
1961
set buffer($tuple,$attrib) {}
1965
foreach attrib $formDef(pkey) {
1966
if {![info exists buffer(0,$attrib)]} then {
1968
append errMsg "[mc pkeyMissing $attrib]\n"
1969
for {set tuple 0} {$tuple < $lastRecord} {incr tuple} {
1970
set buffer($tuple,$attrib) {}
1973
if {$attrib ni $attribList} then {
1974
append errMsg "[mc attribDefPkeyMissing $attrib]\n"
1975
set attribDef($attrib,typeofattrib) taQuoted
1976
set attribbDef($attrib,typeofget) tgDirect