1# 2# This file is part of: 3# 4# gpsman --- GPS Manager: a manager for GPS receiver data 5# 6# Copyright (c) 1998-2013 Miguel Filgueiras migfilg@t-online.de 7# 8# This program is free software; you can redistribute it and/or modify 9# it under the terms of the GNU General Public License as published by 10# the Free Software Foundation; either version 3 of the License, or 11# (at your option) any later version. 12# 13# This program is distributed in the hope that it will be useful, 14# but WITHOUT ANY WARRANTY; without even the implied warranty of 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16# GNU General Public License for more details. 17# 18# You should have received a copy of the GNU General Public License 19# along with this program. 20# 21# File: lists.tcl 22# Last change: 6 October 2013 23# 24 25proc ChangeOnStateList {wh st} { 26 # change state of items list when list becomes empty/non-empty 27 # $wh in $TYPES or LAP 28 # $st in {normal, disabled} 29 global LsW RcW RcMenu GPSState WConf RECTYPES 30 31 # entries in the type list menu and in the type sub-menu of Data menu 32 switch $wh { 33 WP { 34 set es "1 2 5 6 7" ; set aes "1 2 4 5 6" 35 } 36 GR { 37 set es "1 2 4 5 6 7 8 9" ; set aes "1 2 3 4 5 6 7 8" 38 } 39 LAP { 40 set es "0 2" ; set aes "0 2" 41 } 42 default { 43 set es "1 2 5 6" ; set aes "1 2 4 5" 44 } 45 } 46 if { [set ix [lsearch -exact $RECTYPES $wh]] != -1 } { 47 # reconfigure receiver window/menu 48 if { $wh == "GR" } { 49 set bs "frget.frget2.getGR frput.putGR" 50 $RcMenu.gm entryconfigure $WConf(rec,getmn,GR) -state $st 51 $RcMenu.ptm entryconfigure $WConf(rec,putmn,GR) -state $st 52 } elseif { $wh != "IC" && $wh != "LAP" } { 53 set bs "frput.put$wh" 54 $RcMenu.ptm entryconfigure $WConf(rec,putmn,$wh) -state $st 55 } else { set bs "" } 56 if { $st == "normal" && $GPSState == "online" } { 57 set sg normal 58 } else { set sg disabled } 59 foreach b $bs { 60 $RcW.$b configure -state $sg 61 } 62 } 63 foreach e $es { 64 $LsW.frl$wh.frb.file.m entryconfigure $e -state $st 65 } 66 if { [set p $WConf(additemstate)] != "" } { 67 foreach e $aes { 68 ${p}$wh entryconfigure $e -state $st 69 } 70 } 71 return 72} 73 74proc ClearList {wh} { 75 # forget all items in a list; $wh in $TYPES 76 global ListInds List EdWindow GMEd MESS TXT 77 78 if { $ListInds($wh) == "" || \ 79 ! [GMConfirm [format $MESS(forgetall) $TXT(name$wh)]] } { return } 80 set ixs $ListInds($wh) 81 if { [winfo exists $EdWindow($wh)] } { 82 GMMessage [format $MESS(cantfgted) $TXT(name$wh)] 83 set ixs [Delete $ixs $GMEd($wh,Index)] 84 } 85 # ForgetSeveral calls procs that update $ListInds($wh) 86 ForgetSeveral $wh $ixs 87 return 88} 89 90proc Count {wh} { 91 # count items in list; $wh in $TYPES 92 global Number MESS TXT 93 94 GMMessage [format $MESS(counted) $Number($wh) $TXT(name$wh)] 95 return 96} 97 98proc OpenListItem {wh} { 99 # edit or display selected item in a list; $wh in $TYPES 100 global LsW ListInds 101 102 set s [$LsW.frl$wh.frl.box curselection] 103 if { $s != "" } { 104 OpenItem $wh [lindex $ListInds($wh) $s] 105 } 106 return 107} 108 109proc ToggleDisplayItem {wh sel} { 110 # un-/display on map selected item in a list 111 # $wh in $TYPES or LAP; $sel is selection index in list 112 global ListInds EdWindow GMEd ${wh}Displ Number 113 114 if { $wh == "LAP" } { return } 115 if { $Number($wh)>0 && $sel != "" } { 116 set index [lindex $ListInds($wh) $sel] 117 set w $EdWindow($wh) 118 if { [winfo exists $w] && $GMEd($wh,Index) == $index } { 119 Raise $w ; bell 120 return 121 } 122 if { [set [set wh]Displ($index)] } { 123 UnMap $wh $index 124 } else { PutMap $wh $index } 125 } 126 return 127} 128 129proc ToggleDisplayNamed {wh name} { 130 # un-/display on map item with given name 131 # $wh in $TYPES or LAP 132 global EdWindow GMEd ${wh}Displ 133 134 if { $wh == "LAP" } { return } 135 if { [set index [IndexNamed $wh $name]] == -1 } { return } 136 set w $EdWindow($wh) 137 if { [winfo exists $w] && $GMEd($wh,Index) == $index } { 138 Raise $w ; bell 139 } elseif { [set [set wh]Displ($index)] } { 140 UnMap $wh $index 141 } else { PutMap $wh $index } 142 return 143} 144 145proc ListAdd {wh index} { 146 # add new item with given index to non-empty list; $wh in $TYPES or LAP 147 global LsW ListInds Storage CMDLINE LAPStart 148 149 if { $CMDLINE } { return } 150 151 set ids [lindex $Storage($wh) 0] 152 global $ids 153 set name [set [set ids]($index)] 154 if { $ListInds($wh) == "" } { 155 set ListInds($wh) $index 156 $LsW.frl$wh.frl.box insert end $name 157 ChangeOnStateList $wh normal 158 } elseif { $wh != "LAP" } { 159 set a 0 ; set b [expr [$LsW.frl$wh.frl.box size]-1] 160 while 1 { 161 set i [expr int(floor(($a+$b)/2))] 162 if { [string compare $name [$LsW.frl$wh.frl.box get $i]] < 0 } { 163 set b $i 164 } else { set a $i } 165 if { $b == $a } { 166 if { [string compare $name \ 167 [$LsW.frl$wh.frl.box get $a]] > 0 } { 168 incr a 169 } 170 $LsW.frl$wh.frl.box insert $a $name 171 set ListInds($wh) [linsert $ListInds($wh) $a $index] 172 break 173 } 174 if { $b == $a+1 } { 175 if { [string compare $name \ 176 [$LsW.frl$wh.frl.box get $a]] > 0 } { 177 incr a 178 if { [string compare $name \ 179 [$LsW.frl$wh.frl.box get $a]] > 0 } { 180 incr a 181 } 182 } 183 $LsW.frl$wh.frl.box insert $a $name 184 set ListInds($wh) [linsert $ListInds($wh) $a $index] 185 break 186 } 187 } 188 } else { 189 # LAP: order by start date 190 set secs [lindex $LAPStart($index) 1] 191 set a 0 ; set nf 1 192 foreach ix $ListInds(LAP) { 193 if { [lindex $LAPStart($ix) 1] <= $secs } { 194 set nf 0 ; break 195 } 196 incr a 197 } 198 if { $nf } { set a end } 199 $LsW.frl$wh.frl.box insert $a $name 200 set ListInds($wh) [linsert $ListInds($wh) $a $index] 201 } 202 return 203} 204 205proc ListDelete {wh index} { 206 # delete item with given index from list; $wh in $TYPES or LAP 207 global LsW ListInds 208 209 set n [lsearch -exact $ListInds($wh) $index ] 210 $LsW.frl$wh.frl.box delete $n 211 set ListInds($wh) [lreplace $ListInds($wh) $n $n] 212 if { [$LsW.frl$wh.frl.box size] == 0 } { 213 ChangeOnStateList $wh disabled 214 } 215 return 216} 217 218proc ListDeleteSeveral {wh ixs} { 219 # delete items with given indices from list; $wh in $TYPES or LAP 220 # $ixs has the same order of $ListInds($wh) although with some 221 # elements missing 222 global LsW ListInds 223 224 if { $ixs == "" } { return } 225 set exs $ListInds($wh) ; set ks "" 226 set bx $LsW.frl$wh.frl.box ; set ib 0 227 while { $ixs != "" } { 228 set c 0 229 foreach ex $exs ix $ixs { 230 if { $ex == $ix } { 231 $bx delete $ib ; incr c 232 } else { 233 lappend ks $ex ; incr ib 234 break 235 } 236 } 237 set exs [lrange $exs [expr $c+1] end] 238 set ixs [lrange $ixs $c end] 239 } 240 set ListInds($wh) [concat $ks $exs] 241 if { $ib == 0 } { 242 ChangeOnStateList $wh disabled 243 } 244 return 245} 246 247proc ListDeleteAll {wh} { 248 # delete all items from list; $wh in $TYPES or LAP 249 global LsW ListInds 250 251 $LsW.frl$wh.frl.box delete 0 end 252 set ListInds($wh) "" 253 ChangeOnStateList $wh disabled 254 return 255} 256 257proc ChooseItems {wh args} { 258 # create modal dialog for selecting from list of items 259 # $wh in $TYPES or LAP 260 # $args is empty or a list whose head is in {single, many, many_0} 261 # for a single element, at least one element, and zero or more 262 # elements, and whose tail is a pair that is passed on to 263 # GMChooseFrom and describes parameters 264 # return indices of items selected or "" if cancelled 265 global LISTWIDTH Storage ListInds TXT 266 267 set ids [lindex $Storage($wh) 0] 268 global $ids 269 set ns "" 270 foreach i $ListInds($wh) { lappend ns [set [set ids]($i)] } 271 if { $args != "" } { 272 return [GMChooseFrom [lindex $args 0] \ 273 [list $TXT(select) $TXT(name$wh)] \ 274 $LISTWIDTH $ns $ListInds($wh) \ 275 [lindex $args 1] [lindex $args 2]] 276 } 277 return [GMChooseFrom many [list $TXT(select) $TXT(name$wh)] \ 278 $LISTWIDTH $ns $ListInds($wh)] 279} 280 281proc ChItemsCall {wh mode comm args} { 282 # select from list of items and call command 283 # $wh in $TYPES or LAP 284 # $mode in {single, many, many_0} as in proc ChooseItems 285 # $comm is command name to call as 286 # $comm ARG0 ... ARGn NAMES 287 288 if { [set ixs [ChooseItems $wh $mode]] == "" } { return } 289 set names [Apply $ixs NameOf $wh] 290 eval $comm $args $names 291 return 292} 293 294proc InputToGR {whs notwhs preproc proc postproc fmt} { 295 # input data according to contents of group(s) 296 # items of types in $whs (except those in $notwhs) will be read in 297 # $preproc will be called immediately before input is really required 298 # and should return 0 unless operation is to be cancelled; 299 # arguments: GR and $fmt; proc Ignore can be used if nothing is to 300 # be done 301 # $proc is the input procedure, whose arguments will be: 302 # type of item to input, list of indices and $fmt if not "receiver" 303 # $postproc will be called after the last call to $proc; single 304 # argument: GR; proc Ignore can be used if nothing is to be done 305 # $fmt is a either a file format (as used in the FILEFORMAT array) 306 # or "receiver" 307 global MESS TXT GCHow ListInds Storage FILEFORMAT 308 309 set gts "" ; set ts "" 310 foreach t $whs { 311 if { [lsearch -exact $notwhs $t] == -1 } { 312 lappend gts $t ; lappend ts $TXT(name$t) 313 } 314 } 315 set vals [list $TXT(notinGR) $TXT(onlyinGR)] 316 if { $fmt != "receiver" && $FILEFORMAT($fmt,filetype) == "data" } { 317 set mode many 318 } else { set mode single } 319 while 1 { 320 set whs [GMChooseFrom many $MESS(readwhat) 6 $ts $gts \ 321 GCHow [list $vals]] 322 set compl [string compare $GCHow $TXT(onlyinGR)] 323 if { [set i [lsearch -exact $whs GR]] != -1 } { 324 set whs [lreplace $whs $i $i] 325 set rec 1 326 } else { set rec 0 } 327 if { $mode == "single" && [llength $whs] > 1 } { 328 GMMessage $MESS(importonly1) 329 } else { break } 330 } 331 if { $whs == "" || [set ixs [ChooseItems GR]] == "" } { return } 332 if { [$preproc GR $fmt] } { return } 333 if { $mode != "single" } { 334 set ll "" 335 foreach wh $whs { 336 if { [set l [GRsElements $ixs $rec $wh]] != "" } { 337 if { $compl } { 338 set ids [lindex $Storage($wh) 0] 339 global $ids 340 set l [linsert [Complement [array names $ids] $l] 0 -1] 341 } 342 lappend ll $l 343 } 344 } 345 if { $ll != "" } { $proc $whs $ll $fmt } 346 } else { 347 # single 348 if { [set l [GRsElements $ixs $rec $whs]] != "" } { 349 if { $compl } { 350 set ids [lindex $Storage($whs) 0] 351 global $ids 352 set l [linsert [Complement [array names $ids] $l] 0 -1] 353 } 354 if { $fmt != "receiver" } { 355 $proc $whs [list $l] $fmt 356 } else { 357 $proc $whs $l 358 } 359 } 360 } 361 $postproc GR 362 return 363} 364