1# git-gui Tools menu dialogs
   2class tools_add {
   4field w              ; # widget path
   6field w_name         ; # new remote name widget
   7field w_cmd          ; # new remote location widget
   8field name         {}; # name of the tool
  10field command      {}; # command to execute
  11field add_global    0; # add to the --global config
  12field no_console    0; # disable using the console
  13field needs_file    0; # ensure filename is set
  14field confirm       0; # ask for confirmation
  15field ask_branch    0; # ask for a revision
  16field ask_args      0; # ask for additional args
  17constructor dialog {} {
  19        global repo_config
  20        make_toplevel top w
  22        wm title $top [append "[appname] ([reponame]): " [mc "Add Tool"]]
  23        if {$top ne {.}} {
  24                wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
  25                wm transient $top .
  26        }
  27        label $w.header -text [mc "Add New Tool Command"] -font font_uibold
  29        pack $w.header -side top -fill x
  30        frame $w.buttons
  32        checkbutton $w.buttons.global \
  33                -text [mc "Add globally"] \
  34                -variable @add_global
  35        pack $w.buttons.global -side left -padx 5
  36        button $w.buttons.create -text [mc Add] \
  37                -default active \
  38                -command [cb _add]
  39        pack $w.buttons.create -side right
  40        button $w.buttons.cancel -text [mc Cancel] \
  41                -command [list destroy $w]
  42        pack $w.buttons.cancel -side right -padx 5
  43        pack $w.buttons -side bottom -fill x -pady 10 -padx 10
  44        labelframe $w.desc -text [mc "Tool Details"]
  46        label $w.desc.name_cmnt -anchor w\
  48                -text [mc "Use '/' separators to create a submenu tree:"]
  49        grid x $w.desc.name_cmnt -sticky we -padx {0 5} -pady {0 2}
  50        label $w.desc.name_l -text [mc "Name:"]
  51        set w_name $w.desc.name_t
  52        entry $w_name \
  53                -borderwidth 1 \
  54                -relief sunken \
  55                -width 40 \
  56                -textvariable @name \
  57                -validate key \
  58                -validatecommand [cb _validate_name %d %S]
  59        grid $w.desc.name_l $w_name -sticky we -padx {0 5}
  60        label $w.desc.cmd_l -text [mc "Command:"]
  62        set w_cmd $w.desc.cmd_t
  63        entry $w_cmd \
  64                -borderwidth 1 \
  65                -relief sunken \
  66                -width 40 \
  67                -textvariable @command
  68        grid $w.desc.cmd_l $w_cmd -sticky we -padx {0 5} -pady {0 3}
  69        grid columnconfigure $w.desc 1 -weight 1
  71        pack $w.desc -anchor nw -fill x -pady 5 -padx 5
  72        checkbutton $w.confirm \
  74                -text [mc "Show a dialog before running"] \
  75                -variable @confirm -command [cb _check_enable_dlg]
  76        labelframe $w.dlg -labelwidget $w.confirm
  78        checkbutton $w.dlg.askbranch \
  80                -text [mc "Ask the user to select a revision (sets \$REVISION)"] \
  81                -variable @ask_branch -state disabled
  82        pack $w.dlg.askbranch -anchor w -padx 15
  83        checkbutton $w.dlg.askargs \
  85                -text [mc "Ask the user for additional arguments (sets \$ARGS)"] \
  86                -variable @ask_args -state disabled
  87        pack $w.dlg.askargs -anchor w -padx 15
  88        pack $w.dlg -anchor nw -fill x -pady {0 8} -padx 5
  90        checkbutton $w.noconsole \
  92                -text [mc "Don't show the command output window"] \
  93                -variable @no_console
  94        pack $w.noconsole -anchor w -padx 5
  95        checkbutton $w.needsfile \
  97                -text [mc "Run only if a diff is selected (\$FILENAME not empty)"] \
  98                -variable @needs_file
  99        pack $w.needsfile -anchor w -padx 5
 100        bind $w <Visibility> [cb _visible]
 102        bind $w <Key-Escape> [list destroy $w]
 103        bind $w <Key-Return> [cb _add]\;break
 104        tkwait window $w
 105}
 106method _check_enable_dlg {} {
 108        if {$confirm} {
 109                $w.dlg.askbranch configure -state normal
 110                $w.dlg.askargs configure -state normal
 111        } else {
 112                $w.dlg.askbranch configure -state disabled
 113                $w.dlg.askargs configure -state disabled
 114        }
 115}
 116method _add {} {
 118        global repo_config
 119        if {$name eq {}} {
 121                error_popup [mc "Please supply a name for the tool."]
 122                focus $w_name
 123                return
 124        }
 125        set item "guitool.$name.cmd"
 127        if {[info exists repo_config($item)]} {
 129                error_popup [mc "Tool '%s' already exists." $name]
 130                focus $w_name
 131                return
 132        }
 133        set cmd [list git config]
 135        if {$add_global} { lappend cmd --global }
 136        set items {}
 137        if {$no_console} { lappend items "guitool.$name.noconsole" }
 138        if {$needs_file} { lappend items "guitool.$name.needsfile" }
 139        if {$confirm} {
 140                if {$ask_args}   { lappend items "guitool.$name.argprompt" }
 141                if {$ask_branch} { lappend items "guitool.$name.revprompt" }
 142                if {!$ask_args && !$ask_branch} {
 143                        lappend items "guitool.$name.confirm"
 144                }
 145        }
 146        if {[catch {
 148                eval $cmd [list $item $command]
 149                foreach citem $items { eval $cmd [list $citem yes] }
 150            } err]} {
 151                error_popup [mc "Could not add tool:\n%s" $err]
 152        } else {
 153                set repo_config($item) $command
 154                foreach citem $items { set repo_config($citem) yes }
 155                tools_populate_all
 157        }
 158        destroy $w
 160}
 161method _validate_name {d S} {
 163        if {$d == 1} {
 164                if {[regexp {[~?*&\[\0\"\\\{]} $S]} {
 165                        return 0
 166                }
 167        }
 168        return 1
 169}
 170method _visible {} {
 172        grab $w
 173        $w_name icursor end
 174        focus $w_name
 175}
 176}
 178class tools_remove {
 180field w              ; # widget path
 182field w_names        ; # name list
 183constructor dialog {} {
 185        global repo_config global_config system_config
 186        load_config 1
 188        make_toplevel top w
 190        wm title $top [append "[appname] ([reponame]): " [mc "Remove Tool"]]
 191        if {$top ne {.}} {
 192                wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
 193                wm transient $top .
 194        }
 195        label $w.header -text [mc "Remove Tool Commands"] -font font_uibold
 197        pack $w.header -side top -fill x
 198        frame $w.buttons
 200        button $w.buttons.create -text [mc Remove] \
 201                -default active \
 202                -command [cb _remove]
 203        pack $w.buttons.create -side right
 204        button $w.buttons.cancel -text [mc Cancel] \
 205                -command [list destroy $w]
 206        pack $w.buttons.cancel -side right -padx 5
 207        pack $w.buttons -side bottom -fill x -pady 10 -padx 10
 208        frame $w.list
 210        set w_names $w.list.l
 211        listbox $w_names \
 212                -height 10 \
 213                -width 30 \
 214                -selectmode extended \
 215                -exportselection false \
 216                -yscrollcommand [list $w.list.sby set]
 217        scrollbar $w.list.sby -command [list $w.list.l yview]
 218        pack $w.list.sby -side right -fill y
 219        pack $w.list.l -side left -fill both -expand 1
 220        pack $w.list -fill both -expand 1 -pady 5 -padx 5
 221        set local_cnt 0
 223        foreach fullname [tools_list] {
 224                # Cannot delete system tools
 225                if {[info exists system_config(guitool.$fullname.cmd)]} continue
 226                $w_names insert end $fullname
 228                if {![info exists global_config(guitool.$fullname.cmd)]} {
 229                        $w_names itemconfigure end -foreground blue
 230                        incr local_cnt
 231                }
 232        }
 233        if {$local_cnt > 0} {
 235                label $w.colorlbl -foreground blue \
 236                        -text [mc "(Blue denotes repository-local tools)"]
 237                pack $w.colorlbl -fill x -pady 5 -padx 5
 238        }
 239        bind $w <Visibility> [cb _visible]
 241        bind $w <Key-Escape> [list destroy $w]
 242        bind $w <Key-Return> [cb _remove]\;break
 243        tkwait window $w
 244}
 245method _remove {} {
 247        foreach i [$w_names curselection] {
 248                set name [$w_names get $i]
 249                catch { git config --remove-section guitool.$name }
 251                catch { git config --global --remove-section guitool.$name }
 252        }
 253        load_config 0
 255        tools_populate_all
 256        destroy $w
 258}
 259method _visible {} {
 261        grab $w
 262        focus $w_names
 263}
 264}
 266class tools_askdlg {
 268field w              ; # widget path
 270field w_rev        {}; # revision browser
 271field w_args       {}; # arguments
 272field is_ask_args   0; # has arguments field
 274field is_ask_revs   0; # has revision browser
 275field is_ok         0; # ok to start
 277field argstr       {}; # arguments
 278constructor dialog {fullname} {
 280        global M1B
 281        set title [get_config "guitool.$fullname.title"]
 283        if {$title eq {}} {
 284                regsub {/} $fullname { / } title
 285        }
 286        make_toplevel top w -autodelete 0
 288        wm title $top [append "[appname] ([reponame]): " $title]
 289        if {$top ne {.}} {
 290                wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
 291                wm transient $top .
 292        }
 293        set prompt [get_config "guitool.$fullname.prompt"]
 295        if {$prompt eq {}} {
 296                set command [get_config "guitool.$fullname.cmd"]
 297                set prompt [mc "Run Command: %s" $command]
 298        }
 299        label $w.header -text $prompt -font font_uibold
 301        pack $w.header -side top -fill x
 302        set argprompt [get_config "guitool.$fullname.argprompt"]
 304        set revprompt [get_config "guitool.$fullname.revprompt"]
 305        set is_ask_args [expr {$argprompt ne {}}]
 307        set is_ask_revs [expr {$revprompt ne {}}]
 308        if {$is_ask_args} {
 310                if {$argprompt eq {yes} || $argprompt eq {true} || $argprompt eq {1}} {
 311                        set argprompt [mc "Arguments"]
 312                }
 313                labelframe $w.arg -text $argprompt
 315                set w_args $w.arg.txt
 317                entry $w_args \
 318                        -borderwidth 1 \
 319                        -relief sunken \
 320                        -width 40 \
 321                        -textvariable @argstr
 322                pack $w_args -padx 5 -pady 5 -fill both
 323                pack $w.arg -anchor nw -fill both -pady 5 -padx 5
 324        }
 325        if {$is_ask_revs} {
 327                if {$revprompt eq {yes} || $revprompt eq {true} || $revprompt eq {1}} {
 328                        set revprompt [mc "Revision"]
 329                }
 330                if {[is_config_true "guitool.$fullname.revunmerged"]} {
 332                        set w_rev [::choose_rev::new_unmerged $w.rev $revprompt]
 333                } else {
 334                        set w_rev [::choose_rev::new $w.rev $revprompt]
 335                }
 336                pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5
 338        }
 339        frame $w.buttons
 341        if {$is_ask_revs} {
 342                button $w.buttons.visualize \
 343                        -text [mc Visualize] \
 344                        -command [cb _visualize]
 345                pack $w.buttons.visualize -side left
 346        }
 347        button $w.buttons.ok \
 348                -text [mc OK] \
 349                -command [cb _start]
 350        pack $w.buttons.ok -side right
 351        button $w.buttons.cancel \
 352                -text [mc "Cancel"] \
 353                -command [cb _cancel]
 354        pack $w.buttons.cancel -side right -padx 5
 355        pack $w.buttons -side bottom -fill x -pady 10 -padx 10
 356        bind $w <$M1B-Key-Return> [cb _start]
 358        bind $w <Key-Return> [cb _start]
 359        bind $w <Key-Escape> [cb _cancel]
 360        wm protocol $w WM_DELETE_WINDOW [cb _cancel]
 361        bind $w <Visibility> [cb _visible]
 363        return $this
 364}
 365method execute {} {
 367        tkwait window $w
 368        set rv $is_ok
 369        delete_this
 370        return $rv
 371}
 372method _visible {} {
 374        grab $w
 375        if {$is_ask_args} {
 376                focus $w_args
 377        } elseif {$is_ask_revs} {
 378                $w_rev focus_filter
 379        }
 380}
 381method _cancel {} {
 383        wm protocol $w WM_DELETE_WINDOW {}
 384        destroy $w
 385}
 386method _rev {} {
 388        if {[catch {$w_rev commit_or_die}]} {
 389                return {}
 390        }
 391        return [$w_rev get]
 392}
 393method _visualize {} {
 395        global current_branch
 396        set rev [_rev $this]
 397        if {$rev ne {}} {
 398                do_gitk [list --left-right "$current_branch...$rev"]
 399        }
 400}
 401method _start {} {
 403        global env
 404        if {$is_ask_revs} {
 406                set name [_rev $this]
 407                if {$name eq {}} {
 408                        return
 409                }
 410                set env(REVISION) $name
 411        }
 412        if {$is_ask_args} {
 414                set env(ARGS) $argstr
 415        }
 416        set is_ok 1
 418        _cancel $this
 419}
 420}