Few tweaks in main.py

This commit is contained in:
Romain Failliot 2021-11-21 02:10:34 -05:00
parent 8c981d3019
commit bf3a0b11ab
1 changed files with 86 additions and 88 deletions

View File

@ -51,66 +51,6 @@ from diffuse.widgets import LINE_MODE, CHAR_MODE, ALIGN_MODE
theVCSs = VcsRegistry() theVCSs = VcsRegistry()
# convenience method for creating a menu bar according to a template
def createMenuBar(specs, radio, accel_group):
menu_bar = Gtk.MenuBar.new()
for label, spec in specs:
menu = Gtk.MenuItem.new_with_mnemonic(label)
menu.set_submenu(utils.createMenu(spec, radio, accel_group))
menu.set_use_underline(True)
menu.show()
menu_bar.append(menu)
return menu_bar
# convenience method for packing buttons into a container according to a
# template
def appendButtons(box, size, specs):
for spec in specs:
if len(spec) > 0:
button = Gtk.Button.new()
button.set_relief(Gtk.ReliefStyle.NONE)
button.set_can_focus(False)
image = Gtk.Image.new()
image.set_from_stock(spec[0], size)
button.add(image)
image.show()
if len(spec) > 2:
button.connect('clicked', spec[1], spec[2])
if len(spec) > 3:
button.set_tooltip_text(spec[3])
box.pack_start(button, False, False, 0)
button.show()
else:
separator = Gtk.Separator.new(Gtk.Orientation.VERTICAL)
box.pack_start(separator, False, False, 5)
separator.show()
# constructs a full URL for the named file
def path2url(path, proto='file'):
r = [ proto, ':///' ]
s = os.path.abspath(path)
i = 0
while i < len(s) and s[i] == os.sep:
i += 1
for c in s[i:]:
if c == os.sep:
c = '/'
elif c == ':' and utils.isWindows():
c = '|'
else:
v = ord(c)
if v <= 0x20 or v >= 0x7b or c in '$&+,/:;=?@"<>#%\\^[]`':
c = '%%%02X' % (v, )
r.append(c)
return ''.join(r)
# convenience method to request confirmation when closing the last tab
def confirmTabClose(parent):
dialog = utils.MessageDialog(parent, Gtk.MessageType.WARNING, _('Closing this tab will quit %s.') % (constants.APP_NAME, ))
end = (dialog.run() == Gtk.ResponseType.OK)
dialog.destroy()
return end
# widget classed to create notebook tabs with labels and a close button # widget classed to create notebook tabs with labels and a close button
# use notebooktab.button.connect() to be notified when the button is pressed # use notebooktab.button.connect() to be notified when the button is pressed
# make this a Gtk.EventBox so signals can be connected for MMB and RMB button # make this a Gtk.EventBox so signals can be connected for MMB and RMB button
@ -169,18 +109,6 @@ class FileInfo:
# to warn about changes to file on disk # to warn about changes to file on disk
self.last_stat = None self.last_stat = None
# assign user specified labels to the corresponding files
def assign_file_labels(items, labels):
new_items = []
ss = labels[::-1]
for name, data in items:
if ss:
s = ss.pop()
else:
s = None
new_items.append((name, data, s))
return new_items
# the main application class containing a set of file viewers # the main application class containing a set of file viewers
# this class displays tab for switching between viewers and dispatches menu # this class displays tab for switching between viewers and dispatches menu
# commands to the current viewer # commands to the current viewer
@ -191,7 +119,7 @@ class Diffuse(Gtk.Window):
class PaneHeader(Gtk.Box): class PaneHeader(Gtk.Box):
def __init__(self): def __init__(self):
Gtk.Box.__init__(self, orientation = Gtk.Orientation.HORIZONTAL, spacing = 0) Gtk.Box.__init__(self, orientation = Gtk.Orientation.HORIZONTAL, spacing = 0)
appendButtons(self, Gtk.IconSize.MENU, [ _append_buttons(self, Gtk.IconSize.MENU, [
[ Gtk.STOCK_OPEN, self.button_cb, 'open', _('Open File...') ], [ Gtk.STOCK_OPEN, self.button_cb, 'open', _('Open File...') ],
[ Gtk.STOCK_REFRESH, self.button_cb, 'reload', _('Reload File') ], [ Gtk.STOCK_REFRESH, self.button_cb, 'reload', _('Reload File') ],
[ Gtk.STOCK_SAVE, self.button_cb, 'save', _('Save File') ], [ Gtk.STOCK_SAVE, self.button_cb, 'save', _('Save File') ],
@ -430,9 +358,8 @@ class Diffuse(Gtk.Window):
try: try:
if rev is None: if rev is None:
# load the contents of a plain file # load the contents of a plain file
fd = open(name, 'rb') with open(name, 'rb') as fd:
s = fd.read() s = fd.read()
fd.close()
# get the file's modification times so we can detect changes # get the file's modification times so we can detect changes
stat = os.stat(name) stat = os.stat(name)
else: else:
@ -596,9 +523,8 @@ class Diffuse(Gtk.Window):
encoded = codecs.encode(''.join(ss), encoding) encoded = codecs.encode(''.join(ss), encoding)
# write file # write file
fd = open(name, 'wb') with open(name, 'wb') as fd:
fd.write(encoded) fd.write(encoded)
fd.close()
# make the edits look permanent # make the edits look permanent
self.openUndoBlock() self.openUndoBlock()
@ -691,8 +617,8 @@ class Diffuse(Gtk.Window):
footer.updateCursor(self, f) footer.updateCursor(self, f)
# callback to display the format of a pane # callback to display the format of a pane
def format_changed_cb(self, widget, f, format): def format_changed_cb(self, widget, f, fmt):
self.footers[f].setFormat(format) self.footers[f].setFormat(fmt)
def __init__(self, rc_dir): def __init__(self, rc_dir):
Gtk.Window.__init__(self, type = Gtk.WindowType.TOPLEVEL) Gtk.Window.__init__(self, type = Gtk.WindowType.TOPLEVEL)
@ -888,13 +814,13 @@ class Diffuse(Gtk.Window):
# build list of radio menu items so we can update them to match the # build list of radio menu items so we can update them to match the
# currently viewed pane # currently viewed pane
self.radio_menus = radio_menus = {} self.radio_menus = radio_menus = {}
menu_bar = createMenuBar(menuspecs, radio_menus, accel_group) menu_bar = _create_menu_bar(menuspecs, radio_menus, accel_group)
vbox.pack_start(menu_bar, False, False, 0) vbox.pack_start(menu_bar, False, False, 0)
menu_bar.show() menu_bar.show()
# create button bar # create button bar
hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0) hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0)
appendButtons(hbox, Gtk.IconSize.LARGE_TOOLBAR, [ _append_buttons(hbox, Gtk.IconSize.LARGE_TOOLBAR, [
[ DIFFUSE_STOCK_NEW_2WAY_MERGE, self.new_2_way_file_merge_cb, None, _('New 2-Way File Merge') ], [ DIFFUSE_STOCK_NEW_2WAY_MERGE, self.new_2_way_file_merge_cb, None, _('New 2-Way File Merge') ],
[ DIFFUSE_STOCK_NEW_3WAY_MERGE, self.new_3_way_file_merge_cb, None, _('New 3-Way File Merge') ], [ DIFFUSE_STOCK_NEW_3WAY_MERGE, self.new_3_way_file_merge_cb, None, _('New 3-Way File Merge') ],
[], [],
@ -1096,9 +1022,16 @@ class Diffuse(Gtk.Window):
self.closed_tabs.append((nb.page_num(data), data, nb.get_tab_label(data))) self.closed_tabs.append((nb.page_num(data), data, nb.get_tab_label(data)))
nb.remove(data) nb.remove(data)
nb.set_show_tabs(self.prefs.getBool('tabs_always_show') or nb.get_n_pages() > 1) nb.set_show_tabs(self.prefs.getBool('tabs_always_show') or nb.get_n_pages() > 1)
elif not self.prefs.getBool('tabs_warn_before_quit') or confirmTabClose(self.get_toplevel()): elif not self.prefs.getBool('tabs_warn_before_quit') or self._confirm_tab_close():
self.quit_cb(widget, data) self.quit_cb(widget, data)
# convenience method to request confirmation when closing the last tab
def _confirm_tab_close(self):
dialog = utils.MessageDialog(self.get_toplevel(), Gtk.MessageType.WARNING, _('Closing this tab will quit %s.') % (constants.APP_NAME, ))
end = (dialog.run() == Gtk.ResponseType.OK)
dialog.destroy()
return end
# callback for RMB menu on notebook tabs # callback for RMB menu on notebook tabs
def notebooktab_pick_cb(self, widget, data): def notebooktab_pick_cb(self, widget, data):
self.notebook.set_current_page(data) self.notebook.set_current_page(data)
@ -1243,13 +1176,13 @@ class Diffuse(Gtk.Window):
# create a new viewer for 'items' # create a new viewer for 'items'
def createSingleTab(self, items, labels, options): def createSingleTab(self, items, labels, options):
if len(items) > 0: if len(items) > 0:
self.newLoadedFileDiffViewer(assign_file_labels(items, labels)).setOptions(options) self.newLoadedFileDiffViewer(_assign_file_labels(items, labels)).setOptions(options)
# create a new viewer for each item in 'items' # create a new viewer for each item in 'items'
def createSeparateTabs(self, items, labels, options): def createSeparateTabs(self, items, labels, options):
# all tabs inherit the first tab's revision and encoding specifications # all tabs inherit the first tab's revision and encoding specifications
items = [ (name, items[0][1]) for name, data in items ] items = [ (name, items[0][1]) for name, data in items ]
for item in assign_file_labels(items, labels): for item in _assign_file_labels(items, labels):
self.newLoadedFileDiffViewer([ item ]).setOptions(options) self.newLoadedFileDiffViewer([ item ]).setOptions(options)
# create a new viewer for each modified file found in 'items' # create a new viewer for each modified file found in 'items'
@ -1564,7 +1497,7 @@ class Diffuse(Gtk.Window):
help_file = os.path.join(utils.bin_dir, '_'.join(parts) + '.html') help_file = os.path.join(utils.bin_dir, '_'.join(parts) + '.html')
if os.path.isfile(help_file): if os.path.isfile(help_file):
# we found a help file # we found a help file
help_url = path2url(help_file) help_url = _path2url(help_file)
break break
del parts[-1] del parts[-1]
else: else:
@ -1592,7 +1525,7 @@ class Diffuse(Gtk.Window):
d = 'C' d = 'C'
help_file = os.path.join(os.path.join(s, d), 'diffuse.xml') help_file = os.path.join(os.path.join(s, d), 'diffuse.xml')
if os.path.isfile(help_file): if os.path.isfile(help_file):
args = [ browser, path2url(help_file, 'ghelp') ] args = [ browser, _path2url(help_file, 'ghelp') ]
# spawnvp is not available on some systems, use spawnv instead # spawnvp is not available on some systems, use spawnv instead
os.spawnv(os.P_NOWAIT, args[0], args) os.spawnv(os.P_NOWAIT, args[0], args)
return return
@ -1614,6 +1547,71 @@ class Diffuse(Gtk.Window):
dialog.run() dialog.run()
dialog.destroy() dialog.destroy()
# convenience method for creating a menu bar according to a template
def _create_menu_bar(specs, radio, accel_group):
menu_bar = Gtk.MenuBar.new()
for label, spec in specs:
menu = Gtk.MenuItem.new_with_mnemonic(label)
menu.set_submenu(utils.createMenu(spec, radio, accel_group))
menu.set_use_underline(True)
menu.show()
menu_bar.append(menu)
return menu_bar
# convenience method for packing buttons into a container according to a
# template
def _append_buttons(box, size, specs):
for spec in specs:
if len(spec) > 0:
button = Gtk.Button.new()
button.set_relief(Gtk.ReliefStyle.NONE)
button.set_can_focus(False)
image = Gtk.Image.new()
image.set_from_stock(spec[0], size)
button.add(image)
image.show()
if len(spec) > 2:
button.connect('clicked', spec[1], spec[2])
if len(spec) > 3:
button.set_tooltip_text(spec[3])
box.pack_start(button, False, False, 0)
button.show()
else:
separator = Gtk.Separator.new(Gtk.Orientation.VERTICAL)
box.pack_start(separator, False, False, 5)
separator.show()
# constructs a full URL for the named file
def _path2url(path, proto='file'):
r = [ proto, ':///' ]
s = os.path.abspath(path)
i = 0
while i < len(s) and s[i] == os.sep:
i += 1
for c in s[i:]:
if c == os.sep:
c = '/'
elif c == ':' and utils.isWindows():
c = '|'
else:
v = ord(c)
if v <= 0x20 or v >= 0x7b or c in '$&+,/:;=?@"<>#%\\^[]`':
c = '%%%02X' % (v, )
r.append(c)
return ''.join(r)
# assign user specified labels to the corresponding files
def _assign_file_labels(items, labels):
new_items = []
ss = labels[::-1]
for name, data in items:
if ss:
s = ss.pop()
else:
s = None
new_items.append((name, data, s))
return new_items
GObject.signal_new('title-changed', Diffuse.FileDiffViewer, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, (str, )) GObject.signal_new('title-changed', Diffuse.FileDiffViewer, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, (str, ))
GObject.signal_new('status-changed', Diffuse.FileDiffViewer, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, (str, )) GObject.signal_new('status-changed', Diffuse.FileDiffViewer, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, (str, ))
GObject.signal_new('title-changed', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()) GObject.signal_new('title-changed', Diffuse.FileDiffViewer.PaneHeader, GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ())