From c356bb7641db69955b52888ac4acf1072c88e31b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 5 Mar 2019 13:23:45 +0100 Subject: [PATCH] Remove pygtkcompat and clean most deprecation warnings issue8139 review47841002 --- CHANGELOG | 7 + doc/installation.rst | 3 +- setup.py | 3 +- tryton/__init__.py | 186 +--------- tryton/bus.py | 4 +- tryton/client.py | 9 + tryton/common/button.py | 2 - tryton/common/cellrendererbinary.py | 6 +- tryton/common/cellrenderercombo.py | 7 +- tryton/common/cellrendererfloat.py | 15 +- tryton/common/cellrendererinteger.py | 10 +- tryton/common/cellrenderertext.py | 9 +- tryton/common/cellrenderertoggle.py | 7 +- tryton/common/common.py | 321 +++++++++--------- tryton/common/completion.py | 9 +- tryton/common/datetime_.py | 196 +++++------ tryton/common/focus.py | 6 +- tryton/common/htmltextbuffer.py | 3 + tryton/common/popup_menu.py | 45 ++- tryton/common/selection.py | 21 +- tryton/common/timedelta.py | 1 + tryton/common/treeviewcontrol.py | 34 +- tryton/config.py | 5 +- tryton/gui/main.py | 196 ++++++----- tryton/gui/window/dblogin.py | 240 +++++++------ tryton/gui/window/email.py | 109 ------ tryton/gui/window/email_.py | 97 ++++++ tryton/gui/window/form.py | 123 +++---- tryton/gui/window/infobar.py | 2 +- tryton/gui/window/limit.py | 46 +-- tryton/gui/window/preference.py | 40 ++- tryton/gui/window/revision.py | 46 +-- tryton/gui/window/tabcontent.py | 105 +++--- tryton/gui/window/view_board/action.py | 18 +- tryton/gui/window/view_board/view_board.py | 59 ++-- tryton/gui/window/view_form/screen/screen.py | 19 +- tryton/gui/window/view_form/view/calendar_.py | 13 +- .../view_form/view/calendar_gtk/toolbar.py | 85 ++--- tryton/gui/window/view_form/view/form.py | 90 ++--- .../window/view_form/view/form_gtk/binary.py | 67 ++-- .../form_gtk/{calendar.py => calendar_.py} | 24 +- .../window/view_form/view/form_gtk/char.py | 34 +- .../view_form/view/form_gtk/checkbox.py | 8 +- .../view_form/view/form_gtk/dictionary.py | 94 ++--- .../window/view_form/view/form_gtk/float.py | 12 +- .../window/view_form/view/form_gtk/image.py | 29 +- .../window/view_form/view/form_gtk/integer.py | 2 +- .../view_form/view/form_gtk/many2many.py | 77 ++--- .../view_form/view/form_gtk/many2one.py | 41 ++- .../view_form/view/form_gtk/multiselection.py | 24 +- .../view_form/view/form_gtk/one2many.py | 131 +++---- .../view_form/view/form_gtk/progressbar.py | 18 +- .../view_form/view/form_gtk/reference.py | 16 +- .../view_form/view/form_gtk/richtextbox.py | 51 ++- .../view_form/view/form_gtk/selection.py | 18 +- .../view_form/view/form_gtk/state_widget.py | 32 +- .../window/view_form/view/form_gtk/textbox.py | 47 +-- .../view_form/view/form_gtk/timedelta.py | 8 +- .../gui/window/view_form/view/form_gtk/url.py | 18 +- .../window/view_form/view/form_gtk/widget.py | 84 +++-- tryton/gui/window/view_form/view/graph.py | 72 ++-- .../window/view_form/view/graph_gtk/graph.py | 39 ++- tryton/gui/window/view_form/view/list.py | 196 +++++------ .../view_form/view/list_gtk/editabletree.py | 86 +++-- .../window/view_form/view/list_gtk/widget.py | 112 +++--- .../window/view_form/view/screen_container.py | 240 ++++++------- tryton/gui/window/win_csv.py | 208 ++++++------ tryton/gui/window/win_export.py | 76 ++--- tryton/gui/window/win_form.py | 198 +++++------ tryton/gui/window/win_import.py | 36 +- tryton/gui/window/win_search.py | 59 ++-- tryton/gui/window/wizard.py | 99 +++--- tryton/translate.py | 8 +- 73 files changed, 2207 insertions(+), 2254 deletions(-) delete mode 100644 tryton/gui/window/email.py create mode 100644 tryton/gui/window/email_.py rename tryton/gui/window/view_form/view/form_gtk/{calendar.py => calendar_.py} (91%) diff --git a/CHANGELOG b/CHANGELOG index 1f72cd6906..4a31be32e8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,10 @@ +* Rename email and calendar file +* Use markup for styling +* Replace ImageMenuItem by MenuItem +* Replace ComboBoxEntry by ComboBox or ComboBoxText +* Replace GObject.idle_add by GLibe.idle_add +* Remove positional arguments for PyGObject +* Remove pygtkcompat * Implement Reference cell with Selection and Many2One cells * Replace CellRendererBinary with clickable pixbuf cells * Allow cell to have multiple renderers diff --git a/doc/installation.rst b/doc/installation.rst index fec25ee84a..34f91ee749 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -5,8 +5,9 @@ Prerequisites ------------- * Python 3.4 or later (http://www.python.org/) - * gtk+ 3.20 or later and py-gobject3 (http://www.gtk.org/) + * gtk+ 3.20 or later and py-gobject3 3.20 or later (http://www.gtk.org/) * librsvg (http://librsvg.sourceforge.net/) + * pycairo (https://pycairo.readthedocs.io/) * python-dateutil (http://labix.org/python-dateutil) * Optional: GooCalendar 0.4 or later (https://pypi.python.org/pypi/GooCalendar) diff --git a/setup.py b/setup.py index 52c58f9b6e..9dc7163acd 100755 --- a/setup.py +++ b/setup.py @@ -110,10 +110,11 @@ dist = setup(name=name, python_requires='>=3.4', install_requires=[ # "py-gobject3", + 'pycairo', "python-dateutil", ], extras_require={ - 'calendar': ['GooCalendar>=0.4'], + 'calendar': ['GooCalendar>=0.5'], }, zip_safe=False, **args diff --git a/tryton/__init__.py b/tryton/__init__.py index f7f7ce27cc..b12f4cb50c 100644 --- a/tryton/__init__.py +++ b/tryton/__init__.py @@ -1,198 +1,18 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. __version__ = "5.1.0" -import sys - import gi -import pygtkcompat -pygtkcompat.enable() -pygtkcompat.enable_gtk(version='3.0') -try: - pygtkcompat.enable_goocanvas() -except ValueError: - pass +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') +gi.require_foreign('cairo') try: gi.require_version('GtkSpell', '3.0') except ValueError: pass -from gi.repository import GdkPixbuf -_unset = object() - -Gdk = sys.modules['gtk.gdk'] -# XXX this prevents isinstance test -Gdk.PixbufLoader = GdkPixbuf.PixbufLoader.new - -Gtk = sys.modules['gtk'] -Gtk.widget_set_default_direction = Gtk.Widget.set_default_direction -Gtk.accel_map_add_entry = Gtk.AccelMap.add_entry -Gtk.accel_map_load = Gtk.AccelMap.load -Gtk.accel_map_save = Gtk.AccelMap.save - -Gtk.PROGRESS_LEFT_TO_RIGHT = (Gtk.Orientation.HORIZONTAL, False) -Gtk.PROGRESS_RIGHT_TO_LEFT = (Gtk.Orientation.HORIZONTAL, True) -Gtk.PROGRESS_BOTTOM_TO_TOP = (Gtk.Orientation.VERTICAL, True) -Gtk.PROGRESS_TOP_TO_BOTTOM = (Gtk.Orientation.VERTICAL, False) - -Gtk.CLIPBOARD_PRIMARY = Gdk.Atom.intern('PRIMARY', True) -Gtk.CLIPBOARD_CLIPBOARD = Gdk.Atom.intern('CLIPBOARD', True) - -orig_tree_view_column_set_cell_data_func = ( - Gtk.TreeViewColumn.set_cell_data_func) - - -def set_cell_data_func(self, cell, func, user_data=_unset): - def callback(*args): - if args[-1] == _unset: - args = args[:-1] - return func(*args) - orig_tree_view_column_set_cell_data_func( - self, cell, callback, user_data) -Gtk.TreeViewColumn.set_cell_data_func = set_cell_data_func - -Gtk.TreeViewColumn.get_cell_renderers = Gtk.TreeViewColumn.get_cells - -orig_set_orientation = Gtk.ProgressBar.set_orientation - - -def set_orientation(self, orientation): - orientation, inverted = orientation - orig_set_orientation(self, orientation) - self.set_inverted(inverted) -Gtk.ProgressBar.set_orientation = set_orientation - -orig_set_orientation = Gtk.CellRendererProgress.set_orientation - - -def set_orientation(self, orientation): - orientation, inverted = orientation - orig_set_orientation(self, orientation) - self.set_property('inverted', inverted) -Gtk.CellRendererProgress.set_orientation = set_orientation - -orig_popup = Gtk.Menu.popup - - -def popup(self, parent_menu_shell, parent_menu_item, func, button, - activate_time, data=None): - if func: - def position_func(menu, x, y, user_data=None): - return func(menu, user_data) - else: - position_func = None - orig_popup(self, parent_menu_shell, parent_menu_item, - position_func, data, button, activate_time) -Gtk.Menu.popup = popup - - -def get_active_text(self): - active = self.get_active() - if active < 0: - return None - else: - model = self.get_model() - index = self.get_property('entry-text-column') - return model[active][index] -Gtk.ComboBox.get_active_text = get_active_text - -from gi.repository import Pango - - -def make_attr_constructor(method): - def constructor(value, start_index, end_index): - attr = getattr(Pango, method)(value) - attr.start_index = start_index - if end_index >= 0: - attr.end_index = end_index - return attr - return constructor - - -def make_attr_2_constructor(method): - def constructor(one, two, start_index, end_index): - attr = getattr(Pango, method)(one, two) - attr.start_index = start_index - if end_index >= 0: - attr.end_index = end_index - return attr - return constructor - - -def make_attr_3_constructor(method): - def constructor(one, two, three, start_index, end_index): - attr = getattr(Pango, method)(one, two, three) - attr.start_index = start_index - if end_index >= 0: - attr.end_index = end_index - return attr - return constructor - - -for method, name, constructor in [ - ('attr_language_new', 'AttrLanguage', make_attr_constructor), - ('attr_family_new', 'AttrFamily', make_attr_constructor), - ('attr_foreground_new', 'AttrForeground', make_attr_3_constructor), - ('attr_background_new', 'AttrBackground', make_attr_3_constructor), - ('attr_size_new', 'AttrSize', make_attr_constructor), - ('attr_size_new_absolute', 'AttrSizeAbsolute', - make_attr_constructor), - ('attr_style_new', 'AttrStyle', make_attr_constructor), - ('attr_weight_new', 'AttrWeight', make_attr_constructor), - ('attr_variant_new', 'AttrVariant', make_attr_constructor), - ('attr_stretch_new', 'AttrStretch', make_attr_constructor), - ('attr_font_desc_new', 'AttrFontDesc', make_attr_constructor), - ('attr_underline_new', 'AttrUnderline', make_attr_constructor), - ('attr_underline_color_new', 'AttrUnderlineColor', - make_attr_3_constructor), - ('attr_strikethrough_new', 'AttrStrikethrough', - make_attr_constructor), - ('attr_strikethrough_color_new', 'AttrStrikethroughColor', - make_attr_3_constructor), - ('attr_rise_new', 'AttrRise', make_attr_constructor), - ('attr_scale_new', 'AttrScale', make_attr_constructor), - ('attr_fallback_new', 'AttrFallback', make_attr_constructor), - ('attr_letter_spacing_new', 'AttrLetterSpacing', - make_attr_constructor), - ('attr_shape_new', 'AttrShape', make_attr_2_constructor), - ]: - if hasattr(Pango, method): - setattr(Pango, name, constructor(method)) - - -import gtk - -if not hasattr(gtk, 'TreePath'): - gtk.TreePath = tuple -if not hasattr(gtk, 'TargetEntry'): - gtk.TargetEntry = lambda *a: a - gtk.TargetEntry.new = lambda *a: a -if not hasattr(gtk, 'CLIPBOARD_PRIMARY'): - gtk.CLIPBOARD_PRIMARY = 'PRIMARY' - gtk.CLIPBOARD_CLIPBOARD = 'CLIPBOARD' - - -import gobject try: # Import earlier otherwise there is a segmentation fault on MSYS2 import goocalendar except ImportError: pass -gobject.threads_init() - -if not hasattr(gtk.gdk, 'lock'): - class _Lock(object): - __enter__ = gtk.gdk.threads_enter - - def __exit__(*ignored): - gtk.gdk.threads_leave() - - gtk.gdk.lock = _Lock() - -if sys.platform == 'win32': - class Dialog(gtk.Dialog): - - def run(self): - with gtk.gdk.lock: - return super(Dialog, self).run() - gtk.Dialog = Dialog diff --git a/tryton/bus.py b/tryton/bus.py index 206e966418..8920e825e6 100644 --- a/tryton/bus.py +++ b/tryton/bus.py @@ -10,7 +10,7 @@ import uuid from urllib.request import Request, urlopen from urllib.error import HTTPError -from gi.repository import GObject +from gi.repository import GLib from tryton.jsonrpc import object_hook from tryton.config import CONFIG @@ -85,7 +85,7 @@ def _listen(connection): data = json.loads(response.read(), object_hook=object_hook) if data['message']: last_message = data['message']['message_id'] - GObject.idle_add(handle, data['message']) + GLib.idle_add(handle, data['message']) def handle(message): diff --git a/tryton/client.py b/tryton/client.py index 53fdfbcbe3..a26cc1dfae 100644 --- a/tryton/client.py +++ b/tryton/client.py @@ -32,6 +32,15 @@ def main(): label.editable { font-style: italic; } + .window-title, .wizard-title { + background-color: white; + font-size: large; + font-weight: bold; + } + .window-title .status { + font-size: medium; + font-weight: normal; + } """ screen = Gdk.Screen.get_default() diff --git a/tryton/common/button.py b/tryton/common/button.py index 38a88bfb5a..17ded2afaa 100644 --- a/tryton/common/button.py +++ b/tryton/common/button.py @@ -23,8 +23,6 @@ class Button(Gtk.Button): image = self.get_image() if not image and not stock: return - elif image and image.get_stock()[0] == stock: - return if not stock: self.set_image(None) return diff --git a/tryton/common/cellrendererbinary.py b/tryton/common/cellrendererbinary.py index b7b3bdff0b..256e5062c6 100644 --- a/tryton/common/cellrendererbinary.py +++ b/tryton/common/cellrendererbinary.py @@ -132,9 +132,9 @@ class CellRendererBinary(Gtk.CellRenderer): if lwidth < 0: lwidth = 0 layout.set_width(lwidth * Pango.SCALE) - layout.set_ellipsize(Pango.ELLIPSIZE_END) - layout.set_wrap(Pango.WRAP_CHAR) - layout.set_alignment(Pango.ALIGN_RIGHT) + layout.set_ellipsize(Pango.EllipsizeMode.END) + layout.set_wrap(Pango.WrapMode.CHAR) + layout.set_alignment(Pango.Alignment.RIGHT) if lwidth > 0: lw, lh = layout.get_size() # Can not use get_pixel_extents diff --git a/tryton/common/cellrenderercombo.py b/tryton/common/cellrenderercombo.py index 1764387b61..28eaede53d 100644 --- a/tryton/common/cellrenderercombo.py +++ b/tryton/common/cellrenderercombo.py @@ -1,16 +1,15 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk -import gobject +from gi.repository import GObject, Gtk from tryton.common.selection import selection_shortcuts -class CellRendererCombo(gtk.CellRendererCombo): +class CellRendererCombo(Gtk.CellRendererCombo): def on_editing_started(self, editable, path): super().on_editing_started(editable, path) selection_shortcuts(editable) -gobject.type_register(CellRendererCombo) +GObject.type_register(CellRendererCombo) diff --git a/tryton/common/cellrendererfloat.py b/tryton/common/cellrendererfloat.py index 07e51ace03..59cc1a0e3f 100644 --- a/tryton/common/cellrendererfloat.py +++ b/tryton/common/cellrendererfloat.py @@ -1,8 +1,9 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk -import gobject import locale + +from gi.repository import Gdk, GObject + from .cellrendererinteger import CellRendererInteger @@ -18,8 +19,8 @@ class CellRendererFloat(CellRendererInteger): def key_press_event(self, widget, event): for name in ('KP_Decimal', 'KP_Separator'): - if event.keyval == gtk.gdk.keyval_from_name(name): - event.keyval = int(gtk.gdk.unicode_to_keyval( + if event.keyval == Gdk.keyval_from_name(name): + event.keyval = int(Gdk.unicode_to_keyval( ord(locale.localeconv()['decimal_point']))) def sig_insert_text(self, entry, new_text, new_text_length, position): @@ -34,11 +35,11 @@ class CellRendererFloat(CellRendererInteger): try: value = locale.atof(new_value) except ValueError: - entry.stop_emission('insert-text') + entry.stop_emission_by_name('insert-text') return if self.digits and not (round(value, self.digits[1]) == float(value)): - entry.stop_emission('insert-text') + entry.stop_emission_by_name('insert-text') -gobject.type_register(CellRendererFloat) +GObject.type_register(CellRendererFloat) diff --git a/tryton/common/cellrendererinteger.py b/tryton/common/cellrendererinteger.py index 6d77658ada..59b81d17fd 100644 --- a/tryton/common/cellrendererinteger.py +++ b/tryton/common/cellrendererinteger.py @@ -1,9 +1,11 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gobject -from .cellrenderertext import CellRendererText import locale +from gi.repository import GObject + +from .cellrenderertext import CellRendererText + class CellRendererInteger(CellRendererText): @@ -21,7 +23,7 @@ class CellRendererInteger(CellRendererText): try: locale.atoi(new_value) except ValueError: - entry.stop_emission('insert-text') + entry.stop_emission_by_name('insert-text') -gobject.type_register(CellRendererInteger) +GObject.type_register(CellRendererInteger) diff --git a/tryton/common/cellrenderertext.py b/tryton/common/cellrenderertext.py index f8d0232464..428cc438d9 100644 --- a/tryton/common/cellrenderertext.py +++ b/tryton/common/cellrenderertext.py @@ -1,10 +1,9 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk -import gobject +from gi.repository import Gtk, GObject -class CellRendererText(gtk.CellRendererText): +class CellRendererText(Gtk.CellRendererText): def __init__(self): super(CellRendererText, self).__init__() @@ -25,5 +24,5 @@ class CellRendererTextCompletion(CellRendererText): self.set_completion(editable, path) -gobject.type_register(CellRendererText) -gobject.type_register(CellRendererTextCompletion) +GObject.type_register(CellRendererText) +GObject.type_register(CellRendererTextCompletion) diff --git a/tryton/common/cellrenderertoggle.py b/tryton/common/cellrenderertoggle.py index 56c7892fdb..ff222afc59 100644 --- a/tryton/common/cellrenderertoggle.py +++ b/tryton/common/cellrenderertoggle.py @@ -1,11 +1,10 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk -import gobject +from gi.repository import GObject, Gtk -class CellRendererToggle(gtk.CellRendererToggle): +class CellRendererToggle(Gtk.CellRendererToggle): pass -gobject.type_register(CellRendererToggle) +GObject.type_register(CellRendererToggle) diff --git a/tryton/common/common.py b/tryton/common/common.py index 6374098471..e5e00d278b 100644 --- a/tryton/common/common.py +++ b/tryton/common/common.py @@ -1,10 +1,6 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk -import gobject -import glib -import pango import gettext import os import subprocess @@ -48,7 +44,7 @@ except ImportError: from threading import Lock import dateutil.tz -from gi.repository import Gtk, GLib +from gi.repository import Gdk, GdkPixbuf, GLib, GObject, Gtk from tryton import __version__ from tryton.exceptions import TrytonServerError, TrytonError @@ -307,32 +303,35 @@ def selection(title, values, alwaysask=False): return (key, values[key]) parent = get_toplevel_window() - dialog = gtk.Dialog(_('Selection'), parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) - dialog.add_button(set_underline(_("Cancel")), gtk.RESPONSE_CANCEL) - dialog.add_button(set_underline(_("OK")), gtk.RESPONSE_OK) + dialog = Gtk.Dialog( + title=_('Selection'), transient_for=parent, + modal=True, destroy_with_parent=True) + dialog.add_button(set_underline(_("Cancel")), Gtk.ResponseType.CANCEL) + dialog.add_button(set_underline(_("OK")), Gtk.ResponseType.OK) dialog.set_icon(TRYTON_ICON) - dialog.set_default_response(gtk.RESPONSE_OK) + dialog.set_default_response(Gtk.ResponseType.OK) dialog.set_default_size(400, 400) - label = gtk.Label(title or _('Your selection:')) - dialog.vbox.pack_start(label, False, False) - dialog.vbox.pack_start(gtk.HSeparator(), False, True) + label = Gtk.Label(title or _('Your selection:')) + dialog.vbox.pack_start(label, expand=False, fill=False, padding=0) + dialog.vbox.pack_start( + Gtk.HSeparator(), expand=False, fill=True, padding=0) - scrolledwindow = gtk.ScrolledWindow() - scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - treeview = gtk.TreeView() + scrolledwindow = Gtk.ScrolledWindow() + scrolledwindow.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + treeview = Gtk.TreeView() treeview.set_headers_visible(False) scrolledwindow.add(treeview) - dialog.vbox.pack_start(scrolledwindow, True, True) + dialog.vbox.pack_start(scrolledwindow, expand=True, fill=True, padding=0) - treeview.get_selection().set_mode(gtk.SELECTION_SINGLE) - cell = gtk.CellRendererText() - column = gtk.TreeViewColumn("Widget", cell, text=0) + treeview.get_selection().set_mode(Gtk.SelectionMode.SINGLE) + cell = Gtk.CellRendererText() + column = Gtk.TreeViewColumn("Widget", cell, text=0) treeview.append_column(column) treeview.set_search_column(0) - model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT) + model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_INT) keys = list(values.keys()) keys.sort() i = 0 @@ -342,12 +341,12 @@ def selection(title, values, alwaysask=False): treeview.set_model(model) treeview.connect('row-activated', - lambda x, y, z: dialog.response(gtk.RESPONSE_OK) or True) + lambda x, y, z: dialog.response(Gtk.ResponseType.OK) or True) dialog.show_all() response = dialog.run() res = None - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: sel = treeview.get_selection().get_selected() if sel: (model, i) = sel @@ -361,28 +360,29 @@ def selection(title, values, alwaysask=False): def file_selection(title, filename='', - action=gtk.FILE_CHOOSER_ACTION_OPEN, preview=True, multi=False, + action=Gtk.FileChooserAction.OPEN, preview=True, multi=False, filters=None): parent = get_toplevel_window() - if action == gtk.FILE_CHOOSER_ACTION_OPEN: - buttons = (set_underline(_("Cancel")), gtk.RESPONSE_CANCEL, - set_underline(_("Select")), gtk.RESPONSE_OK) + if action == Gtk.FileChooserAction.OPEN: + buttons = (set_underline(_("Cancel")), Gtk.ResponseType.CANCEL, + set_underline(_("Select")), Gtk.ResponseType.OK) else: - buttons = (set_underline(_("Cancel")), gtk.RESPONSE_CANCEL, - set_underline(_("Save")), gtk.RESPONSE_OK) - win = gtk.FileChooserDialog(title, None, action, buttons) - win.set_transient_for(parent) + buttons = (set_underline(_("Cancel")), Gtk.ResponseType.CANCEL, + set_underline(_("Save")), Gtk.ResponseType.OK) + win = Gtk.FileChooserDialog( + title=title, transient_for=parent, action=action) + win.add_buttons(*buttons) win.set_icon(TRYTON_ICON) if filename: - if action in (gtk.FILE_CHOOSER_ACTION_SAVE, - gtk.FILE_CHOOSER_ACTION_CREATE_FOLDER): + if action in (Gtk.FileChooserAction.SAVE, + Gtk.FileChooserAction.CREATE_FOLDER): win.set_current_name(filename) else: win.set_filename(filename) if hasattr(win, 'set_do_overwrite_confirmation'): win.set_do_overwrite_confirmation(True) win.set_select_multiple(multi) - win.set_default_response(gtk.RESPONSE_OK) + win.set_default_response(Gtk.ResponseType.OK) if filters is not None: for filt in filters: win.add_filter(filt) @@ -392,22 +392,22 @@ def file_selection(title, filename='', filename = win.get_preview_filename() if filename: try: - pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( + pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( filename, 128, 128) img.set_from_pixbuf(pixbuf) have_preview = True - except (IOError, glib.GError): + except (IOError, GLib.GError): pass win.set_preview_widget_active(have_preview) return if preview: - img_preview = gtk.Image() + img_preview = Gtk.Image() win.set_preview_widget(img_preview) win.connect('update-preview', update_preview_cb, img_preview) button = win.run() - if button != gtk.RESPONSE_OK: + if button != Gtk.ResponseType.OK: result = None elif not multi: result = win.get_filename() @@ -448,7 +448,7 @@ def file_write(filename, data): def file_open(filename, type=None, print_p=False): def save(): save_name = file_selection(_('Save As...'), - action=gtk.FILE_CHOOSER_ACTION_SAVE) + action=Gtk.FileChooserAction.SAVE) if save_name: file_p = open(filename, 'rb') save_p = open(save_name, 'wb+') @@ -555,11 +555,11 @@ class UniqueDialog(object): class MessageDialog(UniqueDialog): - def build_dialog(self, parent, message, msg_type=gtk.MESSAGE_INFO, - buttons=gtk.BUTTONS_OK, secondary=None): - dialog = gtk.MessageDialog(parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, msg_type, - buttons, message) + def build_dialog(self, parent, message, msg_type=Gtk.MessageType.INFO, + buttons=Gtk.ButtonsType.OK, secondary=None): + dialog = Gtk.MessageDialog( + transient_for=parent, modal=True, destroy_with_parent=True, + message_type=msg_type, buttons=buttons, text=message) if secondary: dialog.format_secondary_text(secondary) return dialog @@ -573,9 +573,9 @@ message = MessageDialog() class WarningDialog(MessageDialog): - def __call__(self, message, title, buttons=gtk.BUTTONS_OK, **kwargs): + def __call__(self, message, title, buttons=Gtk.ButtonsType.OK, **kwargs): return super().__call__( - title, gtk.MESSAGE_WARNING, buttons, message, **kwargs) + title, Gtk.MessageType.WARNING, buttons, message, **kwargs) warning = WarningDialog() @@ -592,25 +592,25 @@ class UserWarningDialog(WarningDialog): def build_dialog(self, *args, **kwargs): dialog = super().build_dialog(*args, **kwargs) - check = gtk.CheckButton(_('Always ignore this warning.')) + check = Gtk.CheckButton(label=_('Always ignore this warning.')) check.connect_after('toggled', self._set_always) - alignment = gtk.Alignment(0, 0.5) + alignment = Gtk.Alignment(xalign=0, yalign=0.5) alignment.add(check) - dialog.vbox.pack_start(alignment, True, False) - label = gtk.Label(_('Do you want to proceed?')) - label.set_alignment(1, 0.5) - dialog.vbox.pack_start(label, True, True) + dialog.vbox.pack_start(alignment, expand=True, fill=False, padding=0) + label = Gtk.Label( + label=_('Do you want to proceed?'), halign=Gtk.Align.END) + dialog.vbox.pack_start(label, expand=True, fill=True, padding=0) return dialog def process_response(self, response): - if response == gtk.RESPONSE_YES: + if response == Gtk.ResponseType.YES: if self.always: return 'always' return 'ok' return 'cancel' def __call__(self, message, title): - return super().__call__(message, title, gtk.BUTTONS_YES_NO) + return super().__call__(message, title, Gtk.ButtonsType.YES_NO) userwarning = UserWarningDialog() @@ -619,14 +619,15 @@ userwarning = UserWarningDialog() class ConfirmationDialog(MessageDialog): def __call__(self, message, *args, **kwargs): - return super().__call__(message, gtk.MESSAGE_QUESTION, *args, **kwargs) + return super().__call__( + message, Gtk.MessageType.QUESTION, *args, **kwargs) class SurDialog(ConfirmationDialog): def __call__(self, message): - response = super().__call__(message, buttons=gtk.BUTTONS_YES_NO) - return response == gtk.RESPONSE_YES + response = super().__call__(message, buttons=Gtk.ButtonsType.YES_NO) + return response == Gtk.ResponseType.YES sur = SurDialog() @@ -635,21 +636,21 @@ sur = SurDialog() class Sur3BDialog(ConfirmationDialog): response_mapping = { - gtk.RESPONSE_YES: 'ok', - gtk.RESPONSE_NO: 'ko', - gtk.RESPONSE_CANCEL: 'cancel' + Gtk.ResponseType.YES: 'ok', + Gtk.ResponseType.NO: 'ko', + Gtk.ResponseType.CANCEL: 'cancel' } def build_dialog(self, *args, **kwargs): dialog = super().build_dialog(*args, **kwargs) - dialog.add_button(set_underline(_("Cancel")), gtk.RESPONSE_CANCEL) - dialog.add_button(set_underline(_("No")), gtk.RESPONSE_NO) - dialog.add_button(set_underline(_("Yes")), gtk.RESPONSE_YES) - dialog.set_default_response(gtk.RESPONSE_YES) + dialog.add_button(set_underline(_("Cancel")), Gtk.ResponseType.CANCEL) + dialog.add_button(set_underline(_("No")), Gtk.ResponseType.NO) + dialog.add_button(set_underline(_("Yes")), Gtk.ResponseType.YES) + dialog.set_default_response(Gtk.ResponseType.YES) return dialog def __call__(self, message): - response = super().__call__(message, buttons=gtk.BUTTONS_NONE) + response = super().__call__(message, buttons=Gtk.ButtonsType.NONE) return self.response_mapping.get(response, 'cancel') @@ -661,22 +662,22 @@ class AskDialog(MessageDialog): def build_dialog(self, *args, **kwargs): visibility = kwargs.pop('visibility') dialog = super().build_dialog(*args, **kwargs) - dialog.set_default_response(gtk.RESPONSE_OK) + dialog.set_default_response(Gtk.ResponseType.OK) box = dialog.get_message_area() - self.entry = gtk.Entry() + self.entry = Gtk.Entry() self.entry.set_activates_default(True) self.entry.set_visibility(visibility) - box.pack_start(self.entry) + box.pack_start(self.entry, False, False, 0) return dialog def process_response(self, response): - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: return self.entry.get_text() def __call__(self, question, visibility=True): return super().__call__( - question, gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK_CANCEL, - visibility=visibility) + question, Gtk.MessageType.QUESTION, + buttons=Gtk.ButtonsType.OK_CANCEL, visibility=visibility) ask = AskDialog() @@ -686,31 +687,31 @@ class ConcurrencyDialog(UniqueDialog): def build_dialog(self, parent, resource, obj_id, context): tooltips = Tooltips() - dialog = gtk.MessageDialog(parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, - _('Concurrency Exception')) + dialog = Gtk.MessageDialog( + transient_for=parent, modal=True, destroy_with_parent=True, + message_type=Gtk.MessageType.QUESTION, + buttons=Gtk.ButtonsType.NONE, text=_('Concurrency Exception')) dialog.format_secondary_text( _('This record has been modified while you were editing it.')) cancel_button = dialog.add_button( - set_underline(_("Cancel")), gtk.RESPONSE_CANCEL) + set_underline(_("Cancel")), Gtk.ResponseType.CANCEL) tooltips.set_tip(cancel_button, _('Cancel saving')) compare_button = dialog.add_button( - set_underline(_("Compare")), gtk.RESPONSE_APPLY) + set_underline(_("Compare")), Gtk.ResponseType.APPLY) tooltips.set_tip(compare_button, _('See the modified version')) write_button = dialog.add_button( - set_underline(_("Write Anyway")), gtk.RESPONSE_OK) + set_underline(_("Write Anyway")), Gtk.ResponseType.OK) tooltips.set_tip(write_button, _('Save your current version')) - dialog.set_default_response(gtk.RESPONSE_CANCEL) + dialog.set_default_response(Gtk.ResponseType.CANCEL) return dialog def __call__(self, resource, obj_id, context): res = super(ConcurrencyDialog, self).__call__(resource, obj_id, context) - if res == gtk.RESPONSE_OK: + if res == Gtk.ResponseType.OK: return True - if res == gtk.RESPONSE_APPLY: + if res == Gtk.ResponseType.APPLY: from tryton.gui.window import Window Window.create(resource, res_id=obj_id, @@ -726,54 +727,48 @@ concurrency = ConcurrencyDialog() class ErrorDialog(UniqueDialog): def build_dialog(self, parent, title, details): - dialog = gtk.MessageDialog(parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - gtk.MESSAGE_ERROR, gtk.BUTTONS_NONE, - _('Application Error')) + dialog = Gtk.MessageDialog( + transient_for=parent, modal=True, destroy_with_parent=True, + message_type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.NONE) dialog.set_default_size(600, 400) + dialog.set_position(Gtk.WindowPosition.CENTER) - dialog.add_button(set_underline(_("Report Bug")), gtk.RESPONSE_OK) - dialog.add_button(set_underline(_("Close")), gtk.RESPONSE_CANCEL) - dialog.set_default_response(gtk.RESPONSE_CANCEL) + dialog.add_button(set_underline(_("Report Bug")), Gtk.ResponseType.OK) + dialog.add_button(set_underline(_("Close")), Gtk.ResponseType.CANCEL) + dialog.set_default_response(Gtk.ResponseType.CANCEL) - vbox = dialog.vbox + dialog.set_markup( + '%s' % GLib.markup_escape_text(_('Application Error'))) + dialog.format_secondary_markup( + '%s' % _('Error: %s') % GLib.markup_escape_text(title)) - scrolledwindow = gtk.ScrolledWindow() - scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scrolledwindow.set_shadow_type(gtk.SHADOW_NONE) + scrolledwindow = Gtk.ScrolledWindow() + scrolledwindow.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scrolledwindow.set_shadow_type(Gtk.ShadowType.NONE) - viewport = gtk.Viewport() - viewport.set_shadow_type(gtk.SHADOW_NONE) + viewport = Gtk.Viewport() + viewport.set_shadow_type(Gtk.ShadowType.NONE) - box = gtk.VBox() - label_error = gtk.Label() - label_error.set_markup('') - label_error.set_alignment(0, 0.5) - label_error.set_padding(-1, 14) - label_error.modify_font(pango.FontDescription("monospace")) - label_error.set_markup('' + _('Error: ') + '' + to_xml(title)) - box.pack_start(label_error, False, False) - textview = gtk.TextView() - buf = gtk.TextBuffer() + textview = Gtk.TextView(editable=False, sensitive=True, monospace=True) + buf = Gtk.TextBuffer() buf.set_text(details) textview.set_buffer(buf) - textview.set_editable(False) - textview.set_sensitive(True) - textview.modify_font(pango.FontDescription("monospace")) - box.pack_start(textview, True, True) - viewport.add(box) + viewport.add(textview) scrolledwindow.add(viewport) - vbox.pack_start(scrolledwindow, expand=True, fill=True) + dialog.vbox.pack_start( + scrolledwindow, expand=True, fill=True, padding=0) button_roundup = Gtk.LinkButton.new_with_label( CONFIG['roundup.url'], _('To report bugs you must have an account on %s') % CONFIG['roundup.url']) - button_roundup.set_alignment(0, 0.5) + button_roundup.get_child().set_halign(Gtk.Align.START) button_roundup.connect('activate-link', lambda widget: webbrowser.open(CONFIG['roundup.url'], new=2)) - vbox.pack_start(button_roundup, False, False) + dialog.vbox.pack_start( + button_roundup, expand=False, fill=False, padding=0) return dialog @@ -784,7 +779,7 @@ class ErrorDialog(UniqueDialog): log.error(details + '\n' + title) response = super(ErrorDialog, self).__call__(title, details) - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: send_bugtracker(title, details) @@ -794,43 +789,48 @@ error = ErrorDialog() def send_bugtracker(title, msg): from tryton import rpc parent = get_toplevel_window() - win = gtk.Dialog(_('Bug Tracker'), parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) - win.add_button(set_underline(_("Cancel")), gtk.RESPONSE_CANCEL) - win.add_button(set_underline(_("OK")), gtk.RESPONSE_OK) + win = Gtk.Dialog( + title=_('Bug Tracker'), transient_for=parent, modal=True, + destroy_with_parent=True) + win.add_button(set_underline(_("Cancel")), Gtk.ResponseType.CANCEL) + win.add_button(set_underline(_("OK")), Gtk.ResponseType.OK) win.set_icon(TRYTON_ICON) - win.set_default_response(gtk.RESPONSE_OK) + win.set_default_response(Gtk.ResponseType.OK) - hbox = gtk.HBox() + hbox = Gtk.HBox() hbox.pack_start( IconFactory.get_image( - 'tryton-info', gtk.ICON_SIZE_DIALOG), - False, False) + 'tryton-info', Gtk.IconSize.DIALOG), + expand=False, fill=False, padding=0) - table = gtk.Table(2, 2) + table = Gtk.Table(n_rows=2, n_columns=2) table.set_col_spacings(3) table.set_row_spacings(3) table.set_border_width(1) - label_user = gtk.Label(_('User:')) - label_user.set_alignment(1.0, 0.5) - table.attach(label_user, 0, 1, 0, 1, yoptions=False, - xoptions=gtk.FILL) - entry_user = gtk.Entry() + label_user = Gtk.Label( + label=_('User:'), halign=Gtk.Align.END) + table.attach( + label_user, 0, 1, 0, 1, yoptions=False, + xoptions=Gtk.AttachOptions.FILL) + entry_user = Gtk.Entry() entry_user.set_activates_default(True) - table.attach(entry_user, 1, 2, 0, 1, yoptions=False, - xoptions=gtk.FILL) - label_password = gtk.Label(_('Password:')) - label_password.set_alignment(1.0, 0.5) - table.attach(label_password, 0, 1, 1, 2, yoptions=False, - xoptions=gtk.FILL) - entry_password = gtk.Entry() + table.attach( + entry_user, 1, 2, 0, 1, yoptions=False, + xoptions=Gtk.AttachOptions.FILL) + label_password = Gtk.Label( + label=_('Password:'), halign=Gtk.Align.END) + table.attach( + label_password, 0, 1, 1, 2, yoptions=False, + xoptions=Gtk.AttachOptions.FILL) + entry_password = Gtk.Entry() entry_password.set_activates_default(True) entry_password.set_visibility(False) - table.attach(entry_password, 1, 2, 1, 2, yoptions=False, - xoptions=gtk.FILL) - hbox.pack_start(table) + table.attach( + entry_password, 1, 2, 1, 2, yoptions=False, + xoptions=Gtk.AttachOptions.FILL) + hbox.pack_start(table, expand=True, fill=True, padding=0) - win.vbox.pack_start(hbox) + win.vbox.pack_start(hbox, expand=True, fill=True, padding=0) win.show_all() if rpc._USERNAME: entry_user.set_text(rpc._USERNAME) @@ -843,7 +843,7 @@ def send_bugtracker(title, msg): user = entry_user.get_text() password = entry_password.get_text() win.destroy() - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: try: msg = msg.encode('ascii', 'replace') title = title.encode('ascii', 'replace') @@ -899,7 +899,8 @@ def send_bugtracker(title, msg): tb_s = reduce(lambda x, y: x + y, traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])) - message(_('Exception:') + '\n' + tb_s, msg_type=gtk.MESSAGE_ERROR) + message( + _('Exception:') + '\n' + tb_s, msg_type=Gtk.MessageType.ERROR) def check_version(box, version=__version__): @@ -940,11 +941,12 @@ def check_version(box, version=__version__): if check_version(box, version): info_bar = Gtk.InfoBar() info_bar.get_content_area().pack_start( - gtk.Label(_("A new version is available!"))) + Gtk.Label(label=_("A new version is available!")), + expand=True, fill=True, padding=0) info_bar.set_show_close_button(True) info_bar.add_button(_("Download"), Gtk.ResponseType.ACCEPT) info_bar.connect('response', info_bar_response, box, url) - box.pack_start(info_bar) + box.pack_start(info_bar, expand=True, fill=True, padding=0) info_bar.show_all() return False @@ -983,7 +985,8 @@ def process_exception(exception, *args, **kwargs): del args[5]['_timestamp'] return rpc_execute(*args) else: - message(_('Concurrency Exception'), msg_type=gtk.MESSAGE_ERROR) + message( + _('Concurrency Exception'), msg_type=Gtk.MessageType.ERROR) elif exception.faultCode == str(int(HTTPStatus.UNAUTHORIZED)): from tryton.gui.main import Main if PLOCK.acquire(False): @@ -1119,7 +1122,7 @@ class RPCProgress(object): self.error = True if self.callback: # Post to GTK queue to be run by the main thread - gobject.idle_add(self.process) + GLib.idle_add(self.process) return True def run(self, process_exception_p=True, callback=None): @@ -1130,9 +1133,12 @@ class RPCProgress(object): # Parent is only useful if it is asynchronous # otherwise the cursor is not updated. self.parent = get_toplevel_window() - if self.parent.get_window(): - watch = gtk.gdk.Cursor(gtk.gdk.WATCH) - self.parent.get_window().set_cursor(watch) + window = self.parent.get_window() + if window: + display = window.get_display() + watch = Gdk.Cursor.new_for_display( + display, Gdk.CursorType.WATCH) + window.set_cursor(watch) _thread.start_new_thread(self.start, ()) return else: @@ -1196,7 +1202,7 @@ class Tooltips(object): if hasattr(widget, 'set_tooltip_text'): return widget.set_tooltip_text(tip_text) if not self._tooltips: - self._tooltips = gtk.Tooltips() + self._tooltips = Gtk.Tooltips() return self._tooltips.set_tip(widget, tip_text) def enable(self): @@ -1290,12 +1296,12 @@ def resize_pixbuf(pixbuf, width, height): width = float(img_width) / float(img_height) * float(height) else: height = float(img_height) / float(img_width) * float(width) - return pixbuf.scale_simple(int(width), int(height), - gtk.gdk.INTERP_BILINEAR) + return pixbuf.scale_simple( + int(width), int(height), GdkPixbuf.InterpType.BILINEAR) def _data2pixbuf(data, width=None, height=None): - loader = gtk.gdk.PixbufLoader() + loader = GdkPixbuf.PixbufLoader() if width and height: loader.set_size(width, height) loader.write(data) @@ -1307,7 +1313,7 @@ def data2pixbuf(data, width=None, height=None): if data: try: return _data2pixbuf(data, width, height) - except glib.GError: + except GLib.GError: pass @@ -1327,6 +1333,17 @@ def ellipsize(string, length): return string[:length - len(ellipsis)] + ellipsis +def get_align(float_): + "Convert float align into Gtk.Align" + value = float(float_) + if value < 0.5: + return Gtk.Align.START + elif value == 0.5: + return Gtk.Align.FILL + else: + return Gtk.Align.END + + def date_format(format_): return format_ or rpc.CONTEXT.get('locale', {}).get('date', '%x') diff --git a/tryton/common/completion.py b/tryton/common/completion.py index d6f56f7f00..8f75133051 100644 --- a/tryton/common/completion.py +++ b/tryton/common/completion.py @@ -3,8 +3,7 @@ import logging import gettext -import gtk -import gobject +from gi.repository import GLib, Gtk from tryton.config import CONFIG from tryton.common import RPCExecute @@ -16,9 +15,9 @@ logger = logging.getLogger(__name__) def get_completion(search=True, create=True): "Return a EntryCompletion" - completion = gtk.EntryCompletion() + completion = Gtk.EntryCompletion() completion.set_match_func(lambda *a: True) - completion.set_model(gtk.ListStore(str, int)) + completion.set_model(Gtk.ListStore(str, int)) completion.set_text_column(0) completion.props.popup_set_width = False if search: @@ -71,4 +70,4 @@ def update_completion(entry, record, field, model, domain=None): exc_info=True) return False search_text = entry.get_text() - gobject.timeout_add(300, update, search_text, domain) + GLib.timeout_add(300, update, search_text, domain) diff --git a/tryton/common/datetime_.py b/tryton/common/datetime_.py index e063ab5185..0fa956541b 100644 --- a/tryton/common/datetime_.py +++ b/tryton/common/datetime_.py @@ -3,8 +3,7 @@ import gettext import datetime -import gobject -import gtk +from gi.repository import Gdk, GObject, Gtk from dateutil.relativedelta import relativedelta from dateutil.parser import parse @@ -24,30 +23,30 @@ def date_parse(text, format_='%x'): return parse(text, dayfirst=dayfirst, yearfirst=yearfirst, ignoretz=True) -class Date(gtk.Entry): +class Date(Gtk.Entry): __gtype_name__ = 'Date' __gproperties__ = { - 'value': (gobject.TYPE_PYOBJECT, + 'value': (GObject.TYPE_PYOBJECT, _('Value'), _('Displayed value'), - gobject.ParamFlags.READABLE | gobject.ParamFlags.WRITABLE), - 'format': (gobject.TYPE_STRING, + GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), + 'format': (GObject.TYPE_STRING, '%x', _('Format'), _('Display format'), - gobject.ParamFlags.READABLE | gobject.ParamFlags.WRITABLE), + GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), } __gsignals__ = { 'date-changed': ( - gobject.SignalFlags.RUN_LAST | gobject.SignalFlags.ACTION, - gobject.TYPE_NONE, ()), + GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, + GObject.TYPE_NONE, ()), } def __init__(self): self.__date = None self.__format = '%x' - gtk.Entry.__init__(self) + Gtk.Entry.__init__(self) self.set_width_chars(20) @@ -56,23 +55,26 @@ class Date(gtk.Entry): # Calendar Popup self.set_icon_from_pixbuf( - gtk.ENTRY_ICON_PRIMARY, - IconFactory.get_pixbuf('tryton-date', gtk.ICON_SIZE_MENU)) - self.set_icon_tooltip_text(gtk.ENTRY_ICON_PRIMARY, + Gtk.EntryIconPosition.PRIMARY, + IconFactory.get_pixbuf('tryton-date', Gtk.IconSize.MENU)) + self.set_icon_tooltip_text( + Gtk.EntryIconPosition.PRIMARY, _('Open the calendar')) self.connect('icon-press', self.icon_press) - self.__cal_popup = gtk.Window(gtk.WINDOW_POPUP) + self.__cal_popup = Gtk.Window(type=Gtk.WindowType.POPUP) self.__cal_popup.set_events( - self.__cal_popup.get_events() | gtk.gdk.KEY_PRESS_MASK) + self.__cal_popup.get_events() | Gdk.EventMask.KEY_PRESS_MASK) self.__cal_popup.set_resizable(False) self.__cal_popup.connect('delete-event', self.cal_popup_closed) self.__cal_popup.connect('key-press-event', self.cal_popup_key_pressed) self.__cal_popup.connect('button-press-event', self.cal_popup_button_pressed) - self.__calendar = gtk.Calendar() - cal_options = gtk.CALENDAR_SHOW_DAY_NAMES | gtk.CALENDAR_SHOW_HEADING + self.__calendar = Gtk.Calendar() + cal_options = ( + Gtk.CalendarDisplayOptions.SHOW_DAY_NAMES | + Gtk.CalendarDisplayOptions.SHOW_HEADING) self.__calendar.set_display_options(cal_options) self.__cal_popup.add(self.__calendar) self.__calendar.connect('day-selected', self.cal_popup_changed) @@ -99,7 +101,7 @@ class Date(gtk.Entry): def icon_press(self, entry, icon_pos, event): self.grab_focus() - if icon_pos == gtk.ENTRY_ICON_PRIMARY: + if icon_pos == Gtk.EntryIconPosition.PRIMARY: self.cal_popup_open() def cal_popup_open(self): @@ -124,18 +126,19 @@ class Date(gtk.Entry): self.cal_popup_hide() def cal_popup_key_pressed(self, calendar, event): - if event.keyval != gtk.keysyms.Escape: + if event.keyval != Gdk.KEY_Escape: return False - self.stop_emission('key-press-event') + self.stop_emission_by_name('key-press-event') self.cal_popup_hide() return True def cal_popup_button_pressed(self, calendar, event): child = event.window - if child != calendar.window: + window = calendar.get_window() + if child != window: while child: - if child == calendar.window: + if child == window: return False child = child.get_parent() self.cal_popup_hide() @@ -188,16 +191,16 @@ class Date(gtk.Entry): return self.__format -gobject.type_register(Date) +GObject.type_register(Date) -class CellRendererDate(gtk.CellRendererText): +class CellRendererDate(Gtk.CellRendererText): __gproperties__ = { - 'format': (gobject.TYPE_STRING, + 'format': (GObject.TYPE_STRING, _('Format'), _('Display format'), '%x', - gobject.ParamFlags.READABLE | gobject.ParamFlags.WRITABLE), + GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), } def __init__(self): @@ -205,18 +208,18 @@ class CellRendererDate(gtk.CellRendererText): self.__entry = None self.__focus_out_id = 0 - gtk.CellRendererText.__init__(self) + Gtk.CellRendererText.__init__(self) def do_set_property(self, prop, value): if prop.name == 'format': self.__format = value return - gtk.CellRendererText.set_property(self, prop, value) + Gtk.CellRendererText.set_property(self, prop, value) def do_get_property(self, prop): if prop.name == 'format': return self.__format - return gtk.CellRendererText.get_property(self, prop) + return Gtk.CellRendererText.get_property(self, prop) def do_start_editing( self, event, widget, path, background_area, cell_area, flags): @@ -250,33 +253,33 @@ class CellRendererDate(gtk.CellRendererText): return False -gobject.type_register(CellRendererDate) +GObject.type_register(CellRendererDate) -class Time(gtk.ComboBoxEntry): +class Time(Gtk.ComboBox): __gtype_name__ = 'Time' __gproperties__ = { - 'value': (gobject.TYPE_PYOBJECT, + 'value': (GObject.TYPE_PYOBJECT, _('Value'), _('Displayed value'), - gobject.ParamFlags.READABLE | gobject.ParamFlags.WRITABLE), - 'format': (gobject.TYPE_STRING, + GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), + 'format': (GObject.TYPE_STRING, _('Format'), _('Display format'), '%X', - gobject.ParamFlags.READABLE | gobject.ParamFlags.WRITABLE), + GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), } __gsignals__ = { 'time-changed': ( - gobject.SignalFlags.RUN_LAST | gobject.SignalFlags.ACTION, - gobject.TYPE_NONE, ()), + GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, + GObject.TYPE_NONE, ()), } def __init__(self): self.__time = None self.__format = '%X' - gtk.ComboBoxEntry.__init__(self) + Gtk.ComboBox.__init__(self, has_entry=True) self.__entry = self.get_child() self.__entry.set_width_chars(10) @@ -285,11 +288,11 @@ class Time(gtk.ComboBoxEntry): self.__entry.connect('activate', self.activate) self.connect('changed', self.changed) - self.__model = gtk.ListStore( - gobject.TYPE_STRING, gobject.TYPE_PYOBJECT) + self.__model = Gtk.ListStore( + GObject.TYPE_STRING, GObject.TYPE_PYOBJECT) self.update_model() self.set_model(self.__model) - self.set_text_column(0) + self.set_entry_text_column(0) def parse(self): text = self.__entry.get_text() @@ -360,16 +363,16 @@ class Time(gtk.ComboBoxEntry): return self.__format -gobject.type_register(Time) +GObject.type_register(Time) -class CellRendererTime(gtk.CellRendererCombo): +class CellRendererTime(Gtk.CellRendererCombo): __gproperties__ = { - 'format': (gobject.TYPE_STRING, + 'format': (GObject.TYPE_STRING, '%X', _('Format'), _('Display format'), - gobject.ParamFlags.READABLE | gobject.ParamFlags.WRITABLE), + GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), } def __init__(self): @@ -377,18 +380,18 @@ class CellRendererTime(gtk.CellRendererCombo): self.__combo = None self.__focus_out_id = 0 - gtk.CellRendererText.__init__(self) + Gtk.CellRendererText.__init__(self) def do_set_property(self, prop, value): if prop.name == 'format': self.__format = value return - gtk.CellRendererText.set_property(self, prop, value) + Gtk.CellRendererText.set_property(self, prop, value) def do_get_property(self, prop): if prop.name == 'format': return self.__format - return gtk.CellRendererText.get_property(self, prop) + return Gtk.CellRendererText.get_property(self, prop) def do_start_editing( self, event, widget, path, background_area, cell_area, flags): @@ -418,44 +421,44 @@ class CellRendererTime(gtk.CellRendererCombo): return False -gobject.type_register(CellRendererTime) +GObject.type_register(CellRendererTime) -class DateTime(gtk.HBox): +class DateTime(Gtk.HBox): __gtype_name__ = 'DateTime' __gproperties__ = { - 'value': (gobject.TYPE_PYOBJECT, + 'value': (GObject.TYPE_PYOBJECT, _('Value'), _('Displayed value'), - gobject.ParamFlags.READABLE | gobject.ParamFlags.WRITABLE), - 'date-format': (gobject.TYPE_STRING, + GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), + 'date-format': (GObject.TYPE_STRING, '%x', _('Date Format'), _('Displayed date format'), - gobject.ParamFlags.READABLE | gobject.ParamFlags.WRITABLE), - 'time-format': (gobject.TYPE_STRING, + GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), + 'time-format': (GObject.TYPE_STRING, '%X', _('Date Format'), _('Displayed date format'), - gobject.ParamFlags.READABLE | gobject.ParamFlags.WRITABLE), + GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE), } __gsignals__ = { 'datetime-changed': ( - gobject.SignalFlags.RUN_LAST | gobject.SignalFlags.ACTION, - gobject.TYPE_NONE, ()), + GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, + GObject.TYPE_NONE, ()), } def __init__(self): - gtk.HBox.__init__(self, spacing=4) + Gtk.HBox.__init__(self, spacing=4) self.__date = Date() - self.pack_start(self.__date, True, True, 0) + self.pack_start(self.__date, expand=True, fill=True, padding=0) self.__date.show() self.__date.connect('date-changed', lambda e: self.emit('datetime-changed')) self.__time = Time() - self.pack_start(self.__time, True, True, 0) + self.pack_start(self.__time, expand=True, fill=True, padding=0) self.__time.show() self.__time.connect('time-changed', lambda e: self.emit('datetime-changed')) @@ -499,16 +502,12 @@ class DateTime(gtk.HBox): self.__time.child.modify_text(state, color) -gobject.type_register(DateTime) +GObject.type_register(DateTime) def popup_position(widget, popup): allocation = widget.get_allocation() - if hasattr(widget.window, 'get_root_coords'): - x, y = widget.window.get_root_coords(allocation.x, allocation.y) - else: - x, y = widget.window.get_origin() - width, height = popup.size_request() + x, y = widget.get_window().get_root_coords(allocation.x, allocation.y) popup.move(x, y + allocation.height) @@ -517,18 +516,19 @@ def popup_show(popup): popup.grab_focus() popup.grab_add() - cursor = gtk.gdk.Cursor(gtk.gdk.ARROW) - gtk.gdk.pointer_grab(popup.window, True, - (gtk.gdk.BUTTON_PRESS_MASK - | gtk.gdk.BUTTON_RELEASE_MASK - | gtk.gdk.POINTER_MOTION_MASK), - None, cursor, 0) + window = popup.get_window() + display = window.get_display() + seat = display.get_default_seat() + seat.grab(window, Gdk.SeatCapabilities.ALL, True, None, None, None, None) def popup_hide(popup): popup.hide() popup.grab_remove() - gtk.gdk.pointer_ungrab(0) + window = popup.get_window() + display = window.get_display() + seat = display.get_default_seat() + seat.ungrab() def timelist_set_list(model, min_, max_, format_): @@ -560,7 +560,7 @@ def add_operators(widget): except TypeError: return False return True - elif event.keyval in (gtk.keysyms.KP_Equal, gtk.keysyms.equal): + elif event.keyval in (Gdk.KEY_KP_Equal, Gdk.KEY_equal): widget.props.value = datetime.datetime.now() return True return False @@ -569,7 +569,7 @@ def add_operators(widget): for child in widget.get_children(): add_operators(child) return widget - if isinstance(widget, gtk.ComboBoxEntry): + if isinstance(widget, Gtk.ComboBox): editable = widget.get_child() else: editable = widget @@ -578,47 +578,47 @@ def add_operators(widget): OPERATORS = { - gtk.keysyms.S: relativedelta(seconds=-1), - gtk.keysyms.s: relativedelta(seconds=1), - gtk.keysyms.I: relativedelta(minutes=-1), - gtk.keysyms.i: relativedelta(minutes=1), - gtk.keysyms.H: relativedelta(hours=-1), - gtk.keysyms.h: relativedelta(hours=1), - gtk.keysyms.D: relativedelta(days=-1), - gtk.keysyms.d: relativedelta(days=1), - gtk.keysyms.W: relativedelta(weeks=-1), - gtk.keysyms.w: relativedelta(weeks=1), - gtk.keysyms.M: relativedelta(months=-1), - gtk.keysyms.m: relativedelta(months=1), - gtk.keysyms.Y: relativedelta(years=-1), - gtk.keysyms.y: relativedelta(years=1), + Gdk.KEY_S: relativedelta(seconds=-1), + Gdk.KEY_s: relativedelta(seconds=1), + Gdk.KEY_I: relativedelta(minutes=-1), + Gdk.KEY_i: relativedelta(minutes=1), + Gdk.KEY_H: relativedelta(hours=-1), + Gdk.KEY_h: relativedelta(hours=1), + Gdk.KEY_D: relativedelta(days=-1), + Gdk.KEY_d: relativedelta(days=1), + Gdk.KEY_W: relativedelta(weeks=-1), + Gdk.KEY_w: relativedelta(weeks=1), + Gdk.KEY_M: relativedelta(months=-1), + Gdk.KEY_m: relativedelta(months=1), + Gdk.KEY_Y: relativedelta(years=-1), + Gdk.KEY_y: relativedelta(years=1), } if __name__ == '__main__': - win = gtk.Window() - win.connect('delete-event', gtk.main_quit) + win = Gtk.Window() + win.connect('delete-event', Gtk.main_quit) - v = gtk.VBox() + v = Gtk.VBox() v.show() d = add_operators(Date()) d.show() - v.pack_start(d, False, False) + v.pack_start(d, expand=False, fill=False, padding=0) t = add_operators(Time()) t.show() - v.pack_start(t, False, False) + v.pack_start(t, expand=False, fill=False, padding=0) t = add_operators(Time()) t.props.format = '%H:%M' t.show() - v.pack_start(t, False, False) + v.pack_start(t, expand=False, fill=False, padding=0) dt = add_operators(DateTime()) dt.show() - v.pack_start(dt, False, False) + v.pack_start(dt, expand=False, fill=False, padding=0) win.add(v) win.show() - gtk.main() + Gtk.main() diff --git a/tryton/common/focus.py b/tryton/common/focus.py index b91446e9f6..2a3806eab8 100644 --- a/tryton/common/focus.py +++ b/tryton/common/focus.py @@ -2,7 +2,7 @@ # this repository contains the full copyright notices and license terms. from functools import cmp_to_key -import gtk +from gi.repository import Gtk def get_invisible_ancestor(widget): @@ -25,7 +25,7 @@ def find_focused_child(widget): def tab_compare(a, b): - text_direction = gtk.widget_get_default_direction() + text_direction = Gtk.Widget.get_default_direction() a_allocation = a.get_allocation() b_allocation = b.get_allocation() y1 = a_allocation.y + a_allocation.height // 2 @@ -35,7 +35,7 @@ def tab_compare(a, b): x1 = a_allocation.x + a_allocation.width // 2 x2 = b_allocation.x + b_allocation.width // 2 - if text_direction == gtk.TEXT_DIR_RTL: + if text_direction == Gtk.TextDirection.RTL: return (x2 > x1) - (x2 < x1) else: return (x1 > x2) - (x1 < x2) diff --git a/tryton/common/htmltextbuffer.py b/tryton/common/htmltextbuffer.py index 2f6cdcedd5..391e2fc182 100644 --- a/tryton/common/htmltextbuffer.py +++ b/tryton/common/htmltextbuffer.py @@ -18,6 +18,7 @@ use_serialize_func = False def _reverse_dict(dct): return {j: i for i, j in dct.items()} + SIZE2SCALE = { '1': 1 / (1.2 * 1.2 * 1.2), '2': 1 / (1.2 * 1.2), @@ -296,6 +297,8 @@ def deserialize(register, content, iter_, text, create_tags, data): def setup_tags(text_buffer): for name, props in reversed(_TAGS): text_buffer.create_tag(name, **props) + + _TAGS = [ ('bold', {'weight': Pango.Weight.BOLD}), ('italic', {'style': Pango.Style.ITALIC}), diff --git a/tryton/common/popup_menu.py b/tryton/common/popup_menu.py index 4fdda7e123..2afa92e626 100644 --- a/tryton/common/popup_menu.py +++ b/tryton/common/popup_menu.py @@ -1,8 +1,10 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk import gettext -from tryton.common import RPCExecute, RPCException, IconFactory + +from gi.repository import Gtk, Gdk + +from tryton.common import RPCExecute, RPCException from tryton.gui.window.view_form.screen import Screen from tryton.action import Action from tryton.gui.window import Window @@ -45,10 +47,10 @@ def populate(menu, model, record, title='', field=None, context=None): 'id': rec.id, 'ids': [rec.id], } - event = gtk.get_current_event() + event = Gtk.get_current_event() allow_similar = False - if (event.state & gtk.gdk.CONTROL_MASK - or event.state & gtk.gdk.MOD1_MASK): + if (event.state & Gdk.ModifierType.CONTROL_MASK + or event.state & Gdk.ModifierType.MOD1_MASK): allow_similar = True with Window(hide_current=True, allow_similar=allow_similar): Action._exec_action(action, data, rec.get_context()) @@ -69,32 +71,26 @@ def populate(menu, model, record, title='', field=None, context=None): if title: if len(menu): - menu.append(gtk.SeparatorMenuItem()) - title_item = gtk.MenuItem(title) + menu.append(Gtk.SeparatorMenuItem()) + title_item = Gtk.MenuItem(label=title) menu.append(title_item) - submenu = gtk.Menu() + submenu = Gtk.Menu() title_item.set_submenu(submenu) action_menu = submenu else: action_menu = menu if len(action_menu): - action_menu.append(gtk.SeparatorMenuItem()) + action_menu.append(Gtk.SeparatorMenuItem()) if field: - edit_item = gtk.MenuItem(_('Edit...')) + edit_item = Gtk.MenuItem(label=_('Edit...')) edit_item.connect('activate', edit) action_menu.append(edit_item) - action_menu.append(gtk.SeparatorMenuItem()) - attachment_item = gtk.ImageMenuItem() - attachment_item.set_label(_('Attachments...')) - attachment_item.set_image(IconFactory.get_image( - 'tryton-attach', gtk.ICON_SIZE_MENU)) + action_menu.append(Gtk.SeparatorMenuItem()) + attachment_item = Gtk.MenuItem(label=_('Attachments...')) action_menu.append(attachment_item) attachment_item.connect('activate', attachment) - note_item = gtk.ImageMenuItem() - note_item.set_label(_('Notes...')) - note_item.set_image(IconFactory.get_image( - 'tryton-note', gtk.ICON_SIZE_MENU)) + note_item = Gtk.MenuItem(label=_('Notes...')) action_menu.append(note_item) note_item.connect('activate', note) @@ -111,20 +107,17 @@ def populate(menu, model, record, title='', field=None, context=None): ('print', 'tryton-print', _('Print...'), 'print'), ): if len(action_menu): - action_menu.append(gtk.SeparatorMenuItem()) - title_item = gtk.ImageMenuItem() - title_item.set_label(label) - title_item.set_image(IconFactory.get_image( - icon, gtk.ICON_SIZE_MENU)) + action_menu.append(Gtk.SeparatorMenuItem()) + title_item = Gtk.MenuItem(label=label) action_menu.append(title_item) if not toolbar[atype]: title_item.set_sensitive(False) continue - submenu = gtk.Menu() + submenu = Gtk.Menu() title_item.set_submenu(submenu) for action in toolbar[atype]: action = action.copy() - item = gtk.MenuItem(action['name']) + item = Gtk.MenuItem(label=action['name']) submenu.append(item) if flavor == 'print': action['direct_print'] = True diff --git a/tryton/common/selection.py b/tryton/common/selection.py index 374f9ef057..6eff80c1c1 100644 --- a/tryton/common/selection.py +++ b/tryton/common/selection.py @@ -3,8 +3,7 @@ import operator import math -import gtk -import gobject +from gi.repository import Gdk, GLib, GObject, Gtk from tryton.common import RPCExecute, RPCException from tryton.common import eval_domain @@ -123,9 +122,9 @@ class SelectionMixin(object): def selection_shortcuts(entry): def key_press(widget, event): - if (event.type == gtk.gdk.KEY_PRESS - and event.state & gtk.gdk.CONTROL_MASK - and event.keyval == gtk.keysyms.space): + if (event.type == Gdk.EventType.KEY_PRESS + and event.state & Gdk.ModifierType.CONTROL_MASK + and event.keyval == Gdk.KEY_space): widget.popup() entry.connect('key_press_event', key_press) return entry @@ -149,12 +148,8 @@ class PopdownMixin(object): return model, lengths = self.get_popdown_model(selection) entry.set_model(model) - # GTK 2.24 and above use a ComboBox instead of a ComboBoxEntry - if hasattr(entry, 'set_text_column'): - entry.set_text_column(0) - else: - entry.set_entry_text_column(0) - completion = gtk.EntryCompletion() + entry.set_entry_text_column(0) + completion = Gtk.EntryCompletion() completion.set_inline_selection(True) completion.set_model(model) child.set_completion(completion) @@ -173,7 +168,7 @@ class PopdownMixin(object): completion.connect('match-selected', self.match_selected, entry) def get_popdown_model(self, selection): - model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT) + model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_PYOBJECT) lengths = [] for (value, name) in selection: name = str(name) @@ -186,7 +181,7 @@ class PopdownMixin(object): model = entry.get_model() for i, values in enumerate(model): if values[1] == value: - gobject.idle_add(entry.set_active, i) + GLib.idle_add(entry.set_active, i) break def get_popdown_value(self, entry, index=1): diff --git a/tryton/common/timedelta.py b/tryton/common/timedelta.py index 9aa9d94757..014c075b15 100644 --- a/tryton/common/timedelta.py +++ b/tryton/common/timedelta.py @@ -108,6 +108,7 @@ def parse(text, converter=None): seconds *= -1 return datetime.timedelta(seconds=seconds) + _tests = [ (None, ''), (datetime.timedelta(), '00:00'), diff --git a/tryton/common/treeviewcontrol.py b/tryton/common/treeviewcontrol.py index b8867725bd..caf05e6970 100644 --- a/tryton/common/treeviewcontrol.py +++ b/tryton/common/treeviewcontrol.py @@ -1,28 +1,36 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of this # repository contains the full copyright notices and license terms. -import gtk -import gobject +from gi.repository import Gdk, GObject, Gtk -MOVEMENT_KEYS = {gtk.keysyms.Up, gtk.keysyms.Down, gtk.keysyms.space, - gtk.keysyms.Left, gtk.keysyms.KP_Left, - gtk.keysyms.Right, gtk.keysyms.KP_Right, - gtk.keysyms.Home, gtk.keysyms.KP_Home, - gtk.keysyms.End, gtk.keysyms.KP_End} +MOVEMENT_KEYS = { + Gdk.KEY_Up, + Gdk.KEY_Down, + Gdk.KEY_space, + Gdk.KEY_Left, + Gdk.KEY_KP_Left, + Gdk.KEY_Right, + Gdk.KEY_KP_Right, + Gdk.KEY_Home, + Gdk.KEY_KP_Home, + Gdk.KEY_End, + Gdk.KEY_KP_End, + } __all__ = ['TreeViewControl'] -class TreeViewControl(gtk.TreeView): +class TreeViewControl(Gtk.TreeView): def do_button_press_event(self, event): self.grab_focus() # grab focus because it doesn't whith CONTROL MASK if event.button == 1: - event.state ^= gtk.gdk.CONTROL_MASK - return gtk.TreeView.do_button_press_event(self, event) + event.state ^= Gdk.ModifierType.CONTROL_MASK + return Gtk.TreeView.do_button_press_event(self, event) def do_key_press_event(self, event): if event.keyval in MOVEMENT_KEYS: - event.state ^= gtk.gdk.CONTROL_MASK - return gtk.TreeView.do_key_press_event(self, event) + event.state ^= Gdk.ModifierType.CONTROL_MASK + return Gtk.TreeView.do_key_press_event(self, event) -gobject.type_register(TreeViewControl) + +GObject.type_register(TreeViewControl) diff --git a/tryton/config.py b/tryton/config.py index 2d9cc46edb..9f4d9dd14e 100644 --- a/tryton/config.py +++ b/tryton/config.py @@ -7,7 +7,8 @@ import gettext import logging import sys import locale -import gtk + +from gi.repository import GdkPixbuf from tryton import __version__ @@ -169,5 +170,5 @@ if not os.path.isdir(PIXMAPS_DIR): PIXMAPS_DIR = pkg_resources.resource_filename( 'tryton', 'data/pixmaps/tryton') -TRYTON_ICON = gtk.gdk.pixbuf_new_from_file( +TRYTON_ICON = GdkPixbuf.Pixbuf.new_from_file( os.path.join(PIXMAPS_DIR, 'tryton-icon.png')) diff --git a/tryton/gui/main.py b/tryton/gui/main.py index bf524680e5..9231accce9 100644 --- a/tryton/gui/main.py +++ b/tryton/gui/main.py @@ -11,9 +11,7 @@ import traceback import webbrowser from urllib.parse import urlparse, parse_qsl, unquote -import gobject -import gtk -from gi.repository import Gtk, GLib, Gio +from gi.repository import Gdk, GdkPixbuf, Gio, GLib, Gtk import tryton.common as common import tryton.plugins @@ -55,12 +53,12 @@ class Main(Gtk.Application): action.connect( 'activate', lambda *a: self.global_search_entry.grab_focus()) self.add_action(action) - self.add_accelerator('k', 'app.menu-search') + self.set_accels_for_action('app.menu-search', ['k']) action = Gio.SimpleAction.new('menu-toggle', None) action.connect('activate', lambda *a: self.menu_toggle()) self.add_action(action) - self.add_accelerator('m', 'app.menu-toggle') + self.set_accels_for_action('app.menu-toggle', ['m']) toolbar_variant = GLib.Variant.new_string( CONFIG['client.toolbar'] or 'both') @@ -91,12 +89,12 @@ class Main(Gtk.Application): action = Gio.SimpleAction.new('tab-previous', None) action.connect('activate', lambda *a: self.win_prev()) self.add_action(action) - self.add_accelerator('Tab', 'app.tab-previous') + self.set_accels_for_action('app.tab-previous', ['Tab']) action = Gio.SimpleAction.new('tab-next', None) action.connect('activate', lambda *a: self.win_next()) self.add_action(action) - self.add_accelerator('Tab', 'app.tab-next') + self.set_accels_for_action('app.tab-next', ['Tab']) action = Gio.SimpleAction.new('search-limit', None) action.connect('activate', lambda *a: self.edit_limit()) @@ -110,7 +108,7 @@ class Main(Gtk.Application): action = Gio.SimpleAction.new('shortcuts', None) action.connect('activate', lambda *a: self.shortcuts()) self.add_action(action) - self.add_accelerator('F1', 'app.shortcuts') + self.set_accels_for_action('app.shortcuts', ['F1']) action = Gio.SimpleAction.new('about', None) action.connect('activate', lambda *a: self.about()) @@ -119,7 +117,7 @@ class Main(Gtk.Application): action = Gio.SimpleAction.new('quit', None) action.connect('activate', self.on_quit) self.add_action(action) - self.add_accelerator('q', 'app.quit') + self.set_accels_for_action('app.quit', ['q']) menu = Gio.Menu.new() menu.append(_("Preferences..."), 'app.preferences') @@ -165,7 +163,7 @@ class Main(Gtk.Application): self.window = Gtk.ApplicationWindow(application=self, title="Tryton") self.window.set_default_size(960, 720) self.window.maximize() - self.window.set_position(Gtk.WIN_POS_CENTER) + self.window.set_position(Gtk.WindowPosition.CENTER) self.window.set_resizable(True) self.window.set_icon(TRYTON_ICON) self.window.connect("destroy", self.on_quit) @@ -198,64 +196,69 @@ class Main(Gtk.Application): self.accel_group = Gtk.AccelGroup() self.window.add_accel_group(self.accel_group) - gtk.accel_map_add_entry('/Form/New', gtk.keysyms.N, - gtk.gdk.CONTROL_MASK) - gtk.accel_map_add_entry('/Form/Save', gtk.keysyms.S, - gtk.gdk.CONTROL_MASK) - gtk.accel_map_add_entry('/Form/Duplicate', gtk.keysyms.D, - gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK) - gtk.accel_map_add_entry('/Form/Delete', gtk.keysyms.D, - gtk.gdk.CONTROL_MASK) - gtk.accel_map_add_entry('/Form/Next', gtk.keysyms.Page_Down, - 0) - gtk.accel_map_add_entry('/Form/Previous', gtk.keysyms.Page_Up, - 0) - gtk.accel_map_add_entry('/Form/Switch View', gtk.keysyms.L, - gtk.gdk.CONTROL_MASK) - gtk.accel_map_add_entry('/Form/Close', gtk.keysyms.W, - gtk.gdk.CONTROL_MASK) - gtk.accel_map_add_entry('/Form/Reload', gtk.keysyms.R, - gtk.gdk.CONTROL_MASK) - gtk.accel_map_add_entry('/Form/Attachments', gtk.keysyms.T, - gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK) - gtk.accel_map_add_entry('/Form/Notes', gtk.keysyms.O, - gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK) - gtk.accel_map_add_entry('/Form/Relate', gtk.keysyms.R, - gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK) - gtk.accel_map_add_entry('/Form/Actions', gtk.keysyms.E, - gtk.gdk.CONTROL_MASK) - gtk.accel_map_add_entry('/Form/Report', gtk.keysyms.P, - gtk.gdk.CONTROL_MASK) - gtk.accel_map_add_entry('/Form/Search', gtk.keysyms.F, - gtk.gdk.CONTROL_MASK) + Gtk.AccelMap.add_entry( + '/Form/New', Gdk.KEY_N, Gdk.ModifierType.CONTROL_MASK) + Gtk.AccelMap.add_entry( + '/Form/Save', Gdk.KEY_S, Gdk.ModifierType.CONTROL_MASK) + Gtk.AccelMap.add_entry( + '/Form/Duplicate', Gdk.KEY_D, + Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.SHIFT_MASK) + Gtk.AccelMap.add_entry( + '/Form/Delete', Gdk.KEY_D, Gdk.ModifierType.CONTROL_MASK) + Gtk.AccelMap.add_entry( + '/Form/Next', Gdk.KEY_Page_Down, 0) + Gtk.AccelMap.add_entry( + '/Form/Previous', Gdk.KEY_Page_Up, 0) + Gtk.AccelMap.add_entry( + '/Form/Switch View', Gdk.KEY_L, + Gdk.ModifierType.CONTROL_MASK) + Gtk.AccelMap.add_entry( + '/Form/Close', Gdk.KEY_W, Gdk.ModifierType.CONTROL_MASK) + Gtk.AccelMap.add_entry( + '/Form/Reload', Gdk.KEY_R, Gdk.ModifierType.CONTROL_MASK) + Gtk.AccelMap.add_entry( + '/Form/Attachments', Gdk.KEY_T, + Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.SHIFT_MASK) + Gtk.AccelMap.add_entry( + '/Form/Notes', Gdk.KEY_O, + Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.SHIFT_MASK) + Gtk.AccelMap.add_entry( + '/Form/Relate', Gdk.KEY_R, + Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.SHIFT_MASK) + Gtk.AccelMap.add_entry( + '/Form/Actions', Gdk.KEY_E, Gdk.ModifierType.CONTROL_MASK) + Gtk.AccelMap.add_entry( + '/Form/Report', Gdk.KEY_P, Gdk.ModifierType.CONTROL_MASK) + Gtk.AccelMap.add_entry( + '/Form/Search', Gdk.KEY_F, Gdk.ModifierType.CONTROL_MASK) - gtk.accel_map_load(os.path.join(get_config_dir(), 'accel.map')) + Gtk.AccelMap.load(os.path.join(get_config_dir(), 'accel.map')) self.tooltips = common.Tooltips() - self.vbox = gtk.VBox() + self.vbox = Gtk.VBox() self.window.add(self.vbox) self.buttons = {} - self.info = gtk.VBox() - self.vbox.pack_start(self.info, expand=False) + self.info = Gtk.VBox() + self.vbox.pack_start(self.info, expand=False, fill=True, padding=0) if CONFIG['client.check_version']: common.check_version(self.info) GLib.timeout_add_seconds( int(CONFIG['download.frequency']), common.check_version, self.info) - self.pane = gtk.HPaned() - self.vbox.pack_start(self.pane, True, True) + self.pane = Gtk.HPaned() + self.vbox.pack_start(self.pane, expand=True, fill=True, padding=0) self.pane.set_position(int(CONFIG['menu.pane'])) self.menu_screen = None - self.menu = gtk.VBox() + self.menu = Gtk.VBox() self.menu.set_vexpand(True) self.pane.add1(self.menu) - self.notebook = gtk.Notebook() + self.notebook = Gtk.Notebook() self.notebook.popup_enable() self.notebook.set_scrollable(True) self.notebook.connect_after('switch-page', self._sig_page_changt) @@ -308,15 +311,15 @@ class Main(Gtk.Application): def set_global_search(self): self.global_search_entry = Gtk.Entry.new() self.global_search_entry.set_width_chars(20) - global_search_completion = gtk.EntryCompletion() + global_search_completion = Gtk.EntryCompletion() global_search_completion.set_match_func(lambda *a: True) - global_search_completion.set_model(gtk.ListStore( - gtk.gdk.Pixbuf, str, str, int, str)) - pixbuf_cell = gtk.CellRendererPixbuf() - global_search_completion.pack_start(pixbuf_cell, False) + global_search_completion.set_model( + Gtk.ListStore(GdkPixbuf.Pixbuf, str, str, int, str)) + pixbuf_cell = Gtk.CellRendererPixbuf() + global_search_completion.pack_start(pixbuf_cell, expand=True) global_search_completion.add_attribute(pixbuf_cell, 'pixbuf', 0) - text_cell = gtk.CellRendererText() - global_search_completion.pack_start(text_cell) + text_cell = Gtk.CellRendererText() + global_search_completion.pack_start(text_cell, expand=True) global_search_completion.add_attribute(text_cell, "markup", 1) global_search_completion.props.popup_set_width = True self.global_search_entry.set_completion(global_search_completion) @@ -369,7 +372,7 @@ class Main(Gtk.Application): if icon: text = common.to_xml(record_name) pixbuf = common.IconFactory.get_pixbuf( - icon, gtk.ICON_SIZE_BUTTON) + icon, Gtk.IconSize.BUTTON) else: text = '%s:\n %s' % ( common.to_xml(model_name), @@ -388,7 +391,7 @@ class Main(Gtk.Application): def changed(widget): search_text = widget.get_text() - gobject.timeout_add(300, update, widget, search_text) + GLib.timeout_add(300, update, widget, search_text) def activate(widget): def message(): @@ -433,9 +436,9 @@ class Main(Gtk.Application): return True def _action_favorite(widget, id_): - event = gtk.get_current_event() - allow_similar = (event.state & gtk.gdk.MOD1_MASK or - event.state & gtk.gdk.SHIFT_MASK) + event = Gtk.get_current_event() + allow_similar = (event.state & Gdk.ModifierType.MOD1_MASK + or event.state & Gdk.ModifierType.SHIFT_MASK) with Window(allow_similar=allow_similar): # ids is not defined to prevent to add suffix Action.exec_keyword('tree_open', { @@ -454,16 +457,11 @@ class Main(Gtk.Application): except Exception: return False for id_, name, icon in favorites: - if icon: - menuitem = gtk.ImageMenuItem(name) - menuitem.set_image( - common.IconFactory.get_image(icon, gtk.ICON_SIZE_MENU)) - else: - menuitem = gtk.MenuItem(name) + menuitem = Gtk.MenuItem(label=name) menuitem.connect('activate', _action_favorite, id_) self.menu_favorite.add(menuitem) - self.menu_favorite.add(gtk.SeparatorMenuItem()) - manage_favorites = gtk.MenuItem(_("Manage..."), + self.menu_favorite.add(Gtk.SeparatorMenuItem()) + manage_favorites = Gtk.MenuItem(label=_("Manage..."), use_underline=True) manage_favorites.connect('activate', _manage_favorites) self.menu_favorite.add(manage_favorites) @@ -481,11 +479,11 @@ class Main(Gtk.Application): if option == 'default': barstyle = False elif option == 'both': - barstyle = gtk.TOOLBAR_BOTH + barstyle = Gtk.ToolbarStyle.BOTH elif option == 'text': - barstyle = gtk.TOOLBAR_TEXT + barstyle = Gtk.ToolbarStyle.TEXT elif option == 'icons': - barstyle = gtk.TOOLBAR_ICONS + barstyle = Gtk.ToolbarStyle.ICONS for page_idx in range(self.notebook.get_n_pages()): page = self.get_page(page_idx) page.toolbar.set_style(barstyle) @@ -495,7 +493,7 @@ class Main(Gtk.Application): Limit().run() def edit_email(self): - from tryton.gui.window.email import Email + from tryton.gui.window.email_ import Email Email().run() def win_next(self): @@ -745,18 +743,19 @@ class Main(Gtk.Application): screen.switch_view(view_type=screen.current_view.view_type) self.menu.pack_start( - screen.screen_container.alternate_viewport, True, True) + screen.screen_container.alternate_viewport, + expand=True, fill=True, padding=0) treeview = screen.current_view.treeview treeview.set_headers_visible(False) # Favorite column - column = gtk.TreeViewColumn() + column = Gtk.TreeViewColumn() column.name = None column._type = None favorite_renderer = CellRendererClickablePixbuf() column.pack_start(favorite_renderer, expand=False) - def favorite_setter(column, cell, store, iter_): + def favorite_setter(column, cell, store, iter_, user_data=None): menu = store.get_value(iter_, 0) favorite = menu.value.get('favorite') if favorite: @@ -767,7 +766,7 @@ class Main(Gtk.Application): icon = None if icon: pixbuf = common.IconFactory.get_pixbuf( - icon, gtk.ICON_SIZE_MENU) + icon, Gtk.IconSize.MENU) else: pixbuf = None cell.set_property('pixbuf', pixbuf) @@ -777,11 +776,11 @@ class Main(Gtk.Application): if treeview.props.window: self.toggle_favorite(renderer, path, treeview) favorite_renderer.connect('clicked', - lambda *a: gobject.idle_add(toggle_favorite, *a), treeview) + lambda *a: GLib.idle_add(toggle_favorite, *a), treeview) # Unset fixed height mode to add column treeview.set_fixed_height_mode(False) treeview.set_property( - 'enable-grid-lines', gtk.TREE_VIEW_GRID_LINES_NONE) + 'enable-grid-lines', Gtk.TreeViewGridLines.NONE) treeview.append_column(column) screen.search_filter() @@ -828,34 +827,34 @@ class Main(Gtk.Application): page_id = -1 self.previous_pages[page] = previous_widget self.pages.append(page) - hbox = gtk.HBox(spacing=3) + hbox = Gtk.HBox(spacing=3) if page.icon: hbox.pack_start( common.IconFactory.get_image( - page.icon, gtk.ICON_SIZE_SMALL_TOOLBAR), - expand=False, fill=False) + page.icon, Gtk.IconSize.SMALL_TOOLBAR), + expand=False, fill=False, padding=0) name = page.name - label = gtk.Label(common.ellipsize(name, 20)) + label = Gtk.Label( + label=common.ellipsize(name, 20), + halign=Gtk.Align.START) self.tooltips.set_tip(label, page.name) self.tooltips.enable() - label.set_alignment(0.0, 0.5) - hbox.pack_start(label, expand=True, fill=True) + hbox.pack_start(label, expand=True, fill=True, padding=0) - button = gtk.Button() - button.set_relief(gtk.RELIEF_NONE) + button = Gtk.Button() + button.set_relief(Gtk.ReliefStyle.NONE) button.set_can_focus(False) button.add(common.IconFactory.get_image( - 'tryton-close', gtk.ICON_SIZE_MENU)) + 'tryton-close', Gtk.IconSize.MENU)) self.tooltips.set_tip(button, _('Close Tab')) button.connect('clicked', self._sig_remove_book, page.widget) - hbox.pack_start(button, expand=False, fill=False) - x, y = gtk.icon_size_lookup_for_settings(button.get_settings(), - gtk.ICON_SIZE_MENU)[-2:] - button.set_size_request(x, y) + hbox.pack_start(button, expand=False, fill=False, padding=0) + size = Gtk.IconSize.lookup(Gtk.IconSize.MENU) + button.set_size_request(size.width, size.height) hbox.show_all() - label_menu = gtk.Label(page.name) - label_menu.set_alignment(0.0, 0.5) + label_menu = Gtk.Label( + label=page.name, halign=Gtk.Align.START) self.notebook.insert_page_menu(page.widget, hbox, label_menu, page_id) self.notebook.set_tab_reorderable(page.widget, True) self.notebook.set_current_page(page_id) @@ -937,9 +936,9 @@ class Main(Gtk.Application): def set_cursor(): if self.current_page == self.notebook.get_current_page(): current_form.set_cursor() - # Using idle_add because the gtk.TreeView grabs the focus at the + # Using idle_add because the Gtk.TreeView grabs the focus at the # end of the event - gobject.idle_add(set_cursor) + GLib.idle_add(set_cursor) for dialog in current_form.dialogs: dialog.show() @@ -1067,10 +1066,9 @@ class Main(Gtk.Application): def open_url(self, url): def idle_open_url(): - with gtk.gdk.lock: - self._open_url(url) - return False - gobject.idle_add(idle_open_url) + self._open_url(url) + return False + GLib.idle_add(idle_open_url) def show_notification(self, title, msg, priority=1): notification = Gio.Notification.new(title) diff --git a/tryton/gui/window/dblogin.py b/tryton/gui/window/dblogin.py index 4eec8e2ea5..21053bd242 100644 --- a/tryton/gui/window/dblogin.py +++ b/tryton/gui/window/dblogin.py @@ -2,14 +2,12 @@ # this repository contains the full copyright notices and license terms. import configparser -import gtk -import gobject import os import gettext import threading import logging -from gi.repository import Gtk, Gdk +from gi.repository import GLib, GObject, Gtk from tryton import __version__ import tryton.common as common @@ -32,112 +30,115 @@ class DBListEditor(object): # GTK Stuffs self.parent = parent - self.dialog = gtk.Dialog(title=_('Profile Editor'), parent=parent, - flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + self.dialog = Gtk.Dialog( + title=_('Profile Editor'), transient_for=parent, + modal=True, destroy_with_parent=True) self.ok_button = self.dialog.add_button( - set_underline(_("Close")), gtk.RESPONSE_CLOSE) - self.dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT) + set_underline(_("Close")), Gtk.ResponseType.CLOSE) + self.dialog.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self.dialog.set_icon(TRYTON_ICON) tooltips = common.Tooltips() - hpaned = gtk.HPaned() - vbox_profiles = gtk.VBox(homogeneous=False, spacing=6) - self.cell = gtk.CellRendererText() + hpaned = Gtk.HPaned() + vbox_profiles = Gtk.VBox(homogeneous=False, spacing=6) + self.cell = Gtk.CellRendererText() self.cell.set_property('editable', True) self.cell.connect('editing-started', self.edit_started) - self.profile_tree = gtk.TreeView() + self.profile_tree = Gtk.TreeView() self.profile_tree.set_model(profile_store) self.profile_tree.insert_column_with_attributes(-1, _('Profile'), self.cell, text=0) self.profile_tree.connect('cursor-changed', self.profile_selected) - scroll = gtk.ScrolledWindow() - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + scroll = Gtk.ScrolledWindow() + scroll.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) scroll.add(self.profile_tree) - self.add_button = gtk.Button() + self.add_button = Gtk.Button() self.add_button.set_image(common.IconFactory.get_image( - 'tryton-add', gtk.ICON_SIZE_BUTTON)) + 'tryton-add', Gtk.IconSize.BUTTON)) tooltips.set_tip(self.add_button, _("Add new profile")) self.add_button.connect('clicked', self.profile_create) - self.remove_button = gtk.Button() + self.remove_button = Gtk.Button() self.remove_button.set_image(common.IconFactory.get_image( - 'tryton-remove', gtk.ICON_SIZE_BUTTON)) + 'tryton-remove', Gtk.IconSize.BUTTON)) tooltips.set_tip(self.remove_button, _("Remove selected profile")) self.remove_button.get_style_context().add_class( Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION) self.remove_button.connect('clicked', self.profile_delete) bbox = Gtk.ButtonBox() - bbox.pack_start(self.remove_button) - bbox.pack_start(self.add_button) - vbox_profiles.pack_start(scroll, expand=True, fill=True) - vbox_profiles.pack_start(bbox, expand=False, fill=True) + bbox.pack_start(self.remove_button, expand=True, fill=True, padding=0) + bbox.pack_start(self.add_button, expand=True, fill=True, padding=0) + vbox_profiles.pack_start(scroll, expand=True, fill=True, padding=0) + vbox_profiles.pack_start(bbox, expand=False, fill=True, padding=0) hpaned.add1(vbox_profiles) - table = gtk.Table(4, 2, homogeneous=False) + table = Gtk.Table(n_rows=4, n_columns=2, homogeneous=False) table.set_row_spacings(3) table.set_col_spacings(3) - host = gtk.Label(set_underline(_('Host:'))) - host.set_use_underline(True) - host.set_alignment(1, 0.5) - host.set_padding(3, 3) - self.host_entry = gtk.Entry() + host = Gtk.Label( + label=set_underline(_('Host:')), + use_underline=True, halign=Gtk.Align.END) + self.host_entry = Gtk.Entry() self.host_entry.connect('focus-out-event', self.display_dbwidget) self.host_entry.connect('changed', self.update_profiles, 'host') self.host_entry.set_activates_default(True) host.set_mnemonic_widget(self.host_entry) - table.attach(host, 0, 1, 1, 2, yoptions=False, xoptions=gtk.FILL) + table.attach( + host, 0, 1, 1, 2, yoptions=False, xoptions=Gtk.AttachOptions.FILL) table.attach(self.host_entry, 1, 2, 1, 2, yoptions=False) - database = gtk.Label(set_underline(_('Database:'))) - database.set_use_underline(True) - database.set_alignment(1, 0.5) - database.set_padding(3, 3) - self.database_entry = gtk.Entry() + database = Gtk.Label( + label=set_underline(_('Database:')), + use_underline=True, halign=Gtk.Align.END) + self.database_entry = Gtk.Entry() self.database_entry.connect('changed', self.dbentry_changed) self.database_entry.connect('changed', self.update_profiles, 'database') self.database_entry.set_activates_default(True) - self.database_label = gtk.Label() + self.database_label = Gtk.Label(valign=Gtk.Align.START) self.database_label.set_use_markup(True) - self.database_label.set_alignment(0, 0.5) - self.database_combo = gtk.ComboBox() - dbstore = gtk.ListStore(gobject.TYPE_STRING) - cell = gtk.CellRendererText() - self.database_combo.pack_start(cell, True) - self.database_combo.add_attribute(cell, 'text', 0) - self.database_combo.set_model(dbstore) + self.database_combo = Gtk.ComboBoxText() self.database_combo.connect('changed', self.dbcombo_changed) - self.database_progressbar = gtk.ProgressBar() + self.database_progressbar = Gtk.ProgressBar() self.database_progressbar.set_text(_('Fetching databases list')) - db_box = gtk.VBox(homogeneous=True) - db_box.pack_start(self.database_entry) - db_box.pack_start(self.database_combo) - db_box.pack_start(self.database_label) - db_box.pack_start(self.database_progressbar) + db_box = Gtk.VBox(homogeneous=True) + db_box.pack_start( + self.database_entry, expand=True, fill=True, padding=0) + db_box.pack_start( + self.database_combo, expand=True, fill=True, padding=0) + db_box.pack_start( + self.database_label, expand=True, fill=True, padding=0) + db_box.pack_start( + self.database_progressbar, expand=True, fill=True, padding=0) # Compute size_request of box in order to prevent "form jumping" width, height = 0, 0 for child in db_box.get_children(): - cwidth, cheight = child.size_request() - width, height = max(width, cwidth), max(height, cheight) + request = child.get_preferred_size()[0] + width = max(width, request.width) + height = max(height, request.height) db_box.set_size_request(width, height) - table.attach(database, 0, 1, 2, 3, yoptions=False, xoptions=gtk.FILL) + table.attach( + database, 0, 1, 2, 3, + yoptions=False, xoptions=Gtk.AttachOptions.FILL) table.attach(db_box, 1, 2, 2, 3, yoptions=False) - username = gtk.Label(set_underline(_('Username:'))) - username.set_use_underline(True) - username.set_alignment(1, 0.5) - username.set_padding(3, 3) - self.username_entry = gtk.Entry() + username = Gtk.Label( + label=set_underline(_('Username:')), + use_underline=True, halign=Gtk.Align.END) + self.username_entry = Gtk.Entry() self.username_entry.connect('changed', self.update_profiles, 'username') username.set_mnemonic_widget(self.username_entry) self.username_entry.set_activates_default(True) - table.attach(username, 0, 1, 3, 4, yoptions=False, xoptions=gtk.FILL) + table.attach( + username, 0, 1, 3, 4, + yoptions=False, xoptions=Gtk.AttachOptions.FILL) table.attach(self.username_entry, 1, 2, 3, 4, yoptions=False) hpaned.add2(table) hpaned.set_position(250) - self.dialog.vbox.pack_start(hpaned) + self.dialog.vbox.pack_start(hpaned, expand=True, fill=True, padding=0) self.dialog.set_default_size(640, 350) - self.dialog.set_default_response(gtk.RESPONSE_CLOSE) + self.dialog.set_default_response(Gtk.ResponseType.CLOSE) self.dialog.connect('close', lambda *a: False) self.dialog.connect('response', self.response) @@ -228,7 +229,7 @@ class DBListEditor(object): self.display_dbwidget(None, None) def edit_started(self, renderer, editable, path): - if isinstance(editable, gtk.Entry): + if isinstance(editable, Gtk.Entry): editable.connect('focus-out-event', self.edit_profilename, renderer, path) @@ -291,7 +292,7 @@ class DBListEditor(object): self.dbs_updated = threading.Event() threading.Thread(target=self.refresh_databases_start, args=(host, port)).start() - gobject.timeout_add(100, self.refresh_databases_end, host, port) + GLib.timeout_add(100, self.refresh_databases_end, host, port) def refresh_databases_start(self, host, port): dbs = None @@ -320,11 +321,10 @@ class DBListEditor(object): self.database_label.set_label('%s' % label) self.database_label.show() else: - liststore = self.database_combo.get_model() - liststore.clear() + self.database_combo.remove_all() index = -1 for db_num, db_name in enumerate(dbs): - liststore.append([db_name]) + self.database_combo.append_text(db_name) if self.current_database and db_name == self.current_database: index = db_num if index == -1: @@ -387,116 +387,112 @@ class DBListEditor(object): try: int(new_value) except ValueError: - entry.stop_emission('insert-text') + entry.stop_emission_by_name('insert-text') class DBLogin(object): def __init__(self): # Fake windows to avoid warning about Dialog without transient - self._window = gtk.Window() - self.dialog = gtk.Dialog( - title="Tryton - " + _('Login'), flags=gtk.DIALOG_MODAL) + self._window = Gtk.Window() + self.dialog = Gtk.Dialog(title="Tryton - " + _('Login'), modal=True) self.dialog.set_transient_for(self._window) self.dialog.set_icon(TRYTON_ICON) - self.dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS) + self.dialog.set_position(Gtk.WindowPosition.CENTER_ALWAYS) self.dialog.set_resizable(False) tooltips = common.Tooltips() - button_cancel = gtk.Button(_('_Cancel'), use_underline=True) + button_cancel = Gtk.Button(label=_('_Cancel'), use_underline=True) tooltips.set_tip(button_cancel, _('Cancel connection to the Tryton server')) - self.dialog.add_action_widget(button_cancel, gtk.RESPONSE_CANCEL) - self.button_connect = gtk.Button(_('C_onnect'), use_underline=True) + self.dialog.add_action_widget(button_cancel, Gtk.ResponseType.CANCEL) + self.button_connect = Gtk.Button( + label=_('C_onnect'), use_underline=True) self.button_connect.get_style_context().add_class( Gtk.STYLE_CLASS_SUGGESTED_ACTION) self.button_connect.set_can_default(True) tooltips.set_tip(self.button_connect, _('Connect the Tryton server')) - self.dialog.add_action_widget(self.button_connect, gtk.RESPONSE_OK) - self.dialog.set_default_response(gtk.RESPONSE_OK) - alignment = gtk.Alignment(yalign=0, yscale=0, xscale=1) - self.table_main = gtk.Table(3, 3, False) + self.dialog.add_action_widget(self.button_connect, Gtk.ResponseType.OK) + self.dialog.set_default_response(Gtk.ResponseType.OK) + alignment = Gtk.Alignment(yalign=0, yscale=0, xscale=1) + self.table_main = Gtk.Table(n_rows=3, n_columns=3, homogeneous=False) self.table_main.set_border_width(0) self.table_main.set_row_spacings(3) self.table_main.set_col_spacings(3) alignment.add(self.table_main) - self.dialog.vbox.pack_start(alignment, True, True, 0) + self.dialog.vbox.pack_start( + alignment, expand=True, fill=True, padding=0) - image = gtk.Image() + image = Gtk.Image() image.set_from_file(os.path.join(PIXMAPS_DIR, 'tryton.png')) - image.set_alignment(0.5, 1) + image.set_valign(Gtk.Align.START) overlay = Gtk.Overlay() overlay.add(image) - label = Gtk.Label(__version__) + label = Gtk.Label( + label='%s' % __version__, + use_markup=True) label.props.halign = Gtk.Align.END label.props.valign = Gtk.Align.START label.props.margin_right = 10 label.props.margin_top = 5 - label.override_color( - Gtk.StateFlags.NORMAL, Gdk.RGBA(1, 1, 1, 1)) overlay.add_overlay(label) self.table_main.attach(overlay, 0, 3, 0, 1, ypadding=2) - self.profile_store = gtk.ListStore(gobject.TYPE_STRING, - gobject.TYPE_BOOLEAN) - self.combo_profile = gtk.ComboBox() - cell = gtk.CellRendererText() - self.combo_profile.pack_start(cell, True) + self.profile_store = Gtk.ListStore( + GObject.TYPE_STRING, GObject.TYPE_BOOLEAN) + self.combo_profile = Gtk.ComboBox() + cell = Gtk.CellRendererText() + self.combo_profile.pack_start(cell, expand=True) self.combo_profile.add_attribute(cell, 'text', 0) self.combo_profile.add_attribute(cell, 'sensitive', 1) self.combo_profile.set_model(self.profile_store) self.combo_profile.connect('changed', self.profile_changed) - self.profile_label = gtk.Label(set_underline(_('Profile:'))) - self.profile_label.set_use_underline(True) - self.profile_label.set_justify(gtk.JUSTIFY_RIGHT) - self.profile_label.set_alignment(1, 0.5) - self.profile_label.set_padding(3, 3) + self.profile_label = Gtk.Label( + label=set_underline(_('Profile:')), + use_underline=True, halign=Gtk.Align.END) self.profile_label.set_mnemonic_widget(self.combo_profile) - self.profile_button = gtk.Button(set_underline(_('Manage...')), - use_underline=True) + self.profile_button = Gtk.Button( + label=set_underline(_('Manage...')), use_underline=True) self.profile_button.connect('clicked', self.profile_manage) - self.table_main.attach(self.profile_label, 0, 1, 1, 2, - xoptions=gtk.FILL) + self.table_main.attach( + self.profile_label, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL) self.table_main.attach(self.combo_profile, 1, 2, 1, 2) - self.table_main.attach(self.profile_button, 2, 3, 1, 2, - xoptions=gtk.FILL) - self.expander = gtk.Expander() + self.table_main.attach( + self.profile_button, 2, 3, 1, 2, xoptions=Gtk.AttachOptions.FILL) + self.expander = Gtk.Expander() self.expander.set_label(_('Host / Database information')) self.expander.connect('notify::expanded', self.expand_hostspec) self.table_main.attach(self.expander, 0, 3, 3, 4) - self.label_host = gtk.Label(set_underline(_('Host:'))) - self.label_host.set_use_underline(True) - self.label_host.set_justify(gtk.JUSTIFY_RIGHT) - self.label_host.set_alignment(1, 0.5) - self.label_host.set_padding(3, 3) - self.entry_host = gtk.Entry() + self.label_host = Gtk.Label( + label=set_underline(_('Host:')), + use_underline=True, halign=Gtk.Align.END) + self.entry_host = Gtk.Entry() self.entry_host.connect_after('focus-out-event', self.clear_profile_combo) self.entry_host.set_activates_default(True) self.label_host.set_mnemonic_widget(self.entry_host) - self.table_main.attach(self.label_host, 0, 1, 4, 5, xoptions=gtk.FILL) + self.table_main.attach( + self.label_host, 0, 1, 4, 5, xoptions=Gtk.AttachOptions.FILL) self.table_main.attach(self.entry_host, 1, 3, 4, 5) - self.label_database = gtk.Label(set_underline(_('Database:'))) - self.label_database.set_use_underline(True) - self.label_database.set_justify(gtk.JUSTIFY_RIGHT) - self.label_database.set_alignment(1, 0.5) - self.label_database.set_padding(3, 3) - self.entry_database = gtk.Entry() + self.label_database = Gtk.Label( + label=set_underline(_('Database:')), + use_underline=True, halign=Gtk.Align.END) + self.entry_database = Gtk.Entry() self.entry_database.connect_after('focus-out-event', self.clear_profile_combo) self.entry_database.set_activates_default(True) self.label_database.set_mnemonic_widget(self.entry_database) - self.table_main.attach(self.label_database, 0, 1, 5, 6, - xoptions=gtk.FILL) + self.table_main.attach( + self.label_database, 0, 1, 5, 6, xoptions=Gtk.AttachOptions.FILL) self.table_main.attach(self.entry_database, 1, 3, 5, 6) - self.entry_login = gtk.Entry() + self.entry_login = Gtk.Entry() self.entry_login.set_activates_default(True) self.table_main.attach(self.entry_login, 1, 3, 6, 7) - label_username = gtk.Label(set_underline(_("User name:"))) - label_username.set_use_underline(True) - label_username.set_alignment(1, 0.5) - label_username.set_padding(3, 3) + label_username = Gtk.Label( + label=set_underline(_("User name:")), + use_underline=True, halign=Gtk.Align.END, margin=3) label_username.set_mnemonic_widget(self.entry_login) - self.table_main.attach(label_username, 0, 1, 6, 7, xoptions=gtk.FILL) + self.table_main.attach( + label_username, 0, 1, 6, 7, xoptions=Gtk.AttachOptions.FILL) # Profile information self.profile_cfg = os.path.join(get_config_dir(), 'profiles.cfg') @@ -620,8 +616,6 @@ class DBLogin(object): self.entry_login.grab_focus() - # Reshow dialog for gtk-quarks - self.dialog.reshow_with_initial_size() self.expander.set_expanded(CONFIG['login.expanded']) # The previous action did not called expand_hostspec self.expand_hostspec(self.expander) @@ -629,7 +623,7 @@ class DBLogin(object): response, result = None, ('', '', '', '') while not all(result): response = self.dialog.run() - if response != gtk.RESPONSE_OK: + if response != Gtk.ResponseType.OK: break self.clear_profile_combo() active_profile = self.combo_profile.get_active() @@ -663,4 +657,4 @@ class DBLogin(object): self.dialog.destroy() self._window.destroy() - return response == gtk.RESPONSE_OK + return response == Gtk.ResponseType.OK diff --git a/tryton/gui/window/email.py b/tryton/gui/window/email.py deleted file mode 100644 index 1c72ba6c21..0000000000 --- a/tryton/gui/window/email.py +++ /dev/null @@ -1,109 +0,0 @@ -# This file is part of Tryton. The COPYRIGHT file at the top level of -# this repository contains the full copyright notices and license terms. - -import gtk -import gettext - -from tryton.common import get_toplevel_window, IconFactory -from tryton.common.underline import set_underline -from tryton.config import TRYTON_ICON, CONFIG -from tryton.gui import Main - -_ = gettext.gettext - - -class Email(object): - - def __init__(self): - self.parent = get_toplevel_window() - self.win = gtk.Dialog(_('Email'), self.parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) - Main().add_window(self.win) - cancel_button = self.win.add_button( - set_underline(_("Cancel")), gtk.RESPONSE_CANCEL) - cancel_button.set_image(IconFactory.get_image( - 'tryton-cancel', gtk.ICON_SIZE_BUTTON)) - cancel_button.set_always_show_image(True) - ok_button = self.win.add_button( - set_underline(_("OK")), gtk.RESPONSE_OK) - ok_button.set_image(IconFactory.get_image( - 'tryton-ok', gtk.ICON_SIZE_BUTTON)) - ok_button.set_always_show_image(True) - self.win.set_default_response(gtk.RESPONSE_OK) - self.win.set_icon(TRYTON_ICON) - self.win.vbox.set_spacing(3) - self.win.vbox.pack_start(gtk.Label( - _('Email Program Settings')), expand=False, fill=True) - self.win.vbox.pack_start(gtk.HSeparator()) - hbox = gtk.HBox(spacing=3) - label = gtk.Label(_('Command Line:')) - hbox.pack_start(label, expand=True, fill=True) - self.entry = gtk.Entry() - self.entry.set_property('activates_default', True) - self.entry.set_width_chars(50) - self.entry.set_text(CONFIG['client.email']) - label.set_mnemonic_widget(label) - hbox.pack_start(self.entry, expand=True, fill=True) - self.win.vbox.pack_start(hbox, expand=True, fill=True) - - label = gtk.Label(_('Legend of Available Placeholders:')) - label.set_alignment(0.0, 0.5) - label.set_padding(0, 10) - self.win.vbox.pack_start(label, expand=False, fill=True) - - hbox = gtk.HBox(spacing=3) - vboxl = gtk.VBox(homogeneous=True, spacing=3) - label = gtk.Label(_('To:')) - label.set_alignment(0, 0) - label.set_padding(10, 0) - vboxl.pack_start(label, expand=False, fill=False) - label = gtk.Label(_('CC:')) - label.set_alignment(0, 0) - label.set_padding(10, 0) - vboxl.pack_start(label, expand=False, fill=False) - label = gtk.Label(_('Subject:')) - label.set_alignment(0, 0) - label.set_padding(10, 0) - vboxl.pack_start(label, expand=False, fill=False) - label = gtk.Label(_('Body:')) - label.set_alignment(0, 0) - label.set_padding(10, 0) - vboxl.pack_start(label, expand=False, fill=False) - label = gtk.Label(_('Attachment:')) - label.set_alignment(0, 0) - label.set_padding(10, 0) - vboxl.pack_start(label, expand=False, fill=False) - - vboxr = gtk.VBox(homogeneous=True, spacing=3) - label = gtk.Label(' ${to}') - label.set_alignment(0, 0) - vboxr.pack_start(label, expand=False, fill=False) - label = gtk.Label(' ${cc}') - label.set_alignment(0, 0) - vboxr.pack_start(label, expand=False, fill=False) - label = gtk.Label(' ${subject}') - label.set_alignment(0, 0) - vboxr.pack_start(label, expand=False, fill=False) - label = gtk.Label(' ${body}') - label.set_alignment(0, 0) - vboxr.pack_start(label, expand=False, fill=False) - label = gtk.Label(' ${attachment}') - label.set_alignment(0, 0) - vboxr.pack_start(label, expand=False, fill=False) - - hbox.pack_start(vboxl, expand=False, fill=False) - hbox.pack_start(vboxr, expand=False, fill=False) - - self.win.vbox.pack_start(hbox, expand=True, fill=True) - - self.win.show_all() - - def run(self): - "Run the window" - res = self.win.run() - if res == gtk.RESPONSE_OK: - CONFIG['client.email'] = self.entry.get_text() - CONFIG.save() - self.parent.present() - self.win.destroy() - return res diff --git a/tryton/gui/window/email_.py b/tryton/gui/window/email_.py new file mode 100644 index 0000000000..27ed5ad780 --- /dev/null +++ b/tryton/gui/window/email_.py @@ -0,0 +1,97 @@ +# This file is part of Tryton. The COPYRIGHT file at the top level of +# this repository contains the full copyright notices and license terms. + +import gettext + +from gi.repository import Gtk + +from tryton.common import get_toplevel_window, IconFactory +from tryton.common.underline import set_underline +from tryton.config import TRYTON_ICON, CONFIG +from tryton.gui import Main + +_ = gettext.gettext + + +class Email(object): + + def __init__(self): + self.parent = get_toplevel_window() + self.win = Gtk.Dialog( + title=_('Email'), transient_for=self.parent, modal=True, + destroy_with_parent=True) + Main().add_window(self.win) + cancel_button = self.win.add_button( + set_underline(_("Cancel")), Gtk.ResponseType.CANCEL) + cancel_button.set_image( + IconFactory.get_image('tryton-cancel', Gtk.IconSize.BUTTON)) + cancel_button.set_always_show_image(True) + ok_button = self.win.add_button( + set_underline(_("OK")), Gtk.ResponseType.OK) + ok_button.set_image( + IconFactory.get_image('tryton-ok', Gtk.IconSize.BUTTON)) + ok_button.set_always_show_image(True) + self.win.set_default_response(Gtk.ResponseType.OK) + self.win.set_icon(TRYTON_ICON) + self.win.vbox.set_spacing(3) + self.win.vbox.pack_start(Gtk.Label( + _('Email Program Settings')), expand=False, fill=True, padding=0) + self.win.vbox.pack_start( + Gtk.HSeparator(), expand=True, fill=True, padding=0) + hbox = Gtk.HBox(spacing=3) + label = Gtk.Label(label=_('Command Line:')) + hbox.pack_start(label, expand=True, fill=True, padding=0) + self.entry = Gtk.Entry() + self.entry.set_property('activates_default', True) + self.entry.set_width_chars(50) + self.entry.set_text(CONFIG['client.email']) + label.set_mnemonic_widget(label) + hbox.pack_start(self.entry, expand=True, fill=True, padding=0) + self.win.vbox.pack_start(hbox, expand=True, fill=True, padding=0) + + label = Gtk.Label( + label=_('Legend of Available Placeholders:'), + halign=Gtk.Align.START, margin_top=10, margin_bottom=5) + self.win.vbox.pack_start(label, expand=False, fill=True, padding=0) + + hbox = Gtk.HBox(spacing=3) + vboxl = Gtk.VBox(homogeneous=True, spacing=3) + label = Gtk.Label(label=_('To:'), halign=Gtk.Align.START) + vboxl.pack_start(label, expand=False, fill=False, padding=0) + label = Gtk.Label(label=_('CC:'), halign=Gtk.Align.START) + vboxl.pack_start(label, expand=False, fill=False, padding=0) + label = Gtk.Label(label=_('Subject:'), halign=Gtk.Align.START) + vboxl.pack_start(label, expand=False, fill=False, padding=0) + label = Gtk.Label(label=_('Body:'), halign=Gtk.Align.START) + vboxl.pack_start(label, expand=False, fill=False, padding=0) + label = Gtk.Label(label=_('Attachment:'), halign=Gtk.Align.START) + vboxl.pack_start(label, expand=False, fill=False, padding=0) + + vboxr = Gtk.VBox(homogeneous=True, spacing=3) + label = Gtk.Label(label=' ${to}', halign=Gtk.Align.START) + vboxr.pack_start(label, expand=False, fill=False, padding=0) + label = Gtk.Label(label=' ${cc}', halign=Gtk.Align.START) + vboxr.pack_start(label, expand=False, fill=False, padding=0) + label = Gtk.Label(label=' ${subject}', halign=Gtk.Align.START) + vboxr.pack_start(label, expand=False, fill=False, padding=0) + label = Gtk.Label(label=' ${body}', halign=Gtk.Align.START) + vboxr.pack_start(label, expand=False, fill=False, padding=0) + label = Gtk.Label(label=' ${attachment}', halign=Gtk.Align.START) + vboxr.pack_start(label, expand=False, fill=False, padding=0) + + hbox.pack_start(vboxl, expand=False, fill=False, padding=0) + hbox.pack_start(vboxr, expand=False, fill=False, padding=0) + + self.win.vbox.pack_start(hbox, expand=True, fill=True, padding=0) + + self.win.show_all() + + def run(self): + "Run the window" + res = self.win.run() + if res == Gtk.ResponseType.OK: + CONFIG['client.email'] = self.entry.get_text() + CONFIG.save() + self.parent.present() + self.win.destroy() + return res diff --git a/tryton/gui/window/form.py b/tryton/gui/window/form.py index 1a70b29989..218e508d44 100644 --- a/tryton/gui/window/form.py +++ b/tryton/gui/window/form.py @@ -2,10 +2,8 @@ # this repository contains the full copyright notices and license terms. "Form" import gettext -import gtk -import gobject -from gi.repository import Gtk +from gi.repository import Gdk, GLib, Gtk from tryton.gui.window.view_form.screen import Screen from tryton.action import Action @@ -53,7 +51,7 @@ class Form(SignalEvent, TabContent): self._record_message) self.screen.signal_connect(self, 'record-modified', - lambda *a: gobject.idle_add(self._record_modified, *a)) + lambda *a: GLib.idle_add(self._record_modified, *a)) self.screen.signal_connect(self, 'record-saved', self._record_saved) self.screen.signal_connect(self, 'attachment-count', self._attachment_count) @@ -127,17 +125,14 @@ class Form(SignalEvent, TabContent): record = self.screen.current_record menu = button._menu = Gtk.Menu() for name, callback in Attachment.get_attachments(record): - item = Gtk.MenuItem() - item.set_label(name) + item = Gtk.MenuItem(label=name) item.connect('activate', activate, callback) menu.add(item) menu.add(Gtk.SeparatorMenuItem()) - add_item = Gtk.MenuItem() - add_item.set_label(_("Add...")) + add_item = Gtk.MenuItem(label=_("Add...")) add_item.connect('activate', add_file) menu.add(add_item) - manage_item = Gtk.MenuItem() - manage_item.set_label(_("Manage...")) + manage_item = Gtk.MenuItem(label=_("Manage...")) manage_item.connect('activate', window) menu.add(manage_item) menu.show_all() @@ -160,7 +155,7 @@ class Form(SignalEvent, TabContent): icon = 'tryton-attach' else: icon = 'tryton-attach' - image = common.IconFactory.get_image(icon, gtk.ICON_SIZE_LARGE_TOOLBAR) + image = common.IconFactory.get_image(icon, Gtk.IconSize.LARGE_TOOLBAR) image.show() self.buttons['attach'].set_icon_widget(image) record = self.screen.current_record @@ -186,9 +181,13 @@ class Form(SignalEvent, TabContent): label = _('Note(%d)') % signal_data self.buttons['note'].set_label(label) if signal_data: - self.buttons['note'].set_stock_id('tryton-note-hi') + # FIXME + icon = 'tryton-note' else: - self.buttons['note'].set_stock_id('tryton-note') + icon = 'tryton-note' + image = common.IconFactory.get_image(icon, Gtk.IconSize.LARGE_TOOLBAR) + image.show() + self.buttons['note'].set_icon_widget(image) record = self.screen.current_record if not record or record.id < 0: sensitive = False @@ -205,7 +204,7 @@ class Form(SignalEvent, TabContent): current_record = self.screen.current_record if not current_record or current_record.id < 0: self.message_info( - _('You have to select one record.'), gtk.MESSAGE_INFO) + _('You have to select one record.'), Gtk.MessageType.INFO) return False fields = [ @@ -281,7 +280,7 @@ class Form(SignalEvent, TabContent): else: label = common.ellipsize(self.name, 80) tooltip = self.name - self.title.set_label(label) + self.title.set_markup(label) tooltips.set_tip(self.title, tooltip) self.set_buttons_sensitive(revision) @@ -315,9 +314,10 @@ class Form(SignalEvent, TabContent): msg = _('Are you sure to remove those records?') if sur(msg): if not self.screen.remove(delete=True, force_remove=True): - self.message_info(_('Records not removed.'), gtk.MESSAGE_ERROR) + self.message_info( + _('Records not removed.'), Gtk.MessageType.ERROR) else: - self.message_info(_('Records removed.'), gtk.MESSAGE_INFO) + self.message_info(_('Records removed.'), Gtk.MessageType.INFO) self.screen.count_tab_domain() def sig_import(self, widget=None): @@ -355,7 +355,7 @@ class Form(SignalEvent, TabContent): return if self.screen.copy(): self.message_info(_('Working now on the duplicated record(s).'), - gtk.MESSAGE_INFO) + Gtk.MessageType.INFO) self.screen.count_tab_domain() def sig_save(self, widget=None): @@ -366,11 +366,12 @@ class Form(SignalEvent, TabContent): or common.MODELACCESS[self.model]['create']): return if self.screen.save_current(): - self.message_info(_('Record saved.'), gtk.MESSAGE_INFO) + self.message_info(_('Record saved.'), Gtk.MessageType.INFO) self.screen.count_tab_domain() return True else: - self.message_info(self.screen.invalid_message(), gtk.MESSAGE_ERROR) + self.message_info( + self.screen.invalid_message(), Gtk.MessageType.ERROR) return False def sig_previous(self, widget=None): @@ -447,19 +448,20 @@ class Form(SignalEvent, TabContent): menu.popdown() return - def menu_position(menu, data): + def menu_position(menu, x, y, user_data): widget_allocation = widget.get_allocation() - if hasattr(widget.window, 'get_root_coords'): - x, y = widget.window.get_root_coords( - widget_allocation.x, widget_allocation.y) - else: - x, y = widget.window.get_origin() - x += widget_allocation.x - y += widget_allocation.y + x, y = widget.get_window().get_root_coords( + widget_allocation.x, widget_allocation.y) return (x, y + widget_allocation.height, False) menu.show_all() - menu.popup(None, None, menu_position, 0, gtk.get_current_event_time(), - None) + if hasattr(menu, 'popup_at_widget'): + menu.popup_at_widget( + widget, Gdk.Gravity.SOUTH_WEST, Gdk.Gravity.NORTH_WEST, + Gtk.get_current_event()) + else: + menu.popup( + None, None, menu_position, None, 0, + Gtk.get_current_event_time()) def _record_message(self, screen, signal_data): name = '_' @@ -542,10 +544,12 @@ class Form(SignalEvent, TabContent): gtktoolbar = super(Form, self).create_toolbar(toolbars) attach_btn = self.buttons['attach'] - attach_btn.drag_dest_set(gtk.DEST_DEFAULT_ALL, [ - gtk.TargetEntry.new('text/uri-list', 0, 0), - gtk.TargetEntry.new('text/plain', 0, 0), - ], gtk.gdk.ACTION_MOVE | gtk.gdk.ACTION_COPY) + attach_btn.drag_dest_set( + Gtk.DestDefaults.ALL, [ + Gtk.TargetEntry.new('text/uri-list', 0, 0), + Gtk.TargetEntry.new('text/plain', 0, 0), + ], + Gdk.DragAction.MOVE | Gdk.DragAction.COPY) attach_btn.connect('drag_data_received', self.attach_drag_data_received) @@ -565,10 +569,10 @@ class Form(SignalEvent, TabContent): ('print', 'print', _('Print'), _('Print report')), ): if action_type is not None: - tbutton = gtk.ToggleToolButton() + tbutton = Gtk.ToggleToolButton() tbutton.set_icon_widget(common.IconFactory.get_image( iconstock.get(special_action), - gtk.ICON_SIZE_LARGE_TOOLBAR)) + Gtk.IconSize.LARGE_TOOLBAR)) tbutton.set_label(action_name) tbutton._menu = self._create_popup_menu(tbutton, action_type, toolbars[action_type], special_action) @@ -579,21 +583,21 @@ class Form(SignalEvent, TabContent): tbutton._can_be_sensitive = bool( tbutton._menu.get_children()) else: - tbutton = gtk.SeparatorToolItem() + tbutton = Gtk.SeparatorToolItem() gtktoolbar.insert(tbutton, -1) - gtktoolbar.insert(gtk.SeparatorToolItem(), -1) + gtktoolbar.insert(Gtk.SeparatorToolItem(), -1) - url_button = gtk.ToggleToolButton() + url_button = Gtk.ToggleToolButton() url_button.set_icon_widget( common.IconFactory.get_image( - 'tryton-public', gtk.ICON_SIZE_LARGE_TOOLBAR)) + 'tryton-public', Gtk.IconSize.LARGE_TOOLBAR)) url_button.set_label(_('_Copy URL')) url_button.set_use_underline(True) self.tooltips.set_tip( url_button, _('Copy URL into clipboard')) - url_button._menu = url_menu = gtk.Menu() - url_menuitem = gtk.MenuItem() + url_button._menu = url_menu = Gtk.Menu() + url_menuitem = Gtk.MenuItem() url_menuitem.connect('activate', self.url_copy) url_menu.add(url_menuitem) url_menu.show_all() @@ -605,7 +609,7 @@ class Form(SignalEvent, TabContent): return gtktoolbar def _create_popup_menu(self, widget, keyword, actions, special_action): - menu = gtk.Menu() + menu = Gtk.Menu() menu.connect('deactivate', self._popup_menu_hide, widget) widget.connect('toggled', self._update_popup_menu, menu, keyword) @@ -615,7 +619,7 @@ class Form(SignalEvent, TabContent): new_action['direct_print'] = True elif special_action == 'email': new_action['email_print'] = True - menuitem = gtk.MenuItem(set_underline(action['name'])) + menuitem = Gtk.MenuItem(label=set_underline(action['name'])) menuitem.set_use_underline(True) menuitem.connect('activate', self._popup_menu_selected, widget, new_action, keyword) @@ -623,10 +627,10 @@ class Form(SignalEvent, TabContent): return menu def _popup_menu_selected(self, menuitem, togglebutton, action, keyword): - event = gtk.get_current_event() + event = Gtk.get_current_event() allow_similar = False - if (event.state & gtk.gdk.CONTROL_MASK - or event.state & gtk.gdk.MOD1_MASK): + if (event.state & Gdk.ModifierType.CONTROL_MASK + or event.state & Gdk.ModifierType.MOD1_MASK): allow_similar = True with Window(hide_current=True, allow_similar=allow_similar): self._action(action, keyword) @@ -638,21 +642,17 @@ class Form(SignalEvent, TabContent): def _update_popup_menu(self, tbutton, menu, keyword): for item in menu.get_children(): if (getattr(item, '_update_action', False) - or isinstance(item, gtk.SeparatorMenuItem)): + or isinstance(item, Gtk.SeparatorMenuItem)): menu.remove(item) buttons = [b for b in self.screen.get_buttons() if keyword == b.attrs.get('keyword', 'action')] if buttons and menu.get_children(): - menu.add(gtk.SeparatorMenuItem()) + menu.add(Gtk.SeparatorMenuItem()) for button in buttons: - menuitem = gtk.ImageMenuItem() - menuitem.set_label( - set_underline(button.attrs.get('string', _('Unknown')))) - menuitem.set_use_underline(True) - if button.attrs.get('icon'): - menuitem.set_image(common.IconFactory.get_image( - button.attrs['icon'], gtk.ICON_SIZE_MENU)) + menuitem = Gtk.MenuItem( + label=set_underline(button.attrs.get('string', _('Unknown'))), + use_underline=True) menuitem.connect('activate', lambda m, attrs: self.screen.button(attrs), button.attrs) menuitem._update_action = True @@ -671,9 +671,9 @@ class Form(SignalEvent, TabContent): kw_plugins.append((name, func)) if kw_plugins: - menu.add(gtk.SeparatorMenuItem()) + menu.add(Gtk.SeparatorMenuItem()) for name, func in kw_plugins: - menuitem = gtk.MenuItem(set_underline(name)) + menuitem = Gtk.MenuItem(label=set_underline(name)) menuitem.set_use_underline(True) menuitem.connect('activate', lambda m, func: func({ 'model': self.model, @@ -687,8 +687,11 @@ class Form(SignalEvent, TabContent): def url_copy(self, menuitem): url = self.screen.get_url(self.name) - for selection in [gtk.CLIPBOARD_PRIMARY, gtk.CLIPBOARD_CLIPBOARD]: - clipboard = gtk.clipboard_get(selection) + for selection in [ + Gdk.Atom.intern('PRIMARY', True), + Gdk.Atom.intern('CLIPBOARD', True), + ]: + clipboard = Gtk.Clipboard.get(selection) clipboard.set_text(url, -1) def url_set(self, button, menuitem): diff --git a/tryton/gui/window/infobar.py b/tryton/gui/window/infobar.py index 75598c8030..086e1b486b 100644 --- a/tryton/gui/window/infobar.py +++ b/tryton/gui/window/infobar.py @@ -11,7 +11,7 @@ class InfoBar(object): self.info_bar = Gtk.InfoBar() self.info_bar.get_content_area().pack_start( - self.info_label, False, False) + self.info_label, False, False, 0) self.info_bar.set_show_close_button(True) self.info_bar.connect('response', lambda i, r: i.hide()) diff --git a/tryton/gui/window/limit.py b/tryton/gui/window/limit.py index e317364970..a3a774f809 100644 --- a/tryton/gui/window/limit.py +++ b/tryton/gui/window/limit.py @@ -1,9 +1,10 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import sys -import gtk import gettext +from gi.repository import Gtk + from tryton.common import get_toplevel_window, IconFactory from tryton.common.underline import set_underline from tryton.config import TRYTON_ICON, CONFIG @@ -17,44 +18,49 @@ class Limit(object): def __init__(self): self.parent = get_toplevel_window() - self.win = gtk.Dialog(_('Limit'), self.parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + self.win = Gtk.Dialog( + title=_('Limit'), transient_for=self.parent, modal=True, + destroy_with_parent=True) Main().add_window(self.win) cancel_button = self.win.add_button( - set_underline(_("Cancel")), gtk.RESPONSE_CANCEL) + set_underline(_("Cancel")), Gtk.ResponseType.CANCEL) cancel_button.set_image(IconFactory.get_image( - 'tryton-cancel', gtk.ICON_SIZE_BUTTON)) + 'tryton-cancel', Gtk.IconSize.BUTTON)) cancel_button.set_always_show_image(True) ok_button = self.win.add_button( - set_underline(_("OK")), gtk.RESPONSE_OK) + set_underline(_("OK")), Gtk.ResponseType.OK) ok_button.set_image(IconFactory.get_image( - 'tryton-ok', gtk.ICON_SIZE_BUTTON)) + 'tryton-ok', Gtk.IconSize.BUTTON)) ok_button.set_always_show_image(True) - self.win.set_default_response(gtk.RESPONSE_OK) + self.win.set_default_response(Gtk.ResponseType.OK) self.win.set_icon(TRYTON_ICON) self.win.vbox.set_spacing(3) - self.win.vbox.pack_start(gtk.Label( - _('Search Limit Settings')), expand=False, fill=True) - self.win.vbox.pack_start(gtk.HSeparator()) - hbox = gtk.HBox(spacing=3) - label = gtk.Label(_('Limit:')) - hbox.pack_start(label, expand=True, fill=True) - adjustment = gtk.Adjustment(value=CONFIG['client.limit'], - lower=1, upper=sys.maxsize, step_incr=10, page_incr=100) - self.spin_limit = gtk.SpinButton() + self.win.vbox.pack_start(Gtk.Label( + label=_('Search Limit Settings')), + expand=False, fill=True, padding=0) + self.win.vbox.pack_start( + Gtk.HSeparator(), expand=True, fill=True, padding=0) + hbox = Gtk.HBox(spacing=3) + label = Gtk.Label(label=_('Limit:')) + hbox.pack_start(label, expand=True, fill=True, padding=0) + adjustment = Gtk.Adjustment( + value=CONFIG['client.limit'], + lower=1, upper=sys.maxsize, + step_incr=10, page_incr=100) + self.spin_limit = Gtk.SpinButton() self.spin_limit.configure(adjustment, climb_rate=1, digits=0) self.spin_limit.set_numeric(False) self.spin_limit.set_activates_default(True) label.set_mnemonic_widget(self.spin_limit) - hbox.pack_start(self.spin_limit, expand=True, fill=True) - self.win.vbox.pack_start(hbox, expand=True, fill=True) + hbox.pack_start(self.spin_limit, expand=True, fill=True, padding=0) + self.win.vbox.pack_start(hbox, expand=True, fill=True, padding=0) self.win.show_all() def run(self): 'Run the window' res = self.win.run() - if res == gtk.RESPONSE_OK: + if res == Gtk.ResponseType.OK: CONFIG['client.limit'] = self.spin_limit.get_value_as_int() CONFIG.save() self.parent.present() diff --git a/tryton/gui/window/preference.py b/tryton/gui/window/preference.py index 44e5c66183..5307787dbb 100644 --- a/tryton/gui/window/preference.py +++ b/tryton/gui/window/preference.py @@ -2,9 +2,10 @@ # this repository contains the full copyright notices and license terms. "Preference" import gettext -import gtk import copy +from gi.repository import Gdk, Gtk + import tryton.rpc as rpc from tryton.common import RPCExecute, RPCException, IconFactory from tryton.common.underline import set_underline @@ -22,29 +23,31 @@ class Preference(NoModal): def __init__(self, user, callback): NoModal.__init__(self) self.callback = callback - self.win = gtk.Dialog(_('Preferences'), self.parent, - gtk.DIALOG_DESTROY_WITH_PARENT) + self.win = Gtk.Dialog( + title=_('Preferences'), transient_for=self.parent, + destroy_with_parent=True) Main().add_window(self.win) - self.win.set_position(gtk.WIN_POS_CENTER_ON_PARENT) + self.win.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self.win.set_icon(TRYTON_ICON) - self.accel_group = gtk.AccelGroup() + self.accel_group = Gtk.AccelGroup() self.win.add_accel_group(self.accel_group) self.but_cancel = self.win.add_button( - set_underline(_("Cancel")), gtk.RESPONSE_CANCEL) - self.but_cancel.set_image(IconFactory.get_image( - 'tryton-cancel', gtk.ICON_SIZE_BUTTON)) + set_underline(_("Cancel")), Gtk.ResponseType.CANCEL) + self.but_cancel.set_image( + IconFactory.get_image('tryton-cancel', Gtk.IconSize.BUTTON)) self.but_cancel.set_always_show_image(True) self.but_ok = self.win.add_button( - set_underline(_("OK")), gtk.RESPONSE_OK) - self.but_ok.set_image(IconFactory.get_image( - 'tryton-ok', gtk.ICON_SIZE_BUTTON)) + set_underline(_("OK")), Gtk.ResponseType.OK) + self.but_ok.set_image( + IconFactory.get_image('tryton-ok', Gtk.IconSize.BUTTON)) self.but_ok.set_always_show_image(True) - self.but_ok.add_accelerator('clicked', self.accel_group, - gtk.keysyms.Return, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) + self.but_ok.add_accelerator( + 'clicked', self.accel_group, Gdk.KEY_Return, + Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE) - self.win.set_default_response(gtk.RESPONSE_OK) + self.win.set_default_response(Gtk.ResponseType.OK) self.win.connect('response', self.response) try: @@ -55,9 +58,9 @@ class Preference(NoModal): self.win = None return - title = gtk.Label(_('Edit User Preferences')) + title = Gtk.Label(label=_('Edit User Preferences')) title.show() - self.win.vbox.pack_start(title, expand=False, fill=True) + self.win.vbox.pack_start(title, expand=False, fill=True, padding=0) self.screen = Screen('res.user', mode=[]) # Reset readonly set automaticly by MODELACCESS self.screen.readonly = False @@ -81,7 +84,8 @@ class Preference(NoModal): self.screen.display(set_cursor=True) self.screen.widget.show() - self.win.vbox.pack_start(self.screen.widget) + self.win.vbox.pack_start( + self.screen.widget, expand=True, fill=True, padding=0) self.win.set_title(_('Preference')) self.win.set_default_size(*self.default_size()) @@ -90,7 +94,7 @@ class Preference(NoModal): self.win.show() def response(self, win, response_id): - if response_id == gtk.RESPONSE_OK: + if response_id == Gtk.ResponseType.OK: if self.screen.current_record.validate(): vals = copy.copy(self.screen.get()) try: diff --git a/tryton/gui/window/revision.py b/tryton/gui/window/revision.py index 639098f6d9..59d8dcb78f 100644 --- a/tryton/gui/window/revision.py +++ b/tryton/gui/window/revision.py @@ -1,8 +1,9 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk import gettext +from gi.repository import Gtk + from tryton.common import get_toplevel_window, IconFactory from tryton.common.datetime_ import date_parse from tryton.common.underline import set_underline @@ -17,31 +18,34 @@ class Revision(object): def __init__(self, revisions, revision=None, format_='%x %H:%M:%S.%f'): self.parent = get_toplevel_window() - self.win = gtk.Dialog(_('Revision'), self.parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + self.win = Gtk.Dialog( + title=_('Revision'), transient_for=self.parent, modal=True, + destroy_with_parent=True) Main().add_window(self.win) cancel_button = self.win.add_button( - set_underline(_("Cancel")), gtk.RESPONSE_CANCEL) + set_underline(_("Cancel")), Gtk.ResponseType.CANCEL) cancel_button.set_image(IconFactory.get_image( - 'tryton-cancel', gtk.ICON_SIZE_BUTTON)) + 'tryton-cancel', Gtk.IconSize.BUTTON)) cancel_button.set_always_show_image(True) ok_button = self.win.add_button( - set_underline(_("OK")), gtk.RESPONSE_OK) + set_underline(_("OK")), Gtk.ResponseType.OK) ok_button.set_image(IconFactory.get_image( - 'tryton-ok', gtk.ICON_SIZE_BUTTON)) + 'tryton-ok', Gtk.IconSize.BUTTON)) ok_button.set_always_show_image(True) - self.win.set_default_response(gtk.RESPONSE_OK) + self.win.set_default_response(Gtk.ResponseType.OK) self.win.set_icon(TRYTON_ICON) self.win.vbox.set_spacing(3) - self.win.vbox.pack_start(gtk.Label( - _('Select a revision')), expand=False, fill=True) - self.win.vbox.pack_start(gtk.HSeparator()) - hbox = gtk.HBox(spacing=3) - label = gtk.Label(_('Revision:')) - hbox.pack_start(label, expand=True, fill=True) - list_store = gtk.ListStore(str, str) + self.win.vbox.pack_start(Gtk.Label( + label=_('Select a revision')), + expand=False, fill=True, padding=0) + self.win.vbox.pack_start( + Gtk.HSeparator(), expand=True, fill=True, padding=0) + hbox = Gtk.HBox(spacing=3) + label = Gtk.Label(label=_('Revision:')) + hbox.pack_start(label, expand=True, fill=True, padding=0) + list_store = Gtk.ListStore(str, str) # Set model on instantiation to get the default cellrenderer as text - combobox = gtk.ComboBoxEntry(model=list_store) + combobox = Gtk.ComboBox(model=list_store, has_entry=True) self.entry = combobox.get_child() self.entry.connect('focus-out-event', self.focus_out) self.entry.connect('activate', self.activate) @@ -62,12 +66,12 @@ class Revision(object): if rev == revision: active = i combobox.set_active(active) - cell = gtk.CellRendererText() - combobox.pack_start(cell, True) + cell = Gtk.CellRendererText() + combobox.pack_start(cell, expand=True) combobox.add_attribute(cell, 'text', 1) - hbox.pack_start(combobox, expand=True, fill=True) + hbox.pack_start(combobox, expand=True, fill=True, padding=0) combobox.set_entry_text_column(0) - self.win.vbox.pack_start(hbox, expand=True, fill=True) + self.win.vbox.pack_start(hbox, expand=True, fill=True, padding=0) self.win.show_all() def focus_out(self, entry, event): @@ -107,7 +111,7 @@ class Revision(object): def run(self): response = self.win.run() revision = None - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: revision = self._value self.parent.present() self.win.destroy() diff --git a/tryton/gui/window/tabcontent.py b/tryton/gui/window/tabcontent.py index ca58f26c1d..f08b604404 100644 --- a/tryton/gui/window/tabcontent.py +++ b/tryton/gui/window/tabcontent.py @@ -2,12 +2,12 @@ # this repository contains the full copyright notices and license terms. import gettext -import gtk -import pango -from gi.repository import Gtk + +from gi.repository import Gtk, Pango import tryton.common as common from tryton.config import CONFIG +from tryton.common.widget_style import widget_class from tryton.gui import Main from .infobar import InfoBar @@ -173,7 +173,7 @@ class TabContent(InfoBar): self.tooltips = common.Tooltips() self.accel_group = Main().accel_group - self.widget = gtk.VBox(spacing=3) + self.widget = Gtk.VBox(spacing=3) self.widget.show() title_box = self.make_title_bar() @@ -181,34 +181,35 @@ class TabContent(InfoBar): self.toolbar = self.create_toolbar(self.get_toolbars()) self.toolbar.show_all() - self.widget.pack_start(self.toolbar, False, True) + self.widget.pack_start( + self.toolbar, expand=False, fill=True, padding=0) - viewport = gtk.Viewport() - viewport.set_shadow_type(gtk.SHADOW_NONE) + viewport = Gtk.Viewport() + viewport.set_shadow_type(Gtk.ShadowType.NONE) viewport.add(self.widget_get()) viewport.show() - self.scrolledwindow = gtk.ScrolledWindow() - self.scrolledwindow.set_shadow_type(gtk.SHADOW_NONE) - self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) + self.scrolledwindow = Gtk.ScrolledWindow() + self.scrolledwindow.set_shadow_type(Gtk.ShadowType.NONE) + self.scrolledwindow.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.scrolledwindow.add(viewport) self.scrolledwindow.show() - self.widget.pack_start(self.scrolledwindow) + self.widget.pack_start( + self.scrolledwindow, expand=True, fill=True, padding=0) self.create_info_bar() - self.widget.pack_start(self.info_bar, False, True) + self.widget.pack_start( + self.info_bar, expand=False, fill=True, padding=0) def make_title_bar(self): - self.title = title = gtk.Label() - title.modify_font(pango.FontDescription("bold 14")) - title.set_label(common.ellipsize(self.name, 80)) - title.set_padding(10, 4) - title.set_alignment(0.0, 0.5) + tooltips = common.Tooltips() + self.title = title = Gtk.Label( + label=common.ellipsize(self.name, 80), + halign=Gtk.Align.START, margin=5, + ellipsize=Pango.EllipsizeMode.END) + tooltips.set_tip(title, self.name) title.set_size_request(0, -1) # Allow overflow - title.set_max_width_chars(1) - title.set_ellipsize(pango.ELLIPSIZE_END) - title.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000")) title.show() menu = Gtk.MenuButton.new() @@ -216,34 +217,30 @@ class TabContent(InfoBar): menu.set_popup(self.set_menu_form()) menu.show() - self.status_label = gtk.Label() - self.status_label.set_padding(5, 4) - self.status_label.set_alignment(0.0, 0.5) + self.status_label = Gtk.Label( + margin=5, halign=Gtk.Align.END) + widget_class(self.status_label, 'status', True) self.status_label.show() - hbox = gtk.HBox() - hbox.pack_start(title, expand=True, fill=True) - hbox.pack_start(self.status_label, expand=False, fill=True) + hbox = Gtk.HBox() + hbox.pack_start(title, expand=True, fill=True, padding=0) + hbox.pack_start(self.status_label, expand=False, fill=True, padding=0) hbox.show() - frame = gtk.Frame() - frame.set_shadow_type(gtk.SHADOW_ETCHED_IN) + frame = Gtk.Frame() + frame.set_shadow_type(Gtk.ShadowType.ETCHED_IN) + widget_class(frame, 'window-title', True) frame.add(hbox) frame.show() - eb = gtk.EventBox() - eb.add(frame) - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#ffffff")) - eb.show() - - frame_menu = gtk.Frame() - frame_menu.set_shadow_type(gtk.SHADOW_ETCHED_IN) + frame_menu = Gtk.Frame() + frame_menu.set_shadow_type(Gtk.ShadowType.ETCHED_IN) frame_menu.add(menu) frame_menu.show() - title_box = gtk.HBox() - title_box.pack_start(frame_menu, expand=False, fill=True) - title_box.pack_start(eb, expand=True, fill=True) + title_box = Gtk.HBox() + title_box.pack_start(frame_menu, expand=False, fill=True, padding=0) + title_box.pack_start(frame, expand=True, fill=True, padding=0) title_box.show() return title_box @@ -255,27 +252,27 @@ class TabContent(InfoBar): if not callback: continue if item.toggle: - toolitem = gtk.ToggleToolButton() + toolitem = Gtk.ToggleToolButton() toolitem.connect('toggled', callback) else: - toolitem = gtk.ToolButton() + toolitem = Gtk.ToolButton() toolitem.connect('clicked', callback) toolitem.set_icon_widget( common.IconFactory.get_image( - item.icon_name, gtk.ICON_SIZE_LARGE_TOOLBAR)) + item.icon_name, Gtk.IconSize.LARGE_TOOLBAR)) toolitem.set_label(item.label) toolitem.set_use_underline(True) self.tooltips.set_tip(toolitem, item.tooltip) self.buttons[item.id] = toolitem elif not item and previous: - toolitem = gtk.SeparatorToolItem() + toolitem = Gtk.SeparatorToolItem() else: continue previous = item toolbar.insert(toolitem, -1) def set_menu_form(self): - menu_form = gtk.Menu() + menu_form = Gtk.Menu() menu_form.set_accel_group(self.accel_group) menu_form.set_accel_path('/Form') previous = None @@ -284,19 +281,15 @@ class TabContent(InfoBar): callback = getattr(self, 'sig_%s' % item.id, None) if not callback: continue - menuitem = gtk.ImageMenuItem(item.label, self.accel_group) - menuitem.set_use_underline(True) + menuitem = Gtk.MenuItem( + label=item.label, + use_underline=True) menuitem.connect('activate', callback) - - if item.icon_name: - menuitem.set_image( - common.IconFactory.get_image( - item.icon_name, gtk.ICON_SIZE_MENU)) if item.accel_path: menuitem.set_accel_path(item.accel_path) self.menu_buttons[item.id] = menuitem elif not item and previous: - menuitem = gtk.SeparatorMenuItem() + menuitem = Gtk.SeparatorMenuItem() else: continue previous = item @@ -306,16 +299,16 @@ class TabContent(InfoBar): return menu_form def create_toolbar(self, toolbars): - gtktoolbar = gtk.Toolbar() + gtktoolbar = Gtk.Toolbar() option = CONFIG['client.toolbar'] if option == 'default': gtktoolbar.set_style(False) elif option == 'both': - gtktoolbar.set_style(gtk.TOOLBAR_BOTH) + gtktoolbar.set_style(Gtk.ToolbarStyle.BOTH) elif option == 'text': - gtktoolbar.set_style(gtk.TOOLBAR_TEXT) + gtktoolbar.set_style(Gtk.ToolbarStyle.TEXT) elif option == 'icons': - gtktoolbar.set_style(gtk.TOOLBAR_ICONS) + gtktoolbar.set_style(Gtk.ToolbarStyle.ICONS) self.create_base_toolbar(gtktoolbar) return gtktoolbar diff --git a/tryton/gui/window/view_board/action.py b/tryton/gui/window/view_board/action.py index 4bc305a474..9eb0eeddf8 100644 --- a/tryton/gui/window/view_board/action.py +++ b/tryton/gui/window/view_board/action.py @@ -1,13 +1,14 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. 'Action' -import gtk -import gobject +import gettext + +from gi.repository import GLib, Gtk + from tryton.gui.window.view_form.screen import Screen import tryton.rpc as rpc import tryton.common as common from tryton.pyson import PYSONDecoder -import gettext from tryton.signal_event import SignalEvent from tryton.gui.window.win_form import WinForm from tryton.common import RPCExecute, RPCException @@ -60,13 +61,13 @@ class Action(SignalEvent): search_value = PYSONDecoder(search_context).decode( self.action['pyson_search_value'] or '[]') - self.widget = gtk.Frame() + self.widget = Gtk.Frame() self.widget.set_border_width(0) - vbox = gtk.VBox(homogeneous=False, spacing=3) + vbox = Gtk.VBox(homogeneous=False, spacing=3) self.widget.add(vbox) - self.title = gtk.Label() + self.title = Gtk.Label() self.widget.set_label_widget(self.title) self.widget.set_label_align(0.0, 0.5) self.widget.show_all() @@ -75,7 +76,8 @@ class Action(SignalEvent): mode=self.action['view_mode'], context=self.context, view_ids=view_ids, domain=self.domain, search_value=search_value, row_activate=self.row_activate) - vbox.pack_start(self.screen.widget, expand=True, fill=True) + vbox.pack_start( + self.screen.widget, expand=True, fill=True, padding=0) self.screen.signal_connect(self, 'record-message', self._active_changed) @@ -146,4 +148,4 @@ class Action(SignalEvent): def display(): if self.screen.widget.props.window: self.display() - gobject.idle_add(display) + GLib.idle_add(display) diff --git a/tryton/gui/window/view_board/view_board.py b/tryton/gui/window/view_board/view_board.py index 0366007c6c..af17058924 100644 --- a/tryton/gui/window/view_board/view_board.py +++ b/tryton/gui/window/view_board/view_board.py @@ -1,11 +1,12 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk import gettext - import xml.dom.minidom + +from gi.repository import Gtk + from tryton.gui.window.view_form.view.form import Container -from tryton.common import node_attributes, IconFactory +from tryton.common import node_attributes, IconFactory, get_align from .action import Action _ = gettext.gettext @@ -48,26 +49,28 @@ class ViewBoard(object): def _parse_image(self, node, container, attributes): container.add( - IconFactory.get_image(attributes['name'], gtk.ICON_SIZE_DIALOG), + IconFactory.get_image(attributes['name'], Gtk.IconSize.DIALOG), attributes) def _parse_separator(self, node, container, attributes): - vbox = gtk.VBox() + vbox = Gtk.VBox() if attributes.get('string'): - label = gtk.Label(attributes['string']) - label.set_alignment(float(attributes.get('xalign', 0.0)), - float(attributes.get('yalign', 0.5))) - vbox.pack_start(label) - vbox.pack_start(gtk.HSeparator()) + label = Gtk.Label(label=attributes['string']) + label.set_halign(get_align(attributes.get('xalign', 0.0))) + label.set_valign(get_align(attributes.get('yalign', 0.5))) + vbox.pack_start( + label, expand=True, fill=True, padding=0) + vbox.pack_start( + Gtk.HSeparator(), expand=True, fill=True, padding=0) container.add(vbox, attributes) def _parse_label(self, node, container, attributes): if not attributes.get('string'): container.add(None, attributes) return - label = gtk.Label(attributes['string']) - label.set_alignment(float(attributes.get('xalign', 0.0)), - float(attributes.get('yalign', 0.5))) + label = Gtk.Label(label=attributes['string']) + label.set_halign(get_align(attributes.get('xalign', 0.0))) + label.set_halign(get_align(attributes.get('yalign', 0.5))) label.set_angle(int(attributes.get('angle', 0))) attributes.setdefault('xexpand', 0) container.add(label, attributes) @@ -78,29 +81,31 @@ class ViewBoard(object): def _parse_notebook(self, node, container, attributes): attributes.setdefault('yexpand', True) attributes.setdefault('yfill', True) - notebook = gtk.Notebook() + notebook = Gtk.Notebook() notebook.set_scrollable(True) container.add(notebook, attributes) self.parse(node, notebook) def _parse_page(self, node, notebook, attributes): - tab_box = gtk.HBox(spacing=3) + tab_box = Gtk.HBox(spacing=3) if '_' not in attributes['string']: attributes['string'] = '_' + attributes['string'] - label = gtk.Label(attributes['string']) + label = Gtk.Label(label=attributes['string']) label.set_use_underline(True) - tab_box.pack_start(label) + tab_box.pack_start(label, expand=True, fill=True, padding=0) if 'icon' in attributes: tab_box.pack_start(IconFactory.get_image( - attributes['icon'], gtk.ICON_SIZE_SMALL_TOOLBAR)) + attributes['icon'], Gtk.IconSize.SMALL_TOOLBAR), + expand=True, fill=True, padding=0) tab_box.show_all() - viewport = gtk.Viewport() - viewport.set_shadow_type(gtk.SHADOW_NONE) - scrolledwindow = gtk.ScrolledWindow() - scrolledwindow.set_shadow_type(gtk.SHADOW_NONE) - scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + viewport = Gtk.Viewport() + viewport.set_shadow_type(Gtk.ShadowType.NONE) + scrolledwindow = Gtk.ScrolledWindow() + scrolledwindow.set_shadow_type(Gtk.ShadowType.NONE) + scrolledwindow.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) scrolledwindow.add(viewport) scrolledwindow.show_all() notebook.append_page(scrolledwindow, tab_box) @@ -110,10 +115,10 @@ class ViewBoard(object): def _parse_group(self, node, container, attributes): group = self.parse(node) group.table.set_homogeneous(attributes.get('homogeneous', False)) - frame = gtk.Frame() + frame = Gtk.Frame() frame.set_label(attributes.get('string')) if not attributes.get('string'): - frame.set_shadow_type(gtk.SHADOW_NONE) + frame.set_shadow_type(Gtk.ShadowType.NONE) frame.set_border_width(0) frame.add(group.table) container.add(frame, attributes) @@ -128,10 +133,10 @@ class ViewBoard(object): self.parse(node, paned) def _parse_hpaned(self, node, container, attributes): - self._parse_paned(node, container, attributes, gtk.HPaned) + self._parse_paned(node, container, attributes, Gtk.HPaned) def _parse_vpaned(self, node, container, attributes): - self._parse_paned(node, container, attributes, gtk.VPaned) + self._parse_paned(node, container, attributes, Gtk.VPaned) def _parse_child(self, node, paned, attributes): container = self.parse(node) diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index 76eca2be29..5c2fe69943 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -3,7 +3,6 @@ "Screen" import copy import functools -import gobject import datetime import calendar import json @@ -14,7 +13,7 @@ import gettext import logging from operator import itemgetter -import gtk +from gi.repository import GLib, Gtk from tryton.gui.window.view_form.model.group import Group from tryton.gui.window.view_form.view.screen_container import ScreenContainer @@ -93,19 +92,19 @@ class Screen(SignalEvent): yield widget for widget in reversed(list(walk_descendants(context_widget))): - if isinstance(widget, gtk.Entry): + if isinstance(widget, Gtk.Entry): widget.connect_after( 'activate', self.screen_container.activate) - elif isinstance(widget, gtk.CheckButton): + elif isinstance(widget, Gtk.CheckButton): widget.connect_after( 'toggled', self.screen_container.activate) def remove_bin(widget): - assert isinstance(widget, (gtk.ScrolledWindow, gtk.Viewport)) + assert isinstance(widget, (Gtk.ScrolledWindow, Gtk.Viewport)) parent = widget.get_parent() parent.remove(widget) child = widget.get_child() - while isinstance(child, (gtk.ScrolledWindow, gtk.Viewport)): + while isinstance(child, (Gtk.ScrolledWindow, Gtk.Viewport)): child = child.get_child() child.get_parent().remove(child) parent.add(child) @@ -446,8 +445,8 @@ class Screen(SignalEvent): unread_note = record.unread_note self.signal('unread-note', unread_note) # update attachment-count after 1 second - gobject.timeout_add(1000, self.update_attachment, record) - gobject.timeout_add(1000, self.update_note, record) + GLib.timeout_add(1000, self.update_attachment, record) + GLib.timeout_add(1000, self.update_note, record) return True current_record = property(__get_current_record, __set_current_record) @@ -537,7 +536,7 @@ class Screen(SignalEvent): self.screen_container.set(self.current_view.widget) self.display() # Postpone set of the cursor to ensure widgets are allocated - gobject.idle_add(self.set_cursor) + GLib.idle_add(self.set_cursor) def load_view_to_load(self): if len(self.view_to_load): @@ -611,7 +610,7 @@ class Screen(SignalEvent): self.current_record = record self.display() # Postpone set of the cursor to ensure widgets are allocated - gobject.idle_add(self.set_cursor, True) + GLib.idle_add(self.set_cursor, True) return self.current_record def new_model_position(self): diff --git a/tryton/gui/window/view_form/view/calendar_.py b/tryton/gui/window/view_form/view/calendar_.py index 6d8851f52a..af349b771b 100644 --- a/tryton/gui/window/view_form/view/calendar_.py +++ b/tryton/gui/window/view_form/view/calendar_.py @@ -2,10 +2,11 @@ # this repository contains the full copyright notices and license terms. from functools import wraps -import gtk import datetime import gettext +from gi.repository import Gtk + from tryton.common import node_attributes from . import View try: @@ -38,7 +39,7 @@ class ViewCalendar(View): self.widget = self.parse(xml) def parse(self, node): - vbox = gtk.VBox() + vbox = Gtk.VBox() if not Calendar_: return vbox fields = [] @@ -59,10 +60,10 @@ class ViewCalendar(View): goocalendar.connect('day-pressed', self.on_day_pressed) goocalendar.connect('day-activated', self.on_day_activated) self.widgets['goocalendar'] = goocalendar - self.scroll = scrolledWindow = gtk.ScrolledWindow() - scrolledWindow.add_with_viewport(goocalendar) - vbox.pack_start(toolbar, False, False) - vbox.pack_start(scrolledWindow, True, True) + self.scroll = scrolledWindow = Gtk.ScrolledWindow() + scrolledWindow.add(goocalendar) + vbox.pack_start(toolbar, expand=False, fill=False, padding=0) + vbox.pack_start(scrolledWindow, expand=True, fill=True, padding=0) return vbox def on_page_changed(self, goocalendar, day, toolbar): diff --git a/tryton/gui/window/view_form/view/calendar_gtk/toolbar.py b/tryton/gui/window/view_form/view/calendar_gtk/toolbar.py index 4de6d4efc6..e12fc896af 100644 --- a/tryton/gui/window/view_form/view/calendar_gtk/toolbar.py +++ b/tryton/gui/window/view_form/view/calendar_gtk/toolbar.py @@ -3,7 +3,8 @@ import datetime import calendar import gettext -import gtk + +from gi.repository import Gdk, Gtk from tryton.gui import Main from tryton.common.datetime_ import popup_position, popup_show, popup_hide @@ -11,23 +12,25 @@ from tryton.common.datetime_ import popup_position, popup_show, popup_hide _ = gettext.gettext -class Toolbar(gtk.Toolbar): +class Toolbar(Gtk.Toolbar): def __init__(self, goocalendar): super(Toolbar, self).__init__() self.goocalendar = goocalendar self.accel_group = Main().accel_group - today_button = gtk.ToolButton() + today_button = Gtk.ToolButton() today_button.set_label(_('Today')) today_button.set_homogeneous(False) today_button.connect("clicked", self.on_today_button_clicked) - today_button.add_accelerator("clicked", self.accel_group, - gtk.keysyms.t, gtk.gdk.MODIFIER_MASK, gtk.ACCEL_VISIBLE) + today_button.add_accelerator( + "clicked", self.accel_group, Gdk.KEY_t, + Gdk.ModifierType.MODIFIER_MASK, Gtk.AccelFlags.VISIBLE) self.insert(today_button, -1) - arrow_left = gtk.Arrow(gtk.ARROW_LEFT, gtk.SHADOW_NONE) - go_back = gtk.ToolButton() + arrow_left = Gtk.Arrow( + arrow_type=Gtk.ArrowType.LEFT, shadow_type=Gtk.ShadowType.NONE) + go_back = Gtk.ToolButton() go_back.set_icon_widget(arrow_left) go_back.set_label(_("go back")) go_back.set_expand(False) @@ -35,15 +38,15 @@ class Toolbar(gtk.Toolbar): go_back.connect("clicked", self.on_go_back_clicked) self.insert(go_back, -1) - self.current_page_label = gtk.Label("") - self.current_page = gtk.ToggleToolButton() + self.current_page_label = Gtk.Label() + self.current_page = Gtk.ToggleToolButton() self.current_page.set_label_widget(self.current_page_label) self.current_page.connect("clicked", self.on_current_page_clicked) self.insert(self.current_page, -1) - self.__cal_popup = gtk.Window(gtk.WINDOW_POPUP) + self.__cal_popup = Gtk.Window(type=Gtk.WindowType.POPUP) self.__cal_popup.set_events( - self.__cal_popup.get_events() | gtk.gdk.KEY_PRESS_MASK) + self.__cal_popup.get_events() | Gdk.EventMask.KEY_PRESS_MASK) self.__cal_popup.set_resizable(False) self.__cal_popup.connect('delete-event', self.on_cal_popup_closed) self.__cal_popup.connect( @@ -51,15 +54,15 @@ class Toolbar(gtk.Toolbar): self.__cal_popup.connect( 'button-press-event', self.on_cal_popup_button_pressed) - gtkcal = gtk.Calendar() + gtkcal = Gtk.Calendar() gtkcal.connect('day-selected', self.on_gtkcal_day_selected) gtkcal.connect( 'day-selected-double-click', self.on_gtkcal_day_selected_double_click) gtkcal.set_display_options( - gtk.CALENDAR_SHOW_HEADING | - gtk.CALENDAR_SHOW_WEEK_NUMBERS | - gtk.CALENDAR_SHOW_DAY_NAMES) + Gtk.CalendarDisplayOptions.SHOW_HEADING | + Gtk.CalendarDisplayOptions.SHOW_WEEK_NUMBERS | + Gtk.CalendarDisplayOptions.SHOW_DAY_NAMES) gtkcal.set_no_show_all(True) self.__cal_popup.add(gtkcal) gtkcal.show() @@ -67,8 +70,9 @@ class Toolbar(gtk.Toolbar): self.goocalendar.connect('day-selected', self.on_goocalendar_day_selected) - arrow_right = gtk.Arrow(gtk.ARROW_RIGHT, gtk.SHADOW_NONE) - go_forward = gtk.ToolButton() + arrow_right = Gtk.Arrow( + arrow_type=Gtk.ArrowType.RIGHT, shadow_type=Gtk.ShadowType.NONE) + go_forward = Gtk.ToolButton() go_forward.set_icon_widget(arrow_right) go_forward.set_label(_("go forward")) go_forward.set_expand(False) @@ -76,8 +80,9 @@ class Toolbar(gtk.Toolbar): go_forward.connect("clicked", self.on_go_forward_clicked) self.insert(go_forward, -1) - arrow_left = gtk.Arrow(gtk.ARROW_LEFT, gtk.SHADOW_NONE) - previous_year = gtk.ToolButton() + arrow_left = Gtk.Arrow( + arrow_type=Gtk.ArrowType.LEFT, shadow_type=Gtk.ShadowType.NONE) + previous_year = Gtk.ToolButton() previous_year.set_icon_widget(arrow_left) previous_year.set_label(_("previous year")) previous_year.set_expand(False) @@ -85,13 +90,14 @@ class Toolbar(gtk.Toolbar): previous_year.connect("clicked", self.on_previous_year_clicked) self.insert(previous_year, -1) - self.current_year_label = gtk.Label("") - current_year = gtk.ToolItem() + self.current_year_label = Gtk.Label() + current_year = Gtk.ToolItem() current_year.add(self.current_year_label) self.insert(current_year, -1) - arrow_right = gtk.Arrow(gtk.ARROW_RIGHT, gtk.SHADOW_NONE) - next_year = gtk.ToolButton() + arrow_right = Gtk.Arrow( + arrow_type=Gtk.ArrowType.RIGHT, shadow_type=Gtk.ShadowType.NONE) + next_year = Gtk.ToolButton() next_year.set_icon_widget(arrow_right) next_year.set_label(_("next year")) next_year.set_expand(False) @@ -99,25 +105,24 @@ class Toolbar(gtk.Toolbar): next_year.connect("clicked", self.on_next_year_clicked) self.insert(next_year, -1) - blank_widget = gtk.ToolItem() + blank_widget = Gtk.ToolItem() blank_widget.set_expand(True) self.insert(blank_widget, -1) - week_button = gtk.RadioToolButton() + week_button = Gtk.RadioToolButton() week_button.set_label(_('Week View')) week_button.connect("clicked", self.on_week_button_clicked) - week_button.add_accelerator("clicked", self.accel_group, gtk.keysyms.w, - gtk.gdk.MODIFIER_MASK, gtk.ACCEL_VISIBLE) + week_button.add_accelerator( + "clicked", self.accel_group, Gdk.KEY_w, + Gdk.ModifierType.MODIFIER_MASK, Gtk.AccelFlags.VISIBLE) self.insert(week_button, -1) - if hasattr(gtk.RadioToolButton, 'new_from_widget'): - month_button = gtk.RadioToolButton.new_from_widget(week_button) - else: - month_button = gtk.RadioToolButton(week_button) - month_button.set_label_widget(gtk.Label(_('Month View'))) + month_button = Gtk.RadioToolButton.new_from_widget(week_button) + month_button.set_label_widget(Gtk.Label(label=_('Month View'))) month_button.connect("clicked", self.on_month_button_clicked) - month_button.add_accelerator("clicked", self.accel_group, - gtk.keysyms.m, gtk.gdk.MODIFIER_MASK, gtk.ACCEL_VISIBLE) + month_button.add_accelerator( + "clicked", self.accel_group, Gdk.KEY_m, + Gdk.ModifierType.MODIFIER_MASK, Gtk.AccelFlags.VISIBLE) self.insert(month_button, -1) buttons = { 'month': month_button, @@ -125,7 +130,7 @@ class Toolbar(gtk.Toolbar): } buttons[self.goocalendar.view].set_active(True) self.update_displayed_date() - self.set_style(gtk.TOOLBAR_ICONS) + self.set_style(Gtk.ToolbarStyle.ICONS) def update_displayed_date(self): date = self.goocalendar.selected_date @@ -160,17 +165,17 @@ class Toolbar(gtk.Toolbar): return True def on_cal_popup_key_pressed(self, widget, event): - if event.keyval != gtk.keysyms.Escape: + if event.keyval != Gdk.KEY_Escape: return False - widget.stop_emission('key-press-event') + widget.stop_emission_by_name('key-press-event') self.cal_popup_hide() return True def on_cal_popup_button_pressed(self, widget, event): child = event.window - if child != widget.window: + if child != widget.props.window: while child: - if child == widget.window: + if child == widget.props.window: return False child = child.get_parent() self.cal_popup_hide() @@ -189,7 +194,7 @@ class Toolbar(gtk.Toolbar): self.cal_popup_hide() def on_goocalendar_day_selected(self, goocalendar, day): - # months go from 0 to 11 in gtk.Calendar instead of 1 to 12 + # months go from 0 to 11 in Gtk.Calendar instead of 1 to 12 new_date = self.goocalendar.selected_date self.gtkcal.select_month(new_date.month - 1, new_date.year) self.gtkcal.handler_block_by_func(self.on_gtkcal_day_selected) diff --git a/tryton/gui/window/view_form/view/form.py b/tryton/gui/window/view_form/view/form.py index bd3122907f..31c4cfe8ce 100644 --- a/tryton/gui/window/view_form/view/form.py +++ b/tryton/gui/window/view_form/view/form.py @@ -1,18 +1,19 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import operator -import gtk import gettext from collections import defaultdict +from gi.repository import Gtk + from . import View from tryton.common.focus import (get_invisible_ancestor, find_focused_child, next_focus_widget, find_focusable_child, find_first_focus_widget) -from tryton.common import Tooltips, node_attributes, IconFactory +from tryton.common import Tooltips, node_attributes, IconFactory, get_align from tryton.common.underline import set_underline from tryton.common.button import Button from tryton.config import CONFIG -from .form_gtk.calendar import Date, Time, DateTime +from .form_gtk.calendar_ import Date, Time, DateTime from .form_gtk.float import Float from .form_gtk.integer import Integer from .form_gtk.selection import Selection @@ -56,7 +57,7 @@ class Container(object): if col < 0: col = 0 self.col = col - self.table = gtk.Table(1, col) + self.table = Gtk.Table(n_rows=1, n_columns=col) self.table.set_homogeneous(homogeneous) self.table.set_col_spacings(0) self.table.set_row_spacings(0) @@ -95,21 +96,21 @@ class Container(object): yopt = 0 if attributes.get('yexpand'): - yopt = gtk.EXPAND + yopt = Gtk.AttachOptions.EXPAND if attributes.get('yfill'): if yopt: - yopt |= gtk.FILL + yopt |= Gtk.AttachOptions.FILL else: - yopt = gtk.FILL + yopt = Gtk.AttachOptions.FILL xopt = 0 if attributes.get('xexpand', True): - xopt = gtk.EXPAND + xopt = Gtk.AttachOptions.EXPAND if attributes.get('xfill', True): if xopt: - xopt |= gtk.FILL + xopt |= Gtk.AttachOptions.FILL else: - xopt = gtk.FILL + xopt = Gtk.AttachOptions.FILL if attributes.get('help'): self.tooltips.set_tip(widget, attributes['help']) @@ -125,7 +126,7 @@ class Container(object): class VContainer(Container): def __init__(self, col=1, homogeneous=False): self.col = 1 - self.table = gtk.VBox() + self.table = Gtk.VBox() self.table.set_homogeneous(homogeneous) def add_row(self): @@ -145,7 +146,7 @@ class VContainer(Container): class HContainer(Container): def __init__(self, col=0, homogeneous=False): self.col = 0 - self.table = gtk.HBox() + self.table = Gtk.HBox() self.table.set_homogeneous(homogeneous) def add_row(self): @@ -175,18 +176,19 @@ class ViewForm(View): container = self.parse(xml) - vbox = gtk.VBox() - vp = gtk.Viewport() - vp.set_shadow_type(gtk.SHADOW_NONE) + vbox = Gtk.VBox() + vp = Gtk.Viewport() + vp.set_shadow_type(Gtk.ShadowType.NONE) vp.add(container.table) - self.scroll = scroll = gtk.ScrolledWindow() + self.scroll = scroll = Gtk.ScrolledWindow() scroll.add(vp) - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scroll.set_placement(gtk.CORNER_TOP_LEFT) - viewport = gtk.Viewport() - viewport.set_shadow_type(gtk.SHADOW_ETCHED_IN) + scroll.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scroll.set_placement(Gtk.CornerType.TOP_LEFT) + viewport = Gtk.Viewport() + viewport.set_shadow_type(Gtk.ShadowType.ETCHED_IN) viewport.add(scroll) - vbox.pack_start(viewport, expand=True, fill=True) + vbox.pack_start(viewport, expand=True, fill=True, padding=0) self.widget = vbox self._viewport = vp @@ -238,12 +240,12 @@ class ViewForm(View): attributes[attr] = field.attrs[attr] vbox = VBox(attrs=attributes) if attributes.get('string'): - label = Label(attributes['string'], attrs=attributes) - label.set_alignment(float(attributes.get('xalign', 0.0)), - float(attributes.get('yalign', 0.5))) - vbox.pack_start(label) + label = Label(label=attributes['string'], attrs=attributes) + label.set_halign(get_align(attributes.get('xalign', 0.0))) + label.set_valign(get_align(attributes.get('yalign', 0.5))) + vbox.pack_start(label, expand=True, fill=True, padding=0) self.state_widgets.append(label) - vbox.pack_start(gtk.HSeparator()) + vbox.pack_start(Gtk.HSeparator(), expand=True, fill=True, padding=0) self.state_widgets.append(vbox) container.add(vbox, attributes) @@ -260,9 +262,9 @@ class ViewForm(View): if CONFIG['client.modepda']: attributes['xalign'] = 0.0 - label = Label(attributes.get('string', ''), attrs=attributes) - label.set_alignment(float(attributes.get('xalign', 1.0)), - float(attributes.get('yalign', 0.5))) + label = Label(label=attributes.get('string', ''), attrs=attributes) + label.set_halign(get_align(attributes.get('xalign', 1.0))) + label.set_valign(get_align(attributes.get('yalign', 0.5))) label.set_angle(int(attributes.get('angle', 0))) attributes.setdefault('xexpand', 0) self.state_widgets.append(label) @@ -307,7 +309,7 @@ class ViewForm(View): self.parse(node, notebook) def _parse_page(self, node, notebook, attributes): - tab_box = gtk.HBox(spacing=3) + tab_box = Gtk.HBox(spacing=3) if 'name' in attributes: field = self.group.fields[attributes['name']] if attributes['name'] == self.screen.exclude_field: @@ -315,20 +317,22 @@ class ViewForm(View): for attr in ('states', 'string'): if attr not in attributes and attr in field.attrs: attributes[attr] = field.attrs[attr] - label = gtk.Label(set_underline(attributes['string'])) + label = Gtk.Label(label=set_underline(attributes['string'])) label.set_use_underline(True) if 'icon' in attributes: tab_box.pack_start(IconFactory.get_image( - attributes['icon'], gtk.ICON_SIZE_SMALL_TOOLBAR)) - tab_box.pack_start(label) + attributes['icon'], Gtk.IconSize.SMALL_TOOLBAR), + expand=True, fill=True, padding=0) + tab_box.pack_start(label, expand=True, fill=True, padding=0) tab_box.show_all() - viewport = gtk.Viewport() - viewport.set_shadow_type(gtk.SHADOW_NONE) + viewport = Gtk.Viewport() + viewport.set_shadow_type(Gtk.ShadowType.NONE) scrolledwindow = ScrolledWindow(attrs=attributes) - scrolledwindow.set_shadow_type(gtk.SHADOW_NONE) - scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + scrolledwindow.set_shadow_type(Gtk.ShadowType.NONE) + scrolledwindow.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) scrolledwindow.add(viewport) scrolledwindow.show_all() self.state_widgets.append(scrolledwindow) @@ -388,12 +392,12 @@ class ViewForm(View): can_expand = attributes.get('expandable') if can_expand: - widget = Expander(attributes.get('string'), attrs=attributes) + widget = Expander(label=attributes.get('string'), attrs=attributes) widget.add(group.table) widget.set_expanded(can_expand == '1') self.expandables.append(widget) else: - widget = Frame(attributes.get('string'), attrs=attributes) + widget = Frame(label=attributes.get('string'), attrs=attributes) widget.add(group.table) self.state_widgets.append(widget) @@ -409,10 +413,10 @@ class ViewForm(View): self.parse(node, paned) def _parse_hpaned(self, node, container, attributes): - self._parse_paned(node, container, attributes, gtk.HPaned) + self._parse_paned(node, container, attributes, Gtk.HPaned) def _parse_vpaned(self, node, container, attributes): - self._parse_paned(node, container, attributes, gtk.VPaned) + self._parse_paned(node, container, attributes, Gtk.VPaned) def _parse_child(self, node, paned, attributes): container = self.parse(node) @@ -479,7 +483,7 @@ class ViewForm(View): for widget in widgets: if (not focused_widget or widget.widget.is_focus() - or (isinstance(widget.widget, gtk.Container) + or (isinstance(widget.widget, Gtk.Container) and widget.widget.get_focus_child())): widget.set_value() @@ -495,7 +499,7 @@ class ViewForm(View): for w in widgets) def get_buttons(self): - return [b for b in self.state_widgets if isinstance(b, gtk.Button)] + return [b for b in self.state_widgets if isinstance(b, Gtk.Button)] def reset(self): record = self.record diff --git a/tryton/gui/window/view_form/view/form_gtk/binary.py b/tryton/gui/window/view_form/view/form_gtk/binary.py index f97009a3c5..fa541dea64 100644 --- a/tryton/gui/window/view_form/view/form_gtk/binary.py +++ b/tryton/gui/window/view_form/view/form_gtk/binary.py @@ -1,10 +1,12 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk import gettext import os from urllib.request import urlopen from urllib.parse import urlparse, unquote + +from gi.repository import Gdk, Gtk + from tryton.common import common from tryton.common import file_selection, Tooltips, file_open, file_write from tryton.common.entry_position import reset_position @@ -22,38 +24,39 @@ class BinaryMixin(Widget): def toolbar(self): 'Return HBox with the toolbar' - hbox = gtk.HBox(spacing=0) + hbox = Gtk.HBox(spacing=0) tooltips = Tooltips() - self.but_save_as = gtk.Button() + self.but_save_as = Gtk.Button() self.but_save_as.set_image(common.IconFactory.get_image( - 'tryton-save', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_save_as.set_relief(gtk.RELIEF_NONE) + 'tryton-save', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_save_as.set_relief(Gtk.ReliefStyle.NONE) self.but_save_as.connect('clicked', self.save_as) tooltips.set_tip(self.but_save_as, _('Save As...')) - hbox.pack_start(self.but_save_as, expand=False, fill=False) + hbox.pack_start(self.but_save_as, expand=False, fill=False, padding=0) - self.but_select = gtk.Button() + self.but_select = Gtk.Button() self.but_select.set_image(common.IconFactory.get_image( - 'tryton-search', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_select.set_relief(gtk.RELIEF_NONE) + 'tryton-search', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_select.set_relief(Gtk.ReliefStyle.NONE) self.but_select.connect('clicked', self.select) - target_entry = gtk.TargetEntry.new('text/uri-list', 0, 0) - self.but_select.drag_dest_set(gtk.DEST_DEFAULT_ALL, [ + target_entry = Gtk.TargetEntry.new('text/uri-list', 0, 0) + self.but_select.drag_dest_set(Gtk.DestDefaults.ALL, [ target_entry, - ], gtk.gdk.ACTION_MOVE | gtk.gdk.ACTION_COPY) + ], + Gdk.DragAction.MOVE | Gdk.DragAction.COPY) self.but_select.connect( 'drag-data-received', self.select_drag_data_received) tooltips.set_tip(self.but_select, _('Select...')) - hbox.pack_start(self.but_select, expand=False, fill=False) + hbox.pack_start(self.but_select, expand=False, fill=False, padding=0) - self.but_clear = gtk.Button() + self.but_clear = Gtk.Button() self.but_clear.set_image(common.IconFactory.get_image( - 'tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_clear.set_relief(gtk.RELIEF_NONE) + 'tryton-clear', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_clear.set_relief(Gtk.ReliefStyle.NONE) self.but_clear.connect('clicked', self.clear) tooltips.set_tip(self.but_clear, _('Clear')) - hbox.pack_start(self.but_clear, expand=False, fill=False) + hbox.pack_start(self.but_clear, expand=False, fill=False, padding=0) tooltips.enable() return hbox @@ -64,7 +67,7 @@ class BinaryMixin(Widget): @property def filters(self): - filter_all = gtk.FileFilter() + filter_all = Gtk.FileFilter() filter_all.set_name(_('All files')) filter_all.add_pattern("*") return [filter_all] @@ -130,7 +133,7 @@ class BinaryMixin(Widget): if self.filename_field: filename = self.filename_field.get(self.record) filename = file_selection(_('Save As...'), filename=filename, - action=gtk.FILE_CHOOSER_ACTION_SAVE) + action=Gtk.FileChooserAction.SAVE) if filename: with open(filename, 'wb') as fp: fp.write(self.get_data()) @@ -147,26 +150,28 @@ class Binary(BinaryMixin, Widget): def __init__(self, view, attrs): super(Binary, self).__init__(view, attrs) - self.widget = gtk.HBox(spacing=0) - self.wid_size = gtk.Entry() + self.widget = Gtk.HBox(spacing=0) + self.wid_size = Gtk.Entry() self.wid_size.set_width_chars(self.default_width_chars) self.wid_size.set_alignment(1.0) self.wid_size.props.sensitive = False if self.filename and attrs.get('filename_visible'): - self.wid_text = gtk.Entry() + self.wid_text = Gtk.Entry() self.wid_text.set_property('activates_default', True) self.wid_text.connect('focus-out-event', lambda x, y: self._focus_out()) self.wid_text.connect_after('key_press_event', self.sig_key_press) self.wid_text.connect('icon-press', self.sig_icon_press) - self.widget.pack_start(self.wid_text, expand=True, fill=True) + self.widget.pack_start( + self.wid_text, expand=True, fill=True, padding=0) else: self.wid_text = None self.mnemonic_widget = self.wid_text - self.widget.pack_start(self.wid_size, expand=not self.filename, - fill=True) + self.widget.pack_start( + self.wid_size, expand=not self.filename, fill=True, padding=0) - self.widget.pack_start(self.toolbar(), expand=False, fill=False) + self.widget.pack_start( + self.toolbar(), expand=False, fill=False, padding=0) def _readonly_set(self, value): self.but_select.set_sensitive(not value) @@ -180,10 +185,10 @@ class Binary(BinaryMixin, Widget): def sig_key_press(self, widget, event, *args): editable = self.wid_text and self.wid_text.get_editable() - if event.keyval == gtk.keysyms.F3 and editable: + if event.keyval == Gdk.KEY_F3 and editable: self.sig_new(widget) return True - elif event.keyval == gtk.keysyms.F2: + elif event.keyval == Gdk.KEY_F2: if self.filename: self.sig_open(widget) else: @@ -192,7 +197,7 @@ class Binary(BinaryMixin, Widget): return False def sig_icon_press(self, widget, icon_pos, event): - if icon_pos == gtk.ENTRY_ICON_PRIMARY: + if icon_pos == Gtk.EntryIconPosition.PRIMARY: self.open_() def display(self): @@ -216,10 +221,10 @@ class Binary(BinaryMixin, Widget): icon, tooltip = 'tryton-open', _("Open...") else: icon, tooltip = None, '' - pos = gtk.ENTRY_ICON_PRIMARY + pos = Gtk.EntryIconPosition.PRIMARY if icon: pixbuf = common.IconFactory.get_pixbuf( - icon, gtk.ICON_SIZE_MENU) + icon, Gtk.IconSize.MENU) else: pixbuf = None self.wid_text.set_icon_from_pixbuf(pos, pixbuf) diff --git a/tryton/gui/window/view_form/view/form_gtk/calendar.py b/tryton/gui/window/view_form/view/form_gtk/calendar_.py similarity index 91% rename from tryton/gui/window/view_form/view/form_gtk/calendar.py rename to tryton/gui/window/view_form/view/form_gtk/calendar_.py index 9d13ac3466..b80491b5ce 100644 --- a/tryton/gui/window/view_form/view/form_gtk/calendar.py +++ b/tryton/gui/window/view_form/view/form_gtk/calendar_.py @@ -1,11 +1,9 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import datetime - -import gtk import gettext -import gobject +from gi.repository import GLib, Gtk from .widget import Widget from tryton import common @@ -21,7 +19,7 @@ class Date(Widget): def __init__(self, view, attrs, _entry=DateEntry): super(Date, self).__init__(view, attrs) - self.widget = gtk.HBox() + self.widget = Gtk.HBox() self.entry = self.mnemonic_widget = add_operators(_entry()) self.real_entry.set_property('activates_default', True) self.real_entry.connect('key_press_event', self.sig_key_press) @@ -29,7 +27,7 @@ class Date(Widget): self.real_entry.connect('changed', lambda _: self.send_modified()) self.real_entry.connect('focus-out-event', lambda x, y: self._focus_out()) - self.widget.pack_start(self.entry, expand=False, fill=False) + self.widget.pack_start(self.entry, expand=False, fill=False, padding=0) @property def real_entry(self): @@ -37,7 +35,7 @@ class Date(Widget): def _set_editable(self, value): self.entry.set_editable(value) - self.entry.set_icon_sensitive(gtk.ENTRY_ICON_PRIMARY, value) + self.entry.set_icon_sensitive(Gtk.EntryIconPosition.PRIMARY, value) def _readonly_set(self, value): self._set_editable(not value) @@ -122,18 +120,18 @@ class Time(Date): # Only when changed from pop list if not combobox.get_child().has_focus(): # Must be deferred because it triggers a display of the form - gobject.idle_add(focus_out) + GLib.idle_add(focus_out) class DateTime(Date): def __init__(self, view, attrs): Widget.__init__(self, view, attrs) - self.widget = gtk.HBox() + self.widget = Gtk.HBox() self.entry = self.mnemonic_widget = DateTimeEntry() for child in self.entry.get_children(): add_operators(child) - if isinstance(child, gtk.ComboBoxEntry): + if isinstance(child, Gtk.ComboBox): child.set_focus_chain([child.get_child()]) child = child.get_child() child.set_property('activates_default', True) @@ -141,7 +139,7 @@ class DateTime(Date): child.connect('activate', self.sig_activate) child.connect('changed', lambda _: self.send_modified()) child.connect('focus-out-event', lambda x, y: self._focus_out()) - self.widget.pack_start(self.entry, expand=False, fill=False) + self.widget.pack_start(self.entry, expand=False, fill=False, padding=0) @classmethod def cast(cls, value): @@ -149,10 +147,10 @@ class DateTime(Date): def _set_editable(self, value): for child in self.entry.get_children(): - if isinstance(child, gtk.Entry): + if isinstance(child, Gtk.Entry): child.set_editable(value) - child.set_icon_sensitive(gtk.ENTRY_ICON_PRIMARY, value) - elif isinstance(child, gtk.ComboBoxEntry): + child.set_icon_sensitive(Gtk.EntryIconPosition.PRIMARY, value) + elif isinstance(child, Gtk.ComboBox): child.set_sensitive(value) def set_format(self): diff --git a/tryton/gui/window/view_form/view/form_gtk/char.py b/tryton/gui/window/view_form/view/form_gtk/char.py index 40bc81a60e..b27406119c 100644 --- a/tryton/gui/window/view_form/view/form_gtk/char.py +++ b/tryton/gui/window/view_form/view/form_gtk/char.py @@ -2,8 +2,8 @@ # this repository contains the full copyright notices and license terms. import gettext -import gobject -import gtk +from gi.repository import GLib, Gtk + from .widget import Widget, TranslateMixin from tryton.common import Tooltips, IconFactory from tryton.common.entry_position import reset_position @@ -19,10 +19,10 @@ class Char(Widget, TranslateMixin, PopdownMixin): def __init__(self, view, attrs): super(Char, self).__init__(view, attrs) - self.widget = gtk.HBox() + self.widget = Gtk.HBox() self.autocomplete = bool(attrs.get('autocomplete')) if self.autocomplete: - self.entry = gtk.ComboBoxEntry() + self.entry = Gtk.ComboBox(has_entry=True) selection_shortcuts(self.entry) focus_entry = self.entry.get_child() self.set_popdown([], self.entry) @@ -30,9 +30,9 @@ class Char(Widget, TranslateMixin, PopdownMixin): self.entry.connect('move-active', self._move_active) self.entry.connect( 'scroll-event', - lambda c, e: c.emit_stop_by_name('scroll-event')) + lambda c, e: c.stop_emission_by_name('scroll-event')) else: - self.entry = gtk.Entry() + self.entry = Gtk.Entry() focus_entry = self.entry self.mnemonic_widget = focus_entry @@ -43,16 +43,16 @@ class Char(Widget, TranslateMixin, PopdownMixin): expand, fill = True, True if attrs.get('size'): expand, fill = False, False - self.widget.pack_start(self.entry, expand=expand, fill=fill) + self.widget.pack_start(self.entry, expand=expand, fill=fill, padding=0) if attrs.get('translate'): self.entry.set_icon_from_pixbuf( - gtk.ENTRY_ICON_SECONDARY, - IconFactory.get_pixbuf('tryton-translate', gtk.ICON_SIZE_MENU)) + Gtk.EntryIconPosition.SECONDARY, + IconFactory.get_pixbuf('tryton-translate', Gtk.IconSize.MENU)) self.entry.connect('icon-press', self.translate) def translate_widget(self): - entry = gtk.Entry() + entry = Gtk.Entry() entry.set_property('activates_default', True) if self.record: field_size = self.record.expr_eval(self.attrs.get('size')) @@ -78,7 +78,7 @@ class Char(Widget, TranslateMixin, PopdownMixin): # Only when changed from pop list if not combobox.get_child().has_focus(): # Must be deferred because it triggers a display of the form - gobject.idle_add(focus_out) + GLib.idle_add(focus_out) @property def modified(self): @@ -141,10 +141,13 @@ class Char(Widget, TranslateMixin, PopdownMixin): def _move_active(self, combobox, scroll_type): if not combobox.get_child().get_editable(): - combobox.emit_stop_by_name('move-active') + combobox.stop_emission_by_name('move-active') def _readonly_set(self, value): - sensitivity = {True: gtk.SENSITIVITY_OFF, False: gtk.SENSITIVITY_AUTO} + sensitivity = { + True: Gtk.SensitivityType.OFF, + False: Gtk.SensitivityType.AUTO, + } super(Char, self)._readonly_set(value) if self.autocomplete: entry_editable = self.entry.get_child() @@ -164,10 +167,11 @@ class Password(Char): super(Password, self).__init__(view, attrs) self.entry.props.visibility = False - self.visibility_checkbox = gtk.CheckButton() + self.visibility_checkbox = Gtk.CheckButton() self.visibility_checkbox.connect('toggled', self.toggle_visibility) Tooltips().set_tip(self.visibility_checkbox, _('Show plain text')) - self.widget.pack_start(self.visibility_checkbox, expand=False) + self.widget.pack_start( + self.visibility_checkbox, expand=False, fill=True, padding=0) def _readonly_set(self, value): super(Char, self)._readonly_set(value) diff --git a/tryton/gui/window/view_form/view/form_gtk/checkbox.py b/tryton/gui/window/view_form/view/form_gtk/checkbox.py index 78bba3399d..3498c6ee8e 100644 --- a/tryton/gui/window/view_form/view/form_gtk/checkbox.py +++ b/tryton/gui/window/view_form/view/form_gtk/checkbox.py @@ -1,9 +1,11 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk -from .widget import Widget import gettext +from gi.repository import Gtk + +from .widget import Widget + _ = gettext.gettext @@ -11,7 +13,7 @@ class CheckBox(Widget): def __init__(self, view, attrs): super(CheckBox, self).__init__(view, attrs) - self.widget = self.mnemonic_widget = gtk.CheckButton() + self.widget = self.mnemonic_widget = Gtk.CheckButton() self.widget.connect('focus-out-event', lambda x, y: self._focus_out()) self.widget.connect_after('toggled', self.sig_activate) diff --git a/tryton/gui/window/view_form/view/form_gtk/dictionary.py b/tryton/gui/window/view_form/view/form_gtk/dictionary.py index f6db66779f..5ca299693c 100644 --- a/tryton/gui/window/view_form/view/form_gtk/dictionary.py +++ b/tryton/gui/window/view_form/view/form_gtk/dictionary.py @@ -2,13 +2,13 @@ # repository contains the full copyright notices and license terms. import operator -import gobject -import gtk import locale import decimal import gettext from decimal import Decimal +from gi.repository import GLib, GObject, Gtk + from .widget import Widget from .integer import IntegerMixin from .float import FloatMixin @@ -40,7 +40,7 @@ class DictEntry(object): self.widget = self.create_widget() def create_widget(self): - widget = gtk.Entry() + widget = Gtk.Entry() widget.connect('key-press-event', self.parent_widget.send_modified) widget.connect('focus-out-event', lambda w, e: self.parent_widget._focus_out()) @@ -65,7 +65,7 @@ class DictEntry(object): class DictBooleanEntry(DictEntry): def create_widget(self): - widget = gtk.CheckButton() + widget = Gtk.CheckButton() widget.connect('toggled', self.parent_widget.sig_activate) widget.connect('focus-out-event', lambda w, e: self.parent_widget._focus_out()) @@ -91,7 +91,7 @@ class DictSelectionEntry(DictEntry): fill = False def create_widget(self): - widget = gtk.ComboBoxEntry() + widget = Gtk.ComboBox(has_entry=True) # customizing entry child = widget.get_child() @@ -104,11 +104,12 @@ class DictSelectionEntry(DictEntry): widget.connect('notify::active', lambda w, e: self.parent_widget._focus_out()) widget.connect( - 'scroll-event', lambda c, e: c.emit_stop_by_name('scroll-event')) + 'scroll-event', + lambda c, e: c.stop_emission_by_name('scroll-event')) selection_shortcuts(widget) # setting completion and selection - model = gtk.ListStore(gobject.TYPE_STRING) + model = Gtk.ListStore(GObject.TYPE_STRING) model.append(('',)) self._selection = {'': None} width = 10 @@ -123,7 +124,7 @@ class DictSelectionEntry(DictEntry): widget.set_model(model) widget.set_text_column(0) child.set_width_chars(width) - completion = gtk.EntryCompletion() + completion = Gtk.EntryCompletion() completion.set_inline_selection(True) completion.set_model(model) child.set_completion(completion) @@ -293,28 +294,28 @@ class DictWidget(Widget): self.buttons = {} self.rows = {} - self.widget = gtk.Frame() - label = gtk.Label(set_underline(attrs.get('string', ''))) + self.widget = Gtk.Frame() + label = Gtk.Label(label=set_underline(attrs.get('string', ''))) label.set_use_underline(True) self.widget.set_label_widget(label) - self.widget.set_shadow_type(gtk.SHADOW_OUT) + self.widget.set_shadow_type(Gtk.ShadowType.OUT) - vbox = gtk.VBox() + vbox = Gtk.VBox() self.widget.add(vbox) - self.table = gtk.Table(1, 3, homogeneous=False) + self.table = Gtk.Table(n_rows=1, n_columns=3, homogeneous=False) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) - vbox.pack_start(self.table, expand=True, fill=True) + vbox.pack_start(self.table, expand=True, fill=True, padding=0) - hbox = gtk.HBox() + hbox = Gtk.HBox() hbox.set_border_width(2) - self.wid_text = gtk.Entry() + self.wid_text = Gtk.Entry() self.wid_text.set_placeholder_text(_('Search')) self.wid_text.props.width_chars = 13 self.wid_text.connect('activate', self._sig_activate) - hbox.pack_start(self.wid_text, expand=True, fill=True) + hbox.pack_start(self.wid_text, expand=True, fill=True, padding=0) label.set_mnemonic_widget(self.wid_text) if int(self.attrs.get('completion', 1)): @@ -326,14 +327,14 @@ class DictWidget(Widget): else: self.wid_completion = None - self.but_add = gtk.Button() + self.but_add = Gtk.Button() self.but_add.connect('clicked', self._sig_add) - self.but_add.add(IconFactory.get_image( - 'tryton-add', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_add.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_add, expand=False, fill=False) + self.but_add.add( + IconFactory.get_image('tryton-add', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_add.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_add, expand=False, fill=False, padding=0) hbox.set_focus_chain([self.wid_text]) - vbox.pack_start(hbox, expand=True, fill=True) + vbox.pack_start(hbox, expand=True, fill=True, padding=0) self.tooltips = Tooltips() self.tooltips.set_tip(self.but_add, _('Add value')) @@ -347,10 +348,10 @@ class DictWidget(Widget): return self.wid_text def _new_remove_btn(self): - but_remove = gtk.Button() - but_remove.add(IconFactory.get_image( - 'tryton-remove', gtk.ICON_SIZE_SMALL_TOOLBAR)) - but_remove.set_relief(gtk.RELIEF_NONE) + but_remove = Gtk.Button() + but_remove.add( + IconFactory.get_image('tryton-remove', Gtk.IconSize.SMALL_TOOLBAR)) + but_remove.set_relief(Gtk.ReliefStyle.NONE) return but_remove def _sig_activate(self, *args): @@ -382,7 +383,7 @@ class DictWidget(Widget): if not focus: # Use idle add because it can be called from the callback # of WinSearch while the popup is still there - gobject.idle_add(self.fields[key_name].widget.grab_focus) + GLib.idle_add(self.fields[key_name].widget.grab_focus) focus = True def _sig_remove(self, button, key, modified=True): @@ -432,32 +433,37 @@ class DictWidget(Widget): key_schema = self.field.keys[key] self.fields[key] = DICT_ENTRIES[key_schema['type_']](key, self) field = self.fields[key] - alignment = gtk.Alignment( - float(self.attrs.get('xalign', 0.0)), - float(self.attrs.get('yalign', 0.5)), - float(self.attrs.get('xexpand', 1.0)), - float(self.attrs.get('yexpand', 1.0))) - hbox = gtk.HBox() - hbox.pack_start(field.widget, expand=field.expand, fill=field.fill) + alignment = Gtk.Alignment() + alignment.props.xalign = float(self.attrs.get('xalign', 0.0)) + alignment.props.yalign = float(self.attrs.get('yalign', 0.5)) + alignment.props.xscale = float(self.attrs.get('xexpand', 1.0)) + alignment.props.yscale = float(self.attrs.get('yexpand', 1.0)) + hbox = Gtk.HBox() + hbox.pack_start( + field.widget, expand=field.expand, fill=field.fill, padding=0) alignment.add(hbox) n_rows = self.table.props.n_rows self.table.resize(n_rows + 1, 3) text = key_schema['string'] + _(':') - label = gtk.Label(set_underline(text)) - label.set_use_underline(True) - label.set_alignment(1., .5) - self.table.attach(label, 0, 1, n_rows - 1, n_rows, - xoptions=gtk.FILL, yoptions=False, xpadding=2) + label = Gtk.Label( + label=set_underline(text), + use_underline=True, halign=Gtk.Align.START) + self.table.attach( + label, 0, 1, n_rows - 1, n_rows, + xoptions=Gtk.AttachOptions.FILL, xpadding=2, yoptions=False) label.set_mnemonic_widget(field.widget) label.show() - self.table.attach(alignment, 1, 2, n_rows - 1, n_rows, - xoptions=gtk.FILL | gtk.EXPAND, yoptions=False, xpadding=2) + self.table.attach( + alignment, 1, 2, n_rows - 1, n_rows, + xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, + xpadding=2, yoptions=False) alignment.show_all() remove_but = self._new_remove_btn() self.tooltips.set_tip(remove_but, _('Remove "%s"') % key_schema['string']) - self.table.attach(remove_but, 2, 3, n_rows - 1, n_rows, - xoptions=gtk.FILL, yoptions=False, xpadding=2) + self.table.attach( + remove_but, 2, 3, n_rows - 1, n_rows, + xoptions=Gtk.AttachOptions.FILL, xpadding=2, yoptions=False) remove_but.connect('clicked', self._sig_remove, key) remove_but.show_all() self.rows[key] = [label, alignment, remove_but] diff --git a/tryton/gui/window/view_form/view/form_gtk/float.py b/tryton/gui/window/view_form/view/form_gtk/float.py index 17bda570d7..acfc562935 100644 --- a/tryton/gui/window/view_form/view/form_gtk/float.py +++ b/tryton/gui/window/view_form/view/form_gtk/float.py @@ -1,7 +1,9 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk import locale + +from gi.repository import Gdk + from .integer import Integer, IntegerMixin @@ -22,16 +24,16 @@ class FloatMixin(IntegerMixin): try: value = locale.atof(new_value) except ValueError: - entry.stop_emission('insert-text') + entry.stop_emission_by_name('insert-text') return digits = self.digits if digits and not (round(value, digits[1]) == float(value)): - entry.stop_emission('insert-text') + entry.stop_emission_by_name('insert-text') def _key_press_event(self, entry, event): for name in ['KP_Decimal', 'KP_Separator']: - if event.keyval == gtk.gdk.keyval_from_name(name): - event.keyval = int(gtk.gdk.unicode_to_keyval( + if event.keyval == Gdk.keyval_from_name(name): + event.keyval = int(Gdk.unicode_to_keyval( ord(locale.localeconv()['decimal_point']))) @property diff --git a/tryton/gui/window/view_form/view/form_gtk/image.py b/tryton/gui/window/view_form/view/form_gtk/image.py index ec5f127bce..18fc047b6b 100644 --- a/tryton/gui/window/view_form/view/form_gtk/image.py +++ b/tryton/gui/window/view_form/view/form_gtk/image.py @@ -1,9 +1,10 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk import gettext import urllib.request +from gi.repository import Gdk, Gtk + from tryton.common import resize_pixbuf, data2pixbuf from tryton.config import CONFIG from .widget import Widget @@ -20,24 +21,26 @@ class Image(BinaryMixin, Widget): self.height = int(attrs.get('height', 100)) self.width = int(attrs.get('width', 300)) - self.widget = gtk.VBox(spacing=3) - self.event = gtk.EventBox() - self.event.drag_dest_set(gtk.DEST_DEFAULT_ALL, [ - gtk.TargetEntry.new('text/plain', 0, 0), - gtk.TargetEntry.new('text/uri-list', 0, 1), - gtk.TargetEntry.new("image/x-xpixmap", 0, 2)], gtk.gdk.ACTION_MOVE) + self.widget = Gtk.VBox(spacing=3) + self.event = Gtk.EventBox() + self.event.drag_dest_set(Gtk.DestDefaults.ALL, [ + Gtk.TargetEntry.new('text/plain', 0, 0), + Gtk.TargetEntry.new('text/uri-list', 0, 1), + Gtk.TargetEntry.new("image/x-xpixmap", 0, 2)], + Gdk.DragAction.MOVE) self.event.connect('drag_motion', self.drag_motion) self.event.connect('drag_data_received', self.drag_data_received) - self.image = gtk.Image() + self.image = Gtk.Image() self.event.add(self.image) - self.widget.pack_start(self.event, expand=True, fill=True) + self.widget.pack_start(self.event, expand=True, fill=True, padding=0) toolbar = self.toolbar() # Set button attributes even if not display if not attrs.get('readonly'): - alignment = gtk.Alignment(xalign=0.5, yalign=0.5) + alignment = Gtk.Alignment(xalign=0.5, yalign=0.5) alignment.add(toolbar) - self.widget.pack_start(alignment, expand=False, fill=False) + self.widget.pack_start( + alignment, expand=False, fill=False, padding=0) self._readonly = False @@ -46,7 +49,7 @@ class Image(BinaryMixin, Widget): @property def filters(self): filters = super(Image, self).filters - filter_image = gtk.FileFilter() + filter_image = Gtk.FileFilter() filter_image.set_name(_('Images')) for mime in ("image/png", "image/jpeg", "image/gif"): filter_image.add_mime_type(mime) @@ -67,7 +70,7 @@ class Image(BinaryMixin, Widget): def drag_motion(self, widget, context, x, y, timestamp): if self._readonly: return False - context.drag_status(gtk.gdk.ACTION_COPY, timestamp) + context.drag_status(Gdk.DragAction.COPY, timestamp) return True def drag_data_received(self, widget, context, x, y, selection, diff --git a/tryton/gui/window/view_form/view/form_gtk/integer.py b/tryton/gui/window/view_form/view/form_gtk/integer.py index 098a664539..3446591a29 100644 --- a/tryton/gui/window/view_form/view/form_gtk/integer.py +++ b/tryton/gui/window/view_form/view/form_gtk/integer.py @@ -22,7 +22,7 @@ class IntegerMixin: try: locale.atoi(new_value) except ValueError: - entry.stop_emission('insert-text') + entry.stop_emission_by_name('insert-text') class Integer(IntegerMixin, Char): diff --git a/tryton/gui/window/view_form/view/form_gtk/many2many.py b/tryton/gui/window/view_form/view/form_gtk/many2many.py index d39a6880ec..12c7c9513f 100644 --- a/tryton/gui/window/view_form/view/form_gtk/many2many.py +++ b/tryton/gui/window/view_form/view/form_gtk/many2many.py @@ -1,16 +1,17 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk - -from tryton.gui.window.view_form.screen import Screen -from .widget import Widget -from tryton.gui.window.win_search import WinSearch -from tryton.gui.window.win_form import WinForm -import tryton.common as common import gettext + +from gi.repository import Gdk, Gtk + +import tryton.common as common +from .widget import Widget from tryton.common.completion import get_completion, update_completion from tryton.common.domain_parser import quote from tryton.common.underline import set_underline +from tryton.gui.window.view_form.screen import Screen +from tryton.gui.window.win_search import WinSearch +from tryton.gui.window.win_form import WinForm _ = gettext.gettext @@ -21,33 +22,33 @@ class Many2Many(Widget): def __init__(self, view, attrs): super(Many2Many, self).__init__(view, attrs) - self.widget = gtk.Frame() - self.widget.set_shadow_type(gtk.SHADOW_NONE) + self.widget = Gtk.Frame() + self.widget.set_shadow_type(Gtk.ShadowType.NONE) self.widget.get_accessible().set_name(attrs.get('string', '')) - vbox = gtk.VBox(homogeneous=False, spacing=5) + vbox = Gtk.VBox(homogeneous=False, spacing=5) self.widget.add(vbox) self._readonly = True self._required = False self._position = 0 - hbox = gtk.HBox(homogeneous=False, spacing=0) + hbox = Gtk.HBox(homogeneous=False, spacing=0) hbox.set_border_width(2) - self.title = gtk.Label(set_underline(attrs.get('string', ''))) - self.title.set_use_underline(True) - self.title.set_alignment(0.0, 0.5) - hbox.pack_start(self.title, expand=True, fill=True) + self.title = Gtk.Label( + label=set_underline(attrs.get('string', '')), + use_underline=True, halign=Gtk.Align.START) + hbox.pack_start(self.title, expand=True, fill=True, padding=0) - hbox.pack_start(gtk.VSeparator(), expand=False, fill=True) + hbox.pack_start(Gtk.VSeparator(), expand=False, fill=True, padding=0) tooltips = common.Tooltips() - self.wid_text = gtk.Entry() + self.wid_text = Gtk.Entry() self.wid_text.set_placeholder_text(_('Search')) self.wid_text.set_property('width_chars', 13) self.wid_text.connect('focus-out-event', self._focus_out) self.focus_out = True - hbox.pack_start(self.wid_text, expand=True, fill=True) + hbox.pack_start(self.wid_text, expand=True, fill=True, padding=0) if int(self.attrs.get('completion', 1)): self.wid_completion = get_completion( @@ -62,30 +63,30 @@ class Many2Many(Widget): else: self.wid_completion = None - self.but_add = gtk.Button() + self.but_add = Gtk.Button() tooltips.set_tip(self.but_add, _('Add existing record')) self.but_add.connect('clicked', self._sig_add) self.but_add.add(common.IconFactory.get_image( - 'tryton-add', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_add.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_add, expand=False, fill=False) + 'tryton-add', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_add.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_add, expand=False, fill=False, padding=0) - self.but_remove = gtk.Button() + self.but_remove = Gtk.Button() tooltips.set_tip(self.but_remove, _('Remove selected record ')) self.but_remove.connect('clicked', self._sig_remove) self.but_remove.add(common.IconFactory.get_image( - 'tryton-remove', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_remove.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_remove, expand=False, fill=False) + 'tryton-remove', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_remove.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_remove, expand=False, fill=False, padding=0) hbox.set_focus_chain([self.wid_text]) tooltips.enable() - frame = gtk.Frame() + frame = Gtk.Frame() frame.add(hbox) - frame.set_shadow_type(gtk.SHADOW_OUT) - vbox.pack_start(frame, expand=False, fill=True) + frame.set_shadow_type(Gtk.ShadowType.OUT) + vbox.pack_start(frame, expand=False, fill=True, padding=0) self.screen = Screen(attrs['relation'], view_ids=attrs.get('view_ids', '').split(','), @@ -94,7 +95,7 @@ class Many2Many(Widget): limit=None) self.screen.signal_connect(self, 'record-message', self._sig_label) - vbox.pack_start(self.screen.widget, expand=True, fill=True) + vbox.pack_start(self.screen.widget, expand=True, fill=True, padding=0) self.title.set_mnemonic_widget( self.screen.current_view.mnemonic_widget) @@ -104,25 +105,25 @@ class Many2Many(Widget): def on_keypress(self, widget, event): editable = self.wid_text.get_editable() - activate_keys = [gtk.keysyms.Tab, gtk.keysyms.ISO_Left_Tab] - remove_keys = [gtk.keysyms.Delete, gtk.keysyms.KP_Delete] + activate_keys = [Gdk.KEY_Tab, Gdk.KEY_ISO_Left_Tab] + remove_keys = [Gdk.KEY_Delete, Gdk.KEY_KP_Delete] if not self.wid_completion: - activate_keys.append(gtk.keysyms.Return) + activate_keys.append(Gdk.KEY_Return) if widget == self.screen.widget: - if event.keyval == gtk.keysyms.F3 and editable: + if event.keyval == Gdk.KEY_F3 and editable: self._sig_add() return True - elif event.keyval == gtk.keysyms.F2: + elif event.keyval == Gdk.KEY_F2: self._sig_edit() return True elif event.keyval in remove_keys and editable: self._sig_remove() return True elif widget == self.wid_text: - if event.keyval == gtk.keysyms.F3: + if event.keyval == Gdk.KEY_F3: self._sig_new() return True - elif event.keyval == gtk.keysyms.F2: + elif event.keyval == Gdk.KEY_F2: self._sig_add() return True elif event.keyval in activate_keys and self.wid_text.get_text(): @@ -163,7 +164,7 @@ class Many2Many(Widget): title=self.attrs.get('string')) win.screen.search_filter(quote(value)) if len(win.screen.group) == 1: - win.response(None, gtk.RESPONSE_OK) + win.response(None, Gtk.ResponseType.OK) else: win.show() diff --git a/tryton/gui/window/view_form/view/form_gtk/many2one.py b/tryton/gui/window/view_form/view/form_gtk/many2one.py index 0ca87a13ab..4f105e7928 100644 --- a/tryton/gui/window/view_form/view/form_gtk/many2one.py +++ b/tryton/gui/window/view_form/view/form_gtk/many2one.py @@ -1,9 +1,9 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk -import gobject import gettext +from gi.repository import Gdk, GLib, Gtk + from .widget import Widget import tryton.common as common from tryton.gui.window.view_form.screen import Screen @@ -23,10 +23,10 @@ class Many2One(Widget): def __init__(self, view, attrs): super(Many2One, self).__init__(view, attrs) - self.widget = gtk.HBox(spacing=0) + self.widget = Gtk.HBox(spacing=0) self.widget.set_property('sensitive', True) - self.wid_text = self.mnemonic_widget = gtk.Entry() + self.wid_text = self.mnemonic_widget = Gtk.Entry() self.wid_text.set_property('width-chars', self.default_width_chars) self.wid_text.set_property('activates_default', True) self.wid_text.connect('key-press-event', self.send_modified) @@ -44,7 +44,7 @@ class Many2One(Widget): self.wid_text.connect('icon-press', self.sig_edit) - self.widget.pack_end(self.wid_text, expand=True, fill=True) + self.widget.pack_end(self.wid_text, expand=True, fill=True, padding=0) self._readonly = False @@ -62,9 +62,9 @@ class Many2One(Widget): def _set_button_sensitive(self): self.wid_text.set_editable(not self._readonly) self.wid_text.set_icon_sensitive( - gtk.ENTRY_ICON_PRIMARY, self.read_access) + Gtk.EntryIconPosition.PRIMARY, self.read_access) self.wid_text.set_icon_sensitive( - gtk.ENTRY_ICON_SECONDARY, not self._readonly) + Gtk.EntryIconPosition.SECONDARY, not self._readonly) def get_access(self, type_): model = self.get_model() @@ -140,7 +140,7 @@ class Many2One(Widget): title=self.attrs.get('string')) win.screen.search_filter(quote(text)) if len(win.screen.group) == 1: - win.response(None, gtk.RESPONSE_OK) + win.response(None, Gtk.ResponseType.OK) else: win.show() return @@ -184,7 +184,7 @@ class Many2One(Widget): self.focus_out = False value = self.field.get(self.record) - if (icon_pos == gtk.ENTRY_ICON_SECONDARY + if (icon_pos == Gtk.EntryIconPosition.SECONDARY and not self._readonly and self.has_target(value)): self.field.set_client(self.record, self.value_from_id(None, '')) @@ -233,15 +233,15 @@ class Many2One(Widget): def sig_key_press(self, widget, event, *args): editable = self.wid_text.get_editable() - activate_keys = [gtk.keysyms.Tab, gtk.keysyms.ISO_Left_Tab] + activate_keys = [Gdk.KEY_Tab, Gdk.KEY_ISO_Left_Tab] if not self.wid_completion: - activate_keys.append(gtk.keysyms.Return) - if (event.keyval == gtk.keysyms.F3 + activate_keys.append(Gdk.KEY_Return) + if (event.keyval == Gdk.KEY_F3 and editable and self.create_access): self.sig_new(widget, event) return True - elif event.keyval == gtk.keysyms.F2 and self.read_access: + elif event.keyval == Gdk.KEY_F2 and self.read_access: self.sig_edit(widget) return True elif (event.keyval in activate_keys @@ -249,8 +249,7 @@ class Many2One(Widget): self.sig_activate() elif (self.has_target(self.field.get(self.record)) and editable - and event.keyval in (gtk.keysyms.Delete, - gtk.keysyms.BackSpace)): + and event.keyval in [Gdk.KEY_Delete, Gdk.KEY_BackSpace]): self.wid_text.set_text('') return False @@ -272,7 +271,7 @@ class Many2One(Widget): # Restore text and position after display self.wid_text.set_text(text) self.wid_text.set_position(position) - gobject.idle_add(clean) + GLib.idle_add(clean) return False def get_value(self): @@ -310,11 +309,11 @@ class Many2One(Widget): if not self.wid_text.get_editable(): icon2, tooltip2 = None, '' for pos, icon, tooltip in [ - (gtk.ENTRY_ICON_PRIMARY, icon1, tooltip1), - (gtk.ENTRY_ICON_SECONDARY, icon2, tooltip2)]: + (Gtk.EntryIconPosition.PRIMARY, icon1, tooltip1), + (Gtk.EntryIconPosition.SECONDARY, icon2, tooltip2)]: if icon: pixbuf = common.IconFactory.get_pixbuf( - icon, gtk.ICON_SIZE_MENU) + icon, Gtk.IconSize.MENU) else: pixbuf = None self.wid_text.set_icon_from_pixbuf(pos, pixbuf) @@ -325,7 +324,7 @@ class Many2One(Widget): value = self.field.get(self.record) if self.has_target(value): # Delay filling of popup as it can take time - gobject.idle_add(populate, menu, self.get_model(), + GLib.idle_add(populate, menu, self.get_model(), self.id_from_value(value), '', self.field) return True @@ -345,7 +344,7 @@ class Many2One(Widget): rec_name, record_id = model.get(iter_, 0, 1) # GTK on win32 doesn't like synchronous call to set_client # because it triggers a display which reset the completion - gobject.idle_add(self.field.set_client, self.record, + GLib.idle_add(self.field.set_client, self.record, self.value_from_id(record_id, rec_name), True) completion_model = self.wid_completion.get_model() diff --git a/tryton/gui/window/view_form/view/form_gtk/multiselection.py b/tryton/gui/window/view_form/view/form_gtk/multiselection.py index 0699fca89f..3eda1cd548 100644 --- a/tryton/gui/window/view_form/view/form_gtk/multiselection.py +++ b/tryton/gui/window/view_form/view/form_gtk/multiselection.py @@ -1,7 +1,6 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of this # repository contains the full copyright notices and license terms. -import gtk -import gobject +from gi.repository import GLib, GObject, Gtk from .widget import Widget from tryton.common.selection import SelectionMixin @@ -15,27 +14,28 @@ class MultiSelection(Widget, SelectionMixin): super(MultiSelection, self).__init__(view, attrs) if int(attrs.get('yexpand', self.expand)): - self.widget = gtk.ScrolledWindow() - self.widget.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.widget.set_shadow_type(gtk.SHADOW_ETCHED_IN) + self.widget = Gtk.ScrolledWindow() + self.widget.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + self.widget.set_shadow_type(Gtk.ShadowType.ETCHED_IN) else: - self.widget = gtk.VBox() + self.widget = Gtk.VBox() self.widget.set_size_request(100, 100) self.widget.get_accessible().set_name(attrs.get('string', '')) - self.model = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING) + self.model = Gtk.ListStore(GObject.TYPE_INT, GObject.TYPE_STRING) self.tree = self.mnemonic_widget = TreeViewControl() self.tree.set_model(self.model) self.tree.set_search_column(1) self.tree.connect('focus-out-event', lambda *a: self._focus_out()) self.tree.set_headers_visible(False) selection = self.tree.get_selection() - selection.set_mode(gtk.SELECTION_MULTIPLE) + selection.set_mode(Gtk.SelectionMode.MULTIPLE) selection.connect('changed', self.changed) self.widget.add(self.tree) - name_column = gtk.TreeViewColumn() - name_cell = gtk.CellRendererText() - name_column.pack_start(name_cell) + name_column = Gtk.TreeViewColumn() + name_cell = Gtk.CellRendererText() + name_column.pack_start(name_cell, expand=True) name_column.add_attribute(name_cell, 'text', 1) self.tree.append_column(name_column) @@ -61,7 +61,7 @@ class MultiSelection(Widget, SelectionMixin): if self.widget.props.window: self._focus_out() # Must be deferred because it triggers a display of the form - gobject.idle_add(focus_out) + GLib.idle_add(focus_out) def get_value(self): model, paths = self.tree.get_selection().get_selected_rows() diff --git a/tryton/gui/window/view_form/view/form_gtk/one2many.py b/tryton/gui/window/view_form/view/form_gtk/one2many.py index 42a032e5c4..b49874e3a4 100644 --- a/tryton/gui/window/view_form/view/form_gtk/one2many.py +++ b/tryton/gui/window/view_form/view/form_gtk/one2many.py @@ -1,9 +1,10 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk import gettext import itertools +from gi.repository import Gdk, Gtk + from .widget import Widget from tryton.gui.window.view_form.screen import Screen from tryton.gui.window.win_search import WinSearch @@ -22,66 +23,66 @@ class One2Many(Widget): def __init__(self, view, attrs): super(One2Many, self).__init__(view, attrs) - self.widget = gtk.Frame() - self.widget.set_shadow_type(gtk.SHADOW_NONE) + self.widget = Gtk.Frame() + self.widget.set_shadow_type(Gtk.ShadowType.NONE) self.widget.get_accessible().set_name(attrs.get('string', '')) - vbox = gtk.VBox(homogeneous=False, spacing=2) + vbox = Gtk.VBox(homogeneous=False, spacing=2) self.widget.add(vbox) self._readonly = True self._required = False self._position = 0 self._length = 0 - self.title_box = hbox = gtk.HBox(homogeneous=False, spacing=0) + self.title_box = hbox = Gtk.HBox(homogeneous=False, spacing=0) hbox.set_border_width(2) - self.title = gtk.Label(set_underline(attrs.get('string', ''))) - self.title.set_use_underline(True) - self.title.set_alignment(0.0, 0.5) - hbox.pack_start(self.title, expand=True, fill=True) + self.title = Gtk.Label( + label=set_underline(attrs.get('string', '')), + use_underline=True, halign=Gtk.Align.START) + hbox.pack_start(self.title, expand=True, fill=True, padding=0) - hbox.pack_start(gtk.VSeparator(), expand=False, fill=True) + hbox.pack_start(Gtk.VSeparator(), expand=False, fill=True, padding=0) tooltips = common.Tooltips() - but_switch = gtk.Button() + but_switch = Gtk.Button() tooltips.set_tip(but_switch, _('Switch')) but_switch.connect('clicked', self.switch_view) but_switch.add(common.IconFactory.get_image( - 'tryton-switch', gtk.ICON_SIZE_SMALL_TOOLBAR)) - but_switch.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(but_switch, expand=False, fill=False) + 'tryton-switch', Gtk.IconSize.SMALL_TOOLBAR)) + but_switch.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(but_switch, expand=False, fill=False, padding=0) - self.but_pre = gtk.Button() + self.but_pre = Gtk.Button() tooltips.set_tip(self.but_pre, _('Previous')) self.but_pre.connect('clicked', self._sig_previous) self.but_pre.add(common.IconFactory.get_image( - 'tryton-back', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_pre.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_pre, expand=False, fill=False) + 'tryton-back', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_pre.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_pre, expand=False, fill=False, padding=0) - self.label = gtk.Label('(0,0)') - hbox.pack_start(self.label, expand=False, fill=False) + self.label = Gtk.Label(label='(0,0)') + hbox.pack_start(self.label, expand=False, fill=False, padding=0) - self.but_next = gtk.Button() + self.but_next = Gtk.Button() tooltips.set_tip(self.but_next, _('Next')) self.but_next.connect('clicked', self._sig_next) self.but_next.add(common.IconFactory.get_image( - 'tryton-forward', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_next.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_next, expand=False, fill=False) + 'tryton-forward', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_next.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_next, expand=False, fill=False, padding=0) - hbox.pack_start(gtk.VSeparator(), expand=False, fill=True) + hbox.pack_start(Gtk.VSeparator(), expand=False, fill=True, padding=0) self.focus_out = True self.wid_completion = None if attrs.get('add_remove'): - self.wid_text = gtk.Entry() + self.wid_text = Gtk.Entry() self.wid_text.set_placeholder_text(_('Search')) self.wid_text.set_property('width_chars', 13) self.wid_text.connect('focus-out-event', self._focus_out) - hbox.pack_start(self.wid_text, expand=True, fill=True) + hbox.pack_start(self.wid_text, expand=True, fill=True, padding=0) if int(self.attrs.get('completion', 1)): access = common.MODELACCESS[attrs['relation']] @@ -95,56 +96,58 @@ class One2Many(Widget): self.wid_text.set_completion(self.wid_completion) self.wid_text.connect('changed', self._update_completion) - self.but_add = gtk.Button() + self.but_add = Gtk.Button() tooltips.set_tip(self.but_add, _('Add existing record')) self.but_add.connect('clicked', self._sig_add) self.but_add.add(common.IconFactory.get_image( - 'tryton-add', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_add.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_add, expand=False, fill=False) + 'tryton-add', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_add.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_add, expand=False, fill=False, padding=0) - self.but_remove = gtk.Button() + self.but_remove = Gtk.Button() tooltips.set_tip(self.but_remove, _('Remove selected record')) self.but_remove.connect('clicked', self._sig_remove, True) self.but_remove.add(common.IconFactory.get_image( - 'tryton-remove', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_remove.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_remove, expand=False, fill=False) + 'tryton-remove', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_remove.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start( + self.but_remove, expand=False, fill=False, padding=0) - hbox.pack_start(gtk.VSeparator(), expand=False, fill=True) + hbox.pack_start( + Gtk.VSeparator(), expand=False, fill=True, padding=0) - self.but_new = gtk.Button() + self.but_new = Gtk.Button() tooltips.set_tip(self.but_new, _('Create a new record ')) self.but_new.connect('clicked', self._sig_new) self.but_new.add(common.IconFactory.get_image( - 'tryton-create', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_new.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_new, expand=False, fill=False) + 'tryton-create', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_new.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_new, expand=False, fill=False, padding=0) - self.but_open = gtk.Button() + self.but_open = Gtk.Button() tooltips.set_tip(self.but_open, _('Edit selected record ')) self.but_open.connect('clicked', self._sig_edit) self.but_open.add(common.IconFactory.get_image( - 'tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_open.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_open, expand=False, fill=False) + 'tryton-open', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_open.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_open, expand=False, fill=False, padding=0) - self.but_del = gtk.Button() + self.but_del = Gtk.Button() tooltips.set_tip(self.but_del, _('Delete selected record ')) self.but_del.connect('clicked', self._sig_remove, False) self.but_del.add(common.IconFactory.get_image( - 'tryton-delete', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_del.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_del, expand=False, fill=False) + 'tryton-delete', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_del.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_del, expand=False, fill=False, padding=0) - self.but_undel = gtk.Button() + self.but_undel = Gtk.Button() tooltips.set_tip(self.but_undel, _('Undelete selected record ')) self.but_undel.connect('clicked', self._sig_undelete) self.but_undel.add(common.IconFactory.get_image( - 'tryton-undo', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_undel.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_undel, expand=False, fill=False) + 'tryton-undo', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_undel.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_undel, expand=False, fill=False, padding=0) if attrs.get('add_remove'): hbox.set_focus_chain([self.wid_text]) @@ -153,10 +156,10 @@ class One2Many(Widget): tooltips.enable() - frame = gtk.Frame() + frame = Gtk.Frame() frame.add(hbox) - frame.set_shadow_type(gtk.SHADOW_OUT) - vbox.pack_start(frame, expand=False, fill=True) + frame.set_shadow_type(Gtk.ShadowType.OUT) + vbox.pack_start(frame, expand=False, fill=True, padding=0) self.screen = Screen(attrs['relation'], mode=attrs.get('mode', 'tree,form').split(','), @@ -168,7 +171,7 @@ class One2Many(Widget): self.screen.pre_validate = bool(int(attrs.get('pre_validate', 0))) self.screen.signal_connect(self, 'record-message', self._sig_label) - vbox.pack_start(self.screen.widget, expand=True, fill=True) + vbox.pack_start(self.screen.widget, expand=True, fill=True, padding=0) self.title.set_mnemonic_widget( self.screen.current_view.mnemonic_widget) @@ -180,27 +183,27 @@ class One2Many(Widget): but_switch.props.sensitive = self.screen.number_of_views > 1 def on_keypress(self, widget, event): - if (event.keyval == gtk.keysyms.F3) \ - and self.but_new.get_property('sensitive'): + if ((event.keyval == Gdk.KEY_F3) + and self.but_new.get_property('sensitive')): self._sig_new(widget) return True - if event.keyval == gtk.keysyms.F2 \ - and widget == self.screen.widget: + if (event.keyval == Gdk.KEY_F2 + and widget == self.screen.widget): self._sig_edit(widget) return True - if (event.keyval in (gtk.keysyms.Delete, gtk.keysyms.KP_Delete) + if (event.keyval in [Gdk.KEY_Delete, Gdk.KEY_KP_Delete] and widget == self.screen.widget and self.but_del.get_property('sensitive')): self._sig_remove(widget) return True - if event.keyval == gtk.keysyms.Insert and widget == self.screen.widget: + if event.keyval == Gdk.KEY_Insert and widget == self.screen.widget: self._sig_undelete(widget) return True if self.attrs.get('add_remove'): editable = self.wid_text.get_editable() - activate_keys = [gtk.keysyms.Tab, gtk.keysyms.ISO_Left_Tab] + activate_keys = [Gdk.KEY_Tab, Gdk.KEY_ISO_Left_Tab] if not self.wid_completion: - activate_keys.append(gtk.keysyms.Return) + activate_keys.append(Gdk.KEY_Return) if (widget == self.wid_text and event.keyval in activate_keys and editable diff --git a/tryton/gui/window/view_form/view/form_gtk/progressbar.py b/tryton/gui/window/view_form/view/form_gtk/progressbar.py index 69c90de225..8433d8c579 100644 --- a/tryton/gui/window/view_form/view/form_gtk/progressbar.py +++ b/tryton/gui/window/view_form/view/form_gtk/progressbar.py @@ -1,8 +1,9 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk import gettext +from gi.repository import Gtk + from .widget import Widget _ = gettext.gettext @@ -11,18 +12,19 @@ _ = gettext.gettext class ProgressBar(Widget): 'Progress Bar' orientations = { - 'left_to_right': gtk.PROGRESS_LEFT_TO_RIGHT, - 'right_to_left': gtk.PROGRESS_RIGHT_TO_LEFT, - 'bottom_to_top': gtk.PROGRESS_BOTTOM_TO_TOP, - 'top_to_bottom': gtk.PROGRESS_TOP_TO_BOTTOM, + 'left_to_right': (Gtk.Orientation.HORIZONTAL, False), + 'right_to_left': (Gtk.Orientation.HORIZONTAL, True), + 'bottom_to_top': (Gtk.Orientation.VERTICAL, True), + 'top_to_bottom': (Gtk.Orientation.VERTICAL, False), } def __init__(self, view, attrs): super(ProgressBar, self).__init__(view, attrs) - self.widget = self.mnemonic_widget = gtk.ProgressBar() - orientation = self.orientations.get(attrs.get('orientation', - 'left_to_right'), gtk.PROGRESS_LEFT_TO_RIGHT) + self.widget = self.mnemonic_widget = Gtk.ProgressBar() + orientation, inverted = self.orientations.get( + attrs.get('orientation', 'left_to_right')) self.widget.set_orientation(orientation) + self.widget.set_prinverted(inverted) def display(self): super(ProgressBar, self).display() diff --git a/tryton/gui/window/view_form/view/form_gtk/reference.py b/tryton/gui/window/view_form/view/form_gtk/reference.py index e0c694ef05..bb03a29865 100644 --- a/tryton/gui/window/view_form/view/form_gtk/reference.py +++ b/tryton/gui/window/view_form/view/form_gtk/reference.py @@ -1,8 +1,9 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk import gettext +from gi.repository import Gtk + from .many2one import Many2One from tryton.common.selection import SelectionMixin, PopdownMixin, \ selection_shortcuts @@ -16,7 +17,7 @@ class Reference(Many2One, SelectionMixin, PopdownMixin): def __init__(self, view, attrs): super(Reference, self).__init__(view, attrs) - self.widget_combo = gtk.ComboBoxEntry() + self.widget_combo = Gtk.ComboBox(has_entry=True) child = self.widget_combo.get_child() child.connect('activate', lambda *a: self._focus_out()) child.connect('focus-out-event', lambda *a: self._focus_out()) @@ -24,11 +25,13 @@ class Reference(Many2One, SelectionMixin, PopdownMixin): self.widget_combo.connect('changed', self.sig_changed_combo) self.widget_combo.connect('move-active', self._move_active) self.widget_combo.connect( - 'scroll-event', lambda c, e: c.emit_stop_by_name('scroll-event')) + 'scroll-event', + lambda c, e: c.stop_emission_by_name('scroll-event')) selection_shortcuts(self.widget_combo) self.widget_combo.set_focus_chain([child]) - self.widget.pack_start(self.widget_combo, expand=False, fill=True) + self.widget.pack_start( + self.widget_combo, expand=False, fill=True, padding=0) self.init_selection() self.set_popdown(self.selection, self.widget_combo) @@ -51,13 +54,14 @@ class Reference(Many2One, SelectionMixin, PopdownMixin): def _move_active(self, combobox, scroll_type): if not combobox.get_child().get_editable(): - combobox.emit_stop_by_name('move-active') + combobox.stop_emission_by_name('move-active') def _set_button_sensitive(self): super(Reference, self)._set_button_sensitive() self.widget_combo.get_child().set_editable(not self._readonly) self.widget_combo.set_button_sensitivity( - gtk.SENSITIVITY_OFF if self._readonly else gtk.SENSITIVITY_AUTO) + Gtk.SensitivityType.OFF if self._readonly + else Gtk.SensitivityType.AUTO) if self._readonly and CONFIG['client.fast_tabbing']: self.widget.set_focus_chain([]) else: diff --git a/tryton/gui/window/view_form/view/form_gtk/richtextbox.py b/tryton/gui/window/view_form/view/form_gtk/richtextbox.py index 495640a417..a480b6583a 100644 --- a/tryton/gui/window/view_form/view/form_gtk/richtextbox.py +++ b/tryton/gui/window/view_form/view/form_gtk/richtextbox.py @@ -3,7 +3,7 @@ from gettext import gettext as _ from weakref import WeakKeyDictionary -import gtk +from gi.repository import Gtk from .textbox import TextBox from tryton.common import get_toplevel_window, IconFactory @@ -25,71 +25,70 @@ class RichTextBox(TextBox): self.colors = {} if int(self.attrs.get('toolbar', 1)): self.toolbar = self.get_toolbar(self.textview) - self.widget.pack_start(self.toolbar, expand=False, fill=True) + self.widget.pack_start( + self.toolbar, expand=False, fill=True, padding=0) def get_toolbar(self, textview): - toolbar = gtk.Toolbar() + toolbar = Gtk.Toolbar() toolbar.set_style({ 'default': False, - 'both': gtk.TOOLBAR_BOTH, - 'text': gtk.TOOLBAR_TEXT, - 'icons': gtk.TOOLBAR_ICONS}[CONFIG['client.toolbar']]) + 'both': Gtk.ToolbarStyle.BOTH, + 'text': Gtk.ToolbarStyle.TEXT, + 'icons': Gtk.ToolbarStyle.ICONS, + }[CONFIG['client.toolbar']]) tag_widgets = self.tag_widgets[textview] = {} for icon in ['bold', 'italic', 'underline']: - button = gtk.ToggleToolButton() + button = Gtk.ToggleToolButton() button.set_icon_widget(IconFactory.get_image( 'tryton-format-%s' % icon, - gtk.ICON_SIZE_SMALL_TOOLBAR)) + Gtk.IconSize.SMALL_TOOLBAR)) button.connect('toggled', self.toggle_props, icon, textview) toolbar.insert(button, -1) tag_widgets[icon] = button - toolbar.insert(gtk.SeparatorToolItem(), -1) + toolbar.insert(Gtk.SeparatorToolItem(), -1) for name, options, active in [ ('family', FAMILIES, FAMILIES.index('normal')), ('size', SIZES, SIZES.index('4')), ]: - try: - combobox = gtk.ComboBoxText() - except AttributeError: - combobox = gtk.combo_box_new_text() + combobox = Gtk.ComboBoxText() for option in options: combobox.append_text(option) combobox.set_active(active) combobox.set_focus_on_click(False) combobox.connect('changed', self.change_props, name, textview) - tool = gtk.ToolItem() + tool = Gtk.ToolItem() tool.add(combobox) toolbar.insert(tool, -1) tag_widgets[name] = combobox - toolbar.insert(gtk.SeparatorToolItem(), -1) + toolbar.insert(Gtk.SeparatorToolItem(), -1) button = None for name in ['left', 'center', 'right', 'justify']: icon = 'tryton-format-align-%s' % name - button = gtk.RadioToolButton.new_from_widget(button) + button = Gtk.RadioToolButton.new_from_widget(button) button.set_icon_widget(IconFactory.get_image( - icon, gtk.ICON_SIZE_SMALL_TOOLBAR)) + icon, Gtk.IconSize.SMALL_TOOLBAR)) button.set_active(icon == 'left') button.connect( 'toggled', self.toggle_justification, name, textview) toolbar.insert(button, -1) tag_widgets[name] = button - toolbar.insert(gtk.SeparatorToolItem(), -1) + toolbar.insert(Gtk.SeparatorToolItem(), -1) for icon, label in [ ('foreground', _('Foreground')), # TODO ('background', _('Background')), ]: - button = gtk.ToolButton() + button = Gtk.ToolButton() if icon == 'foreground': button.set_icon_widget(IconFactory.get_image( 'tryton-format-color-text', - gtk.ICON_SIZE_SMALL_TOOLBAR)) + Gtk.IconSize.SMALL_TOOLBAR)) button.set_label(label) button.connect('clicked', self.toggle_color, icon, textview) toolbar.insert(button, -1) @@ -114,7 +113,7 @@ class RichTextBox(TextBox): textview = widget.get_children()[-1].get_child() if self.toolbar: widget.pack_start( - self.get_toolbar(textview), expand=False, fill=True) + self.get_toolbar(textview), expand=False, fill=True, padding=0) return widget def translate_widget_set_readonly(self, widget, value): @@ -266,19 +265,19 @@ class RichTextBox(TextBox): def _apply_tool(self, text_buffer, name, tool, start, end): # First test RadioToolButton as they inherit from ToggleToolButton - if isinstance(tool, gtk.RadioToolButton): + if isinstance(tool, Gtk.RadioToolButton): name = 'justification %s' % name if not tool.get_active(): remove_tags(text_buffer, start, end, name) else: remove_tags(text_buffer, start, end, 'justification') text_buffer.apply_tag_by_name(name, start, end) - elif isinstance(tool, gtk.ToggleToolButton): + elif isinstance(tool, Gtk.ToggleToolButton): if tool.get_active(): text_buffer.apply_tag_by_name(name, start, end) else: text_buffer.remove_tag_by_name(name, start, end) - elif isinstance(tool, gtk.ComboBox): + elif isinstance(tool, Gtk.ComboBoxText): value = tool.get_active_text() remove_tags(text_buffer, start, end, name) name = '%s %s' % (name, value) @@ -325,14 +324,14 @@ class RichTextBox(TextBox): start = start.get_offset() end = end.get_offset() - dialog = gtk.ColorSelectionDialog(_('Select a color')) + dialog = Gtk.ColorSelectionDialog(_('Select a color')) dialog.set_transient_for(get_toplevel_window()) colorsel = dialog.get_color_selection() colorsel.set_has_palette(True) color = self.colors.get(name) if color: colorsel.set_current_color(color) - if dialog.run() == gtk.RESPONSE_OK: + if dialog.run() == Gtk.ResponseType.OK: color = colorsel.get_current_color() self.colors[name] = color if start is not None and end is not None: diff --git a/tryton/gui/window/view_form/view/form_gtk/selection.py b/tryton/gui/window/view_form/view/form_gtk/selection.py index f8aa9f0309..628d3a2ae0 100644 --- a/tryton/gui/window/view_form/view/form_gtk/selection.py +++ b/tryton/gui/window/view_form/view/form_gtk/selection.py @@ -1,7 +1,6 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk -import gobject +from gi.repository import GLib, Gtk from .widget import Widget from tryton.common.selection import SelectionMixin, selection_shortcuts, \ @@ -14,8 +13,8 @@ class Selection(Widget, SelectionMixin, PopdownMixin): def __init__(self, view, attrs): super(Selection, self).__init__(view, attrs) - self.widget = gtk.HBox(spacing=3) - self.entry = gtk.ComboBoxEntry() + self.widget = Gtk.HBox(spacing=3) + self.entry = Gtk.ComboBox(has_entry=True) child = self.mnemonic_widget = self.entry.get_child() child.set_property('activates_default', True) child.set_max_length(int(attrs.get('size', 0))) @@ -27,8 +26,9 @@ class Selection(Widget, SelectionMixin, PopdownMixin): self.entry.connect('changed', self.changed) self.entry.connect('move-active', self._move_active) self.entry.connect( - 'scroll-event', lambda c, e: c.emit_stop_by_name('scroll-event')) - self.widget.pack_start(self.entry) + 'scroll-event', + lambda c, e: c.stop_emission_by_name('scroll-event')) + self.widget.pack_start(self.entry, expand=True, fill=True, padding=0) self.widget.set_focus_chain([child]) self.selection = attrs.get('selection', [])[:] @@ -41,17 +41,17 @@ class Selection(Widget, SelectionMixin, PopdownMixin): if combobox.props.window: self._focus_out() # Must be deferred because it triggers a display of the form - gobject.idle_add(focus_out) + GLib.idle_add(focus_out) def _move_active(self, combobox, scroll_type): if not combobox.get_child().get_editable(): - combobox.emit_stop_by_name('move-active') + combobox.stop_emission_by_name('move-active') def _readonly_set(self, value): super(Selection, self)._readonly_set(value) self.entry.get_child().set_editable(not value) self.entry.set_button_sensitivity( - gtk.SENSITIVITY_OFF if value else gtk.SENSITIVITY_AUTO) + Gtk.SensitivityType.OFF if value else Gtk.SensitivityType.AUTO) if value and CONFIG['client.fast_tabbing']: self.widget.set_focus_chain([]) else: diff --git a/tryton/gui/window/view_form/view/form_gtk/state_widget.py b/tryton/gui/window/view_form/view/form_gtk/state_widget.py index 30e0bf2d5a..ae7cb79468 100644 --- a/tryton/gui/window/view_form/view/form_gtk/state_widget.py +++ b/tryton/gui/window/view_form/view/form_gtk/state_widget.py @@ -1,6 +1,6 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk +from gi.repository import Gtk import tryton.common as common @@ -22,7 +22,7 @@ class StateMixin(object): self.show() -class Label(StateMixin, gtk.Label): +class Label(StateMixin, Gtk.Label): def state_set(self, record): super(Label, self).state_set(record) @@ -47,11 +47,11 @@ class Label(StateMixin, gtk.Label): common.apply_label_attributes(self, readonly, required) -class VBox(StateMixin, gtk.VBox): +class VBox(StateMixin, Gtk.VBox): pass -class Image(StateMixin, gtk.Image): +class Image(StateMixin, Gtk.Image): def state_set(self, record): super(Image, self).state_set(record) @@ -62,21 +62,21 @@ class Image(StateMixin, gtk.Image): field = record.group.fields[name] name = field.get(record) self.set_from_pixbuf(common.IconFactory.get_pixbuf( - name, gtk.ICON_SIZE_DIALOG)) + name, Gtk.IconSize.DIALOG)) -class Frame(StateMixin, gtk.Frame): +class Frame(StateMixin, Gtk.Frame): def __init__(self, label=None, attrs=None): if not label: # label must be None to have no label widget label = None super(Frame, self).__init__(label=label, attrs=attrs) if not label: - self.set_shadow_type(gtk.SHADOW_NONE) + self.set_shadow_type(Gtk.ShadowType.NONE) self.set_border_width(0) -class ScrolledWindow(StateMixin, gtk.ScrolledWindow): +class ScrolledWindow(StateMixin, Gtk.ScrolledWindow): def state_set(self, record): # Force to show first to ensure it is displayed in the Notebook @@ -84,7 +84,7 @@ class ScrolledWindow(StateMixin, gtk.ScrolledWindow): super(ScrolledWindow, self).state_set(record) -class Notebook(StateMixin, gtk.Notebook): +class Notebook(StateMixin, Gtk.Notebook): def state_set(self, record): super(Notebook, self).state_set(record) @@ -98,20 +98,20 @@ class Notebook(StateMixin, gtk.Notebook): widget._readonly_set(True) -class Alignment(gtk.Alignment): +class Alignment(Gtk.Alignment): def __init__(self, widget, attrs): - super(Alignment, self).__init__( - float(attrs.get('xalign', 0.0)), - float(attrs.get('yalign', 0.5)), - float(attrs.get('xexpand', 1.0)), - float(attrs.get('yexpand', 1.0))) + super(Alignment, self).__init__() + self.props.xalign = float(attrs.get('xalign', 0.0)) + self.props.yalign = float(attrs.get('yalign', 0.5)) + self.props.xscale = float(attrs.get('xexpand', 1.0)) + self.props.yscale = float(attrs.get('yexpand', 1.0)) self.add(widget) widget.connect('show', lambda *a: self.show()) widget.connect('hide', lambda *a: self.hide()) -class Expander(StateMixin, gtk.Expander): +class Expander(StateMixin, Gtk.Expander): def __init__(self, label=None, attrs=None): if not label: diff --git a/tryton/gui/window/view_form/view/form_gtk/textbox.py b/tryton/gui/window/view_form/view/form_gtk/textbox.py index eb1ecd80d8..7398e3dc81 100644 --- a/tryton/gui/window/view_form/view/form_gtk/textbox.py +++ b/tryton/gui/window/view_form/view/form_gtk/textbox.py @@ -2,15 +2,16 @@ # this repository contains the full copyright notices and license terms. import logging -import gtk -from .widget import Widget, TranslateMixin -from tryton.config import CONFIG - +from gi.repository import Gtk try: from gi.repository import GtkSpell except ImportError: GtkSpell = None +from .widget import Widget, TranslateMixin +from tryton.config import CONFIG + + logger = logging.getLogger(__name__) @@ -20,11 +21,11 @@ class TextBox(Widget, TranslateMixin): def __init__(self, view, attrs): super(TextBox, self).__init__(view, attrs) - self.widget = gtk.VBox() - self.scrolledwindow = gtk.ScrolledWindow() - self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) - self.scrolledwindow.set_shadow_type(gtk.SHADOW_ETCHED_IN) + self.widget = Gtk.VBox() + self.scrolledwindow = Gtk.ScrolledWindow() + self.scrolledwindow.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + self.scrolledwindow.set_shadow_type(Gtk.ShadowType.ETCHED_IN) self.scrolledwindow.set_size_request(100, 100) self.textview = self.mnemonic_widget = self._get_textview() @@ -37,33 +38,35 @@ class TextBox(Widget, TranslateMixin): self.button = None if attrs.get('translate'): self.button = self.translate_button() - self.widget.pack_end(self.button, False, False) + self.widget.pack_end( + self.button, expand=False, fill=False, padding=0) - self.widget.pack_end(self.scrolledwindow) + self.widget.pack_end( + self.scrolledwindow, expand=True, fill=True, padding=0) def _get_textview(self): if self.attrs.get('size'): textbuffer = TextBufferLimitSize(int(self.attrs['size'])) - textview = gtk.TextView() + textview = Gtk.TextView() textview.set_buffer(textbuffer) else: - textview = gtk.TextView() - textview.set_wrap_mode(gtk.WRAP_WORD) + textview = Gtk.TextView() + textview.set_wrap_mode(Gtk.WrapMode.WORD) # TODO better tab solution textview.set_accepts_tab(False) return textview def translate_widget(self): - box = gtk.VBox() - scrolledwindow = gtk.ScrolledWindow() - scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) - scrolledwindow.set_shadow_type(gtk.SHADOW_ETCHED_IN) + box = Gtk.VBox() + scrolledwindow = Gtk.ScrolledWindow() + scrolledwindow.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scrolledwindow.set_shadow_type(Gtk.ShadowType.ETCHED_IN) scrolledwindow.set_size_request(-1, 80) textview = self._get_textview() scrolledwindow.add(textview) - box.pack_end(scrolledwindow) + box.pack_end(scrolledwindow, expand=True, fill=True, padding=0) return box def translate_widget_set(self, widget, value): @@ -141,7 +144,7 @@ class TextBox(Widget, TranslateMixin): checker.detach() -class TextBufferLimitSize(gtk.TextBuffer): +class TextBufferLimitSize(Gtk.TextBuffer): __gsignals__ = { 'insert-text': 'override', } @@ -154,4 +157,4 @@ class TextBufferLimitSize(gtk.TextBuffer): free_chars = self.max_length - self.get_char_count() text = text[0:free_chars] length = len(text) - return gtk.TextBuffer.do_insert_text(self, iter, text, length) + return Gtk.TextBuffer.do_insert_text(self, iter, text, length) diff --git a/tryton/gui/window/view_form/view/form_gtk/timedelta.py b/tryton/gui/window/view_form/view/form_gtk/timedelta.py index 7b684f8da5..371d0be0d4 100644 --- a/tryton/gui/window/view_form/view/form_gtk/timedelta.py +++ b/tryton/gui/window/view_form/view/form_gtk/timedelta.py @@ -1,6 +1,6 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk +from gi.repository import Gtk from tryton.config import CONFIG from tryton.common.entry_position import reset_position @@ -12,15 +12,15 @@ class TimeDelta(Widget): def __init__(self, view, attrs): super(TimeDelta, self).__init__(view, attrs) - self.widget = gtk.HBox() - self.entry = self.mnemonic_widget = gtk.Entry() + self.widget = Gtk.HBox() + self.entry = self.mnemonic_widget = Gtk.Entry() self.entry.set_alignment(1.0) self.entry.set_property('activates_default', True) self.entry.connect('activate', self.sig_activate) self.entry.connect('focus-out-event', lambda x, y: self._focus_out()) self.entry.connect('key-press-event', self.send_modified) - self.widget.pack_start(self.entry) + self.widget.pack_start(self.entry, expand=True, fill=True, padding=0) @property def modified(self): diff --git a/tryton/gui/window/view_form/view/form_gtk/url.py b/tryton/gui/window/view_form/view/form_gtk/url.py index 421417f243..ff98d0e3e2 100644 --- a/tryton/gui/window/view_form/view/form_gtk/url.py +++ b/tryton/gui/window/view_form/view/form_gtk/url.py @@ -1,8 +1,10 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk -from .char import Char import webbrowser + +from gi.repository import Gtk + +from .char import Char import tryton.common as common from tryton.config import CONFIG @@ -14,13 +16,13 @@ class URL(Char): super(URL, self).__init__(view, attrs) self.tooltips = common.Tooltips() - self.button = gtk.Button() + self.button = Gtk.Button() self.button.set_image(common.IconFactory.get_image( - 'tryton-public', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.button.set_relief(gtk.RELIEF_NONE) + 'tryton-public', Gtk.IconSize.SMALL_TOOLBAR)) + self.button.set_relief(Gtk.ReliefStyle.NONE) self.button.connect('clicked', self.button_clicked) - self.button.set_alignment(0.5, 0.5) - self.widget.pack_start(self.button, expand=False, fill=False) + self.widget.pack_start( + self.button, expand=False, fill=False, padding=0) self.widget.set_focus_chain([self.entry]) def display(self): @@ -34,7 +36,7 @@ class URL(Char): else: value = icon self.button.set_image(common.IconFactory.get_image( - value, gtk.ICON_SIZE_SMALL_TOOLBAR)) + value, Gtk.IconSize.SMALL_TOOLBAR)) def set_tooltips(self): value = self.entry.get_text() diff --git a/tryton/gui/window/view_form/view/form_gtk/widget.py b/tryton/gui/window/view_form/view/form_gtk/widget.py index 05b90960dc..f5fb56f591 100644 --- a/tryton/gui/window/view_form/view/form_gtk/widget.py +++ b/tryton/gui/window/view_form/view/form_gtk/widget.py @@ -1,9 +1,9 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk -import gobject import gettext +from gi.repository import Gdk, GLib, Gtk + import tryton.common as common from tryton.common import RPCExecute, RPCException from tryton.common import TRYTON_ICON @@ -84,9 +84,9 @@ class Widget(object): def get_value(): if not self.widget.props.window: return - gobject.timeout_add(300, send, self.get_value()) + GLib.timeout_add(300, send, self.get_value()) # Wait the current event is finished to retreive the value - gobject.idle_add(get_value) + GLib.idle_add(get_value) return False def invisible_set(self, value): @@ -135,44 +135,50 @@ class TranslateDialog(NoModal): def __init__(self, widget, languages, readonly): NoModal.__init__(self) self.widget = widget - self.win = gtk.Dialog(_('Translation'), self.parent, - gtk.DIALOG_DESTROY_WITH_PARENT) + self.win = Gtk.Dialog( + title=_('Translation'), transient_for=self.parent, + destroy_with_parent=True) Main().add_window(self.win) - self.win.set_position(gtk.WIN_POS_CENTER_ON_PARENT) + self.win.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self.win.set_icon(TRYTON_ICON) self.win.connect('response', self.response) self.win.set_default_size(-1, self.default_size()[1]) - self.accel_group = gtk.AccelGroup() + self.accel_group = Gtk.AccelGroup() self.win.add_accel_group(self.accel_group) cancel_button = self.win.add_button( - set_underline(_("Cancel")), gtk.RESPONSE_CANCEL) - cancel_button.set_image(common.IconFactory.get_image( - 'tryton-cancel', gtk.ICON_SIZE_BUTTON)) + set_underline(_("Cancel")), Gtk.ResponseType.CANCEL) + cancel_button.set_image( + common.IconFactory.get_image('tryton-cancel', Gtk.IconSize.BUTTON)) cancel_button.set_always_show_image(True) ok_button = self.win.add_button( - set_underline(_("OK")), gtk.RESPONSE_OK) - ok_button.set_image(common.IconFactory.get_image( - 'tryton-ok', gtk.ICON_SIZE_BUTTON)) + set_underline(_("OK")), Gtk.ResponseType.OK) + ok_button.set_image( + common.IconFactory.get_image('tryton-ok', Gtk.IconSize.BUTTON)) ok_button.set_always_show_image(True) ok_button.add_accelerator( - 'clicked', self.accel_group, gtk.keysyms.Return, - gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) + 'clicked', self.accel_group, Gdk.KEY_Return, + Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE) tooltips = common.Tooltips() self.widgets = {} - table = gtk.Table(len(languages), 4) + table = Gtk.Table(n_rows=len(languages), n_columns=4) table.set_homogeneous(False) table.set_col_spacings(3) table.set_row_spacings(2) table.set_border_width(1) for i, language in enumerate(languages): label = language['name'] + _(':') - label = gtk.Label(label) - label.set_alignment(1.0, 0.0 if self.widget.expand else 0.5) - table.attach(label, 0, 1, i, i + 1, xoptions=gtk.FILL, xpadding=2) + label = Gtk.Label( + label=label, + halign=Gtk.Alignment.END, + valign=(Gtk.Alignment.START if self.widget.expand + else Gtk.Alignment.FILL)) + table.attach( + label, 0, 1, i, i + 1, + xoptions=Gtk.AttachOptions.FILL, xpadding=2) context = dict( language=language['code'], @@ -201,31 +207,35 @@ class TranslateDialog(NoModal): self.widget.translate_widget_set_readonly(widget, True) yopt = 0 if self.widget.expand: - yopt = gtk.EXPAND | gtk.FILL + yopt = Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL table.attach(widget, 1, 2, i, i + 1, yoptions=yopt) - editing = gtk.CheckButton() + editing = Gtk.CheckButton() editing.connect('toggled', self.editing_toggled, widget) editing.props.sensitive = not readonly tooltips.set_tip(editing, _('Edit')) - table.attach(editing, 2, 3, i, i + 1, xoptions=gtk.FILL) - fuzzy = gtk.CheckButton() + table.attach( + editing, 2, 3, i, i + 1, xoptions=Gtk.AttachOptions.FILL) + fuzzy = Gtk.CheckButton() fuzzy.set_active(value != fuzzy_value) fuzzy.props.sensitive = False tooltips.set_tip(fuzzy, _('Fuzzy')) - table.attach(fuzzy, 4, 5, i, i + 1, xoptions=gtk.FILL) + table.attach( + fuzzy, 4, 5, i, i + 1, xoptions=Gtk.AttachOptions.FILL) self.widgets[language['code']] = (widget, editing, fuzzy) tooltips.enable() - vbox = gtk.VBox() - vbox.pack_start(table, self.widget.expand, True) - viewport = gtk.Viewport() - viewport.set_shadow_type(gtk.SHADOW_NONE) + vbox = Gtk.VBox() + vbox.pack_start(table, expand=self.widget.expand, fill=True, padding=0) + viewport = Gtk.Viewport() + viewport.set_shadow_type(Gtk.ShadowType.NONE) viewport.add(vbox) - scrolledwindow = gtk.ScrolledWindow() - scrolledwindow.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) - scrolledwindow.set_shadow_type(gtk.SHADOW_NONE) + scrolledwindow = Gtk.ScrolledWindow() + scrolledwindow.set_policy( + Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) + scrolledwindow.set_shadow_type(Gtk.ShadowType.NONE) scrolledwindow.add(viewport) - self.win.vbox.pack_start(scrolledwindow, True, True) + self.win.vbox.pack_start( + scrolledwindow, expand=True, fill=True, padding=0) self.win.show_all() self.register() @@ -236,7 +246,7 @@ class TranslateDialog(NoModal): not editing.get_active()) def response(self, win, response): - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: for code, widget in self.widgets.items(): widget, editing, fuzzy = widget if not editing.get_active(): @@ -271,10 +281,10 @@ class TranslateDialog(NoModal): class TranslateMixin: def translate_button(self): - button = gtk.Button() + button = Gtk.Button() button.set_image(common.IconFactory.get_image( - 'tryton-translate', gtk.ICON_SIZE_SMALL_TOOLBAR)) - button.set_relief(gtk.RELIEF_NONE) + 'tryton-translate', Gtk.IconSize.SMALL_TOOLBAR)) + button.set_relief(Gtk.ReliefStyle.NONE) button.connect('clicked', self.translate) return button diff --git a/tryton/gui/window/view_form/view/graph.py b/tryton/gui/window/view_form/view/graph.py index ba6272a319..a40e90ba37 100644 --- a/tryton/gui/window/view_form/view/graph.py +++ b/tryton/gui/window/view_form/view/graph.py @@ -2,9 +2,10 @@ # this repository contains the full copyright notices and license terms. import sys -import gtk import gettext +from gi.repository import Gtk + from . import View from .graph_gtk.bar import VerticalBar, HorizontalBar from .graph_gtk.line import Line @@ -54,7 +55,7 @@ class ViewGraph(View): Widget = self.get_widget(self.attributes.get('type', 'vbar')) widget = Widget(self, xfield, yfields) self.widgets['root'] = widget - event = gtk.EventBox() + event = Gtk.EventBox() event.add(widget) event.connect('button-press-event', self.button_press) return event @@ -99,44 +100,50 @@ class ViewGraph(View): def save(self, widget): parent = get_toplevel_window() - dia = gtk.Dialog(_('Image Size'), parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + dia = Gtk.Dialog( + title=_('Image Size'), transient_for=parent, modal=True, + destroy_with_parent=True) Main().add_window(dia) cancel_button = dia.add_button( - set_underline(_("Cancel")), gtk.RESPONSE_CANCEL) + set_underline(_("Cancel")), Gtk.ResponseType.CANCEL) cancel_button.set_image(IconFactory.get_image( - 'tryton-cancel', gtk.ICON_SIZE_BUTTON)) + 'tryton-cancel', Gtk.IconSize.BUTTON)) cancel_button.set_always_show_image(True) ok_button = dia.add_button( - set_underline(_("OK")), gtk.RESPONSE_OK) + set_underline(_("OK")), Gtk.ResponseType.OK) ok_button.set_image(IconFactory.get_image( - 'tryton-ok', gtk.ICON_SIZE_BUTTON)) + 'tryton-ok', Gtk.IconSize.BUTTON)) ok_button.set_always_show_image(True) dia.set_icon(TRYTON_ICON) - dia.set_default_response(gtk.RESPONSE_OK) + dia.set_default_response(Gtk.ResponseType.OK) - hbox = gtk.HBox(spacing=3) - dia.vbox.pack_start(hbox, False, True) + hbox = Gtk.HBox(spacing=3) + dia.vbox.pack_start(hbox, expand=False, fill=True, padding=0) - hbox.pack_start(gtk.Label(_('Width:')), False, True) - spinwidth = gtk.SpinButton() - spinwidth.configure(gtk.Adjustment(400.0, 0.0, sys.maxsize, 1.0, 10.0), + hbox.pack_start( + Gtk.Label(label=_('Width:')), expand=False, fill=True, padding=0) + spinwidth = Gtk.SpinButton() + spinwidth.configure(Gtk.Adjustment( + value=400.0, lower=0.0, upper=sys.maxsize, + step_increment=1.0, page_increment=10.0), climb_rate=1, digits=0) spinwidth.set_numeric(True) spinwidth.set_activates_default(True) - hbox.pack_start(spinwidth, True, True) + hbox.pack_start(spinwidth, expand=True, fill=True, padding=0) - hbox.pack_start(gtk.Label(_('Height:')), False, True) - spinheight = gtk.SpinButton() - spinheight.configure(gtk.Adjustment( - 200.0, 0.0, sys.maxsize, 1.0, 10.0), + hbox.pack_start( + Gtk.Label(label=_('Height:')), expand=False, fill=True, padding=0) + spinheight = Gtk.SpinButton() + spinheight.configure(Gtk.Adjustment( + value=200.0, lower=0.0, upper=sys.maxsize, + step_increment=1.0, page_increment=10.0), climb_rate=1, digits=0) spinheight.set_numeric(True) spinheight.set_activates_default(True) - hbox.pack_start(spinheight, True, True) + hbox.pack_start(spinheight, expand=True, fill=True, padding=0) dia.show_all() - filter = gtk.FileFilter() + filter = Gtk.FileFilter() filter.set_name(_('PNG image (*.png)')) filter.add_mime_type('image/png') filter.add_pattern('*.png') @@ -145,9 +152,10 @@ class ViewGraph(View): response = dia.run() width = spinwidth.get_value_as_int() height = spinheight.get_value_as_int() - if response == gtk.RESPONSE_OK: - filename = file_selection(_('Save As'), - action=gtk.FILE_CHOOSER_ACTION_SAVE, + if response == Gtk.ResponseType.OK: + filename = file_selection( + _('Save As'), + action=Gtk.FileChooserAction.SAVE, preview=False, filters=[filter]) if width and height and filename: @@ -158,8 +166,9 @@ class ViewGraph(View): filename, width, height) break except MemoryError: - message(_('Image size too large.'), dia, - gtk.MESSAGE_ERROR) + message( + _('Image size too large.'), dia, + Gtk.MessageType.ERROR) else: break parent.present() @@ -167,14 +176,15 @@ class ViewGraph(View): def button_press(self, widget, event): if event.button == 3: - menu = gtk.Menu() - item = gtk.ImageMenuItem(_('Save As...')) - item.set_image(IconFactory.get_image( - 'tryton-save-as', gtk.ICON_SIZE_MENU)) + menu = Gtk.Menu() + item = Gtk.MenuItem(label=_('Save As...')) item.connect('activate', self.save) item.show() menu.append(item) - menu.popup(None, None, None, event.button, event.time) + if hasattr(menu, 'popup_at_pointer'): + menu.popup_at_pointer(event) + else: + menu.popup(None, None, None, event.button, event.time) return True elif event.button == 1: self.widgets['root'].action() diff --git a/tryton/gui/window/view_form/view/graph_gtk/graph.py b/tryton/gui/window/view_form/view/graph_gtk/graph.py index 029ac6669a..0b0e84948d 100644 --- a/tryton/gui/window/view_form/view/graph_gtk/graph.py +++ b/tryton/gui/window/view_form/view/graph_gtk/graph.py @@ -2,31 +2,31 @@ # this repository contains the full copyright notices and license terms. # This code is inspired by the pycha project # (http://www.lorenzogil.com/projects/pycha/) -import gtk - -from functools import reduce -from tryton.common import hex2rgb, generateColorscheme, \ - COLOR_SCHEMES -from tryton.pyson import PYSONDecoder +import datetime import locale import math -import datetime from dateutil.relativedelta import relativedelta -import tryton.rpc as rpc +from functools import reduce + import cairo +from gi.repository import Gdk, Gtk + +import tryton.rpc as rpc from tryton.action import Action +from tryton.common import hex2rgb, generateColorscheme, COLOR_SCHEMES from tryton.gui.window import Window +from tryton.pyson import PYSONDecoder class Popup(object): def __init__(self, widget): - self.win = gtk.Window(gtk.WINDOW_POPUP) + self.win = Gtk.Window(type=Gtk.WindowType.POPUP) self.win.set_name('gtk-tooltips') self.win.set_resizable(False) self.win.set_border_width(1) - self.win.set_transient_for(widget.window) - self.label = gtk.Label() + self.win.set_transient_for(widget.props.window) + self.label = Gtk.Label() self.win.add(self.label) self.win.connect('enter-notify-event', self.enter) @@ -34,7 +34,7 @@ class Popup(object): self.label.set_text(text) def set_position(self, widget, x, y): - widget_x, widget_y = widget.window.get_origin() + origin = widget.props.window.get_origin() allocation = widget.get_allocation() width, height = allocation.width, allocation.height popup_width, popup_height = self.win.get_size() @@ -42,14 +42,14 @@ class Popup(object): x = popup_width // 2 if x > width - popup_width // 2: x = width - popup_width // 2 - pos_x = widget_x + x - popup_width // 2 + pos_x = origin.x + x - popup_width // 2 if pos_x < 0: pos_x = 0 if y < popup_height + 5: y = popup_height + 5 if y > height: y = height - pos_y = widget_y + y - popup_height - 5 + pos_y = origin.y + y - popup_height - 5 if pos_y < 0: pos_y = 0 self.win.move(int(pos_x), int(pos_y)) @@ -67,7 +67,7 @@ class Popup(object): self.win.hide() -class Graph(gtk.DrawingArea): +class Graph(Gtk.DrawingArea): 'Graph' __gsignals__ = {"draw": "override"} @@ -82,7 +82,7 @@ class Graph(gtk.DrawingArea): self.bottomPadding = 15 self.rightPadding = 30 self.leftPadding = 30 - self.set_events(gtk.gdk.POINTER_MOTION_MASK) + self.set_events(Gdk.EventMask.POINTER_MOTION_MASK) self.connect('motion-notify-event', self.motion) self.connect('leave-notify-event', self.leave) self.popup = Popup(self) @@ -106,7 +106,6 @@ class Graph(gtk.DrawingArea): self.popup.hide() def do_draw(self, cr): - cr = self.window.cairo_create() width = self.get_allocated_width() height = self.get_allocated_height() @@ -142,10 +141,10 @@ class Graph(gtk.DrawingArea): del ctx['active_ids'] if 'active_id' in ctx: del ctx['active_id'] - event = gtk.get_current_event() + event = Gtk.get_current_event() allow_similar = False - if (event.state & gtk.gdk.CONTROL_MASK - or event.state & gtk.gdk.MOD1_MASK): + if (event.state & Gdk.ModifierType.CONTROL_MASK + or event.state & Gdk.ModifierType.MOD1_MASK): allow_similar = True with Window(hide_current=True, allow_similar=allow_similar): return Action.exec_keyword('graph_open', { diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py index 3893cf8916..643781e16c 100644 --- a/tryton/gui/window/view_form/view/list.py +++ b/tryton/gui/window/view_form/view/list.py @@ -1,7 +1,5 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gobject -import gtk import sys import json import locale @@ -9,6 +7,9 @@ import gettext from functools import wraps from collections import defaultdict +from gi.repository import Gdk, GLib, GObject, Gtk +from pygtkcompat.generictreemodel import GenericTreeModel + from tryton.config import CONFIG from tryton.common.cellrendererbutton import CellRendererButton from tryton.gui.window import Window @@ -37,7 +38,7 @@ def delay(func): if self.treeview.display_counter == display_counter: func(self, *args, **kwargs) display_counter = self.treeview.display_counter - gobject.idle_add(wait) + GLib.idle_add(wait) return wrapper @@ -57,7 +58,7 @@ def path_convert_id2pos(model, id_path): return tuple(indexes) -class AdaptModelGroup(gtk.GenericTreeModel): +class AdaptModelGroup(GenericTreeModel): def __init__(self, group, children_field=None): super(AdaptModelGroup, self).__init__() @@ -154,7 +155,7 @@ class AdaptModelGroup(gtk.GenericTreeModel): prev = record if prev: prev.next[id(self.group)] = None - path = gtk.TreePath() + path = Gtk.TreePath() # XXX pygobject does not allow to create empty TreePath, # it is always a path of 0 # see: https://bugzilla.gnome.org/show_bug.cgi?id=770665 @@ -168,7 +169,7 @@ class AdaptModelGroup(gtk.GenericTreeModel): def on_get_flags(self): if not self.children_field: - return gtk.TREE_MODEL_LIST_ONLY + return Gtk.TreeModelFlags.LIST_ONLY return 0 def on_get_n_columns(self): @@ -177,7 +178,7 @@ class AdaptModelGroup(gtk.GenericTreeModel): def on_get_column_type(self, index): # XXX - return gobject.TYPE_PYOBJECT + return GObject.TYPE_PYOBJECT def on_get_path(self, record): return record.get_index_path(self.group) @@ -258,14 +259,14 @@ class ViewTree(View): self.state_widgets = [] self.children_field = children_field self.sum_widgets = [] - self.sum_box = gtk.HBox() + self.sum_box = Gtk.HBox() self.reload = False if self.attributes.get('editable') and not screen.readonly: self.treeview = EditableTreeView(self.attributes['editable'], self) - grid_lines = gtk.TREE_VIEW_GRID_LINES_BOTH + grid_lines = Gtk.TreeViewGridLines.BOTH else: self.treeview = TreeView(self) - grid_lines = gtk.TREE_VIEW_GRID_LINES_VERTICAL + grid_lines = Gtk.TreeViewGridLines.VERTICAL self.mnemonic_widget = self.treeview self.parse(xml) @@ -273,7 +274,7 @@ class ViewTree(View): self.treeview.set_property('rules-hint', True) self.treeview.set_property('enable-grid-lines', grid_lines) self.treeview.set_fixed_height_mode( - all(c.get_sizing() == gtk.TREE_VIEW_COLUMN_FIXED + all(c.get_sizing() == Gtk.TreeViewColumnSizing.FIXED for c in self.treeview.get_columns())) self.treeview.connect('button-press-event', self.__button_press) self.treeview.connect('key-press-event', self.on_keypress) @@ -284,23 +285,25 @@ class ViewTree(View): self.treeview.set_rubber_banding(True) selection = self.treeview.get_selection() - selection.set_mode(gtk.SELECTION_MULTIPLE) + selection.set_mode(Gtk.SelectionMode.MULTIPLE) selection.connect('changed', self.__select_changed) self.set_drag_and_drop() - self.widget = gtk.VBox() - self.scroll = scroll = gtk.ScrolledWindow() + self.widget = Gtk.VBox() + self.scroll = scroll = Gtk.ScrolledWindow() scroll.add(self.treeview) - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scroll.set_placement(gtk.CORNER_TOP_LEFT) - viewport = gtk.Viewport() - viewport.set_shadow_type(gtk.SHADOW_ETCHED_IN) + scroll.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scroll.set_placement(Gtk.CornerType.TOP_LEFT) + viewport = Gtk.Viewport() + viewport.set_shadow_type(Gtk.ShadowType.ETCHED_IN) viewport.add(scroll) - self.widget.pack_start(viewport, expand=True, fill=True) + self.widget.pack_start(viewport, expand=True, fill=True, padding=0) self.sum_box.show() - self.widget.pack_start(self.sum_box, expand=False, fill=False) + self.widget.pack_start( + self.sum_box, expand=False, fill=False, padding=0) self.display() @@ -342,7 +345,7 @@ class ViewTree(View): widget = Widget(self, node_attrs) self.widgets[name].append(widget) - column = gtk.TreeViewColumn(node_attrs['string']) + column = Gtk.TreeViewColumn(node_attrs['string']) column._type = 'field' column.name = name @@ -394,7 +397,7 @@ class ViewTree(View): widget = Button(self, node_attrs) self.state_widgets.append(widget) - column = gtk.TreeViewColumn(node_attrs.get('string', ''), + column = Gtk.TreeViewColumn(node_attrs.get('string', ''), widget.renderer) column._type = 'button' column.name = None @@ -441,8 +444,8 @@ class ViewTree(View): def set_column_widget(self, column, field, attributes, arrow=True, align=0.5): - hbox = gtk.HBox(False, 2) - label = gtk.Label(attributes['string']) + hbox = Gtk.HBox(homogeneous=False, spacing=2) + label = Gtk.Label(label=attributes['string']) if field and self.editable: required = field.attrs.get('required') readonly = field.attrs.get('readonly') @@ -458,12 +461,14 @@ class ViewTree(View): tooltips.set_tip(label, help) tooltips.enable() if arrow: - arrow_widget = gtk.Arrow(gtk.ARROW_NONE, gtk.SHADOW_NONE) + arrow_widget = Gtk.Arrow( + arrow_type=Gtk.ArrowType.NONE, shadow_type=Gtk.ShadowType.NONE) arrow_widget.show() column.arrow = arrow_widget - hbox.pack_start(label, True, True, 0) + hbox.pack_start(label, expand=True, fill=True, padding=0) if arrow: - hbox.pack_start(arrow_widget, False, False, 0) + hbox.pack_start( + arrow_widget, expand=False, fill=False, padding=0) column.set_clickable(True) hbox.show() column.set_widget(hbox) @@ -505,7 +510,7 @@ class ViewTree(View): column.set_expand(expand) column.set_resizable(True) if attributes.get('widget') != 'text': - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) def get_column_widget(self, column): 'Return the widget of the column' @@ -517,30 +522,30 @@ class ViewTree(View): if 'sum' not in attributes: return text = attributes['sum'] + _(':') - label, sum_ = gtk.Label(text), gtk.Label() + label, sum_ = Gtk.Label(label=text), Gtk.Label() - hbox = gtk.HBox() + hbox = Gtk.HBox() hbox.pack_start(label, expand=True, fill=False, padding=2) hbox.pack_start(sum_, expand=True, fill=False, padding=2) hbox.show_all() - self.sum_box.pack_start(hbox, expand=False, fill=False) + self.sum_box.pack_start(hbox, expand=False, fill=False, padding=0) self.sum_widgets.append((attributes['name'], sum_)) def sort_model(self, column): for col in self.treeview.get_columns(): if col != column and getattr(col, 'arrow', None): - col.arrow.set(gtk.ARROW_NONE, gtk.SHADOW_NONE) + col.arrow.set(Gtk.ArrowType.NONE, Gtk.ShadowType.NONE) self.screen.order = self.screen.default_order - if column.arrow.props.arrow_type == gtk.ARROW_NONE: - column.arrow.set(gtk.ARROW_DOWN, gtk.SHADOW_IN) + if column.arrow.props.arrow_type == Gtk.ArrowType.NONE: + column.arrow.set(Gtk.ArrowType.DOWN, Gtk.ShadowType.IN) self.screen.order = [(column.name, 'ASC')] else: - if column.arrow.props.arrow_type == gtk.ARROW_DOWN: - column.arrow.set(gtk.ARROW_UP, gtk.SHADOW_IN) + if column.arrow.props.arrow_type == Gtk.ArrowType.DOWN: + column.arrow.set(Gtk.ArrowType.UP, Gtk.ShadowType.IN) self.screen.order = [(column.name, 'DESC')] else: - column.arrow.set(gtk.ARROW_NONE, gtk.SHADOW_NONE) + column.arrow.set(Gtk.ArrowType.NONE, Gtk.ShadowType.NONE) model = self.treeview.get_model() unsaved_records = [x for x in model.group if x.id < 0] search_string = self.screen.screen_container.get_text() or '' @@ -558,8 +563,8 @@ class ViewTree(View): if order and len(order) == 1: (name, direction), = order direction = { - 'ASC': gtk.ARROW_DOWN, - 'DESC': gtk.ARROW_UP, + 'ASC': Gtk.ArrowType.DOWN, + 'DESC': Gtk.ArrowType.UP, }[direction] else: name, direction = None, None @@ -568,19 +573,19 @@ class ViewTree(View): arrow = getattr(col, 'arrow', None) if arrow: if col.name != name: - arrow.set(gtk.ARROW_NONE, gtk.SHADOW_NONE) + arrow.set(Gtk.ArrowType.NONE, Gtk.ShadowType.NONE) else: - arrow.set(direction, gtk.SHADOW_IN) + arrow.set(direction, Gtk.ShadowType.IN) def add_last_column(self): for column in self.treeview.get_columns(): if column.get_expand(): break else: - column = gtk.TreeViewColumn() + column = Gtk.TreeViewColumn() column._type = 'fill' column.name = None - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) self.treeview.append_column(column) def set_drag_and_drop(self): @@ -602,20 +607,20 @@ class ViewTree(View): return self.treeview.enable_model_drag_dest( - [('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0)], - gtk.gdk.ACTION_MOVE) + [('MY_TREE_MODEL_ROW', Gtk.TargetFlags.SAME_WIDGET, 0)], + Gdk.DragAction.MOVE) self.treeview.enable_model_drag_source( - gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK, - [('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0)], - gtk.gdk.ACTION_MOVE) + Gdk.ModifierType.BUTTON1_MASK | Gdk.ModifierType.BUTTON3_MASK, + [('MY_TREE_MODEL_ROW', Gtk.TargetFlags.SAME_WIDGET, 0)], + Gdk.DragAction.MOVE) # XXX have to set manually because enable_model_drag_source # does not set the mask # https://bugzilla.gnome.org/show_bug.cgi?id=756177 self.treeview.drag_source_set( - gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK, - [gtk.TargetEntry.new( - 'MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0)], - gtk.gdk.ACTION_MOVE) + Gdk.ModifierType.BUTTON1_MASK | Gdk.ModifierType.BUTTON3_MASK, + [Gtk.TargetEntry.new( + 'MY_TREE_MODEL_ROW', Gtk.TargetFlags.SAME_WIDGET, 0)], + Gdk.DragAction.MOVE) self.treeview.connect("drag-data-get", self.drag_data_get) self.treeview.connect('drag-data-received', @@ -640,14 +645,14 @@ class ViewTree(View): if isinstance(b.renderer, CellRendererButton)] def on_keypress(self, widget, event): - control_mask = gtk.gdk.CONTROL_MASK + control_mask = Gdk.ModifierType.CONTROL_MASK if sys.platform == 'darwin': - control_mask = gtk.gdk.MOD2_MASK - if (event.keyval == gtk.keysyms.c + control_mask = Gdk.ModifierType.MOD2_MASK + if (event.keyval == Gdk.KEY_c and event.state & control_mask): self.on_copy() return False - if (event.keyval == gtk.keysyms.v + if (event.keyval == Gdk.KEY_v and event.state & control_mask): self.on_paste() return False @@ -674,8 +679,8 @@ class ViewTree(View): return False def on_copy(self): - for clipboard_type in (gtk.gdk.SELECTION_CLIPBOARD, - gtk.gdk.SELECTION_PRIMARY): + for clipboard_type in [ + Gdk.SELECTION_CLIPBOARD, Gdk.SELECTION_PRIMARY]: clipboard = self.treeview.get_clipboard(clipboard_type) selection = self.treeview.get_selection() data = [] @@ -704,8 +709,8 @@ class ViewTree(View): return value[1:-1] return value data = [] - for clipboard_type in (gtk.gdk.SELECTION_CLIPBOARD, - gtk.gdk.SELECTION_PRIMARY): + for clipboard_type in [ + Gdk.SELECTION_CLIPBOARD, Gdk.SELECTION_PRIMARY]: clipboard = self.treeview.get_clipboard(clipboard_type) text = clipboard.wait_for_text() if not text: @@ -751,7 +756,7 @@ class ViewTree(View): def drag_data_get(self, treeview, context, selection, target_id, etime): - treeview.emit_stop_by_name('drag-data-get') + treeview.stop_emission_by_name('drag-data-get') def _func_sel_get(model, path, iter_, data): value = model.get_value(iter_, 0) @@ -767,7 +772,7 @@ class ViewTree(View): def drag_data_received(self, treeview, context, x, y, selection, info, etime): - treeview.emit_stop_by_name('drag-data-received') + treeview.stop_emission_by_name('drag-data-received') if self.attributes.get('sequence'): field = self.group.fields[self.attributes['sequence']] for record in self.group: @@ -786,7 +791,7 @@ class ViewTree(View): # internal state of the cursor. cursor, column = treeview.get_cursor() if column: - for renderer in column.get_cell_renderers(): + for renderer in column.get_cells(): if renderer.props.editing: return @@ -811,36 +816,34 @@ class ViewTree(View): if drop_info: path, position = drop_info check_path = tuple(path) - if position in (gtk.TREE_VIEW_DROP_BEFORE, - gtk.TREE_VIEW_DROP_AFTER): + if position in [ + Gtk.TreeViewDropPosition.BEFORE, + Gtk.TreeViewDropPosition.AFTER]: check_path = path[:-1] if not check_recursion(record_path, check_path): return - if position == gtk.TREE_VIEW_DROP_BEFORE: + if position == Gtk.TreeViewDropPosition.BEFORE: model.move_before(record, path) - elif position == gtk.TREE_VIEW_DROP_AFTER: + elif position == Gtk.TreeViewDropPosition.AFTER: model.move_after(record, path) elif self.children_field: model.move_into(record, path) else: model.move_after(record, (len(model) - 1,)) - if hasattr(gtk.gdk, 'drop_finish'): - gtk.gdk.drop_finish(context, False, etime) - else: - context.drop_finish(False, etime) + Gdk.drop_finish(context, False, etime) if self.attributes.get('sequence'): record.group.set_sequence(field=self.attributes['sequence']) return True def drag_drop(self, treeview, context, x, y, time): - treeview.emit_stop_by_name('drag-drop') + treeview.stop_emission_by_name('drag-drop') targets = treeview.drag_dest_get_target_list() target = treeview.drag_dest_find_target(context, targets) treeview.drag_get_data(context, target, time) return True def drag_data_delete(self, treeview, context): - treeview.emit_stop_by_name('drag-data-delete') + treeview.stop_emission_by_name('drag-data-delete') def __button_press(self, treeview, event): if event.button == 3: @@ -850,18 +853,19 @@ class ViewTree(View): except TypeError: # Outside row return False - menu = gtk.Menu() - copy_item = gtk.ImageMenuItem('gtk-copy') - copy_item.set_use_stock(True) + menu = Gtk.Menu() + copy_item = Gtk.MenuItem(label=_('Copy')) copy_item.connect('activate', lambda x: self.on_copy()) menu.append(copy_item) if self.editable: - paste_item = gtk.ImageMenuItem('gtk-paste') - paste_item.set_use_stock(True) + paste_item = Gtk.MenuItem(label=_('Paste')) paste_item.connect('activate', lambda x: self.on_paste()) menu.append(paste_item) menu.show_all() - menu.popup(None, None, None, event.button, event.time) + if hasattr(menu, 'popup_at_pointer'): + menu.popup_at_pointer(event) + else: + menu.popup(None, None, None, event.button, event.time) def pop(menu, group, record): # Don't activate actions if parent is modified @@ -897,13 +901,13 @@ class ViewTree(View): selection = treeview.get_selection() if selection.count_selected_rows() == 1: group = self.group - if selection.get_mode() == gtk.SELECTION_SINGLE: + if selection.get_mode() == Gtk.SelectionMode.SINGLE: model = selection.get_selected()[0] - elif selection.get_mode() == gtk.SELECTION_MULTIPLE: + elif selection.get_mode() == Gtk.SelectionMode.MULTIPLE: model = selection.get_selected_rows()[0] record = model.get_value(model.get_iter(path), 0) # Delay filling of popup as it can take time - gobject.idle_add(pop, menu, group, record) + GLib.idle_add(pop, menu, group, record) return True # Don't change the selection elif event.button == 2: with Window(allow_similar=True): @@ -961,9 +965,9 @@ class ViewTree(View): if column._type == 'button': return allow_similar = False - event = gtk.get_current_event() - if (event.state & gtk.gdk.MOD1_MASK - or event.state & gtk.gdk.SHIFT_MASK): + event = Gtk.get_current_event() + if (event.state & Gdk.ModifierType.MOD1_MASK + or event.state & Gdk.ModifierType.SHIFT_MASK): allow_similar = True with Window(allow_similar=allow_similar): if not self.screen.row_activate() and self.children_field: @@ -977,7 +981,7 @@ class ViewTree(View): if previous_record and previous_record not in previous_record.group: previous_record = None - if tree_sel.get_mode() == gtk.SELECTION_SINGLE: + if tree_sel.get_mode() == Gtk.SelectionMode.SINGLE: model, iter_ = tree_sel.get_selected() if model and iter_: record = model.get_value(iter_, 0) @@ -985,7 +989,7 @@ class ViewTree(View): else: self.record = None - elif tree_sel.get_mode() == gtk.SELECTION_MULTIPLE: + elif tree_sel.get_mode() == Gtk.SelectionMode.MULTIPLE: model, paths = tree_sel.get_selected_rows() if model and paths: iter_ = model.get_iter(paths[0]) @@ -1009,7 +1013,7 @@ class ViewTree(View): go_previous() return True # Delay the save to let GTK process the current event - gobject.idle_add(save) + GLib.idle_add(save) elif previous_record != self.record and self.screen.pre_validate: def pre_validate(): @@ -1017,7 +1021,7 @@ class ViewTree(View): if not previous_record.pre_validate(): go_previous() # Delay the pre_validate to let GTK process the current event - gobject.idle_add(pre_validate) + GLib.idle_add(pre_validate) self.update_sum() def set_value(self): @@ -1140,18 +1144,18 @@ class ViewTree(View): model = self.treeview.get_model() if self.record and model: path = self.record.get_index_path(model.group) - if model.get_flags() & gtk.TREE_MODEL_LIST_ONLY: + if model.get_flags() & Gtk.TreeModelFlags.LIST_ONLY: path = (path[0],) focus_column, focus_cell = self.treeview.next_column( path, editable=new) if path[:-1]: - self.treeview.expand_to_path(gtk.TreePath(path[:-1])) + self.treeview.expand_to_path(Gtk.TreePath(path[:-1])) self.treeview.scroll_to_cell(path, focus_column, use_align=False) current_path = self.treeview.get_cursor()[0] selected_path = \ self.treeview.get_selection().get_selected_rows()[1] - path = gtk.TreePath(path) + path = Gtk.TreePath(path) if (current_path != path and path not in selected_path) or new: self.treeview.set_cursor(path, focus_column, new) @@ -1188,7 +1192,7 @@ class ViewTree(View): for node in nodes: path = path_convert_id2pos(model, node) if path: - selection.select_path(gtk.TreePath(path)) + selection.select_path(Gtk.TreePath(path)) if not scroll: self.treeview.scroll_to_cell(path) scroll = True @@ -1203,12 +1207,12 @@ class ViewTree(View): id_paths = [] model = self.treeview.get_model() if starting_path: - iter_ = model.get_iter(gtk.TreePath(starting_path)) + iter_ = model.get_iter(Gtk.TreePath(starting_path)) else: iter_ = None for path_idx in range(model.iter_n_children(iter_)): path = starting_path + (path_idx,) - expanded = self.treeview.row_expanded(gtk.TreePath(path)) + expanded = self.treeview.row_expanded(Gtk.TreePath(path)) if expanded: iter_ = model.get_iter(path) expanded_record = model.get_value(iter_, 0) @@ -1223,4 +1227,4 @@ class ViewTree(View): for node in nodes: expand_path = path_convert_id2pos(model, node) if expand_path: - self.treeview.expand_to_path(gtk.TreePath(expand_path)) + self.treeview.expand_to_path(Gtk.TreePath(expand_path)) diff --git a/tryton/gui/window/view_form/view/list_gtk/editabletree.py b/tryton/gui/window/view_form/view/list_gtk/editabletree.py index adff22facc..f6183b304c 100644 --- a/tryton/gui/window/view_form/view/list_gtk/editabletree.py +++ b/tryton/gui/window/view_form/view/list_gtk/editabletree.py @@ -1,11 +1,9 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk import gettext -import gobject from itertools import islice, cycle, chain -from gi.repository import Gtk +from gi.repository import Gdk, GLib, Gtk from tryton.common import MODELACCESS from tryton.common.datetime_ import Date, Time @@ -20,7 +18,7 @@ def focusable_cells(column, editable=True): yield cell -class TreeView(gtk.TreeView): +class TreeView(Gtk.TreeView): display_counter = 0 def __init__(self, view): @@ -73,10 +71,10 @@ class TreeView(gtk.TreeView): class EditableTreeView(TreeView): - leaving_record_events = (gtk.keysyms.Up, gtk.keysyms.Down, - gtk.keysyms.Return) - leaving_events = leaving_record_events + (gtk.keysyms.Tab, - gtk.keysyms.ISO_Left_Tab, gtk.keysyms.KP_Enter) + leaving_record_events = ( + Gdk.KEY_Up, Gdk.KEY_Down, Gdk.KEY_Return) + leaving_events = leaving_record_events + ( + Gdk.KEY_Tab, Gdk.KEY_ISO_Left_Tab, Gdk.KEY_KP_Enter) def __init__(self, position, view): super(EditableTreeView, self).__init__(view) @@ -137,7 +135,7 @@ class EditableTreeView(TreeView): self.grab_focus() if focus_column: widget = self.view.get_column_widget(focus_column) - if isinstance(widget.renderer, gtk.CellRendererToggle): + if isinstance(widget.renderer, Gtk.CellRendererToggle): start_editing = False self.scroll_to_cell(path, focus_column, use_align=False) if cell: @@ -150,7 +148,7 @@ class EditableTreeView(TreeView): path, column = self.get_cursor() if not path or not column or not column.name: return True - for renderer in column.get_cell_renderers(): + for renderer in column.get_cells(): if renderer.props.editing: widget = self.view.get_column_widget(column) self.on_editing_done(widget.editable, renderer) @@ -163,16 +161,16 @@ class EditableTreeView(TreeView): self.display_counter += 1 # Force a display leaving = False - if event.keyval == gtk.keysyms.Right: - if isinstance(entry, gtk.Entry): + if event.keyval == Gdk.KEY_Right: + if isinstance(entry, Gtk.Entry): if entry.get_position() >= \ len(entry.get_text()) \ and not entry.get_selection_bounds(): leaving = True else: leaving = True - elif event.keyval == gtk.keysyms.Left: - if isinstance(entry, gtk.Entry): + elif event.keyval == Gdk.KEY_Left: + if isinstance(entry, Gtk.Entry): if entry.get_position() <= 0 \ and not entry.get_selection_bounds(): leaving = True @@ -183,22 +181,30 @@ class EditableTreeView(TreeView): if isinstance(entry, (Date, Time)): entry.activate() txt = entry.props.value - elif isinstance(entry, gtk.Entry): + elif isinstance(entry, Gtk.Entry): txt = entry.get_text() + elif isinstance(entry, Gtk.ComboBox): + active = entry.get_active() + if active < 0: + txt = None + else: + model = entry.get_model() + index = entry.get_property('entry-text-column') + txt = model[active][index] else: - txt = entry.get_active_text() + return True keyval = event.keyval entry.handler_block(entry.editing_done_id) def callback(): entry.handler_unblock(entry.editing_done_id) - if (keyval in (gtk.keysyms.Tab, gtk.keysyms.KP_Enter) - or (keyval == gtk.keysyms.Right and leaving)): - gobject.idle_add(self.set_cursor, path, + if (keyval in [Gdk.KEY_Tab, Gdk.KEY_KP_Enter] + or (keyval == Gdk.KEY_Right and leaving)): + GLib.idle_add(self.set_cursor, path, *self.next_column(path, column, renderer), True) - elif (keyval == gtk.keysyms.ISO_Left_Tab - or (keyval == gtk.keysyms.Left and leaving)): - gobject.idle_add(self.set_cursor, path, + elif (keyval == Gdk.KEY_ISO_Left_Tab + or (keyval == Gdk.KEY_Left and leaving)): + GLib.idle_add(self.set_cursor, path, *self.prev_column(path, column, renderer), True) elif keyval in self.leaving_record_events: fields = list(self.view.widgets.keys()) @@ -208,53 +214,61 @@ class EditableTreeView(TreeView): for col in self.get_columns(): if col.name in invalid_fields: break - gobject.idle_add(self.set_cursor, path, col, True) + GLib.idle_add(self.set_cursor, path, col, True) return if ((self.view.screen.pre_validate and not record.pre_validate()) or (not self.view.screen.parent and not record.save())): - gobject.idle_add(self.set_cursor, path, column, + GLib.idle_add(self.set_cursor, path, column, True) return entry.handler_block(entry.editing_done_id) - if keyval == gtk.keysyms.Up: + if keyval == Gdk.KEY_Up: self._key_up(path, model, column) - elif keyval == gtk.keysyms.Down: + elif keyval == Gdk.KEY_Down: self._key_down(path, model, column) - elif keyval == gtk.keysyms.Return: + elif keyval == Gdk.KEY_Return: if self.editable == 'top': new_path = self._key_up(path, model) else: new_path = self._key_down(path, model) - gobject.idle_add(self.set_cursor, new_path, + GLib.idle_add(self.set_cursor, new_path, *self.next_column(new_path), True) entry.handler_unblock(entry.editing_done_id) else: - gobject.idle_add(self.set_cursor, path, column, True) + GLib.idle_add(self.set_cursor, path, column, True) self.on_quit_cell(record, column, renderer, txt, callback=callback) return True - elif event.keyval in (gtk.keysyms.F3, gtk.keysyms.F2): - if isinstance(entry, gtk.Entry): + elif event.keyval in [Gdk.KEY_F3, Gdk.KEY_F2]: + if isinstance(entry, Gtk.Entry): value = entry.get_text() + elif isinstance(entry, Gtk.ComboBox): + active = entry.get_active() + if active < 0: + value = None + else: + model = entry.get_model() + index = entry.get_property('entry-text-column') + value = model[active][index] else: - value = entry.get_active_text() + return True entry.handler_block(entry.editing_done_id) def callback(): widget = self.view.get_column_widget(column) value = widget.get_textual_value(record) - if isinstance(entry, gtk.Entry): + if isinstance(entry, Gtk.Entry): entry.set_text(value) else: entry.set_active_text(value) entry.handler_unblock(entry.editing_done_id) self.on_open_remote(record, column, - create=(event.keyval == gtk.keysyms.F3), value=value, + create=(event.keyval == Gdk.KEY_F3), value=value, callback=callback) else: field = record[column.name] - if isinstance(entry, gtk.Entry): + if isinstance(entry, Gtk.Entry): entry.set_max_length(int(field.attrs.get('size', 0))) record.modified_fields.setdefault(column.name) return False @@ -292,7 +306,7 @@ class EditableTreeView(TreeView): if isinstance(entry, (Date, Time)): entry.activate() text = entry.props.value - elif isinstance(entry, (gtk.ComboBoxEntry, gtk.ComboBox)): + elif isinstance(entry, Gtk.ComboBox): text = entry.get_active_text else: text = entry.get_text() diff --git a/tryton/gui/window/view_form/view/list_gtk/widget.py b/tryton/gui/window/view_form/view/list_gtk/widget.py index da3f860cfe..778f407bba 100644 --- a/tryton/gui/window/view_form/view/list_gtk/widget.py +++ b/tryton/gui/window/view_form/view/list_gtk/widget.py @@ -2,14 +2,12 @@ # this repository contains the full copyright notices and license terms. import datetime import os -import gtk import gettext import webbrowser - -from gi.repository import Gtk, GObject - from functools import wraps, partial +from gi.repository import Gdk, GLib, Gtk + from tryton.gui.window.win_search import WinSearch from tryton.gui.window.win_form import WinForm from tryton.gui.window.view_form.screen import Screen @@ -38,7 +36,7 @@ def send_keys(renderer, editable, position, treeview): editable.connect('key_press_event', treeview.on_keypressed, renderer) editable.editing_done_id = editable.connect('editing_done', treeview.on_editing_done, renderer) - if isinstance(editable, (gtk.ComboBoxEntry, gtk.ComboBox)): + if isinstance(editable, Gtk.ComboBox): def changed(combobox): # "changed" signal is also triggered by text editing # so only trigger editing-done if a row is active @@ -90,7 +88,7 @@ class CellCache(list): @classmethod def cache(cls, func): @wraps(func) - def wrapper(self, column, cell, store, iter_): + def wrapper(self, column, cell, store, iter_, user_data=None): if not hasattr(self, 'display_counters'): self.display_counters = {} if not hasattr(self, 'cell_caches'): @@ -99,11 +97,11 @@ class CellCache(list): counter = self.view.treeview.display_counter if (self.display_counters.get(record.id) != counter): if getattr(cell, 'decorated', None): - func(self, column, cell, store, iter_) + func(self, column, cell, store, iter_, user_data) else: cache = cls() cache.decorate(cell) - func(self, column, cell, store, iter_) + func(self, column, cell, store, iter_, user_data) cache.undecorate(cell) self.cell_caches[record.id] = cache self.display_counters[record.id] = counter @@ -150,14 +148,14 @@ class Affix(Cell): if not self.icon: self.icon = 'tryton-public' elif self.icon: - self.renderer = gtk.CellRendererPixbuf() + self.renderer = Gtk.CellRendererPixbuf() else: - self.renderer = gtk.CellRendererText() + self.renderer = Gtk.CellRendererText() self.view = view @realized @CellCache.cache - def setter(self, column, cell, store, iter_): + def setter(self, column, cell, store, iter_, user_data=None): record, field = self._get_record_field_from_iter(iter_, store) field = record[self.attrs['name']] field.state_set(record, states=('invisible',)) @@ -168,7 +166,7 @@ class Affix(Cell): value = record[self.icon].get_client(record) or '' else: value = self.icon - pixbuf = common.IconFactory.get_pixbuf(value, gtk.ICON_SIZE_BUTTON) + pixbuf = common.IconFactory.get_pixbuf(value, Gtk.IconSize.BUTTON) cell.set_property('pixbuf', pixbuf) else: text = self.attrs.get('string', '') @@ -216,7 +214,7 @@ class GenericText(Cell): @realized @CellCache.cache - def setter(self, column, cell, store, iter_): + def setter(self, column, cell, store, iter_, user_data=None): record = store.get_value(iter_, 0) text = self.get_textual_value(record) @@ -254,8 +252,9 @@ class GenericText(Cell): if isinstance(cell, CellRendererToggle): cell.set_property('activatable', not readonly) - elif isinstance(cell, (gtk.CellRendererProgress, - CellRendererButton, gtk.CellRendererPixbuf)): + elif isinstance(cell, + (Gtk.CellRendererProgress, CellRendererButton, + Gtk.CellRendererPixbuf)): pass else: cell.set_property('editable', not readonly) @@ -290,8 +289,8 @@ class Char(GenericText): @realized @CellCache.cache - def setter(self, column, cell, store, iter_): - super(Char, self).setter(column, cell, store, iter_) + def setter(self, column, cell, store, iter_, user_data=None): + super(Char, self).setter(column, cell, store, iter_, user_data) cell.set_property('single-paragraph-mode', True) @@ -345,8 +344,8 @@ class URL(Char): @realized @CellCache.cache - def setter(self, column, cell, store, iter_): - super(URL, self).setter(column, cell, store, iter_) + def setter(self, column, cell, store, iter_, user_data=None): + super(URL, self).setter(column, cell, store, iter_, user_data) record, field = self._get_record_field_from_iter(iter_, store) field.state_set(record, states=('readonly',)) readonly = field.get_state_attrs(record).get('readonly', False) @@ -361,10 +360,10 @@ class Date(GenericText): super(Date, self).__init__(view, attrs, renderer=renderer) @realized - def setter(self, column, cell, store, iter_): + def setter(self, column, cell, store, iter_, user_data=None): record, field = self._get_record_field_from_iter(iter_, store) self.renderer.props.format = self.get_format(record, field) - super(Date, self).setter(column, cell, store, iter_) + super(Date, self).setter(column, cell, store, iter_, user_data) def get_format(self, record, field): if field and record: @@ -419,8 +418,8 @@ class Float(Int): super(Float, self).__init__(view, attrs, renderer=renderer) @realized - def setter(self, column, cell, store, iter_): - super(Float, self).setter(column, cell, store, iter_) + def setter(self, column, cell, store, iter_, user_data=None): + super(Float, self).setter(column, cell, store, iter_, user_data) record, field = self._get_record_field_from_iter(iter_, store) digits = field.digits(record, factor=self.factor) cell.digits = digits @@ -464,7 +463,7 @@ class Binary(GenericText): @realized @CellCache.cache - def setter(self, column, cell, store, iter_): + def setter(self, column, cell, store, iter_, user_data=None): record, field = self._get_record_field_from_iter(iter_, store) text = self.get_textual_value(record) cell.set_property('text', text) @@ -522,14 +521,14 @@ class _BinarySave(_BinaryIcon): filename_field = record.group.fields.get(self.attrs['filename']) filename = filename_field.get(record) filename = file_selection(_('Save As...'), filename=filename, - action=gtk.FILE_CHOOSER_ACTION_SAVE) + action=Gtk.FileChooserAction.SAVE) if filename: with open(filename, 'wb') as fp: fp.write(self.binary.get_data(record, field)) @realized @CellCache.cache - def setter(self, column, cell, store, iter_): + def setter(self, column, cell, store, iter_, user_data=None): record, field = self._get_record_field_from_iter(iter_, store) if hasattr(field, 'get_size'): size = field.get_size(record) @@ -564,11 +563,11 @@ class _BinarySelect(_BinaryIcon): if filename_field: filename_field.set_client( record, os.path.basename(filename)) - GObject.idle_add(_select) + GLib.idle_add(_select) @realized @CellCache.cache - def setter(self, column, cell, store, iter_): + def setter(self, column, cell, store, iter_, user_data=None): record, field = self._get_record_field_from_iter(iter_, store) if hasattr(field, 'get_size'): size = field.get_size(record) @@ -601,11 +600,11 @@ class _BinaryOpen(_BinarySave): root, type_ = os.path.splitext(filename) if type_: type_ = type_[1:] - GObject.idle_add(file_open, file_path, type_) + GLib.idle_add(file_open, file_path, type_) @realized @CellCache.cache - def setter(self, column, cell, store, iter_): + def setter(self, column, cell, store, iter_, user_data=None): super().setter(column, cell, store, iter_) record, field = self._get_record_field_from_iter(iter_, store) filename_field = record.group.fields.get(self.attrs.get('filename')) @@ -619,14 +618,14 @@ class Image(GenericText): def __init__(self, view, attrs=None, renderer=None): if renderer is None: - renderer = gtk.CellRendererPixbuf + renderer = Gtk.CellRendererPixbuf super(Image, self).__init__(view, attrs, renderer) self.renderer.set_fixed_size(self.attrs.get('width', -1), self.attrs.get('height', -1)) @realized @CellCache.cache - def setter(self, column, cell, store, iter_): + def setter(self, column, cell, store, iter_, user_data=None): record, field = self._get_record_field_from_iter(iter_, store) value = field.get_client(record) if isinstance(value, int): @@ -682,7 +681,7 @@ class M2O(GenericText): field = record[self.attrs['name']] win = self.search_remote(record, field, text, callback=callback) if len(win.screen.group) == 1: - win.response(None, gtk.RESPONSE_OK) + win.response(None, Gtk.ResponseType.OK) else: win.show() @@ -704,11 +703,11 @@ class M2O(GenericText): icon1, tooltip1 = None, '' icon2, tooltip2 = 'tryton-search', _("Search a record ") for pos, icon, tooltip in [ - (gtk.ENTRY_ICON_PRIMARY, icon1, tooltip1), - (gtk.ENTRY_ICON_SECONDARY, icon2, tooltip2)]: + (Gtk.EntryIconPosition.PRIMARY, icon1, tooltip1), + (Gtk.EntryIconPosition.SECONDARY, icon2, tooltip2)]: if icon: pixbuf = common.IconFactory.get_pixbuf( - icon, gtk.ICON_SIZE_MENU) + icon, Gtk.IconSize.MENU) else: pixbuf = None editable.set_icon_from_pixbuf(pos, pixbuf) @@ -718,7 +717,8 @@ class M2O(GenericText): value = field.get(record) if not model: return - if icon_pos == gtk.ENTRY_ICON_SECONDARY and self.has_target(value): + if (icon_pos == Gtk.EntryIconPosition.SECONDARY + and self.has_target(value)): field.set_client( record, self.value_from_id(model, None, '')) editable.set_text('') @@ -818,8 +818,7 @@ class M2O(GenericText): def _key_press(self, entry, event, path): record, field = self._get_record_field_from_path(path) if (self.has_target(field.get(record)) - and event.keyval in (gtk.keysyms.Delete, - gtk.keysyms.BackSpace)): + and event.keyval in [Gdk.KEY_Delete, Gdk.KEY_BackSpace]): entry.set_text('') return False @@ -974,7 +973,14 @@ class Selection(GenericText, SelectionMixin, PopdownMixin): def set_value(self, editable, record, field): value = self.get_popdown_value(editable) if 'relation' in self.attrs and value: - value = (value, editable.get_active_text()) + active = editable.get_active() + if active < 0: + text = None + else: + model = editable.get_model() + index = editable.get_property('entry-text-column') + text = model[active][index] + value = (value, text) field.set_client(record, value) return False @@ -1050,28 +1056,26 @@ class _ReferenceSelection(Selection): class ProgressBar(object): align = 0.5 orientations = { - 'left_to_right': gtk.PROGRESS_LEFT_TO_RIGHT, - 'right_to_left': gtk.PROGRESS_RIGHT_TO_LEFT, - 'bottom_to_top': gtk.PROGRESS_BOTTOM_TO_TOP, - 'top_to_bottom': gtk.PROGRESS_TOP_TO_BOTTOM, - } + 'left_to_right': (Gtk.Orientation.HORIZONTAL, False), + 'right_to_left': (Gtk.Orientation.HORIZONTAL, True), + 'bottom_to_top': (Gtk.Orientation.VERTICAL, True), + 'top_to_bottom': (Gtk.Orientation.VERTICAL, False), + } def __init__(self, view, attrs): super(ProgressBar, self).__init__() self.view = view self.attrs = attrs - self.renderer = gtk.CellRendererProgress() - orientation = self.orientations.get(self.attrs.get('orientation', - 'left_to_right'), gtk.PROGRESS_LEFT_TO_RIGHT) - if hasattr(self.renderer, 'set_orientation'): - self.renderer.set_orientation(orientation) - else: - self.renderer.set_property('orientation', orientation) + self.renderer = Gtk.CellRendererProgress() + orientation, inverted = self.orientations.get( + self.attrs.get('orientation', 'left_to_right')) + self.renderer.set_orientation(orientation) + self.renderer.set_property('inverted', inverted) self.renderer.set_property('yalign', 0) @realized @CellCache.cache - def setter(self, column, cell, store, iter_): + def setter(self, column, cell, store, iter_, user_data=None): record, field = self._get_record_field_from_iter(iter_, store) field.state_set(record, states=('invisible',)) invisible = field.get_state_attrs(record).get('invisible', False) @@ -1110,7 +1114,7 @@ class Button(Cell): @realized @CellCache.cache - def setter(self, column, cell, store, iter_): + def setter(self, column, cell, store, iter_, user_data=None): record = store.get_value(iter_, 0) states = record.expr_eval(self.attrs.get('states', {})) invisible = states.get('invisible', False) diff --git a/tryton/gui/window/view_form/view/screen_container.py b/tryton/gui/window/view_form/view/screen_container.py index a17439f1a0..05d5a6ea01 100644 --- a/tryton/gui/window/view_form/view/screen_container.py +++ b/tryton/gui/window/view_form/view/screen_container.py @@ -1,11 +1,9 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import datetime - -from gi.repository import Gtk -import gtk import gettext -import gobject + +from gi.repository import Gdk, GLib, GObject, Gtk import tryton.common as common from tryton.common.domain_parser import quote @@ -22,10 +20,11 @@ class Between(Gtk.HBox): def __init__(self, _entry=Gtk.Entry): super().__init__() self.from_ = _entry() - self.pack_start(self.from_, expand=True, fill=True) - self.pack_start(Gtk.Label(_('..')), expand=False, fill=False) + self.pack_start(self.from_, expand=True, fill=True, padding=0) + self.pack_start( + Gtk.Label(label=_('..')), expand=False, fill=False, padding=0) self.to = _entry() - self.pack_start(self.to, expand=True, fill=True) + self.pack_start(self.to, expand=True, fill=True, padding=0) if self._changed_signal: self.from_.connect_after( @@ -136,26 +135,27 @@ class DateTimes(BetweenDates): widget.props.date_format + ' ' + widget.props.time_format) -class Selection(gtk.ScrolledWindow): +class Selection(Gtk.ScrolledWindow): def __init__(self, selections): super(Selection, self).__init__() self.treeview = TreeViewControl() - model = gtk.ListStore(gobject.TYPE_STRING) + model = Gtk.ListStore(GObject.TYPE_STRING) for selection in selections: model.append((selection,)) self.treeview.set_model(model) - column = gtk.TreeViewColumn() - cell = gtk.CellRendererText() - column.pack_start(cell) + column = Gtk.TreeViewColumn() + cell = Gtk.CellRendererText() + column.pack_start(cell, expand=True) column.add_attribute(cell, 'text', 0) self.treeview.append_column(column) - self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) + self.treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self.treeview.set_headers_visible(False) self.add(self.treeview) - self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.set_shadow_type(gtk.SHADOW_ETCHED_IN) + self.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + self.set_shadow_type(Gtk.ShadowType.ETCHED_IN) self.set_min_content_height(min(20 * len(selections), 200)) self.set_max_content_height(200) @@ -173,11 +173,11 @@ class Selection(gtk.ScrolledWindow): class ScreenContainer(object): def __init__(self, tab_domain): - self.viewport = gtk.Viewport() - self.viewport.set_shadow_type(gtk.SHADOW_NONE) - self.vbox = gtk.VBox(spacing=3) - self.alternate_viewport = gtk.Viewport() - self.alternate_viewport.set_shadow_type(gtk.SHADOW_NONE) + self.viewport = Gtk.Viewport() + self.viewport.set_shadow_type(Gtk.ShadowType.NONE) + self.vbox = Gtk.VBox(spacing=3) + self.alternate_viewport = Gtk.Viewport() + self.alternate_viewport.set_shadow_type(Gtk.ShadowType.NONE) self.alternate_view = False self.search_popover = None self.search_table = None @@ -187,20 +187,20 @@ class ScreenContainer(object): tooltips = common.Tooltips() - self.filter_vbox = gtk.VBox(spacing=0) + self.filter_vbox = Gtk.VBox(spacing=0) self.filter_vbox.set_border_width(0) - hbox = gtk.HBox(homogeneous=False, spacing=0) + hbox = Gtk.HBox(homogeneous=False, spacing=0) - self.search_entry = gtk.Entry() + self.search_entry = Gtk.Entry() self.search_entry.set_placeholder_text(_('Search')) self.search_entry.set_alignment(0.0) self.search_entry.set_icon_from_pixbuf( - gtk.ENTRY_ICON_PRIMARY, - common.IconFactory.get_pixbuf('tryton-filter', gtk.ICON_SIZE_MENU)) + Gtk.EntryIconPosition.PRIMARY, + common.IconFactory.get_pixbuf('tryton-filter', Gtk.IconSize.MENU)) self.search_entry.set_icon_tooltip_text( - gtk.ENTRY_ICON_PRIMARY, _('Open filters')) - self.completion = gtk.EntryCompletion() - self.completion.set_model(gtk.ListStore(str)) + Gtk.EntryIconPosition.PRIMARY, _('Open filters')) + self.completion = Gtk.EntryCompletion() + self.completion.set_model(Gtk.ListStore(str)) self.completion.set_text_column(0) self.completion.props.inline_selection = True self.completion.props.popup_set_width = False @@ -212,7 +212,7 @@ class ScreenContainer(object): self.search_entry.connect('focus-in-event', self.focus_in) self.search_entry.connect('icon-press', self.icon_press) - hbox.pack_start(self.search_entry, expand=True, fill=True) + hbox.pack_start(self.search_entry, expand=True, fill=True, padding=0) def popup(widget): menu = widget._menu @@ -224,76 +224,77 @@ class ScreenContainer(object): def menu_position(menu, data=None): widget_allocation = widget.get_allocation() - if hasattr(widget.window, 'get_root_coords'): - x, y = widget.window.get_root_coords( - widget_allocation.x, widget_allocation.y) - else: - x, y = widget.window.get_origin() - x += widget_allocation.x - y += widget_allocation.y + x, y = widget.get_window().get_root_coords( + widget_allocation.x, widget_allocation.y) return (x, y + widget_allocation.height, False) for id_, name, domain in self.bookmarks(): - menuitem = gtk.MenuItem(name) + menuitem = Gtk.MenuItem(label=name) menuitem.connect('activate', self.bookmark_activate, domain) menu.add(menuitem) menu.show_all() - menu.popup(None, None, menu_position, 0, 0) + if hasattr(menu, 'popup_at_widget'): + menu.popup_at_widget( + widget, Gdk.Gravity.SOUTH_WEST, Gdk.Gravity.NORTH_WEST, + Gtk.get_current_event()) + else: + menu.popup(None, None, menu_position, 0, 0) def deactivate(menuitem, togglebutton): togglebutton.props.active = False - but_bookmark = gtk.ToggleButton() + but_bookmark = Gtk.ToggleButton() self.but_bookmark = but_bookmark tooltips.set_tip(but_bookmark, _('Show bookmarks of filters')) but_bookmark.add(common.IconFactory.get_image( - 'tryton-bookmarks', gtk.ICON_SIZE_SMALL_TOOLBAR)) - but_bookmark.set_relief(gtk.RELIEF_NONE) - menu = gtk.Menu() + 'tryton-bookmarks', Gtk.IconSize.SMALL_TOOLBAR)) + but_bookmark.set_relief(Gtk.ReliefStyle.NONE) + menu = Gtk.Menu() menu.set_property('reserve-toggle-size', False) menu.connect('deactivate', deactivate, but_bookmark) but_bookmark._menu = menu but_bookmark.connect('toggled', popup) - hbox.pack_start(but_bookmark, expand=False, fill=False) + hbox.pack_start(but_bookmark, expand=False, fill=False, padding=0) - but_active = gtk.ToggleButton() + but_active = Gtk.ToggleButton() self.but_active = but_active self._set_active_tooltip() but_active.add(common.IconFactory.get_image( - 'tryton-archive', gtk.ICON_SIZE_SMALL_TOOLBAR)) - but_active.set_relief(gtk.RELIEF_NONE) + 'tryton-archive', Gtk.IconSize.SMALL_TOOLBAR)) + but_active.set_relief(Gtk.ReliefStyle.NONE) but_active.connect('toggled', self.search_active) - hbox.pack_start(but_active, expand=False, fill=False) + hbox.pack_start(but_active, expand=False, fill=False, padding=0) - but_prev = gtk.Button() + but_prev = Gtk.Button() self.but_prev = but_prev tooltips.set_tip(but_prev, _('Previous')) but_prev.connect('clicked', self.search_prev) but_prev.add(common.IconFactory.get_image( - 'tryton-back', gtk.ICON_SIZE_SMALL_TOOLBAR)) - but_prev.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(but_prev, expand=False, fill=False) + 'tryton-back', Gtk.IconSize.SMALL_TOOLBAR)) + but_prev.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(but_prev, expand=False, fill=False, padding=0) - but_next = gtk.Button() + but_next = Gtk.Button() self.but_next = but_next tooltips.set_tip(but_next, _('Next')) but_next.connect('clicked', self.search_next) but_next.add(common.IconFactory.get_image( - 'tryton-forward', gtk.ICON_SIZE_SMALL_TOOLBAR)) - but_next.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(but_next, expand=False, fill=False) + 'tryton-forward', Gtk.IconSize.SMALL_TOOLBAR)) + but_next.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(but_next, expand=False, fill=False, padding=0) hbox.show_all() hbox.set_focus_chain([self.search_entry]) - self.filter_vbox.pack_start(hbox, expand=False, fill=False) + self.filter_vbox.pack_start(hbox, expand=False, fill=False, padding=0) - hseparator = gtk.HSeparator() + hseparator = Gtk.HSeparator() hseparator.show() - self.filter_vbox.pack_start(hseparator, expand=False, fill=False) + self.filter_vbox.pack_start( + hseparator, expand=False, fill=False, padding=0) if self.tab_domain: - self.notebook = gtk.Notebook() + self.notebook = Gtk.Notebook() try: self.notebook.props.homogeneous = True except AttributeError: @@ -301,30 +302,34 @@ class ScreenContainer(object): pass self.notebook.set_scrollable(True) for name, domain, count in self.tab_domain: - hbox = gtk.HBox(spacing=3) - label = gtk.Label('_' + name) + hbox = Gtk.HBox(spacing=3) + label = Gtk.Label(label='_' + name) label.set_use_underline(True) - hbox.pack_start(label, expand=True, fill=True) - counter = gtk.Label() - hbox.pack_start(counter, expand=False, fill=True) + hbox.pack_start(label, expand=True, fill=True, padding=0) + counter = Gtk.Label() + hbox.pack_start(counter, expand=False, fill=True, padding=0) hbox.show_all() - self.notebook.append_page(gtk.VBox(), hbox) + self.notebook.append_page(Gtk.VBox(), hbox) self.tab_counter.append(counter) - self.filter_vbox.pack_start(self.notebook, expand=True, fill=True) + self.filter_vbox.pack_start( + self.notebook, expand=True, fill=True, padding=0) self.notebook.show_all() # Set the current page before connecting to switch-page to not # trigger the search a second times. self.notebook.set_current_page(0) - self.notebook.get_nth_page(0).pack_end(self.viewport) + self.notebook.get_nth_page(0).pack_end( + self.viewport, expand=True, fill=True, padding=0) self.notebook.connect('switch-page', self.switch_page) self.notebook.connect_after('switch-page', self.switch_page_after) filter_expand = True else: self.notebook = None - self.vbox.pack_end(self.viewport) + self.vbox.pack_end( + self.viewport, expand=True, fill=True, padding=0) filter_expand = False - self.vbox.pack_start(self.filter_vbox, expand=filter_expand, fill=True) + self.vbox.pack_start( + self.filter_vbox, expand=filter_expand, fill=True, padding=0) self.but_next.set_sensitive(False) self.but_prev.set_sensitive(False) @@ -347,7 +352,8 @@ class ScreenContainer(object): if self.viewport in self.vbox.get_children(): self.vbox.remove(self.viewport) self.notebook.get_nth_page(self.notebook.get_current_page() - ).pack_end(self.viewport) + ).pack_end( + self.viewport, expand=True, fill=True, padding=0) def hide_filter(self): if self.filter_vbox: @@ -357,7 +363,8 @@ class ScreenContainer(object): if self.viewport not in self.vbox.get_children(): self.notebook.get_nth_page(self.notebook.get_current_page() ).remove(self.viewport) - self.vbox.pack_end(self.viewport) + self.vbox.pack_end( + self.viewport, expand=True, fill=True, padding=0) def set(self, widget): viewport1 = self.viewport @@ -399,32 +406,34 @@ class ScreenContainer(object): current_text = self.get_text() if current_text: current_domain = self.screen.domain_parser.parse(current_text) - self.search_entry.set_icon_activatable(gtk.ENTRY_ICON_SECONDARY, - bool(current_text)) - self.search_entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, - bool(current_text)) + self.search_entry.set_icon_activatable( + Gtk.EntryIconPosition.SECONDARY, bool(current_text)) + self.search_entry.set_icon_sensitive( + Gtk.EntryIconPosition.SECONDARY, bool(current_text)) for id_, name, domain in self.bookmarks(): text = self.screen.domain_parser.string(domain) domain = self.screen.domain_parser.parse(text) if (text == current_text or domain == current_domain): self.search_entry.set_icon_from_pixbuf( - gtk.ENTRY_ICON_SECONDARY, + Gtk.EntryIconPosition.SECONDARY, common.IconFactory.get_pixbuf( - 'tryton-bookmark', gtk.ICON_SIZE_MENU)) + 'tryton-bookmark', Gtk.IconSize.MENU)) self.search_entry.set_icon_tooltip_text( - gtk.ENTRY_ICON_SECONDARY, _('Remove this bookmark')) + Gtk.EntryIconPosition.SECONDARY, + _('Remove this bookmark')) return id_ self.search_entry.set_icon_from_pixbuf( - gtk.ENTRY_ICON_SECONDARY, + Gtk.EntryIconPosition.SECONDARY, common.IconFactory.get_pixbuf( - 'tryton-bookmark-border', gtk.ICON_SIZE_MENU)) + 'tryton-bookmark-border', Gtk.IconSize.MENU)) if current_text: - self.search_entry.set_icon_tooltip_text(gtk.ENTRY_ICON_SECONDARY, - _('Bookmark this filter')) - elif self.search_entry.get_icon_tooltip_text(gtk.ENTRY_ICON_SECONDARY): - self.search_entry.set_icon_tooltip_text(gtk.ENTRY_ICON_SECONDARY, - None) + self.search_entry.set_icon_tooltip_text( + Gtk.EntryIconPosition.SECONDARY, _('Bookmark this filter')) + elif self.search_entry.get_icon_tooltip_text( + Gtk.EntryIconPosition.SECONDARY): + self.search_entry.set_icon_tooltip_text( + Gtk.EntryIconPosition.SECONDARY, None) def search_next(self, widget=None): self.screen.search_next(self.get_text()) @@ -449,7 +458,7 @@ class ScreenContainer(object): current_page.remove(self.viewport) new_page = notebook.get_nth_page(page_num) - new_page.pack_end(self.viewport) + new_page.pack_end(self.viewport, expand=True, fill=True, padding=0) def switch_page_after(self, notebook, page, page_num): self.do_search() @@ -490,7 +499,7 @@ class ScreenContainer(object): return self.update() self.search_entry.emit('changed') - gobject.idle_add(callback) + GLib.idle_add(callback) def activate(self, widget): if not self.search_entry.get_selection_bounds(): @@ -509,12 +518,12 @@ class ScreenContainer(object): return self.update() self.bookmark_match() - gobject.idle_add(keypress) + GLib.idle_add(keypress) def icon_press(self, widget, icon_pos, event): - if icon_pos == gtk.ENTRY_ICON_PRIMARY: + if icon_pos == Gtk.EntryIconPosition.PRIMARY: self.search_box(widget) - elif icon_pos == gtk.ENTRY_ICON_SECONDARY: + elif icon_pos == Gtk.EntryIconPosition.SECONDARY: model_name = self.screen.model_name id_ = self.bookmark_match() if not id_: @@ -546,7 +555,7 @@ class ScreenContainer(object): self.search_popover.popdown() text = '' for label, entry in self.search_table.fields: - if isinstance(entry, gtk.ComboBox): + if isinstance(entry, Gtk.ComboBoxText): value = quote(entry.get_active_text()) or None elif isinstance(entry, (Between, Selection)): value = entry.get_value() @@ -564,10 +573,10 @@ class ScreenContainer(object): self.search_popover = Gtk.Popover() self.search_popover.set_relative_to(widget) - vbox = gtk.VBox() + vbox = Gtk.VBox() fields = [f for f in self.screen.domain_parser.fields.values() if f.get('searchable', True)] - self.search_table = gtk.Table(rows=len(fields), columns=2) + self.search_table = Gtk.Table(n_rows=len(fields), n_columns=2) self.search_table.set_homogeneous(False) self.search_table.set_border_width(5) self.search_table.set_row_spacings(2) @@ -576,16 +585,14 @@ class ScreenContainer(object): # Fill table with fields self.search_table.fields = [] for i, field in enumerate(fields): - label = gtk.Label(field['string']) - label.set_alignment(0.0, 0.0) - self.search_table.attach(label, 0, 1, i, i + 1, - yoptions=gtk.FILL) + label = Gtk.Label( + label=field['string'], + halign=Gtk.Align.START, valign=Gtk.Align.START) + self.search_table.attach( + label, 0, 1, i, i + 1, yoptions=Gtk.AttachOptions.FILL) yoptions = False if field['type'] == 'boolean': - if hasattr(gtk, 'ComboBoxText'): - entry = gtk.ComboBoxText() - else: - entry = gtk.combo_box_new_text() + entry = Gtk.ComboBoxText() entry.append_text('') selections = (_('True'), _('False')) for selection in selections: @@ -593,7 +600,8 @@ class ScreenContainer(object): elif field['type'] == 'selection': selections = tuple(x[1] for x in field['selection']) entry = Selection(selections) - yoptions = gtk.FILL | gtk.EXPAND + yoptions = ( + Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND) elif field['type'] in ('date', 'datetime', 'time'): date_format = common.date_format( self.screen.context.get('date_format')) @@ -607,28 +615,30 @@ class ScreenContainer(object): entry = DateTimes(date_format, time_format) entry.connect('activate', lambda *a: search()) else: - entry = gtk.Entry() + entry = Gtk.Entry() entry.connect('activate', lambda *a: search()) label.set_mnemonic_widget(entry) self.search_table.attach(entry, 1, 2, i, i + 1, yoptions=yoptions) self.search_table.fields.append((field['string'], entry)) - scrolled = gtk.ScrolledWindow() - scrolled.add_with_viewport(self.search_table) - scrolled.set_shadow_type(gtk.SHADOW_NONE) - scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) - vbox.pack_start(scrolled, expand=True, fill=True) - find_button = gtk.Button(_('Find')) + scrolled = Gtk.ScrolledWindow() + scrolled.add(self.search_table) + scrolled.set_shadow_type(Gtk.ShadowType.NONE) + scrolled.set_policy( + Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) + vbox.pack_start(scrolled, expand=True, fill=True, padding=0) + find_button = Gtk.Button(label=_('Find')) find_button.connect('clicked', lambda *a: search()) find_button.set_image(common.IconFactory.get_image( - 'tryton-search', gtk.ICON_SIZE_SMALL_TOOLBAR)) + 'tryton-search', Gtk.IconSize.SMALL_TOOLBAR)) find_button.set_can_default(True) self.search_popover.set_default_widget(find_button) - hbuttonbox = gtk.HButtonBox() - hbuttonbox.pack_start(find_button) - hbuttonbox.set_layout(gtk.BUTTONBOX_END) - vbox.pack_start(hbuttonbox, expand=False, fill=True) + hbuttonbox = Gtk.HButtonBox() + hbuttonbox.pack_start( + find_button, expand=False, fill=False, padding=0) + hbuttonbox.set_layout(Gtk.ButtonBoxStyle.END) + vbox.pack_start(hbuttonbox, expand=False, fill=True, padding=0) self.search_popover.add(vbox) vbox.show_all() scrolled.set_size_request( @@ -642,7 +652,7 @@ class ScreenContainer(object): if self.last_search_text.strip() != self.get_text().strip(): for label, entry in self.search_table.fields: - if isinstance(entry, gtk.ComboBox): + if isinstance(entry, Gtk.ComboBoxText): entry.set_active(-1) elif isinstance(entry, Between): entry.set_value(None, None) diff --git a/tryton/gui/window/win_csv.py b/tryton/gui/window/win_csv.py index d2691de04a..562e1905ce 100644 --- a/tryton/gui/window/win_csv.py +++ b/tryton/gui/window/win_csv.py @@ -3,11 +3,10 @@ import locale import os import sys - -import gtk -import gobject import gettext +from gi.repository import Gdk, GObject, Gtk + from tryton.common import IconFactory from tryton.common.underline import set_underline from tryton.config import TRYTON_ICON @@ -37,103 +36,111 @@ class WinCSV(NoModal): def __init__(self, *args, **kwargs): super(WinCSV, self).__init__(*args, **kwargs) - self.dialog = gtk.Dialog( - parent=self.parent, flags=gtk.DIALOG_DESTROY_WITH_PARENT) + self.dialog = Gtk.Dialog( + transient_for=self.parent, destroy_with_parent=True) Main().add_window(self.dialog) - self.dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT) + self.dialog.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self.dialog.set_icon(TRYTON_ICON) self.dialog.set_default_size(*self.default_size()) self.dialog.connect('response', self.response) - dialog_vbox = gtk.VBox() + dialog_vbox = Gtk.VBox() - hbox_mapping = gtk.HBox(True) - dialog_vbox.pack_start(hbox_mapping, True, True, 0) + hbox_mapping = Gtk.HBox(homogeneous=True) + dialog_vbox.pack_start(hbox_mapping, expand=True, fill=True, padding=0) - frame_fields = gtk.Frame() - frame_fields.set_shadow_type(gtk.SHADOW_NONE) - viewport_fields = gtk.Viewport() - scrolledwindow_fields = gtk.ScrolledWindow() - scrolledwindow_fields.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) + frame_fields = Gtk.Frame() + frame_fields.set_shadow_type(Gtk.ShadowType.NONE) + viewport_fields = Gtk.Viewport() + scrolledwindow_fields = Gtk.ScrolledWindow() + scrolledwindow_fields.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) viewport_fields.add(scrolledwindow_fields) frame_fields.add(viewport_fields) - label_all_fields = gtk.Label(_('All fields')) - label_all_fields.set_use_markup(True) + label_all_fields = Gtk.Label( + label=_('All fields'), use_markup=True) frame_fields.set_label_widget(label_all_fields) - hbox_mapping.pack_start(frame_fields, True, True, 0) + hbox_mapping.pack_start( + frame_fields, expand=True, fill=True, padding=0) - vbox_buttons = gtk.VBox(False, 10) + vbox_buttons = Gtk.VBox(homogeneous=False, spacing=10) vbox_buttons.set_border_width(5) - hbox_mapping.pack_start(vbox_buttons, False, True, 0) + hbox_mapping.pack_start( + vbox_buttons, expand=False, fill=True, padding=0) - button_add = gtk.Button(_('_Add'), stock=None, use_underline=True) + button_add = Gtk.Button( + label=_('_Add'), stock=None, use_underline=True) button_add.set_image(IconFactory.get_image( - 'tryton-add', gtk.ICON_SIZE_BUTTON)) + 'tryton-add', Gtk.IconSize.BUTTON)) button_add.set_always_show_image(True) button_add.connect_after('clicked', self.sig_sel) - vbox_buttons.pack_start(button_add, False, False, 0) + vbox_buttons.pack_start( + button_add, expand=False, fill=False, padding=0) - button_remove = gtk.Button( - _('_Remove'), stock=None, use_underline=True) + button_remove = Gtk.Button( + label=_('_Remove'), stock=None, use_underline=True) button_remove.set_image(IconFactory.get_image( - 'tryton-remove', gtk.ICON_SIZE_BUTTON)) + 'tryton-remove', Gtk.IconSize.BUTTON)) button_remove.set_always_show_image(True) button_remove.connect_after('clicked', self.sig_unsel) - vbox_buttons.pack_start(button_remove, False, False, 0) + vbox_buttons.pack_start( + button_remove, expand=False, fill=False, padding=0) - button_remove_all = gtk.Button( - _('_Clear'), stock=None, use_underline=True) + button_remove_all = Gtk.Button( + label=_('_Clear'), stock=None, use_underline=True) button_remove_all.set_image(IconFactory.get_image( - 'tryton-clear', gtk.ICON_SIZE_BUTTON)) + 'tryton-clear', Gtk.IconSize.BUTTON)) button_remove_all.set_always_show_image(True) button_remove_all.connect_after('clicked', self.sig_unsel_all) - vbox_buttons.pack_start(button_remove_all, False, False, 0) + vbox_buttons.pack_start( + button_remove_all, expand=False, fill=False, padding=0) - hseparator_buttons = gtk.HSeparator() - vbox_buttons.pack_start(hseparator_buttons, False, False, 3) + hseparator_buttons = Gtk.HSeparator() + vbox_buttons.pack_start( + hseparator_buttons, expand=False, fill=False, padding=3) self.add_buttons(vbox_buttons) - frame_fields_selected = gtk.Frame() - frame_fields_selected.set_shadow_type(gtk.SHADOW_NONE) - viewport_fields_selected = gtk.Viewport() - scrolledwindow_fields_selected = gtk.ScrolledWindow() + frame_fields_selected = Gtk.Frame() + frame_fields_selected.set_shadow_type(Gtk.ShadowType.NONE) + viewport_fields_selected = Gtk.Viewport() + scrolledwindow_fields_selected = Gtk.ScrolledWindow() scrolledwindow_fields_selected.set_policy( - gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) viewport_fields_selected.add(scrolledwindow_fields_selected) frame_fields_selected.add(viewport_fields_selected) - label_fields_selected = gtk.Label(_('Fields selected')) - label_fields_selected .set_use_markup(True) + label_fields_selected = Gtk.Label( + label=_('Fields selected'), use_markup=True) frame_fields_selected.set_label_widget(label_fields_selected) - hbox_mapping.pack_start(frame_fields_selected, True, True, 0) + hbox_mapping.pack_start( + frame_fields_selected, expand=True, fill=True, padding=0) - frame_csv_param = gtk.Frame() - frame_csv_param.set_shadow_type(gtk.SHADOW_ETCHED_OUT) - dialog_vbox.pack_start(frame_csv_param, False, True, 0) - alignment_csv_param = gtk.Alignment(0.5, 0.5, 1, 1) - alignment_csv_param.set_padding(7, 7, 7, 7) - frame_csv_param.add(alignment_csv_param) + frame_csv_param = Gtk.Frame() + frame_csv_param.set_shadow_type(Gtk.ShadowType.ETCHED_OUT) + dialog_vbox.pack_start( + frame_csv_param, expand=False, fill=True, padding=0) - vbox_csv_param = gtk.VBox() - alignment_csv_param.add(vbox_csv_param) + vbox_csv_param = Gtk.VBox() + vbox_csv_param.props.margin = 7 + frame_csv_param.add(vbox_csv_param) self.add_chooser(vbox_csv_param) - expander_csv = gtk.Expander() - vbox_csv_param.pack_start(expander_csv, False, True, 0) - label_csv_param = gtk.Label(_('CSV Parameters')) + expander_csv = Gtk.Expander() + vbox_csv_param.pack_start( + expander_csv, expand=False, fill=True, padding=0) + label_csv_param = Gtk.Label(label=_('CSV Parameters')) expander_csv.set_label_widget(label_csv_param) - table = gtk.Table(2, 4, False) + table = Gtk.Table(n_rows=2, n_columns=4, homogeneous=False) table.set_border_width(8) table.set_row_spacings(9) table.set_col_spacings(8) expander_csv.add(table) - label_csv_delimiter = gtk.Label(_('Delimiter:')) - label_csv_delimiter.set_alignment(1, 0.5) + label_csv_delimiter = Gtk.Label( + label=_('Delimiter:'), halign=Gtk.Align.END) table.attach(label_csv_delimiter, 0, 1, 0, 1) - self.csv_delimiter = gtk.Entry() + self.csv_delimiter = Gtk.Entry() self.csv_delimiter.set_max_length(1) if os.name == 'nt' and ',' == locale.localeconv()['decimal_point']: delimiter = ';' @@ -144,22 +151,19 @@ class WinCSV(NoModal): label_csv_delimiter.set_mnemonic_widget(self.csv_delimiter) table.attach(self.csv_delimiter, 1, 2, 0, 1) - label_csv_quotechar = gtk.Label(_("Quote char:")) - label_csv_quotechar.set_alignment(1, 0.5) + label_csv_quotechar = Gtk.Label( + label=_("Quote char:"), halign=Gtk.Align.END) table.attach(label_csv_quotechar, 2, 3, 0, 1) - self.csv_quotechar = gtk.Entry() + self.csv_quotechar = Gtk.Entry() self.csv_quotechar.set_text("\"") self.csv_quotechar.set_width_chars(1) label_csv_quotechar.set_mnemonic_widget(self.csv_quotechar) table.attach(self.csv_quotechar, 3, 4, 0, 1) - label_csv_enc = gtk.Label(_("Encoding:")) - label_csv_enc.set_alignment(1, 0.5) + label_csv_enc = Gtk.Label( + label=_("Encoding:"), halign=Gtk.Align.END) table.attach(label_csv_enc, 0, 1, 1, 2) - if hasattr(gtk, 'ComboBoxText'): - self.csv_enc = gtk.ComboBoxText() - else: - self.csv_enc = gtk.combo_box_new_text() + self.csv_enc = Gtk.ComboBoxText() for i, encoding in enumerate(encodings): self.csv_enc.append_text(encoding) if ((os.name == 'nt' and encoding == 'cp1252') @@ -171,37 +175,38 @@ class WinCSV(NoModal): self.add_csv_header_param(table) button_cancel = self.dialog.add_button( - set_underline(_("Cancel")), gtk.RESPONSE_CANCEL) + set_underline(_("Cancel")), Gtk.ResponseType.CANCEL) button_cancel.set_image(IconFactory.get_image( - 'tryton-cancel', gtk.ICON_SIZE_BUTTON)) + 'tryton-cancel', Gtk.IconSize.BUTTON)) button_ok = self.dialog.add_button( - set_underline(_("OK")), gtk.RESPONSE_OK) + set_underline(_("OK")), Gtk.ResponseType.OK) button_ok.set_image(IconFactory.get_image( - 'tryton-ok', gtk.ICON_SIZE_BUTTON)) + 'tryton-ok', Gtk.IconSize.BUTTON)) - self.dialog.vbox.pack_start(dialog_vbox) + self.dialog.vbox.pack_start( + dialog_vbox, expand=True, fill=True, padding=0) - self.view1 = gtk.TreeView() - self.view1.get_selection().set_mode(gtk.SELECTION_MULTIPLE) + self.view1 = Gtk.TreeView() + self.view1.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self.view1.connect('row-expanded', self.on_row_expanded) scrolledwindow_fields.add(self.view1) - self.view2 = gtk.TreeView() - self.view2.get_selection().set_mode(gtk.SELECTION_MULTIPLE) + self.view2 = Gtk.TreeView() + self.view2.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) scrolledwindow_fields_selected.add(self.view2) self.view1.set_headers_visible(False) self.view2.set_headers_visible(False) - cell = gtk.CellRendererText() - column = gtk.TreeViewColumn(_('Field name'), cell, text=0) + cell = Gtk.CellRendererText() + column = Gtk.TreeViewColumn(_('Field name'), cell, text=0) self.view1.append_column(column) - cell = gtk.CellRendererText() - column = gtk.TreeViewColumn(_('Field name'), cell, text=0) + cell = Gtk.CellRendererText() + column = Gtk.TreeViewColumn(_('Field name'), cell, text=0) self.view2.append_column(column) - self.model1 = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING) - self.model2 = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) + self.model1 = Gtk.TreeStore(GObject.TYPE_STRING, GObject.TYPE_STRING) + self.model2 = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) self.model_populate(self._get_fields(self.model)) @@ -217,14 +222,15 @@ class WinCSV(NoModal): if sys.platform != 'darwin': self.view2.drag_source_set( - gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK, - [gtk.TargetEntry.new( - 'EXPORT_TREE', gtk.TARGET_SAME_WIDGET, 0)], - gtk.gdk.ACTION_MOVE) - self.view2.drag_dest_set(gtk.DEST_DEFAULT_ALL, - [gtk.TargetEntry.new( - 'EXPORT_TREE', gtk.TARGET_SAME_WIDGET, 0)], - gtk.gdk.ACTION_MOVE) + Gdk.ModifierType.BUTTON1_MASK | Gdk.ModifierType.BUTTON3_MASK, + [Gtk.TargetEntry.new( + 'EXPORT_TREE', Gtk.TargetFlags.SAME_WIDGET, 0)], + Gdk.DragAction.MOVE) + self.view2.drag_dest_set( + Gtk.DestDefaults.ALL, + [Gtk.TargetEntry.new( + 'EXPORT_TREE', Gtk.TargetFlags.SAME_WIDGET, 0)], + Gdk.DragAction.MOVE) self.view2.connect('drag-begin', self.drag_begin) self.view2.connect('drag-motion', self.drag_motion) self.view2.connect('drag-drop', self.drag_drop) @@ -240,20 +246,17 @@ class WinCSV(NoModal): treeview.set_drag_dest_row(*treeview.get_dest_row_at_pos(x, y)) except TypeError: treeview.set_drag_dest_row(len(treeview.get_model()) - 1, - gtk.TREE_VIEW_DROP_AFTER) - if hasattr(gtk.gdk, 'drag_status'): - gtk.gdk.drag_status(context, gtk.gdk.ACTION_MOVE, time) - else: - context.drag_status(gtk.gdk.ACTION_MOVE, time) + Gtk.TreeViewDropPosition.AFTER) + Gdk.drag_status(context, Gdk.DragAction.MOVE, time) return True def drag_drop(self, treeview, context, x, y, time): - treeview.emit_stop_by_name('drag-drop') + treeview.stop_emission_by_name('drag-drop') return True def drag_data_get(self, treeview, context, selection, target_id, etime): - treeview.emit_stop_by_name('drag-data-get') + treeview.stop_emission_by_name('drag-data-get') def _func_sel_get(store, path, iter_, data): data.append(path[0]) @@ -268,7 +271,7 @@ class WinCSV(NoModal): def drag_data_received(self, treeview, context, x, y, selection, info, etime): - treeview.emit_stop_by_name('drag-data-received') + treeview.stop_emission_by_name('drag-data-received') try: selection_data = selection.data except AttributeError: @@ -285,22 +288,19 @@ class WinCSV(NoModal): pos = store.get_iter(path) else: pos = store.get_iter((len(store) - 1,)) - position = gtk.TREE_VIEW_DROP_AFTER - if position == gtk.TREE_VIEW_DROP_AFTER: + position = Gtk.TreeViewDropPosition.AFTER + if position == Gtk.TreeViewDropPosition.AFTER: data_iters = reversed(data_iters) for item in data_iters: - if position == gtk.TREE_VIEW_DROP_BEFORE: + if position == Gtk.TreeViewDropPosition.BEFORE: store.move_before(item, pos) else: store.move_after(item, pos) - if hasattr(gtk.gdk, 'drop_finish'): - gtk.gdk.drop_finish(context, False, etime) - else: - context.drop_finish(False, etime) + Gdk.drop_finish(context, False, etime) return True def drag_data_delete(self, treeview, context): - treeview.emit_stop_by_name('drag-data-delete') + treeview.stop_emission_by_name('drag-data-delete') def get_delimiter(self): return self.csv_delimiter.get_text() or ',' diff --git a/tryton/gui/window/win_export.py b/tryton/gui/window/win_export.py index 7406ddf7c8..938c087882 100644 --- a/tryton/gui/window/win_export.py +++ b/tryton/gui/window/win_export.py @@ -3,11 +3,10 @@ import csv import os import tempfile - -import gtk -import gobject import gettext +from gi.repository import Gdk, GObject, Gtk + import tryton.common as common from tryton.common import RPCExecute, RPCException from tryton.gui.window.win_csv import WinCSV @@ -28,63 +27,62 @@ class WinExport(WinCSV): self.dialog.set_title(_('CSV Export: %s') % name) def add_buttons(self, box): - button_save_export = gtk.Button( - _('_Save Export'), stock=None, use_underline=True) + button_save_export = Gtk.Button( + label=_('_Save Export'), stock=None, use_underline=True) button_save_export.set_image(common.IconFactory.get_image( - 'tryton-save', gtk.ICON_SIZE_BUTTON)) + 'tryton-save', Gtk.IconSize.BUTTON)) button_save_export.set_always_show_image(True) button_save_export.connect_after('clicked', self.addreplace_predef) - box.pack_start(button_save_export, False, False, 0) + box.pack_start( + button_save_export, expand=False, fill=False, padding=0) - button_del_export = gtk.Button( - _('_Delete Export'), stock=None, use_underline=True) + button_del_export = Gtk.Button( + label=_('_Delete Export'), stock=None, use_underline=True) button_del_export.set_image(common.IconFactory.get_image( - 'tryton-delete', gtk.ICON_SIZE_BUTTON)) + 'tryton-delete', Gtk.IconSize.BUTTON)) button_del_export.set_always_show_image(True) button_del_export.connect_after('clicked', self.remove_predef) - box.pack_start(button_del_export, False, False, 0) + box.pack_start(button_del_export, expand=False, fill=False, padding=0) - frame_predef_exports = gtk.Frame() + frame_predef_exports = Gtk.Frame() frame_predef_exports.set_border_width(2) - frame_predef_exports.set_shadow_type(gtk.SHADOW_NONE) - box.pack_start(frame_predef_exports, True, True, 0) - viewport_exports = gtk.Viewport() - scrolledwindow_exports = gtk.ScrolledWindow() - scrolledwindow_exports.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) - label_predef_exports = gtk.Label(_("Predefined exports")) - label_predef_exports.set_use_markup(True) + frame_predef_exports.set_shadow_type(Gtk.ShadowType.NONE) + box.pack_start(frame_predef_exports, expand=True, fill=True, padding=0) + viewport_exports = Gtk.Viewport() + scrolledwindow_exports = Gtk.ScrolledWindow() + scrolledwindow_exports.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + label_predef_exports = Gtk.Label( + label=_("Predefined exports"), use_markup=True) frame_predef_exports.set_label_widget(label_predef_exports) viewport_exports.add(scrolledwindow_exports) frame_predef_exports.add(viewport_exports) - self.pref_export = gtk.TreeView() - self.pref_export.append_column(gtk.TreeViewColumn(_('Name'), - gtk.CellRendererText(), text=2)) + self.pref_export = Gtk.TreeView() + self.pref_export.append_column( + Gtk.TreeViewColumn(_('Name'), Gtk.CellRendererText(), text=2)) scrolledwindow_exports.add(self.pref_export) self.pref_export.connect("button-press-event", self.export_click) self.pref_export.connect("key-press-event", self.export_keypress) - self.predef_model = gtk.ListStore( - gobject.TYPE_INT, - gobject.TYPE_PYOBJECT, - gobject.TYPE_STRING) + self.predef_model = Gtk.ListStore( + GObject.TYPE_INT, + GObject.TYPE_PYOBJECT, + GObject.TYPE_STRING) self.fill_predefwin() def add_chooser(self, box): - hbox_csv_export = gtk.HBox() - box.pack_start(hbox_csv_export, False, True, 0) - if hasattr(gtk, 'ComboBoxText'): - self.saveas = gtk.ComboBoxText() - else: - self.saveas = gtk.combo_box_new_text() - hbox_csv_export.pack_start(self.saveas, True, True, 0) + hbox_csv_export = Gtk.HBox() + box.pack_start(hbox_csv_export, expand=False, fill=True, padding=0) + self.saveas = Gtk.ComboBoxText() + hbox_csv_export.pack_start( + self.saveas, expand=True, fill=True, padding=0) self.saveas.append_text(_("Open")) self.saveas.append_text(_("Save")) self.saveas.set_active(0) def add_csv_header_param(self, table): - self.add_field_names = gtk.CheckButton(_("Add _field names")) + self.add_field_names = Gtk.CheckButton(label=_("Add _field names")) self.add_field_names.set_active(True) table.attach(self.add_field_names, 2, 4, 1, 2) @@ -268,7 +266,7 @@ class WinExport(WinCSV): self.model2.append((long_string, name)) def response(self, dialog, response): - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: fields = [] fields2 = [] iter = self.model2.get_iter_first() @@ -291,7 +289,7 @@ class WinExport(WinCSV): common.file_open(fname, 'csv') else: fname = common.file_selection(_('Save As...'), - action=gtk.FILE_CHOOSER_ACTION_SAVE) + action=Gtk.FileChooserAction.SAVE) if fname: self.export_csv(fname, fields2, data) self.destroy() @@ -328,7 +326,7 @@ class WinExport(WinCSV): return path, col, x, y = path_at_pos selection = treeview.get_selection() - if event.type == gtk.gdk._2BUTTON_PRESS: + if event.type == Gdk.EventType._2BUTTON_PRESS: self.sel_predef(path) selection.select_path(path) return True @@ -337,7 +335,7 @@ class WinExport(WinCSV): return True def export_keypress(self, treeview, event): - if event.keyval not in (gtk.keysyms.Return, gtk.keysyms.space): + if event.keyval not in [Gdk.KEY_Return, Gdk.KEY_.space]: return model, selected = treeview.get_selection().get_selected() if not selected: diff --git a/tryton/gui/window/win_form.py b/tryton/gui/window/win_form.py index 50ae285740..a3b3d797aa 100644 --- a/tryton/gui/window/win_form.py +++ b/tryton/gui/window/win_form.py @@ -1,14 +1,15 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -from tryton.common import TRYTON_ICON -import tryton.common as common -import gtk -import pango import gettext +from gi.repository import Gdk, Gtk, Pango + from .infobar import InfoBar +import tryton.common as common +from tryton.common import TRYTON_ICON from tryton.common.domain_parser import quote from tryton.common.underline import set_underline +from tryton.common.widget_style import widget_class from tryton.gui import Main from tryton.gui.window.nomodal import NoModal @@ -38,10 +39,11 @@ class WinForm(NoModal, InfoBar): return if new: self.screen.new(rec_name=rec_name) - self.win = gtk.Dialog(_('Link'), self.parent, - gtk.DIALOG_DESTROY_WITH_PARENT) + self.win = Gtk.Dialog( + title=_('Link'), transient_for=self.parent, + destroy_with_parent=True) Main().add_window(self.win) - self.win.set_position(gtk.WIN_POS_CENTER_ON_PARENT) + self.win.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self.win.set_icon(TRYTON_ICON) self.win.set_deletable(False) self.win.connect('delete-event', lambda *a: True) @@ -50,7 +52,7 @@ class WinForm(NoModal, InfoBar): self.win.set_default_size(*self.default_size()) - self.accel_group = gtk.AccelGroup() + self.accel_group = Gtk.AccelGroup() self.win.add_accel_group(self.accel_group) readonly = self.screen.readonly or self.screen.group.readonly @@ -66,184 +68,183 @@ class WinForm(NoModal, InfoBar): label, icon = _("Cancel"), 'tryton-cancel' self._initial_value = self.screen.current_record.get_eval() self.but_cancel = self.win.add_button( - set_underline(label), gtk.RESPONSE_CANCEL) + set_underline(label), Gtk.ResponseType.CANCEL) self.but_cancel.set_image(common.IconFactory.get_image( - icon, gtk.ICON_SIZE_BUTTON)) + icon, Gtk.IconSize.BUTTON)) self.but_cancel.set_always_show_image(True) if new and self.many: self.but_new = self.win.add_button( - set_underline(_("New")), gtk.RESPONSE_ACCEPT) + set_underline(_("New")), Gtk.ResponseType.ACCEPT) self.but_new.set_image(common.IconFactory.get_image( - 'tryton-create', gtk.ICON_SIZE_BUTTON)) + 'tryton-create', Gtk.IconSize.BUTTON)) self.but_new.set_always_show_image(True) self.but_new.set_accel_path('/Form/New', self.accel_group) if self.save_current: - self.but_ok = gtk.Button(_('_Save'), use_underline=True) + self.but_ok = Gtk.Button(label=_('_Save'), use_underline=True) self.but_ok.set_image(common.IconFactory.get_image( - 'tryton-save', gtk.ICON_SIZE_BUTTON)) + 'tryton-save', Gtk.IconSize.BUTTON)) self.but_ok.set_always_show_image(True) self.but_ok.set_accel_path('/Form/Save', self.accel_group) self.but_ok.set_can_default(True) self.but_ok.show() - self.win.add_action_widget(self.but_ok, gtk.RESPONSE_OK) + self.win.add_action_widget(self.but_ok, Gtk.ResponseType.OK) if not new: self.but_ok.props.sensitive = False else: self.but_ok = self.win.add_button( - set_underline(_("OK")), gtk.RESPONSE_OK) + set_underline(_("OK")), Gtk.ResponseType.OK) self.but_ok.set_image(common.IconFactory.get_image( - 'tryton-ok', gtk.ICON_SIZE_BUTTON)) + 'tryton-ok', Gtk.IconSize.BUTTON)) self.but_ok.set_always_show_image(True) self.but_ok.add_accelerator('clicked', self.accel_group, - gtk.keysyms.Return, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) - self.win.set_default_response(gtk.RESPONSE_OK) + Gdk.KEY_Return, Gdk.ModifierType.CONTROL_MASK, + Gtk.AccelFlags.VISIBLE) + self.win.set_default_response(Gtk.ResponseType.OK) self.win.set_title(self.title) - title = gtk.Label() - title.modify_font(pango.FontDescription("bold 12")) - title.set_label(common.ellipsize(self.title, 80)) + title = Gtk.Label( + label=common.ellipsize(self.title, 80), + halign=Gtk.Align.START, margin=5, + ellipsize=Pango.EllipsizeMode.END) tooltips.set_tip(title, self.title) - title.set_padding(20, 3) - title.set_alignment(0.0, 0.5) title.set_size_request(0, -1) # Allow overflow - title.set_max_width_chars(1) - title.set_ellipsize(pango.ELLIPSIZE_END) - title.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000")) title.show() - hbox = gtk.HBox() - hbox.pack_start(title, expand=True, fill=True) + hbox = Gtk.HBox() + hbox.pack_start(title, expand=True, fill=True, padding=0) hbox.show() - frame = gtk.Frame() - frame.set_shadow_type(gtk.SHADOW_ETCHED_IN) + frame = Gtk.Frame() + frame.set_shadow_type(Gtk.ShadowType.ETCHED_IN) + widget_class(frame, 'window-title', True) frame.add(hbox) frame.show() - eb = gtk.EventBox() - eb.add(frame) - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#ffffff")) - eb.show() - - self.win.vbox.pack_start(eb, expand=False, fill=True, padding=3) + self.win.vbox.pack_start(frame, expand=False, fill=True, padding=3) if view_type == 'tree': - hbox = gtk.HBox(homogeneous=False, spacing=0) + hbox = Gtk.HBox(homogeneous=False, spacing=0) + hbox.set_halign(Gtk.Align.END) access = common.MODELACCESS[screen.model_name] - but_switch = gtk.Button() + but_switch = Gtk.Button() tooltips.set_tip(but_switch, _('Switch')) but_switch.connect('clicked', self.switch_view) but_switch.add(common.IconFactory.get_image( - 'tryton-switch', gtk.ICON_SIZE_SMALL_TOOLBAR)) - but_switch.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(but_switch, expand=False, fill=False) + 'tryton-switch', Gtk.IconSize.SMALL_TOOLBAR)) + but_switch.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(but_switch, expand=False, fill=False, padding=0) - self.but_pre = gtk.Button() + self.but_pre = Gtk.Button() tooltips.set_tip(self.but_pre, _('Previous')) self.but_pre.connect('clicked', self._sig_previous) self.but_pre.add(common.IconFactory.get_image( - 'tryton-back', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_pre.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_pre, expand=False, fill=False) + 'tryton-back', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_pre.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_pre, expand=False, fill=False, padding=0) - self.label = gtk.Label('(0,0)') - hbox.pack_start(self.label, expand=False, fill=False) + self.label = Gtk.Label(label='(0,0)') + hbox.pack_start(self.label, expand=False, fill=False, padding=0) - self.but_next = gtk.Button() + self.but_next = Gtk.Button() tooltips.set_tip(self.but_next, _('Next')) self.but_next.connect('clicked', self._sig_next) self.but_next.add(common.IconFactory.get_image( - 'tryton-forward', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_next.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_next, expand=False, fill=False) + 'tryton-forward', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_next.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_next, expand=False, fill=False, padding=0) - hbox.pack_start(gtk.VSeparator(), expand=False, fill=True) + hbox.pack_start( + Gtk.VSeparator(), expand=False, fill=True, padding=0) if domain is not None: - self.wid_text = gtk.Entry() + self.wid_text = Gtk.Entry() self.wid_text.set_property('width_chars', 13) self.wid_text.connect('activate', self._sig_activate) self.wid_text.connect('focus-out-event', self._focus_out) - hbox.pack_start(self.wid_text, expand=True, fill=True) + hbox.pack_start( + self.wid_text, expand=True, fill=True, padding=0) - self.but_add = gtk.Button() + self.but_add = Gtk.Button() tooltips.set_tip(self.but_add, _('Add')) self.but_add.connect('clicked', self._sig_add) self.but_add.add(common.IconFactory.get_image( - 'tryton-add', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_add.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_add, expand=False, fill=False) + 'tryton-add', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_add.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start( + self.but_add, expand=False, fill=False, padding=0) if not access['read'] or readonly: self.but_add.set_sensitive(False) - self.but_remove = gtk.Button() + self.but_remove = Gtk.Button() tooltips.set_tip(self.but_remove, _('Remove ')) self.but_remove.connect('clicked', self._sig_remove, True) self.but_remove.add(common.IconFactory.get_image( - 'tryton-remove', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_remove.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_remove, expand=False, fill=False) + 'tryton-remove', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_remove.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start( + self.but_remove, expand=False, fill=False, padding=0) if not access['read'] or readonly: self.but_remove.set_sensitive(False) - hbox.pack_start(gtk.VSeparator(), expand=False, fill=True) + hbox.pack_start( + Gtk.VSeparator(), expand=False, fill=True, padding=0) - self.but_new = gtk.Button() + self.but_new = Gtk.Button() tooltips.set_tip(self.but_new, _('Create a new record ')) self.but_new.connect('clicked', self._sig_new) self.but_new.add(common.IconFactory.get_image( - 'tryton-create', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_new.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_new, expand=False, fill=False) + 'tryton-create', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_new.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_new, expand=False, fill=False, padding=0) if not access['create'] or readonly: self.but_new.set_sensitive(False) - self.but_del = gtk.Button() + self.but_del = Gtk.Button() tooltips.set_tip(self.but_del, _('Delete selected record ')) self.but_del.connect('clicked', self._sig_remove, False) self.but_del.add(common.IconFactory.get_image( - 'tryton-delete', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_del.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_del, expand=False, fill=False) + 'tryton-delete', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_del.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start(self.but_del, expand=False, fill=False, padding=0) if not access['delete'] or readonly: self.but_del.set_sensitive(False) - self.but_undel = gtk.Button() + self.but_undel = Gtk.Button() tooltips.set_tip(self.but_undel, _('Undelete selected record ')) self.but_undel.connect('clicked', self._sig_undelete) self.but_undel.add(common.IconFactory.get_image( - 'tryton-undo', gtk.ICON_SIZE_SMALL_TOOLBAR)) - self.but_undel.set_relief(gtk.RELIEF_NONE) - hbox.pack_start(self.but_undel, expand=False, fill=False) + 'tryton-undo', Gtk.IconSize.SMALL_TOOLBAR)) + self.but_undel.set_relief(Gtk.ReliefStyle.NONE) + hbox.pack_start( + self.but_undel, expand=False, fill=False, padding=0) if not access['delete'] or readonly: self.but_undel.set_sensitive(False) but_switch.props.sensitive = screen.number_of_views > 1 tooltips.enable() + hbox.show_all() - alignment = gtk.Alignment(1.0) - alignment.add(hbox) - alignment.show_all() + self.win.vbox.pack_start( + hbox, expand=False, fill=True, padding=0) - self.win.vbox.pack_start(alignment, expand=False, fill=True) - - scroll = gtk.ScrolledWindow() - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scroll.set_placement(gtk.CORNER_TOP_LEFT) - scroll.set_shadow_type(gtk.SHADOW_NONE) + scroll = Gtk.ScrolledWindow() + scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scroll.set_placement(Gtk.CornerType.TOP_LEFT) + scroll.set_shadow_type(Gtk.ShadowType.NONE) scroll.show() - self.win.vbox.pack_start(scroll, expand=True, fill=True) + self.win.vbox.pack_start(scroll, expand=True, fill=True, padding=0) scroll.add(self.screen.screen_container.alternate_viewport) self.create_info_bar() - self.win.vbox.pack_start(self.info_bar, False, True) + self.win.vbox.pack_start( + self.info_bar, expand=False, fill=True, padding=0) if view_type == 'tree': self.screen.signal_connect(self, 'record-message', self._sig_label) @@ -263,12 +264,12 @@ class WinForm(NoModal, InfoBar): self.screen.current_view.set_cursor() def on_keypress(self, widget, event): - if (event.keyval == gtk.keysyms.F3) \ - and self.but_new.get_property('sensitive'): + if ((event.keyval == Gdk.KEY_F3) + and self.but_new.get_property('sensitive')): self._sig_new(widget) return False - if event.keyval in (gtk.keysyms.Delete, gtk.keysyms.KP_Delete) \ - and widget == self.screen.screen_container.alternate_viewport: + if (event.keyval in [Gdk.KEY_Delete, Gdk.KEY_KP_Delete] + and widget == self.screen.screen_container.alternate_viewport): self._sig_remove(widget) return False @@ -353,16 +354,17 @@ class WinForm(NoModal, InfoBar): sensitive = modified or self.but_ok.props.sensitive self.but_ok.props.sensitive = sensitive self.win.set_default_response( - gtk.RESPONSE_OK if sensitive else gtk.RESPONSE_CANCEL) + Gtk.ResponseType.OK if sensitive else Gtk.ResponseType.CANCEL) def close(self, widget): - widget.emit_stop_by_name('close') - self.response(self.win, gtk.RESPONSE_CANCEL) + widget.stop_emission_by_name('close') + self.response(self.win, Gtk.ResponseType.CANCEL) return True def response(self, win, response_id): validate = False - cancel_responses = (gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT) + cancel_responses = [ + Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT] self.screen.current_view.set_value() readonly = self.screen.group.readonly if (response_id not in cancel_responses @@ -386,12 +388,12 @@ class WinForm(NoModal, InfoBar): validate = record.pre_validate() if not validate: self.message_info(self.screen.invalid_message(), - gtk.MESSAGE_ERROR) + Gtk.MessageType.ERROR) self.screen.set_cursor() self.screen.display() return self.message_info() - if response_id == gtk.RESPONSE_ACCEPT: + if response_id == Gtk.ResponseType.ACCEPT: self.new() return if (self.screen.current_record @@ -418,7 +420,7 @@ class WinForm(NoModal, InfoBar): self.many -= 1 if self.many == 0: self.but_new.set_sensitive(False) - self.win.set_default_response(gtk.RESPONSE_OK) + self.win.set_default_response(Gtk.ResponseType.OK) def destroy(self): self.screen.screen_container.alternate_view = False diff --git a/tryton/gui/window/win_import.py b/tryton/gui/window/win_import.py index 7be0888107..fecf8603e7 100644 --- a/tryton/gui/window/win_import.py +++ b/tryton/gui/window/win_import.py @@ -3,7 +3,7 @@ import csv import gettext -import gtk +from gi.repository import Gtk import tryton.common as common from tryton.common import RPCExecute, RPCException @@ -26,31 +26,35 @@ class WinImport(WinCSV): self.dialog.set_title(_('CSV Import: %s') % name) def add_buttons(self, box): - button_autodetect = gtk.Button( - _('_Auto-Detect'), stock=None, use_underline=True) - button_autodetect.set_alignment(0.0, 0.0) + button_autodetect = Gtk.Button( + label=_('_Auto-Detect'), stock=None, use_underline=True) button_autodetect.set_image(common.IconFactory.get_image( - 'tryton-search', gtk.ICON_SIZE_BUTTON)) + 'tryton-search', Gtk.IconSize.BUTTON)) button_autodetect.set_always_show_image(True) button_autodetect.connect_after('clicked', self.sig_autodetect) - box.pack_start(button_autodetect, False, False, 0) + box.pack_start( + button_autodetect, expand=False, fill=False, padding=0) def add_chooser(self, box): - hbox_csv_import = gtk.HBox() - box.pack_start(hbox_csv_import, False, True, 4) - label_csv_import = gtk.Label(_("File to Import:")) + hbox_csv_import = Gtk.HBox() + box.pack_start(hbox_csv_import, expand=False, fill=True, padding=4) + label_csv_import = Gtk.Label(label=_("File to Import:")) hbox_csv_import.pack_start(label_csv_import, False, False, 0) - self.import_csv_file = gtk.FileChooserButton(_("Open...")) + self.import_csv_file = Gtk.FileChooserButton(title=_("Open...")) label_csv_import.set_mnemonic_widget(self.import_csv_file) - hbox_csv_import.pack_start(self.import_csv_file, True, True, 0) + hbox_csv_import.pack_start( + self.import_csv_file, expand=True, fill=True, padding=0) def add_csv_header_param(self, table): - label_csv_skip = gtk.Label(_('Lines to Skip:')) - label_csv_skip.set_alignment(1, 0.5) + label_csv_skip = Gtk.Label( + label=_('Lines to Skip:'), halign=Gtk.Align.START) table.attach(label_csv_skip, 2, 3, 1, 2) - self.csv_skip = gtk.SpinButton() - self.csv_skip.configure(gtk.Adjustment(0, 0, 100, 1, 10), 1, 0) + self.csv_skip = Gtk.SpinButton() + self.csv_skip.configure(Gtk.Adjustment( + value=0, lower=0, upper=100, + step_increment=1, page_increment=10), + 1, 0) label_csv_skip.set_mnemonic_widget(self.csv_skip) table.attach(self.csv_skip, 3, 4, 1, 2) @@ -163,7 +167,7 @@ class WinImport(WinCSV): self.model2.clear() def response(self, dialog, response): - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: fields = [] iter = self.model2.get_iter_first() while iter: diff --git a/tryton/gui/window/win_search.py b/tryton/gui/window/win_search.py index 3faf99403b..67c51d9550 100644 --- a/tryton/gui/window/win_search.py +++ b/tryton/gui/window/win_search.py @@ -1,8 +1,9 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -import gtk import gettext +from gi.repository import Gtk, Gdk + import tryton.common as common from tryton.common.underline import set_underline from tryton.config import TRYTON_ICON @@ -33,49 +34,52 @@ class WinSearch(NoModal): self.callback = callback self.title = title - self.win = gtk.Dialog(_('Search'), self.parent, - gtk.DIALOG_DESTROY_WITH_PARENT) + self.win = Gtk.Dialog( + title=_('Search'), transient_for=self.parent, + destroy_with_parent=True) Main().add_window(self.win) self.win.set_icon(TRYTON_ICON) - self.win.set_position(gtk.WIN_POS_CENTER_ON_PARENT) - self.win.set_default_response(gtk.RESPONSE_APPLY) + self.win.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) + self.win.set_default_response(Gtk.ResponseType.APPLY) self.win.connect('response', self.response) self.win.set_default_size(*self.default_size()) - self.accel_group = gtk.AccelGroup() + self.accel_group = Gtk.AccelGroup() self.win.add_accel_group(self.accel_group) self.but_cancel = self.win.add_button( - set_underline(_("Cancel")), gtk.RESPONSE_CANCEL) + set_underline(_("Cancel")), Gtk.ResponseType.CANCEL) self.but_cancel.set_image(common.IconFactory.get_image( - 'tryton-cancel', gtk.ICON_SIZE_BUTTON)) + 'tryton-cancel', Gtk.IconSize.BUTTON)) self.but_cancel.set_always_show_image(True) self.but_find = self.win.add_button( - set_underline(_("Search")), gtk.RESPONSE_APPLY) + set_underline(_("Search")), Gtk.ResponseType.APPLY) self.but_find.set_image(common.IconFactory.get_image( - 'tryton-search', gtk.ICON_SIZE_BUTTON)) + 'tryton-search', Gtk.IconSize.BUTTON)) self.but_find.set_always_show_image(True) if new and common.MODELACCESS[model]['create']: self.but_new = self.win.add_button( - set_underline(_("New")), gtk.RESPONSE_ACCEPT) + set_underline(_("New")), Gtk.ResponseType.ACCEPT) self.but_new.set_image(common.IconFactory.get_image( - 'tryton-create', gtk.ICON_SIZE_BUTTON)) + 'tryton-create', Gtk.IconSize.BUTTON)) self.but_new.set_always_show_image(True) self.but_new.set_accel_path('/Form/New', self.accel_group) self.but_ok = self.win.add_button( - set_underline(_("OK")), gtk.RESPONSE_OK) + set_underline(_("OK")), Gtk.ResponseType.OK) self.but_ok.set_image(common.IconFactory.get_image( - 'tryton-ok', gtk.ICON_SIZE_BUTTON)) + 'tryton-ok', Gtk.IconSize.BUTTON)) self.but_ok.set_always_show_image(True) - self.but_ok.add_accelerator('clicked', self.accel_group, - gtk.keysyms.Return, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) + self.but_ok.add_accelerator( + 'clicked', self.accel_group, Gdk.KEY_Return, + Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE) - hbox = gtk.HBox() + hbox = Gtk.HBox() hbox.show() - self.win.vbox.pack_start(hbox, expand=False, fill=True) - self.win.vbox.pack_start(gtk.HSeparator(), expand=False, fill=True) + self.win.vbox.pack_start(hbox, expand=False, fill=True, padding=0) + self.win.vbox.pack_start( + Gtk.HSeparator(), expand=False, fill=True, padding=0) self.screen = Screen(model, domain=domain, mode=['tree'], order=order, context=context, view_ids=view_ids, views_preload=views_preload, @@ -87,10 +91,11 @@ class WinSearch(NoModal): self.win.set_title(_('Search %s') % self.title) if not sel_multi: - sel.set_mode(gtk.SELECTION_SINGLE) + sel.set_mode(Gtk.SelectionMode.SINGLE) else: - sel.set_mode(gtk.SELECTION_MULTIPLE) - self.win.vbox.pack_start(self.screen.widget, expand=True, fill=True) + sel.set_mode(Gtk.SelectionMode.MULTIPLE) + self.win.vbox.pack_start( + self.screen.widget, expand=True, fill=True, padding=0) self.screen.widget.show() self.model_name = model @@ -98,8 +103,8 @@ class WinSearch(NoModal): self.register() def sig_activate(self, *args): - self.view.treeview.emit_stop_by_name('row_activated') - self.win.response(gtk.RESPONSE_OK) + self.view.treeview.stop_emission_by_name('row_activated') + self.win.response(Gtk.ResponseType.OK) return True def destroy(self): @@ -115,12 +120,12 @@ class WinSearch(NoModal): def response(self, win, response_id): res = None - if response_id == gtk.RESPONSE_OK: + if response_id == Gtk.ResponseType.OK: res = [r.id for r in self.screen.selected_records] - elif response_id == gtk.RESPONSE_APPLY: + elif response_id == Gtk.ResponseType.APPLY: self.screen.search_filter(self.screen.screen_container.get_text()) return - elif response_id == gtk.RESPONSE_ACCEPT: + elif response_id == Gtk.ResponseType.ACCEPT: # Remove first tree view as mode if form only view_ids = self.view_ids[1:] screen = Screen(self.model_name, domain=self.domain, diff --git a/tryton/gui/window/wizard.py b/tryton/gui/window/wizard.py index 38a76773b7..f299564a47 100644 --- a/tryton/gui/window/wizard.py +++ b/tryton/gui/window/wizard.py @@ -3,10 +3,7 @@ import logging import gettext -import gtk -import pango - -from gi.repository import Gtk +from gi.repository import Gdk, Gtk, Pango from tryton.signal_event import SignalEvent import tryton.common as common @@ -17,6 +14,7 @@ from tryton.gui.window.nomodal import NoModal from tryton.common.button import Button from tryton.common import RPCExecute, RPCException, RPCContextReload from tryton.common import TRYTON_ICON +from tryton.common.widget_style import widget_class from .infobar import InfoBar from .tabcontent import TabContent @@ -28,7 +26,7 @@ class Wizard(InfoBar): def __init__(self, name=''): super(Wizard, self).__init__() - self.widget = gtk.VBox(spacing=3) + self.widget = Gtk.VBox(spacing=3) self.toolbar_box = None self.widget.show() self.name = name or '' @@ -173,7 +171,8 @@ class Wizard(InfoBar): if (not self.screen.current_record.validate() and state != self.end_state): self.screen.display(set_cursor=True) - self.message_info(self.screen.invalid_message(), gtk.MESSAGE_ERROR) + self.message_info( + self.screen.invalid_message(), Gtk.MessageType.ERROR) return self.message_info() self.state = state @@ -206,52 +205,47 @@ class Wizard(InfoBar): self.screen.signal_connect(self, 'group-changed', self._record_changed) - title = gtk.Label() - title.modify_font(pango.FontDescription("bold 14")) - title.set_label(common.ellipsize(self.name, 80)) + title = Gtk.Label( + label=common.ellipsize(self.name, 80), + halign=Gtk.Align.START, margin=5, + ellipsize=Pango.EllipsizeMode.END) tooltips.set_tip(title, self.name) - title.set_padding(20, 4) - title.set_alignment(0.0, 0.5) - title.set_max_width_chars(1) - title.set_ellipsize(pango.ELLIPSIZE_END) title.set_size_request(0, -1) # Allow overflow - title.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000")) title.show() - hbox = gtk.HBox() - hbox.pack_start(title, expand=True, fill=True) + hbox = Gtk.HBox() + hbox.pack_start(title, expand=True, fill=True, padding=0) hbox.show() - frame = gtk.Frame() - frame.set_shadow_type(gtk.SHADOW_ETCHED_IN) + frame = Gtk.Frame() + frame.set_shadow_type(Gtk.ShadowType.ETCHED_IN) + widget_class(frame, 'wizard-title', True) frame.add(hbox) frame.show() - eb = gtk.EventBox() - eb.add(frame) - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#ffffff")) - eb.show() - - self.widget.pack_start(eb, expand=False, fill=True, padding=3) + self.widget.pack_start(frame, expand=False, fill=True, padding=3) if self.toolbar_box: - self.widget.pack_start(self.toolbar_box, False, True) + self.widget.pack_start( + self.toolbar_box, expand=False, fill=True, padding=0) - viewport = gtk.Viewport() - viewport.set_shadow_type(gtk.SHADOW_NONE) + viewport = Gtk.Viewport() + viewport.set_shadow_type(Gtk.ShadowType.NONE) viewport.add(self.screen.widget) viewport.show() - self.scrolledwindow = gtk.ScrolledWindow() - self.scrolledwindow.set_shadow_type(gtk.SHADOW_NONE) - self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) + self.scrolledwindow = Gtk.ScrolledWindow() + self.scrolledwindow.set_shadow_type(Gtk.ShadowType.NONE) + self.scrolledwindow.set_policy( + Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.scrolledwindow.add(viewport) self.scrolledwindow.show() - self.widget.pack_start(self.scrolledwindow, expand=True, fill=True) + self.widget.pack_start( + self.scrolledwindow, expand=True, fill=True, padding=0) self.create_info_bar() - self.widget.pack_start(self.info_bar, False, True) + self.widget.pack_start( + self.info_bar, expand=False, fill=True, padding=0) class WizardForm(Wizard, TabContent, SignalEvent): @@ -259,12 +253,13 @@ class WizardForm(Wizard, TabContent, SignalEvent): def __init__(self, name=''): super(WizardForm, self).__init__(name=name) - self.toolbar_box = gtk.HBox() - self.hbuttonbox = gtk.HButtonBox() + self.toolbar_box = Gtk.HBox() + self.hbuttonbox = Gtk.HButtonBox() self.hbuttonbox.set_spacing(5) - self.hbuttonbox.set_layout(gtk.BUTTONBOX_END) + self.hbuttonbox.set_layout(Gtk.ButtonBoxStyle.END) self.hbuttonbox.show() - self.widget.pack_start(self.toolbar_box, False, True) + self.widget.pack_start( + self.toolbar_box, expand=False, fill=True, padding=0) self.dialogs = [] self.handlers = { @@ -280,12 +275,13 @@ class WizardForm(Wizard, TabContent, SignalEvent): button = super(WizardForm, self)._get_button(state) response = len(self.states) button.connect('clicked', self.response, response) - self.hbuttonbox.pack_start(button) + self.hbuttonbox.pack_start(button, expand=True, fill=True, padding=0) return button def update(self, view, buttons): super(WizardForm, self).update(view, buttons) - self.widget.pack_start(self.hbuttonbox, expand=False, fill=True) + self.widget.pack_start( + self.hbuttonbox, expand=False, fill=True, padding=0) def sig_close(self): if self.end_state in self.states: @@ -318,20 +314,22 @@ class WizardDialog(Wizard, NoModal): name = _('Wizard') Wizard.__init__(self, name=name) NoModal.__init__(self) - self.dia = gtk.Dialog(self.name, self.parent, - gtk.DIALOG_DESTROY_WITH_PARENT) + self.dia = Gtk.Dialog( + title=self.name, transient_for=self.parent, + destroy_with_parent=True) Main().add_window(self.dia) - self.dia.set_position(gtk.WIN_POS_CENTER_ON_PARENT) + self.dia.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self.dia.set_icon(TRYTON_ICON) self.dia.set_deletable(False) self.dia.connect('delete-event', lambda *a: True) self.dia.connect('close', self.close) self.dia.connect('response', self.response) - self.accel_group = gtk.AccelGroup() + self.accel_group = Gtk.AccelGroup() self.dia.add_accel_group(self.accel_group) - self.dia.vbox.pack_start(self.widget, expand=True, fill=True) + self.dia.vbox.pack_start( + self.widget, expand=True, fill=True, padding=0) self.register() @@ -346,9 +344,9 @@ class WizardDialog(Wizard, NoModal): response = len(self.states) self.dia.add_action_widget(button, response) if definition['default']: - button.add_accelerator('clicked', self.accel_group, - gtk.keysyms.Return, gtk.gdk.CONTROL_MASK, - gtk.ACCEL_VISIBLE) + button.add_accelerator( + 'clicked', self.accel_group, Gdk.KEY_Return, + Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE) button.get_style_context().add_class( Gtk.STYLE_CLASS_SUGGESTED_ACTION) button.set_can_default(True) @@ -359,10 +357,11 @@ class WizardDialog(Wizard, NoModal): def update(self, view, buttons): super(WizardDialog, self).update(view, buttons) current_view = self.screen.current_view - self.scrolledwindow.set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER) + self.scrolledwindow.set_policy( + Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER) if current_view.scroll: current_view.scroll.set_policy( - gtk.POLICY_NEVER, gtk.POLICY_NEVER) + Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER) self.show() def destroy(self, action=None): @@ -395,7 +394,7 @@ class WizardDialog(Wizard, NoModal): screen.client_action(action) def close(self, widget, event=None): - widget.emit_stop_by_name('close') + widget.stop_emission_by_name('close') if self.end_state in self.states: self.states[self.end_state].clicked() return True diff --git a/tryton/translate.py b/tryton/translate.py index eea44f2f3d..f26333fbb2 100644 --- a/tryton/translate.py +++ b/tryton/translate.py @@ -5,9 +5,10 @@ import os import locale import gettext import logging -import gtk import sys +from gi.repository import Gtk + from tryton.config import CURRENT_DIR _ = gettext.gettext @@ -199,6 +200,7 @@ def setlang(lang=None, locale_dict=None): def set_language_direction(direction): if direction == 'rtl': - gtk.widget_set_default_direction(gtk.TEXT_DIR_RTL) + direction = Gtk.TextDirection.RTL else: - gtk.widget_set_default_direction(gtk.TEXT_DIR_LTR) + direction = Gtk.TextDirection.LTR + Gtk.Widget.set_default_direction(direction)