From c7002898fc54cd0ce40e3175483cbf81fa55fee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 1 Aug 2018 11:52:32 +0200 Subject: [PATCH] Use MessageDialog for UniqueDialog issue7587 review60281003 --- tryton/common/common.py | 205 ++++++++++++++-------------------------- 1 file changed, 69 insertions(+), 136 deletions(-) diff --git a/tryton/common/common.py b/tryton/common/common.py index cb078e49a6..054cae9bbe 100644 --- a/tryton/common/common.py +++ b/tryton/common/common.py @@ -48,6 +48,8 @@ from tryton import __version__ from tryton.exceptions import TrytonServerError, TrytonError from tryton.pyson import PYSONEncoder +from .underline import set_underline + _ = gettext.gettext logger = logging.getLogger(__name__) @@ -496,6 +498,9 @@ class UniqueDialog(object): def build_dialog(self, *args): raise NotImplementedError + def process_response(self, response): + return response + def __call__(self, *args, **kwargs): if self.running: return @@ -503,11 +508,12 @@ class UniqueDialog(object): parent = kwargs.get('parent') if not parent: parent = get_toplevel_window() - dialog = self.build_dialog(parent, *args) + dialog = self.build_dialog(parent, *args, **kwargs) dialog.set_icon(TRYTON_ICON) self.running = True dialog.show_all() response = dialog.run() + response = self.process_response(response) if parent: parent.present() dialog.destroy() @@ -517,27 +523,26 @@ class UniqueDialog(object): class MessageDialog(UniqueDialog): - def build_dialog(self, parent, message, msg_type): + def build_dialog(self, parent, message, msg_type, buttons=gtk.BUTTONS_OK, + secondary=None): dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, msg_type, - gtk.BUTTONS_OK, message) + buttons, message) + if secondary: + dialog.format_secondary_text(secondary) return dialog - def __call__(self, message, msg_type=gtk.MESSAGE_INFO): - super(MessageDialog, self).__call__(message, msg_type) + def __call__(self, message, *args, **kwargs): + return super(MessageDialog, self).__call__(message, *args, **kwargs) message = MessageDialog() -class WarningDialog(UniqueDialog): +class WarningDialog(MessageDialog): - def build_dialog(self, parent, message, title, buttons=gtk.BUTTONS_OK): - dialog = gtk.MessageDialog(parent, gtk.DIALOG_DESTROY_WITH_PARENT, - gtk.MESSAGE_WARNING, buttons) - dialog.set_markup('%s' % (to_xml(title))) - dialog.format_secondary_markup(to_xml(message)) - return dialog + def __call__(self, message, title, buttons=gtk.BUTTONS_OK): + return super().__call__(title, gtk.MESSAGE_WARNING, buttons, message) warning = WarningDialog() @@ -552,9 +557,8 @@ class UserWarningDialog(WarningDialog): def _set_always(self, toggle): self.always = toggle.get_active() - def build_dialog(self, parent, message, title): - dialog = super(UserWarningDialog, self).build_dialog(parent, message, - title, gtk.BUTTONS_YES_NO) + def build_dialog(self, *args, **kwargs): + dialog = super().build_dialog(*args, **kwargs) check = gtk.CheckButton(_('Always ignore this warning.')) check.connect_after('toggled', self._set_always) alignment = gtk.Alignment(0, 0.5) @@ -565,51 +569,31 @@ class UserWarningDialog(WarningDialog): dialog.vbox.pack_start(label, True, True) return dialog - def __call__(self, message, title): - response = super(UserWarningDialog, self).__call__(message, title) + def process_response(self, response): if response == gtk.RESPONSE_YES: if self.always: return 'always' return 'ok' return 'cancel' + def __call__(self, message, title): + return super().__call__(message, title, gtk.BUTTONS_YES_NO) + userwarning = UserWarningDialog() -class ConfirmationDialog(UniqueDialog): +class ConfirmationDialog(MessageDialog): - def build_dialog(self, parent, message): - dialog = gtk.Dialog(_('Confirmation'), parent, gtk.DIALOG_MODAL - | gtk.DIALOG_DESTROY_WITH_PARENT | gtk.WIN_POS_CENTER_ON_PARENT - | gtk.gdk.WINDOW_TYPE_HINT_DIALOG) - hbox = gtk.HBox() - image = gtk.Image() - image.set_from_stock('tryton-dialog-information', - gtk.ICON_SIZE_DIALOG) - image.set_padding(15, 15) - hbox.pack_start(image, False, False) - label = gtk.Label('%s' % (to_xml(message))) - hbox.pack_start(label, True, True) - dialog.vbox.pack_start(hbox) - return dialog + def __call__(self, message, *args, **kwargs): + return super().__call__(message, gtk.MESSAGE_QUESTION, *args, **kwargs) class SurDialog(ConfirmationDialog): - def build_dialog(self, parent, message): - dialog = super(SurDialog, self).build_dialog(parent, message) - cancel_button = dialog.add_button("gtk-cancel", gtk.RESPONSE_CANCEL) - cancel_button.set_always_show_image(True) - ok_button = dialog.add_button("gtk-ok", gtk.RESPONSE_OK) - ok_button.set_always_show_image(True) - dialog.set_default(ok_button) - dialog.set_default_response(gtk.RESPONSE_OK) - return dialog - def __call__(self, message): - response = super(SurDialog, self).__call__(message) - return response == gtk.RESPONSE_OK + response = super().__call__(message, buttons=gtk.BUTTONS_YES_NO) + return response == gtk.RESPONSE_YES sur = SurDialog() @@ -623,70 +607,43 @@ class Sur3BDialog(ConfirmationDialog): gtk.RESPONSE_CANCEL: 'cancel' } - def build_dialog(self, parent, message): - dialog = super(Sur3BDialog, self).build_dialog(parent, message) - cancel_button = dialog.add_button("gtk-cancel", gtk.RESPONSE_CANCEL) - cancel_button.set_always_show_image(True) - no_button = dialog.add_button("gtk-no", gtk.RESPONSE_NO) - no_button.set_always_show_image(True) - yes_button = dialog.add_button("gtk-yes", gtk.RESPONSE_YES) - yes_button.set_always_show_image(True) - dialog.set_default(yes_button) + def build_dialog(self, *args, **kwargs): + dialog = super().build_dialog(*args, **kwargs) + dialog.add_button("gtk-cancel", gtk.RESPONSE_CANCEL) + dialog.add_button("gtk-no", gtk.RESPONSE_NO) + dialog.add_button("gtk-yes", gtk.RESPONSE_YES) dialog.set_default_response(gtk.RESPONSE_YES) return dialog def __call__(self, message): - response = super(Sur3BDialog, self).__call__(message) + response = super().__call__(message, buttons=gtk.BUTTONS_NONE) return self.response_mapping.get(response, 'cancel') sur_3b = Sur3BDialog() -class AskDialog(UniqueDialog): +class AskDialog(MessageDialog): - def build_dialog(self, parent, question, visibility): - win = gtk.Dialog(CONFIG['client.title'], parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT | - gtk.WIN_POS_CENTER_ON_PARENT) - cancel_button = win.add_button('gtk-cancel', gtk.RESPONSE_CANCEL) - cancel_button.set_always_show_image(True) - ok_button = win.add_button('gtk-ok', gtk.RESPONSE_OK) - ok_button.set_always_show_image(True) - win.set_default_response(gtk.RESPONSE_OK) - - hbox = gtk.HBox() - image = gtk.Image() - image.set_from_stock('tryton-dialog-information', - gtk.ICON_SIZE_DIALOG) - hbox.pack_start(image) - vbox = gtk.VBox() - vbox.pack_start(gtk.Label(question)) + def build_dialog(self, *args, **kwargs): + visibility = kwargs.pop('visibility') + dialog = super().build_dialog(*args, **kwargs) + dialog.set_default_response(gtk.RESPONSE_OK) + box = dialog.get_message_area() self.entry = gtk.Entry() self.entry.set_activates_default(True) self.entry.set_visibility(visibility) - vbox.pack_start(self.entry) - hbox.pack_start(vbox) - win.vbox.pack_start(hbox) - return win + box.pack_start(self.entry) + return dialog + + def process_response(self, response): + if response == gtk.RESPONSE_OK: + return self.entry.get_text() def __call__(self, question, visibility=True): - if self.running: - return - - parent = get_toplevel_window() - dialog = self.build_dialog(parent, question, visibility=visibility) - dialog.set_icon(TRYTON_ICON) - self.running = True - dialog.show_all() - response = dialog.run() - result = None - if response == gtk.RESPONSE_OK: - result = self.entry.get_text() - parent.present() - dialog.destroy() - self.running = False - return result + return super().__call__( + question, gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK_CANCEL, + visibility=visibility) ask = AskDialog() @@ -695,42 +652,29 @@ ask = AskDialog() class ConcurrencyDialog(UniqueDialog): def build_dialog(self, parent, resource, obj_id, context): - dialog = gtk.Dialog(_('Concurrency Exception'), parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT | - gtk.WIN_POS_CENTER_ON_PARENT | gtk.gdk.WINDOW_TYPE_HINT_DIALOG) + tooltips = Tooltips() + dialog = gtk.MessageDialog(parent, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, + _('Concurrency Exception')) dialog.set_default_response(gtk.RESPONSE_CANCEL) - hbox = gtk.HBox() - image = gtk.Image() - image.set_from_stock('tryton-dialog-information', - gtk.ICON_SIZE_DIALOG) - image.set_padding(15, 15) - hbox.pack_start(image, False, False) - label = gtk.Label() - label.set_padding(15, 15) - label.set_use_markup(True) - label.set_markup(_('Write Concurrency Warning:\n\n' - 'This record has been modified while you were editing it.\n' - ' Choose:\n' - ' - "Cancel" to cancel saving;\n' - ' - "Compare" to see the modified version;\n' - ' - "Write Anyway" to save your current version.')) - hbox.pack_start(label, True, True) - dialog.vbox.pack_start(hbox) + dialog.format_secondary_text( + _('This record has been modified while you were editing it.')) cancel_button = dialog.add_button('gtk-cancel', gtk.RESPONSE_CANCEL) - cancel_button.set_always_show_image(True) + tooltips.set_tip(cancel_button, _('Cancel saving')) compare_button = gtk.Button( - '_' + _('Compare').replace('_', '__'), use_underline=True) + set_underline(_('Compare')), use_underline=True) + tooltips.set_tip(compare_button, _('See the modified version')) image = gtk.Image() image.set_from_stock('tryton-find-replace', gtk.ICON_SIZE_BUTTON) compare_button.set_image(image) - compare_button.set_always_show_image(True) dialog.add_action_widget(compare_button, gtk.RESPONSE_APPLY) write_button = gtk.Button( - '_' + _('Write Anyway').replace('_', '__'), use_underline=True) + set_underline(_('Write Anyway')), use_underline=True) + tooltips.set_tip(write_button, _('Save your current version')) image = gtk.Image() image.set_from_stock('tryton-save', gtk.ICON_SIZE_BUTTON) write_button.set_image(image) - write_button.set_always_show_image(True) dialog.add_action_widget(write_button, gtk.RESPONSE_OK) return dialog @@ -756,8 +700,11 @@ concurrency = ConcurrencyDialog() class ErrorDialog(UniqueDialog): def build_dialog(self, parent, title, details): - dialog = gtk.Dialog(_('Error'), parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + dialog = gtk.MessageDialog(parent, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + gtk.MESSAGE_ERROR, gtk.BUTTONS_NONE, + _('Application Error')) + dialog.set_default_size(600, 400) but_send = gtk.Button(_('Report Bug')) dialog.add_action_widget(but_send, gtk.RESPONSE_OK) @@ -765,17 +712,7 @@ class ErrorDialog(UniqueDialog): close_button.set_always_show_image(True) dialog.set_default_response(gtk.RESPONSE_CANCEL) - vbox = gtk.VBox() - label_title = gtk.Label() - label_title.set_markup('' + _('Application Error.') + '') - label_title.set_padding(-1, 5) - vbox.pack_start(label_title, False, False) - vbox.pack_start(gtk.HSeparator(), False, False) - - hbox = gtk.HBox() - image = gtk.Image() - image.set_from_stock('tryton-dialog-error', gtk.ICON_SIZE_DIALOG) - hbox.pack_start(image, False, False) + vbox = dialog.vbox scrolledwindow = gtk.ScrolledWindow() scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) @@ -799,13 +736,11 @@ class ErrorDialog(UniqueDialog): textview.set_editable(False) textview.set_sensitive(True) textview.modify_font(pango.FontDescription("monospace")) - box.pack_start(textview, False, False) + box.pack_start(textview, True, True) viewport.add(box) scrolledwindow.add(viewport) - hbox.pack_start(scrolledwindow) - - vbox.pack_start(hbox) + vbox.pack_start(scrolledwindow, expand=True, fill=True) button_roundup = Gtk.LinkButton.new_with_label( CONFIG['roundup.url'], @@ -816,8 +751,6 @@ class ErrorDialog(UniqueDialog): lambda widget: webbrowser.open(CONFIG['roundup.url'], new=2)) vbox.pack_start(button_roundup, False, False) - dialog.vbox.pack_start(vbox) - dialog.set_default_size(600, 400) return dialog def __call__(self, title, details):