diff options
Diffstat (limited to 'git-gui/lib')
31 files changed, 1174 insertions, 659 deletions
diff --git a/git-gui/lib/about.tcl b/git-gui/lib/about.tcl index 241ab892cd..cfa50fca87 100644 --- a/git-gui/lib/about.tcl +++ b/git-gui/lib/about.tcl @@ -4,31 +4,26 @@  proc do_about {} {  	global appvers copyright oguilib  	global tcl_patchLevel tk_patchLevel -	global ui_comm_spell +	global ui_comm_spell NS use_ttk  	set w .about_dialog -	toplevel $w +	Dialog $w  	wm geometry $w "+[winfo rootx .]+[winfo rooty .]"  	pack [git_logo $w.git_logo] -side left -fill y -padx 10 -pady 10 -	label $w.header -text [mc "About %s" [appname]] \ -		-font font_uibold +	${NS}::label $w.header -text [mc "About %s" [appname]] \ +		-font font_uibold -anchor center  	pack $w.header -side top -fill x -	frame $w.buttons -	button $w.buttons.close -text {Close} \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.close -text {Close} \  		-default active \  		-command [list destroy $w]  	pack $w.buttons.close -side right  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 -	label $w.desc \ -		-text "[mc "git-gui - a graphical user interface for Git."]\n$copyright" \ -		-padx 5 -pady 5 \ -		-justify left \ -		-anchor w \ -		-borderwidth 1 \ -		-relief solid +	paddedlabel $w.desc \ +		-text "[mc "git-gui - a graphical user interface for Git."]\n$copyright"  	pack $w.desc -side top -fill x -padx 5 -pady 5  	set v {} @@ -52,22 +47,10 @@ proc do_about {} {  	append d "git exec dir: [gitexec]\n"  	append d "git-gui lib: $oguilib" -	label $w.vers \ -		-text $v \ -		-padx 5 -pady 5 \ -		-justify left \ -		-anchor w \ -		-borderwidth 1 \ -		-relief solid +	paddedlabel $w.vers -text $v  	pack $w.vers -side top -fill x -padx 5 -pady 5 -	label $w.dirs \ -		-text $d \ -		-padx 5 -pady 5 \ -		-justify left \ -		-anchor w \ -		-borderwidth 1 \ -		-relief solid +	paddedlabel $w.dirs -text $d  	pack $w.dirs -side top -fill x -padx 5 -pady 5  	menu $w.ctxm -tearoff 0 diff --git a/git-gui/lib/blame.tcl b/git-gui/lib/blame.tcl index 1f3b08f9ef..61e358f960 100644 --- a/git-gui/lib/blame.tcl +++ b/git-gui/lib/blame.tcl @@ -61,7 +61,7 @@ field tooltip_timer     {} ; # Current timer event for our tooltip  field tooltip_commit    {} ; # Commit(s) in tooltip  constructor new {i_commit i_path i_jump} { -	global cursor_ptr M1B M1T have_tk85 +	global cursor_ptr M1B M1T have_tk85 use_ttk NS  	variable active_color  	variable group_colors @@ -73,15 +73,15 @@ constructor new {i_commit i_path i_jump} {  	set font_w [font measure font_diff "0"] -	frame $w.header -background gold -	label $w.header.commit_l \ +	gold_frame $w.header +	tlabel $w.header.commit_l \  		-text [mc "Commit:"] \  		-background gold \  		-foreground black \  		-anchor w \  		-justify left  	set w_back $w.header.commit_b -	label $w_back \ +	tlabel $w_back \  		-image ::blame::img_back_arrow \  		-borderwidth 0 \  		-relief flat \ @@ -94,20 +94,20 @@ constructor new {i_commit i_path i_jump} {  			[cb _history_menu]  		}  		" -	label $w.header.commit \ +	tlabel $w.header.commit \  		-textvariable @commit \  		-background gold \  		-foreground black \  		-anchor w \  		-justify left -	label $w.header.path_l \ +	tlabel $w.header.path_l \  		-text [mc "File:"] \  		-background gold \  		-foreground black \  		-anchor w \  		-justify left  	set w_path $w.header.path -	label $w_path \ +	tlabel $w_path \  		-background gold \  		-foreground black \  		-anchor w \ @@ -209,10 +209,10 @@ constructor new {i_commit i_path i_jump} {  	set w_columns [list $w_amov $w_asim $w_line $w_file] -	scrollbar $w.file_pane.out.sbx \ +	${NS}::scrollbar $w.file_pane.out.sbx \  		-orient h \  		-command [list $w_file xview] -	scrollbar $w.file_pane.out.sby \ +	${NS}::scrollbar $w.file_pane.out.sby \  		-orient v \  		-command [list scrollbar2many $w_columns yview]  	eval grid $w_columns $w.file_pane.out.sby -sticky nsew @@ -254,10 +254,10 @@ constructor new {i_commit i_path i_jump} {  		-background $active_color \  		-font font_ui  	$w_cviewer tag raise sel -	scrollbar $w.file_pane.cm.sbx \ +	${NS}::scrollbar $w.file_pane.cm.sbx \  		-orient h \  		-command [list $w_cviewer xview] -	scrollbar $w.file_pane.cm.sby \ +	${NS}::scrollbar $w.file_pane.cm.sby \  		-orient v \  		-command [list $w_cviewer yview]  	pack $w.file_pane.cm.sby -side right -fill y @@ -449,11 +449,35 @@ method _load {jump} {  	$status show [mc "Reading %s..." "$commit:[escape_path $path]"]  	$w_path conf -text [escape_path $path] + +	set do_textconv 0 +	if {![is_config_false gui.textconv] && [git-version >= 1.7.2]} { +		set filter [gitattr $path diff set] +		set textconv [get_config [join [list diff $filter textconv] .]] +		if {$filter ne {set} && $textconv ne {}} { +			set do_textconv 1 +		} +	}  	if {$commit eq {}} { -		set fd [open $path r] +		if {$do_textconv ne 0} { +			# Run textconv with sh -c "..." to allow it to +			# contain command + arguments. On windows, just +			# call the filter command. +			if {![file executable [shellpath]]} { +				set fd [open |[linsert $textconv end $path] r] +			} else { +				set fd [open |[list [shellpath] -c "$textconv \"\$0\"" $path] r] +			} +		} else { +			set fd [open $path r] +		}  		fconfigure $fd -eofchar {}  	} else { -		set fd [git_read cat-file blob "$commit:$path"] +		if {$do_textconv ne 0} { +			set fd [git_read cat-file --textconv "$commit:$path"] +		} else { +			set fd [git_read cat-file blob "$commit:$path"] +		}  	}  	fconfigure $fd \  		-blocking 0 \ @@ -1245,6 +1269,18 @@ method _open_tooltip {cur_w} {  	$tooltip_t conf -state disabled  	_position_tooltip $this + +	# On MacOS raising a window causes it to acquire focus. +	# Tk 8.5 on MacOS seems to properly support wm transient, +	# so we can safely counter the effect there. +	if {$::have_tk85 && [is_MacOSX]} { +		update +		if {$w eq {}} { +			raise . +		} else { +			raise $w +		} +	}  }  method _position_tooltip {} { @@ -1268,7 +1304,9 @@ method _position_tooltip {} {  	append g $pos_y  	wm geometry $tooltip_wm $g -	raise $tooltip_wm +	if {![is_MacOSX]} { +		raise $tooltip_wm +	}  }  method _hide_tooltip {} { diff --git a/git-gui/lib/branch_checkout.tcl b/git-gui/lib/branch_checkout.tcl index 6603703ea1..2e459a8297 100644 --- a/git-gui/lib/branch_checkout.tcl +++ b/git-gui/lib/branch_checkout.tcl @@ -10,21 +10,24 @@ field opt_fetch     1; # refetch tracking branch if used?  field opt_detach    0; # force a detached head case?  constructor dialog {} { -	make_toplevel top w +	global use_ttk NS +	make_dialog top w +	wm withdraw $w  	wm title $top [append "[appname] ([reponame]): " [mc "Checkout Branch"]]  	if {$top ne {.}} {  		wm geometry $top "+[winfo rootx .]+[winfo rooty .]"  	} -	label $w.header -text [mc "Checkout Branch"] -font font_uibold +	${NS}::label $w.header -text [mc "Checkout Branch"] \ +		-font font_uibold -anchor center  	pack $w.header -side top -fill x -	frame $w.buttons -	button $w.buttons.create -text [mc Checkout] \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.create -text [mc Checkout] \  		-default active \  		-command [cb _checkout]  	pack $w.buttons.create -side right -	button $w.buttons.cancel -text [mc Cancel] \ +	${NS}::button $w.buttons.cancel -text [mc Cancel] \  		-command [list destroy $w]  	pack $w.buttons.cancel -side right -padx 5  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 @@ -33,14 +36,14 @@ constructor dialog {} {  	$w_rev bind_listbox <Double-Button-1> [cb _checkout]  	pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5 -	labelframe $w.options -text [mc Options] +	${NS}::labelframe $w.options -text [mc Options] -	checkbutton $w.options.fetch \ +	${NS}::checkbutton $w.options.fetch \  		-text [mc "Fetch Tracking Branch"] \  		-variable @opt_fetch  	pack $w.options.fetch -anchor nw -	checkbutton $w.options.detach \ +	${NS}::checkbutton $w.options.detach \  		-text [mc "Detach From Local Branch"] \  		-variable @opt_detach  	pack $w.options.detach -anchor nw @@ -50,6 +53,7 @@ constructor dialog {} {  	bind $w <Visibility> [cb _visible]  	bind $w <Key-Escape> [list destroy $w]  	bind $w <Key-Return> [cb _checkout]\;break +	wm deiconify $w  	tkwait window $w  } diff --git a/git-gui/lib/branch_create.tcl b/git-gui/lib/branch_create.tcl index 3817771b94..4bb907705c 100644 --- a/git-gui/lib/branch_create.tcl +++ b/git-gui/lib/branch_create.tcl @@ -16,48 +16,48 @@ field opt_fetch     1; # refetch tracking branch if used?  field reset_ok      0; # did the user agree to reset?  constructor dialog {} { -	global repo_config +	global repo_config use_ttk NS -	make_toplevel top w +	make_dialog top w +	wm withdraw $w  	wm title $top [append "[appname] ([reponame]): " [mc "Create Branch"]]  	if {$top ne {.}} {  		wm geometry $top "+[winfo rootx .]+[winfo rooty .]"  	} -	label $w.header -text [mc "Create New Branch"] -font font_uibold +	${NS}::label $w.header -text [mc "Create New Branch"] \ +		-font font_uibold -anchor center  	pack $w.header -side top -fill x -	frame $w.buttons -	button $w.buttons.create -text [mc Create] \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.create -text [mc Create] \  		-default active \  		-command [cb _create]  	pack $w.buttons.create -side right -	button $w.buttons.cancel -text [mc Cancel] \ +	${NS}::button $w.buttons.cancel -text [mc Cancel] \  		-command [list destroy $w]  	pack $w.buttons.cancel -side right -padx 5  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 -	labelframe $w.desc -text [mc "Branch Name"] -	radiobutton $w.desc.name_r \ -		-anchor w \ +	${NS}::labelframe $w.desc -text [mc "Branch Name"] +	${NS}::radiobutton $w.desc.name_r \  		-text [mc "Name:"] \  		-value user \  		-variable @name_type +	if {!$use_ttk} {$w.desc.name_r configure -anchor w}  	set w_name $w.desc.name_t -	entry $w_name \ -		-borderwidth 1 \ -		-relief sunken \ +	${NS}::entry $w_name \  		-width 40 \  		-textvariable @name \  		-validate key \  		-validatecommand [cb _validate %d %S]  	grid $w.desc.name_r $w_name -sticky we -padx {0 5} -	radiobutton $w.desc.match_r \ -		-anchor w \ +	${NS}::radiobutton $w.desc.match_r \  		-text [mc "Match Tracking Branch Name"] \  		-value match \  		-variable @name_type +	if {!$use_ttk} {$w.desc.match_r configure -anchor w}  	grid $w.desc.match_r -sticky we -padx {0 5} -columnspan 2  	grid columnconfigure $w.desc 1 -weight 1 @@ -66,34 +66,34 @@ constructor dialog {} {  	set w_rev [::choose_rev::new $w.rev [mc "Starting Revision"]]  	pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5 -	labelframe $w.options -text [mc Options] +	${NS}::labelframe $w.options -text [mc Options] -	frame $w.options.merge -	label $w.options.merge.l -text [mc "Update Existing Branch:"] +	${NS}::frame $w.options.merge +	${NS}::label $w.options.merge.l -text [mc "Update Existing Branch:"]  	pack $w.options.merge.l -side left -	radiobutton $w.options.merge.no \ +	${NS}::radiobutton $w.options.merge.no \  		-text [mc No] \  		-value none \  		-variable @opt_merge  	pack $w.options.merge.no -side left -	radiobutton $w.options.merge.ff \ +	${NS}::radiobutton $w.options.merge.ff \  		-text [mc "Fast Forward Only"] \  		-value ff \  		-variable @opt_merge  	pack $w.options.merge.ff -side left -	radiobutton $w.options.merge.reset \ +	${NS}::radiobutton $w.options.merge.reset \  		-text [mc Reset] \  		-value reset \  		-variable @opt_merge  	pack $w.options.merge.reset -side left  	pack $w.options.merge -anchor nw -	checkbutton $w.options.fetch \ +	${NS}::checkbutton $w.options.fetch \  		-text [mc "Fetch Tracking Branch"] \  		-variable @opt_fetch  	pack $w.options.fetch -anchor nw -	checkbutton $w.options.checkout \ +	${NS}::checkbutton $w.options.checkout \  		-text [mc "Checkout After Creation"] \  		-variable @opt_checkout  	pack $w.options.checkout -anchor nw @@ -109,6 +109,7 @@ constructor dialog {} {  	bind $w <Visibility> [cb _visible]  	bind $w <Key-Escape> [list destroy $w]  	bind $w <Key-Return> [cb _create]\;break +	wm deiconify $w  	tkwait window $w  } diff --git a/git-gui/lib/branch_delete.tcl b/git-gui/lib/branch_delete.tcl index 20d5e42307..867938ec6a 100644 --- a/git-gui/lib/branch_delete.tcl +++ b/git-gui/lib/branch_delete.tcl @@ -9,41 +9,40 @@ field w_check         ; # revision picker for merge test  field w_delete        ; # delete button  constructor dialog {} { -	global current_branch +	global current_branch use_ttk NS -	make_toplevel top w +	make_dialog top w +	wm withdraw $w  	wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch"]]  	if {$top ne {.}} {  		wm geometry $top "+[winfo rootx .]+[winfo rooty .]"  	} -	label $w.header -text [mc "Delete Local Branch"] -font font_uibold +	${NS}::label $w.header -text [mc "Delete Local Branch"] \ +		-font font_uibold -anchor center  	pack $w.header -side top -fill x -	frame $w.buttons +	${NS}::frame $w.buttons  	set w_delete $w.buttons.delete -	button $w_delete \ +	${NS}::button $w_delete \  		-text [mc Delete] \  		-default active \  		-state disabled \  		-command [cb _delete]  	pack $w_delete -side right -	button $w.buttons.cancel \ +	${NS}::button $w.buttons.cancel \  		-text [mc Cancel] \  		-command [list destroy $w]  	pack $w.buttons.cancel -side right -padx 5  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 -	labelframe $w.list -text [mc "Local Branches"] +	${NS}::labelframe $w.list -text [mc "Local Branches"]  	set w_heads $w.list.l -	listbox $w_heads \ +	slistbox $w_heads \  		-height 10 \  		-width 70 \  		-selectmode extended \ -		-exportselection false \ -		-yscrollcommand [list $w.list.sby set] -	scrollbar $w.list.sby -command [list $w.list.l yview] -	pack $w.list.sby -side right -fill y +		-exportselection false  	pack $w.list.l -side left -fill both -expand 1  	pack $w.list -fill both -expand 1 -pady 5 -padx 5 @@ -67,6 +66,7 @@ constructor dialog {} {  	"  	bind $w <Key-Escape> [list destroy $w]  	bind $w <Key-Return> [cb _delete]\;break +	wm deiconify $w  	tkwait window $w  } diff --git a/git-gui/lib/branch_rename.tcl b/git-gui/lib/branch_rename.tcl index 166538808f..6e510ec2e3 100644 --- a/git-gui/lib/branch_rename.tcl +++ b/git-gui/lib/branch_rename.tcl @@ -8,9 +8,10 @@ field oldname  field newname  constructor dialog {} { -	global current_branch +	global current_branch use_ttk NS -	make_toplevel top w +	make_dialog top w +	wm withdraw $w  	wm title $top [append "[appname] ([reponame]): " [mc "Rename Branch"]]  	if {$top ne {.}} {  		wm geometry $top "+[winfo rootx .]+[winfo rooty .]" @@ -19,27 +20,31 @@ constructor dialog {} {  	set oldname $current_branch  	set newname [get_config gui.newbranchtemplate] -	label $w.header -text [mc "Rename Branch"] -font font_uibold +	${NS}::label $w.header -text [mc "Rename Branch"]\ +		-font font_uibold -anchor center  	pack $w.header -side top -fill x -	frame $w.buttons -	button $w.buttons.rename -text [mc Rename] \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.rename -text [mc Rename] \  		-default active \  		-command [cb _rename]  	pack $w.buttons.rename -side right -	button $w.buttons.cancel -text [mc Cancel] \ +	${NS}::button $w.buttons.cancel -text [mc Cancel] \  		-command [list destroy $w]  	pack $w.buttons.cancel -side right -padx 5  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 -	frame $w.rename -	label $w.rename.oldname_l -text [mc "Branch:"] -	eval tk_optionMenu $w.rename.oldname_m @oldname [load_all_heads] +	${NS}::frame $w.rename +	${NS}::label $w.rename.oldname_l -text [mc "Branch:"] +	if {$use_ttk} { +		ttk::combobox $w.rename.oldname_m -textvariable @oldname \ +			-values [load_all_heads] -state readonly +	} else { +		eval tk_optionMenu $w.rename.oldname_m @oldname [load_all_heads] +	} -	label $w.rename.newname_l -text [mc "New Name:"] -	entry $w.rename.newname_t \ -		-borderwidth 1 \ -		-relief sunken \ +	${NS}::label $w.rename.newname_l -text [mc "New Name:"] +	${NS}::entry $w.rename.newname_t \  		-width 40 \  		-textvariable @newname \  		-validate key \ @@ -48,7 +53,7 @@ constructor dialog {} {  			return 1  		} -	grid $w.rename.oldname_l $w.rename.oldname_m -sticky w  -padx {0 5} +	grid $w.rename.oldname_l $w.rename.oldname_m -sticky we -padx {0 5}  	grid $w.rename.newname_l $w.rename.newname_t -sticky we -padx {0 5}  	grid columnconfigure $w.rename 1 -weight 1  	pack $w.rename -anchor nw -fill x -pady 5 -padx 5 @@ -60,6 +65,7 @@ constructor dialog {} {  		$w.rename.newname_t icursor end  		focus $w.rename.newname_t  	" +	wm deiconify $w  	tkwait window $w  } diff --git a/git-gui/lib/browser.tcl b/git-gui/lib/browser.tcl index 0410cc68df..a8c6223511 100644 --- a/git-gui/lib/browser.tcl +++ b/git-gui/lib/browser.tcl @@ -21,23 +21,23 @@ field browser_busy   1  field ls_buf     {}; # Buffered record output from ls-tree  constructor new {commit {path {}}} { -	global cursor_ptr M1B -	make_toplevel top w +	global cursor_ptr M1B use_ttk NS +	make_dialog top w +	wm withdraw $top  	wm title $top [append "[appname] ([reponame]): " [mc "File Browser"]]  	set browser_commit $commit  	set browser_path $browser_commit:$path -	label $w.path \ +	${NS}::label $w.path \  		-textvariable @browser_path \  		-anchor w \  		-justify left \ -		-borderwidth 1 \ -		-relief sunken \  		-font font_uibold +	if {!$use_ttk} { $w.path configure -borderwidth 1 -relief sunken}  	pack $w.path -anchor w -side top -fill x -	frame $w.list +	${NS}::frame $w.list  	set w_list $w.list.l  	text $w_list -background white -foreground black \  		-borderwidth 0 \ @@ -49,19 +49,18 @@ constructor new {commit {path {}}} {  		-xscrollcommand [list $w.list.sbx set] \  		-yscrollcommand [list $w.list.sby set]  	rmsel_tag $w_list -	scrollbar $w.list.sbx -orient h -command [list $w_list xview] -	scrollbar $w.list.sby -orient v -command [list $w_list yview] +	${NS}::scrollbar $w.list.sbx -orient h -command [list $w_list xview] +	${NS}::scrollbar $w.list.sby -orient v -command [list $w_list yview]  	pack $w.list.sbx -side bottom -fill x  	pack $w.list.sby -side right -fill y  	pack $w_list -side left -fill both -expand 1  	pack $w.list -side top -fill both -expand 1 -	label $w.status \ +	${NS}::label $w.status \  		-textvariable @browser_status \  		-anchor w \ -		-justify left \ -		-borderwidth 1 \ -		-relief sunken +		-justify left +	if {!$use_ttk} { $w.status configure -borderwidth 1 -relief sunken}  	pack $w.status -anchor w -side bottom -fill x  	bind $w_list <Button-1>        "[cb _click 0 @%x,%y];break" @@ -78,6 +77,7 @@ constructor new {commit {path {}}} {  	bind $w_list <Right>           break  	bind $w_list <Visibility> [list focus $w_list] +	wm deiconify $top  	set w $w_list  	if {$path ne {}} {  		_ls $this $browser_commit:$path $path @@ -121,7 +121,7 @@ method _parent {} {  		if {$browser_stack eq {}} {  			regsub {:.*$} $browser_path {:} browser_path  		} else { -			regsub {/[^/]+$} $browser_path {} browser_path +			regsub {/[^/]+/$} $browser_path {/} browser_path  		}  		set browser_status [mc "Loading %s..." $browser_path]  		_ls $this [lindex $parent 0] [lindex $parent 1] @@ -263,23 +263,27 @@ field w              ; # widget path  field w_rev          ; # mega-widget to pick the initial revision  constructor dialog {} { -	make_toplevel top w +	global use_ttk NS +	make_dialog top w +	wm withdraw $top  	wm title $top [append "[appname] ([reponame]): " [mc "Browse Branch Files"]]  	if {$top ne {.}} {  		wm geometry $top "+[winfo rootx .]+[winfo rooty .]" +		wm transient $top .  	} -	label $w.header \ +	${NS}::label $w.header \  		-text [mc "Browse Branch Files"] \ -		-font font_uibold +		-font font_uibold \ +		-anchor center  	pack $w.header -side top -fill x -	frame $w.buttons -	button $w.buttons.browse -text [mc Browse] \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.browse -text [mc Browse] \  		-default active \  		-command [cb _open]  	pack $w.buttons.browse -side right -	button $w.buttons.cancel -text [mc Cancel] \ +	${NS}::button $w.buttons.cancel -text [mc Cancel] \  		-command [list destroy $w]  	pack $w.buttons.cancel -side right -padx 5  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 @@ -291,6 +295,7 @@ constructor dialog {} {  	bind $w <Visibility> [cb _visible]  	bind $w <Key-Escape> [list destroy $w]  	bind $w <Key-Return> [cb _open]\;break +	wm deiconify $top  	tkwait window $w  } diff --git a/git-gui/lib/choose_font.tcl b/git-gui/lib/choose_font.tcl index 56443b042c..ebe50bd7d0 100644 --- a/git-gui/lib/choose_font.tcl +++ b/git-gui/lib/choose_font.tcl @@ -17,6 +17,7 @@ variable all_families [list]  ; # All fonts known to Tk  constructor pick {path title a_family a_size} {  	variable all_families +	global use_ttk NS  	set v_family $a_family  	set v_size $a_size @@ -27,29 +28,30 @@ constructor pick {path title a_family a_size} {  	set f_family $pv_family  	set f_size $pv_size -	make_toplevel top w +	make_dialog top w +	wm withdraw $top  	wm title $top "[appname] ([reponame]): $title"  	wm geometry $top "+[winfo rootx $path]+[winfo rooty $path]" -	label $w.header -text $title -font font_uibold +	${NS}::label $w.header -text $title -font font_uibold -anchor center  	pack $w.header -side top -fill x -	frame $w.buttons -	button $w.buttons.select \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.select \  		-text [mc Select] \  		-default active \  		-command [cb _select] -	button $w.buttons.cancel \ +	${NS}::button $w.buttons.cancel \  		-text [mc Cancel] \  		-command [list destroy $w]  	pack $w.buttons.select -side right  	pack $w.buttons.cancel -side right -padx 5  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 -	frame $w.inner +	${NS}::frame $w.inner -	frame $w.inner.family -	label $w.inner.family.l \ +	${NS}::frame $w.inner.family +	${NS}::label $w.inner.family.l \  		-text [mc "Font Family"] \  		-anchor w  	set w_family $w.inner.family.v @@ -64,16 +66,16 @@ constructor pick {path title a_family a_size} {  		-height 10 \  		-yscrollcommand [list $w.inner.family.sby set]  	rmsel_tag $w_family -	scrollbar $w.inner.family.sby -command [list $w_family yview] +	${NS}::scrollbar $w.inner.family.sby -command [list $w_family yview]  	pack $w.inner.family.l -side top -fill x  	pack $w.inner.family.sby -side right -fill y  	pack $w_family -fill both -expand 1 -	frame $w.inner.size -	label $w.inner.size.l \ +	${NS}::frame $w.inner.size +	${NS}::label $w.inner.size.l \  		-text [mc "Font Size"] \  		-anchor w -	spinbox $w.inner.size.v \ +	tspinbox $w.inner.size.v \  		-textvariable @f_size \  		-from 2 -to 80 -increment 1 \  		-width 3 @@ -86,8 +88,8 @@ constructor pick {path title a_family a_size} {  	grid columnconfigure $w.inner 0 -weight 1  	pack $w.inner -fill both -expand 1 -padx 5 -pady 5 -	frame $w.example -	label $w.example.l \ +	${NS}::frame $w.example +	${NS}::label $w.example.l \  		-text [mc "Font Example"] \  		-anchor w  	set w_example $w.example.t @@ -129,6 +131,7 @@ constructor pick {path title a_family a_size} {  		grab $w  		focus $w  	" +	wm deiconify $w  	tkwait window $w  } diff --git a/git-gui/lib/choose_repository.tcl b/git-gui/lib/choose_repository.tcl index 633cc572bb..657f7d5dc1 100644 --- a/git-gui/lib/choose_repository.tcl +++ b/git-gui/lib/choose_repository.tcl @@ -22,9 +22,9 @@ field readtree_err        ; # Error output from read-tree (if any)  field sorted_recent       ; # recent repositories (sorted)  constructor pick {} { -	global M1T M1B +	global M1T M1B use_ttk NS -	make_toplevel top w +	make_dialog top w  	wm title $top [mc "Git Gui"]  	if {$top eq {.}} { @@ -71,11 +71,11 @@ constructor pick {} {  	set w_body $w.body  	set opts $w_body.options -	frame $w_body +	${NS}::frame $w_body  	text $opts \  		-cursor $::cursor_ptr \  		-relief flat \ -		-background [$w_body cget -background] \ +		-background [get_bg_color $w_body] \  		-wrap none \  		-spacing1 5 \  		-width 50 \ @@ -100,12 +100,17 @@ constructor pick {} {  	$opts insert end [mc "Clone Existing Repository"] link_clone  	$opts insert end "\n"  	if {$m_repo ne {}} { +		if {[tk windowingsystem] eq "win32"} { +			set key L +		} else { +			set key C +		}  		$m_repo add command \  			-command [cb _next clone] \ -			-accelerator $M1T-C \ +			-accelerator $M1T-$key \  			-label [mc "Clone..."] -		bind $top <$M1B-c> [cb _next clone] -		bind $top <$M1B-C> [cb _next clone] +		bind $top <$M1B-[string tolower $key]> [cb _next clone] +		bind $top <$M1B-[string toupper $key]> [cb _next clone]  	}  	$opts tag conf link_open -foreground blue -underline 1 @@ -132,15 +137,15 @@ constructor pick {} {  				-label [mc "Recent Repositories"]  		} -		label $w_body.space -		label $w_body.recentlabel \ +		${NS}::label $w_body.space +		${NS}::label $w_body.recentlabel \  			-anchor w \  			-text [mc "Open Recent Repository:"]  		set w_recentlist $w_body.recentlist  		text $w_recentlist \  			-cursor $::cursor_ptr \  			-relief flat \ -			-background [$w_body.recentlabel cget -background] \ +			-background [get_bg_color $w_body.recentlabel] \  			-wrap none \  			-width 50 \  			-height 10 @@ -176,10 +181,10 @@ constructor pick {} {  	}  	pack $w_body -fill x -padx 10 -pady 10 -	frame $w.buttons +	${NS}::frame $w.buttons  	set w_next $w.buttons.next  	set w_quit $w.buttons.quit -	button $w_quit \ +	${NS}::button $w_quit \  		-text [mc "Quit"] \  		-command exit  	pack $w_quit -side right -padx 5 @@ -203,19 +208,12 @@ constructor pick {} {  	wm deiconify $top  	tkwait variable @done +	grab release $top  	if {$top eq {.}} {  		eval destroy [winfo children $top]  	}  } -proc _home {} { -	if {[catch {set h $::env(HOME)}] -		|| ![file isdirectory $h]} { -		set h . -	} -	return $h -} -  method _center {} {  	set nx [winfo reqwidth $top]  	set ny [winfo reqheight $top] @@ -235,6 +233,8 @@ proc _get_recentrepos {} {  	foreach p [get_config gui.recentrepo] {  		if {[_is_git [file join $p .git]]} {  			lappend recent $p +		} else { +			_unset_recentrepo $p  		}  	}  	return [lsort $recent] @@ -243,6 +243,7 @@ proc _get_recentrepos {} {  proc _unset_recentrepo {p} {  	regsub -all -- {([()\[\]{}\.^$+*?\\])} $p {\\\1} p  	git config --global --unset gui.recentrepo "^$p\$" +	load_config 1  }  proc _append_recentrepos {path} { @@ -261,6 +262,7 @@ proc _append_recentrepos {path} {  	lappend recent $path  	git config --global --add gui.recentrepo $path +	load_config 1  	while {[llength $recent] > 10} {  		_unset_recentrepo [lindex $recent 0] @@ -280,9 +282,10 @@ method _open_recent_path {p} {  }  method _next {action} { +	global NS  	destroy $w_body  	if {![winfo exists $w_next]} { -		button $w_next -default active +		${NS}::button $w_next -default active  		pack $w_next -side right -padx 5 -before $w_quit  	}  	_do_$action $this @@ -371,26 +374,25 @@ proc _objdir {path} {  ## Create New Repository  method _do_new {} { +	global use_ttk NS  	$w_next conf \  		-state disabled \  		-command [cb _do_new2] \  		-text [mc "Create"] -	frame $w_body -	label $w_body.h \ -		-font font_uibold \ +	${NS}::frame $w_body +	${NS}::label $w_body.h \ +		-font font_uibold -anchor center \  		-text [mc "Create New Repository"]  	pack $w_body.h -side top -fill x -pady 10  	pack $w_body -fill x -padx 10 -	frame $w_body.where -	label $w_body.where.l -text [mc "Directory:"] -	entry $w_body.where.t \ +	${NS}::frame $w_body.where +	${NS}::label $w_body.where.l -text [mc "Directory:"] +	${NS}::entry $w_body.where.t \  		-textvariable @local_path \ -		-borderwidth 1 \ -		-relief sunken \  		-width 50 -	button $w_body.where.b \ +	${NS}::button $w_body.where.b \  		-text [mc "Browse"] \  		-command [cb _new_local_path]  	set w_localpath $w_body.where.t @@ -410,7 +412,7 @@ method _new_local_path {} {  	if {$local_path ne {}} {  		set p [file dirname $local_path]  	} else { -		set p [_home] +		set p [pwd]  	}  	set p [tk_chooseDirectory \ @@ -456,63 +458,57 @@ proc _new_ok {p} {  ## Clone Existing Repository  method _do_clone {} { +	global use_ttk NS  	$w_next conf \  		-state disabled \  		-command [cb _do_clone2] \  		-text [mc "Clone"] -	frame $w_body -	label $w_body.h \ -		-font font_uibold \ +	${NS}::frame $w_body +	${NS}::label $w_body.h \ +		-font font_uibold -anchor center \  		-text [mc "Clone Existing Repository"]  	pack $w_body.h -side top -fill x -pady 10  	pack $w_body -fill x -padx 10  	set args $w_body.args -	frame $w_body.args +	${NS}::frame $w_body.args  	pack $args -fill both -	label $args.origin_l -text [mc "Source Location:"] -	entry $args.origin_t \ +	${NS}::label $args.origin_l -text [mc "Source Location:"] +	${NS}::entry $args.origin_t \  		-textvariable @origin_url \ -		-borderwidth 1 \ -		-relief sunken \  		-width 50 -	button $args.origin_b \ +	${NS}::button $args.origin_b \  		-text [mc "Browse"] \  		-command [cb _open_origin]  	grid $args.origin_l $args.origin_t $args.origin_b -sticky ew -	label $args.where_l -text [mc "Target Directory:"] -	entry $args.where_t \ +	${NS}::label $args.where_l -text [mc "Target Directory:"] +	${NS}::entry $args.where_t \  		-textvariable @local_path \ -		-borderwidth 1 \ -		-relief sunken \  		-width 50 -	button $args.where_b \ +	${NS}::button $args.where_b \  		-text [mc "Browse"] \  		-command [cb _new_local_path]  	grid $args.where_l $args.where_t $args.where_b -sticky ew  	set w_localpath $args.where_t -	label $args.type_l -text [mc "Clone Type:"] -	frame $args.type_f +	${NS}::label $args.type_l -text [mc "Clone Type:"] +	${NS}::frame $args.type_f  	set w_types [list] -	lappend w_types [radiobutton $args.type_f.hardlink \ +	lappend w_types [${NS}::radiobutton $args.type_f.hardlink \  		-state disabled \ -		-anchor w \  		-text [mc "Standard (Fast, Semi-Redundant, Hardlinks)"] \  		-variable @clone_type \  		-value hardlink] -	lappend w_types [radiobutton $args.type_f.full \ +	lappend w_types [${NS}::radiobutton $args.type_f.full \  		-state disabled \ -		-anchor w \  		-text [mc "Full Copy (Slower, Redundant Backup)"] \  		-variable @clone_type \  		-value full] -	lappend w_types [radiobutton $args.type_f.shared \ +	lappend w_types [${NS}::radiobutton $args.type_f.shared \  		-state disabled \ -		-anchor w \  		-text [mc "Shared (Fastest, Not Recommended, No Backup)"] \  		-variable @clone_type \  		-value shared] @@ -537,7 +533,7 @@ method _open_origin {} {  	if {$origin_url ne {} && [file isdirectory $origin_url]} {  		set p $origin_url  	} else { -		set p [_home] +		set p [pwd]  	}  	set p [tk_chooseDirectory \ @@ -1001,26 +997,25 @@ method _postcheckout_wait {fd_ph} {  ## Open Existing Repository  method _do_open {} { +	global NS  	$w_next conf \  		-state disabled \  		-command [cb _do_open2] \  		-text [mc "Open"] -	frame $w_body -	label $w_body.h \ -		-font font_uibold \ +	${NS}::frame $w_body +	${NS}::label $w_body.h \ +		-font font_uibold -anchor center \  		-text [mc "Open Existing Repository"]  	pack $w_body.h -side top -fill x -pady 10  	pack $w_body -fill x -padx 10 -	frame $w_body.where -	label $w_body.where.l -text [mc "Repository:"] -	entry $w_body.where.t \ +	${NS}::frame $w_body.where +	${NS}::label $w_body.where.l -text [mc "Repository:"] +	${NS}::entry $w_body.where.t \  		-textvariable @local_path \ -		-borderwidth 1 \ -		-relief sunken \  		-width 50 -	button $w_body.where.b \ +	${NS}::button $w_body.where.b \  		-text [mc "Browse"] \  		-command [cb _open_local_path] @@ -1039,7 +1034,7 @@ method _open_local_path {} {  	if {$local_path ne {}} {  		set p $local_path  	} else { -		set p [_home] +		set p [pwd]  	}  	set p [tk_chooseDirectory \ diff --git a/git-gui/lib/choose_rev.tcl b/git-gui/lib/choose_rev.tcl index c8821c1463..c12d5e1698 100644 --- a/git-gui/lib/choose_rev.tcl +++ b/git-gui/lib/choose_rev.tcl @@ -10,7 +10,7 @@ field w_list          ; # list of currently filtered specs  field w_filter        ; # filter entry for $w_list  field c_expr        {}; # current revision expression -field filter          ; # current filter string +field filter        ""; # current filter string  field revtype     head; # type of revision chosen  field cur_specs [list]; # list of specs for $revtype  field spec_head       ; # list of all head specs @@ -32,7 +32,7 @@ proc new_unmerged {path {title {}}} {  }  constructor _new {path unmerged_only title} { -	global current_branch is_detached +	global current_branch is_detached use_ttk NS  	if {![info exists ::all_remotes]} {  		load_all_remotes @@ -41,65 +41,65 @@ constructor _new {path unmerged_only title} {  	set w $path  	if {$title ne {}} { -		labelframe $w -text $title +		${NS}::labelframe $w -text $title  	} else { -		frame $w +		${NS}::frame $w  	}  	bind $w <Destroy> [cb _delete %W]  	if {$is_detached} { -		radiobutton $w.detachedhead_r \ -			-anchor w \ +		${NS}::radiobutton $w.detachedhead_r \  			-text [mc "This Detached Checkout"] \  			-value HEAD \  			-variable @revtype +		if {!$use_ttk} {$w.detachedhead_r configure -anchor w}  		grid $w.detachedhead_r -sticky we -padx {0 5} -columnspan 2  	} -	radiobutton $w.expr_r \ +	${NS}::radiobutton $w.expr_r \  		-text [mc "Revision Expression:"] \  		-value expr \  		-variable @revtype -	entry $w.expr_t \ -		-borderwidth 1 \ -		-relief sunken \ +	${NS}::entry $w.expr_t \  		-width 50 \  		-textvariable @c_expr \  		-validate key \  		-validatecommand [cb _validate %d %S]  	grid $w.expr_r $w.expr_t -sticky we -padx {0 5} -	frame $w.types -	radiobutton $w.types.head_r \ +	${NS}::frame $w.types +	${NS}::radiobutton $w.types.head_r \  		-text [mc "Local Branch"] \  		-value head \  		-variable @revtype  	pack $w.types.head_r -side left -	radiobutton $w.types.trck_r \ +	${NS}::radiobutton $w.types.trck_r \  		-text [mc "Tracking Branch"] \  		-value trck \  		-variable @revtype  	pack $w.types.trck_r -side left -	radiobutton $w.types.tag_r \ +	${NS}::radiobutton $w.types.tag_r \  		-text [mc "Tag"] \  		-value tag \  		-variable @revtype  	pack $w.types.tag_r -side left  	set w_filter $w.types.filter -	entry $w_filter \ -		-borderwidth 1 \ -		-relief sunken \ +	${NS}::entry $w_filter \  		-width 12 \  		-textvariable @filter \  		-validate key \  		-validatecommand [cb _filter %P]  	pack $w_filter -side right -	pack [label $w.types.filter_icon \ +	pack [${NS}::label $w.types.filter_icon \  		-image ::choose_rev::img_find \  		] -side right  	grid $w.types -sticky we -padx {0 5} -columnspan 2 -	frame $w.list +	if {$use_ttk} { +		ttk::frame $w.list -style SListbox.TFrame -padding 2 +	} else { +		frame $w.list +	}  	set w_list $w.list.l  	listbox $w_list \  		-font font_diff \ @@ -109,6 +109,9 @@ constructor _new {path unmerged_only title} {  		-exportselection false \  		-xscrollcommand [cb _sb_set $w.list.sbx h] \  		-yscrollcommand [cb _sb_set $w.list.sby v] +	if {$use_ttk} { +		$w_list configure -relief flat -highlightthickness 0 -borderwidth 0 +	}  	pack $w_list -fill both -expand 1  	grid $w.list -sticky nswe -padx {20 5} -columnspan 2  	bind $w_list <Any-Motion>  [cb _show_tooltip @%x,%y] @@ -235,11 +238,12 @@ constructor _new {path unmerged_only title} {  }  method none {text} { +	global NS use_ttk  	if {![winfo exists $w.none_r]} { -		radiobutton $w.none_r \ -			-anchor w \ +		${NS}::radiobutton $w.none_r \  			-value none \  			-variable @revtype +		if {!$use_ttk} {$w.none_r configure -anchor w}  		grid $w.none_r -sticky we -padx {0 5} -columnspan 2  	}  	$w.none_r configure -text $text @@ -425,6 +429,7 @@ method _delete {current} {  }  method _sb_set {sb orient first last} { +	global NS  	set old_focus [focus -lastfor $w]  	if {$first == 0 && $last == 1} { @@ -440,10 +445,10 @@ method _sb_set {sb orient first last} {  	if {![winfo exists $sb]} {  		if {$orient eq {h}} { -			scrollbar $sb -orient h -command [list $w_list xview] +			${NS}::scrollbar $sb -orient h -command [list $w_list xview]  			pack $sb -fill x -side bottom -before $w_list  		} else { -			scrollbar $sb -orient v -command [list $w_list yview] +			${NS}::scrollbar $sb -orient v -command [list $w_list yview]  			pack $sb -fill y -side right -before $w_list  		}  		if {$old_focus ne {}} { diff --git a/git-gui/lib/class.tcl b/git-gui/lib/class.tcl index dc2141192a..c27b71476a 100644 --- a/git-gui/lib/class.tcl +++ b/git-gui/lib/class.tcl @@ -134,6 +134,13 @@ proc delete_this {{t {}}} {  	if {[namespace exists $t]} {namespace delete $t}  } +proc make_dialog {t w args} { +	upvar $t top $w pfx this this +	global use_ttk +	uplevel [linsert $args 0 make_toplevel $t $w] +	pave_toplevel $pfx +} +  proc make_toplevel {t w args} {  	upvar $t top $w pfx this this diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl index 7f459cd564..5ce46877bf 100644 --- a/git-gui/lib/commit.tcl +++ b/git-gui/lib/commit.tcl @@ -161,11 +161,12 @@ The rescan will be automatically started now.  	#  	set files_ready 0  	foreach path [array names file_states] { -		switch -glob -- [lindex $file_states($path) 0] { +		set s $file_states($path) +		switch -glob -- [lindex $s 0] {  		_? {continue}  		A? -  		D? - -		T_ - +		T? -  		M? {set files_ready 1}  		_U -  		U? { @@ -452,7 +453,11 @@ A rescan will be automatically started now.  		}  		AM -  		AD - +		AT - +		TM - +		TD -  		MM - +		MT -  		MD {  			set file_states($path) [list \  				_[string index $m 1] \ diff --git a/git-gui/lib/console.tcl b/git-gui/lib/console.tcl index c112464ec3..1f3248ffd1 100644 --- a/git-gui/lib/console.tcl +++ b/git-gui/lib/console.tcl @@ -27,20 +27,20 @@ constructor embed {path title} {  }  method _init {} { -	global M1B +	global M1B use_ttk NS  	if {$is_toplevel} { -		make_toplevel top w -autodelete 0 +		make_dialog top w -autodelete 0  		wm title $top "[appname] ([reponame]): $t_short"  	} else { -		frame $w +		${NS}::frame $w  	}  	set console_cr 1.0  	set w_t $w.m.t -	frame $w.m -	label $w.m.l1 \ +	${NS}::frame $w.m +	${NS}::label $w.m.l1 \  		-textvariable @t_long  \  		-anchor w \  		-justify left \ @@ -78,7 +78,7 @@ method _init {} {  		"  	if {$is_toplevel} { -		button $w.ok -text [mc "Close"] \ +		${NS}::button $w.ok -text [mc "Close"] \  			-state disabled \  			-command [list destroy $w]  		pack $w.ok -side bottom -anchor e -pady 10 -padx 10 @@ -206,13 +206,14 @@ method done {ok} {  }  method _sb_set {sb orient first last} { +	global NS  	if {![winfo exists $sb]} {  		if {$first == $last || ($first == 0 && $last == 1)} return  		if {$orient eq {h}} { -			scrollbar $sb -orient h -command [list $w_t xview] +			${NS}::scrollbar $sb -orient h -command [list $w_t xview]  			pack $sb -fill x -side bottom -before $w_t  		} else { -			scrollbar $sb -orient v -command [list $w_t yview] +			${NS}::scrollbar $sb -orient v -command [list $w_t yview]  			pack $sb -fill y -side right -before $w_t  		}  	} diff --git a/git-gui/lib/database.tcl b/git-gui/lib/database.tcl index a18ac8b430..1f187ed286 100644 --- a/git-gui/lib/database.tcl +++ b/git-gui/lib/database.tcl @@ -2,6 +2,7 @@  # Copyright (C) 2006, 2007 Shawn Pearce  proc do_stats {} { +	global use_ttk NS  	set fd [git_read count-objects -v]  	while {[gets $fd line] > 0} {  		if {[regexp {^([^:]+): (\d+)$} $line _ name value]} { @@ -21,24 +22,22 @@ proc do_stats {} {  	}  	set w .stats_view -	toplevel $w +	Dialog $w +	wm withdraw $w  	wm geometry $w "+[winfo rootx .]+[winfo rooty .]" -	label $w.header -text [mc "Database Statistics"] -	pack $w.header -side top -fill x - -	frame $w.buttons -border 1 -	button $w.buttons.close -text [mc Close] \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.close -text [mc Close] \  		-default active \  		-command [list destroy $w] -	button $w.buttons.gc -text [mc "Compress Database"] \ +	${NS}::button $w.buttons.gc -text [mc "Compress Database"] \  		-default normal \  		-command "destroy $w;do_gc"  	pack $w.buttons.close -side right  	pack $w.buttons.gc -side left  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 -	frame $w.stat -borderwidth 1 -relief solid +	${NS}::labelframe $w.stat -text [mc "Database Statistics"]  	foreach s {  		{count           {mc "Number of loose objects"}}  		{size            {mc "Disk space used by loose objects"} { KiB}} @@ -55,8 +54,8 @@ proc do_stats {} {  			set value "$value[lindex $s 2]"  		} -		label $w.stat.l_$name -text "$label:" -anchor w -		label $w.stat.v_$name -text $value -anchor w +		${NS}::label $w.stat.l_$name -text "$label:" -anchor w +		${NS}::label $w.stat.v_$name -text $value -anchor w  		grid $w.stat.l_$name $w.stat.v_$name -sticky we -padx {0 5}  	}  	pack $w.stat -pady 10 -padx 10 @@ -65,6 +64,7 @@ proc do_stats {} {  	bind $w <Key-Escape> [list destroy $w]  	bind $w <Key-Return> [list destroy $w]  	wm title $w [append "[appname] ([reponame]): " [mc "Database Statistics"]] +	wm deiconify $w  	tkwait window $w  } @@ -89,27 +89,26 @@ proc do_fsck_objects {} {  }  proc hint_gc {} { -	set object_limit 8 +	set ndirs 1 +	set limit 8  	if {[is_Windows]} { -		set object_limit 1 +		set ndirs 4 +		set limit 1  	} -	set objects_current [llength [glob \ -		-directory [gitdir objects 42] \ +	set count [llength [glob \  		-nocomplain \ -		-tails \  		-- \ -		*]] +		[gitdir objects 4\[0-[expr {$ndirs-1}]\]/*]]] -	if {$objects_current >= $object_limit} { -		set objects_current [expr {$objects_current * 250}] -		set object_limit    [expr {$object_limit    * 250}] +	if {$count >= $limit * $ndirs} { +		set objects_current [expr {$count * 256/$ndirs}]  		if {[ask_popup \  			[mc "This repository currently has approximately %i loose objects. -To maintain optimal performance it is strongly recommended that you compress the database when more than %i loose objects exist. +To maintain optimal performance it is strongly recommended that you compress the database. -Compress the database now?" $objects_current $object_limit]] eq yes} { +Compress the database now?" $objects_current]] eq yes} {  			do_gc  		}  	} diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl index 925b3f56c1..cf8a95ec34 100644 --- a/git-gui/lib/diff.tcl +++ b/git-gui/lib/diff.tcl @@ -55,7 +55,7 @@ proc handle_empty_diff {} {  	set path $current_diff_path  	set s $file_states($path) -	if {[lindex $s 0] ne {_M}} return +	if {[lindex $s 0] ne {_M} || [has_textconv $path]} return  	# Prevent infinite rescan loops  	incr diff_empty_count @@ -122,22 +122,22 @@ proc show_unmerged_diff {cont_info} {  	if {$merge_stages(2) eq {}} {  		set is_conflict_diff 1  		lappend current_diff_queue \ -			[list [mc "LOCAL: deleted\nREMOTE:\n"] d======= \ +			[list [mc "LOCAL: deleted\nREMOTE:\n"] d= \  			    [list ":1:$current_diff_path" ":3:$current_diff_path"]]  	} elseif {$merge_stages(3) eq {}} {  		set is_conflict_diff 1  		lappend current_diff_queue \ -			[list [mc "REMOTE: deleted\nLOCAL:\n"] d======= \ +			[list [mc "REMOTE: deleted\nLOCAL:\n"] d= \  			    [list ":1:$current_diff_path" ":2:$current_diff_path"]]  	} elseif {[lindex $merge_stages(1) 0] eq {120000}  		|| [lindex $merge_stages(2) 0] eq {120000}  		|| [lindex $merge_stages(3) 0] eq {120000}} {  		set is_conflict_diff 1  		lappend current_diff_queue \ -			[list [mc "LOCAL:\n"] d======= \ +			[list [mc "LOCAL:\n"] d= \  			    [list ":1:$current_diff_path" ":2:$current_diff_path"]]  		lappend current_diff_queue \ -			[list [mc "REMOTE:\n"] d======= \ +			[list [mc "REMOTE:\n"] d= \  			    [list ":1:$current_diff_path" ":3:$current_diff_path"]]  	} else {  		start_show_diff $cont_info @@ -208,32 +208,32 @@ proc show_other_diff {path w m cont_info} {  			$ui_diff insert end [append \  				"* " \  				[mc "Git Repository (subproject)"] \ -				"\n"] d_@ +				"\n"] d_info  		} elseif {![catch {set type [exec file $path]}]} {  			set n [string length $path]  			if {[string equal -length $n $path $type]} {  				set type [string range $type $n end]  				regsub {^:?\s*} $type {} type  			} -			$ui_diff insert end "* $type\n" d_@ +			$ui_diff insert end "* $type\n" d_info  		}  		if {[string first "\0" $content] != -1} {  			$ui_diff insert end \  				[mc "* Binary file (not showing content)."] \ -				d_@ +				d_info  		} else {  			if {$sz > $max_sz} {  				$ui_diff insert end [mc \  "* Untracked file is %d bytes.  * Showing only first %d bytes. -" $sz $max_sz] d_@ +" $sz $max_sz] d_info  			}  			$ui_diff insert end $content  			if {$sz > $max_sz} {  				$ui_diff insert end [mc "  * Untracked file clipped here by %s.  * To see the entire file, use an external editor. -" [appname]] d_@ +" [appname]] d_info  			}  		}  		$ui_diff conf -state disabled @@ -253,9 +253,22 @@ proc show_other_diff {path w m cont_info} {  	}  } +proc get_conflict_marker_size {path} { +	set size 7 +	catch { +		set fd_rc [eval [list git_read check-attr "conflict-marker-size" -- $path]] +		set ret [gets $fd_rc line] +		close $fd_rc +		if {$ret > 0} { +			regexp {.*: conflict-marker-size: (\d+)$} $line line size +		} +	} +	return $size +} +  proc start_show_diff {cont_info {add_opts {}}} {  	global file_states file_lists -	global is_3way_diff diff_active repo_config +	global is_3way_diff is_submodule_diff diff_active repo_config  	global ui_diff ui_index ui_workdir  	global current_diff_path current_diff_side current_diff_header @@ -265,8 +278,10 @@ proc start_show_diff {cont_info {add_opts {}}} {  	set s $file_states($path)  	set m [lindex $s 0]  	set is_3way_diff 0 +	set is_submodule_diff 0  	set diff_active 1  	set current_diff_header {} +	set conflict_size [get_conflict_marker_size $path]  	set cmd [list]  	if {$w eq $ui_index} { @@ -279,9 +294,21 @@ proc start_show_diff {cont_info {add_opts {}}} {  			lappend cmd diff-files  		}  	} +	if {![is_config_false gui.textconv] && [git-version >= 1.6.1]} { +		lappend cmd --textconv +	} + +	if {[string match {160000 *} [lindex $s 2]] +	 || [string match {160000 *} [lindex $s 3]]} { +		set is_submodule_diff 1 + +		if {[git-version >= "1.6.6"]} { +			lappend cmd --submodule +		} +	}  	lappend cmd -p -	lappend cmd --no-color +	lappend cmd --color  	if {$repo_config(gui.diffcontext) >= 1} {  		lappend cmd "-U$repo_config(gui.diffcontext)"  	} @@ -295,6 +322,14 @@ proc start_show_diff {cont_info {add_opts {}}} {  		lappend cmd $path  	} +	if {$is_submodule_diff && [git-version < "1.6.6"]} { +		if {$w eq $ui_index} { +			set cmd [list submodule summary --cached -- $path] +		} else { +			set cmd [list submodule summary --files -- $path] +		} +	} +  	if {[catch {set fd [eval git_read --nice $cmd]} err]} {  		set diff_active 0  		unlock_index @@ -308,48 +343,89 @@ proc start_show_diff {cont_info {add_opts {}}} {  		-blocking 0 \  		-encoding [get_path_encoding $path] \  		-translation lf -	fileevent $fd readable [list read_diff $fd $cont_info] +	fileevent $fd readable [list read_diff $fd $conflict_size $cont_info]  } -proc read_diff {fd cont_info} { -	global ui_diff diff_active +proc parse_color_line {line} { +	set start 0 +	set result "" +	set markup [list] +	set regexp {\033\[((?:\d+;)*\d+)?m} +	set need_reset 0 +	while {[regexp -indices -start $start $regexp $line match code]} { +		foreach {begin end} $match break +		append result [string range $line $start [expr {$begin - 1}]] +		set pos [string length $result] +		set col [eval [linsert $code 0 string range $line]] +		set start [incr end] +		if {$col eq "0" || $col eq ""} { +			if {!$need_reset} continue +			set need_reset 0 +		} else { +			set need_reset 1 +		} +		lappend markup $pos $col +	} +	append result [string range $line $start end] +	if {[llength $markup] < 4} {set markup {}} +	return [list $result $markup] +} + +proc read_diff {fd conflict_size cont_info} { +	global ui_diff diff_active is_submodule_diff  	global is_3way_diff is_conflict_diff current_diff_header  	global current_diff_queue  	global diff_empty_count  	$ui_diff conf -state normal  	while {[gets $fd line] >= 0} { -		# -- Cleanup uninteresting diff header lines. +		foreach {line markup} [parse_color_line $line] break +		set line [string map {\033 ^} $line] + +		set tags {} + +		# -- Check for start of diff header. +		if {   [string match {diff --git *}      $line] +		    || [string match {diff --cc *}       $line] +		    || [string match {diff --combined *} $line]} { +			set ::current_diff_inheader 1 +		} + +		# -- Check for end of diff header (any hunk line will do this).  		# +		if {[regexp {^@@+ } $line]} {set ::current_diff_inheader 0} + +		# -- Automatically detect if this is a 3 way diff. +		# +		if {[string match {@@@ *} $line]} {set is_3way_diff 1} +  		if {$::current_diff_inheader} { + +			# -- These two lines stop a diff header and shouldn't be in there +			if {   [string match {Binary files * and * differ} $line] +			    || [regexp {^\* Unmerged path }                $line]} { +				set ::current_diff_inheader 0 +			} else { +				append current_diff_header $line "\n" +			} + +			# -- Cleanup uninteresting diff header lines. +			#  			if {   [string match {diff --git *}      $line]  			    || [string match {diff --cc *}       $line]  			    || [string match {diff --combined *} $line]  			    || [string match {--- *}             $line] -			    || [string match {+++ *}             $line]} { -				append current_diff_header $line "\n" +			    || [string match {+++ *}             $line] +			    || [string match {index *}           $line]} {  				continue  			} -		} -		if {[string match {index *} $line]} continue -		if {$line eq {deleted file mode 120000}} { -			set line "deleted symlink" -		} -		set ::current_diff_inheader 0 -		# -- Automatically detect if this is a 3 way diff. -		# -		if {[string match {@@@ *} $line]} {set is_3way_diff 1} +			# -- Name it symlink, not 120000 +			#    Note, that the original line is in $current_diff_header +			regsub {^(deleted|new) file mode 120000} $line {\1 symlink} line -		if {[string match {mode *} $line] -			|| [string match {new file *} $line] -			|| [regexp {^(old|new) mode *} $line] -			|| [string match {deleted file *} $line] -			|| [string match {deleted symlink} $line] -			|| [string match {Binary files * and * differ} $line] -			|| $line eq {\ No newline at end of file} -			|| [regexp {^\* Unmerged path } $line]} { -			set tags {} +		} elseif {   $line eq {\ No newline at end of file}} { +			# -- Handle some special lines  		} elseif {$is_3way_diff} {  			set op [string range $line 0 1]  			switch -- $op { @@ -361,7 +437,9 @@ proc read_diff {fd cont_info} {  			{- } {set tags d_-s}  			{--} {set tags d_--}  			{++} { -				if {[regexp {^\+\+([<>]{7} |={7})} $line _g op]} { +				set regexp [string map [list %conflict_size $conflict_size]\ +								{^\+\+([<>=]){%conflict_size}(?: |$)}] +				if {[regexp $regexp $line _g op]} {  					set is_conflict_diff 1  					set line [string replace $line 0 1 {  }]  					set tags d$op @@ -374,6 +452,25 @@ proc read_diff {fd cont_info} {  				set tags {}  			}  			} +		} elseif {$is_submodule_diff} { +			if {$line == ""} continue +			if {[regexp {^Submodule } $line]} { +				set tags d_info +			} elseif {[regexp {^\* } $line]} { +				set line [string replace $line 0 1 {Submodule }] +				set tags d_info +			} else { +				set op [string range $line 0 2] +				switch -- $op { +				{  <} {set tags d_-} +				{  >} {set tags d_+} +				{  W} {set tags {}} +				default { +					puts "error: Unhandled submodule diff marker: {$op}" +					set tags {} +				} +				} +			}  		} else {  			set op [string index $line 0]  			switch -- $op { @@ -381,7 +478,9 @@ proc read_diff {fd cont_info} {  			{@} {set tags d_@}  			{-} {set tags d_-}  			{+} { -				if {[regexp {^\+([<>]{7} |={7})} $line _g op]} { +				set regexp [string map [list %conflict_size $conflict_size]\ +								{^\+([<>=]){%conflict_size}(?: |$)}] +				if {[regexp $regexp $line _g op]} {  					set is_conflict_diff 1  					set tags d$op  				} else { @@ -394,11 +493,23 @@ proc read_diff {fd cont_info} {  			}  			}  		} +		set mark [$ui_diff index "end - 1 line linestart"]  		$ui_diff insert end $line $tags  		if {[string index $line end] eq "\r"} {  			$ui_diff tag add d_cr {end - 2c}  		}  		$ui_diff insert end "\n" $tags + +		foreach {posbegin colbegin posend colend} $markup { +			set prefix clr +			foreach style [split $colbegin ";"] { +				if {$style eq "7"} {append prefix i; continue} +				if {$style < 30 || $style > 47} {continue} +				set a "$mark linestart + $posbegin chars" +				set b "$mark linestart + $posend chars" +				catch {$ui_diff tag add $prefix$style $a $b} +			} +		}  	}  	$ui_diff conf -state disabled @@ -505,10 +616,23 @@ proc apply_hunk {x y} {  	}  } -proc apply_line {x y} { +proc apply_range_or_line {x y} {  	global current_diff_path current_diff_header current_diff_side  	global ui_diff ui_index file_states +	set selected [$ui_diff tag nextrange sel 0.0] + +	if {$selected == {}} { +		set first [$ui_diff index "@$x,$y"] +		set last $first +	} else { +		set first [lindex $selected 0] +		set last [lindex $selected 1] +	} + +	set first_l [$ui_diff index "$first linestart"] +	set last_l [$ui_diff index "$last lineend"] +  	if {$current_diff_path eq {} || $current_diff_header eq {}} return  	if {![lock_index apply_hunk]} return @@ -531,119 +655,147 @@ proc apply_line {x y} {  		}  	} -	set the_l [$ui_diff index @$x,$y] - -	# operate only on change lines -	set c1 [$ui_diff get "$the_l linestart"] -	if {$c1 ne {+} && $c1 ne {-}} { -		unlock_index -		return -	} -	set sign $c1 +	set wholepatch {} -	set i_l [$ui_diff search -backwards -regexp ^@@ $the_l 0.0] -	if {$i_l eq {}} { -		unlock_index -		return -	} -	# $i_l is now at the beginning of a line +	while {$first_l < $last_l} { +		set i_l [$ui_diff search -backwards -regexp ^@@ $first_l 0.0] +		if {$i_l eq {}} { +			# If there's not a @@ above, then the selected range +			# must have come before the first_l @@ +			set i_l [$ui_diff search -regexp ^@@ $first_l $last_l] +		} +		if {$i_l eq {}} { +			unlock_index +			return +		} +		# $i_l is now at the beginning of a line -	# pick start line number from hunk header -	set hh [$ui_diff get $i_l "$i_l + 1 lines"] -	set hh [lindex [split $hh ,] 0] -	set hln [lindex [split $hh -] 1] +		# pick start line number from hunk header +		set hh [$ui_diff get $i_l "$i_l + 1 lines"] +		set hh [lindex [split $hh ,] 0] +		set hln [lindex [split $hh -] 1] -	# There is a special situation to take care of. Consider this hunk: -	# -	#    @@ -10,4 +10,4 @@ -	#     context before -	#    -old 1 -	#    -old 2 -	#    +new 1 -	#    +new 2 -	#     context after -	# -	# We used to keep the context lines in the order they appear in the -	# hunk. But then it is not possible to correctly stage only -	# "-old 1" and "+new 1" - it would result in this staged text: -	# -	#    context before -	#    old 2 -	#    new 1 -	#    context after -	# -	# (By symmetry it is not possible to *un*stage "old 2" and "new 2".) -	# -	# We resolve the problem by introducing an asymmetry, namely, when -	# a "+" line is *staged*, it is moved in front of the context lines -	# that are generated from the "-" lines that are immediately before -	# the "+" block. That is, we construct this patch: -	# -	#    @@ -10,4 +10,5 @@ -	#     context before -	#    +new 1 -	#     old 1 -	#     old 2 -	#     context after -	# -	# But we do *not* treat "-" lines that are *un*staged in a special -	# way. -	# -	# With this asymmetry it is possible to stage the change -	# "old 1" -> "new 1" directly, and to stage the change -	# "old 2" -> "new 2" by first staging the entire hunk and -	# then unstaging the change "old 1" -> "new 1". - -	# This is non-empty if and only if we are _staging_ changes; -	# then it accumulates the consecutive "-" lines (after converting -	# them to context lines) in order to be moved after the "+" change -	# line. -	set pre_context {} - -	set n 0 -	set i_l [$ui_diff index "$i_l + 1 lines"] -	set patch {} -	while {[$ui_diff compare $i_l < "end - 1 chars"] && -	       [$ui_diff get $i_l "$i_l + 2 chars"] ne {@@}} { -		set next_l [$ui_diff index "$i_l + 1 lines"] -		set c1 [$ui_diff get $i_l] -		if {[$ui_diff compare $i_l <= $the_l] && -		    [$ui_diff compare $the_l < $next_l]} { -			# the line to stage/unstage -			set ln [$ui_diff get $i_l $next_l] -			if {$c1 eq {-}} { -				set n [expr $n+1] +		# There is a special situation to take care of. Consider this +		# hunk: +		# +		#    @@ -10,4 +10,4 @@ +		#     context before +		#    -old 1 +		#    -old 2 +		#    +new 1 +		#    +new 2 +		#     context after +		# +		# We used to keep the context lines in the order they appear in +		# the hunk. But then it is not possible to correctly stage only +		# "-old 1" and "+new 1" - it would result in this staged text: +		# +		#    context before +		#    old 2 +		#    new 1 +		#    context after +		# +		# (By symmetry it is not possible to *un*stage "old 2" and "new +		# 2".) +		# +		# We resolve the problem by introducing an asymmetry, namely, +		# when a "+" line is *staged*, it is moved in front of the +		# context lines that are generated from the "-" lines that are +		# immediately before the "+" block. That is, we construct this +		# patch: +		# +		#    @@ -10,4 +10,5 @@ +		#     context before +		#    +new 1 +		#     old 1 +		#     old 2 +		#     context after +		# +		# But we do *not* treat "-" lines that are *un*staged in a +		# special way. +		# +		# With this asymmetry it is possible to stage the change "old +		# 1" -> "new 1" directly, and to stage the change "old 2" -> +		# "new 2" by first staging the entire hunk and then unstaging +		# the change "old 1" -> "new 1". +		# +		# Applying multiple lines adds complexity to the special +		# situation.  The pre_context must be moved after the entire +		# first block of consecutive staged "+" lines, so that +		# staging both additions gives the following patch: +		# +		#    @@ -10,4 +10,6 @@ +		#     context before +		#    +new 1 +		#    +new 2 +		#     old 1 +		#     old 2 +		#     context after + +		# This is non-empty if and only if we are _staging_ changes; +		# then it accumulates the consecutive "-" lines (after +		# converting them to context lines) in order to be moved after +		# "+" change lines. +		set pre_context {} + +		set n 0 +		set m 0 +		set i_l [$ui_diff index "$i_l + 1 lines"] +		set patch {} +		while {[$ui_diff compare $i_l < "end - 1 chars"] && +		       [$ui_diff get $i_l "$i_l + 2 chars"] ne {@@}} { +			set next_l [$ui_diff index "$i_l + 1 lines"] +			set c1 [$ui_diff get $i_l] +			if {[$ui_diff compare $first_l <= $i_l] && +			    [$ui_diff compare $i_l < $last_l] && +			    ($c1 eq {-} || $c1 eq {+})} { +				# a line to stage/unstage +				set ln [$ui_diff get $i_l $next_l] +				if {$c1 eq {-}} { +					set n [expr $n+1] +					set patch "$patch$pre_context$ln" +					set pre_context {} +				} else { +					set m [expr $m+1] +					set patch "$patch$ln" +				} +			} elseif {$c1 ne {-} && $c1 ne {+}} { +				# context line +				set ln [$ui_diff get $i_l $next_l]  				set patch "$patch$pre_context$ln" +				set n [expr $n+1] +				set m [expr $m+1] +				set pre_context {} +			} elseif {$c1 eq $to_context} { +				# turn change line into context line +				set ln [$ui_diff get "$i_l + 1 chars" $next_l] +				if {$c1 eq {-}} { +					set pre_context "$pre_context $ln" +				} else { +					set patch "$patch $ln" +				} +				set n [expr $n+1] +				set m [expr $m+1]  			} else { -				set patch "$patch$ln$pre_context" -			} -			set pre_context {} -		} elseif {$c1 ne {-} && $c1 ne {+}} { -			# context line -			set ln [$ui_diff get $i_l $next_l] -			set patch "$patch$pre_context$ln" -			set n [expr $n+1] -			set pre_context {} -		} elseif {$c1 eq $to_context} { -			# turn change line into context line -			set ln [$ui_diff get "$i_l + 1 chars" $next_l] -			if {$c1 eq {-}} { -				set pre_context "$pre_context $ln" -			} else { -				set patch "$patch $ln" +				# a change in the opposite direction of +				# to_context which is outside the range of +				# lines to apply. +				set patch "$patch$pre_context" +				set pre_context {}  			} -			set n [expr $n+1] +			set i_l $next_l  		} -		set i_l $next_l +		set patch "$patch$pre_context" +		set wholepatch "$wholepatch@@ -$hln,$n +$hln,$m @@\n$patch" +		set first_l [$ui_diff index "$next_l + 1 lines"]  	} -	set patch "@@ -$hln,$n +$hln,[eval expr $n $sign 1] @@\n$patch"  	if {[catch {  		set enc [get_path_encoding $current_diff_path]  		set p [eval git_write $apply_cmd]  		fconfigure $p -translation binary -encoding $enc  		puts -nonewline $p $current_diff_header -		puts -nonewline $p $patch +		puts -nonewline $p $wholepatch  		close $p} err]} {  		error_popup [append $failed_msg "\n\n$err"]  	} diff --git a/git-gui/lib/error.tcl b/git-gui/lib/error.tcl index 75650157e5..c0fa69af56 100644 --- a/git-gui/lib/error.tcl +++ b/git-gui/lib/error.tcl @@ -71,11 +71,13 @@ proc ask_popup {msg} {  }  proc hook_failed_popup {hook msg {is_fatal 1}} { +	global use_ttk NS  	set w .hookfail -	toplevel $w +	Dialog $w +	wm withdraw $w -	frame $w.m -	label $w.m.l1 -text "$hook hook failed:" \ +	${NS}::frame $w.m +	${NS}::label $w.m.l1 -text "$hook hook failed:" \  		-anchor w \  		-justify left \  		-font font_uibold @@ -87,10 +89,10 @@ proc hook_failed_popup {hook msg {is_fatal 1}} {  		-width 80 -height 10 \  		-font font_diff \  		-yscrollcommand [list $w.m.sby set] -	scrollbar $w.m.sby -command [list $w.m.t yview] +	${NS}::scrollbar $w.m.sby -command [list $w.m.t yview]  	pack $w.m.l1 -side top -fill x  	if {$is_fatal} { -		label $w.m.l2 \ +		${NS}::label $w.m.l2 \  			-text [mc "You must correct the above errors before committing."] \  			-anchor w \  			-justify left \ @@ -104,7 +106,7 @@ proc hook_failed_popup {hook msg {is_fatal 1}} {  	$w.m.t insert 1.0 $msg  	$w.m.t conf -state disabled -	button $w.ok -text OK \ +	${NS}::button $w.ok -text OK \  		-width 15 \  		-command "destroy $w"  	pack $w.ok -side bottom -anchor e -pady 10 -padx 10 @@ -112,5 +114,6 @@ proc hook_failed_popup {hook msg {is_fatal 1}} {  	bind $w <Visibility> "grab $w; focus $w"  	bind $w <Key-Return> "destroy $w"  	wm title $w [strcat "[appname] ([reponame]): " [mc "error"]] +	wm deiconify $w  	tkwait window $w  } diff --git a/git-gui/lib/index.tcl b/git-gui/lib/index.tcl index d33896a0ce..5d7bbf23ed 100644 --- a/git-gui/lib/index.tcl +++ b/git-gui/lib/index.tcl @@ -8,36 +8,41 @@ proc _delete_indexlock {} {  }  proc _close_updateindex {fd after} { +	global use_ttk NS  	fconfigure $fd -blocking 1  	if {[catch {close $fd} err]} {  		set w .indexfried -		toplevel $w +		Dialog $w +		wm withdraw $w  		wm title $w [strcat "[appname] ([reponame]): " [mc "Index Error"]]  		wm geometry $w "+[winfo rootx .]+[winfo rooty .]" -		pack [label $w.msg \ -			-justify left \ -			-anchor w \ -			-text [strcat \ -				[mc "Updating the Git index failed.  A rescan will be automatically started to resynchronize git-gui."] \ -				"\n\n$err"] \ -			] -anchor w - -		frame $w.buttons -		button $w.buttons.continue \ +		set s [mc "Updating the Git index failed.  A rescan will be automatically started to resynchronize git-gui."] +		text $w.msg -yscrollcommand [list $w.vs set] \ +			-width [string length $s] -relief flat \ +			-borderwidth 0 -highlightthickness 0 \ +			-background [get_bg_color $w] +		$w.msg tag configure bold -font font_uibold -justify center +		${NS}::scrollbar $w.vs -command [list $w.msg yview] +		$w.msg insert end $s bold \n\n$err {} +		$w.msg configure -state disabled + +		${NS}::button $w.continue \  			-text [mc "Continue"] \  			-command [list destroy $w] -		pack $w.buttons.continue -side right -padx 5 -		button $w.buttons.unlock \ +		${NS}::button $w.unlock \  			-text [mc "Unlock Index"] \  			-command "destroy $w; _delete_indexlock" -		pack $w.buttons.unlock -side right -		pack $w.buttons -side bottom -fill x -pady 10 -padx 10 +		grid $w.msg - $w.vs -sticky news +		grid $w.unlock $w.continue - -sticky se -padx 2 -pady 2 +		grid columnconfigure $w 0 -weight 1 +		grid rowconfigure $w 0 -weight 1  		wm protocol $w WM_DELETE_WINDOW update -		bind $w.buttons.continue <Visibility> " +		bind $w.continue <Visibility> "  			grab $w -			focus $w.buttons.continue +			focus %W  		" +		wm deiconify $w  		tkwait window $w  		$::main_status stop @@ -98,8 +103,11 @@ proc write_update_indexinfo {fd pathList totalCnt batch after} {  		set s $file_states($path)  		switch -glob -- [lindex $s 0] {  		A? {set new _O} -		M? {set new _M} +		MT - +		TM -  		T_ {set new _T} +		M? {set new _M} +		TD -  		D_ {set new _D}  		D? {set new _?}  		?? {continue} @@ -162,7 +170,10 @@ proc write_update_index {fd pathList totalCnt batch after} {  		AD {set new __}  		?D {set new D_}  		_O - +		AT -  		AM {set new A_} +		TM - +		MT -  		_T {set new T_}  		_U -  		U? { @@ -256,7 +267,7 @@ proc unstage_helper {txt paths} {  		switch -glob -- [lindex $file_states($path) 0] {  		A? -  		M? - -		T_ - +		T? -  		D? {  			lappend pathList $path  			if {$path eq $current_diff_path} { diff --git a/git-gui/lib/merge.tcl b/git-gui/lib/merge.tcl index 283e4915e9..460d32fa22 100644 --- a/git-gui/lib/merge.tcl +++ b/git-gui/lib/merge.tcl @@ -83,6 +83,7 @@ method _visualize {} {  method _start {} {  	global HEAD current_branch remote_url +	global _last_merged_branch  	set name [_rev $this]  	if {$name eq {}} { @@ -109,6 +110,7 @@ method _start {} {  	regsub ^refs/heads/ $branch {} branch  	puts $fh "$cmit\t\tbranch '$branch' of $remote"  	close $fh +	set _last_merged_branch $branch  	set cmd [list git]  	lappend cmd merge @@ -139,14 +141,14 @@ method _finish {cons ok} {  constructor dialog {} {  	global current_branch -	global M1B +	global M1B use_ttk NS  	if {![_can_merge $this]} {  		delete_this  		return  	} -	make_toplevel top w +	make_dialog top w  	wm title $top [append "[appname] ([reponame]): " [mc "Merge"]]  	if {$top ne {.}} {  		wm geometry $top "+[winfo rootx .]+[winfo rooty .]" @@ -154,21 +156,21 @@ constructor dialog {} {  	set _start [cb _start] -	label $w.header \ +	${NS}::label $w.header \  		-text [mc "Merge Into %s" $current_branch] \  		-font font_uibold  	pack $w.header -side top -fill x -	frame $w.buttons -	button $w.buttons.visualize \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.visualize \  		-text [mc Visualize] \  		-command [cb _visualize]  	pack $w.buttons.visualize -side left -	button $w.buttons.merge \ +	${NS}::button $w.buttons.merge \  		-text [mc Merge] \  		-command $_start  	pack $w.buttons.merge -side right -	button $w.buttons.cancel \ +	${NS}::button $w.buttons.cancel \  		-text [mc "Cancel"] \  		-command [cb _cancel]  	pack $w.buttons.cancel -side right -padx 5 diff --git a/git-gui/lib/mergetool.tcl b/git-gui/lib/mergetool.tcl index 3fe90e6970..3c8e73bceb 100644 --- a/git-gui/lib/mergetool.tcl +++ b/git-gui/lib/mergetool.tcl @@ -175,43 +175,56 @@ proc merge_resolve_tool2 {} {  	# Build the command line  	switch -- $tool { -	kdiff3 { +	araxis {  		if {$base_stage ne {}} { -			set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Base)" \ -				--L2 "$MERGED (Local)" --L3 "$MERGED (Remote)" -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE"] +			set cmdline [list "$merge_tool_path" -wait -merge -3 -a1 \ +				-title1:"'$MERGED (Base)'" -title2:"'$MERGED (Local)'" \ +				-title3:"'$MERGED (Remote)'" \ +				"$BASE" "$LOCAL" "$REMOTE" "$MERGED"]  		} else { -			set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Local)" \ -				--L2 "$MERGED (Remote)" -o "$MERGED" "$LOCAL" "$REMOTE"] +			set cmdline [list "$merge_tool_path" -wait -2 \ +				 -title1:"'$MERGED (Local)'" -title2:"'$MERGED (Remote)'" \ +				 "$LOCAL" "$REMOTE" "$MERGED"]  		}  	} -	tkdiff { +	bc3 {  		if {$base_stage ne {}} { -			set cmdline [list "$merge_tool_path" -a "$BASE" -o "$MERGED" "$LOCAL" "$REMOTE"] +			set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" -mergeoutput="$MERGED"]  		} else { -			set cmdline [list "$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"] +			set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -mergeoutput="$MERGED"]  		}  	} -	meld { -		set cmdline [list "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"] +	ecmerge { +		if {$base_stage ne {}} { +			set cmdline [list "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" --default --mode=merge3 --to="$MERGED"] +		} else { +			set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" --default --mode=merge2 --to="$MERGED"] +		} +	} +	emerge { +		if {$base_stage ne {}} { +			set cmdline [list "$merge_tool_path" -f emerge-files-with-ancestor-command \ +					"$LOCAL" "$REMOTE" "$BASE" "$basename"] +		} else { +			set cmdline [list "$merge_tool_path" -f emerge-files-command \ +					"$LOCAL" "$REMOTE" "$basename"] +		}  	}  	gvimdiff {  		set cmdline [list "$merge_tool_path" -f "$LOCAL" "$MERGED" "$REMOTE"]  	} -	xxdiff { +	kdiff3 {  		if {$base_stage ne {}} { -			set cmdline [list "$merge_tool_path" -X --show-merged-pane \ -					    -R {Accel.SaveAsMerged: "Ctrl-S"} \ -					    -R {Accel.Search: "Ctrl+F"} \ -					    -R {Accel.SearchForward: "Ctrl-G"} \ -					    --merged-file "$MERGED" "$LOCAL" "$BASE" "$REMOTE"] +			set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Base)" \ +				--L2 "$MERGED (Local)" --L3 "$MERGED (Remote)" -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE"]  		} else { -			set cmdline [list "$merge_tool_path" -X --show-merged-pane \ -					    -R {Accel.SaveAsMerged: "Ctrl-S"} \ -					    -R {Accel.Search: "Ctrl+F"} \ -					    -R {Accel.SearchForward: "Ctrl-G"} \ -					    --merged-file "$MERGED" "$LOCAL" "$REMOTE"] +			set cmdline [list "$merge_tool_path" --auto --L1 "$MERGED (Local)" \ +				--L2 "$MERGED (Remote)" -o "$MERGED" "$LOCAL" "$REMOTE"]  		}  	} +	meld { +		set cmdline [list "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"] +	}  	opendiff {  		if {$base_stage ne {}} {  			set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$MERGED"] @@ -219,22 +232,20 @@ proc merge_resolve_tool2 {} {  			set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -merge "$MERGED"]  		}  	} -	ecmerge { -		if {$base_stage ne {}} { -			set cmdline [list "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" --default --mode=merge3 --to="$MERGED"] -		} else { -			set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" --default --mode=merge2 --to="$MERGED"] -		} +	p4merge { +		set cmdline [list "$merge_tool_path" "$BASE" "$REMOTE" "$LOCAL" "$MERGED"]  	} -	emerge { +	tkdiff {  		if {$base_stage ne {}} { -			set cmdline [list "$merge_tool_path" -f emerge-files-with-ancestor-command \ -					"$LOCAL" "$REMOTE" "$BASE" "$basename"] +			set cmdline [list "$merge_tool_path" -a "$BASE" -o "$MERGED" "$LOCAL" "$REMOTE"]  		} else { -			set cmdline [list "$merge_tool_path" -f emerge-files-command \ -					"$LOCAL" "$REMOTE" "$basename"] +			set cmdline [list "$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"]  		}  	} +	vimdiff { +		error_popup [mc "Not a GUI merge tool: '%s'" $tool] +		return +	}  	winmerge {  		if {$base_stage ne {}} {  			# This tool does not support 3-way merges. @@ -245,25 +256,21 @@ proc merge_resolve_tool2 {} {  				-dl "Theirs File" -dr "Mine File" "$REMOTE" "$LOCAL" "$MERGED"]  		}  	} -	araxis { +	xxdiff {  		if {$base_stage ne {}} { -			set cmdline [list "$merge_tool_path" -wait -merge -3 -a1 \ -				-title1:"'$MERGED (Base)'" -title2:"'$MERGED (Local)'" \ -				-title3:"'$MERGED (Remote)'" \ -				"$BASE" "$LOCAL" "$REMOTE" "$MERGED"] +			set cmdline [list "$merge_tool_path" -X --show-merged-pane \ +					    -R {Accel.SaveAsMerged: "Ctrl-S"} \ +					    -R {Accel.Search: "Ctrl+F"} \ +					    -R {Accel.SearchForward: "Ctrl-G"} \ +					    --merged-file "$MERGED" "$LOCAL" "$BASE" "$REMOTE"]  		} else { -			set cmdline [list "$merge_tool_path" -wait -2 \ -				 -title1:"'$MERGED (Local)'" -title2:"'$MERGED (Remote)'" \ -				 "$LOCAL" "$REMOTE" "$MERGED"] +			set cmdline [list "$merge_tool_path" -X --show-merged-pane \ +					    -R {Accel.SaveAsMerged: "Ctrl-S"} \ +					    -R {Accel.Search: "Ctrl+F"} \ +					    -R {Accel.SearchForward: "Ctrl-G"} \ +					    --merged-file "$MERGED" "$LOCAL" "$REMOTE"]  		}  	} -	p4merge { -		set cmdline [list "$merge_tool_path" "$BASE" "$REMOTE" "$LOCAL" "$MERGED"] -	} -	vimdiff { -		error_popup [mc "Not a GUI merge tool: '%s'" $tool] -		return -	}  	default {  		error_popup [mc "Unsupported merge tool '%s'" $tool]  		return diff --git a/git-gui/lib/option.tcl b/git-gui/lib/option.tcl index 1d55b49c9b..3807c8d283 100644 --- a/git-gui/lib/option.tcl +++ b/git-gui/lib/option.tcl @@ -91,7 +91,7 @@ proc save_config {} {  proc do_options {} {  	global repo_config global_config font_descs  	global repo_config_new global_config_new -	global ui_comm_spell +	global ui_comm_spell use_ttk NS  	array unset repo_config_new  	array unset global_config_new @@ -110,26 +110,28 @@ proc do_options {} {  	}  	set w .options_editor -	toplevel $w +	Dialog $w +	wm withdraw $w +	wm transient $w [winfo parent $w]  	wm geometry $w "+[winfo rootx .]+[winfo rooty .]" -	frame $w.buttons -	button $w.buttons.restore -text [mc "Restore Defaults"] \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.restore -text [mc "Restore Defaults"] \  		-default normal \  		-command do_restore_defaults  	pack $w.buttons.restore -side left -	button $w.buttons.save -text [mc Save] \ +	${NS}::button $w.buttons.save -text [mc Save] \  		-default active \  		-command [list do_save_config $w]  	pack $w.buttons.save -side right -	button $w.buttons.cancel -text [mc "Cancel"] \ +	${NS}::button $w.buttons.cancel -text [mc "Cancel"] \  		-default normal \  		-command [list destroy $w]  	pack $w.buttons.cancel -side right -padx 5  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 -	labelframe $w.repo -text [mc "%s Repository" [reponame]] -	labelframe $w.global -text [mc "Global (All Repositories)"] +	${NS}::labelframe $w.repo -text [mc "%s Repository" [reponame]] +	${NS}::labelframe $w.global -text [mc "Global (All Repositories)"]  	pack $w.repo -side left -fill both -expand 1 -pady 5 -padx 5  	pack $w.global -side right -fill both -expand 1 -pady 5 -padx 5 @@ -146,6 +148,7 @@ proc do_options {} {  		{b gui.trustmtime  {mc "Trust File Modification Timestamps"}}  		{b gui.pruneduringfetch {mc "Prune Tracking Branches During Fetch"}}  		{b gui.matchtrackingbranch {mc "Match Tracking Branches"}} +		{b gui.textconv {mc "Use Textconv For Diffs and Blames"}}  		{b gui.fastcopyblame {mc "Blame Copy Only On Changed Files"}}  		{i-20..200 gui.copyblamethreshold {mc "Minimum Letters To Blame Copy On"}}  		{i-0..300 gui.blamehistoryctx {mc "Blame History Context Radius (days)"}} @@ -161,7 +164,7 @@ proc do_options {} {  		foreach f {repo global} {  			switch -glob -- $type {  			b { -				checkbutton $w.$f.$optid -text $text \ +				${NS}::checkbutton $w.$f.$optid -text $text \  					-variable ${f}_config_new($name) \  					-onvalue true \  					-offvalue false @@ -169,10 +172,10 @@ proc do_options {} {  			}  			i-* {  				regexp -- {-(\d+)\.\.(\d+)$} $type _junk min max -				frame $w.$f.$optid -				label $w.$f.$optid.l -text "$text:" +				${NS}::frame $w.$f.$optid +				${NS}::label $w.$f.$optid.l -text "$text:"  				pack $w.$f.$optid.l -side left -anchor w -fill x -				spinbox $w.$f.$optid.v \ +				tspinbox $w.$f.$optid.v \  					-textvariable ${f}_config_new($name) \  					-from $min \  					-to $max \ @@ -184,11 +187,9 @@ proc do_options {} {  			}  			c -  			t { -				frame $w.$f.$optid -				label $w.$f.$optid.l -text "$text:" -				entry $w.$f.$optid.v \ -					-borderwidth 1 \ -					-relief sunken \ +				${NS}::frame $w.$f.$optid +				${NS}::label $w.$f.$optid.l -text "$text:" +				${NS}::entry $w.$f.$optid.v \  					-width 20 \  					-textvariable ${f}_config_new($name)  				pack $w.$f.$optid.l -side left -anchor w @@ -199,7 +200,7 @@ proc do_options {} {  					menu $w.$f.$optid.m  					build_encoding_menu $w.$f.$optid.m \  						[list set ${f}_config_new($name)] 1 -					button $w.$f.$optid.b \ +					${NS}::button $w.$f.$optid.b \  						-text [mc "Change"] \  						-command [list popup_btn_menu \  							$w.$f.$optid.m $w.$f.$optid.b] @@ -226,11 +227,17 @@ proc do_options {} {  			set ${f}_config_new(gui.spellingdictionary) $value  		} -		frame $w.$f.$optid -		label $w.$f.$optid.l -text [mc "Spelling Dictionary:"] -		eval tk_optionMenu $w.$f.$optid.v \ -			${f}_config_new(gui.spellingdictionary) \ -			$all_dicts +		${NS}::frame $w.$f.$optid +		${NS}::label $w.$f.$optid.l -text [mc "Spelling Dictionary:"] +		if {$use_ttk} { +			ttk::combobox $w.$f.$optid.v \ +				-textvariable ${f}_config_new(gui.spellingdictionary) \ +				-values $all_dicts -state readonly +		} else { +			eval tk_optionMenu $w.$f.$optid.v \ +				${f}_config_new(gui.spellingdictionary) \ +				$all_dicts +		}  		pack $w.$f.$optid.l -side left -anchor w -fill x  		pack $w.$f.$optid.v -side right -anchor e -padx 5  		pack $w.$f.$optid -side top -anchor w -fill x @@ -248,20 +255,20 @@ proc do_options {} {  		set global_config_new(gui.$font^^size) \  			[font configure $font -size] -		frame $w.global.$name -		label $w.global.$name.l -text "$text:" -		button $w.global.$name.b \ +		${NS}::frame $w.global.$name +		${NS}::label $w.global.$name.l -text "$text:" +		${NS}::button $w.global.$name.b \  			-text [mc "Change Font"] \  			-command [list \ -				choose_font::pick \ +				tchoosefont \  				$w \  				[mc "Choose %s" $text] \  				global_config_new(gui.$font^^family) \  				global_config_new(gui.$font^^size) \  				] -		label $w.global.$name.f -textvariable global_config_new(gui.$font^^family) -		label $w.global.$name.s -textvariable global_config_new(gui.$font^^size) -		label $w.global.$name.pt -text [mc "pt."] +		${NS}::label $w.global.$name.f -textvariable global_config_new(gui.$font^^family) +		${NS}::label $w.global.$name.s -textvariable global_config_new(gui.$font^^size) +		${NS}::label $w.global.$name.pt -text [mc "pt."]  		pack $w.global.$name.l -side left -anchor w  		pack $w.global.$name.b -side right -anchor e  		pack $w.global.$name.pt -side right -anchor w @@ -280,6 +287,7 @@ proc do_options {} {  		set t [mc "Options"]  	}  	wm title $w "[appname] ([reponame]): $t" +	wm deiconify $w  	tkwait window $w  } diff --git a/git-gui/lib/remote.tcl b/git-gui/lib/remote.tcl index b92b429cf7..5e4e7f4c83 100644 --- a/git-gui/lib/remote.tcl +++ b/git-gui/lib/remote.tcl @@ -157,22 +157,7 @@ proc add_fetch_entry {r} {  	}  	if {$enable} { -		if {![winfo exists $fetch_m]} { -			menu $remove_m -			$remote_m insert 0 cascade \ -				-label [mc "Remove Remote"] \ -				-menu $remove_m - -			menu $prune_m -			$remote_m insert 0 cascade \ -				-label [mc "Prune from"] \ -				-menu $prune_m - -			menu $fetch_m -			$remote_m insert 0 cascade \ -				-label [mc "Fetch from"] \ -				-menu $fetch_m -		} +		make_sure_remote_submenues_exist $remote_m  		$fetch_m add command \  			-label $r \ @@ -222,6 +207,70 @@ proc add_push_entry {r} {  	}  } +proc make_sure_remote_submenues_exist {remote_m} { +	set fetch_m $remote_m.fetch +	set prune_m $remote_m.prune +	set remove_m $remote_m.remove + +	if {![winfo exists $fetch_m]} { +		menu $remove_m +		$remote_m insert 0 cascade \ +			-label [mc "Remove Remote"] \ +			-menu $remove_m + +		menu $prune_m +		$remote_m insert 0 cascade \ +			-label [mc "Prune from"] \ +			-menu $prune_m + +		menu $fetch_m +		$remote_m insert 0 cascade \ +			-label [mc "Fetch from"] \ +			-menu $fetch_m +	} +} + +proc update_all_remotes_menu_entry {} { +	global all_remotes + +	if {[git-version < 1.6.6]} { return } + +	set have_remote 0 +	foreach r $all_remotes { +		incr have_remote +	} + +	set remote_m .mbar.remote +	set fetch_m $remote_m.fetch +	set prune_m $remote_m.prune +	if {$have_remote > 1} { +		make_sure_remote_submenues_exist $remote_m +		if {[$fetch_m entrycget end -label] ne "All"} { + +			$fetch_m insert end separator +			$fetch_m insert end command \ +				-label "All" \ +				-command fetch_from_all + +			$prune_m insert end separator +			$prune_m insert end command \ +				-label "All" \ +				-command prune_from_all +		} +	} else { +		if {[winfo exists $fetch_m]} { +			if {[$fetch_m entrycget end -label] eq "All"} { + +				delete_from_menu $fetch_m end +				delete_from_menu $fetch_m end + +				delete_from_menu $prune_m end +				delete_from_menu $prune_m end +			} +		} +	} +} +  proc populate_remotes_menu {} {  	global all_remotes @@ -229,6 +278,8 @@ proc populate_remotes_menu {} {  		add_fetch_entry $r  		add_push_entry $r  	} + +	update_all_remotes_menu_entry  }  proc add_single_remote {name location} { @@ -244,6 +295,8 @@ proc add_single_remote {name location} {  	add_fetch_entry $name  	add_push_entry $name + +	update_all_remotes_menu_entry  }  proc delete_from_menu {menu name} { @@ -264,8 +317,8 @@ proc remove_remote {name} {  		unset repo_config(remote.$name.push)  	} -	set i [lsearch -exact all_remotes $name] -	lreplace all_remotes $i $i +	set i [lsearch -exact $all_remotes $name] +	set all_remotes [lreplace $all_remotes $i $i]  	set remote_m .mbar.remote  	delete_from_menu $remote_m.fetch $name @@ -273,4 +326,6 @@ proc remove_remote {name} {  	delete_from_menu $remote_m.remove $name  	# Not all remotes are in the push menu  	catch { delete_from_menu $remote_m.push $name } + +	update_all_remotes_menu_entry  } diff --git a/git-gui/lib/remote_add.tcl b/git-gui/lib/remote_add.tcl index fb29422aa7..50029d0cee 100644 --- a/git-gui/lib/remote_add.tcl +++ b/git-gui/lib/remote_add.tcl @@ -13,45 +13,43 @@ field location     {}; # location of the remote the user has chosen  field opt_action fetch; # action to do after registering the remote locally  constructor dialog {} { -	global repo_config +	global repo_config use_ttk NS -	make_toplevel top w +	make_dialog top w +	wm withdraw $top  	wm title $top [append "[appname] ([reponame]): " [mc "Add Remote"]]  	if {$top ne {.}} {  		wm geometry $top "+[winfo rootx .]+[winfo rooty .]"  	} -	label $w.header -text [mc "Add New Remote"] -font font_uibold +	${NS}::label $w.header -text [mc "Add New Remote"] \ +		-font font_uibold -anchor center  	pack $w.header -side top -fill x -	frame $w.buttons -	button $w.buttons.create -text [mc Add] \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.create -text [mc Add] \  		-default active \  		-command [cb _add]  	pack $w.buttons.create -side right -	button $w.buttons.cancel -text [mc Cancel] \ +	${NS}::button $w.buttons.cancel -text [mc Cancel] \  		-command [list destroy $w]  	pack $w.buttons.cancel -side right -padx 5  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 -	labelframe $w.desc -text [mc "Remote Details"] +	${NS}::labelframe $w.desc -text [mc "Remote Details"] -	label $w.desc.name_l -text [mc "Name:"] +	${NS}::label $w.desc.name_l -text [mc "Name:"]  	set w_name $w.desc.name_t -	entry $w_name \ -		-borderwidth 1 \ -		-relief sunken \ +	${NS}::entry $w_name \  		-width 40 \  		-textvariable @name \  		-validate key \  		-validatecommand [cb _validate_name %d %S]  	grid $w.desc.name_l $w_name -sticky we -padx {0 5} -	label $w.desc.loc_l -text [mc "Location:"] +	${NS}::label $w.desc.loc_l -text [mc "Location:"]  	set w_loc $w.desc.loc_t -	entry $w_loc \ -		-borderwidth 1 \ -		-relief sunken \ +	${NS}::entry $w_loc \  		-width 40 \  		-textvariable @location  	grid $w.desc.loc_l $w_loc -sticky we -padx {0 5} @@ -59,21 +57,21 @@ constructor dialog {} {  	grid columnconfigure $w.desc 1 -weight 1  	pack $w.desc -anchor nw -fill x -pady 5 -padx 5 -	labelframe $w.action -text [mc "Further Action"] +	${NS}::labelframe $w.action -text [mc "Further Action"] -	radiobutton $w.action.fetch \ +	${NS}::radiobutton $w.action.fetch \  		-text [mc "Fetch Immediately"] \  		-value fetch \  		-variable @opt_action  	pack $w.action.fetch -anchor nw -	radiobutton $w.action.push \ +	${NS}::radiobutton $w.action.push \  		-text [mc "Initialize Remote Repository and Push"] \  		-value push \  		-variable @opt_action  	pack $w.action.push -anchor nw -	radiobutton $w.action.none \ +	${NS}::radiobutton $w.action.none \  		-text [mc "Do Nothing Else Now"] \  		-value none \  		-variable @opt_action @@ -85,6 +83,7 @@ constructor dialog {} {  	bind $w <Visibility> [cb _visible]  	bind $w <Key-Escape> [list destroy $w]  	bind $w <Key-Return> [cb _add]\;break +	wm deiconify $top  	tkwait window $w  } diff --git a/git-gui/lib/remote_branch_delete.tcl b/git-gui/lib/remote_branch_delete.tcl index 4e02fc0d39..fcc06d03a1 100644 --- a/git-gui/lib/remote_branch_delete.tcl +++ b/git-gui/lib/remote_branch_delete.tcl @@ -23,34 +23,40 @@ field full_cache  field cached  constructor dialog {} { -	global all_remotes M1B +	global all_remotes M1B use_ttk NS -	make_toplevel top w +	make_dialog top w  	wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch Remotely"]]  	if {$top ne {.}} {  		wm geometry $top "+[winfo rootx .]+[winfo rooty .]"  	} -	label $w.header -text [mc "Delete Branch Remotely"] -font font_uibold +	${NS}::label $w.header -text [mc "Delete Branch Remotely"] \ +		-font font_uibold -anchor center  	pack $w.header -side top -fill x -	frame $w.buttons -	button $w.buttons.delete -text [mc Delete] \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.delete -text [mc Delete] \  		-default active \  		-command [cb _delete]  	pack $w.buttons.delete -side right -	button $w.buttons.cancel -text [mc "Cancel"] \ +	${NS}::button $w.buttons.cancel -text [mc "Cancel"] \  		-command [list destroy $w]  	pack $w.buttons.cancel -side right -padx 5  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 -	labelframe $w.dest -text [mc "From Repository"] +	${NS}::labelframe $w.dest -text [mc "From Repository"]  	if {$all_remotes ne {}} { -		radiobutton $w.dest.remote_r \ +		${NS}::radiobutton $w.dest.remote_r \  			-text [mc "Remote:"] \  			-value remote \  			-variable @urltype -		eval tk_optionMenu $w.dest.remote_m @remote $all_remotes +		if {$use_ttk} { +			ttk::combobox $w.dest.remote_m -textvariable @remote \ +				-values $all_remotes -state readonly +		} else { +			eval tk_optionMenu $w.dest.remote_m @remote $all_remotes +		}  		grid $w.dest.remote_r $w.dest.remote_m -sticky w  		if {[lsearch -sorted -exact $all_remotes origin] != -1} {  			set remote origin @@ -62,13 +68,11 @@ constructor dialog {} {  	} else {  		set urltype url  	} -	radiobutton $w.dest.url_r \ +	${NS}::radiobutton $w.dest.url_r \  		-text [mc "Arbitrary Location:"] \  		-value url \  		-variable @urltype -	entry $w.dest.url_t \ -		-borderwidth 1 \ -		-relief sunken \ +	${NS}::entry $w.dest.url_t \  		-width 50 \  		-textvariable @url \  		-validate key \ @@ -81,33 +85,30 @@ constructor dialog {} {  	grid columnconfigure $w.dest 1 -weight 1  	pack $w.dest -anchor nw -fill x -pady 5 -padx 5 -	labelframe $w.heads -text [mc "Branches"] -	listbox $w.heads.l \ +	${NS}::labelframe $w.heads -text [mc "Branches"] +	slistbox $w.heads.l \  		-height 10 \  		-width 70 \  		-listvariable @head_list \ -		-selectmode extended \ -		-yscrollcommand [list $w.heads.sby set] -	scrollbar $w.heads.sby -command [list $w.heads.l yview] +		-selectmode extended -	frame $w.heads.footer -	label $w.heads.footer.status \ +	${NS}::frame $w.heads.footer +	${NS}::label $w.heads.footer.status \  		-textvariable @status \  		-anchor w \  		-justify left -	button $w.heads.footer.rescan \ +	${NS}::button $w.heads.footer.rescan \  		-text [mc "Rescan"] \  		-command [cb _rescan]  	pack $w.heads.footer.status -side left -fill x  	pack $w.heads.footer.rescan -side right  	pack $w.heads.footer -side bottom -fill x -	pack $w.heads.sby -side right -fill y  	pack $w.heads.l -side left -fill both -expand 1  	pack $w.heads -fill both -expand 1 -pady 5 -padx 5 -	labelframe $w.validate -text [mc "Delete Only If"] -	radiobutton $w.validate.head_r \ +	${NS}::labelframe $w.validate -text [mc "Delete Only If"] +	${NS}::radiobutton $w.validate.head_r \  		-text [mc "Merged Into:"] \  		-value head \  		-variable @checktype @@ -115,7 +116,7 @@ constructor dialog {} {  	trace add variable @head_list write [cb _write_head_list]  	trace add variable @check_head write [cb _write_check_head]  	grid $w.validate.head_r $w.validate.head_m -sticky w -	radiobutton $w.validate.always_r \ +	${NS}::radiobutton $w.validate.always_r \  		-text [mc "Always (Do not perform merge checks)"] \  		-value always \  		-variable @checktype @@ -208,13 +209,15 @@ method _delete {} {  		return  	} -	if {[tk_messageBox \ -		-icon warning \ -		-type yesno \ -		-title [wm title $w] \ -		-parent $w \ -		-message [mc "Recovering deleted branches is difficult.\n\nDelete the selected branches?"]] ne yes} { -		return +	if {$checktype ne {head}} { +		if {[tk_messageBox \ +			-icon warning \ +			-type yesno \ +			-title [wm title $w] \ +			-parent $w \ +			-message [mc "Recovering deleted branches is difficult.\n\nDelete the selected branches?"]] ne yes} { +			return +		}  	}  	destroy $w @@ -248,6 +251,8 @@ method _write_url        {args} { set urltype url    }  method _write_check_head {args} { set checktype head }  method _write_head_list {args} { +	global current_branch _last_merged_branch +  	$head_m delete 0 end  	foreach abr $head_list {  		$head_m insert end radiobutton \ @@ -256,7 +261,18 @@ method _write_head_list {args} {  			-variable @check_head  	}  	if {[lsearch -exact -sorted $head_list $check_head] < 0} { -		set check_head {} +		if {[lsearch -exact -sorted $head_list $current_branch] < 0} { +			set check_head {} +		} else { +			set check_head $current_branch +		} +	} +	set lmb [lsearch -exact -sorted $head_list $_last_merged_branch] +	if {$lmb >= 0} { +		$w.heads.l conf -state normal +		$w.heads.l select set $lmb +		$w.heads.l yview $lmb +		$w.heads.l conf -state disabled  	}  } diff --git a/git-gui/lib/search.tcl b/git-gui/lib/search.tcl index b371e9a30a..7fdbf87bcd 100644 --- a/git-gui/lib/search.tcl +++ b/git-gui/lib/search.tcl @@ -14,15 +14,16 @@ field smarktop  field smarkbot  constructor new {i_w i_text args} { +	global use_ttk NS  	set w      $i_w  	set ctext  $i_text -	frame  $w -	label  $w.l       -text [mc Find:] +	${NS}::frame  $w +	${NS}::label  $w.l       -text [mc Find:]  	entry  $w.ent -textvariable ${__this}::searchstring -background lightgreen -	button $w.bn      -text [mc Next] -command [cb find_next] -	button $w.bp      -text [mc Prev] -command [cb find_prev] -	checkbutton $w.cs -text [mc Case-Sensitive] \ +	${NS}::button $w.bn      -text [mc Next] -command [cb find_next] +	${NS}::button $w.bp      -text [mc Prev] -command [cb find_prev] +	${NS}::checkbutton $w.cs -text [mc Case-Sensitive] \  		-variable ${__this}::casesensitive -command [cb _incrsearch]  	pack   $w.l   -side left  	pack   $w.cs  -side right diff --git a/git-gui/lib/shortcut.tcl b/git-gui/lib/shortcut.tcl index 2f20eb39c0..78878ef89d 100644 --- a/git-gui/lib/shortcut.tcl +++ b/git-gui/lib/shortcut.tcl @@ -2,6 +2,7 @@  # Copyright (C) 2006, 2007 Shawn Pearce  proc do_windows_shortcut {} { +	global _gitworktree  	set fn [tk_getSaveFile \  		-parent . \  		-title [append "[appname] ([reponame]): " [mc "Create Desktop Icon"]] \ @@ -15,7 +16,7 @@ proc do_windows_shortcut {} {  					[info nameofexecutable] \  					[file normalize $::argv0] \  					] \ -					[file dirname [file normalize [gitdir]]] +					[file normalize $_gitworktree]  			} err]} {  			error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"]  		} @@ -23,7 +24,7 @@ proc do_windows_shortcut {} {  }  proc do_cygwin_shortcut {} { -	global argv0 +	global argv0 _gitworktree  	if {[catch {  		set desktop [exec cygpath \ @@ -56,7 +57,7 @@ proc do_cygwin_shortcut {} {  					$sh -c \  					"CHERE_INVOKING=1 source /etc/profile;[sq $me] &" \  					] \ -					[file dirname [file normalize [gitdir]]] +					[file normalize $_gitworktree]  			} err]} {  			error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"]  		} diff --git a/git-gui/lib/sshkey.tcl b/git-gui/lib/sshkey.tcl index 82a1a80ff4..5f75bc96b3 100644 --- a/git-gui/lib/sshkey.tcl +++ b/git-gui/lib/sshkey.tcl @@ -15,7 +15,7 @@ proc find_ssh_key {} {  }  proc do_ssh_key {} { -	global sshkey_title have_tk85 sshkey_fd +	global sshkey_title have_tk85 sshkey_fd use_ttk NS  	set w .sshkey_dialog  	if {[winfo exists $w]} { @@ -23,7 +23,7 @@ proc do_ssh_key {} {  		return  	} -	toplevel $w +	Dialog $w  	wm transient $w .  	set finfo [find_ssh_key] @@ -35,9 +35,9 @@ proc do_ssh_key {} {  		set gen_state   disabled  	} -	frame $w.header -relief flat -	label $w.header.lbl -textvariable sshkey_title -anchor w -	button $w.header.gen -text [mc "Generate Key"] \ +	${NS}::frame $w.header +	${NS}::label $w.header.lbl -textvariable sshkey_title -anchor w +	${NS}::button $w.header.gen -text [mc "Generate Key"] \  		-command [list make_ssh_key $w] -state $gen_state  	pack $w.header.lbl -side left -expand 1 -fill x  	pack $w.header.gen -side right @@ -46,14 +46,16 @@ proc do_ssh_key {} {  	text $w.contents -width 60 -height 10 -wrap char -relief sunken  	pack $w.contents -fill both -expand 1  	if {$have_tk85} { -		$w.contents configure -inactiveselectbackground darkblue +		set clr darkblue +		if {$use_ttk} { set clr [ttk::style lookup . -selectbackground] } +		$w.contents configure -inactiveselectbackground $clr  	} -	frame $w.buttons -	button $w.buttons.close -text [mc Close] \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.close -text [mc Close] \  		-default active -command [list destroy $w]  	pack $w.buttons.close -side right -	button $w.buttons.copy -text [mc "Copy To Clipboard"] \ +	${NS}::button $w.buttons.copy -text [mc "Copy To Clipboard"] \  		-command [list tk_textCopy $w.contents]  	pack $w.buttons.copy -side left  	pack $w.buttons -side bottom -fill x -pady 5 -padx 5 diff --git a/git-gui/lib/status_bar.tcl b/git-gui/lib/status_bar.tcl index 51d4177551..95cb44991f 100644 --- a/git-gui/lib/status_bar.tcl +++ b/git-gui/lib/status_bar.tcl @@ -13,14 +13,16 @@ field units   {}; # unit of progress  field meter   {}; # current core git progress meter (if active)  constructor new {path} { +	global use_ttk NS  	set w $path  	set w_l $w.l  	set w_c $w.c -	frame $w \ -		-borderwidth 1 \ -		-relief sunken -	label $w_l \ +	${NS}::frame $w +	if {!$use_ttk} { +		$w configure -borderwidth 1 -relief sunken +	} +	${NS}::label $w_l \  		-textvariable @status \  		-anchor w \  		-justify left @@ -37,12 +39,13 @@ method _oneline_pack {} {  }  constructor two_line {path} { +	global NS  	set w $path  	set w_l $w.l  	set w_c $w.c -	frame $w -	label $w_l \ +	${NS}::frame $w +	${NS}::label $w_l \  		-textvariable @status \  		-anchor w \  		-justify left diff --git a/git-gui/lib/themed.tcl b/git-gui/lib/themed.tcl new file mode 100644 index 0000000000..1da458673b --- /dev/null +++ b/git-gui/lib/themed.tcl @@ -0,0 +1,174 @@ +# Functions for supporting the use of themed Tk widgets in git-gui. +# Copyright (C) 2009 Pat Thoyts <patthoyts@users.sourceforge.net> + +proc InitTheme {} { +	# Create a color label style (bg can be overridden by widget option) +	ttk::style layout Color.TLabel { +		Color.Label.border -sticky news -children { +			Color.label.fill -sticky news -children { +				Color.Label.padding -sticky news -children { +					Color.Label.label -sticky news}}}} +	eval [linsert [ttk::style configure TLabel] 0 \ +			  ttk::style configure Color.TLabel] +	ttk::style configure Color.TLabel \ +		-borderwidth 0 -relief flat -padding 2 +	ttk::style map Color.TLabel -background {{} gold} +	# We also need a padded label. +	ttk::style configure Padded.TLabel \ +		-padding {5 5} -borderwidth 1 -relief solid +	# We need a gold frame. +	ttk::style layout Gold.TFrame { +		Gold.Frame.border -sticky nswe -children { +			Gold.Frame.fill -sticky nswe}} +	ttk::style configure Gold.TFrame -background gold -relief flat +	# listboxes should have a theme border so embed in ttk::frame +	ttk::style layout SListbox.TFrame { +        SListbox.Frame.Entry.field -sticky news -border true -children { +            SListbox.Frame.padding -sticky news +        } +    } +} + +proc gold_frame {w args} { +	global use_ttk +	if {$use_ttk} { +		eval [linsert $args 0 ttk::frame $w -style Gold.TFrame] +	} else { +		eval [linsert $args 0 frame $w -background gold] +	} +} + +proc tlabel {w args} { +	global use_ttk +	if {$use_ttk} { +		set cmd [list ttk::label $w -style Color.TLabel] +		foreach {k v} $args { +			switch -glob -- $k { +				-activebackground {} +				default { lappend cmd $k $v } +			} +		} +		eval $cmd +	} else { +		eval [linsert $args 0 label $w] +	} +} + +# The padded label gets used in the about class. +proc paddedlabel {w args} { +	global use_ttk +	if {$use_ttk} { +		eval [linsert $args 0 ttk::label $w -style Padded.TLabel] +	} else { +		eval [linsert $args 0 label $w \ +				  -padx 5 -pady 5 \ +				  -justify left \ +				  -anchor w \ +				  -borderwidth 1 \ +				  -relief solid] +	} +} + +# Create a toplevel for use as a dialog. +# If available, sets the EWMH dialog hint and if ttk is enabled +# place a themed frame over the surface. +proc Dialog {w args} { +	eval [linsert $args 0 toplevel $w -class Dialog] +	pave_toplevel $w +	return $w +} + +# Tk toplevels are not themed - so pave it over with a themed frame to get +# the base color correct per theme. +proc pave_toplevel {w} { +	global use_ttk +	if {$use_ttk && ![winfo exists $w.!paving]} { +		set paving [ttk::frame $w.!paving] +		place $paving -x 0 -y 0 -relwidth 1 -relheight 1 +		lower $paving +	} +} + +# Create a scrolled listbox with appropriate border for the current theme. +# On many themes the border for a scrolled listbox needs to go around the +# listbox and the scrollbar. +proc slistbox {w args} { +	global use_ttk NS +	if {$use_ttk} { +		set f [ttk::frame $w -style SListbox.TFrame -padding 2] +	} else { +		set f [frame $w -relief flat] +	} +    if {[catch { +		if {$use_ttk} { +			eval [linsert $args 0 listbox $f.list -relief flat \ +					  -highlightthickness 0 -borderwidth 0] +		} else { +			eval [linsert $args 0 listbox $f.list] +		} +        ${NS}::scrollbar $f.vs -command [list $f.list yview] +        $f.list configure -yscrollcommand [list $f.vs set] +        grid $f.list $f.vs -sticky news +        grid rowconfigure $f 0 -weight 1 +        grid columnconfigure $f 0 -weight 1 +		bind $f.list <<ListboxSelect>> \ +			[list event generate $w <<ListboxSelect>>] +        interp hide {} $w +        interp alias {} $w {} $f.list +    } err]} { +        destroy $f +        return -code error $err +    } +    return $w +} + +# fetch the background color from a widget. +proc get_bg_color {w} { +	global use_ttk +	if {$use_ttk} { +		set bg [ttk::style lookup [winfo class $w] -background] +	} else { +		set bg [$w cget -background] +	} +	return $bg +} + +# ttk::spinbox didn't get added until 8.6 +proc tspinbox {w args} { +	global use_ttk +	if {$use_ttk && [llength [info commands ttk::spinbox]] > 0} { +		eval [linsert $args 0 ttk::spinbox $w] +	} else { +		eval [linsert $args 0 spinbox $w] +	} +} + +# Tk 8.6 provides a standard font selection dialog. This uses the native +# dialogs on Windows and MacOSX or a standard Tk dialog on X11. +proc tchoosefont {w title familyvar sizevar} { +	if {[package vsatisfies [package provide Tk] 8.6]} { +		upvar #0 $familyvar family +		upvar #0 $sizevar size +		tk fontchooser configure -parent $w -title $title \ +			-font [list $family $size] \ +			-command [list on_choosefont $familyvar $sizevar] +		tk fontchooser show +	} else { +		choose_font::pick $w $title $familyvar $sizevar +	} +} + +# Called when the Tk 8.6 fontchooser selects a font. +proc on_choosefont {familyvar sizevar font} { +	upvar #0 $familyvar family +	upvar #0 $sizevar size +	set font [font actual $font] +	set family [dict get $font -family] +	set size [dict get $font -size] +} + +# Local variables: +# mode: tcl +# indent-tabs-mode: t +# tab-width: 4 +# End: diff --git a/git-gui/lib/tools_dlg.tcl b/git-gui/lib/tools_dlg.tcl index 5f7f08e239..7eeda9daf2 100644 --- a/git-gui/lib/tools_dlg.tcl +++ b/git-gui/lib/tools_dlg.tcl @@ -16,53 +16,50 @@ field ask_branch    0; # ask for a revision  field ask_args      0; # ask for additional args  constructor dialog {} { -	global repo_config +	global repo_config use_ttk NS -	make_toplevel top w +	make_dialog top w  	wm title $top [append "[appname] ([reponame]): " [mc "Add Tool"]]  	if {$top ne {.}} {  		wm geometry $top "+[winfo rootx .]+[winfo rooty .]"  		wm transient $top .  	} -	label $w.header -text [mc "Add New Tool Command"] -font font_uibold +	${NS}::label $w.header -text [mc "Add New Tool Command"] \ +		-font font_uibold -anchor center  	pack $w.header -side top -fill x -	frame $w.buttons -	checkbutton $w.buttons.global \ +	${NS}::frame $w.buttons +	${NS}::checkbutton $w.buttons.global \  		-text [mc "Add globally"] \  		-variable @add_global  	pack $w.buttons.global -side left -padx 5 -	button $w.buttons.create -text [mc Add] \ +	${NS}::button $w.buttons.create -text [mc Add] \  		-default active \  		-command [cb _add]  	pack $w.buttons.create -side right -	button $w.buttons.cancel -text [mc Cancel] \ +	${NS}::button $w.buttons.cancel -text [mc Cancel] \  		-command [list destroy $w]  	pack $w.buttons.cancel -side right -padx 5  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 -	labelframe $w.desc -text [mc "Tool Details"] +	${NS}::labelframe $w.desc -text [mc "Tool Details"] -	label $w.desc.name_cmnt -anchor w\ +	${NS}::label $w.desc.name_cmnt -anchor w\  		-text [mc "Use '/' separators to create a submenu tree:"]  	grid x $w.desc.name_cmnt -sticky we -padx {0 5} -pady {0 2} -	label $w.desc.name_l -text [mc "Name:"] +	${NS}::label $w.desc.name_l -text [mc "Name:"]  	set w_name $w.desc.name_t -	entry $w_name \ -		-borderwidth 1 \ -		-relief sunken \ +	${NS}::entry $w_name \  		-width 40 \  		-textvariable @name \  		-validate key \  		-validatecommand [cb _validate_name %d %S]  	grid $w.desc.name_l $w_name -sticky we -padx {0 5} -	label $w.desc.cmd_l -text [mc "Command:"] +	${NS}::label $w.desc.cmd_l -text [mc "Command:"]  	set w_cmd $w.desc.cmd_t -	entry $w_cmd \ -		-borderwidth 1 \ -		-relief sunken \ +	${NS}::entry $w_cmd \  		-width 40 \  		-textvariable @command  	grid $w.desc.cmd_l $w_cmd -sticky we -padx {0 5} -pady {0 3} @@ -70,30 +67,30 @@ constructor dialog {} {  	grid columnconfigure $w.desc 1 -weight 1  	pack $w.desc -anchor nw -fill x -pady 5 -padx 5 -	checkbutton $w.confirm \ +	${NS}::checkbutton $w.confirm \  		-text [mc "Show a dialog before running"] \  		-variable @confirm -command [cb _check_enable_dlg] -	labelframe $w.dlg -labelwidget $w.confirm +	${NS}::labelframe $w.dlg -labelwidget $w.confirm -	checkbutton $w.dlg.askbranch \ +	${NS}::checkbutton $w.dlg.askbranch \  		-text [mc "Ask the user to select a revision (sets \$REVISION)"] \  		-variable @ask_branch -state disabled  	pack $w.dlg.askbranch -anchor w -padx 15 -	checkbutton $w.dlg.askargs \ +	${NS}::checkbutton $w.dlg.askargs \  		-text [mc "Ask the user for additional arguments (sets \$ARGS)"] \  		-variable @ask_args -state disabled  	pack $w.dlg.askargs -anchor w -padx 15  	pack $w.dlg -anchor nw -fill x -pady {0 8} -padx 5 -	checkbutton $w.noconsole \ +	${NS}::checkbutton $w.noconsole \  		-text [mc "Don't show the command output window"] \  		-variable @no_console  	pack $w.noconsole -anchor w -padx 5 -	checkbutton $w.needsfile \ +	${NS}::checkbutton $w.needsfile \  		-text [mc "Run only if a diff is selected (\$FILENAME not empty)"] \  		-variable @needs_file  	pack $w.needsfile -anchor w -padx 5 @@ -182,40 +179,38 @@ field w              ; # widget path  field w_names        ; # name list  constructor dialog {} { -	global repo_config global_config system_config +	global repo_config global_config system_config use_ttk NS  	load_config 1 -	make_toplevel top w +	make_dialog top w  	wm title $top [append "[appname] ([reponame]): " [mc "Remove Tool"]]  	if {$top ne {.}} {  		wm geometry $top "+[winfo rootx .]+[winfo rooty .]"  		wm transient $top .  	} -	label $w.header -text [mc "Remove Tool Commands"] -font font_uibold +	${NS}::label $w.header -text [mc "Remove Tool Commands"] \ +		-font font_uibold -anchor center  	pack $w.header -side top -fill x -	frame $w.buttons -	button $w.buttons.create -text [mc Remove] \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.create -text [mc Remove] \  		-default active \  		-command [cb _remove]  	pack $w.buttons.create -side right -	button $w.buttons.cancel -text [mc Cancel] \ +	${NS}::button $w.buttons.cancel -text [mc Cancel] \  		-command [list destroy $w]  	pack $w.buttons.cancel -side right -padx 5  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 -	frame $w.list +	${NS}::frame $w.list  	set w_names $w.list.l -	listbox $w_names \ +	slistbox $w_names \  		-height 10 \  		-width 30 \  		-selectmode extended \ -		-exportselection false \ -		-yscrollcommand [list $w.list.sby set] -	scrollbar $w.list.sby -command [list $w.list.l yview] -	pack $w.list.sby -side right -fill y +		-exportselection false  	pack $w.list.l -side left -fill both -expand 1  	pack $w.list -fill both -expand 1 -pady 5 -padx 5 @@ -232,7 +227,7 @@ constructor dialog {} {  	}  	if {$local_cnt > 0} { -		label $w.colorlbl -foreground blue \ +		${NS}::label $w.colorlbl -foreground blue \  			-text [mc "(Blue denotes repository-local tools)"]  		pack $w.colorlbl -fill x -pady 5 -padx 5  	} @@ -277,14 +272,14 @@ field is_ok         0; # ok to start  field argstr       {}; # arguments  constructor dialog {fullname} { -	global M1B +	global M1B use_ttk NS  	set title [get_config "guitool.$fullname.title"]  	if {$title eq {}} {  		regsub {/} $fullname { / } title  	} -	make_toplevel top w -autodelete 0 +	make_dialog top w -autodelete 0  	wm title $top [append "[appname] ([reponame]): " $title]  	if {$top ne {.}} {  		wm geometry $top "+[winfo rootx .]+[winfo rooty .]" @@ -297,7 +292,7 @@ constructor dialog {fullname} {  		set prompt [mc "Run Command: %s" $command]  	} -	label $w.header -text $prompt -font font_uibold +	${NS}::label $w.header -text $prompt -font font_uibold -anchor center  	pack $w.header -side top -fill x  	set argprompt [get_config "guitool.$fullname.argprompt"] @@ -311,12 +306,10 @@ constructor dialog {fullname} {  			set argprompt [mc "Arguments"]  		} -		labelframe $w.arg -text $argprompt +		${NS}::labelframe $w.arg -text $argprompt  		set w_args $w.arg.txt -		entry $w_args \ -			-borderwidth 1 \ -			-relief sunken \ +		${NS}::entry $w_args \  			-width 40 \  			-textvariable @argstr  		pack $w_args -padx 5 -pady 5 -fill both @@ -337,18 +330,18 @@ constructor dialog {fullname} {  		pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5  	} -	frame $w.buttons +	${NS}::frame $w.buttons  	if {$is_ask_revs} { -		button $w.buttons.visualize \ +		${NS}::button $w.buttons.visualize \  			-text [mc Visualize] \  			-command [cb _visualize]  		pack $w.buttons.visualize -side left  	} -	button $w.buttons.ok \ +	${NS}::button $w.buttons.ok \  		-text [mc OK] \  		-command [cb _start]  	pack $w.buttons.ok -side right -	button $w.buttons.cancel \ +	${NS}::button $w.buttons.cancel \  		-text [mc "Cancel"] \  		-command [cb _cancel]  	pack $w.buttons.cancel -side right -padx 5 diff --git a/git-gui/lib/transport.tcl b/git-gui/lib/transport.tcl index b18d9c7a1b..7fad9b7d91 100644 --- a/git-gui/lib/transport.tcl +++ b/git-gui/lib/transport.tcl @@ -20,6 +20,35 @@ proc prune_from {remote} {  	console::exec $w [list git remote prune $remote]  } +proc fetch_from_all {} { +	set w [console::new \ +		[mc "fetch all remotes"] \ +		[mc "Fetching new changes from all remotes"]] + +	set cmd [list git fetch --all] +	if {[is_config_true gui.pruneduringfetch]} { +		lappend cmd --prune +	} + +	console::exec $w $cmd +} + +proc prune_from_all {} { +	global all_remotes + +	set w [console::new \ +		[mc "remote prune all remotes"] \ +		[mc "Pruning tracking branches deleted from all remotes"]] + +	set cmd [list git remote prune] + +	foreach r $all_remotes { +		lappend cmd $r +	} + +	console::exec $w $cmd +} +  proc push_to {remote} {  	set w [console::new \  		[mc "push %s" $remote] \ @@ -91,50 +120,58 @@ trace add variable push_remote write \  proc do_push_anywhere {} {  	global all_remotes current_branch  	global push_urltype push_remote push_url push_thin push_tags -	global push_force +	global push_force use_ttk NS  	set w .push_setup  	toplevel $w +	wm withdraw $w  	wm geometry $w "+[winfo rootx .]+[winfo rooty .]" +	pave_toplevel $w -	label $w.header -text [mc "Push Branches"] -font font_uibold +	${NS}::label $w.header -text [mc "Push Branches"] \ +		-font font_uibold -anchor center  	pack $w.header -side top -fill x -	frame $w.buttons -	button $w.buttons.create -text [mc Push] \ +	${NS}::frame $w.buttons +	${NS}::button $w.buttons.create -text [mc Push] \  		-default active \  		-command [list start_push_anywhere_action $w]  	pack $w.buttons.create -side right -	button $w.buttons.cancel -text [mc "Cancel"] \ +	${NS}::button $w.buttons.cancel -text [mc "Cancel"] \  		-default normal \  		-command [list destroy $w]  	pack $w.buttons.cancel -side right -padx 5  	pack $w.buttons -side bottom -fill x -pady 10 -padx 10 -	labelframe $w.source -text [mc "Source Branches"] -	listbox $w.source.l \ +	${NS}::labelframe $w.source -text [mc "Source Branches"] +	slistbox $w.source.l \  		-height 10 \  		-width 70 \ -		-selectmode extended \ -		-yscrollcommand [list $w.source.sby set] +		-selectmode extended  	foreach h [load_all_heads] {  		$w.source.l insert end $h  		if {$h eq $current_branch} {  			$w.source.l select set end +			$w.source.l yview end  		}  	} -	scrollbar $w.source.sby -command [list $w.source.l yview] -	pack $w.source.sby -side right -fill y  	pack $w.source.l -side left -fill both -expand 1  	pack $w.source -fill both -expand 1 -pady 5 -padx 5 -	labelframe $w.dest -text [mc "Destination Repository"] +	${NS}::labelframe $w.dest -text [mc "Destination Repository"]  	if {$all_remotes ne {}} { -		radiobutton $w.dest.remote_r \ +		${NS}::radiobutton $w.dest.remote_r \  			-text [mc "Remote:"] \  			-value remote \  			-variable push_urltype -		eval tk_optionMenu $w.dest.remote_m push_remote $all_remotes +		if {$use_ttk} { +			ttk::combobox $w.dest.remote_m -state readonly \ +				-exportselection false \ +				-textvariable push_remote \ +				-values $all_remotes +		} else { +			eval tk_optionMenu $w.dest.remote_m push_remote $all_remotes +		}  		grid $w.dest.remote_r $w.dest.remote_m -sticky w  		if {[lsearch -sorted -exact $all_remotes origin] != -1} {  			set push_remote origin @@ -145,13 +182,11 @@ proc do_push_anywhere {} {  	} else {  		set push_urltype url  	} -	radiobutton $w.dest.url_r \ +	${NS}::radiobutton $w.dest.url_r \  		-text [mc "Arbitrary Location:"] \  		-value url \  		-variable push_urltype -	entry $w.dest.url_t \ -		-borderwidth 1 \ -		-relief sunken \ +	${NS}::entry $w.dest.url_t \  		-width 50 \  		-textvariable push_url \  		-validate key \ @@ -166,16 +201,16 @@ proc do_push_anywhere {} {  	grid columnconfigure $w.dest 1 -weight 1  	pack $w.dest -anchor nw -fill x -pady 5 -padx 5 -	labelframe $w.options -text [mc "Transfer Options"] -	checkbutton $w.options.force \ +	${NS}::labelframe $w.options -text [mc "Transfer Options"] +	${NS}::checkbutton $w.options.force \  		-text [mc "Force overwrite existing branch (may discard changes)"] \  		-variable push_force  	grid $w.options.force -columnspan 2 -sticky w -	checkbutton $w.options.thin \ +	${NS}::checkbutton $w.options.thin \  		-text [mc "Use thin pack (for slow network connections)"] \  		-variable push_thin  	grid $w.options.thin -columnspan 2 -sticky w -	checkbutton $w.options.tags \ +	${NS}::checkbutton $w.options.tags \  		-text [mc "Include tags"] \  		-variable push_tags  	grid $w.options.tags -columnspan 2 -sticky w @@ -191,5 +226,6 @@ proc do_push_anywhere {} {  	bind $w <Key-Escape> "destroy $w"  	bind $w <Key-Return> [list start_push_anywhere_action $w]  	wm title $w [append "[appname] ([reponame]): " [mc "Push"]] +	wm deiconify $w  	tkwait window $w  } diff --git a/git-gui/lib/win32.tcl b/git-gui/lib/win32.tcl index d7f93d045d..db91ab84a5 100644 --- a/git-gui/lib/win32.tcl +++ b/git-gui/lib/win32.tcl @@ -18,9 +18,9 @@ proc win32_create_lnk {lnk_path lnk_exec lnk_dir} {  	eval [list exec wscript.exe \  		/E:jscript \  		/nologo \ -		[file join $oguilib win32_shortcut.js] \ +		[file nativename [file join $oguilib win32_shortcut.js]] \  		$lnk_path \ -		[file join $oguilib git-gui.ico] \ +		[file nativename [file join $oguilib git-gui.ico]] \  		$lnk_dir \  		$lnk_exec] $lnk_args  }  | 
