From ea721647988723b7ee480ddede874a27f60c68df Mon Sep 17 00:00:00 2001 From: Calum Lind Date: Fri, 11 Nov 2016 16:58:55 +0000 Subject: [PATCH] [GTK3] Large rename/modify code for GTK3 --- deluge/ui/gtkui/aboutdialog.py | 9 +- deluge/ui/gtkui/addtorrentdialog.py | 76 ++++--- deluge/ui/gtkui/common.py | 43 ++-- deluge/ui/gtkui/connectionmanager.py | 32 +-- deluge/ui/gtkui/createtorrentdialog.py | 92 ++++---- deluge/ui/gtkui/dialogs.py | 154 ++++++++------ deluge/ui/gtkui/edittrackersdialog.py | 24 +-- deluge/ui/gtkui/files_tab.py | 69 +++--- deluge/ui/gtkui/filtertreeview.py | 34 +-- deluge/ui/gtkui/glade/add_torrent_dialog.ui | 137 ++++++------ deluge/ui/gtkui/glade/main_window.tabs.ui | 153 ++++++-------- deluge/ui/gtkui/glade/main_window.ui | 171 +++++++-------- deluge/ui/gtkui/gtkui.py | 33 ++- deluge/ui/gtkui/ipcinterface.py | 2 +- deluge/ui/gtkui/listview.py | 58 ++--- deluge/ui/gtkui/mainwindow.py | 55 ++--- deluge/ui/gtkui/menubar.py | 44 ++-- deluge/ui/gtkui/menubar_osx.py | 17 +- deluge/ui/gtkui/options_tab.py | 2 +- deluge/ui/gtkui/path_combo_chooser.py | 223 +++++++++++--------- deluge/ui/gtkui/peers_tab.py | 22 +- deluge/ui/gtkui/piecesbar.py | 41 ++-- deluge/ui/gtkui/preferences.py | 82 +++---- deluge/ui/gtkui/queuedtorrents.py | 4 +- deluge/ui/gtkui/removetorrentdialog.py | 6 +- deluge/ui/gtkui/sidebar.py | 6 +- deluge/ui/gtkui/status_tab.py | 2 +- deluge/ui/gtkui/statusbar.py | 38 ++-- deluge/ui/gtkui/systemtray.py | 14 +- deluge/ui/gtkui/toolbar.py | 2 +- deluge/ui/gtkui/torrentdetails.py | 6 +- deluge/ui/gtkui/torrentview.py | 24 +-- 32 files changed, 845 insertions(+), 830 deletions(-) diff --git a/deluge/ui/gtkui/aboutdialog.py b/deluge/ui/gtkui/aboutdialog.py index abb3135f1..cb3ed43c8 100644 --- a/deluge/ui/gtkui/aboutdialog.py +++ b/deluge/ui/gtkui/aboutdialog.py @@ -9,7 +9,7 @@ from __future__ import unicode_literals -import gtk +from gi.repository import Gtk import deluge.component as component from deluge.common import get_version, open_url_in_browser, windows_check @@ -19,9 +19,10 @@ from deluge.ui.gtkui.common import get_deluge_icon, get_pixbuf class AboutDialog(object): def __init__(self): - self.about = gtk.AboutDialog() - self.about.set_transient_for(component.get('MainWindow').window) - self.about.set_position(gtk.WIN_POS_CENTER) + self.about = Gtk.AboutDialog() + self.about.set_transient_for(component.get('MainWindow').get_window()) + self.about.set_position(Gtk.WindowPosition.CENTER) + self.about.set_name(_('Deluge')) self.about.set_program_name(_('Deluge')) if windows_check(): diff --git a/deluge/ui/gtkui/addtorrentdialog.py b/deluge/ui/gtkui/addtorrentdialog.py index bd7db2f1a..7c6843ffa 100644 --- a/deluge/ui/gtkui/addtorrentdialog.py +++ b/deluge/ui/gtkui/addtorrentdialog.py @@ -15,8 +15,8 @@ from base64 import b64decode, b64encode from xml.sax.saxutils import escape as xml_escape from xml.sax.saxutils import unescape as xml_unescape -import gtk -from gobject import TYPE_INT64, TYPE_UINT64 +from gi.repository import Gtk +from gi.repository.GObject import TYPE_INT64, TYPE_UINT64 import deluge.common import deluge.component as component @@ -40,7 +40,7 @@ log = logging.getLogger(__name__) class AddTorrentDialog(component.Component): def __init__(self): component.Component.__init__(self, 'AddTorrentDialog') - self.builder = gtk.Builder() + self.builder = Gtk.Builder() # The base dialog self.builder.add_from_file( deluge.common.resource_filename( @@ -68,10 +68,10 @@ class AddTorrentDialog(component.Component): self.builder.connect_signals(self) # download?, path, filesize, sequence number, inconsistent? - self.files_treestore = gtk.TreeStore( + self.files_treestore = Gtk.TreeStore( bool, str, TYPE_UINT64, TYPE_INT64, bool, str ) - self.files_treestore.set_sort_column_id(1, gtk.SORT_ASCENDING) + self.files_treestore.set_sort_column_id(1, Gtk.SortType.ASCENDING) # Holds the files info self.files = {} @@ -86,22 +86,22 @@ class AddTorrentDialog(component.Component): self.prefetching_magnets = [] - render = gtk.CellRendererText() + render = Gtk.CellRendererText() render.connect('edited', self._on_torrent_name_edit) render.set_property('editable', True) - column = gtk.TreeViewColumn(_('Torrent'), render, text=1) + column = Gtk.TreeViewColumn(_('Torrent'), render, text=1) self.listview_torrents.append_column(column) - render = gtk.CellRendererToggle() + render = Gtk.CellRendererToggle() render.connect('toggled', self._on_file_toggled) - column = gtk.TreeViewColumn(None, render, active=0, inconsistent=4) + column = Gtk.TreeViewColumn(None, render, active=0, inconsistent=4) self.listview_files.append_column(column) - column = gtk.TreeViewColumn(_('Filename')) - render = gtk.CellRendererPixbuf() + column = Gtk.TreeViewColumn(_('Filename')) + render = Gtk.CellRendererPixbuf() column.pack_start(render, False) column.add_attribute(render, 'stock-id', 5) - render = gtk.CellRendererText() + render = Gtk.CellRendererText() render.set_property('editable', True) render.connect('edited', self._on_filename_edited) column.pack_start(render, True) @@ -109,18 +109,18 @@ class AddTorrentDialog(component.Component): column.set_expand(True) self.listview_files.append_column(column) - render = gtk.CellRendererText() - column = gtk.TreeViewColumn(_('Size')) + render = Gtk.CellRendererText() + column = Gtk.TreeViewColumn(_('Size')) column.pack_start(render, True) column.set_cell_data_func(render, cell_data_size, 2) self.listview_files.append_column(column) - self.torrent_liststore = gtk.ListStore(str, str, str) + self.torrent_liststore = Gtk.ListStore(str, str, str) self.listview_torrents.set_model(self.torrent_liststore) self.listview_torrents.set_tooltip_column(2) self.listview_files.set_model(self.files_treestore) - self.listview_files.get_selection().set_mode(gtk.SELECTION_MULTIPLE) + self.listview_files.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self.listview_torrents.get_selection().connect( 'changed', self._on_torrent_changed ) @@ -377,7 +377,7 @@ class AddTorrentDialog(component.Component): for key, value in split_files.items(): if key.endswith(os.path.sep): chunk_iter = self.files_treestore.append( - parent_iter, [True, key, 0, -1, False, gtk.STOCK_DIRECTORY] + parent_iter, [True, key, 0, -1, False, Gtk.STOCK_DIRECTORY] ) chunk_size = self.add_files(chunk_iter, value) self.files_treestore.set(chunk_iter, 2, chunk_size) @@ -385,7 +385,7 @@ class AddTorrentDialog(component.Component): else: self.files_treestore.append( parent_iter, - [value[2], key, value[1]['size'], value[0], False, gtk.STOCK_FILE], + [value[2], key, value[1]['size'], value[0], False, Gtk.STOCK_FILE], ) ret += value[1]['size'] if parent_iter and self.files_treestore.iter_has_child(parent_iter): @@ -651,15 +651,15 @@ class AddTorrentDialog(component.Component): def on_button_file_clicked(self, widget): log.debug('on_button_file_clicked') # Setup the filechooserdialog - chooser = gtk.FileChooserDialog( + chooser = Gtk.FileChooserDialog( _('Choose a .torrent file'), None, - gtk.FILE_CHOOSER_ACTION_OPEN, + Gtk.FileChooserAction.OPEN, buttons=( - gtk.STOCK_CANCEL, - gtk.RESPONSE_CANCEL, - gtk.STOCK_OPEN, - gtk.RESPONSE_OK, + Gtk.STOCK_CANCEL, + Gtk.ResponseType.CANCEL, + Gtk.STOCK_OPEN, + Gtk.ResponseType.OK, ), ) @@ -669,11 +669,11 @@ class AddTorrentDialog(component.Component): chooser.set_local_only(False) # Add .torrent and * file filters - file_filter = gtk.FileFilter() + file_filter = Gtk.FileFilter() file_filter.set_name(_('Torrent files')) file_filter.add_pattern('*.' + 'torrent') chooser.add_filter(file_filter) - file_filter = gtk.FileFilter() + file_filter = Gtk.FileFilter() file_filter.set_name(_('All files')) file_filter.add_pattern('*') chooser.add_filter(file_filter) @@ -686,7 +686,7 @@ class AddTorrentDialog(component.Component): # Run the dialog response = chooser.run() - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: result = chooser.get_filenames() self.config['default_load_path'] = chooser.get_current_folder() else: @@ -701,7 +701,7 @@ class AddTorrentDialog(component.Component): dialog = self.builder.get_object('url_dialog') entry = self.builder.get_object('entry_url') - dialog.set_default_response(gtk.RESPONSE_OK) + dialog.set_default_response(Gtk.ResponseType.OK) dialog.set_transient_for(self.dialog) entry.grab_focus() @@ -712,7 +712,7 @@ class AddTorrentDialog(component.Component): dialog.show_all() response = dialog.run() - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: url = entry.get_text().decode('utf-8') else: url = None @@ -736,16 +736,14 @@ class AddTorrentDialog(component.Component): ).run() def add_from_url(self, url): - dialog = gtk.Dialog( + dialog = Gtk.Dialog( _('Downloading...'), - flags=gtk.DIALOG_MODAL - | gtk.DIALOG_DESTROY_WITH_PARENT - | gtk.DIALOG_NO_SEPARATOR, + flags=Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, parent=self.dialog, ) dialog.set_transient_for(self.dialog) - pb = gtk.ProgressBar() + pb = Gtk.ProgressBar() dialog.vbox.pack_start(pb, True, True, 0) dialog.show_all() @@ -795,7 +793,7 @@ class AddTorrentDialog(component.Component): entry = self.builder.get_object('entry_hash') textview = self.builder.get_object('text_trackers') - dialog.set_default_response(gtk.RESPONSE_OK) + dialog.set_default_response(Gtk.ResponseType.OK) dialog.set_transient_for(self.dialog) entry.grab_focus() @@ -806,7 +804,7 @@ class AddTorrentDialog(component.Component): dialog.show_all() response = dialog.run() infohash = entry.get_text().strip() - if response == gtk.RESPONSE_OK and deluge.common.is_infohash(infohash): + if response == Gtk.RESPONSE_OK and deluge.common.is_infohash(infohash): # Create a list of trackers from the textview buffer tview_buf = textview.get_buffer() trackers_text = tview_buf.get_text(*tview_buf.get_bounds()) @@ -974,7 +972,7 @@ class AddTorrentDialog(component.Component): split_text = new_text.split(os.path.sep) for s in split_text[:-1]: parent = self.files_treestore.append( - parent, [True, s, 0, -1, False, gtk.STOCK_DIRECTORY] + parent, [True, s, 0, -1, False, Gtk.STOCK_DIRECTORY] ) self.files_treestore[itr][1] = split_text[-1] @@ -1034,7 +1032,7 @@ class AddTorrentDialog(component.Component): # the existing itr and change the text parent = self.files_treestore.append( parent, - [True, s + os.path.sep, 0, -1, False, gtk.STOCK_DIRECTORY], + [True, s + os.path.sep, 0, -1, False, Gtk.STOCK_DIRECTORY], ) self.files_treestore[itr][1] = split_text[-1] + os.path.sep @@ -1046,7 +1044,7 @@ class AddTorrentDialog(component.Component): # We need to re-expand the view because it might contracted # if we change the root iter # FIXME add back expand_row - # self.listview_files.expand_row('0', False) + # self.listview_files.expand_row(b'0', False) self.listview_files.expand_all() else: # This was a simple folder rename without any splits, so just diff --git a/deluge/ui/gtkui/common.py b/deluge/ui/gtkui/common.py index a02eace0a..57e309c80 100644 --- a/deluge/ui/gtkui/common.py +++ b/deluge/ui/gtkui/common.py @@ -16,22 +16,17 @@ import shutil import sys import six.moves.cPickle as pickle -from gobject import GError -from gtk import ( - SORT_ASCENDING, +from gi.repository.Gdk import SELECTION_CLIPBOARD +from gi.repository.GdkPixbuf import Colorspace, Pixbuf +from gi.repository.GObject import GError +from gi.repository.Gtk import ( + Clipboard, + IconTheme, Menu, MenuItem, RadioMenuItem, SeparatorMenuItem, - clipboard_get, - icon_theme_get_default, -) -from gtk.gdk import ( - COLORSPACE_RGB, - SELECTION_PRIMARY, - Pixbuf, - pixbuf_new_from_file, - pixbuf_new_from_file_at_size, + SortType, ) from deluge.common import get_pixmap, osx_check, windows_check @@ -40,14 +35,14 @@ log = logging.getLogger(__name__) def create_blank_pixbuf(size=16): - pix = Pixbuf(COLORSPACE_RGB, True, 8, size, size) + pix = Pixbuf(Colorspace.RGB, True, 8, size, size) pix.fill(0x0) return pix def get_pixbuf(filename): try: - return pixbuf_new_from_file(get_pixmap(filename)) + return Pixbuf.new_from_file(get_pixmap(filename)) except GError as ex: log.warning(ex) return create_blank_pixbuf() @@ -64,7 +59,7 @@ icon_checking = get_pixbuf('checking16.png') def get_pixbuf_at_size(filename, size): try: - return pixbuf_new_from_file_at_size(get_pixmap(filename), size, size) + return Pixbuf.new_from_file_at_size(get_pixmap(filename), size, size) except GError as ex: # Failed to load the pixbuf (Bad image file), so return a blank pixbuf. log.warning(ex) @@ -78,7 +73,7 @@ def get_logo(size): size (int): Size of logo in pixels Returns: - gtk.gdk.Pixbuf: deluge logo + Pixbuf: deluge logo """ filename = 'deluge.svg' if windows_check(): @@ -111,7 +106,7 @@ def build_menu_radio_list( The pref_value is what you would like to test for the default active radio item. Returns: - gtk.Menu: The menu radio + Menu: The menu radio """ menu = Menu() group = None @@ -188,13 +183,13 @@ def get_deluge_icon(): that is distributed with the package. Returns: - gtk.gdk.Pixbuf: the deluge icon + Pixbuf: the deluge icon """ if windows_check(): return get_logo(32) else: try: - icon_theme = icon_theme_get_default() + icon_theme = IconTheme.get_default() return icon_theme.load_icon('deluge', 64, 0) except GError: return get_logo(64) @@ -252,7 +247,7 @@ def associate_magnet_links(overwrite=False): elif not osx_check(): # gconf method is only available in a GNOME environment try: - import gconf + from gi.repository import GConf except ImportError: log.debug( 'gconf not available, so will not attempt to register magnet uri handler' @@ -260,7 +255,7 @@ def associate_magnet_links(overwrite=False): return False else: key = '/desktop/gnome/url-handlers/magnet/command' - gconf_client = gconf.client_get_default() + gconf_client = GConf.Client.get_default() if (gconf_client.get(key) and overwrite) or not gconf_client.get(key): # We are either going to overwrite the key, or do it if it hasn't been set yet if gconf_client.set_string(key, 'deluge "%s"'): @@ -357,7 +352,7 @@ def listview_replace_treestore(listview): treestore.clear() treestore.set_default_sort_func(lambda *args: 0) original_sort = treestore.get_sort_column_id() - treestore.set_sort_column_id(-1, SORT_ASCENDING) + treestore.set_sort_column_id(-1, SortType.ASCENDING) yield @@ -370,8 +365,8 @@ def listview_replace_treestore(listview): def get_clipboard_text(): text = ( - clipboard_get(selection=SELECTION_PRIMARY).wait_for_text() - or clipboard_get().wait_for_text() + Clipboard.get(selection=SELECTION_CLIPBOARD).wait_for_text() + or Clipboard.get().wait_for_text() ) if text: return text.strip() diff --git a/deluge/ui/gtkui/connectionmanager.py b/deluge/ui/gtkui/connectionmanager.py index 6320f649a..915c9046b 100644 --- a/deluge/ui/gtkui/connectionmanager.py +++ b/deluge/ui/gtkui/connectionmanager.py @@ -13,7 +13,7 @@ import logging import os from socket import gaierror, gethostbyname -import gtk +from gi.repository import Gtk from twisted.internet import defer, reactor import deluge.component as component @@ -79,7 +79,7 @@ class ConnectionManager(component.Component): def stop(self): # Close this dialog when we are shutting down if self.running: - self.connection_manager.response(gtk.RESPONSE_CLOSE) + self.connection_manager.response(Gtk.ResponseType.CLOSE) def shutdown(self): pass @@ -87,7 +87,7 @@ class ConnectionManager(component.Component): # Public methods def show(self): """Show the ConnectionManager dialog.""" - self.builder = gtk.Builder() + self.builder = Gtk.Builder() self.builder.add_from_file( resource_filename( 'deluge.ui.gtkui', os.path.join('glade', 'connection_manager.ui') @@ -98,29 +98,29 @@ class ConnectionManager(component.Component): # Create status pixbufs if not HOSTLIST_PIXBUFS: - for stock_id in (gtk.STOCK_NO, gtk.STOCK_YES, gtk.STOCK_CONNECT): + for stock_id in (Gtk.STOCK_NO, Gtk.STOCK_YES, Gtk.STOCK_CONNECT): HOSTLIST_PIXBUFS.append( - self.connection_manager.render_icon(stock_id, gtk.ICON_SIZE_MENU) + self.connection_manager.render_icon(stock_id, Gtk.IconSize.MENU) ) # Setup the hostlist liststore and treeview self.treeview = self.builder.get_object('treeview_hostlist') self.liststore = self.builder.get_object('liststore_hostlist') - render = gtk.CellRendererPixbuf() - column = gtk.TreeViewColumn(_('Status'), render) + render = Gtk.CellRendererPixbuf() + column = Gtk.TreeViewColumn(_('Status'), render) column.set_cell_data_func(render, cell_render_status, HOSTLIST_COL_STATUS) self.treeview.append_column(column) - render = gtk.CellRendererText() - column = gtk.TreeViewColumn(_('Host'), render, text=HOSTLIST_COL_HOST) + render = Gtk.CellRendererText() + column = Gtk.TreeViewColumn(_('Host'), render, text=HOSTLIST_COL_HOST) host_data = (HOSTLIST_COL_HOST, HOSTLIST_COL_PORT, HOSTLIST_COL_USER) column.set_cell_data_func(render, cell_render_host, host_data) column.set_expand(True) self.treeview.append_column(column) - column = gtk.TreeViewColumn( - _('Version'), gtk.CellRendererText(), text=HOSTLIST_COL_VERSION + column = Gtk.TreeViewColumn( + _('Version'), Gtk.CellRendererText(), text=HOSTLIST_COL_VERSION ) self.treeview.append_column(column) @@ -212,7 +212,7 @@ class ConnectionManager(component.Component): self.builder.get_object('button_removehost').set_sensitive(False) self.builder.get_object('button_startdaemon').set_sensitive(False) self.builder.get_object('image_startdaemon').set_from_stock( - gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU + Gtk.STOCK_EXECUTE, Gtk.IconSize.MENU ) self.builder.get_object('label_startdaemon').set_text_with_mnemonic( '_Start Daemon' @@ -242,7 +242,7 @@ class ConnectionManager(component.Component): if status == 'Connected' or status == 'Online': self.builder.get_object('button_connect').set_sensitive(True) self.builder.get_object('image_startdaemon').set_from_stock( - gtk.STOCK_STOP, gtk.ICON_SIZE_MENU + Gtk.STOCK_STOP, Gtk.IconSize.MENU ) self.builder.get_object('label_startdaemon').set_text_with_mnemonic( _('_Stop Daemon') @@ -310,7 +310,7 @@ class ConnectionManager(component.Component): # this component will be stopped(while the connect deferred is # running), so, self.connection_manager will be deleted. # If that's not the case, close the dialog. - self.connection_manager.response(gtk.RESPONSE_OK) + self.connection_manager.response(Gtk.ResponseType.OK) component.start() def _on_connect_fail(self, reason, host_id, try_counter): @@ -321,7 +321,7 @@ class ConnectionManager(component.Component): dialog = AuthenticationDialog(reason.value.message, reason.value.username) def dialog_finished(response_id): - if response_id == gtk.RESPONSE_OK: + if response_id == Gtk.RESPONSE_OK: self._connect(host_id, dialog.get_username(), dialog.get_password()) return dialog.run().addCallback(dialog_finished) @@ -371,7 +371,7 @@ class ConnectionManager(component.Component): self._connect(host_id, try_counter=try_counter) def on_button_close_clicked(self, widget): - self.connection_manager.response(gtk.RESPONSE_CLOSE) + self.connection_manager.response(Gtk.ResponseType.CLOSE) def _run_addhost_dialog(self, edit_host_info=None): """Create and runs the add host dialog. diff --git a/deluge/ui/gtkui/createtorrentdialog.py b/deluge/ui/gtkui/createtorrentdialog.py index 8a61ee3d1..224bea0ef 100644 --- a/deluge/ui/gtkui/createtorrentdialog.py +++ b/deluge/ui/gtkui/createtorrentdialog.py @@ -13,8 +13,8 @@ import logging import os.path from base64 import b64encode -import gtk -from gobject import TYPE_UINT64, idle_add +from gi.repository import Gtk +from gi.repository.GObject import TYPE_UINT64, idle_add from twisted.internet.threads import deferToThread import deluge.component as component @@ -35,7 +35,7 @@ class CreateTorrentDialog(object): pass def show(self): - self.builder = gtk.Builder() + self.builder = Gtk.Builder() # The main dialog self.builder.add_from_file( @@ -73,20 +73,20 @@ class CreateTorrentDialog(object): self.builder.connect_signals(self) # path, icon, size - self.files_treestore = gtk.TreeStore(str, str, TYPE_UINT64) + self.files_treestore = Gtk.TreeStore(str, str, TYPE_UINT64) - column = gtk.TreeViewColumn(_('Filename')) - render = gtk.CellRendererPixbuf() + column = Gtk.TreeViewColumn(_('Filename')) + render = Gtk.CellRendererPixbuf() column.pack_start(render, False) column.add_attribute(render, 'stock-id', 1) - render = gtk.CellRendererText() + render = Gtk.CellRendererText() column.pack_start(render, True) column.add_attribute(render, 'text', 0) column.set_expand(True) self.builder.get_object('treeview_files').append_column(column) - column = gtk.TreeViewColumn(_('Size')) - render = gtk.CellRendererText() + column = Gtk.TreeViewColumn(_('Size')) + render = Gtk.CellRendererText() column.pack_start(render, True) column.set_cell_data_func(render, cell_data_size, 2) self.builder.get_object('treeview_files').append_column(column) @@ -95,17 +95,17 @@ class CreateTorrentDialog(object): self.builder.get_object('treeview_files').set_show_expanders(False) # tier, url - self.trackers_liststore = gtk.ListStore(int, str) + self.trackers_liststore = Gtk.ListStore(int, str) self.builder.get_object('tracker_treeview').append_column( - gtk.TreeViewColumn(_('Tier'), gtk.CellRendererText(), text=0) + Gtk.TreeViewColumn(_('Tier'), Gtk.CellRendererText(), text=0) ) self.builder.get_object('tracker_treeview').append_column( - gtk.TreeViewColumn(_('Tracker'), gtk.CellRendererText(), text=1) + Gtk.TreeViewColumn(_('Tracker'), Gtk.CellRendererText(), text=1) ) self.builder.get_object('tracker_treeview').set_model(self.trackers_liststore) - self.trackers_liststore.set_sort_column_id(0, gtk.SORT_ASCENDING) + self.trackers_liststore.set_sort_column_id(0, Gtk.SortType.ASCENDING) if not client.is_localhost() and client.connected(): self.builder.get_object('button_remote_path').show() @@ -140,15 +140,15 @@ class CreateTorrentDialog(object): def on_button_file_clicked(self, widget): log.debug('on_button_file_clicked') # Setup the filechooserdialog - chooser = gtk.FileChooserDialog( + chooser = Gtk.FileChooserDialog( _('Choose a file'), self.dialog, - gtk.FILE_CHOOSER_ACTION_OPEN, + Gtk.FileChooserAction.OPEN, buttons=( - gtk.STOCK_CANCEL, - gtk.RESPONSE_CANCEL, - gtk.STOCK_OPEN, - gtk.RESPONSE_OK, + Gtk.STOCK_CANCEL, + Gtk.ResponseType.CANCEL, + Gtk.STOCK_OPEN, + Gtk.ResponseType.OK, ), ) @@ -159,7 +159,7 @@ class CreateTorrentDialog(object): # Run the dialog response = chooser.run() - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: result = chooser.get_filename() else: chooser.destroy() @@ -168,22 +168,22 @@ class CreateTorrentDialog(object): path = result.decode('utf-8') self.files_treestore.clear() - self.files_treestore.append(None, [result, gtk.STOCK_FILE, get_path_size(path)]) + self.files_treestore.append(None, [result, Gtk.STOCK_FILE, get_path_size(path)]) self.adjust_piece_size() chooser.destroy() def on_button_folder_clicked(self, widget): log.debug('on_button_folder_clicked') # Setup the filechooserdialog - chooser = gtk.FileChooserDialog( + chooser = Gtk.FileChooserDialog( _('Choose a folder'), self.dialog, - gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, + Gtk.FileChooserAction.SELECT_FOLDER, buttons=( - gtk.STOCK_CANCEL, - gtk.RESPONSE_CANCEL, - gtk.STOCK_OPEN, - gtk.RESPONSE_OK, + Gtk.STOCK_CANCEL, + Gtk.ResponseType.CANCEL, + Gtk.STOCK_OPEN, + Gtk.ResponseType.OK, ), ) @@ -193,7 +193,7 @@ class CreateTorrentDialog(object): # Run the dialog response = chooser.run() - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: result = chooser.get_filename() else: chooser.destroy() @@ -202,7 +202,7 @@ class CreateTorrentDialog(object): path = result.decode('utf-8') self.files_treestore.clear() - self.files_treestore.append(None, [result, gtk.STOCK_OPEN, get_path_size(path)]) + self.files_treestore.append(None, [result, Gtk.STOCK_OPEN, get_path_size(path)]) self.adjust_piece_size() chooser.destroy() @@ -215,14 +215,14 @@ class CreateTorrentDialog(object): entry.grab_focus() response = dialog.run() - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: result = entry.get_text() def _on_get_path_size(size): log.debug('size: %s', size) if size > 0: self.files_treestore.clear() - self.files_treestore.append(None, [result, gtk.STOCK_NETWORK, size]) + self.files_treestore.append(None, [result, Gtk.STOCK_NETWORK, size]) self.adjust_piece_size() client.core.get_path_size(result).addCallback(_on_get_path_size) @@ -243,7 +243,7 @@ class CreateTorrentDialog(object): path = self.files_treestore[0][0].rstrip('\\/') torrent_filename = '%s.torrent' % os.path.split(path)[-1] - is_remote = self.files_treestore[0][1] == gtk.STOCK_NETWORK + is_remote = self.files_treestore[0][1] == Gtk.STOCK_NETWORK if is_remote: # This is a remote path @@ -252,7 +252,7 @@ class CreateTorrentDialog(object): dialog_save_path = self.builder.get_object('entry_save_path') dialog_save_path.set_text(path + '.torrent') response = dialog.run() - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: result = dialog_save_path.get_text() else: dialog.hide() @@ -260,15 +260,15 @@ class CreateTorrentDialog(object): dialog.hide() else: # Setup the filechooserdialog - chooser = gtk.FileChooserDialog( + chooser = Gtk.FileChooserDialog( _('Save .torrent file'), self.dialog, - gtk.FILE_CHOOSER_ACTION_SAVE, + Gtk.FileChooserAction.SAVE, buttons=( - gtk.STOCK_CANCEL, - gtk.RESPONSE_CANCEL, - gtk.STOCK_SAVE, - gtk.RESPONSE_OK, + Gtk.STOCK_CANCEL, + Gtk.ResponseType.CANCEL, + Gtk.STOCK_SAVE, + Gtk.ResponseType.OK, ), ) @@ -277,11 +277,11 @@ class CreateTorrentDialog(object): chooser.set_property('skip-taskbar-hint', True) # Add .torrent and * file filters - file_filter = gtk.FileFilter() + file_filter = Gtk.FileFilter() file_filter.set_name(_('Torrent files')) file_filter.add_pattern('*.' + 'torrent') chooser.add_filter(file_filter) - file_filter = gtk.FileFilter() + file_filter = Gtk.FileFilter() file_filter.set_name(_('All files')) file_filter.add_pattern('*') chooser.add_filter(file_filter) @@ -290,7 +290,7 @@ class CreateTorrentDialog(object): # Run the dialog response = chooser.run() - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: result = chooser.get_filename() else: chooser.destroy() @@ -339,7 +339,7 @@ class CreateTorrentDialog(object): if is_remote: def torrent_created(): - self.builder.get_object('progress_dialog').hide_all() + self.builder.get_object('progress_dialog').hide() client.deregister_event_handler( 'CreateTorrentProgressEvent', on_create_torrent_progress_event ) @@ -371,7 +371,7 @@ class CreateTorrentDialog(object): else: def hide_progress(result): - self.builder.get_object('progress_dialog').hide_all() + self.builder.get_object('progress_dialog').hide() deferToThread( self.create_torrent, @@ -475,7 +475,7 @@ class CreateTorrentDialog(object): def on_button_add_clicked(self, widget): log.debug('on_button_add_clicked') - builder = gtk.Builder() + builder = Gtk.Builder() builder.add_from_file( resource_filename( 'deluge.ui.gtkui', os.path.join('glade', 'edit_trackers.add.ui') @@ -493,7 +493,7 @@ class CreateTorrentDialog(object): textview.grab_focus() response = dialog.run() - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: # Create a list of trackers from the textview buffer textview_buf = textview.get_buffer() trackers_text = textview_buf.get_text(*textview_buf.get_bounds()) diff --git a/deluge/ui/gtkui/dialogs.py b/deluge/ui/gtkui/dialogs.py index 562b2ce51..36015486e 100644 --- a/deluge/ui/gtkui/dialogs.py +++ b/deluge/ui/gtkui/dialogs.py @@ -11,7 +11,7 @@ from __future__ import unicode_literals -import gtk +from gi.repository import Gtk from twisted.internet import defer import deluge.component as component @@ -19,7 +19,7 @@ from deluge.common import windows_check from deluge.ui.gtkui.common import get_deluge_icon, get_pixbuf_at_size -class BaseDialog(gtk.Dialog): +class BaseDialog(Gtk.Dialog): """ Base dialog class that should be used with all dialogs. """ @@ -36,9 +36,7 @@ class BaseDialog(gtk.Dialog): super(BaseDialog, self).__init__( title=header, parent=parent if parent else component.get('MainWindow').window, - flags=gtk.DIALOG_MODAL - | gtk.DIALOG_DESTROY_WITH_PARENT - | gtk.DIALOG_NO_SEPARATOR, + flags=Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, buttons=buttons, ) @@ -50,9 +48,9 @@ class BaseDialog(gtk.Dialog): # Setup all the formatting and such to make our dialog look pretty self.set_border_width(5) self.set_default_size(200, 100) - hbox = gtk.HBox(spacing=5) - image = gtk.Image() - if not gtk.stock_lookup(icon) and ( + hbox = Gtk.HBox(spacing=5) + image = Gtk.Image() + if not Gtk.stock_lookup(icon) and ( icon.endswith('.svg') or icon.endswith('.png') ): # Hack for Windows since it doesn't support svg @@ -60,11 +58,11 @@ class BaseDialog(gtk.Dialog): icon = icon.rpartition('.svg')[0] + '16.png' image.set_from_pixbuf(get_pixbuf_at_size(icon, 32)) else: - image.set_from_stock(icon, gtk.ICON_SIZE_DIALOG) + image.set_from_stock(icon, Gtk.IconSize.DIALOG) image.set_alignment(0.5, 0.0) hbox.pack_start(image, False, False, 0) - vbox = gtk.VBox(spacing=5) - tlabel = gtk.Label(text) + vbox = Gtk.VBox(spacing=5) + tlabel = Gtk.Label(label=text) tlabel.set_use_markup(True) tlabel.set_line_wrap(True) tlabel.set_alignment(0.0, 0.5) @@ -75,7 +73,7 @@ class BaseDialog(gtk.Dialog): self.vbox.show_all() def _on_delete_event(self, widget, event): - self.deferred.callback(gtk.RESPONSE_DELETE_EVENT) + self.deferred.callback(Gtk.ResponseType.DELETE_EVENT) self.destroy() def _on_response(self, widget, response): @@ -96,7 +94,7 @@ class YesNoDialog(BaseDialog): """ Displays a dialog asking the user to select Yes or No to a question. - When run(), it will return either a gtk.RESPONSE_YES or a gtk.RESPONSE_NO. + When run(), it will return either a Gtk.ResponseType.YES or a Gtk.ResponseType.NO. """ @@ -109,8 +107,8 @@ class YesNoDialog(BaseDialog): super(YesNoDialog, self).__init__( header, text, - gtk.STOCK_DIALOG_QUESTION, - (gtk.STOCK_NO, gtk.RESPONSE_NO, gtk.STOCK_YES, gtk.RESPONSE_YES), + Gtk.STOCK_DIALOG_QUESTION, + (Gtk.STOCK_NO, Gtk.ResponseType.NO, Gtk.STOCK_YES, Gtk.ResponseType.YES), parent, ) @@ -119,7 +117,7 @@ class InformationDialog(BaseDialog): """ Displays an information dialog. - When run(), it will return a gtk.RESPONSE_CLOSE. + When run(), it will return a Gtk.ResponseType.CLOSE. """ def __init__(self, header, text, parent=None): @@ -131,8 +129,8 @@ class InformationDialog(BaseDialog): super(InformationDialog, self).__init__( header, text, - gtk.STOCK_DIALOG_INFO, - (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE), + Gtk.STOCK_DIALOG_INFO, + (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE), parent, ) @@ -141,7 +139,7 @@ class ErrorDialog(BaseDialog): """ Displays an error dialog with optional details text for more information. - When run(), it will return a gtk.RESPONSE_CLOSE. + When run(), it will return a Gtk.ResponseType.CLOSE. """ def __init__(self, header, text, parent=None, details=None, traceback=False): @@ -158,8 +156,8 @@ class ErrorDialog(BaseDialog): super(ErrorDialog, self).__init__( header, text, - gtk.STOCK_DIALOG_ERROR, - (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE), + Gtk.STOCK_DIALOG_ERROR, + (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE), parent, ) @@ -176,14 +174,14 @@ class ErrorDialog(BaseDialog): if details: self.set_default_size(600, 400) - textview = gtk.TextView() + textview = Gtk.TextView() textview.set_editable(False) textview.get_buffer().set_text(details) - sw = gtk.ScrolledWindow() - sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - sw.set_shadow_type(gtk.SHADOW_IN) + sw = Gtk.ScrolledWindow() + sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + sw.set_shadow_type(Gtk.ShadowType.IN) sw.add(textview) - label = gtk.Label(_('Details:')) + label = Gtk.Label(label=_('Details:')) label.set_alignment(0.0, 0.5) self.vbox.pack_start(label, False, False, 0) self.vbox.pack_start(sw, True, True, 0) @@ -194,8 +192,8 @@ class AuthenticationDialog(BaseDialog): """ Displays a dialog with entry fields asking for username and password. - When run(), it will return either a gtk.RESPONSE_CANCEL or a - gtk.RESPONSE_OK. + When run(), it will return either a Gtk.ResponseType.CANCEL or a + Gtk.ResponseType.OK. """ def __init__(self, err_msg='', username=None, parent=None): @@ -206,25 +204,30 @@ class AuthenticationDialog(BaseDialog): super(AuthenticationDialog, self).__init__( _('Authenticate'), err_msg, - gtk.STOCK_DIALOG_AUTHENTICATION, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_CONNECT, gtk.RESPONSE_OK), + Gtk.STOCK_DIALOG_AUTHENTICATION, + ( + Gtk.STOCK_CANCEL, + Gtk.ResponseType.CANCEL, + Gtk.STOCK_CONNECT, + Gtk.ResponseType.OK, + ), parent, ) - table = gtk.Table(2, 2, False) - self.username_label = gtk.Label() + table = Gtk.Table(2, 2, False) + self.username_label = Gtk.Label() self.username_label.set_markup('' + _('Username:') + '') self.username_label.set_alignment(1.0, 0.5) self.username_label.set_padding(5, 5) - self.username_entry = gtk.Entry() + self.username_entry = Gtk.Entry() table.attach(self.username_label, 0, 1, 0, 1) table.attach(self.username_entry, 1, 2, 0, 1) - self.password_label = gtk.Label() + self.password_label = Gtk.Label() self.password_label.set_markup('' + _('Password:') + '') self.password_label.set_alignment(1.0, 0.5) self.password_label.set_padding(5, 5) - self.password_entry = gtk.Entry() + self.password_entry = Gtk.Entry() self.password_entry.set_visibility(False) self.password_entry.connect('activate', self.on_password_activate) table.attach(self.password_label, 0, 1, 1, 2) @@ -247,7 +250,7 @@ class AuthenticationDialog(BaseDialog): return self.password_entry.get_text() def on_password_activate(self, widget): - self.response(gtk.RESPONSE_OK) + self.response(Gtk.ResponseType.OK) class AccountDialog(BaseDialog): @@ -263,12 +266,12 @@ class AccountDialog(BaseDialog): super(AccountDialog, self).__init__( _('Edit Account'), _('Edit existing account'), - gtk.STOCK_DIALOG_INFO, + Gtk.STOCK_DIALOG_INFO, ( - gtk.STOCK_CANCEL, - gtk.RESPONSE_CANCEL, - gtk.STOCK_APPLY, - gtk.RESPONSE_OK, + Gtk.STOCK_CANCEL, + Gtk.ResponseType.CANCEL, + Gtk.STOCK_APPLY, + Gtk.ResponseType.OK, ), parent, ) @@ -276,29 +279,34 @@ class AccountDialog(BaseDialog): super(AccountDialog, self).__init__( _('New Account'), _('Create a new account'), - gtk.STOCK_DIALOG_INFO, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_ADD, gtk.RESPONSE_OK), + Gtk.STOCK_DIALOG_INFO, + ( + Gtk.STOCK_CANCEL, + Gtk.ResponseType.CANCEL, + Gtk.STOCK_ADD, + Gtk.ResponseType.OK, + ), parent, ) self.levels_mapping = levels_mapping - table = gtk.Table(2, 3, False) - self.username_label = gtk.Label() + table = Gtk.Table(2, 3, False) + self.username_label = Gtk.Label() self.username_label.set_markup('' + _('Username:') + '') self.username_label.set_alignment(1.0, 0.5) self.username_label.set_padding(5, 5) - self.username_entry = gtk.Entry() + self.username_entry = Gtk.Entry() table.attach(self.username_label, 0, 1, 0, 1) table.attach(self.username_entry, 1, 2, 0, 1) - self.authlevel_label = gtk.Label() + self.authlevel_label = Gtk.Label() self.authlevel_label.set_markup('' + _('Authentication Level:') + '') self.authlevel_label.set_alignment(1.0, 0.5) self.authlevel_label.set_padding(5, 5) # combo_box_new_text is deprecated but no other pygtk alternative. - self.authlevel_combo = gtk.combo_box_new_text() + self.authlevel_combo = Gtk.ComboBoxText() active_idx = None for idx, level in enumerate(levels_mapping): self.authlevel_combo.append_text(level) @@ -313,11 +321,11 @@ class AccountDialog(BaseDialog): table.attach(self.authlevel_label, 0, 1, 1, 2) table.attach(self.authlevel_combo, 1, 2, 1, 2) - self.password_label = gtk.Label() + self.password_label = Gtk.Label() self.password_label.set_markup('' + _('Password:') + '') self.password_label.set_alignment(1.0, 0.5) self.password_label.set_padding(5, 5) - self.password_entry = gtk.Entry() + self.password_entry = Gtk.Entry() self.password_entry.set_visibility(False) table.attach(self.password_label, 0, 1, 2, 3) table.attach(self.password_entry, 1, 2, 2, 3) @@ -362,24 +370,31 @@ class OtherDialog(BaseDialog): raise TypeError('default value needs to be an int or float') if not icon: - icon = gtk.STOCK_DIALOG_INFO + icon = Gtk.STOCK_DIALOG_INFO super(OtherDialog, self).__init__( header, text, icon, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_APPLY, gtk.RESPONSE_OK), + ( + Gtk.STOCK_CANCEL, + Gtk.ResponseType.CANCEL, + Gtk.STOCK_APPLY, + Gtk.ResponseType.OK, + ), parent, ) - hbox = gtk.HBox(spacing=5) - alignment_spacer = gtk.Alignment() + hbox = Gtk.HBox(spacing=5) + alignment_spacer = Gtk.Alignment() hbox.pack_start(alignment_spacer, True, True, 0) - alignment_spin = gtk.Alignment(1, 0.5, 1, 1) - adjustment_spin = gtk.Adjustment( - value=-1, lower=-1, upper=2097151, step_incr=1, page_incr=10 + alignment_spin = Gtk.Alignment(xalign=1, yalign=0.5, xscale=1, yscale=1) + adjustment_spin = Gtk.Adjustment( + value=-1, lower=-1, upper=2097151, step_increment=1, page_increment=10 + ) + self.spinbutton = Gtk.SpinButton( + adjustment=adjustment_spin, climb_rate=0, digits=0 ) - self.spinbutton = gtk.SpinButton(adjustment_spin) self.spinbutton.set_value(default) self.spinbutton.select_region(0, -1) self.spinbutton.set_width_chars(6) @@ -389,7 +404,7 @@ class OtherDialog(BaseDialog): self.spinbutton.set_digits(1) alignment_spin.add(self.spinbutton) hbox.pack_start(alignment_spin, False, True, 0) - label_type = gtk.Label() + label_type = Gtk.Label() label_type.set_text(unit_text) label_type.set_alignment(0.0, 0.5) hbox.pack_start(label_type, True, True, 0) @@ -403,7 +418,7 @@ class OtherDialog(BaseDialog): def _on_response(self, widget, response): value = None - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: if self.value_type is int: value = self.spinbutton.get_value_as_int() else: @@ -416,7 +431,7 @@ class PasswordDialog(BaseDialog): """ Displays a dialog with an entry field asking for a password. - When run(), it will return either a gtk.RESPONSE_CANCEL or a gtk.RESPONSE_OK. + When run(), it will return either a Gtk.ResponseType.CANCEL or a Gtk.ResponseType.OK. """ def __init__(self, password_msg='', parent=None): @@ -427,17 +442,22 @@ class PasswordDialog(BaseDialog): super(PasswordDialog, self).__init__( _('Password Protected'), password_msg, - gtk.STOCK_DIALOG_AUTHENTICATION, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_CONNECT, gtk.RESPONSE_OK), + Gtk.STOCK_DIALOG_AUTHENTICATION, + ( + Gtk.STOCK_CANCEL, + Gtk.ResponseType.CANCEL, + Gtk.STOCK_CONNECT, + Gtk.ResponseType.OK, + ), parent, ) - table = gtk.Table(1, 2, False) - self.password_label = gtk.Label() + table = Gtk.Table(1, 2, False) + self.password_label = Gtk.Label() self.password_label.set_markup('' + _('Password:') + '') self.password_label.set_alignment(1.0, 0.5) self.password_label.set_padding(5, 5) - self.password_entry = gtk.Entry() + self.password_entry = Gtk.Entry() self.password_entry.set_visibility(False) self.password_entry.connect('activate', self.on_password_activate) table.attach(self.password_label, 0, 1, 1, 2) @@ -452,4 +472,4 @@ class PasswordDialog(BaseDialog): return self.password_entry.get_text() def on_password_activate(self, widget): - self.response(gtk.RESPONSE_OK) + self.response(Gtk.ResponseType.OK) diff --git a/deluge/ui/gtkui/edittrackersdialog.py b/deluge/ui/gtkui/edittrackersdialog.py index bf1ba0ca9..2a4bb7494 100644 --- a/deluge/ui/gtkui/edittrackersdialog.py +++ b/deluge/ui/gtkui/edittrackersdialog.py @@ -12,7 +12,7 @@ from __future__ import unicode_literals import logging import os.path -import gtk +from gi.repository import Gtk from twisted.internet import defer import deluge.component as component @@ -28,7 +28,7 @@ def last_tier_trackers_from_liststore(trackers_liststore): """Create a list of tracker from existing liststore and find last tier number. Args: - tracker_liststore (gtk.ListStore): A gtk.ListStore with [tier (int), tracker (str)] rows. + tracker_liststore (Gtk.ListStore): A gtk.ListStore with [tier (int), tracker (str)] rows. Returns: tuple(int, list): A tuple containing last tier number and list of trackers. @@ -79,7 +79,7 @@ def trackers_tiers_from_text(text_str=''): class EditTrackersDialog(object): def __init__(self, torrent_id, parent=None): self.torrent_id = torrent_id - self.builder = gtk.Builder() + self.builder = Gtk.Builder() self.gtkui_config = ConfigManager('gtkui.conf') # Main dialog @@ -118,18 +118,18 @@ class EditTrackersDialog(object): self.builder.connect_signals(self) # Create a liststore for tier, url - self.liststore = gtk.ListStore(int, str) + self.liststore = Gtk.ListStore(int, str) # Create the columns self.treeview.append_column( - gtk.TreeViewColumn(_('Tier'), gtk.CellRendererText(), text=0) + Gtk.TreeViewColumn(_('Tier'), Gtk.CellRendererText(), text=0) ) self.treeview.append_column( - gtk.TreeViewColumn(_('Tracker'), gtk.CellRendererText(), text=1) + Gtk.TreeViewColumn(_('Tracker'), Gtk.CellRendererText(), text=1) ) self.treeview.set_model(self.liststore) - self.liststore.set_sort_column_id(0, gtk.SORT_ASCENDING) + self.liststore.set_sort_column_id(0, Gtk.SortType.ASCENDING) self.dialog.connect('delete-event', self._on_delete_event) self.dialog.connect('response', self._on_response) @@ -163,7 +163,7 @@ class EditTrackersDialog(object): self.gtkui_config['edit_trackers_dialog_height'] = event.height def _on_delete_event(self, widget, event): - self.deferred.callback(gtk.RESPONSE_DELETE_EVENT) + self.deferred.callback(Gtk.ResponseType.DELETE_EVENT) self.dialog.destroy() def _on_response(self, widget, response): @@ -180,11 +180,11 @@ class EditTrackersDialog(object): if self.old_trackers != self.trackers: # Set the torrens trackers client.core.set_torrent_trackers(self.torrent_id, self.trackers) - self.deferred.callback(gtk.RESPONSE_OK) + self.deferred.callback(Gtk.ResponseType.OK) else: - self.deferred.callback(gtk.RESPONSE_CANCEL) + self.deferred.callback(Gtk.ResponseType.CANCEL) else: - self.deferred.callback(gtk.RESPONSE_CANCEL) + self.deferred.callback(Gtk.ResponseType.CANCEL) self.dialog.destroy() def _on_get_torrent_status(self, status): @@ -294,6 +294,6 @@ class EditTrackersDialog(object): def on_button_add_cancel_clicked(self, widget): log.debug('on_button_add_cancel_clicked') # Clear the entry widget and hide the dialog - b = gtk.TextBuffer() + b = Gtk.TextBuffer() self.builder.get_object('textview_trackers').set_buffer(b) self.add_tracker_dialog.hide() diff --git a/deluge/ui/gtkui/files_tab.py b/deluge/ui/gtkui/files_tab.py index 91a0b480c..fb8e347bf 100644 --- a/deluge/ui/gtkui/files_tab.py +++ b/deluge/ui/gtkui/files_tab.py @@ -12,15 +12,10 @@ from __future__ import division, unicode_literals import logging import os.path -import gtk import six.moves.cPickle as pickle -from gobject import TYPE_UINT64 -from gtk.gdk import ( # pylint: disable=ungrouped-imports - ACTION_DEFAULT, - ACTION_MOVE, - BUTTON1_MASK, - keyval_name, -) +from gi.repository import Gtk +from gi.repository.Gdk import DragAction, ModifierType, keyval_name +from gi.repository.GObject import TYPE_UINT64 import deluge.component as component from deluge.common import open_file, show_file @@ -38,10 +33,10 @@ from deluge.ui.gtkui.torrentview_data_funcs import cell_data_size log = logging.getLogger(__name__) CELL_PRIORITY_ICONS = { - 'Ignore': gtk.STOCK_NO, - 'Low': gtk.STOCK_GO_DOWN, - 'Normal': gtk.STOCK_OK, - 'High': gtk.STOCK_GO_UP, + 'Ignore': Gtk.STOCK_NO, + 'Low': Gtk.STOCK_GO_DOWN, + 'Normal': Gtk.STOCK_OK, + 'High': Gtk.STOCK_GO_UP, } @@ -83,8 +78,8 @@ class FilesTab(Tab): self.listview = self.main_builder.get_object('files_listview') # filename, size, progress string, progress value, priority, file index, icon id - self.treestore = gtk.TreeStore(str, TYPE_UINT64, str, float, int, int, str) - self.treestore.set_sort_column_id(0, gtk.SORT_ASCENDING) + self.treestore = Gtk.TreeStore(str, TYPE_UINT64, str, float, int, int, str) + self.treestore.set_sort_column_id(0, Gtk.SortType.ASCENDING) # We need to store the row that's being edited to prevent updating it until # it's been done editing @@ -92,11 +87,11 @@ class FilesTab(Tab): # Filename column self.filename_column_name = _('Filename') - column = gtk.TreeViewColumn(self.filename_column_name) - render = gtk.CellRendererPixbuf() + column = Gtk.TreeViewColumn(self.filename_column_name) + render = Gtk.CellRendererPixbuf() column.pack_start(render, False) column.add_attribute(render, 'stock-id', 6) - render = gtk.CellRendererText() + render = Gtk.CellRendererText() render.set_property('editable', True) render.connect('edited', self._on_filename_edited) render.connect('editing-started', self._on_filename_editing_start) @@ -112,8 +107,8 @@ class FilesTab(Tab): self.listview.append_column(column) # Size column - column = gtk.TreeViewColumn(_('Size')) - render = gtk.CellRendererText() + column = Gtk.TreeViewColumn(_('Size')) + render = Gtk.CellRendererText() column.pack_start(render, False) column.set_cell_data_func(render, cell_data_size, 1) column.set_sort_column_id(1) @@ -125,8 +120,8 @@ class FilesTab(Tab): self.listview.append_column(column) # Progress column - column = gtk.TreeViewColumn(_('Progress')) - render = gtk.CellRendererProgress() + column = Gtk.TreeViewColumn(_('Progress')) + render = Gtk.CellRendererProgress() column.pack_start(render, True) column.set_cell_data_func(render, cell_progress, (2, 3)) column.set_sort_column_id(3) @@ -138,11 +133,11 @@ class FilesTab(Tab): self.listview.append_column(column) # Priority column - column = gtk.TreeViewColumn(_('Priority')) - render = gtk.CellRendererPixbuf() + column = Gtk.TreeViewColumn(_('Priority')) + render = Gtk.CellRendererPixbuf() column.pack_start(render, False) column.set_cell_data_func(render, cell_priority_icon, 4) - render = gtk.CellRendererText() + render = Gtk.CellRendererText() column.pack_start(render, False) column.set_cell_data_func(render, cell_priority, 4) column.set_sort_column_id(4) @@ -157,7 +152,7 @@ class FilesTab(Tab): self.listview.set_model(self.treestore) - self.listview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) + self.listview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) self.file_menu = self.main_builder.get_object('menu_file_tab') self.file_menu_priority_items = [ @@ -179,9 +174,11 @@ class FilesTab(Tab): self.listview.connect('button-press-event', self._on_button_press_event) self.listview.enable_model_drag_source( - BUTTON1_MASK, [('text/plain', 0, 0)], ACTION_DEFAULT | ACTION_MOVE + ModifierType.BUTTON1_MASK, + [('text/plain', 0, 0)], + DragAction.DEFAULT | DragAction.MOVE, ) - self.listview.enable_model_drag_dest([('text/plain', 0, 0)], ACTION_DEFAULT) + self.listview.enable_model_drag_dest([('text/plain', 0, 0)], DragAction.DEFAULT) self.listview.connect('drag_data_get', self._on_drag_data_get_data) self.listview.connect('drag_data_received', self._on_drag_data_received_data) @@ -244,7 +241,7 @@ class FilesTab(Tab): cname = column.get_title() if cname in state['columns']: cstate = state['columns'][cname] - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) column.set_fixed_width(cstate['width'] if cstate['width'] > 0 else 10) if state['sort_id'] == index and state['sort_order'] is not None: column.set_sort_indicator(True) @@ -320,7 +317,7 @@ class FilesTab(Tab): path = self.get_file_path(select).split('/') filepath = os.path.join(status['download_location'], *path) log.debug('Open file: %s', filepath) - timestamp = gtk.get_current_event_time() + timestamp = Gtk.get_current_event_time() open_file(filepath, timestamp=timestamp) def _on_show_file(self, status): @@ -333,7 +330,7 @@ class FilesTab(Tab): path = self.get_file_path(select).split('/') filepath = os.path.join(status['download_location'], *path) log.debug('Show file: %s', filepath) - timestamp = gtk.get_current_event_time() + timestamp = Gtk.get_current_event_time() show_file(filepath, timestamp=timestamp) # The following 3 methods create the folder/file view in the treeview @@ -363,7 +360,7 @@ class FilesTab(Tab): for key, value in split_files.items(): if key.endswith('/'): chunk_iter = self.treestore.append( - parent_iter, [key, 0, '', 0, 0, -1, gtk.STOCK_DIRECTORY] + parent_iter, [key, 0, '', 0, 0, -1, Gtk.STOCK_DIRECTORY] ) chunk_size = self.add_files(chunk_iter, value) self.treestore.set(chunk_iter, 1, chunk_size) @@ -371,7 +368,7 @@ class FilesTab(Tab): else: self.treestore.append( parent_iter, - [key, value[1]['size'], '', 0, 0, value[0], gtk.STOCK_FILE], + [key, value[1]['size'], '', 0, 0, value[0], Gtk.STOCK_FILE], ) chunk_size_total += value[1]['size'] return chunk_size_total @@ -502,7 +499,7 @@ class FilesTab(Tab): for widget in self.file_menu_priority_items: widget.set_sensitive(not self.__is_seed) - self.file_menu.popup(None, None, None, event.button, event.time) + self.file_menu.popup(None, None, None, None, event.button, event.time) return True def _on_key_press_event(self, widget, event): @@ -663,7 +660,7 @@ class FilesTab(Tab): 0, 0, -1, - gtk.STOCK_DIRECTORY, + Gtk.STOCK_DIRECTORY, ], ) p_itr = self.get_iter_at_path('/'.join(parent_path) + '/') @@ -684,7 +681,7 @@ class FilesTab(Tab): parent_iter = None for f in new_folders: parent_iter = self.treestore.append( - parent_iter, [f + '/', 0, '', 0, 0, -1, gtk.STOCK_DIRECTORY] + parent_iter, [f + '/', 0, '', 0, 0, -1, Gtk.STOCK_DIRECTORY] ) child = self.get_iter_at_path(old_name) self.treestore.append( @@ -793,7 +790,7 @@ class FilesTab(Tab): if new_split: for ns in new_split[:-1]: parent = self.treestore.append( - parent, [ns + '/', 0, '', 0, 0, -1, gtk.STOCK_DIRECTORY] + parent, [ns + '/', 0, '', 0, 0, -1, Gtk.STOCK_DIRECTORY] ) self.treestore[old_folder_iter][0] = new_split[-1] + '/' diff --git a/deluge/ui/gtkui/filtertreeview.py b/deluge/ui/gtkui/filtertreeview.py index ba9d9bb9e..d761a22d5 100644 --- a/deluge/ui/gtkui/filtertreeview.py +++ b/deluge/ui/gtkui/filtertreeview.py @@ -15,9 +15,9 @@ import logging import os import warnings -import gtk -from gtk.gdk import Pixbuf -from pango import ELLIPSIZE_END +from gi.repository import Gtk +from gi.repository.GdkPixbuf import Pixbuf +from gi.repository.Pango import EllipsizeMode import deluge.component as component from deluge.common import TORRENT_STATE, resource_filename @@ -53,7 +53,7 @@ class FilterTreeView(component.Component): self.tracker_icons = component.get('TrackerIcons') self.sidebar = component.get('SideBar') - self.treeview = gtk.TreeView() + self.treeview = Gtk.TreeView() self.sidebar.add_tab(self.treeview, 'filters', 'Filters') # set filter to all when hidden: @@ -61,22 +61,22 @@ class FilterTreeView(component.Component): # Create the treestore # cat, value, label, count, pixmap, visible - self.treestore = gtk.TreeStore(str, str, str, int, Pixbuf, bool) + self.treestore = Gtk.TreeStore(str, str, str, int, Pixbuf, bool) # Create the column and cells - column = gtk.TreeViewColumn('Filters') - column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE) + column = Gtk.TreeViewColumn('Filters') + column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) # icon cell - self.cell_pix = gtk.CellRendererPixbuf() + self.cell_pix = Gtk.CellRendererPixbuf() column.pack_start(self.cell_pix, expand=False) column.add_attribute(self.cell_pix, 'pixbuf', 4) # label cell - cell_label = gtk.CellRendererText() - cell_label.set_property('ellipsize', ELLIPSIZE_END) + cell_label = Gtk.CellRendererText() + cell_label.set_property('ellipsize', EllipsizeMode.END) column.pack_start(cell_label, expand=True) column.set_cell_data_func(cell_label, self.render_cell_data, None) # count cell - self.cell_count = gtk.CellRendererText() + self.cell_count = Gtk.CellRendererText() self.cell_count.set_property('xalign', 1.0) self.cell_count.set_padding(3, 0) column.pack_start(self.cell_count, expand=False) @@ -88,7 +88,7 @@ class FilterTreeView(component.Component): self.treeview.set_headers_visible(False) self.treeview.set_level_indentation(-21) # Force theme to use expander-size so we don't cut out entries due to indentation hack. - gtk.rc_parse_string( + Gtk.rc_parse_string( """style "treeview-style" {GtkTreeView::expander-size = 7} class "GtkTreeView" style "treeview-style" """ ) @@ -100,12 +100,12 @@ class FilterTreeView(component.Component): self.treeview.connect('button-press-event', self.on_button_press_event) # colors using current theme. - style = component.get('MainWindow').window.get_style() - self.colour_background = style.bg[gtk.STATE_NORMAL] - self.colour_foreground = style.fg[gtk.STATE_NORMAL] + style_ctx = component.get('MainWindow').window.get_style_context() + self.colour_background = style_ctx.get_background_color(Gtk.StateFlags.NORMAL) + self.colour_foreground = style_ctx.get_color(Gtk.StateFlags.NORMAL) # filtertree menu - builder = gtk.Builder() + builder = Gtk.Builder() builder.add_from_file( resource_filename( 'deluge.ui.gtkui', os.path.join('glade', 'filtertree_menu.ui') @@ -338,7 +338,7 @@ class FilterTreeView(component.Component): # Show the pop-up menu self.set_menu_sensitivity() self.menu.hide() - self.menu.popup(None, None, None, event.button, event.time) + self.menu.popup(None, None, None, None, event.button, event.time) self.menu.show() if cat == 'cat': diff --git a/deluge/ui/gtkui/glade/add_torrent_dialog.ui b/deluge/ui/gtkui/glade/add_torrent_dialog.ui index 664393e38..429a07abf 100644 --- a/deluge/ui/gtkui/glade/add_torrent_dialog.ui +++ b/deluge/ui/gtkui/glade/add_torrent_dialog.ui @@ -1,7 +1,7 @@ + - - + -1 9999 @@ -32,11 +32,59 @@ center-on-parent True dialog + + + - + True False 2 + + + True + False + end + + + gtk-cancel + False + True + True + True + True + + + + False + False + 0 + + + + + gtk-add + False + True + True + True + True + + + + False + False + 1 + + + + + False + True + end + 1 + + True @@ -57,8 +105,6 @@ True True - automatic - automatic in @@ -66,6 +112,9 @@ True True False + + + @@ -96,7 +145,7 @@ True False gtk-open - 1 + 1 False @@ -142,7 +191,7 @@ True False gtk-network - 1 + 1 False @@ -188,7 +237,7 @@ True False gtk-revert-to-saved - 1 + 1 False @@ -289,7 +338,6 @@ True True False - 1 True @@ -346,8 +394,6 @@ True True 2 - automatic - automatic in @@ -356,7 +402,10 @@ 1 False True - + + + + @@ -504,7 +553,7 @@ - + True False @@ -607,6 +656,7 @@ used sparingly. True False Useful if adding a complete torrent for seeding. + start 0 True @@ -671,8 +721,6 @@ used sparingly. 1 False False - True - True adjustment1 @@ -687,8 +735,8 @@ used sparingly. True False Maximum torrent download speed - 0 Down Speed: + 0 GTK_FILL @@ -700,8 +748,8 @@ used sparingly. True False Maximum torrent upload speed - 0 Up Speed: + 0 1 @@ -715,8 +763,8 @@ used sparingly. True False Maximum torrent connections - 0 Connections: + 0 2 @@ -730,8 +778,8 @@ used sparingly. True False Maximum torrent upload slots - 0 Upload Slots: + 0 3 @@ -747,8 +795,6 @@ used sparingly. 1 False False - True - True adjustment2 if-valid @@ -768,8 +814,6 @@ used sparingly. 1 False False - True - True adjustment3 @@ -788,8 +832,6 @@ used sparingly. 1 False False - True - True adjustment4 @@ -866,8 +908,8 @@ used sparingly. True False - 0 Apply To All + 0 False @@ -1002,49 +1044,6 @@ used sparingly. 0 - - - True - False - end - - - gtk-cancel - True - True - True - True - - - - False - False - 0 - - - - - gtk-add - True - True - True - True - - - - False - False - 1 - - - - - False - True - end - 1 - - diff --git a/deluge/ui/gtkui/glade/main_window.tabs.ui b/deluge/ui/gtkui/glade/main_window.tabs.ui index ba99cfbe3..344bfd6db 100644 --- a/deluge/ui/gtkui/glade/main_window.tabs.ui +++ b/deluge/ui/gtkui/glade/main_window.tabs.ui @@ -1,7 +1,7 @@ + - - + -1 999999 @@ -38,18 +38,18 @@ False + + + True True left - 8 True True - automatic - automatic True @@ -77,8 +77,8 @@ True False - True 0.10000000149 + True True @@ -114,8 +114,8 @@ True False - 0 20 + 0 1 @@ -143,8 +143,8 @@ True False - 0 15 + 0 1 @@ -189,8 +189,8 @@ True False - 0 Downloaded: + 0 @@ -212,8 +212,8 @@ True False - 0 Down Speed: + 0 @@ -233,8 +233,8 @@ True False - 0 Up Speed: + 0 @@ -256,8 +256,8 @@ True False - 0 Seeds: + 0 @@ -279,8 +279,8 @@ True False - 0 Uploaded: + 0 @@ -297,8 +297,8 @@ True False - 0 Complete Seen: + 0 @@ -315,9 +315,9 @@ True False - 0 True char + 0 7 @@ -331,8 +331,8 @@ True False - 0 Last Transfer: + 0 @@ -349,9 +349,9 @@ True False - 0 True char + 0 7 @@ -365,8 +365,8 @@ True False - 0 Seeding Time: + 0 @@ -397,8 +397,8 @@ True False - 0 Active Time: + 0 @@ -429,8 +429,8 @@ True False - 0 ETA Time: + 0 @@ -457,8 +457,8 @@ True False - 0 Peers: + 0 @@ -475,8 +475,8 @@ True False - 0 10 + 0 4 @@ -488,8 +488,8 @@ True False - 0 10 + 0 4 @@ -503,8 +503,8 @@ True False - 0 Seed Rank: + 0 @@ -535,8 +535,8 @@ True False - 0 Availability: + 0 @@ -553,9 +553,9 @@ True False - 0 True word-char + 0 4 @@ -569,8 +569,8 @@ True False - 0 Share Ratio: + 0 @@ -587,8 +587,8 @@ True False - 0 15 + 0 1 @@ -640,8 +640,6 @@ True True - automatic - automatic True @@ -670,11 +668,11 @@ True False - 0 True word-char True end + 0 1 @@ -701,8 +699,8 @@ True False - 0 Name: + 0 @@ -716,8 +714,8 @@ True False - 0 Total Size: + 0 @@ -733,8 +731,8 @@ True False - 0 True + 0 1 @@ -749,8 +747,8 @@ True False - 0 Total Files: + 0 @@ -766,8 +764,8 @@ True False - 0 True + 0 1 @@ -782,8 +780,8 @@ True False - 0 Completed: + 0 @@ -815,8 +813,8 @@ True False - 0 Added: + 0 @@ -849,8 +847,8 @@ True False - 0 Pieces: + 0 @@ -882,8 +880,8 @@ True False - 0 Hash: + 0 @@ -899,10 +897,10 @@ True False - 0 True True 40 + 0 1 @@ -917,8 +915,8 @@ True False - 0 Download Folder: + 0 @@ -934,11 +932,11 @@ True False - 0 True char True start + 0 1 @@ -952,10 +950,10 @@ True False - 0 char True end + 0 1 @@ -969,8 +967,8 @@ True False - 0 Comments: + 0 @@ -986,8 +984,8 @@ True False - 0 Created By: + 0 @@ -1003,10 +1001,10 @@ True False - 0 char True end + 0 1 @@ -1043,12 +1041,13 @@ True True - automatic - automatic True True + + + @@ -1072,12 +1071,13 @@ True True - automatic - automatic True True + + + @@ -1101,8 +1101,6 @@ True True - automatic - automatic True @@ -1179,11 +1177,8 @@ • 6 1 - True False False - True - True spin_max_connections_adjustment True @@ -1203,11 +1198,8 @@ • 6 1 - True False False - True - True spin_max_upload_adjustment 1 True @@ -1228,11 +1220,8 @@ • 6 1 - True False False - True - True spin_max_download_adjustment 1 1 @@ -1249,8 +1238,8 @@ True False - 0 Connections: + 0 2 @@ -1263,8 +1252,8 @@ True False - 0 Upload Speed: + 0 1 @@ -1277,8 +1266,8 @@ True False - 0 Download Speed: + 0 GTK_FILL @@ -1324,8 +1313,8 @@ True False - 0 Upload Slots: + 0 3 @@ -1341,11 +1330,8 @@ • 6 1 - True False False - True - True spin_max_upload_slots_adjustment True @@ -1396,8 +1382,8 @@ True False - 0 Owner: + 0 @@ -1412,9 +1398,9 @@ True False - 0 char True + 0 False @@ -1584,11 +1570,8 @@ True True • - True False False - True - True spin_stop_ratio_adjustment 1 True @@ -1695,8 +1678,6 @@ True True - automatic - automatic True @@ -1722,8 +1703,8 @@ True False - 0 Current Tracker: + 0 @@ -1739,8 +1720,8 @@ True False - 0 True + 0 1 @@ -1754,8 +1735,8 @@ True False - 0 Next Announce: + 0 @@ -1771,8 +1752,8 @@ True False - 0 True + 0 1 @@ -1786,9 +1767,9 @@ True False + Tracker Status: 0 0 - Tracker Status: @@ -1804,10 +1785,10 @@ True False - 0 True char True + 0 1 @@ -1855,8 +1836,8 @@ True False - 0 Total Trackers: + 0 @@ -1870,8 +1851,8 @@ True False - 0 True + 0 1 @@ -1883,8 +1864,8 @@ True False - 0 Private Torrent: + 0 @@ -1900,9 +1881,9 @@ True False - 0 char True + 0 1 diff --git a/deluge/ui/gtkui/glade/main_window.ui b/deluge/ui/gtkui/glade/main_window.ui index 2c8188309..3210cc60e 100644 --- a/deluge/ui/gtkui/glade/main_window.ui +++ b/deluge/ui/gtkui/glade/main_window.ui @@ -1,80 +1,17 @@ + - - + - - -1 - 999999 - 1 - 10 - - - -1 - 99999 - 1 - 10 - - - -1 - 999999 - 1 - 10 - - - -1 - 999999 - 1 - 10 - - - 99999 - 2 - 0.10000000000000001 - 10 - - - True - False - gtk-add - 1 - - - True - False - gtk-no - 1 - - - True - False - gtk-yes - 1 - - - True - False - gtk-go-up - 1 - - - True - False - gtk-goto-top - 1 - - - True - False - gtk-zoom-fit - 1 - False Deluge + + + True @@ -102,8 +39,8 @@ False True False - + @@ -114,8 +51,8 @@ False True False - + @@ -130,8 +67,8 @@ False True False - + @@ -176,8 +113,8 @@ True True accelgroup1 - + @@ -188,8 +125,8 @@ False True False - + @@ -280,8 +217,8 @@ False _Find ... True - + @@ -367,8 +304,8 @@ Frequently Asked Questions True False - + @@ -461,8 +398,8 @@ This will filter torrents for the current selection on the sidebar. _Filter True gtk-find - + False @@ -476,6 +413,7 @@ This will filter torrents for the current selection on the sidebar. False + False @@ -520,6 +458,7 @@ This will filter torrents for the current selection on the sidebar. False + False @@ -563,6 +502,7 @@ This will filter torrents for the current selection on the sidebar. False + False @@ -650,7 +590,7 @@ This will filter torrents for the current selection on the sidebar. True False gtk-close - 2 + 2 @@ -683,13 +623,9 @@ This will filter torrents for the current selection on the sidebar. This will filter torrents for the current selection on the sidebar. • True - True False gtk-clear - True - True False - True Clear the search Clear the search @@ -731,8 +667,6 @@ This will filter torrents for the current selection on the sidebar. True True - automatic - automatic out @@ -740,6 +674,9 @@ This will filter torrents for the current selection on the sidebar. True True False + + + @@ -768,8 +705,6 @@ This will filter torrents for the current selection on the sidebar. left False True - 8 - 0 False @@ -799,4 +734,70 @@ This will filter torrents for the current selection on the sidebar. + + -1 + 999999 + 1 + 10 + + + -1 + 99999 + 1 + 10 + + + -1 + 999999 + 1 + 10 + + + -1 + 999999 + 1 + 10 + + + 99999 + 2 + 0.10000000000000001 + 10 + + + True + False + gtk-add + 1 + + + True + False + gtk-no + 1 + + + True + False + gtk-yes + 1 + + + True + False + gtk-go-up + 1 + + + True + False + gtk-goto-top + 1 + + + True + False + gtk-zoom-fit + 1 + diff --git a/deluge/ui/gtkui/gtkui.py b/deluge/ui/gtkui/gtkui.py index 660e915ad..5f3a115c1 100644 --- a/deluge/ui/gtkui/gtkui.py +++ b/deluge/ui/gtkui/gtkui.py @@ -16,21 +16,22 @@ import signal import sys import time -import pygtk # isort:skip (Required before gtk import). +import gi # isort:skip (Required before Gtk import). -pygtk.require('2.0') # NOQA: E402 +gi.require_version('Gtk', '3.0') # NOQA: E402 +gi.require_version('Gdk', '3.0') # NOQA: E402 # isort:imports-thirdparty -from gobject import set_prgname -from gtk import RESPONSE_YES -from gtk.gdk import WINDOWING, threads_enter, threads_init, threads_leave -from twisted.internet import defer, gtk2reactor +from gi.repository.Gdk import threads_enter, threads_init, threads_leave +from gi.repository.GObject import set_prgname +from gi.repository.Gtk import ResponseType +from twisted.internet import defer, gtk3reactor from twisted.internet.error import ReactorAlreadyInstalledError from twisted.internet.task import LoopingCall try: # Install twisted reactor, before any other modules import reactor. - reactor = gtk2reactor.install() + reactor = gtk3reactor.install() except ReactorAlreadyInstalledError: # Running unit tests so trial already installed a rector from twisted.internet import reactor @@ -69,7 +70,7 @@ from deluge.ui.sessionproxy import SessionProxy from deluge.ui.tracker_icons import TrackerIcons from deluge.ui.translations_util import set_language, setup_translations -set_prgname('deluge'.encode('utf8')) +set_prgname('deluge') log = logging.getLogger(__name__) try: @@ -160,7 +161,7 @@ class GtkUI(object): SetConsoleCtrlHandler(on_die, True) log.debug('Win32 "die" handler registered') - elif osx_check() and WINDOWING == 'quartz': + elif osx_check(): # TODO: Add this back: `and WINDOWING == 'quartz':` import gtkosx_application self.osxapp = gtkosx_application.gtkosx_application_get() @@ -190,11 +191,9 @@ class GtkUI(object): self.queuedtorrents = QueuedTorrents() self.ipcinterface = IPCInterface(args.torrents) - # FIXME: Verify that removing gdk threading has no adverse effects. - # There are the two commits [64a94ec] [1f3e930] that added gdk threading - # and my thinking is there is no need for the code anymore. # Since PyGObject 3.10.2, calling GObject.threads_init() this is no longer needed. - # threads_init() + # For details on need for threading, see: https://wiki.gnome.org/Projects/PyGObject/Threading + threads_init() # We make sure that the UI components start once we get a core URI client.set_disconnect_callback(self.__on_disconnect) @@ -214,7 +213,7 @@ class GtkUI(object): self.statusbar = StatusBar() self.addtorrentdialog = AddTorrentDialog() - if osx_check() and WINDOWING == 'quartz': + if osx_check(): # TODO: Add this back: `and WINDOWING == 'quartz':` def nsapp_open_file(osxapp, filename): # Ignore command name which is raised at app launch (python opening main script). @@ -255,8 +254,8 @@ class GtkUI(object): # Initialize gdk threading threads_enter() reactor.run() - # Reactor no longer running so async callbacks (Deferreds) cannot be - # processed after this point. + # Reactor is not running. Any async callbacks (Deferreds) can no longer + # be processed from this point on. threads_leave() def shutdown(self, *args, **kwargs): @@ -349,7 +348,7 @@ class GtkUI(object): def on_dialog_response(response): """User response to switching mode dialog.""" - if response == RESPONSE_YES: + if response == ResponseType.Yes: # Turning off standalone self.config['standalone'] = False self._start_thinclient() diff --git a/deluge/ui/gtkui/ipcinterface.py b/deluge/ui/gtkui/ipcinterface.py index a2e348028..175d0ccfa 100644 --- a/deluge/ui/gtkui/ipcinterface.py +++ b/deluge/ui/gtkui/ipcinterface.py @@ -157,7 +157,7 @@ class IPCInterface(component.Component): reactor.run() if self.factory.stop: log.info('Success sending arguments to running Deluge.') - from gtk.gdk import notify_startup_complete + from gi.repository.Gdk import notify_startup_complete notify_startup_complete() sys.exit(0) diff --git a/deluge/ui/gtkui/listview.py b/deluge/ui/gtkui/listview.py index ba182a735..1968e61b9 100644 --- a/deluge/ui/gtkui/listview.py +++ b/deluge/ui/gtkui/listview.py @@ -11,16 +11,16 @@ from __future__ import unicode_literals import logging -import gtk -from gobject import SIGNAL_RUN_LAST, TYPE_NONE, signal_new -from gtk.gdk import Event # pylint: disable=ungrouped-imports +from gi.repository import GObject, Gtk +from gi.repository.Gdk import Event # pylint: disable=ungrouped-imports +from gi.repository.GObject import SIGNAL_RUN_LAST, TYPE_NONE, signal_new from deluge.common import decode_bytes from deluge.ui.gtkui.common import load_pickled_state_file, save_pickled_state_file # FIXME: ? signal_new( - 'button-press-event', gtk.TreeViewColumn, SIGNAL_RUN_LAST, TYPE_NONE, (Event,) + 'button-press-event', Gtk.TreeViewColumn, SIGNAL_RUN_LAST, TYPE_NONE, (Event,) ) log = logging.getLogger(__name__) @@ -44,8 +44,8 @@ class ListViewColumnState: # pylint: disable=old-style-class # FIXME: Why is this needed? class TreeModel(GObject.Object, Gtk.TreeModel): - def __init__(self, filter): - Gtk.TreeModel.__init__(self, filter) + def __init__(self, filter_): + Gtk.TreeModel.__init__(self, filter_) class ListView(object): @@ -82,7 +82,7 @@ class ListView(object): self.pixbuf_index = 0 self.data_func = None - class TreeviewColumn(gtk.TreeViewColumn, object): + class TreeviewColumn(Gtk.TreeViewColumn, object): """ TreeViewColumn does not signal right-click events, and we need them This subclass is equivalent to TreeViewColumn, but it signals these events @@ -91,9 +91,9 @@ class ListView(object): """ def __init__(self, title=None, cell_renderer=None, **args): - """ Constructor, see gtk.TreeViewColumn """ - gtk.TreeViewColumn.__init__(self, title, cell_renderer, **args) - label = gtk.Label(title) + """ Constructor, see Gtk.TreeViewColumn """ + Gtk.TreeViewColumn.__init__(self, title, cell_renderer, **args) + label = Gtk.Label(label=title) self.set_widget(label) label.show() label.__realize = label.connect('realize', self.on_realize) @@ -105,7 +105,7 @@ class ListView(object): def on_realize(self, widget): widget.disconnect(widget.__realize) del widget.__realize - button = widget.get_ancestor(gtk.Button) + button = widget.get_ancestor(Gtk.Button) if button is not None: button.connect('button-press-event', self.on_button_pressed) @@ -119,7 +119,7 @@ class ListView(object): self.cell_renderer = cell_renderer def set_visible(self, visible): - gtk.TreeViewColumn.set_visible(self, visible) + Gtk.TreeViewColumn.set_visible(self, visible) if self.data_func: if not visible: # Set data function to None to prevent unecessary calls when column is hidden @@ -143,10 +143,10 @@ class ListView(object): # User supplied a treeview widget self.treeview = treeview_widget else: - self.treeview = gtk.TreeView() + self.treeview = Gtk.TreeView() self.treeview.set_enable_search(True) - self.treeview.set_search_equal_func(self.on_keypress_search_by_name) + self.treeview.set_search_equal_func(self.on_keypress_search_by_name, None) if state_file: self.load_state(state_file) @@ -157,7 +157,7 @@ class ListView(object): self.treeview.set_rules_hint(True) self.treeview.set_reorderable(False) self.treeview.set_rubber_banding(True) # Enable mouse multi-row selection. - self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) + self.treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) # Dictionary of 'header' or 'name' to ListViewColumn object self.columns = {} @@ -191,7 +191,7 @@ class ListView(object): """ model_filter = self.liststore.filter_new() model_filter.set_visible_column(self.columns['filter'].column_indices[0]) - self.model_filter = gtk.TreeModelSort(model_filter) + self.model_filter = Gtk.TreeModelSort(model=model_filter) self.model_filter.connect('sort-column-changed', self.on_model_sort_changed) self.model_filter.connect('row-inserted', self.on_model_row_inserted) self.treeview.set_model(self.model_filter) @@ -207,7 +207,7 @@ class ListView(object): # Using the default sort column elif self.default_sort_column_id: self.model_filter.set_sort_column_id( - self.default_sort_column_id, gtk.SORT_ASCENDING + self.default_sort_column_id, Gtk.SortType.ASCENDING ) self.model_filter.set_default_sort_func( self.generic_sort_func, self.get_column_index('Added')[0] @@ -359,7 +359,7 @@ class ListView(object): def on_treeview_header_right_clicked(self, column, event): if event.button == 3: - self.menu.popup(None, None, None, event.button, event.get_time()) + self.menu.popup(None, None, None, None, event.button, event.get_time()) def register_checklist_menu(self, menu): """Register a checklist menu with the listview. It will automatically @@ -369,7 +369,7 @@ class ListView(object): def create_checklist_menu(self): """Creates a menu used for toggling the display of columns.""" - menu = self.menu = gtk.Menu() + menu = self.menu = Gtk.Menu() # Iterate through the column_index list to preserve order for name in self.column_index: column = self.columns[name] @@ -377,7 +377,7 @@ class ListView(object): # menu. if column.hidden is True: continue - menuitem = gtk.CheckMenuItem(column.name) + menuitem = Gtk.CheckMenuItem(column.name) # If the column is currently visible, make sure it's set active # (or checked) in the menu. if column.column.get_visible() is True: @@ -397,7 +397,7 @@ class ListView(object): """Creates a new GtkListStore based on the liststore_columns list""" # Create a new liststore with added column and move the data from the # old one to the new one. - new_list = gtk.ListStore(*tuple(self.liststore_columns)) + new_list = Gtk.ListStore(*tuple(self.liststore_columns)) # This function is used in the liststore.foreach method with user_data # being the new liststore and the columns list @@ -596,11 +596,11 @@ class ListView(object): column_in_state = False if self.state is not None: for column_state in self.state: - if header == column_state.name.decode('utf-8'): + if header == column_state.name: # We found a loaded state column_in_state = True if column_state.width > 0: - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) column.set_fixed_width(column_state.width) column.set_visible(column_state.visible) @@ -642,7 +642,7 @@ class ListView(object): ): """Add a text column to the listview. Only the header name is required. """ - render = gtk.CellRendererText() + render = Gtk.CellRendererText() self.add_column( header, render, @@ -674,7 +674,7 @@ class ListView(object): default=True, ): """Add a bool column to the listview""" - render = gtk.CellRendererToggle() + render = Gtk.CellRendererToggle() self.add_column( header, render, @@ -705,7 +705,7 @@ class ListView(object): """Add a function column to the listview. Need a header name, the function and the column types.""" - render = gtk.CellRendererText() + render = Gtk.CellRendererText() self.add_column( header, render, @@ -741,7 +741,7 @@ class ListView(object): if col_types is None: col_types = [float, str] - render = gtk.CellRendererProgress() + render = Gtk.CellRendererProgress() self.add_column( header, render, @@ -779,8 +779,8 @@ class ListView(object): """Adds a texticon column to the listview.""" if col_types is None: col_types = [str, str] - render1 = gtk.CellRendererPixbuf() - render2 = gtk.CellRendererText() + render1 = Gtk.CellRendererPixbuf() + render2 = Gtk.CellRendererText() self.add_column( header, diff --git a/deluge/ui/gtkui/mainwindow.py b/deluge/ui/gtkui/mainwindow.py index b967f7262..9403916e0 100644 --- a/deluge/ui/gtkui/mainwindow.py +++ b/deluge/ui/gtkui/mainwindow.py @@ -9,18 +9,12 @@ from __future__ import unicode_literals -import copy import logging import os.path from hashlib import sha1 as sha -import gtk -from gtk.gdk import ( - ACTION_COPY, - WINDOW_STATE_ICONIFIED, - WINDOW_STATE_MAXIMIZED, - WINDOW_STATE_WITHDRAWN, -) +from gi.repository import Gtk +from gi.repository.Gdk import DragAction, WindowState from twisted.internet import reactor from twisted.internet.error import ReactorNotRunning @@ -33,9 +27,13 @@ from deluge.ui.gtkui.dialogs import PasswordDialog from deluge.ui.gtkui.ipcinterface import process_args try: - import wnck + import gi + + gi.require_version('Wnck', '3.0') + from gi.repository import Wnck except ImportError: - wnck = None + Wnck = None + log = logging.getLogger(__name__) @@ -65,11 +63,11 @@ class _GtkBuilderSignalsHolder(object): class MainWindow(component.Component): def __init__(self): - if wnck: - self.screen = wnck.screen_get_default() + if Wnck: + self.screen = Wnck.Screen.get_default() component.Component.__init__(self, 'MainWindow', interval=2) self.config = ConfigManager('gtkui.conf') - self.main_builder = gtk.Builder() + self.main_builder = Gtk.Builder() # Patch this GtkBuilder to avoid connecting signals from elsewhere # @@ -115,7 +113,9 @@ class MainWindow(component.Component): self.restart = False self.window.drag_dest_set( - gtk.DEST_DEFAULT_ALL, [('text/uri-list', 0, 80)], ACTION_COPY + Gtk.DestDefaults.ALL, + [Gtk.TargetEntry.new(target='text/uri-list', flags=0, info=80)], + DragAction.COPY, ) # Connect events @@ -124,7 +124,7 @@ class MainWindow(component.Component): self.window.connect('delete-event', self.on_window_delete_event) self.window.connect('drag-data-received', self.on_drag_data_received_event) self.vpaned.connect('notify::position', self.on_vpaned_position_event) - self.window.connect('expose-event', self.on_expose_event) + self.window.connect('draw', self.on_expose_event) self.config.register_set_function( 'show_rate_in_title', self._on_set_show_rate_in_title, apply_now=False @@ -146,8 +146,8 @@ class MainWindow(component.Component): log.debug('Showing window') self.show() - while gtk.events_pending(): - gtk.main_iteration() + while Gtk.events_pending(): + Gtk.main_iteration() def show(self): component.resume(self.child_components) @@ -174,7 +174,7 @@ class MainWindow(component.Component): dialog = PasswordDialog(_('Enter your password to show Deluge...')) def on_dialog_response(response_id): - if response_id == gtk.RESPONSE_OK: + if response_id == Gtk.ResponseType.OK: if ( self.config['tray_password'] == sha(dialog.get_password()).hexdigest() @@ -225,7 +225,7 @@ class MainWindow(component.Component): dialog = PasswordDialog(_('Enter your password to Quit Deluge...')) def on_dialog_response(response_id): - if response_id == gtk.RESPONSE_OK: + if response_id == Gtk.ResponseType.OK: if ( self.config['tray_password'] == sha(dialog.get_password()).hexdigest() @@ -257,14 +257,14 @@ class MainWindow(component.Component): self.config['window_height'] = event.height def on_window_state_event(self, widget, event): - if event.changed_mask & WINDOW_STATE_MAXIMIZED: - if event.new_window_state & WINDOW_STATE_MAXIMIZED: + if event.changed_mask & WindowState.MAXIMIZED: + if event.new_window_state & WindowState.MAXIMIZED: log.debug('pos: %s', self.window.get_position()) self.config['window_maximized'] = True - elif not event.new_window_state & WINDOW_STATE_WITHDRAWN: + elif not event.new_window_state & WindowState.WITHDRAWN: self.config['window_maximized'] = False - if event.changed_mask & WINDOW_STATE_ICONIFIED: - if event.new_window_state & WINDOW_STATE_ICONIFIED: + if event.changed_mask & WindowState.ICONIFIED: + if event.new_window_state & WindowState.ICONIFIED: log.debug('MainWindow is minimized..') component.get('TorrentView').save_state() component.pause(self.child_components) @@ -341,9 +341,12 @@ class MainWindow(component.Component): bool: True if on active workspace (or wnck module not available), otherwise False. """ - if wnck: + + if Wnck: self.screen.force_update() - win = wnck.window_get(self.window.get_window().xid) + from gi.repository import GdkX11 # NOQA + + win = Wnck.Window.get(self.window.get_window().get_xid()) if win: active_wksp = win.get_screen().get_active_workspace() if active_wksp: diff --git a/deluge/ui/gtkui/menubar.py b/deluge/ui/gtkui/menubar.py index f54f81e09..35eea9b91 100644 --- a/deluge/ui/gtkui/menubar.py +++ b/deluge/ui/gtkui/menubar.py @@ -14,7 +14,7 @@ from __future__ import unicode_literals import logging import os.path -import gtk +from gi.repository import Gtk import deluge.common import deluge.component as component @@ -34,7 +34,7 @@ class MenuBar(component.Component): self.main_builder = self.mainwindow.get_builder() self.config = ConfigManager('gtkui.conf') - self.builder = gtk.Builder() + self.builder = Gtk.Builder() # Get the torrent menu from the gtk builder file self.builder.add_from_file( deluge.common.resource_filename( @@ -74,33 +74,33 @@ class MenuBar(component.Component): 'menuitem_max_connections', 'menuitem_upload_slots', ): - submenu = gtk.Menu() - item = gtk.MenuItem(_('Set Unlimited')) + submenu = Gtk.Menu() + item = Gtk.MenuItem(_('Set Unlimited')) item.set_name(menuitem) item.connect('activate', self.on_menuitem_set_unlimited) submenu.append(item) - item = gtk.MenuItem(_('Other...')) + item = Gtk.MenuItem(_('Other...')) item.set_name(menuitem) item.connect('activate', self.on_menuitem_set_other) submenu.append(item) submenu.show_all() self.builder.get_object(menuitem).set_submenu(submenu) - submenu = gtk.Menu() - item = gtk.MenuItem(_('On')) + submenu = Gtk.Menu() + item = Gtk.MenuItem(_('On')) item.connect('activate', self.on_menuitem_set_automanaged_on) submenu.append(item) - item = gtk.MenuItem(_('Off')) + item = Gtk.MenuItem(_('Off')) item.connect('activate', self.on_menuitem_set_automanaged_off) submenu.append(item) submenu.show_all() self.builder.get_object('menuitem_auto_managed').set_submenu(submenu) - submenu = gtk.Menu() - item = gtk.MenuItem(_('Disable')) + submenu = Gtk.Menu() + item = Gtk.MenuItem(_('Disable')) item.connect('activate', self.on_menuitem_set_stop_seed_at_ratio_disable) submenu.append(item) - item = gtk.MenuItem(_('Enable...')) + item = Gtk.MenuItem(_('Enable...')) item.set_name('menuitem_stop_seed_at_ratio') item.connect('activate', self.on_menuitem_set_other) submenu.append(item) @@ -223,7 +223,7 @@ class MenuBar(component.Component): # Any better way than duplicating toolbar.py:update_buttons in here? def add_torrentmenu_separator(self): - sep = gtk.SeparatorMenuItem() + sep = Gtk.SeparatorMenuItem() self.torrentmenu.append(sep) sep.show() return sep @@ -310,7 +310,7 @@ class MenuBar(component.Component): log.debug('on_menuitem_open_folder') def _on_torrent_status(status): - timestamp = gtk.get_current_event_time() + timestamp = Gtk.get_current_event_time() path = os.path.join( status['download_location'], status['files'][0]['path'].split('/')[0] ) @@ -329,7 +329,7 @@ class MenuBar(component.Component): def show_move_storage_dialog(self, status): log.debug('show_move_storage_dialog') - builder = gtk.Builder() + builder = Gtk.Builder() builder.add_from_file( deluge.common.resource_filename( 'deluge.ui.gtkui', os.path.join('glade', 'move_storage_dialog.ui') @@ -352,10 +352,10 @@ class MenuBar(component.Component): del self.move_storage_dialog del self.move_storage_dialog_hbox - if response_id == gtk.RESPONSE_CANCEL: + if response_id == Gtk.ResponseType.CANCEL: on_core_result(None) - if response_id == gtk.RESPONSE_OK: + if response_id == Gtk.ResponseType.OK: log.debug( 'Moving torrents to %s', self.move_storage_path_chooser.get_text() ) @@ -454,13 +454,13 @@ class MenuBar(component.Component): _('Incoming Connections'), _('Set the maximum incoming connections'), '', - gtk.STOCK_NETWORK, + Gtk.STOCK_NETWORK, ], 'menuitem_upload_slots': [ _('Peer Upload Slots'), _('Set the maximum upload slots'), '', - gtk.STOCK_SORT_ASCENDING, + Gtk.STOCK_SORT_ASCENDING, ], 'menuitem_stop_seed_at_ratio': [ _('Stop Seed At Ratio'), @@ -545,15 +545,15 @@ class MenuBar(component.Component): self.builder.get_object('menuitem_change_owner').set_visible(True) - self.change_owner_submenu = gtk.Menu() + self.change_owner_submenu = Gtk.Menu() self.change_owner_submenu_items = {} - maingroup = gtk.RadioMenuItem(None, None) + maingroup = Gtk.RadioMenuItem(None, None) - self.change_owner_submenu_items[None] = gtk.RadioMenuItem(group=maingroup) + self.change_owner_submenu_items[None] = Gtk.RadioMenuItem(group=maingroup) for account in known_accounts: username = account['username'] - item = gtk.RadioMenuItem(group=maingroup, label=username) + item = Gtk.RadioMenuItem(group=maingroup, label=username) self.change_owner_submenu_items[username] = item self.change_owner_submenu.append(item) item.connect('toggled', self._on_change_owner_toggled, username) diff --git a/deluge/ui/gtkui/menubar_osx.py b/deluge/ui/gtkui/menubar_osx.py index 511594b04..2f282cbcd 100644 --- a/deluge/ui/gtkui/menubar_osx.py +++ b/deluge/ui/gtkui/menubar_osx.py @@ -9,8 +9,9 @@ from __future__ import unicode_literals -from gtk import ACCEL_VISIBLE, SeparatorMenuItem, accel_groups_from_object -from gtk.gdk import CONTROL_MASK, META_MASK, SHIFT_MASK +from gi.repository.Gdk import ModifierType +from gi.repository.Gtk import SeparatorMenuItem, accel_groups_from_object +from gi.repository.Gtk.AccelFlags import VISIBLE from deluge.configmanager import ConfigManager @@ -18,11 +19,11 @@ from deluge.configmanager import ConfigManager def accel_swap(item, group, skey, smod, dkey, dmod): # Accel map hack broken, see ticket #3078 # item.remove_accelerator(group, ord(skey), smod) - item.add_accelerator('activate', group, ord(dkey), dmod, ACCEL_VISIBLE) + item.add_accelerator('activate', group, ord(dkey), dmod, VISIBLE) def accel_meta(item, group, key): - accel_swap(item, group, key, CONTROL_MASK, key, META_MASK) + accel_swap(item, group, key, ModifierType.CONTROL_MASK, key, ModifierType.META_MASK) def menubar_osx(gtkui, osxapp): @@ -45,9 +46,9 @@ def menubar_osx(gtkui, osxapp): quit_all_item, group, 'q', - SHIFT_MASK | CONTROL_MASK, + ModifierType.SHIFT_MASK | ModifierType.CONTROL_MASK, 'q', - SHIFT_MASK | META_MASK, + ModifierType.SHIFT_MASK | ModifierType.META_MASK, ) for item in range(2, len(file_items)): # remove quits file_menu.remove(file_items[item]) @@ -56,7 +57,9 @@ def menubar_osx(gtkui, osxapp): edit_menu = menu_widget.get_submenu() edit_items = edit_menu.get_children() pref_item = edit_items[0] - accel_swap(pref_item, group, 'p', CONTROL_MASK, ',', META_MASK) + accel_swap( + pref_item, group, 'p', ModifierType.CONTROL_MASK, ',', ModifierType.META_MASK + ) edit_menu.remove(pref_item) conn_item = edit_items[1] diff --git a/deluge/ui/gtkui/options_tab.py b/deluge/ui/gtkui/options_tab.py index 5a68e57a9..0e75fabdb 100644 --- a/deluge/ui/gtkui/options_tab.py +++ b/deluge/ui/gtkui/options_tab.py @@ -10,7 +10,7 @@ from __future__ import unicode_literals -from gtk.gdk import keyval_name +from gi.repository.Gdk import keyval_name import deluge.component as component from deluge.ui.client import client diff --git a/deluge/ui/gtkui/path_combo_chooser.py b/deluge/ui/gtkui/path_combo_chooser.py index bdcaa0654..0dc0b7383 100755 --- a/deluge/ui/gtkui/path_combo_chooser.py +++ b/deluge/ui/gtkui/path_combo_chooser.py @@ -13,10 +13,10 @@ from __future__ import division, print_function, unicode_literals import os # FIXME: use this as fallback to get_introspection_module? -from gi.importer import modules - -# from gi.module import get_introspection_module +# from gi.importer import modules +from gi.module import get_introspection_module from gi.repository import Gdk, GObject, Gtk +from gi.repository.GObject import SignalFlags import deluge.component as component from deluge.common import resource_filename @@ -35,11 +35,11 @@ def is_ascii_value(keyval, ascii_key): def key_is_up(keyval): - return keyval == keysyms.Up or keyval == keysyms.KP_Up + return keyval == Gdk.KEY_Up or keyval == Gdk.KEY_KP_Up def key_is_down(keyval): - return keyval == keysyms.Down or keyval == keysyms.KP_Down + return keyval == Gdk.KEY_Down or keyval == Gdk.KEY_KP_Down def key_is_up_or_down(keyval): @@ -47,11 +47,11 @@ def key_is_up_or_down(keyval): def key_is_pgup_or_pgdown(keyval): - return keyval == keysyms.Page_Down or keyval == keysyms.Page_Up + return keyval == Gdk.KEY_Page_Down or keyval == Gdk.KEY_Page_Up def key_is_enter(keyval): - return keyval == keysyms.Return or keyval == keysyms.KP_Enter + return keyval == Gdk.KEY_Return or keyval == Gdk.KEY_KP_Enter def path_without_trailing_path_sep(path): @@ -193,11 +193,9 @@ class ValueList(object): Enter or Return : Select """ keyval = event.keyval - state = event.get_state() & gtk.accelerator_get_default_mod_mask() - - if keyval == keysyms.Escape or ( - key_is_up(keyval) and state == gdk.MOD1_MASK - ): # ALT Key + state = event.get_state() & Gtk.accelerator_get_default_mod_mask() + alt_up = (state == Gdk.ModifierType.MOD1_MASK) and key_is_up(keyval) + if keyval == Gdk.KEY_Escape or alt_up: self.popdown() return True # Set entry value to the selected row @@ -218,8 +216,8 @@ class ValueList(object): if event.button != 3: # Double clicked a row, set this as the entry value # and close the popup - if (double_click and event.type == gdk._2BUTTON_PRESS) or ( - not double_click and event.type == gdk.BUTTON_PRESS + if (double_click and event.type == Gdk.EventType._2BUTTON_PRESS) or ( + not double_click and event.type == Gdk.EventType.BUTTON_PRESS ): path = self.get_selection_path() if path: @@ -358,12 +356,12 @@ class StoredValuesList(ValueList): :param path: the paths to edit :type path: tuple :param column: the column to edit - :type column: gtk.TreeViewColumn + :type column: Gtk.TreeViewColumn """ self.rendererText.set_property('editable', True) self.treeview.grab_focus() - self.treeview.set_cursor(path, focus_column=column, start_editing=True) + self.treeview.set_cursor(path, column=column, start_editing=True) def on_treeview_mouse_button_press_event(self, treeview, event): """ @@ -389,10 +387,10 @@ class StoredValuesList(ValueList): treeview.grab_focus() treeview.set_cursor(path, col, 0) - self.path_list_popup = gtk.Menu() - menuitem_edit = gtk.MenuItem('Edit path') + self.path_list_popup = Gtk.Menu() + menuitem_edit = Gtk.MenuItem('Edit path') self.path_list_popup.append(menuitem_edit) - menuitem_remove = gtk.MenuItem('Remove path') + menuitem_remove = Gtk.MenuItem('Remove path') self.path_list_popup.append(menuitem_remove) def on_edit_clicked(widget, path): @@ -428,16 +426,16 @@ class StoredValuesList(ValueList): """ keyval = event.keyval - ctrl = event.get_state() & gdk.CONTROL_MASK + ctrl = event.get_state() & Gdk.ModifierType.CONTROL_MASK # Edit selected row - if keyval in [keysyms.Left, keysyms.Right, keysyms.space]: + if keyval in [Gdk.KEY_Left, Gdk.KEY_Right, Gdk.KEY_space]: path = self.get_selection_path() if path: self.on_edit_path(path, self.tree_column) elif key_is_up_or_down(keyval): # Swap the row value - if event.get_state() & gdk.CONTROL_MASK: + if event.get_state() & Gdk.ModifierType.CONTROL_MASK: self.handle_list_scroll(_next=key_is_down(keyval), swap=True) else: self.handle_list_scroll(_next=key_is_down(keyval)) @@ -505,7 +503,7 @@ class CompletionList(ValueList): if ret: return ret keyval = event.keyval - ctrl = event.get_state() & gdk.CONTROL_MASK + ctrl = event.get_state() & Gdk.ModifierType.CONTROL_MASK if key_is_up_or_down(keyval): self.handle_list_scroll(_next=key_is_down(keyval)) return True @@ -555,7 +553,7 @@ class PathChooserPopup(object): if not self.path_entry.get_realized(): return self.popup_window.grab_remove() - self.popup_window.hide_all() + self.popup_window.hide() def is_popped_up(self): """Check if window is popped up. @@ -586,7 +584,7 @@ class PathChooserPopup(object): self.treeview.realize() # We start with the coordinates of the parent window - x, y = self.path_entry.get_window().get_origin() + z, x, y = self.path_entry.get_window().get_origin() # Add the position of the alignment_widget relative to the parent window. x += self.alignment_widget.get_allocation().x @@ -594,20 +592,20 @@ class PathChooserPopup(object): height_extra = 8 buttonbox_width = 0 - height = self.popup_window.size_request()[1] - width = self.popup_window.size_request()[0] + height = self.popup_window.get_preferred_size().height + width = self.popup_window.get_preferred_size().width if self.popup_buttonbox: buttonbox_height = max( - self.popup_buttonbox.size_request()[1], + self.popup_buttonbox.get_preferred_size().height, self.popup_buttonbox.get_allocation().height, ) buttonbox_width = max( - self.popup_buttonbox.size_request()[0], + self.popup_buttonbox.get_preferred_size().width, self.popup_buttonbox.get_allocation().width, ) - treeview_width = self.treeview.size_request()[0] - # After removing an element from the tree store, self.treeview.size_request()[0] + treeview_width = self.treeview.get_preferred_size().width + # After removing an element from the tree store, self.treeview.get_preferred_size()[0] # returns -1 for some reason, so the requested width cannot be used until the treeview # has been displayed once. if treeview_width != -1: @@ -621,12 +619,14 @@ class PathChooserPopup(object): width = self.alignment_widget.get_allocation().width # 10 is extra spacing - content_width = self.treeview.size_request()[0] + buttonbox_width + 10 + content_width = self.treeview.get_preferred_size().width + buttonbox_width + 10 # Adjust height according to number of list items if len(self.tree_store) > 0 and self.max_visible_rows > 0: # The height for one row in the list - self.row_height = self.treeview.size_request()[1] // len(self.tree_store) + self.row_height = self.treeview.get_preferred_size().height / len( + self.tree_store + ) # Set height to number of rows height = len(self.tree_store) * self.row_height + height_extra # Adjust the height according to the max number of rows @@ -679,13 +679,13 @@ class PathChooserPopup(object): def popup_grab_window(self): activate_time = 0 if ( - gdk.pointer_grab( + Gdk.pointer_grab( self.popup_window.get_window(), True, ( - gdk.BUTTON_PRESS_MASK - | gdk.BUTTON_RELEASE_MASK - | gdk.POINTER_MOTION_MASK + Gdk.EventMask.BUTTON_PRESS_MASK + | Gdk.EventMask.BUTTON_RELEASE_MASK + | Gdk.EventMask.POINTER_MOTION_MASK ), None, None, @@ -694,7 +694,7 @@ class PathChooserPopup(object): == 0 ): if ( - gdk.keyboard_grab(self.popup_window.get_window(), True, activate_time) + Gdk.keyboard_grab(self.popup_window.get_window(), True, activate_time) == 0 ): return True @@ -733,25 +733,11 @@ class PathChooserPopup(object): def on_popup_window_button_press_event(self, window, event): # If we're clicking outside of the window close the popup - hide = False - # Also if the intersection of self and the event is empty, hide - # the path_list - if tuple( - self.popup_window.get_allocation().intersect( - gdk.Rectangle(x=int(event.x), y=int(event.y), width=1, height=1) - ) - ) == (0, 0, 0, 0): - hide = True - # Toplevel is the window that received the event, and parent is the - # path_list window. If they are not the same, means the popup should - # be hidden. This is necessary for when the event happens on another - # widget - toplevel = event.window.get_toplevel() - parent = self.popup_window.get_window() + allocation = self.popup_window.get_allocation() - if toplevel != parent: - hide = True - if hide: + if (event.x < allocation.x or event.x > allocation.width) or ( + event.y < allocation.y or event.y > allocation.height + ): self.popdown() @@ -846,10 +832,11 @@ class StoredValuesPopup(StoredValuesList, PathChooserPopup): Handles scroll events from text entry, toggle button and treeview """ - swap = event.get_state() & gdk.CONTROL_MASK - scroll_window = event.get_state() & gdk.SHIFT_MASK + + swap = event.get_state() & Gdk.ModifierType.CONTROL_MASK + scroll_window = event.get_state() & Gdk.ModifierType.SHIFT_MASK self.handle_list_scroll( - _next=event.direction == gdk.SCROLL_DOWN, + _next=event.direction == Gdk.ScrollDirection.DOWN, set_entry=widget != self.treeview, swap=swap, scroll_window=scroll_window, @@ -862,8 +849,10 @@ class StoredValuesPopup(StoredValuesList, PathChooserPopup): is on any of the buttons in the popup """ keyval = event.keyval - state = event.get_state() & gtk.accelerator_get_default_mod_mask() - if keyval == keysyms.Escape or (key_is_up(keyval) and state == gdk.MOD1_MASK): + state = event.get_state() & Gtk.accelerator_get_default_mod_mask() + if keyval == Gdk.KEY_Escape or ( + key_is_up(keyval) and state == Gdk.ModifierType.MOD1_MASK + ): self.popdown() return True return False @@ -983,7 +972,7 @@ class PathCompletionPopup(CompletionList, PathChooserPopup): """ x, y, state = event.window.get_pointer() self.handle_list_scroll( - _next=event.direction == gdk.SCROLL_DOWN, + _next=event.direction == Gdk.ScrollDirection.DOWN, set_entry=widget != self.treeview, scroll_window=True, ) @@ -1013,7 +1002,7 @@ class PathAutoCompleter(object): self.signal_handlers[ 'on_entry_text_insert_text' ] = self.on_entry_text_insert_text - self.accelerator_string = gtk.accelerator_name(keysyms.Tab, 0) + self.accelerator_string = Gtk.accelerator_name(Gdk.KEY_Tab, 0) def on_entry_text_insert_text(self, entry, new_text, new_text_length, position): if self.path_entry.get_realized(): @@ -1050,7 +1039,7 @@ class PathAutoCompleter(object): if ret: return ret keyval = event.keyval - state = event.get_state() & gtk.accelerator_get_default_mod_mask() + state = event.get_state() & Gtk.accelerator_get_default_mod_mask() if ( self.is_auto_completion_accelerator(keyval, state) and self.auto_complete_enabled @@ -1061,10 +1050,23 @@ class PathAutoCompleter(object): else: self.completion_popup.handle_list_scroll(_next=True) return True - self.path_entry.text_entry.emit('key-press-event', event) + # Buggy stuff (in pygobject?) causing type mismatch between EventKey and GdkEvent. Convert manually... + n = Gdk.Event() + n.type = event.type + n.window = event.window + n.send_event = event.send_event + n.time = event.time + n.state = event.state + n.keyval = event.keyval + n.length = event.length + n.string = event.string + n.hardware_keycode = event.hardware_keycode + n.group = event.group + n.is_modifier = event.is_modifier + self.path_entry.text_entry.emit('key-press-event', n) def is_auto_completion_accelerator(self, keyval, state): - return gtk.accelerator_name(keyval, state.numerator) == self.accelerator_string + return Gtk.accelerator_name(keyval, state) == self.accelerator_string def do_completion(self, value=None, forward_completion=True): if not value: @@ -1100,28 +1102,34 @@ class PathAutoCompleter(object): self.completion_popup.popdown() -class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject): +# FIXME: use this as fallback to get_introspection_module? +# GtkGI = modules['Gtk']._introspection_module +GtkGI = get_introspection_module('Gtk') + + +class PathChooserComboBox(GtkGI.Box, StoredValuesPopup, GObject.GObject): __gsignals__ = { - b'list-value-added': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)), - b'list-value-removed': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)), - b'list-values-reordered': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)), - b'list-values-changed': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)), - b'auto-complete-enabled-toggled': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)), - b'show-filechooser-toggled': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)), - b'show-path-entry-toggled': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)), - b'show-folder-name-on-button': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)), - b'show-hidden-files-toggled': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)), - b'accelerator-set': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)), - b'max-rows-changed': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)), - b'text-changed': (SIGNAL_RUN_FIRST, TYPE_NONE, (object,)), + b'list-value-added': (SignalFlags.RUN_FIRST, None, (object,)), + b'list-value-removed': (SignalFlags.RUN_FIRST, None, (object,)), + b'list-values-reordered': (SignalFlags.RUN_FIRST, None, (object,)), + b'list-values-changed': (SignalFlags.RUN_FIRST, None, (object,)), + b'auto-complete-enabled-toggled': (SignalFlags.RUN_FIRST, None, (object,)), + b'show-filechooser-toggled': (SignalFlags.RUN_FIRST, None, (object,)), + b'show-path-entry-toggled': (SignalFlags.RUN_FIRST, None, (object,)), + b'show-folder-name-on-button': (SignalFlags.RUN_FIRST, None, (object,)), + b'show-hidden-files-toggled': (SignalFlags.RUN_FIRST, None, (object,)), + b'accelerator-set': (SignalFlags.RUN_FIRST, None, (object,)), + b'max-rows-changed': (SignalFlags.RUN_FIRST, None, (object,)), + b'text-changed': (SignalFlags.RUN_FIRST, None, (object,)), } def __init__( self, max_visible_rows=20, auto_complete=True, use_completer_popup=True ): - gtk.HBox.__init__(self) - GObject.__init__(self) + GtkGI.Box.__init__(self) + GObject.GObject.__init__(self) + self.list_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self._stored_values_popping_down = False self.filechooser_visible = True self.filechooser_enabled = True @@ -1129,7 +1137,7 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject): self.properties_enabled = True self.show_folder_name_on_button = False self.setting_accelerator_key = False - self.builder = gtk.Builder() + self.builder = Gtk.Builder() self.popup_buttonbox = self.builder.get_object('buttonbox') self.builder.add_from_file( resource_filename( @@ -1147,13 +1155,19 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject): self.folder_name_label = self.builder.get_object('folder_name_label') self.default_text = None self.button_properties = self.builder.get_object('button_properties') + + # FIXME: These are commented out but should be fixed. + # self.combobox_window = self.builder.get_object('combobox_window') self.combo_hbox = self.builder.get_object('entry_combobox_hbox') # Change the parent of the hbox from the glade Window to this hbox. - self.combo_hbox.reparent(self) + # self.combobox_window.remove(self.combo_hbox) + self.combobox_window = self.get_window() + self.add(self.combo_hbox) StoredValuesPopup.__init__( self, self.builder, self, max_visible_rows, self.combo_hbox ) + self.tooltips = Gtk.Tooltip() self.auto_completer = PathAutoCompleter(self.builder, self, max_visible_rows) self.auto_completer.set_use_popup(use_completer_popup) self.auto_completer.auto_complete_enabled = auto_complete @@ -1246,7 +1260,7 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject): return try: # Verify that the accelerator can be parsed - keyval, mask = gtk.accelerator_parse(self.auto_completer.accelerator_string) + keyval, mask = Gtk.accelerator_parse(self.auto_completer.accelerator_string) self.auto_completer.accelerator_string = accelerator except TypeError as ex: raise TypeError('TypeError when setting accelerator string: %s' % ex) @@ -1374,7 +1388,7 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject): def _set_path_entry_filechooser_widths(self): if self.path_entry_visible: self.combo_hbox.set_child_packing( - self.filechooser_button, 0, 0, 0, gtk.PACK_START + self.filechooser_button, 0, 0, 0, Gtk.PackType.START ) width, height = self.folder_name_label.get_size_request() width = 120 @@ -1382,11 +1396,11 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject): width = 0 self.folder_name_label.set_size_request(width, height) self.combo_hbox.set_child_packing( - self.filechooser_button, 0, 0, 0, gtk.PACK_START + self.filechooser_button, 0, 0, 0, Gtk.PackType.START ) else: self.combo_hbox.set_child_packing( - self.filechooser_button, 1, 1, 0, gtk.PACK_START + self.filechooser_button, 1, 1, 0, Gtk.PackType.START ) self.folder_name_label.set_size_request(-1, -1) # Update text on the button label @@ -1418,9 +1432,10 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject): Return True whenever we want no other event listeners to be called. """ + # on_entry_text_key_press_event Errors follow here when pressing ALT key while popup is visible") keyval = event.keyval - state = event.get_state() & gtk.accelerator_get_default_mod_mask() - ctrl = event.get_state() & gdk.CONTROL_MASK + state = event.get_state() & Gtk.accelerator_get_default_mod_mask() + ctrl = event.get_state() & Gdk.ModifierType.CONTROL_MASK # Select new row with arrow up/down is pressed if key_is_up_or_down(keyval): @@ -1484,8 +1499,8 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject): self.popdown() self.enable_completion.set_active(self.get_auto_complete_enabled()) # Set the value of the label to the current accelerator - keyval, mask = gtk.accelerator_parse(self.auto_completer.accelerator_string) - self.accelerator_label.set_text(gtk.accelerator_get_label(keyval, mask)) + keyval, mask = Gtk.accelerator_parse(self.auto_completer.accelerator_string) + self.accelerator_label.set_text(Gtk.accelerator_get_label(keyval, mask)) self.visible_rows.set_value(self.get_max_popup_rows()) self.show_filechooser_checkbutton.set_active( self.get_filechooser_button_visible() @@ -1611,23 +1626,23 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject): def on_completion_config_dialog_key_release_event(widget, event): # We are listening for a new key if set_key_button.get_active(): - state = event.get_state() & gtk.accelerator_get_default_mod_mask() + state = event.get_state() & Gtk.accelerator_get_default_mod_mask() accelerator_mask = state.numerator # If e.g. only CTRL key is pressed. - if not gtk.accelerator_valid(event.keyval, accelerator_mask): + if not Gtk.accelerator_valid(event.keyval, accelerator_mask): accelerator_mask = 0 - self.auto_completer.accelerator_string = gtk.accelerator_name( + self.auto_completer.accelerator_string = Gtk.accelerator_name( event.keyval, accelerator_mask ) self.accelerator_label.set_text( - gtk.accelerator_get_label(event.keyval, accelerator_mask) + Gtk.accelerator_get_label(event.keyval, accelerator_mask) ) self.emit('accelerator-set', self.auto_completer.accelerator_string) stop_setting_accelerator() return True else: keyval = event.keyval - ctrl = event.get_state() & gdk.CONTROL_MASK + ctrl = event.get_state() & Gdk.ModifierType.CONTROL_MASK if ctrl: # Set show/hide hidden files if is_ascii_value(keyval, 'h'): @@ -1656,19 +1671,23 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject): } -type_register(PathChooserComboBox) +GObject.type_register(PathChooserComboBox) if __name__ == '__main__': + import signal + + # necessary to exit with CTRL-C (https://bugzilla.gnome.org/show_bug.cgi?id=622084) + signal.signal(signal.SIGINT, signal.SIG_DFL) import sys - w = gtk.Window() - w.set_position(gtk.WIN_POS_CENTER) + w = Gtk.Window() + w.set_position(Gtk.WindowPosition.CENTER) w.set_size_request(600, -1) w.set_title('ComboEntry example') - w.connect('delete-event', gtk.main_quit) + w.connect('delete-event', Gtk.main_quit) - box1 = gtk.VBox(gtk.FALSE, 0) + box1 = Gtk.VBox(False, 0) def get_resource2(filename): return '%s/glade/%s' % (os.path.abspath(os.path.dirname(sys.argv[0])), filename) @@ -1713,4 +1732,4 @@ if __name__ == '__main__': entry2.connect('list-value-added', list_value_added_event) w.add(box1) w.show_all() - gtk.main() + Gtk.main() diff --git a/deluge/ui/gtkui/peers_tab.py b/deluge/ui/gtkui/peers_tab.py index 5966564a6..dc729911a 100644 --- a/deluge/ui/gtkui/peers_tab.py +++ b/deluge/ui/gtkui/peers_tab.py @@ -12,16 +12,16 @@ from __future__ import unicode_literals import logging import os.path -from gtk import ( - TREE_VIEW_COLUMN_FIXED, +from gi.repository.GdkPixbuf import Pixbuf +from gi.repository.Gtk import ( Builder, CellRendererPixbuf, CellRendererProgress, CellRendererText, ListStore, TreeViewColumn, + TreeViewColumnSizing, ) -from gtk.gdk import Pixbuf, pixbuf_new_from_file import deluge.common import deluge.component as component @@ -197,7 +197,7 @@ class PeersTab(Tab): cname = column.get_title() if cname in state['columns']: cstate = state['columns'][cname] - column.set_sizing(TREE_VIEW_COLUMN_FIXED) + column.set_sizing(TreeViewColumnSizing.FIXED) column.set_fixed_width(cstate['width'] if cstate['width'] > 0 else 10) if state['sort_id'] == index and state['sort_order'] is not None: column.set_sort_indicator(True) @@ -243,7 +243,7 @@ class PeersTab(Tab): if country not in self.cached_flag_pixbufs: # We haven't created a pixbuf for this country yet try: - self.cached_flag_pixbufs[country] = pixbuf_new_from_file( + self.cached_flag_pixbufs[country] = Pixbuf.new_from_file( deluge.common.resource_filename( 'deluge', os.path.join( @@ -351,19 +351,17 @@ class PeersTab(Tab): return True def _on_query_tooltip(self, widget, x, y, keyboard_tip, tooltip): - if not widget.get_tooltip_context(x, y, keyboard_tip): - return False - else: - model, path, _iter = widget.get_tooltip_context(x, y, keyboard_tip) - + tooltip, x, y, model, path, _iter = widget.get_tooltip_context( + x, y, keyboard_tip + ) + if tooltip: country_code = model.get(_iter, 5)[0] if country_code != ' ' and country_code in COUNTRIES: tooltip.set_text(COUNTRIES[country_code]) # widget here is self.listview widget.set_tooltip_cell(tooltip, path, widget.get_column(0), None) return True - else: - return False + return False def on_menuitem_add_peer_activate(self, menuitem): """This is a callback for manually adding a peer""" diff --git a/deluge/ui/gtkui/piecesbar.py b/deluge/ui/gtkui/piecesbar.py index 8893c6946..5e6e259fb 100644 --- a/deluge/ui/gtkui/piecesbar.py +++ b/deluge/ui/gtkui/piecesbar.py @@ -11,12 +11,16 @@ from __future__ import division, unicode_literals from math import pi -from cairo import FORMAT_ARGB32, Context, ImageSurface -from gtk import DrawingArea, ProgressBar -from gtk.gdk import colormap_get_system -from pango import SCALE, WEIGHT_BOLD -from pangocairo import CairoContext +import gi # isort:skip (Version check required before import). +gi.require_version('PangoCairo', '1.0') # NOQA: E402 + +# isort:imports-thirdparty +from gi.repository import PangoCairo, cairo +from gi.repository.Gtk import DrawingArea, ProgressBar +from gi.repository.Pango import SCALE, Weight + +# isort:imports-firstparty from deluge.configmanager import ConfigManager COLOR_STATES = ['missing', 'waiting', 'downloading', 'completed'] @@ -24,7 +28,7 @@ COLOR_STATES = ['missing', 'waiting', 'downloading', 'completed'] class PiecesBar(DrawingArea): # Draw in response to an expose-event - __gsignals__ = {b'expose-event': b'override'} + __gsignals__ = {b'draw': b'override'} def __init__(self): super(PiecesBar, self).__init__() @@ -32,7 +36,7 @@ class PiecesBar(DrawingArea): pb = ProgressBar() pb_style = pb.get_style() self.text_font = pb_style.font_desc - self.text_font.set_weight(WEIGHT_BOLD) + self.text_font.set_weight(Weight.BOLD) # Done with the ProgressBar styles, don't keep refs of it del pb, pb_style @@ -49,7 +53,6 @@ class PiecesBar(DrawingArea): self.cr = None self.connect('size-allocate', self.do_size_allocate_event) - self.set_colormap(colormap_get_system()) self.show() def do_size_allocate_event(self, widget, size): @@ -59,7 +62,7 @@ class PiecesBar(DrawingArea): self.height = size.height # Handle the expose-event by drawing - def do_expose_event(self, event): + def do_draw(self, event): # Create cairo context self.cr = self.window.cairo_create() self.cr.set_line_width(max(self.cr.device_to_user_distance(0.5, 0.5))) @@ -115,8 +118,10 @@ class PiecesBar(DrawingArea): or self.pieces_overlay is None ): # Need to recreate the cache drawing - self.pieces_overlay = ImageSurface(FORMAT_ARGB32, self.width, self.height) - ctx = Context(self.pieces_overlay) + self.pieces_overlay = cairo.ImageSurface( + cairo.FORMAT_ARGB32, self.width, self.height + ) + ctx = cairo.Context(self.pieces_overlay) if self.pieces: pieces = self.pieces @@ -152,8 +157,10 @@ class PiecesBar(DrawingArea): or self.progress_overlay is None ): # Need to recreate the cache drawing - self.progress_overlay = ImageSurface(FORMAT_ARGB32, self.width, self.height) - ctx = Context(self.progress_overlay) + self.progress_overlay = cairo.ImageSurface( + cairo.FORMAT_ARGB32, self.width, self.height + ) + ctx = cairo.Context(self.progress_overlay) ctx.set_source_rgba(0.1, 0.1, 0.1, 0.3) # Transparent ctx.rectangle(0, 0, self.width * self.fraction, self.height) ctx.fill() @@ -167,9 +174,11 @@ class PiecesBar(DrawingArea): if self.resized() or self.text != self.prev_text or self.text_overlay is None: # Need to recreate the cache drawing - self.text_overlay = ImageSurface(FORMAT_ARGB32, self.width, self.height) - ctx = Context(self.text_overlay) - pg = CairoContext(ctx) + self.text_overlay = cairo.ImageSurface( + cairo.FORMAT_ARGB32, self.width, self.height + ) + ctx = cairo.Context(self.text_overlay) + pg = PangoCairo.create_context(ctx) pl = pg.create_layout() pl.set_font_description(self.text_font) pl.set_width(-1) # No text wrapping diff --git a/deluge/ui/gtkui/preferences.py b/deluge/ui/gtkui/preferences.py index 9c690a543..3f697df54 100644 --- a/deluge/ui/gtkui/preferences.py +++ b/deluge/ui/gtkui/preferences.py @@ -14,8 +14,8 @@ import logging import os from hashlib import sha1 as sha -import gtk -from gtk.gdk import Color +from gi.repository import Gtk +from gi.repository.Gdk import Color import deluge.common import deluge.component as component @@ -64,7 +64,7 @@ COLOR_STATES = { class Preferences(component.Component): def __init__(self): component.Component.__init__(self, 'Preferences') - self.builder = gtk.Builder() + self.builder = Gtk.Builder() self.builder.add_from_file( deluge.common.resource_filename( 'deluge.ui.gtkui', os.path.join('glade', 'preferences_dialog.ui') @@ -89,10 +89,10 @@ class Preferences(component.Component): self.builder.get_object('button_associate_magnet').hide() # Setup the liststore for the categories (tab pages) - self.liststore = gtk.ListStore(int, str, str) + self.liststore = Gtk.ListStore(int, str, str) self.treeview.set_model(self.liststore) - render = gtk.CellRendererText() - column = gtk.TreeViewColumn(None, render, text=2) + render = Gtk.CellRendererText() + column = Gtk.TreeViewColumn(None, render, text=2) self.treeview.append_column(column) # Add the default categories @@ -119,26 +119,26 @@ class Preferences(component.Component): self.treeview.set_row_separator_func(set_separator, None) self.liststore.append([len(self.liststore), '_separator_', '']) # Add a dummy notebook page to keep indexing synced with liststore. - self.notebook.append_page(gtk.HSeparator()) + self.notebook.append_page(Gtk.HSeparator()) # Setup accounts tab lisview self.accounts_levels_mapping = None self.accounts_authlevel = self.builder.get_object('accounts_authlevel') - self.accounts_liststore = gtk.ListStore(str, str, str, int) + self.accounts_liststore = Gtk.ListStore(str, str, str, int) self.accounts_liststore.set_sort_column_id( - ACCOUNTS_USERNAME, gtk.SORT_ASCENDING + ACCOUNTS_USERNAME, Gtk.SortType.ASCENDING ) self.accounts_listview = self.builder.get_object('accounts_listview') self.accounts_listview.append_column( - gtk.TreeViewColumn( - _('Username'), gtk.CellRendererText(), text=ACCOUNTS_USERNAME + Gtk.TreeViewColumn( + _('Username'), Gtk.CellRendererText(), text=ACCOUNTS_USERNAME ) ) self.accounts_listview.append_column( - gtk.TreeViewColumn(_('Level'), gtk.CellRendererText(), text=ACCOUNTS_LEVEL) + Gtk.TreeViewColumn(_('Level'), Gtk.CellRendererText(), text=ACCOUNTS_LEVEL) ) - password_column = gtk.TreeViewColumn( - 'password', gtk.CellRendererText(), text=ACCOUNTS_PASSWORD + password_column = Gtk.TreeViewColumn( + 'password', Gtk.CellRendererText(), text=ACCOUNTS_PASSWORD ) self.accounts_listview.append_column(password_column) password_column.set_visible(False) @@ -151,18 +151,18 @@ class Preferences(component.Component): # Setup plugin tab listview # The third entry is for holding translated plugin names - self.plugin_liststore = gtk.ListStore(str, bool, str) - self.plugin_liststore.set_sort_column_id(0, gtk.SORT_ASCENDING) + self.plugin_liststore = Gtk.ListStore(str, bool, str) + self.plugin_liststore.set_sort_column_id(0, Gtk.SortType.ASCENDING) self.plugin_listview = self.builder.get_object('plugin_listview') self.plugin_listview.set_model(self.plugin_liststore) - render = gtk.CellRendererToggle() + render = Gtk.CellRendererToggle() render.connect('toggled', self.on_plugin_toggled) render.set_property('activatable', True) self.plugin_listview.append_column( - gtk.TreeViewColumn(_('Enabled'), render, active=1) + Gtk.TreeViewColumn(_('Enabled'), render, active=1) ) self.plugin_listview.append_column( - gtk.TreeViewColumn(_('Plugin'), gtk.CellRendererText(), text=2) + Gtk.TreeViewColumn(_('Plugin'), Gtk.CellRendererText(), text=2) ) # Connect to the 'changed' event of TreeViewSelection to get selection @@ -247,26 +247,26 @@ class Preferences(component.Component): parent = widget.get_parent() if parent: parent.remove(widget) - vbox = gtk.VBox() - label = gtk.Label() + vbox = Gtk.VBox() + label = Gtk.Label() label.set_use_markup(True) label.set_markup('' + name + '') label.set_alignment(0.00, 0.50) label.set_padding(10, 10) vbox.pack_start(label, False, True, 0) - sep = gtk.HSeparator() + sep = Gtk.HSeparator() vbox.pack_start(sep, False, True, 0) - align = gtk.Alignment() + align = Gtk.Alignment() align.set_padding(5, 0, 0, 0) align.set(0, 0, 1, 1) align.add(widget) vbox.pack_start(align, True, True, 0) - scrolled = gtk.ScrolledWindow() - viewport = gtk.Viewport() - viewport.set_shadow_type(gtk.SHADOW_NONE) + scrolled = Gtk.ScrolledWindow() + viewport = Gtk.Viewport() + viewport.set_shadow_type(Gtk.ShadowType.NONE) viewport.add(vbox) scrolled.add(viewport) - scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) scrolled.show_all() # Add this page to the notebook index = self.notebook.append_page(scrolled, None) @@ -918,7 +918,7 @@ class Preferences(component.Component): if was_standalone != new_gtkui_standalone: def on_response(response): - if response == gtk.RESPONSE_YES: + if response == Gtk.ResponseType.YES: shutdown_daemon = ( not client.is_standalone() and client.connected() @@ -1091,11 +1091,11 @@ class Preferences(component.Component): def on_get_test(status): if status: - self.builder.get_object('port_img').set_from_stock(gtk.STOCK_YES, 4) + self.builder.get_object('port_img').set_from_stock(Gtk.STOCK_YES, 4) self.builder.get_object('port_img').show() else: self.builder.get_object('port_img').set_from_stock( - gtk.STOCK_DIALOG_WARNING, 4 + Gtk.STOCK_DIALOG_WARNING, 4 ) self.builder.get_object('port_img').show() @@ -1147,15 +1147,15 @@ class Preferences(component.Component): def on_button_plugin_install_clicked(self, widget): log.debug('on_button_plugin_install_clicked') - chooser = gtk.FileChooserDialog( + chooser = Gtk.FileChooserDialog( _('Select the Plugin'), self.pref_dialog, - gtk.FILE_CHOOSER_ACTION_OPEN, + Gtk.FileChooserAction.OPEN, buttons=( - gtk.STOCK_CANCEL, - gtk.RESPONSE_CANCEL, - gtk.STOCK_OPEN, - gtk.RESPONSE_OK, + Gtk.STOCK_CANCEL, + Gtk.ResponseType.CANCEL, + Gtk.STOCK_OPEN, + Gtk.ResponseType.OK, ), ) @@ -1163,7 +1163,7 @@ class Preferences(component.Component): chooser.set_select_multiple(False) chooser.set_property('skip-taskbar-hint', True) - file_filter = gtk.FileFilter() + file_filter = Gtk.FileFilter() file_filter.set_name(_('Plugin Eggs')) file_filter.add_pattern('*.' + 'egg') chooser.add_filter(file_filter) @@ -1171,7 +1171,7 @@ class Preferences(component.Component): # Run the dialog response = chooser.run() - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: filepath = deluge.common.decode_bytes(chooser.get_filename()) else: chooser.destroy() @@ -1375,7 +1375,7 @@ class Preferences(component.Component): details=failure.getErrorMessage(), ).run() - if response_id == gtk.RESPONSE_OK: + if response_id == Gtk.ResponseType.OK: client.core.create_account(username, password, authlevel).addCallback( add_ok ).addErrback(add_fail) @@ -1408,7 +1408,7 @@ class Preferences(component.Component): details=failure.getErrorMessage(), ).run() - if response_id == gtk.RESPONSE_OK: + if response_id == Gtk.ResponseType.OK: client.core.update_account( dialog.get_username(), dialog.get_password(), dialog.get_authlevel() ).addCallback(update_ok).addErrback(update_fail) @@ -1448,7 +1448,7 @@ class Preferences(component.Component): details=failure.getErrorMessage(), ).run() - if response_id == gtk.RESPONSE_YES: + if response_id == Gtk.ResponseType.YES: client.core.remove_account(username).addCallback(remove_ok).addErrback( remove_fail ) diff --git a/deluge/ui/gtkui/queuedtorrents.py b/deluge/ui/gtkui/queuedtorrents.py index 9693dca58..38ce1bcc7 100644 --- a/deluge/ui/gtkui/queuedtorrents.py +++ b/deluge/ui/gtkui/queuedtorrents.py @@ -12,8 +12,8 @@ from __future__ import unicode_literals import logging import os.path -from gobject import timeout_add -from gtk import ( +from gi.repository.GObject import timeout_add +from gi.repository.Gtk import ( STOCK_SORT_DESCENDING, Builder, CellRendererText, diff --git a/deluge/ui/gtkui/removetorrentdialog.py b/deluge/ui/gtkui/removetorrentdialog.py index 92bbe1e8c..d5d627a2a 100644 --- a/deluge/ui/gtkui/removetorrentdialog.py +++ b/deluge/ui/gtkui/removetorrentdialog.py @@ -12,7 +12,7 @@ from __future__ import unicode_literals import logging import os -import gtk +from gi.repository import Gtk import deluge.common import deluge.component as component @@ -42,7 +42,7 @@ class RemoveTorrentDialog(object): self.__torrent_ids = torrent_ids - self.builder = gtk.Builder() + self.builder = Gtk.Builder() self.builder.add_from_file( deluge.common.resource_filename( 'deluge.ui.gtkui', os.path.join('glade', 'remove_torrent_dialog.ui') @@ -88,6 +88,6 @@ class RemoveTorrentDialog(object): Shows the dialog and awaits for user input. The user can select to remove the torrent(s) from the session with or without their data. """ - if self.__dialog.run() == gtk.RESPONSE_OK: + if self.__dialog.run() == Gtk.ResponseType.OK: self.__remove_torrents(self.builder.get_object('delete_files').get_active()) self.__dialog.destroy() diff --git a/deluge/ui/gtkui/sidebar.py b/deluge/ui/gtkui/sidebar.py index f4eacfc17..8d2a8fed4 100644 --- a/deluge/ui/gtkui/sidebar.py +++ b/deluge/ui/gtkui/sidebar.py @@ -12,7 +12,7 @@ from __future__ import unicode_literals import logging -from gtk import POLICY_AUTOMATIC, Label, ScrolledWindow +from gi.repository.Gtk import Label, PolicyType, ScrolledWindow import deluge.component as component from deluge.configmanager import ConfigManager @@ -62,9 +62,9 @@ class SideBar(component.Component): log.debug('add tab: %s', tab_name) self.tabs[tab_name] = widget scrolled = ScrolledWindow() - scrolled.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC) + scrolled.set_policy(PolicyType.AUTOMATIC, PolicyType.AUTOMATIC) scrolled.add(widget) - self.notebook.insert_page(scrolled, Label(label), -1) + self.notebook.insert_page(scrolled, Label(label=label), -1) scrolled.show_all() self.after_update() diff --git a/deluge/ui/gtkui/status_tab.py b/deluge/ui/gtkui/status_tab.py index ae2c454c7..8a70aa1ec 100644 --- a/deluge/ui/gtkui/status_tab.py +++ b/deluge/ui/gtkui/status_tab.py @@ -106,7 +106,7 @@ class StatusTab(Tab): # Update all the label widgets for widget in self.tab_widgets.values(): txt = self.widget_status_as_fstr(widget, status) - if widget[0].get_text() != txt: + if widget[0].get_text().decode('utf-8') != txt: widget[0].set_text(txt) # Update progress bar seperately as it's a special case (not a label). diff --git a/deluge/ui/gtkui/statusbar.py b/deluge/ui/gtkui/statusbar.py index 0d50f7571..834d84d7b 100644 --- a/deluge/ui/gtkui/statusbar.py +++ b/deluge/ui/gtkui/statusbar.py @@ -11,8 +11,8 @@ from __future__ import division, unicode_literals import logging -import gtk -from gobject import timeout_add +from gi.repository import Gtk +from gi.repository.GObject import timeout_add import deluge.component as component from deluge.common import fsize, fspeed, get_pixmap @@ -34,11 +34,11 @@ class StatusBarItem(object): tooltip=None, ): self._widgets = [] - self._ebox = gtk.EventBox() - self._hbox = gtk.HBox() + self._ebox = Gtk.EventBox() + self._hbox = Gtk.HBox() self._hbox.set_spacing(3) - self._image = gtk.Image() - self._label = gtk.Label() + self._image = Gtk.Image() + self._label = Gtk.Label() self._hbox.add(self._image) self._hbox.add(self._label) self._ebox.add(self._hbox) @@ -76,7 +76,7 @@ class StatusBarItem(object): self._image.set_from_file(image) def set_image_from_stock(self, stock): - self._image.set_from_stock(stock, gtk.ICON_SIZE_MENU) + self._image.set_from_stock(stock, Gtk.IconSize.MENU) def set_text(self, text): if not text: @@ -134,9 +134,9 @@ class StatusBar(component.Component): } self.current_warnings = [] # Add a HBox to the statusbar after removing the initial label widget - self.hbox = gtk.HBox() + self.hbox = Gtk.HBox() self.hbox.set_spacing(10) - align = gtk.Alignment() + align = Gtk.Alignment() align.set_padding(2, 0, 3, 0) align.add(self.hbox) frame = self.statusbar.get_children()[0] @@ -145,7 +145,7 @@ class StatusBar(component.Component): self.statusbar.show_all() # Create the not connected item self.not_connected_item = StatusBarItem( - stock=gtk.STOCK_STOP, + stock=Gtk.STOCK_STOP, text=_('Not Connected'), callback=self._on_notconnected_item_clicked, ) @@ -164,7 +164,7 @@ class StatusBar(component.Component): self.remove_item(self.not_connected_item) self.connections_item = self.add_item( - stock=gtk.STOCK_NETWORK, + stock=Gtk.STOCK_NETWORK, callback=self._on_connection_item_clicked, tooltip=_('Connections (Limit)'), pack_start=True, @@ -196,14 +196,14 @@ class StatusBar(component.Component): ) self.diskspace_item = self.add_item( - stock=gtk.STOCK_HARDDISK, + stock=Gtk.STOCK_HARDDISK, callback=self._on_diskspace_item_clicked, tooltip=_('Free Disk Space'), pack_start=True, ) self.health_item = self.add_item( - stock=gtk.STOCK_DIALOG_ERROR, + stock=Gtk.STOCK_DIALOG_ERROR, text=_('Port Issue'), markup=True, tooltip=_('No incoming connections, check port forwarding'), @@ -293,7 +293,7 @@ class StatusBar(component.Component): """Displays a warning to the user in the status bar""" if text not in self.current_warnings: item = self.add_item( - stock=gtk.STOCK_DIALOG_WARNING, text=text, callback=callback + stock=Gtk.STOCK_DIALOG_WARNING, text=text, callback=callback ) self.current_warnings.append(text) timeout_add(3000, self.remove_warning, item) @@ -472,7 +472,7 @@ class StatusBar(component.Component): _('Incoming Connections'), _('Set the maximum incoming connections'), '', - gtk.STOCK_NETWORK, + Gtk.STOCK_NETWORK, self.max_connections_global, ), } @@ -492,7 +492,7 @@ class StatusBar(component.Component): elif widget.get_name() == 'other': def dialog_finished(response_id): - if response_id == gtk.RESPONSE_OK: + if response_id == Gtk.ResponseType.OK: set_value(dialog.get_value()) dialog = dialogs.OtherDialog(*other_dialog_info[core_key]) @@ -511,7 +511,7 @@ class StatusBar(component.Component): show_other=True, ) menu.show_all() - menu.popup(None, None, None, event.button, event.time) + menu.popup(None, None, None, None, event.button, event.time) def _on_set_download_speed(self, widget): log.debug('_on_set_download_speed') @@ -527,7 +527,7 @@ class StatusBar(component.Component): show_other=True, ) menu.show_all() - menu.popup(None, None, None, event.button, event.time) + menu.popup(None, None, None, None, event.button, event.time) def _on_set_upload_speed(self, widget): log.debug('_on_set_upload_speed') @@ -542,7 +542,7 @@ class StatusBar(component.Component): show_other=True, ) menu.show_all() - menu.popup(None, None, None, event.button, event.time) + menu.popup(None, None, None, None, event.button, event.time) def _on_set_connection_limit(self, widget): log.debug('_on_set_connection_limit') diff --git a/deluge/ui/gtkui/systemtray.py b/deluge/ui/gtkui/systemtray.py index 2f3453d49..f8dcc8252 100644 --- a/deluge/ui/gtkui/systemtray.py +++ b/deluge/ui/gtkui/systemtray.py @@ -12,13 +12,7 @@ from __future__ import unicode_literals import logging import os -from gtk import ( - Builder, - RadioMenuItem, - status_icon_new_from_icon_name, - status_icon_new_from_pixbuf, - status_icon_position_menu, -) +from gi.repository.Gtk import Builder, RadioMenuItem, StatusIcon import deluge.component as component from deluge.common import ( @@ -120,9 +114,9 @@ class SystemTray(component.Component): else: log.debug('Enabling the system tray icon..') if windows_check() or osx_check(): - self.tray = status_icon_new_from_pixbuf(get_logo(32)) + self.tray = StatusIcon.new_from_pixbuf(get_logo(32)) else: - self.tray = status_icon_new_from_icon_name('deluge-panel') + self.tray = StatusIcon.new_from_icon_name('deluge-panel') self.tray.connect('activate', self.on_tray_clicked) self.tray.connect('popup-menu', self.on_tray_popup) @@ -353,7 +347,7 @@ class SystemTray(component.Component): else: self.builder.get_object('menuitem_show_deluge').set_active(False) - popup_function = status_icon_position_menu + popup_function = StatusIcon.position_menu if windows_check() or osx_check(): popup_function = None button = 0 diff --git a/deluge/ui/gtkui/toolbar.py b/deluge/ui/gtkui/toolbar.py index b478e0277..98fe7459f 100644 --- a/deluge/ui/gtkui/toolbar.py +++ b/deluge/ui/gtkui/toolbar.py @@ -11,7 +11,7 @@ from __future__ import unicode_literals import logging -from gtk import SeparatorToolItem, ToolButton +from gi.repository.Gtk import SeparatorToolItem, ToolButton import deluge.component as component from deluge.configmanager import ConfigManager diff --git a/deluge/ui/gtkui/torrentdetails.py b/deluge/ui/gtkui/torrentdetails.py index 66498c16f..35c220f2a 100644 --- a/deluge/ui/gtkui/torrentdetails.py +++ b/deluge/ui/gtkui/torrentdetails.py @@ -14,7 +14,7 @@ from __future__ import unicode_literals import logging from collections import namedtuple -from gtk import CheckMenuItem, Menu, SeparatorMenuItem +from gi.repository.Gtk import CheckMenuItem, Menu, SeparatorMenuItem import deluge.component as component from deluge.ui.client import client @@ -314,7 +314,7 @@ class TorrentDetails(component.Component): """Generates the checklist menu for all the tabs and attaches it""" menu = Menu() # Create 'All' menuitem and a separator - menuitem = CheckMenuItem(self.translate_tabs['All'], True) + menuitem = CheckMenuItem.new_with_mnemonic(self.translate_tabs['All']) menuitem.set_name('All') all_tabs = True @@ -337,7 +337,7 @@ class TorrentDetails(component.Component): menuitem_list.sort() for pos, name in menuitem_list: - menuitem = CheckMenuItem(self.translate_tabs[name], True) + menuitem = CheckMenuItem.new_with_mnemonic(self.translate_tabs[name]) menuitem.set_name(name) menuitem.set_active(self.tabs[name].is_visible) menuitem.connect('toggled', self._on_menuitem_toggled) diff --git a/deluge/ui/gtkui/torrentview.py b/deluge/ui/gtkui/torrentview.py index f008d0fc4..2443c7f7a 100644 --- a/deluge/ui/gtkui/torrentview.py +++ b/deluge/ui/gtkui/torrentview.py @@ -13,9 +13,9 @@ from __future__ import unicode_literals import logging from locale import strcoll -from gobject import TYPE_UINT64, idle_add -from gtk import ENTRY_ICON_SECONDARY -from gtk.gdk import CONTROL_MASK, MOD1_MASK, SHIFT_MASK, keyval_name +from gi.repository.Gdk import ModifierType, keyval_name +from gi.repository.GObject import TYPE_UINT64, idle_add +from gi.repository.Gtk import EntryIconPosition from twisted.internet import reactor import deluge.component as component @@ -27,7 +27,7 @@ from deluge.ui.gtkui.removetorrentdialog import RemoveTorrentDialog log = logging.getLogger(__name__) try: - CTRL_ALT_MASK = CONTROL_MASK | MOD1_MASK + CTRL_ALT_MASK = ModifierType.CONTROL_MASK | ModifierType.MOD1_MASK except TypeError: # Sphinx AutoDoc has a mock issue with gtk.gdk masks. pass @@ -126,7 +126,7 @@ class SearchBox(object): def hide(self): self.visible = False self.clear_search() - self.search_box.hide_all() + self.search_box.hide() self.search_pending = self.prefiltered = None def clear_search(self): @@ -223,7 +223,7 @@ class SearchBox(object): self.search_pending = reactor.callLater(0.7, self.torrentview.update) def on_search_torrents_entry_icon_press(self, entry, icon, event): - if icon != ENTRY_ICON_SECONDARY: + if icon != EntryIconPosition.SECONDARY: return self.clear_search() @@ -753,9 +753,7 @@ class TorrentView(ListView, component.Component): log.debug('Unable to get iter from path: %s', ex) continue - child_row = self.treeview.get_model().convert_iter_to_child_iter( - None, row - ) + child_row = self.treeview.get_model().convert_iter_to_child_iter(row) child_row = ( self.treeview.get_model() .get_model() @@ -811,7 +809,7 @@ class TorrentView(ListView, component.Component): else: self.treeview.get_selection().select_iter(row) torrentmenu = component.get('MenuBar').torrentmenu - torrentmenu.popup(None, None, None, event.button, event.time) + torrentmenu.popup(None, None, None, None, event.button, event.time) return True def on_selection_changed(self, treeselection): @@ -895,7 +893,7 @@ class TorrentView(ListView, component.Component): # Move queue position up with Ctrl+Alt or Ctrl+Alt+Shift if event.get_state() & CTRL_ALT_MASK: - if event.get_state() & SHIFT_MASK: + if event.get_state() & ModifierType.SHIFT_MASK: client.core.queue_top(torrents) else: client.core.queue_up(torrents) @@ -909,7 +907,7 @@ class TorrentView(ListView, component.Component): # Move queue position down with Ctrl+Alt or Ctrl+Alt+Shift if event.get_state() & CTRL_ALT_MASK: - if event.get_state() & SHIFT_MASK: + if event.get_state() & ModifierType.SHIFT_MASK: client.core.queue_bottom(torrents) else: client.core.queue_down(torrents) @@ -918,7 +916,7 @@ class TorrentView(ListView, component.Component): log.debug('keypress_delete') torrents = self.get_selected_torrents() if torrents: - if event.get_state() & SHIFT_MASK: + if event.get_state() & ModifierType.SHIFT_MASK: RemoveTorrentDialog(torrents, delete_files=True).run() else: RemoveTorrentDialog(torrents).run()