5 namespace eval ::maint {}
18 proc ::maint::SetGameFlags {flag type value} {
19 if {$flag == "mark"} {
set flag $::maintFlag}
33 sc_base gameflag $base "dbfilter" $op $flag
39 sc_base gameflag $base "all" $op $flag
49 set maintFlaglist {W B M E N P T Q K ! ? U 1 2 3 4 5 6}
50 array set maintFlags {
78 proc ::maint::OpenClose {} {
79 global maintWin maintFlag maintFlags maintFlaglist
81 if {[
winfo exists $w]} {
88 set bold font_SmallBold
90 wm title $w "Scid: [
tr FileMaint]"
92 bind $w <F1> {helpWindow Maintenance}
93 bind $w <Escape> "destroy $w; break"
94 bind $w <Destroy> {set maintWin 0}
97 ttk::label $w.title.name -text "[
tr Database]:"
98 ttk::label $w.title.vname -text "0" -font font_Bold
99 ttk::label $w.title.icon
100 ttk::button $w.title.vicon -command {changeBaseType [sc_base current]}
101 grid $w.title.vicon -rowspan 2 -padx "0 10"
102 grid $w.title.name -row 0 -column 1 -sticky w
103 grid $w.title.vname -row 1 -column 1 -sticky nw
104 grid columnconfigure $w.title 1 -weight 1
107 ttk::label $w.stats.games -textvar ::tr(NumOfGames) -font font_SmallBold
108 ttk::label $w.stats.vgames -text "0" -font font_SmallBold
109 ttk::label $w.stats.mark -font $font
110 ttk::label $w.stats.vmark -text "0" -font $font
111 ttk::label $w.stats.filter -textvar ::tr(NumFilterGames) -font $font
112 ttk::label $w.stats.vfilter -text "0" -font $font
113 ttk::label $w.stats.dates -textvar ::tr(YearRange) -font $font
114 ttk::label $w.stats.vdates -text "0" -font $font
115 ttk::label $w.stats.ratings -textvar ::tr(RatingRange) -font $font
116 ttk::label $w.stats.vratings -text "0" -font $font
117 grid $w.stats.games x x $w.stats.dates x x $w.stats.ratings -row 0 -sticky w
118 grid x $w.stats.vgames x x $w.stats.vdates x x $w.stats.vratings -row 0 -sticky e
119 grid x x x $w.stats.mark x x $w.stats.filter -row 1 -sticky w
120 grid x x x x $w.stats.vmark x x $w.stats.vfilter -row 1 -sticky e
121 grid columnconfigure $w.stats 2 -weight 1
122 grid columnconfigure $w.stats 5 -weight 1
125 ttk::label $w.dbdesc.lab -text $::tr(Description:) -font font_SmallBold
126 ttk::entry $w.dbdesc.text -textvariable ::maint::dbdesc -validate key -validatecommand "
127 $w.dbdesc.edit configure -state normal
130 ttk::button $w.dbdesc.edit -text "[
tr Save]" -style Small.TButton -command {
131 if { [catch {sc_base extra $::curr_db description $::maint::dbdesc}] } {
136 grid $w.dbdesc.lab $w.dbdesc.text -padx "0 5" -sticky we
137 grid $w.dbdesc.edit -row 0 -column 2 -sticky e
138 grid columnconfigure $w.dbdesc 1 -weight 1
140 ttk::frame $w.customFlags
141 ttk::label $w.customFlags.lab -text "[
::tr CustomFlags]:" -font font_SmallBold
142 ttk::entry $w.customFlags.text1 -width 8 -validate key -validatecommand "::maint::validateCustomFlag $w %P"
143 ttk::entry $w.customFlags.text2 -width 8 -validate key -validatecommand "::maint::validateCustomFlag $w %P"
144 ttk::entry $w.customFlags.text3 -width 8 -validate key -validatecommand "::maint::validateCustomFlag $w %P"
145 ttk::entry $w.customFlags.text4 -width 8 -validate key -validatecommand "::maint::validateCustomFlag $w %P"
146 ttk::entry $w.customFlags.text5 -width 8 -validate key -validatecommand "::maint::validateCustomFlag $w %P"
147 ttk::entry $w.customFlags.text6 -width 8 -validate key -validatecommand "::maint::validateCustomFlag $w %P"
148 ttk::button $w.customFlags.edit -text "[
tr Save]" -style Small.TButton -command "::maint::saveCustomFlags $w"
149 grid $w.customFlags.lab $w.customFlags.text1 $w.customFlags.text2 $w.customFlags.text3 \
150 $w.customFlags.text4 $w.customFlags.text5 $w.customFlags.text6 -padx "0 5"
151 grid $w.customFlags.edit -row 0 -column 7 -sticky e
152 grid columnconfigure $w.customFlags 7 -weight 1
155 ttk::label $w.autog.lab -text $::tr(AutoloadGame:) -font font_SmallBold
156 ttk::entry $w.autog.text -width 10 -justify right -textvariable autoloadGame -validate key -validatecommand {
157 if {![string is integer %P]} { return false }
158 .maintWin.autog.edit configure -state normal
161 ttk::button $w.autog.current -text $::tr(Current) -style Small.TButton -command {
162 set ::autoloadGame [sc_game number]
163 .maintWin.autog.edit configure -state normal
165 ttk::button $w.autog.edit -text "[
tr Save]" -style Small.TButton -command {
166 sc_base extra $::curr_db autoload $::autoloadGame
169 grid $w.autog.lab $w.autog.text $w.autog.current -padx "0 5"
170 grid $w.autog.edit -row 0 -column 3 -sticky e
171 grid columnconfigure $w.autog 3 -weight 1
174 ttk::labelframe $w.dm.delete -text [
tr DeleteFlag]
175 ttk::labelframe $w.dm.mark -text [
tr Flag]
176 ttk::labelframe $w.dm.spell -text [
tr Spellchecking]
177 ttk::labelframe $w.dm.db -text [
tr DatabaseOps]
178 grid $w.dm.delete -row 0 -column 0 -sticky snwe -padx "0 10" -pady "0 10"
179 grid $w.dm.mark -row 0 -column 1 -sticky snwe -pady "0 10"
180 grid $w.dm.spell -row 1 -column 0 -sticky snwe -padx "0 10"
181 grid $w.dm.db -row 1 -column 1 -sticky snwe
182 grid columnconfigure $w.dm 0 -weight 1
183 grid columnconfigure $w.dm 1 -weight 1
185 foreach grid {dm.mark dm.spell dm.db} cols {2 2 2} {
186 for {
set i 0} {$i < $cols} {
incr i} {
187 grid columnconfigure $w.$grid $i -weight 1
191 ttk::label $w.dm.delete.vdelete
192 ttk::menubutton $w.dm.mark.title -menu $w.dm.mark.title.m
193 menu $w.dm.mark.title.m -font $font
195 foreach flag $maintFlaglist {
196 $w.dm.mark.title.m add command -label $flag -command "set maintFlag $flag; ::maint::Refresh"
199 foreach flag {delete mark} on {Delete Mark} off {Undelete Unmark} {
201 foreach b {Current Filter All} {
202 ttk::button $w.dm.$flag.on$b -textvar "::tr($on$b)" -style Small.TButton -command "::maint::SetGameFlags $flag [
string tolower $b] 1"
203 ttk::button $w.dm.$flag.off$b -textvar "::tr($off$b)" -style Small.TButton -command "::maint::SetGameFlags $flag [
string tolower $b] 0"
206 if { $flag eq "mark" } {
207 grid $w.dm.$flag.title -columnspan 2 -row 0 -column 0 -sticky we -padx 30 -pady "0 5"
209 grid $w.dm.$flag.vdelete -columnspan 2 -sticky w
212 grid $w.dm.$flag.onCurrent -row $row -column 0 -sticky we -padx "0 5" -pady "0 5"
213 grid $w.dm.$flag.offCurrent -row $row -column 1 -sticky we -pady "0 5"
215 grid $w.dm.$flag.onFilter -row $row -column 0 -sticky we -padx "0 5" -pady "0 5"
216 grid $w.dm.$flag.offFilter -row $row -column 1 -sticky we -pady "0 5"
218 grid $w.dm.$flag.onAll -row $row -column 0 -sticky we -padx "0 5" -pady "0 5"
219 grid $w.dm.$flag.offAll -row $row -column 1 -sticky we -pady "0 5"
221 grid rowconfigure $w.dm.delete 0 -weight 1
222 grid columnconfigure $w.dm.delete 0 -weight 1
223 grid columnconfigure $w.dm.delete 1 -weight 1
226 ttk::button $w.dm.spell.player -textvar ::tr(Players...) -style Small.TButton \
227 -command "openSpellCheckWin Player $w"
228 ttk::button $w.dm.spell.event -textvar ::tr(Events...) -style Small.TButton \
229 -command "openSpellCheckWin Event $w"
230 ttk::button $w.dm.spell.site -textvar ::tr(Sites...) -style Small.TButton \
231 -command "openSpellCheckWin Site $w"
232 ttk::button $w.dm.spell.round -textvar ::tr(Rounds...) -style Small.TButton \
233 -command "openSpellCheckWin Round $w"
234 grid $w.dm.spell.player -row 0 -column 0 -sticky we -padx "0 5" -pady "0 5"
235 grid $w.dm.spell.event -row 0 -column 1 -sticky we -pady "0 5"
236 grid $w.dm.spell.site -row 1 -column 0 -sticky we -padx "0 5" -pady "0 5"
237 grid $w.dm.spell.round -row 1 -column 1 -sticky we -pady "0 5"
239 bind $w <Alt-p> "$w.dm.spell.player invoke"
240 bind $w <Alt-e> "$w.dm.spell.event invoke"
241 bind $w <Alt-s> "$w.dm.spell.site invoke"
242 bind $w <Alt-r> "$w.dm.spell.round invoke"
244 ttk::button $w.dm.db.eco -style Small.TButton -textvar ::tr(ReclassifyGames...) -command classifyAllGames
245 ttk::button $w.dm.db.compact -style Small.TButton -textvar ::tr(CompactDatabase...) -command compactDB
246 ttk::button $w.dm.db.elo -style Small.TButton -textvar ::tr(AddEloRatings...) -command allocateRatings
247 ttk::button $w.dm.db.dups -style Small.TButton -textvar ::tr(DeleteTwins...) -command "markTwins $w"
248 ttk::button $w.dm.db.cleaner -style Small.TButton -textvar ::tr(Cleaner...) -command cleanerWin
249 ttk::button $w.dm.db.strip -style Small.TButton -textvar ::tr(StripTags...) -command stripTags
251 foreach i {eco compact elo dups cleaner strip} {
252 $w.dm.db.$i configure -style Small.TButton
254 bind $w <Alt-d> "$w.dm.db.dups invoke"
256 grid $w.dm.db.eco -row 0 -column 0 -sticky we -padx "0 5" -pady "0 5"
257 grid $w.dm.db.elo -row 0 -column 1 -sticky we -pady "0 5"
258 grid $w.dm.db.dups -row 1 -column 0 -sticky we -padx "0 5" -pady "0 5"
259 grid $w.dm.db.strip -row 1 -column 1 -sticky we -pady "0 5"
260 grid $w.dm.db.compact -row 2 -column 0 -sticky we -padx "0 5" -pady "0 5"
261 grid $w.dm.db.cleaner -row 2 -column 1 -sticky we -pady "0 5"
263 grid $w.title -sticky news
264 grid $w.stats -pady 5 -sticky news
265 grid $w.dbdesc -sticky news
266 grid $w.autog -pady 5 -sticky news
267 grid $w.customFlags -sticky news
268 grid $w.dm -pady "10 0" -sticky news
273 proc ::maint::validateCustomFlag {w val} {
274 if {[
string length $val] > 8} {
return false}
275 $w.customFlags.edit configure -state normal
278 proc ::maint::saveCustomFlags {w} {
279 for {
set i 1} {$i <7} {
incr i} {
280 set desc [$w.customFlags.text$i get]
281 sc_base extra $::curr_db flag$i $desc
286 proc ::maint::Refresh {} {
287 global maintFlag maintFlags
291 if {![
winfo exists $w]} {
return}
292 set ::curr_db [
sc_base current]
293 set ng [
sc_base numGames $::curr_db]
294 set dates [
sc_base stats $::curr_db dates]
295 set deleted [
sc_base stats $::curr_db flag D]
296 set marked [
sc_base stats $::curr_db flag $maintFlag]
297 set flags [
sc_base stats $::curr_db flags]
298 set ratings [
sc_base stats $::curr_db ratings]
299 $w.title.vicon configure -image dbt0
300 $w.title.vname configure -text [
file tail [
sc_base filename $::curr_db]]
305 $w.stats.vdates configure \
306 -text "[
lindex $dates 0]-[
lindex $dates 1] ([
lindex $dates 2])"
307 $w.stats.vratings configure \
308 -text "[
lindex $ratings 0]-[
lindex $ratings 1] ([
lindex $ratings 2])"
311 foreach flag $::maintFlaglist {
312 $w.dm.mark.title.m entryconfigure $i -label "[
tr $maintFlags($flag)] ($flag)"
316 grid remove $w.dbdesc
318 grid remove $w.customFlags
319 foreach {tagname tagvalue} [
sc_base extra $::curr_db] {
320 if {$tagname eq "type"} {
321 catch { $w.title.vicon configure -image dbt$tagvalue}
322 }
elseif {$tagname eq "description"} {
323 set ::maint::dbdesc $tagvalue
325 }
elseif {$tagname eq "autoload" } {
326 set ::autoloadGame $tagvalue
328 }
elseif { [regexp {flag([1-6])} $tagname -> i] } {
329 $w.customFlags.text$i configure -state normal
330 $w.customFlags.text$i delete 0 end
331 $w.customFlags.text$i insert end $tagvalue
333 if {$tagvalue ne ""} {
334 $w.dm.mark.title.m entryconfigure [
expr $i + 11] -label "$tagvalue ($i)"
339 set idx [lsearch -exact $::maintFlaglist $::maintFlag]
341 set flagname [$w.dm.mark.title.m entrycget $idx -label]
342 $w.stats.mark configure -text $flagname
343 $w.dm.mark.title configure -text $flagname
347 set state [
expr {[sc_base isReadOnly $::curr_db] ? "disabled" : "normal"}]
348 foreach frame {title dbdesc autog customFlags} {
349 foreach widget [
winfo children $w.$frame] {
350 if {[
winfo class $widget] eq "TLabel"} { continue}
351 $widget configure -state $state
354 $w.dbdesc.edit configure -state disabled
355 $w.autog.edit configure -state disabled
356 $w.customFlags.edit configure -state disabled
358 set state [
expr {$state eq "disabled" || $ng == 0 ? "disabled" : "normal"}]
359 foreach frame {dm.delete dm.mark dm.spell dm.db} {
360 foreach widget [
winfo children $w.$frame] {
361 if {[
winfo class $widget] eq "TLabel"} { continue}
362 $widget configure -state $state
365 if {$state eq "normal" && ![
sc_game number]} {
366 $w.dm.delete.onCurrent configure -state disabled
367 $w.dm.delete.offCurrent configure -state disabled
368 $w.dm.mark.onCurrent configure -state disabled
369 $w.dm.mark.offCurrent configure -state disabled
372 $w.dm.db.compact configure -state disabled
373 $w.dm.db.cleaner configure -state disabled
382 proc markTwins {{parent .}} {
384 if {[
sc_base numGames $::curr_db] == 0} {
385 tk_messageBox -type ok -icon info -title [
concat "Scid: " $::tr(noGames)] \
386 -message $::tr(TwinCheckNoDelete)
391 if {! [
winfo exists $w]} {
394 wm title $w "Scid: $::tr(DeleteTwins)"
395 pack [ttk::frame $w.f]
398 ttk::label $w.f.note -text $::tr(TwinsNote) -justify left -wraplength 300 -font $small
399 pack $w.f.note -side top -anchor w -ipady 0 -pady 0
400 ttk::labelframe $w.f.g -text $::tr(TwinsCriteria)
401 pack $w.f.g -side top -anchor w -fill x -pady 10
404 foreach name {Colors Event Day Result Round Month ECO Site Year Moves} {
405 set n [
string tolower $name]
406 ttk::checkbutton $w.f.g.b$n -text $::tr(Twins$name) \
407 -variable twinSettings($n) -onvalue Yes -offvalue No
408 grid $w.f.g.b$n -row $row -column $col -sticky w
413 grid [ttk::label $w.f.g.space$n -text " "] -row $row -column $col
418 pack $w.f.pg -side top -anchor w -pady 10 -fill x
419 ttk::labelframe $w.f.pg.players -text $::tr(TwinsPlayers)
420 ttk::radiobutton $w.f.pg.players.yes -variable twinSettings(players) -value Yes \
421 -text $::tr(TwinsPlayersExact) -style Small.TRadiobutton
422 ttk::radiobutton $w.f.pg.players.no -variable twinSettings(players) -value No \
423 -text $::tr(TwinsPlayersPrefix) -style Small.TRadiobutton
425 pack $w.f.pg.players.yes $w.f.pg.players.no -side top -anchor w
428 ttk::labelframe $w.f.pg.g2 -text $::tr(TwinsWhich)
429 pack $w.f.pg.players $w.f.pg.g2 -side left -anchor w -fill x -padx "0 15"
430 ttk::radiobutton $w.f.pg.g2.exall -text $::tr(SelectAllGames) -style Small.TRadiobutton \
431 -variable twinSettings(usefilter) -value No
432 ttk::radiobutton $w.f.pg.g2.exfil -text $::tr(SelectFilterGames) -style Small.TRadiobutton \
433 -variable twinSettings(usefilter) -value Yes
434 pack $w.f.pg.g2.exall $w.f.pg.g2.exfil -side top -fill x -anchor w
436 ttk::labelframe $w.f.g3 -text $::tr(TwinsWhen)
437 pack $w.f.g3 -side top -fill x
439 foreach n {skipshort undelete setfilter comments variations} \
440 name {SkipShort Undelete SetFilter Comments Vars} {
441 ttk::checkbutton $w.f.g3.b$n -text $::tr(Twins$name) -variable twinSettings($n) -onvalue Yes -offvalue No
442 grid $w.f.g3.b$n -row $row -column 0 -sticky w
445 ttk::label $w.f.g3.ldelete -text $::tr(TwinsDeleteWhich) -font font_Bold
446 grid $w.f.g3.ldelete -row 0 -column 1 -sticky w -padx "15 0"
449 foreach v {Shorter Older Newer} {
450 ttk::radiobutton $w.f.g3.v$v -text $::tr(TwinsDelete$v) \
451 -variable twinSettings(delete) -value $v -style Small.TRadiobutton
452 grid $w.f.g3.v$v -row $row -column 1 -padx "25 0" -sticky w
457 dialogbutton $w.f.b.defaults -textvar ::tr(Defaults) -command {
458 array set twinSettings [array get twinSettingsDefaults]
460 dialogbuttonsmall $w.f.b.help [ list -text $::tr(Help) -command "helpWindow Maintenance Twins; focus $w"]
462 if {[twinCriteriaOK .twinSettings]} {
463 grab release .twinSettings
464 .twinSettings.f.b.cancel configure -command "progressBarCancel"
465 set result [doMarkDups .twinSettings]
467 destroy .twinSettings
469 ::notify::DatabaseChanged
470 set gn [sc_filter first]
477 dialogbuttonsmall $w.f.b.cancel [ list -text $::tr(Cancel) -command "grab release $w; focus .; destroy $w"]
479 canvas $w.f.progress -width 300 -height 20 -bg white -relief solid -border 1
480 $w.f.progress create rectangle 0 0 0 0 -fill blue -outline blue -tags bar
481 $w.f.progress create text 295 10 -anchor e -font font_Regular -tags time \
482 -fill black -text "0:00 / 0:00"
484 pack $w.f.progress -side bottom -padx 2 -pady 2
485 pack $w.f.b -side bottom -fill x
487 pack $w.f.b.defaults $w.f.b.help -side left -padx 5 -pady "15 5"
488 bind $w <F1> "$w.f.b.help invoke"
489 bind $w <Escape> "$w.f.b.cancel invoke"
490 bind $w <Return> "$w.f.b.go invoke"
493 $w.f.note configure -wraplength [
winfo width $w]
502 proc twinCriteriaOK {{parent .}} {
505 set msg $::tr(TwinCriteria1)
509 if {$twinSettings(moves) == "No"} {
510 if {$twinSettings(colors) == "No" || $twinSettings(event) == "No" || \
511 $twinSettings(site) == "No" || $twinSettings(year) == "No" || \
512 $twinSettings(month) == "No"} {
513 append msg $::tr(TwinCriteria2)
514 set result [
tk_messageBox -type yesno -parent $parent -icon warning \
515 -title $::tr(TwinCriteriaConfirm) \
517 if {$result == "no"} {
return 0}
else {
return 1}
523 if {$twinSettings(site) == "Yes"} {
incr count}
524 if {$twinSettings(round) == "Yes"} {
incr count}
525 if {$twinSettings(year) == "Yes"} {
incr count}
527 append msg $::tr(TwinCriteria3)
528 set result [
tk_messageBox -type yesno -parent $parent -icon warning \
529 -title $::tr(TwinCriteriaConfirm) \
531 if {$result == "no"} {
return 0}
else {
return 1}
537 proc doMarkDups {{parent .}} {
540 if {$twinSettings(undelete) == "Yes"} {
550 -colors $twinSettings(colors) \
551 -event $twinSettings(event) -site $twinSettings(site) \
552 -round $twinSettings(round) -year $twinSettings(year) \
553 -month $twinSettings(month) -day $twinSettings(day) \
554 -result $twinSettings(result) -eco $twinSettings(eco) \
555 -moves $twinSettings(moves) -players $twinSettings(players) \
556 -skipshort $twinSettings(skipshort) \
557 -setfilter $twinSettings(setfilter) \
558 -usefilter $twinSettings(usefilter) \
559 -comments $twinSettings(comments) \
560 -variations $twinSettings(variations) \
561 -delete $twinSettings(delete)} result]} {
565 set message [subst $::tr(TwinCheckFound1)]
566 if {$result > 0} {
append message $::tr(TwinCheckFound2)}
568 tk_messageBox -type ok -parent $parent -icon info -title [
concat "Scid: " $::tr(Result)] \
576 set classifyOption(AllGames) all
577 set classifyOption(ExtendedCodes) 1
584 proc classifyAllGames {} {
588 proc makeClassifyWin {} {
589 global classifyOption
591 if {[
winfo exists $w]} {
596 wm title $w "Scid: [
tr FileMaintClass]"
598 pack [ttk::frame $w.f] -expand 1
599 ttk::labelframe $w.f.g -text $::tr(ClassifyWhich)
600 ttk::radiobutton $w.f.g.all -textvar ::tr(ClassifyAll) -variable classifyOption(AllGames) -value all
601 ttk::radiobutton $w.f.g.filter -textvar ::tr(SelectFilterGames) -variable classifyOption(AllGames) -value filter
605 ttk::radiobutton $w.f.g.year -textvar ::tr(ClassifyYear) -variable classifyOption(AllGames) \
606 -value "date:[
expr $year - 1].$month.$day"
607 if {$month == "01"} {
611 scan $month "%02u" month
613 set month [
format "%02u" $month]
615 ttk::radiobutton $w.f.g.month -textvar ::tr(ClassifyMonth) -variable classifyOption(AllGames) \
616 -value "date:$year.$month.$day"
617 ttk::radiobutton $w.f.g.new -textvar ::tr(ClassifyNew) -variable classifyOption(AllGames) -value nocode
619 foreach f {all filter year month new} {
620 grid $w.f.g.$f -row $row -column 0 -sticky w
623 ttk::labelframe $w.f.codes -text $::tr(ClassifyCodes)
624 ttk::radiobutton $w.f.codes.extended -textvar ::tr(ClassifyBasic) -variable classifyOption(ExtendedCodes) -value 0
625 ttk::radiobutton $w.f.codes.basic -textvar ::tr(ClassifyExtended) -variable classifyOption(ExtendedCodes) -value 1
628 ttk::button $w.f.b.go -textvar ::tr(Classify) -command {
629 .classify.f.b.cancel configure -command "progressBarCancel"
630 .classify.f.b.cancel configure -textvar ::tr(Stop)
631 progressBarSet .classify.f.progress 301 21
632 grab .classify.f.b.cancel
633 if {[catch {sc_eco base $classifyOption(AllGames) $classifyOption(ExtendedCodes)} result]} {
634 grab release .classify.f.b.cancel
637 grab release .classify.f.b.cancel
639 .classify.f.b.cancel configure -command {focus .; destroy .classify}
640 .classify.f.b.cancel configure -textvar ::tr(Close)
641 ::windows::gamelist::Refresh
643 ttk::button $w.f.b.cancel -textvar ::tr(Close) -command "focus .; destroy $w"
644 canvas $w.f.progress -width 300 -height 20 -bg white -relief solid -border 1
645 $w.f.progress create rectangle 0 0 0 0 -fill blue -outline blue -tags bar
646 $w.f.progress create text 295 10 -anchor e -font font_Regular -tags time \
647 -fill black -text "0:00 / 0:00"
649 pack $w.f.g -anchor w -fill x -side top -pady "0 10"
651 pack $w.f.codes -side top -pady 10 -anchor w -fill x
652 pack $w.f.codes.extended $w.f.codes.basic -side top -anchor w -fill x
653 pack $w.f.b -side top -fill x
655 pack $w.f.progress -side bottom -padx 2 -pady 2
657 bind $w <F1> {helpWindow ECO}
658 bind $w <Escape> "$w.b.cancel invoke"
662 proc updateClassifyWin {} {
664 if {! [
winfo exists $w]} {
return}
666 if {[
sc_base inUse]} {
set state normal}
667 $w.f.b.go configure -state $state
673 set twincheck(left) 0
674 set twincheck(right) 0
676 proc updateTwinChecker {} {
679 if {![
winfo exists $w]} {
681 pack [ttk::frame $w.b] -side bottom -fill x
682 pack [ttk::frame $w.f] -side top -fill both -expand yes
684 pack $w.f.left -side left -fill y -expand yes
685 ttk::frame $w.f.right
686 pack $w.f.right -side left -fill y -expand yes -padx "10 0"
687 foreach i {left right} {
689 pack [ttk::frame $f.title] -side top -fill x
690 ttk::label $f.title.label -font font_Bold -text [
concat $::tr(game) " 0: "]
691 ttk::checkbutton $f.title.d -text $::tr(Deleted) -variable twincheck($i) -style Small.TCheckbutton
692 ttk::label $f.title.note -font font_Small
693 pack $f.title.label $f.title.d $f.title.note -side left
694 ttk::label $f.tmt -font font_Small -text "" -anchor w
695 pack $f.tmt -side bottom -fill x
697 -height 16 -width 40 -background white \
698 -takefocus 0 -wrap word
699 $f.t.text tag configure h -background lightSteelBlue
700 pack $f.t -side top -fill both -expand yes
702 $w.f.left.title.note configure -text [
concat "(\"1\"" $::tr(TwinCheckUndelete)]
703 $w.f.right.title.note configure -text [
concat "(\"2\"" $::tr(TwinCheckUndelete)]
704 ttk::button $w.b.prev -text $::tr(TwinCheckprevPair) \
705 -command {::game::LoadNextPrev previous}
706 ttk::button $w.b.next -text $::tr(TwinChecknextPair) -underline 0 \
707 -command {::game::LoadNextPrev next}
708 ttk::button $w.b.share -text $::tr(TwinCheckTag) -underline 0
709 ttk::button $w.b.delete -text $::tr(DeleteTwins) -underline 0 \
710 -command "markTwins $w"
711 ttk::button $w.b.help -text $::tr(Help) -command {helpWindow Maintenance Twins}
712 ttk::button $w.b.close -text $::tr(Close) -command "focus .; destroy $w"
714 pack $w.b.prev $w.b.next $w.b.share -side left -padx 5 -pady "15 5"
715 bind $w <F1> "$w.b.help invoke"
716 bind $w <Escape> "focus .; destroy $w"
717 bind $w <Alt-p> {::game::LoadNextPrev previous}
718 bind $w <KeyPress-p> {::game::LoadNextPrev previous}
719 bind $w <Alt-n> {::game::LoadNextPrev next}
720 bind $w <KeyPress-n> {::game::LoadNextPrev next}
721 bind $w <Alt-d> "markTwins $w"
722 bind $w <KeyPress-d> "markTwins $w"
723 bind $w <KeyPress-1> "$w.f.left.title.d invoke"
724 bind $w <KeyPress-$::MB2> "$w.f.right.title.d invoke"
725 bind $w <KeyPress-s> "$w.b.share invoke"
726 bind $w <KeyPress-u> {
727 if {$twincheck(left)} {.twinchecker.f.left.title.d invoke}
728 if {$twincheck(right)} {.twinchecker.f.right.title.d invoke}
731 if {$twincheck(left)} {.twinchecker.f.left.title.d invoke}
732 if {$twincheck(right)} {.twinchecker.f.right.title.d invoke}
735 wm title $w $::tr(TwinChecker)
741 set dup [
sc_game info duplicate]
743 set twincheck(left) 0
744 set twincheck(right) 0
746 $w.f.left.title.label configure -text [
concat $::tr(game) " $gn: "]
749 set twincheck(left) [
sc_base gameflag [
sc_base current] $gn get del]
750 $w.f.left.title.d configure -command "sc_base gameflag \[sc_base current\] $gn invert del; ::notify::GameChanged"
751 $w.f.left.title.d configure -state normal
752 set tmt [
sc_game crosstable count +deleted]
753 $w.f.left.tmt configure -text [
concat $::tr(TwinCheckTournament) $tmt]
755 $w.f.left.title.d configure -state disabled
756 $w.f.left.tmt configure -text ""
759 set twincheck(right) [
sc_base gameflag [
sc_base current] $dup get del]
760 $w.f.right.title.label configure -text [
concat $::tr(game) " $dup: "]
761 $w.f.right.title.d configure -command "sc_base gameflag \[sc_base current\] $dup invert del; ::notify::GameChanged"
762 $w.f.right.title.d configure -state normal
763 set tmt [
sc_game crosstable count -game $dup +deleted]
764 $w.f.right.tmt configure -text [
concat $::tr(TwinCheckTournament) $tmt]
766 $w.f.right.title.label configure -text $::tr(TwinCheckNoTwin)
767 $w.f.right.title.d configure -state disabled
768 $w.f.right.tmt configure -text ""
771 $w.b.share configure -state disabled -command {}
772 if {$gn > 0 && $dup > 0} {
773 if {[
llength [
sc_game tags share check $gn $dup]] > 0} {
774 $w.b.share configure -state normal -command "shareTwinTags $gn $dup $w"
777 set t $w.f.left.t.text
778 $t configure -state normal
782 set t $w.f.right.t.text
783 $t configure -state normal
786 $t insert end [
sc_game pgn -gameNumber $dup]
788 $t insert end $::tr(TwinCheckNoTwinfound)
793 set rlen [$w.f.right.t.text index end-1c]
794 set llen [$w.f.left.t.text index end-1c]
796 for {
set i 0} {$i < $rlen} {
incr i} {
797 set line [$w.f.right.t.text get $i.0 "$i.0 lineend"]
798 set length [
string length $line]
800 for {
set j 0} {$j < $llen} {
incr j} {
801 set otherLine [$w.f.left.t.text get $j.0 "$j.0 lineend"]
802 set plen [strPrefixLen $line $otherLine]
803 if {$plen > $max} {
set max $plen}
805 if {$max < $length} {
806 if {![
string compare [
string index $line 0] "\["]} {
set max 0}
807 $w.f.right.t.text tag add h $i.$max "$i.0 lineend"
811 for {
set i 0} {$i < $llen} {
incr i} {
812 set line [$w.f.left.t.text get $i.0 "$i.0 lineend"]
813 set length [
string length $line]
815 for {
set j 0} {$j < $rlen} {
incr j} {
816 set otherLine [$w.f.right.t.text get $j.0 "$j.0 lineend"]
817 set plen [strPrefixLen $line $otherLine]
818 if {$plen > $max} {
set max $plen}
820 if {$max < $length} {
821 if {![
string compare [
string index $line 0] "\["]} {
set max 0}
822 $w.f.left.t.text tag add h $i.$max "$i.0 lineend"
828 $w.b.delete configure -state normal
830 $w.b.delete configure -state disabled
833 foreach side {left right} {
834 $w.f.$side.t.text configure -state disabled
844 proc shareTwinTags {g1 g2 {parent .}} {
845 set sharelist [
sc_game tags share check $g1 $g2]
846 if {[
llength $sharelist] == 0} {
return}
848 set msg $::tr(TwinChangeTag)
849 foreach {gn tag old new} $sharelist {
850 append msg [
concat $::tr(game) " $gn: $tag: \"$old\" -> \"$new\""]
853 set answer [
tk_messageBox -parent $parent -title "Scid" \
854 -type okcancel -default ok -icon question -message $msg]
855 if {$answer != "ok"} {
return}
856 sc_game tags share update $g1 $g2
865 proc baseIsCompactable {} {
868 set curr_base [
sc_base current]
869 if {[
sc_base isReadOnly $curr_base]} {
return 0}
870 if {$curr_base == $::clipbase_db} {
return 0}
874 proc compactDB {{base -1}} {
875 if {$base < 0} {
set base [
sc_base current]}
877 if {[
catch {
sc_base compact $base stats} stats]} {
880 set msg "[
sc_base filename $base]\n\n"
881 append msg "Deleted games: [
lindex $stats 0]\n"
882 append msg "Unused names: [
lindex $stats 1]\n"
883 append msg "Sparse games: [
lindex $stats 2]\n"
884 append msg "Missing names (bad idx): [
lindex $stats 3]"
885 append msg "\n\nProceed?"
886 set confirm [
tk_messageBox -type okcancel -icon info -parent . \
887 -title [
concat "Scid: " $::tr(CompactDatabase)] \
889 if {$confirm != "ok"} {
return}
900 destroy .analysisWin1
901 destroy .analysisWin2
906 destroy .inputengineconsole
908 progressWindow "Scid" [
concat $::tr(CompactDatabase) "..."] $::tr(Cancel)
909 set err [
catch {
sc_base compact $base} result]
912 set extra "$::tr(CompactDatabase)\n"
913 if {$::errorCode == $::ERROR::FileOpen} {
914 append extra "\n$::ERROR::msg(CompactCreate)"
920 set msg "[
sc_base filename $base]\n\n"
921 append msg [
tr GameFileCompacted]
922 tk_messageBox -type ok -icon info -parent . \
923 -title [
concat "Scid: " $::tr(CompactDatabase)] \
933 set addRatings(overwrite) 0
934 set addRatings(filter) 0
936 proc allocateRatings {} {
937 if {[
catch {
sc_name ratings -test 1} result]} {
938 tk_messageBox -type ok -icon info -parent . -title "Scid" -message $result
944 ttk::label $w.lab -wraplength 3i -justify left -text $::tr(AllocRatingDescription)
945 pack $w.lab -side top -expand 1 -fill x -anchor w
946 ttk::labelframe $w.g -text $::tr(AddRatings)
947 pack $w.g -side top -fill x -anchor w -pady 10
948 ttk::radiobutton $w.g.all -variable addRatings(filter) \
949 -value 0 -text $::tr(SelectAllGames)
950 ttk::radiobutton $w.g.filter -variable addRatings(filter) \
951 -value 1 -text $::tr(SelectFilterGames)
952 pack $w.g $w.g.all $w.g.filter -side top -anchor w
953 ttk::checkbutton $w.r -text $::tr(RatingOverride) \
954 -variable addRatings(overwrite) -onvalue 1 -offvalue 0
955 pack $w.r -side top -anchor w -fill x -pady "5 0"
956 pack [ttk::frame $w.b] -side top -fill x
957 ttk::button $w.b.ok -text "OK" \
958 -command "catch {grab release $w}; destroy $w; doAllocateRatings"
959 ttk::button $w.b.cancel -text $::tr(Cancel) \
960 -command "catch {grab release $w}; destroy $w"
966 proc doAllocateRatings {} {
968 if {[
catch {
sc_name ratings -test 1} result]} {
969 tk_messageBox -type ok -icon info -parent . -title "Scid" -message $result
973 set err [
catch {
sc_name ratings -change $addRatings(overwrite) -filter $addRatings(filter)} result]
980 tk_messageBox -type ok -icon info -parent . \
981 -title "Scid" -message [subst $::tr(AddedRatings)]
990 array set stripTagCount {}
993 global stripTagChoice stripTagCount
995 if {[
winfo exists $w]} {
1002 progressWindow "Scid" "Searching for extra PGN tags..." $::tr(Cancel)
1003 set err [
catch {
sc_base tag list} result]
1011 array unset stripTagCount
1013 foreach {tag count} $result {
1014 set stripTagCount($tag) $count
1019 tk_messageBox -title "Scid" -icon info -type ok \
1020 -message "No extra tags were found."
1025 wm title $w "Scid: $::tr(StripTags)"
1026 ttk::label $w.title -text "Extra PGN tags:" -font font_Bold -anchor w
1027 pack $w.title -side top -fill x -anchor center
1028 pack [ttk::frame $w.f] -side top -fill x
1029 pack [ttk::frame $w.b] -side bottom -fill x
1032 foreach tag [lsort [
array names stripTagCount]] {
1033 set count $stripTagCount($tag)
1034 ttk::radiobutton $w.f.t$tag -text "$tag " -variable stripTagChoice -value $tag
1036 if {$row == 0} {
set stripTagChoice $tag}
1037 grid $w.f.t$tag -row $row -column 0 -sticky w
1038 grid $w.f.c$tag -row $row -column 1 -sticky e
1041 ttk::button $w.b.find -text $::tr(SetFilter) -command findStripTags
1042 ttk::button $w.b.strip -text $::tr(StripTag...) -command {
1043 set removed [doStripTags .striptags]
1044 set stripTagCount($stripTagChoice) \
1045 [expr {$stripTagCount($stripTagChoice) - $removed} ]
1046 .striptags.f.c$stripTagChoice configure -text \
1047 [::utils::thousands $stripTagCount($stripTagChoice)]
1049 ttk::button $w.b.cancel -text $::tr(Cancel) \
1050 -command "catch {grab release $w}; destroy $w"
1057 proc doStripTags {{parent .}} {
1058 global stripTagChoice
1059 set msg "Do you really want to remove all occurrences of the PGN tag"
1060 append msg " \"$stripTagChoice\" from this database?"
1061 set result [
tk_messageBox -title "Scid" -parent $parent \
1062 -icon question -type yesno -message $msg]
1063 if {$result == "no"} {
return 0}
1064 progressWindow "Scid" "Removing the PGN tag $stripTagChoice..." $::tr(Cancel)
1065 set err [
catch {
sc_base tag strip $stripTagChoice} result]
1073 set result "Removed $result instances of \"$stripTagChoice\"."
1074 append result "\n\n"
1075 append result "To save space and maintain database efficiency, it is a "
1076 append result "good idea to compact the game file after removing tags."
1077 tk_messageBox -title "Scid" -parent $parent -type ok -icon info \
1082 proc findStripTags {} {
1083 global stripTagChoice
1084 progressWindow "Scid" "Finding games with the PGN tag $stripTagChoice..." $::tr(Cancel)
1085 set err [
catch {
sc_base tag find $stripTagChoice} result]
1095 set cleaner(players) 1
1096 set cleaner(events) 1
1097 set cleaner(sites) 1
1098 set cleaner(rounds) 1
1101 set cleaner(twins) 1
1102 set cleaner(cgames) 0
1104 proc cleanerWin {} {
1106 if {[
winfo exists $w]} {
return}
1109 wm title $w "Scid: $::tr(Cleaner)"
1110 bind $w <F1> {helpWindow Maintenance Cleaner}
1111 pack [ttk::frame $w.f]
1113 pack [ttk::frame $w.f.help] -side top -fill x
1114 ttk::label $w.f.help.text -wraplength 3i -text [
string trim $::tr(CleanerHelp)]
1115 pack $w.f.help.text -side left -fill x -expand yes
1117 pack [ttk::frame $w.f.f] -side top -pady "10 0"
1119 set spelltext $::tr(Spellchecking)
1120 foreach i {players events sites rounds eco elo twins cgames} \
1121 j {Players Events Sites Rounds ReclassifyGames AddEloRatings DeleteTwins CompactDatabase } {
1123 if { $i eq "eco" } {
set spelltext ""}
1124 ttk::checkbutton $w.f.f.$i -variable cleaner($i) -offvalue 0 -onvalue 1 -text "$spelltext $::tr($j)"
1127 foreach i {players events sites rounds eco elo twins cgames} {
1128 grid $w.f.f.$i -row $row -column 0 -sticky w
1132 pack [ttk::frame $w.f.b] -side bottom -fill x
1133 ttk::button $w.f.b.ok -text "OK" -command "catch {grab release $w}; destroy $w; doCleaner"
1134 ttk::button $w.f.b.cancel -text $::tr(Cancel) -command "catch {grab release $w}; destroy $w"
1145 set cleaner_maxSpellCorrections 0
1149 global cleaner twinSettings
1150 global cleaner_maxSpellCorrections
1154 set answer [
tk_messageBox -type yesno -icon question \
1155 -title $::tr(TwinCriteriaConfirm) \
1156 -message [
string trim $::tr(CleanerConfirm)]]
1157 if {$answer == "no"} {
return}
1160 if {! [
winfo exists $w]} {
1162 wm title $w "Scid: $::tr(Cleaner)"
1163 pack [ttk::frame $w.f]
1164 pack [ttk::frame $w.f.b] -side bottom -fill x -expand yes
1165 pack [ttk::frame $w.f.t] -side top -fill both -expand yes
1166 text $w.f.t.text -width 60 -height 10 -wrap none -setgrid 1 \
1167 -cursor top_left_arrow -yscrollcommand "$w.f.t.ybar set"
1168 ttk::scrollbar $w.f.t.ybar -orient vertical -command "$w.f.t.text yview" -takefocus 0
1169 pack $w.f.t.ybar -side right -fill y
1170 pack $w.f.t.text -side left -fill both -expand yes
1171 ttk::button $w.f.b.close -text $::tr(Close) -command "catch {grab release $w}; destroy $w"
1180 $t insert end "$::tr(Cleaner)."
1181 $t insert end " $::tr(Database): [
file tail [
sc_base filename $dbase]]\n"
1183 $w.f.b.close configure -state disabled
1187 foreach nameType {Player Event Site Round} {
1190 set tag [
string tolower $names]
1191 if {$cleaner($tag)} {
1192 mtoolAdd $t "$count: $::tr(Spellchecking): $::tr($names)..."
1194 set err [
catch {
sc_name spellcheck -max $cleaner_maxSpellCorrections $nameType} corrections]
1197 set err [
catch {
sc_name correct $nameType $corrections} result]
1202 set msg "Number of games corrected: [
lindex $result 2]\n"
1204 $t insert end " $msg\n"
1209 if {$cleaner(eco)} {
1210 mtoolAdd $t "$count: $::tr(ReclassifyGames)..."
1212 catch {
sc_eco base $::classifyOption(AllGames) \
1213 $::classifyOption(ExtendedCodes)} result
1214 $t insert end " ECO classified $result games\n"
1218 if {$cleaner(elo)} {
1219 mtoolAdd $t "$count: $::tr(AddEloRatings)..."
1221 if {[
catch {
sc_name ratings} result]} {
1222 $t insert end " $result\n"
1226 $t insert end " Scid added $r Elo ratings in $g games.\n"
1230 if {$cleaner(twins)} {
1231 mtoolAdd $t "$count: $::tr(DeleteTwins)..."
1233 if {$twinSettings(undelete) == "Yes"} {
1237 -colors $twinSettings(colors) \
1238 -event $twinSettings(event) -site $twinSettings(site) \
1239 -round $twinSettings(round) -year $twinSettings(year) \
1240 -month $twinSettings(month) -day $twinSettings(day) \
1241 -result $twinSettings(result) -eco $twinSettings(eco) \
1242 -moves $twinSettings(moves) -players $twinSettings(players) \
1243 -setfilter $twinSettings(setfilter) \
1244 -usefilter $twinSettings(usefilter) \
1245 -comments $twinSettings(comments) \
1246 -variations $twinSettings(variations) \
1247 -delete $twinSettings(delete)} result]} {
1250 set message "Scid found $result twin games"
1251 if {$result > 0} {
append message " and set their delete flags"}
1253 $t insert end " $message.\n"
1256 if {$cleaner(cgames)} {
1257 mtoolAdd $t "$count: $::tr(CompactDatabase)..."
1259 if {[
catch {
sc_base compact $dbase stats} stats]} {
1260 $t insert end " Error: unable to compacwt the database.\n"
1262 if {[
lindex $stats 0] == 0 && [
lindex $stats 1] == 0 && \
1263 [
lindex $stats 2] == 0 && [
lindex $stats 3] == 0} {
1264 $t insert end " Database already compacted.\n"
1266 if {[
catch {
sc_base compact $dbase} result]} {
1267 $t insert end " Error: unable to compact the database.\n"
1269 $t insert end " Done.\n"
1279 $w.f.b.close configure -state normal
1280 catch {grab release $w}
1284 proc mtoolAdd {tw title} {
1285 set time [
clock format [
clock seconds] -format "%H:%M:%S"]
1286 $tw insert end "\n\[$time\]\n"
1287 if {$title != ""} { $tw insert end "$title\n"}