def confirm_destructive_action(self, title=_('Confirm'), question=_('Really continue?')): """Asks the user to confirm an action that might lose work :param title: Dialog title :param question: Question to ask the user :rtype bool: :returns: true if the user chose to destroy their work This method doesn't bother asking if there are fewer than a handful of seconds of unsaved work. By default, that's 1 second, but the build-time and runtime debugging flags make this period longer to allow faster develop and test cycles. """ self.doc.model.sync_pending_changes() t = self.doc.model.unsaved_painting_time t_bother = 1 if mypaintlib.heavy_debug: t_bother += 7 if os.environ.get("MYPAINT_DEBUG", False): t_bother += 7 # This used to be 30, but see https://gna.org/bugs/?17955 # Then 8 by default, but Twitter users hate that too. logger.debug("Destructive action don't-bother period is %ds", t_bother) if t < t_bother: return True #TRANSLATORS: Abbreviated string is an already translated time #TRANSLATORS: period abbreviation, like "6m42s", or "103s". unsaved_str = _( u"This will discard {abbreviated_time} of unsaved painting" ).format(abbreviated_time=helpers.fmt_time_period_abbr(t), ) d = gtk.Dialog(title, self.app.drawWindow, gtk.DIALOG_MODAL) b = d.add_button(gtk.STOCK_DISCARD, gtk.RESPONSE_OK) b.set_image( gtk.image_new_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_BUTTON)) d.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) b = d.add_button(_("_Save as Scrap"), gtk.RESPONSE_APPLY) b.set_image( gtk.image_new_from_stock(gtk.STOCK_SAVE, gtk.ICON_SIZE_BUTTON)) d.set_default_response(gtk.RESPONSE_CANCEL) l = gtk.Label() l.set_markup("<b>%s</b>\n\n%s" % (question, unsaved_str)) l.set_padding(10, 10) l.show() d.vbox.pack_start(l) response = d.run() d.destroy() if response == gtk.RESPONSE_APPLY: self.save_scrap_cb(None) return True return response == gtk.RESPONSE_OK
def confirm_destructive_action(self, title=_('Confirm'), question=_('Really continue?')): """Asks the user to confirm an action that might lose work :param title: Dialog title :param question: Question to ask the user :rtype bool: :returns: true if the user chose to destroy their work This method doesn't bother asking if there are fewer than a handful of seconds of unsaved work. By default, that's 1 second, but the build-time and runtime debugging flags make this period longer to allow faster develop and test cycles. """ self.doc.model.sync_pending_changes() t = self.doc.model.unsaved_painting_time t_bother = 1 if mypaintlib.heavy_debug: t_bother += 7 if os.environ.get("MYPAINT_DEBUG", False): t_bother += 7 # This used to be 30, but see https://gna.org/bugs/?17955 # Then 8 by default, but Twitter users hate that too. logger.debug("Destructive action don't-bother period is %ds", t_bother) if t < t_bother: return True #TRANSLATORS: Abbreviated string is an already translated time #TRANSLATORS: period abbreviation, like "6m42s", or "103s". unsaved_str = _( u"This will discard {abbreviated_time} of unsaved painting" ).format( abbreviated_time = helpers.fmt_time_period_abbr(t), ) d = gtk.Dialog(title, self.app.drawWindow, gtk.DIALOG_MODAL) b = d.add_button(gtk.STOCK_DISCARD, gtk.RESPONSE_OK) b.set_image(gtk.image_new_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_BUTTON)) d.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) b = d.add_button(_("_Save as Scrap"), gtk.RESPONSE_APPLY) b.set_image(gtk.image_new_from_stock(gtk.STOCK_SAVE, gtk.ICON_SIZE_BUTTON)) d.set_default_response(gtk.RESPONSE_CANCEL) l = gtk.Label() l.set_markup("<b>%s</b>\n\n%s" % (question, unsaved_str)) l.set_padding(10, 10) l.show() d.vbox.pack_start(l) response = d.run() d.destroy() if response == gtk.RESPONSE_APPLY: self.save_scrap_cb(None) return True return response == gtk.RESPONSE_OK
def confirm_destructive_action(self, title=None, confirm=None, offer_save=True): """Asks the user to confirm an action that might lose work. :param unicode title: Short question to ask the user. :param unicode confirm: Imperative verb for the "do it" button. :param bool offer_save: Set False to turn off the save checkbox. :rtype: bool :returns: True if the user allows the destructive action Phrase the title question tersely. In English/source, use title case for it, and with a question mark. Good examples are “Really Quit?”, or “Delete Everything?”. The title should always tell the user what destructive action is about to take place. If it is not specified, a default title is used. Use a single, specific, imperative verb for the confirm string. It should reflect the title question. This is used for the primary confirmation button, if specified. See the GNOME HIG for further guidelines on what to use here. This method doesn't bother asking if there's less than a handful of seconds of unsaved work. By default, that's 1 second. The build-time and runtime debugging flags make this period longer to allow more convenient development and testing. Ref: https://developer.gnome.org/hig/stable/dialogs.html.en """ if title is None: title = C_( "Destructive action confirm dialog: " "fallback title (normally overridden)", "Really Continue?" ) # Get an accurate assesment of how much change is unsaved. self.doc.model.sync_pending_changes() t = self.doc.model.unsaved_painting_time # This used to be 30, but see https://gna.org/bugs/?17955 # Then 8 by default, but Twitter users hate that too. t_bother = 1 if mypaintlib.heavy_debug: t_bother += 7 if os.environ.get("MYPAINT_DEBUG", False): t_bother += 7 logger.debug("Destructive action don't-bother period is %ds", t_bother) if t < t_bother: return True # Custom response codes. # The default ones are all negative ints. save1st_response_code = 1 continue_response_code = 2 # Dialog setup. d = Gtk.MessageDialog( title = title, parent = self.app.drawWindow, type = Gtk.MessageType.QUESTION, flags = Gtk.DialogFlags.MODAL, ) # Translated strings for things cancel_btn_text = C_( "Destructive action confirm dialog: cancel button", u"_Cancel", ) save_to_scraps_first_text = C_( "Destructive action confirm dialog: save checkbox", u"_Save to Scraps first", ) if not confirm: continue_btn_text = C_( "Destructive action confirm dialog: " "fallback continue button (normally overridden)", u"Co_ntinue", ) else: continue_btn_text = confirm # Button setup. Cancel first, continue at end. d.add_button(cancel_btn_text, Gtk.ResponseType.CANCEL) d.add_button(continue_btn_text, continue_response_code) # Explanatory message. if self.filename: file_basename = os.path.basename(self.filename) else: file_basename = None warning_msg_tmpl = C_( "Destructive action confirm dialog: warning message", u"You risk losing {abbreviated_time} of unsaved painting. " ) markup_tmpl = warning_msg_tmpl d.set_markup(markup_tmpl.format( abbreviated_time = lib.xml.escape(helpers.fmt_time_period_abbr(t)), current_file_name = lib.xml.escape(file_basename), )) # Checkbox for saving if offer_save: save1st_text = save_to_scraps_first_text save1st_cb = Gtk.CheckButton.new_with_mnemonic(save1st_text) save1st_cb.set_hexpand(False) save1st_cb.set_halign(Gtk.Align.END) save1st_cb.set_vexpand(False) save1st_cb.set_margin_top(12) save1st_cb.set_margin_bottom(12) save1st_cb.set_margin_start(12) save1st_cb.set_margin_end(12) save1st_cb.set_can_focus(False) # set back again in show handler d.connect( "show", self._destructive_action_dialog_show_cb, save1st_cb, ) save1st_cb.connect( "toggled", self._destructive_action_dialog_save1st_toggled_cb, d, ) vbox = d.get_content_area() vbox.set_spacing(0) vbox.set_margin_top(12) vbox.pack_start(save1st_cb, False, True, 0) # Get a response and handle it. d.set_default_response(Gtk.ResponseType.CANCEL) response_code = d.run() d.destroy() if response_code == continue_response_code: logger.debug("Destructive action confirmed") if offer_save and save1st_cb.get_active(): logger.info("Saving current canvas as a new scrap") self.save_scrap_cb(None) return True else: logger.debug("Destructive action cancelled") return False
def confirm_destructive_action(self, title=None, confirm=None, offer_save=True): """Asks the user to confirm an action that might lose work. :param unicode title: Short question to ask the user. :param unicode confirm: Imperative verb for the "do it" button. :param bool offer_save: Set False to turn off the save checkbox. :rtype: bool :returns: True if the user allows the destructive action Phrase the title question tersely. In English/source, use title case for it, and with a question mark. Good examples are “Really Quit?”, or “Delete Everything?”. The title should always tell the user what destructive action is about to take place. If it is not specified, a default title is used. Use a single, specific, imperative verb for the confirm string. It should reflect the title question. This is used for the primary confirmation button, if specified. See the GNOME HIG for further guidelines on what to use here. This method doesn't bother asking if there's less than a handful of seconds of unsaved work. By default, that's 1 second. The build-time and runtime debugging flags make this period longer to allow more convenient development and testing. Ref: https://developer.gnome.org/hig/stable/dialogs.html.en """ if title is None: title = C_( "Destructive action confirm dialog: " "fallback title (normally overridden)", "Really Continue?") # Get an accurate assesment of how much change is unsaved. self.doc.model.sync_pending_changes() t = self.doc.model.unsaved_painting_time # This used to be 30, but see https://gna.org/bugs/?17955 # Then 8 by default, but Twitter users hate that too. t_bother = 1 if mypaintlib.heavy_debug: t_bother += 7 if os.environ.get("MYPAINT_DEBUG", False): t_bother += 7 logger.debug("Destructive action don't-bother period is %ds", t_bother) if t < t_bother: return True # Custom response codes. # The default ones are all negative ints. save1st_response_code = 1 continue_response_code = 2 # Dialog setup. d = Gtk.MessageDialog( title=title, parent=self.app.drawWindow, type=Gtk.MessageType.QUESTION, flags=Gtk.DialogFlags.MODAL, ) # Translated strings for things cancel_btn_text = C_( "Destructive action confirm dialog: cancel button", u"_Cancel", ) save_to_scraps_first_text = C_( "Destructive action confirm dialog: save checkbox", u"_Save to Scraps first", ) if not confirm: continue_btn_text = C_( "Destructive action confirm dialog: " "fallback continue button (normally overridden)", u"Co_ntinue", ) else: continue_btn_text = confirm # Button setup. Cancel first, continue at end. d.add_button(cancel_btn_text, Gtk.ResponseType.CANCEL) d.add_button(continue_btn_text, continue_response_code) # Explanatory message. if self.filename: file_basename = os.path.basename(self.filename) else: file_basename = None warning_msg_tmpl = C_( "Destructive action confirm dialog: warning message", u"You risk losing {abbreviated_time} of unsaved painting. ") markup_tmpl = warning_msg_tmpl d.set_markup( markup_tmpl.format( abbreviated_time=lib.xml.escape( helpers.fmt_time_period_abbr(t)), current_file_name=lib.xml.escape(file_basename), )) # Checkbox for saving if offer_save: save1st_text = save_to_scraps_first_text save1st_cb = Gtk.CheckButton.new_with_mnemonic(save1st_text) save1st_cb.set_hexpand(False) save1st_cb.set_halign(Gtk.Align.END) save1st_cb.set_vexpand(False) save1st_cb.set_margin_top(12) save1st_cb.set_margin_bottom(12) save1st_cb.set_margin_start(12) save1st_cb.set_margin_end(12) save1st_cb.set_can_focus(False) # set back again in show handler d.connect( "show", self._destructive_action_dialog_show_cb, save1st_cb, ) save1st_cb.connect( "toggled", self._destructive_action_dialog_save1st_toggled_cb, d, ) vbox = d.get_content_area() vbox.set_spacing(0) vbox.set_margin_top(12) vbox.pack_start(save1st_cb, False, True, 0) # Get a response and handle it. d.set_default_response(Gtk.ResponseType.CANCEL) response_code = d.run() d.destroy() if response_code == continue_response_code: logger.debug("Destructive action confirmed") if offer_save and save1st_cb.get_active(): logger.info("Saving current canvas as a new scrap") self.save_scrap_cb(None) return True else: logger.debug("Destructive action cancelled") return False