Skip to content

Commit

Permalink
Merge pull request #834 from Vulcalien/ask-before-closing
Browse files Browse the repository at this point in the history
Ask before closing, even if there is only one terminal
  • Loading branch information
mattrose authored Feb 8, 2024
2 parents 94254ee + 8c0c7ce commit b47f7d0
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 63 deletions.
15 changes: 7 additions & 8 deletions doc/terminator_config.5
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
'\" t
.\" Title: terminator_config
.\" Author: [see the "AUTHOR(S)" section]
.\" Generator: Asciidoctor 2.0.18
.\" Date: 2023-04-22
.\" Generator: Asciidoctor 2.0.16
.\" Date: 2023-10-10
.\" Manual: Manual for Terminator
.\" Source: Terminator
.\" Language: English
.\"
.TH "TERMINATOR_CONFIG" "5" "2023-04-22" "Terminator" "Manual for Terminator"
.TH "TERMINATOR_CONFIG" "5" "2023-10-10" "Terminator" "Manual for Terminator"
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.ss \n[.ss] 0
Expand Down Expand Up @@ -130,12 +130,11 @@ If set to True, the window will resize in step with font sizes.
Default value: \fBFalse\fP
.RE
.sp
\fBsuppress_multiple_term_dialog\fP = \fIboolean\fP
\fBask_before_closing\fP = \fIstring\fP
.RS 4
If set to True, Terminator will ask for confirmation when closing
multiple terminals.
.br
Default value: \fBFalse\fP
Specify when to ask for confirmation before closing a window or a tab.
Can be any of: \*(Aqalways\*(Aq, \*(Aqmultiple_terminals\*(Aq, \*(Aqnever\*(Aq.
Default value: \fBmultiple_terminals\fP
.RE
.sp
\fBborderless\fP = \fIboolean\fP
Expand Down
10 changes: 5 additions & 5 deletions doc/terminator_config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
:doctype: manpage
:manmanual: Manual for Terminator
:mansource: Terminator
:revdate: 2023-04-22
:revdate: 2023-10-10
:docdate: {revdate}

== NAME
Expand Down Expand Up @@ -90,10 +90,10 @@ Default value: *False*
If set to True, the window will resize in step with font sizes. +
Default value: *False*

*suppress_multiple_term_dialog* = _boolean_::
If set to True, Terminator will ask for confirmation when closing
multiple terminals. +
Default value: *False*
*ask_before_closing* = _string_::
Specify when to ask for confirmation before closing a window or a tab.
Can be any of: 'always', 'multiple_terminals', 'never'.
Default value: *multiple_terminals*

// --- Window appearance ---

Expand Down
2 changes: 1 addition & 1 deletion terminatorlib/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
'enabled_plugins' : ['LaunchpadBugURLHandler',
'LaunchpadCodeURLHandler',
'APTURLHandler'],
'suppress_multiple_term_dialog': False,
'ask_before_closing' : 'multiple_terminals',
'always_split_with_profile': False,
'putty_paste_style' : False,
'putty_paste_style_source_clipboard': False,
Expand Down
54 changes: 38 additions & 16 deletions terminatorlib/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,33 +152,54 @@ def unzoom(self, widget):
"""Unzoom a terminal"""
raise NotImplementedError('unzoom')

def construct_confirm_close(self, window, reqtype):
def construct_confirm_close(self, window, child):
"""Create a confirmation dialog for closing things"""

maker = Factory()

has_multiple_terms = False
if not maker.isinstance(child, 'Terminal'):
has_multiple_terms = True
elif maker.isinstance(self, 'Window'):
has_multiple_terms = self.is_zoomed()

# skip this dialog if applicable
if self.config['suppress_multiple_term_dialog']:
if self.config['ask_before_closing'] == 'never':
return Gtk.ResponseType.ACCEPT

elif self.config['ask_before_closing'] == 'multiple_terminals':
if not has_multiple_terms:
return Gtk.ResponseType.ACCEPT

# text
confirm_button_text = (_('Close _Terminals') if has_multiple_terms
else _('Close _Terminal'))
big_label_text = (_('Close multiple terminals?') if has_multiple_terms
else _('Close terminal?'))

if not has_multiple_terms:
description_text = _('Do you really wish to close this terminal?')
elif maker.isinstance(self, 'Window'):
description_text = _('This window has several terminals open. Closing \
the window will also close all terminals within it.')
elif maker.isinstance(self, 'Notebook'):
description_text = _('This tab has several terminals open. Closing \
the tab will also close all terminals within it.')
else:
description_text = ''

# dialog GUI
dialog = Gtk.Dialog(_('Close?'), window, Gtk.DialogFlags.MODAL)
dialog.set_resizable(False)

dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT)
c_all = dialog.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.ACCEPT)
c_all.get_children()[0].get_children()[0].get_children()[1].set_label(
_('Close _Terminals'))
confirm_button_text)

primary = Gtk.Label(label=_('<big><b>Close multiple terminals?</b></big>'))
primary = Gtk.Label(label=_('<big><b>' + big_label_text + '</b></big>'))
primary.set_use_markup(True)
primary.set_alignment(0, 0.5)
if reqtype == 'window':
label_text = _('This window has several terminals open. Closing \
the window will also close all terminals within it.')
elif reqtype == 'tab':
label_text = _('This tab has several terminals open. Closing \
the tab will also close all terminals within it.')
else:
label_text = ''
secondary = Gtk.Label(label=label_text)

secondary = Gtk.Label(label=description_text)
secondary.set_line_wrap(True)

labels = Gtk.VBox()
Expand All @@ -203,7 +224,8 @@ def construct_confirm_close(self, window, reqtype):

# set configuration
self.config.base.reload()
self.config['suppress_multiple_term_dialog'] = checkbox.get_active()
if checkbox.get_active():
self.config['ask_before_closing'] = 'never'
self.config.save()

dialog.destroy()
Expand Down
34 changes: 16 additions & 18 deletions terminatorlib/notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,35 +379,33 @@ def closetab(self, widget, label):
maker = Factory()
child = nb.get_nth_page(tabnum)

confirm_close = self.construct_confirm_close(self.window, child)
if confirm_close != Gtk.ResponseType.ACCEPT:
dbg('user cancelled request')
return

if maker.isinstance(child, 'Terminal'):
dbg('child is a single Terminal')

del nb.last_active_term[child]
child.close()
# FIXME: We only do this del and return here to avoid removing the
# page below, which child.close() implicitly does
del(label)
return
elif maker.isinstance(child, 'Container'):
dbg('child is a Container')
result = self.construct_confirm_close(self.window, _('tab'))

if result == Gtk.ResponseType.ACCEPT:
containers = None
objects = None
containers, objects = enumerate_descendants(child)

while len(objects) > 0:
descendant = objects.pop()
descendant.close()
while Gtk.events_pending():
Gtk.main_iteration()
return
else:
dbg('user cancelled request')
return

containers = None
objects = None
containers, objects = enumerate_descendants(child)

while len(objects) > 0:
descendant = objects.pop()
descendant.close()
while Gtk.events_pending():
Gtk.main_iteration()
else:
err('Notebook::closetab: child is unknown type %s' % child)
return

def resizeterm(self, widget, keyname):
"""Handle a keyboard event requesting a terminal resize"""
Expand Down
23 changes: 8 additions & 15 deletions terminatorlib/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,22 +280,15 @@ def tab_new(self, widget=None, debugtab=False, _param1=None, _param2=None):
def on_delete_event(self, window, event, data=None):
"""Handle a window close request"""
maker = Factory()
if maker.isinstance(self.get_child(), 'Terminal'):
if self.is_zoomed():
return(self.confirm_close(window, _('window')))
else:
dbg('Only one child, closing is fine')
return(False)
elif maker.isinstance(self.get_child(), 'Container'):
return(self.confirm_close(window, _('window')))
else:
dbg('unknown child: %s' % self.get_child())

def confirm_close(self, window, type):
"""Display a confirmation dialog when the user is closing multiple
terminals in one window"""

return(not (self.construct_confirm_close(window, type) == Gtk.ResponseType.ACCEPT))
child = self.get_child()
if (maker.isinstance(child, 'Terminal') or
maker.isinstance(child, 'Container')):
confirm_close = self.construct_confirm_close(window, child)
return (confirm_close != Gtk.ResponseType.ACCEPT)
else:
dbg('unknown child: %s' % child)
return False # close anyway

def on_destroy_event(self, widget, data=None):
"""Handle window destruction"""
Expand Down

0 comments on commit b47f7d0

Please sign in to comment.