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 @@
+
-
-
+
@@ -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 @@
1
@@ -969,8 +967,8 @@
@@ -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()