| 1 | # git-gui options editor |
| 2 | # Copyright (C) 2006, 2007 Shawn Pearce |
| 3 | |
| 4 | proc config_check_encodings {} { |
| 5 | global repo_config_new global_config_new |
| 6 | |
| 7 | set enc $global_config_new(gui.encoding) |
| 8 | if {$enc eq {}} { |
| 9 | set global_config_new(gui.encoding) [encoding system] |
| 10 | } elseif {[tcl_encoding $enc] eq {}} { |
| 11 | error_popup [mc "Invalid global encoding '%s'" $enc] |
| 12 | return 0 |
| 13 | } |
| 14 | |
| 15 | set enc $repo_config_new(gui.encoding) |
| 16 | if {$enc eq {}} { |
| 17 | set repo_config_new(gui.encoding) [encoding system] |
| 18 | } elseif {[tcl_encoding $enc] eq {}} { |
| 19 | error_popup [mc "Invalid repo encoding '%s'" $enc] |
| 20 | return 0 |
| 21 | } |
| 22 | |
| 23 | return 1 |
| 24 | } |
| 25 | |
| 26 | proc save_config {} { |
| 27 | global default_config font_descs |
| 28 | global repo_config global_config system_config |
| 29 | global repo_config_new global_config_new |
| 30 | global ui_comm_spell |
| 31 | |
| 32 | foreach option $font_descs { |
| 33 | set name [lindex $option 0] |
| 34 | set font [lindex $option 1] |
| 35 | font configure $font \ |
| 36 | -family $global_config_new(gui.$font^^family) \ |
| 37 | -size $global_config_new(gui.$font^^size) |
| 38 | font configure ${font}bold \ |
| 39 | -family $global_config_new(gui.$font^^family) \ |
| 40 | -size $global_config_new(gui.$font^^size) |
| 41 | font configure ${font}italic \ |
| 42 | -family $global_config_new(gui.$font^^family) \ |
| 43 | -size $global_config_new(gui.$font^^size) |
| 44 | set global_config_new(gui.$name) [font configure $font] |
| 45 | unset global_config_new(gui.$font^^family) |
| 46 | unset global_config_new(gui.$font^^size) |
| 47 | } |
| 48 | |
| 49 | foreach name [array names default_config] { |
| 50 | set value $global_config_new($name) |
| 51 | if {$value ne $global_config($name)} { |
| 52 | if {$value eq $system_config($name)} { |
| 53 | catch {git config --global --unset $name} |
| 54 | } else { |
| 55 | regsub -all "\[{}\]" $value {"} value |
| 56 | git config --global $name $value |
| 57 | } |
| 58 | set global_config($name) $value |
| 59 | if {$value eq $repo_config($name)} { |
| 60 | catch {git config --unset $name} |
| 61 | set repo_config($name) $value |
| 62 | } |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | foreach name [array names default_config] { |
| 67 | set value $repo_config_new($name) |
| 68 | if {$value ne $repo_config($name)} { |
| 69 | if {$value eq $global_config($name)} { |
| 70 | catch {git config --unset $name} |
| 71 | } else { |
| 72 | regsub -all "\[{}\]" $value {"} value |
| 73 | git config $name $value |
| 74 | } |
| 75 | set repo_config($name) $value |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | if {[info exists repo_config(gui.spellingdictionary)]} { |
| 80 | set value $repo_config(gui.spellingdictionary) |
| 81 | if {$value eq {none}} { |
| 82 | if {[info exists ui_comm_spell]} { |
| 83 | $ui_comm_spell stop |
| 84 | } |
| 85 | } elseif {[info exists ui_comm_spell]} { |
| 86 | $ui_comm_spell lang $value |
| 87 | } |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | proc do_options {} { |
| 92 | global repo_config global_config font_descs |
| 93 | global repo_config_new global_config_new |
| 94 | global ui_comm_spell |
| 95 | |
| 96 | array unset repo_config_new |
| 97 | array unset global_config_new |
| 98 | foreach name [array names repo_config] { |
| 99 | set repo_config_new($name) $repo_config($name) |
| 100 | } |
| 101 | load_config 1 |
| 102 | foreach name [array names repo_config] { |
| 103 | switch -- $name { |
| 104 | gui.diffcontext {continue} |
| 105 | } |
| 106 | set repo_config_new($name) $repo_config($name) |
| 107 | } |
| 108 | foreach name [array names global_config] { |
| 109 | set global_config_new($name) $global_config($name) |
| 110 | } |
| 111 | |
| 112 | set w .options_editor |
| 113 | Dialog $w |
| 114 | wm withdraw $w |
| 115 | wm transient $w [winfo parent $w] |
| 116 | wm geometry $w "+[winfo rootx .]+[winfo rooty .]" |
| 117 | |
| 118 | ttk::frame $w.buttons |
| 119 | ttk::button $w.buttons.restore -text [mc "Restore Defaults"] \ |
| 120 | -default normal \ |
| 121 | -command do_restore_defaults |
| 122 | pack $w.buttons.restore -side left |
| 123 | ttk::button $w.buttons.save -text [mc Save] \ |
| 124 | -default active \ |
| 125 | -command [list do_save_config $w] |
| 126 | pack $w.buttons.save -side right |
| 127 | ttk::button $w.buttons.cancel -text [mc "Cancel"] \ |
| 128 | -default normal \ |
| 129 | -command [list destroy $w] |
| 130 | pack $w.buttons.cancel -side right -padx 5 |
| 131 | pack $w.buttons -side bottom -fill x -pady 10 -padx 10 |
| 132 | |
| 133 | ttk::labelframe $w.repo -text [mc "%s Repository" [reponame]] |
| 134 | ttk::labelframe $w.global -text [mc "Global (All Repositories)"] |
| 135 | pack $w.repo -side left -fill both -expand 1 -pady 5 -padx 5 |
| 136 | pack $w.global -side right -fill both -expand 1 -pady 5 -padx 5 |
| 137 | |
| 138 | set optid 0 |
| 139 | foreach option { |
| 140 | {t user.name {mc "User Name"}} |
| 141 | {t user.email {mc "Email Address"}} |
| 142 | |
| 143 | {b merge.summary {mc "Summarize Merge Commits"}} |
| 144 | {i-1..5 merge.verbosity {mc "Merge Verbosity"}} |
| 145 | {b merge.diffstat {mc "Show Diffstat After Merge"}} |
| 146 | {t merge.tool {mc "Use Merge Tool"}} |
| 147 | |
| 148 | {b gui.trustmtime {mc "Trust File Modification Timestamps"}} |
| 149 | {b gui.pruneduringfetch {mc "Prune Tracking Branches During Fetch"}} |
| 150 | {b gui.matchtrackingbranch {mc "Match Tracking Branches"}} |
| 151 | {b gui.textconv {mc "Use Textconv For Diffs and Blames"}} |
| 152 | {b gui.fastcopyblame {mc "Blame Copy Only On Changed Files"}} |
| 153 | {i-0..100 gui.maxrecentrepo {mc "Maximum Length of Recent Repositories List"}} |
| 154 | {i-20..200 gui.copyblamethreshold {mc "Minimum Letters To Blame Copy On"}} |
| 155 | {i-0..300 gui.blamehistoryctx {mc "Blame History Context Radius (days)"}} |
| 156 | {i-1..99 gui.diffcontext {mc "Number of Diff Context Lines"}} |
| 157 | {t gui.diffopts {mc "Additional Diff Parameters"}} |
| 158 | {i-0..99 gui.commitmsgwidth {mc "Commit Message Text Width"}} |
| 159 | {t gui.newbranchtemplate {mc "New Branch Name Template"}} |
| 160 | {c gui.encoding {mc "Default File Contents Encoding"}} |
| 161 | {b gui.warndetachedcommit {mc "Warn before committing to a detached head"}} |
| 162 | {s gui.stageuntracked {mc "Staging of untracked files"} {list "yes" "no" "ask"}} |
| 163 | {b gui.displayuntracked {mc "Show untracked files"}} |
| 164 | {i-1..99 gui.tabsize {mc "Tab spacing"}} |
| 165 | } { |
| 166 | set type [lindex $option 0] |
| 167 | set name [lindex $option 1] |
| 168 | set text [eval [lindex $option 2]] |
| 169 | incr optid |
| 170 | foreach f {repo global} { |
| 171 | switch -glob -- $type { |
| 172 | b { |
| 173 | ttk::checkbutton $w.$f.$optid -text $text \ |
| 174 | -variable ${f}_config_new($name) \ |
| 175 | -onvalue true \ |
| 176 | -offvalue false |
| 177 | pack $w.$f.$optid -side top -anchor w |
| 178 | } |
| 179 | i-* { |
| 180 | regexp -- {-(\d+)\.\.(\d+)$} $type _junk min max |
| 181 | ttk::frame $w.$f.$optid |
| 182 | ttk::label $w.$f.$optid.l -text [mc "%s:" $text] |
| 183 | pack $w.$f.$optid.l -side left -anchor w -fill x |
| 184 | tspinbox $w.$f.$optid.v \ |
| 185 | -textvariable ${f}_config_new($name) \ |
| 186 | -from $min \ |
| 187 | -to $max \ |
| 188 | -increment 1 \ |
| 189 | -width [expr {1 + [string length $max]}] |
| 190 | bind $w.$f.$optid.v <FocusIn> {%W selection range 0 end} |
| 191 | pack $w.$f.$optid.v -side right -anchor e -padx 5 |
| 192 | pack $w.$f.$optid -side top -anchor w -fill x |
| 193 | } |
| 194 | c - |
| 195 | t { |
| 196 | ttk::frame $w.$f.$optid |
| 197 | ttk::label $w.$f.$optid.l -text [mc "%s:" $text] |
| 198 | ttk::entry $w.$f.$optid.v \ |
| 199 | -width 20 \ |
| 200 | -textvariable ${f}_config_new($name) |
| 201 | pack $w.$f.$optid.l -side left -anchor w |
| 202 | pack $w.$f.$optid.v -side left -anchor w \ |
| 203 | -fill x -expand 1 \ |
| 204 | -padx 5 |
| 205 | if {$type eq {c}} { |
| 206 | menu $w.$f.$optid.m |
| 207 | build_encoding_menu $w.$f.$optid.m \ |
| 208 | [list set ${f}_config_new($name)] 1 |
| 209 | ttk::button $w.$f.$optid.b \ |
| 210 | -text [mc "Change"] \ |
| 211 | -command [list popup_btn_menu \ |
| 212 | $w.$f.$optid.m $w.$f.$optid.b] |
| 213 | pack $w.$f.$optid.b -side left -anchor w |
| 214 | } |
| 215 | pack $w.$f.$optid -side top -anchor w -fill x |
| 216 | } |
| 217 | s { |
| 218 | set opts [eval [lindex $option 3]] |
| 219 | ttk::frame $w.$f.$optid |
| 220 | ttk::label $w.$f.$optid.l -text [mc "%s:" $text] |
| 221 | ttk::combobox $w.$f.$optid.v \ |
| 222 | -textvariable ${f}_config_new($name) \ |
| 223 | -values $opts -state readonly |
| 224 | pack $w.$f.$optid.l -side left -anchor w -fill x |
| 225 | pack $w.$f.$optid.v -side right -anchor e -padx 5 |
| 226 | pack $w.$f.$optid -side top -anchor w -fill x |
| 227 | } |
| 228 | } |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | set all_dicts [linsert \ |
| 233 | [spellcheck::available_langs] \ |
| 234 | 0 \ |
| 235 | none] |
| 236 | incr optid |
| 237 | foreach f {repo global} { |
| 238 | if {![info exists ${f}_config_new(gui.spellingdictionary)]} { |
| 239 | if {[info exists ui_comm_spell]} { |
| 240 | set value [$ui_comm_spell lang] |
| 241 | } else { |
| 242 | set value none |
| 243 | } |
| 244 | set ${f}_config_new(gui.spellingdictionary) $value |
| 245 | } |
| 246 | |
| 247 | ttk::frame $w.$f.$optid |
| 248 | ttk::label $w.$f.$optid.l -text [mc "Spelling Dictionary:"] |
| 249 | ttk::combobox $w.$f.$optid.v \ |
| 250 | -textvariable ${f}_config_new(gui.spellingdictionary) \ |
| 251 | -values $all_dicts -state readonly |
| 252 | pack $w.$f.$optid.l -side left -anchor w -fill x |
| 253 | pack $w.$f.$optid.v -side right -anchor e -padx 5 |
| 254 | pack $w.$f.$optid -side top -anchor w -fill x |
| 255 | } |
| 256 | unset all_dicts |
| 257 | |
| 258 | set all_fonts [lsort [font families]] |
| 259 | foreach option $font_descs { |
| 260 | set name [lindex $option 0] |
| 261 | set font [lindex $option 1] |
| 262 | set text [eval [lindex $option 2]] |
| 263 | |
| 264 | set global_config_new(gui.$font^^family) \ |
| 265 | [font configure $font -family] |
| 266 | set global_config_new(gui.$font^^size) \ |
| 267 | [font configure $font -size] |
| 268 | |
| 269 | ttk::frame $w.global.$name |
| 270 | ttk::label $w.global.$name.l -text [mc "%s:" $text] |
| 271 | ttk::button $w.global.$name.b \ |
| 272 | -text [mc "Change Font"] \ |
| 273 | -command [list \ |
| 274 | tchoosefont \ |
| 275 | $w \ |
| 276 | [mc "Choose %s" $text] \ |
| 277 | global_config_new(gui.$font^^family) \ |
| 278 | global_config_new(gui.$font^^size) \ |
| 279 | ] |
| 280 | ttk::label $w.global.$name.f -textvariable global_config_new(gui.$font^^family) |
| 281 | ttk::label $w.global.$name.s -textvariable global_config_new(gui.$font^^size) |
| 282 | ttk::label $w.global.$name.pt -text [mc "pt."] |
| 283 | pack $w.global.$name.l -side left -anchor w |
| 284 | pack $w.global.$name.b -side right -anchor e |
| 285 | pack $w.global.$name.pt -side right -anchor w |
| 286 | pack $w.global.$name.s -side right -anchor w |
| 287 | pack $w.global.$name.f -side right -anchor w |
| 288 | pack $w.global.$name -side top -anchor w -fill x |
| 289 | } |
| 290 | |
| 291 | bind $w <Visibility> "grab $w; focus $w.buttons.save" |
| 292 | bind $w <Key-Escape> "destroy $w" |
| 293 | bind $w <Key-Return> [list do_save_config $w] |
| 294 | |
| 295 | if {[is_MacOSX]} { |
| 296 | set t [mc "Preferences"] |
| 297 | } else { |
| 298 | set t [mc "Options"] |
| 299 | } |
| 300 | wm title $w "[appname] ([reponame]): $t" |
| 301 | wm deiconify $w |
| 302 | tkwait window $w |
| 303 | } |
| 304 | |
| 305 | proc do_restore_defaults {} { |
| 306 | global font_descs default_config repo_config system_config |
| 307 | global repo_config_new global_config_new |
| 308 | |
| 309 | foreach name [array names default_config] { |
| 310 | set repo_config_new($name) $system_config($name) |
| 311 | set global_config_new($name) $system_config($name) |
| 312 | } |
| 313 | |
| 314 | foreach option $font_descs { |
| 315 | set name [lindex $option 0] |
| 316 | set repo_config(gui.$name) $system_config(gui.$name) |
| 317 | } |
| 318 | apply_config |
| 319 | |
| 320 | foreach option $font_descs { |
| 321 | set name [lindex $option 0] |
| 322 | set font [lindex $option 1] |
| 323 | set global_config_new(gui.$font^^family) \ |
| 324 | [font configure $font -family] |
| 325 | set global_config_new(gui.$font^^size) \ |
| 326 | [font configure $font -size] |
| 327 | } |
| 328 | } |
| 329 | |
| 330 | proc do_save_config {w} { |
| 331 | if {![config_check_encodings]} return |
| 332 | if {[catch {save_config} err]} { |
| 333 | error_popup [strcat [mc "Failed to completely save options:"] "\n\n$err"] |
| 334 | } |
| 335 | reshow_diff |
| 336 | destroy $w |
| 337 | } |