mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-09 09:58:39 +00:00
[GTKUI] Refactor gtk imports and code
* Where possible use 'from gtk import ...', i.e. if repeated often or under 10 individual imports. * Remove osx_check to not show svg. It's only an issue on Windows so should work fine... * Rearrange and deduplicate code into d.u.g.common for getting pixbuf from files. * Use 'from gtk.gdk import...' to make it cleaner to apply GTK3 changes in future. * Move generic icon code from torrent_data_funcs to common. * Fix pylint import warnings and add WindowsError to pylintrc file.
This commit is contained in:
parent
c8e6a4476d
commit
0cdf0230e9
24 changed files with 233 additions and 242 deletions
|
@ -281,7 +281,7 @@ dummy-variables-rgx=_$|dummy
|
||||||
|
|
||||||
# List of additional names supposed to be defined in builtins. Remember that
|
# List of additional names supposed to be defined in builtins. Remember that
|
||||||
# you should avoid to define new builtins when possible.
|
# you should avoid to define new builtins when possible.
|
||||||
additional-builtins=_,_n,__request__
|
additional-builtins=_,_n,__request__,WindowsError
|
||||||
|
|
||||||
# List of strings which can identify a callback function by name. A callback
|
# List of strings which can identify a callback function by name. A callback
|
||||||
# name must start or end with one of those strings.
|
# name must start or end with one of those strings.
|
||||||
|
|
|
@ -41,7 +41,7 @@ if windows_check():
|
||||||
import _winreg
|
import _winreg
|
||||||
try:
|
try:
|
||||||
hkey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, 'Software\\7-Zip')
|
hkey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, 'Software\\7-Zip')
|
||||||
except WindowsError: # pylint: disable=undefined-variable
|
except WindowsError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
win_7z_path = os.path.join(_winreg.QueryValueEx(hkey, 'Path')[0], '7z.exe')
|
win_7z_path = os.path.join(_winreg.QueryValueEx(hkey, 'Path')[0], '7z.exe')
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
import gtk
|
import gtk
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge.common import get_pixmap, get_version
|
from deluge.common import get_version
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
from deluge.ui.gtkui.common import get_deluge_icon
|
from deluge.ui.gtkui.common import get_deluge_icon, get_pixbuf
|
||||||
|
|
||||||
|
|
||||||
class AboutDialog(object):
|
class AboutDialog(object):
|
||||||
|
@ -247,7 +247,7 @@ class AboutDialog(object):
|
||||||
self.about.set_website_label('deluge-torrent.org')
|
self.about.set_website_label('deluge-torrent.org')
|
||||||
|
|
||||||
self.about.set_icon(get_deluge_icon())
|
self.about.set_icon(get_deluge_icon())
|
||||||
self.about.set_logo(gtk.gdk.pixbuf_new_from_file(get_pixmap('deluge-about.png')))
|
self.about.set_logo(get_pixbuf('deluge-about.png'))
|
||||||
|
|
||||||
if client.connected():
|
if client.connected():
|
||||||
if not client.is_standalone():
|
if not client.is_standalone():
|
||||||
|
|
|
@ -15,14 +15,46 @@ import os
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import gtk
|
|
||||||
from gobject import GError
|
from gobject import GError
|
||||||
|
from gtk import SORT_ASCENDING, Menu, MenuItem, RadioMenuItem, SeparatorMenuItem, icon_theme_get_default
|
||||||
|
from gtk.gdk import COLORSPACE_RGB, Pixbuf, pixbuf_new_from_file, pixbuf_new_from_file_at_size
|
||||||
|
|
||||||
import deluge.common
|
from deluge.common import get_pixmap, osx_check, windows_check
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def create_blank_pixbuf(size=16):
|
||||||
|
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))
|
||||||
|
except GError as ex:
|
||||||
|
log.warning(ex)
|
||||||
|
return create_blank_pixbuf()
|
||||||
|
|
||||||
|
# Status icons.. Create them from file only once to avoid constantly re-creating them.
|
||||||
|
icon_downloading = get_pixbuf('downloading16.png')
|
||||||
|
icon_seeding = get_pixbuf('seeding16.png')
|
||||||
|
icon_inactive = get_pixbuf('inactive16.png')
|
||||||
|
icon_alert = get_pixbuf('alert16.png')
|
||||||
|
icon_queued = get_pixbuf('queued16.png')
|
||||||
|
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)
|
||||||
|
except GError as ex:
|
||||||
|
# Failed to load the pixbuf (Bad image file), so return a blank pixbuf.
|
||||||
|
log.warning(ex)
|
||||||
|
return create_blank_pixbuf(size)
|
||||||
|
|
||||||
|
|
||||||
def get_logo(size):
|
def get_logo(size):
|
||||||
"""A Deluge logo.
|
"""A Deluge logo.
|
||||||
|
|
||||||
|
@ -33,12 +65,9 @@ def get_logo(size):
|
||||||
gtk.gdk.Pixbuf: deluge logo
|
gtk.gdk.Pixbuf: deluge logo
|
||||||
"""
|
"""
|
||||||
filename = 'deluge.svg'
|
filename = 'deluge.svg'
|
||||||
if deluge.common.windows_check() or deluge.common.osx_check():
|
if windows_check():
|
||||||
filename = 'deluge.png'
|
filename = 'deluge.png'
|
||||||
try:
|
return get_pixbuf_at_size(filename, size)
|
||||||
return gtk.gdk.pixbuf_new_from_file_at_size(deluge.common.get_pixmap(filename), size, size)
|
|
||||||
except GError as ex:
|
|
||||||
log.warning(ex)
|
|
||||||
|
|
||||||
|
|
||||||
def build_menu_radio_list(value_list, callback, pref_value=None, suffix=None, show_notset=False,
|
def build_menu_radio_list(value_list, callback, pref_value=None, suffix=None, show_notset=False,
|
||||||
|
@ -60,7 +89,7 @@ def build_menu_radio_list(value_list, callback, pref_value=None, suffix=None, sh
|
||||||
Returns:
|
Returns:
|
||||||
gtk.Menu: The menu radio
|
gtk.Menu: The menu radio
|
||||||
"""
|
"""
|
||||||
menu = gtk.Menu()
|
menu = Menu()
|
||||||
group = None
|
group = None
|
||||||
|
|
||||||
if pref_value > -1 and pref_value not in value_list:
|
if pref_value > -1 and pref_value not in value_list:
|
||||||
|
@ -71,7 +100,7 @@ def build_menu_radio_list(value_list, callback, pref_value=None, suffix=None, sh
|
||||||
item_text = str(value)
|
item_text = str(value)
|
||||||
if suffix:
|
if suffix:
|
||||||
item_text += ' ' + suffix
|
item_text += ' ' + suffix
|
||||||
menuitem = gtk.RadioMenuItem(group=group, label=item_text)
|
menuitem = RadioMenuItem(group=group, label=item_text)
|
||||||
group = menuitem
|
group = menuitem
|
||||||
if pref_value and value == pref_value:
|
if pref_value and value == pref_value:
|
||||||
menuitem.set_active(True)
|
menuitem.set_active(True)
|
||||||
|
@ -80,7 +109,7 @@ def build_menu_radio_list(value_list, callback, pref_value=None, suffix=None, sh
|
||||||
menu.append(menuitem)
|
menu.append(menuitem)
|
||||||
|
|
||||||
if show_notset:
|
if show_notset:
|
||||||
menuitem = gtk.RadioMenuItem(group=group, label=notset_label)
|
menuitem = RadioMenuItem(group=group, label=notset_label)
|
||||||
menuitem.set_name('unlimited')
|
menuitem.set_name('unlimited')
|
||||||
if pref_value and pref_value < notset_lessthan:
|
if pref_value and pref_value < notset_lessthan:
|
||||||
menuitem.set_active(True)
|
menuitem.set_active(True)
|
||||||
|
@ -88,9 +117,9 @@ def build_menu_radio_list(value_list, callback, pref_value=None, suffix=None, sh
|
||||||
menu.append(menuitem)
|
menu.append(menuitem)
|
||||||
|
|
||||||
if show_other:
|
if show_other:
|
||||||
menuitem = gtk.SeparatorMenuItem()
|
menuitem = SeparatorMenuItem()
|
||||||
menu.append(menuitem)
|
menu.append(menuitem)
|
||||||
menuitem = gtk.MenuItem(_('Other...'))
|
menuitem = MenuItem(_('Other...'))
|
||||||
menuitem.set_name('other')
|
menuitem.set_name('other')
|
||||||
menuitem.connect('activate', callback)
|
menuitem.connect('activate', callback)
|
||||||
menu.append(menuitem)
|
menu.append(menuitem)
|
||||||
|
@ -135,11 +164,11 @@ def get_deluge_icon():
|
||||||
Returns:
|
Returns:
|
||||||
gtk.gdk.Pixbuf: the deluge icon
|
gtk.gdk.Pixbuf: the deluge icon
|
||||||
"""
|
"""
|
||||||
if deluge.common.windows_check():
|
if windows_check():
|
||||||
return get_logo(32)
|
return get_logo(32)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
icon_theme = gtk.icon_theme_get_default()
|
icon_theme = icon_theme_get_default()
|
||||||
return icon_theme.load_icon('deluge', 64, 0)
|
return icon_theme.load_icon('deluge', 64, 0)
|
||||||
except GError:
|
except GError:
|
||||||
return get_logo(64)
|
return get_logo(64)
|
||||||
|
@ -156,12 +185,12 @@ def associate_magnet_links(overwrite=False):
|
||||||
bool: True if association was set
|
bool: True if association was set
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if deluge.common.windows_check():
|
if windows_check():
|
||||||
import _winreg
|
import _winreg
|
||||||
|
|
||||||
try:
|
try:
|
||||||
hkey = _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT, 'Magnet')
|
hkey = _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT, 'Magnet')
|
||||||
except WindowsError: # pylint: disable=undefined-variable
|
except WindowsError:
|
||||||
overwrite = True
|
overwrite = True
|
||||||
else:
|
else:
|
||||||
_winreg.CloseKey(hkey)
|
_winreg.CloseKey(hkey)
|
||||||
|
@ -170,7 +199,7 @@ def associate_magnet_links(overwrite=False):
|
||||||
deluge_exe = os.path.join(os.path.dirname(sys.executable), 'deluge.exe')
|
deluge_exe = os.path.join(os.path.dirname(sys.executable), 'deluge.exe')
|
||||||
try:
|
try:
|
||||||
magnet_key = _winreg.CreateKey(_winreg.HKEY_CLASSES_ROOT, 'Magnet')
|
magnet_key = _winreg.CreateKey(_winreg.HKEY_CLASSES_ROOT, 'Magnet')
|
||||||
except WindowsError: # pylint: disable=undefined-variable
|
except WindowsError:
|
||||||
# Could not create for all users, falling back to current user
|
# Could not create for all users, falling back to current user
|
||||||
magnet_key = _winreg.CreateKey(_winreg.HKEY_CURRENT_USER, 'Software\\Classes\\Magnet')
|
magnet_key = _winreg.CreateKey(_winreg.HKEY_CURRENT_USER, 'Software\\Classes\\Magnet')
|
||||||
|
|
||||||
|
@ -182,7 +211,7 @@ def associate_magnet_links(overwrite=False):
|
||||||
_winreg.CloseKey(magnet_key)
|
_winreg.CloseKey(magnet_key)
|
||||||
|
|
||||||
# Don't try associate magnet on OSX see: #2420
|
# Don't try associate magnet on OSX see: #2420
|
||||||
elif not deluge.common.osx_check():
|
elif not osx_check():
|
||||||
# gconf method is only available in a GNOME environment
|
# gconf method is only available in a GNOME environment
|
||||||
try:
|
try:
|
||||||
import gconf
|
import gconf
|
||||||
|
@ -280,7 +309,7 @@ def listview_replace_treestore(listview):
|
||||||
treestore.clear()
|
treestore.clear()
|
||||||
treestore.set_default_sort_func(lambda *args: 0)
|
treestore.set_default_sort_func(lambda *args: 0)
|
||||||
original_sort = treestore.get_sort_column_id()
|
original_sort = treestore.get_sort_column_id()
|
||||||
treestore.set_sort_column_id(-1, gtk.SORT_ASCENDING)
|
treestore.set_sort_column_id(-1, SORT_ASCENDING)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@ import gtk
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge.common import get_pixmap, osx_check, windows_check
|
from deluge.common import windows_check
|
||||||
from deluge.ui.gtkui.common import get_deluge_icon
|
from deluge.ui.gtkui.common import get_deluge_icon, get_pixbuf_at_size
|
||||||
|
|
||||||
|
|
||||||
class BaseDialog(gtk.Dialog):
|
class BaseDialog(gtk.Dialog):
|
||||||
|
@ -48,10 +48,9 @@ class BaseDialog(gtk.Dialog):
|
||||||
image = gtk.Image()
|
image = gtk.Image()
|
||||||
if not gtk.stock_lookup(icon) and (icon.endswith('.svg') or icon.endswith('.png')):
|
if not gtk.stock_lookup(icon) and (icon.endswith('.svg') or icon.endswith('.png')):
|
||||||
# Hack for Windows since it doesn't support svg
|
# Hack for Windows since it doesn't support svg
|
||||||
if icon.endswith('.svg') and (windows_check() or osx_check()):
|
if icon.endswith('.svg') and windows_check():
|
||||||
icon = icon.rpartition('.svg')[0] + '16.png'
|
icon = icon.rpartition('.svg')[0] + '16.png'
|
||||||
pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(get_pixmap(icon), 32, 32)
|
image.set_from_pixbuf(get_pixbuf_at_size(icon, 32))
|
||||||
image.set_from_pixbuf(pixbuf)
|
|
||||||
else:
|
else:
|
||||||
image.set_from_stock(icon, gtk.ICON_SIZE_DIALOG)
|
image.set_from_stock(icon, gtk.ICON_SIZE_DIALOG)
|
||||||
image.set_alignment(0.5, 0.0)
|
image.set_alignment(0.5, 0.0)
|
||||||
|
|
|
@ -14,8 +14,8 @@ import logging
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
import gtk
|
import gtk
|
||||||
import gtk.gdk
|
|
||||||
from gobject import TYPE_UINT64
|
from gobject import TYPE_UINT64
|
||||||
|
from gtk.gdk import ACTION_DEFAULT, ACTION_MOVE, BUTTON1_MASK, keyval_name # pylint: disable=ungrouped-imports
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge.common import FILE_PRIORITY, open_file, show_file
|
from deluge.common import FILE_PRIORITY, open_file, show_file
|
||||||
|
@ -193,10 +193,8 @@ class FilesTab(Tab):
|
||||||
self.listview.connect('button-press-event', self._on_button_press_event)
|
self.listview.connect('button-press-event', self._on_button_press_event)
|
||||||
|
|
||||||
self.listview.enable_model_drag_source(
|
self.listview.enable_model_drag_source(
|
||||||
gtk.gdk.BUTTON1_MASK,
|
BUTTON1_MASK, [('text/plain', 0, 0)], ACTION_DEFAULT | ACTION_MOVE)
|
||||||
[('text/plain', 0, 0)],
|
self.listview.enable_model_drag_dest([('text/plain', 0, 0)], ACTION_DEFAULT)
|
||||||
gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE)
|
|
||||||
self.listview.enable_model_drag_dest([('text/plain', 0, 0)], gtk.gdk.ACTION_DEFAULT)
|
|
||||||
|
|
||||||
self.listview.connect('drag_data_get', self._on_drag_data_get_data)
|
self.listview.connect('drag_data_get', self._on_drag_data_get_data)
|
||||||
self.listview.connect('drag_data_received', self._on_drag_data_received_data)
|
self.listview.connect('drag_data_received', self._on_drag_data_received_data)
|
||||||
|
@ -500,7 +498,7 @@ class FilesTab(Tab):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _on_key_press_event(self, widget, event):
|
def _on_key_press_event(self, widget, event):
|
||||||
keyname = gtk.gdk.keyval_name(event.keyval)
|
keyname = keyval_name(event.keyval)
|
||||||
if keyname is not None:
|
if keyname is not None:
|
||||||
func = getattr(self, 'keypress_' + keyname.lower(), None)
|
func = getattr(self, 'keypress_' + keyname.lower(), None)
|
||||||
selected_rows = self.listview.get_selection().get_selected_rows()[1]
|
selected_rows = self.listview.get_selection().get_selected_rows()[1]
|
||||||
|
|
|
@ -14,13 +14,14 @@ import os
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
import gtk
|
import gtk
|
||||||
import pango
|
from gtk.gdk import Pixbuf
|
||||||
from gobject import GError
|
from pango import ELLIPSIZE_END
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge.common import TORRENT_STATE, get_pixmap, resource_filename
|
from deluge.common import TORRENT_STATE, resource_filename
|
||||||
from deluge.configmanager import ConfigManager
|
from deluge.configmanager import ConfigManager
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
|
from deluge.ui.gtkui.common import get_pixbuf, get_pixbuf_at_size
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ class FilterTreeView(component.Component):
|
||||||
|
|
||||||
# Create the treestore
|
# Create the treestore
|
||||||
# cat, value, label, count, pixmap, visible
|
# cat, value, label, count, pixmap, visible
|
||||||
self.treestore = gtk.TreeStore(str, str, str, int, gtk.gdk.Pixbuf, bool)
|
self.treestore = gtk.TreeStore(str, str, str, int, Pixbuf, bool)
|
||||||
|
|
||||||
# Create the column and cells
|
# Create the column and cells
|
||||||
column = gtk.TreeViewColumn('Filters')
|
column = gtk.TreeViewColumn('Filters')
|
||||||
|
@ -72,7 +73,7 @@ class FilterTreeView(component.Component):
|
||||||
column.add_attribute(self.cell_pix, 'pixbuf', 4)
|
column.add_attribute(self.cell_pix, 'pixbuf', 4)
|
||||||
# label cell
|
# label cell
|
||||||
cell_label = gtk.CellRendererText()
|
cell_label = gtk.CellRendererText()
|
||||||
cell_label.set_property('ellipsize', pango.ELLIPSIZE_END)
|
cell_label.set_property('ellipsize', ELLIPSIZE_END)
|
||||||
column.pack_start(cell_label, expand=True)
|
column.pack_start(cell_label, expand=True)
|
||||||
column.set_cell_data_func(cell_label, self.render_cell_data, None)
|
column.set_cell_data_func(cell_label, self.render_cell_data, None)
|
||||||
# count cell
|
# count cell
|
||||||
|
@ -242,26 +243,10 @@ class FilterTreeView(component.Component):
|
||||||
pix = TRACKER_PIX.get(value, None)
|
pix = TRACKER_PIX.get(value, None)
|
||||||
|
|
||||||
if pix:
|
if pix:
|
||||||
try:
|
return get_pixbuf('%s16.png' % pix)
|
||||||
return gtk.gdk.pixbuf_new_from_file(get_pixmap('%s16.png' % pix))
|
|
||||||
except GError as ex:
|
|
||||||
log.warning(ex)
|
|
||||||
return self.get_transparent_pix(16, 16)
|
|
||||||
|
|
||||||
def get_transparent_pix(self, width, height):
|
|
||||||
pix = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, width, height)
|
|
||||||
pix.fill(0x0000000)
|
|
||||||
return pix
|
|
||||||
|
|
||||||
def set_row_image(self, cat, value, filename):
|
def set_row_image(self, cat, value, filename):
|
||||||
pix = None
|
pix = get_pixbuf_at_size(filename, 16)
|
||||||
try: # assume we could get trashed images here..
|
|
||||||
pix = gtk.gdk.pixbuf_new_from_file_at_size(filename, 16, 16)
|
|
||||||
except Exception as ex:
|
|
||||||
log.debug(ex)
|
|
||||||
|
|
||||||
if not pix:
|
|
||||||
pix = self.get_transparent_pix(16, 16)
|
|
||||||
row = self.filters[(cat, value)]
|
row = self.filters[(cat, value)]
|
||||||
self.treestore.set_value(row, 4, pix)
|
self.treestore.set_value(row, 4, pix)
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
# the additional special exception to link portions of this program with the OpenSSL library.
|
# the additional special exception to link portions of this program with the OpenSSL library.
|
||||||
# See LICENSE for more details.
|
# See LICENSE for more details.
|
||||||
#
|
#
|
||||||
|
# pylint: disable=wrong-import-position
|
||||||
|
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
|
|
||||||
|
@ -19,8 +20,9 @@ import pygtk # isort:skip (Required before gtk import).
|
||||||
pygtk.require('2.0') # NOQA: E402
|
pygtk.require('2.0') # NOQA: E402
|
||||||
|
|
||||||
# isort:imports-thirdparty
|
# isort:imports-thirdparty
|
||||||
import gtk
|
|
||||||
from gobject import set_prgname
|
from gobject import set_prgname
|
||||||
|
from gtk import RESPONSE_OK, RESPONSE_YES
|
||||||
|
from gtk.gdk import WINDOWING, threads_enter, threads_init, threads_leave
|
||||||
from twisted.internet import defer, gtk2reactor
|
from twisted.internet import defer, gtk2reactor
|
||||||
from twisted.internet.error import ReactorAlreadyInstalledError
|
from twisted.internet.error import ReactorAlreadyInstalledError
|
||||||
from twisted.internet.task import LoopingCall
|
from twisted.internet.task import LoopingCall
|
||||||
|
@ -33,8 +35,8 @@ except ReactorAlreadyInstalledError as ex:
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
|
|
||||||
# isort:imports-firstparty
|
# isort:imports-firstparty
|
||||||
import deluge.common
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
|
from deluge.common import fsize, fspeed, get_default_download_dir, osx_check, windows_check
|
||||||
from deluge.configmanager import ConfigManager, get_config_dir
|
from deluge.configmanager import ConfigManager, get_config_dir
|
||||||
from deluge.error import AuthenticationRequired, BadLoginError, DaemonRunningError
|
from deluge.error import AuthenticationRequired, BadLoginError, DaemonRunningError
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
|
@ -103,11 +105,11 @@ DEFAULT_PREFS = {
|
||||||
'autoconnect_host_id': None,
|
'autoconnect_host_id': None,
|
||||||
'autostart_localhost': False,
|
'autostart_localhost': False,
|
||||||
'autoadd_queued': False,
|
'autoadd_queued': False,
|
||||||
'choose_directory_dialog_path': deluge.common.get_default_download_dir(),
|
'choose_directory_dialog_path': get_default_download_dir(),
|
||||||
'show_new_releases': True,
|
'show_new_releases': True,
|
||||||
'ntf_tray_blink': True,
|
'ntf_tray_blink': True,
|
||||||
'ntf_sound': False,
|
'ntf_sound': False,
|
||||||
'ntf_sound_path': deluge.common.get_default_download_dir(),
|
'ntf_sound_path': get_default_download_dir(),
|
||||||
'ntf_popup': False,
|
'ntf_popup': False,
|
||||||
'ntf_email': False,
|
'ntf_email': False,
|
||||||
'ntf_email_add': '',
|
'ntf_email_add': '',
|
||||||
|
@ -144,16 +146,15 @@ class GtkUI(object):
|
||||||
log.debug("OS signal 'die' caught with args: %s", args)
|
log.debug("OS signal 'die' caught with args: %s", args)
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
|
|
||||||
if deluge.common.windows_check():
|
if windows_check():
|
||||||
from win32api import SetConsoleCtrlHandler
|
from win32api import SetConsoleCtrlHandler
|
||||||
SetConsoleCtrlHandler(on_die, True)
|
SetConsoleCtrlHandler(on_die, True)
|
||||||
log.debug("Win32 'die' handler registered")
|
log.debug("Win32 'die' handler registered")
|
||||||
elif deluge.common.osx_check():
|
elif osx_check() and WINDOWING == 'quartz':
|
||||||
if gtk.gdk.WINDOWING == 'quartz':
|
import gtkosx_application
|
||||||
import gtkosx_application
|
self.osxapp = gtkosx_application.gtkosx_application_get()
|
||||||
self.osxapp = gtkosx_application.gtkosx_application_get()
|
self.osxapp.connect('NSApplicationWillTerminate', on_die)
|
||||||
self.osxapp.connect('NSApplicationWillTerminate', on_die)
|
log.debug("OSX quartz 'die' handler registered")
|
||||||
log.debug("OSX quartz 'die' handler registered")
|
|
||||||
|
|
||||||
# Set process name again to fix gtk issue
|
# Set process name again to fix gtk issue
|
||||||
setproctitle(getproctitle())
|
setproctitle(getproctitle())
|
||||||
|
@ -179,7 +180,7 @@ class GtkUI(object):
|
||||||
self.ipcinterface = IPCInterface(args.torrents)
|
self.ipcinterface = IPCInterface(args.torrents)
|
||||||
|
|
||||||
# Initialize gdk threading
|
# Initialize gdk threading
|
||||||
gtk.gdk.threads_init()
|
threads_init()
|
||||||
|
|
||||||
# We make sure that the UI components start once we get a core URI
|
# We make sure that the UI components start once we get a core URI
|
||||||
client.set_disconnect_callback(self.__on_disconnect)
|
client.set_disconnect_callback(self.__on_disconnect)
|
||||||
|
@ -199,7 +200,7 @@ class GtkUI(object):
|
||||||
self.statusbar = StatusBar()
|
self.statusbar = StatusBar()
|
||||||
self.addtorrentdialog = AddTorrentDialog()
|
self.addtorrentdialog = AddTorrentDialog()
|
||||||
|
|
||||||
if deluge.common.osx_check() and gtk.gdk.WINDOWING == 'quartz':
|
if osx_check() and WINDOWING == 'quartz':
|
||||||
def nsapp_open_file(osxapp, filename):
|
def nsapp_open_file(osxapp, filename):
|
||||||
# Ignore command name which is raised at app launch (python opening main script).
|
# Ignore command name which is raised at app launch (python opening main script).
|
||||||
if filename == sys.argv[0]:
|
if filename == sys.argv[0]:
|
||||||
|
@ -235,11 +236,11 @@ class GtkUI(object):
|
||||||
reactor.callWhenRunning(self._on_reactor_start)
|
reactor.callWhenRunning(self._on_reactor_start)
|
||||||
|
|
||||||
# Initialize gdk threading
|
# Initialize gdk threading
|
||||||
gtk.gdk.threads_enter()
|
threads_enter()
|
||||||
reactor.run()
|
reactor.run()
|
||||||
# Reactor is not running. Any async callbacks (Deferreds) can no longer
|
# Reactor is not running. Any async callbacks (Deferreds) can no longer
|
||||||
# be processed from this point on.
|
# be processed from this point on.
|
||||||
gtk.gdk.threads_leave()
|
threads_leave()
|
||||||
|
|
||||||
def shutdown(self, *args, **kwargs):
|
def shutdown(self, *args, **kwargs):
|
||||||
log.debug('GTKUI shutting down...')
|
log.debug('GTKUI shutting down...')
|
||||||
|
@ -281,10 +282,9 @@ class GtkUI(object):
|
||||||
delta_sent = sent - self.daemon_bps[1]
|
delta_sent = sent - self.daemon_bps[1]
|
||||||
delta_recv = recv - self.daemon_bps[2]
|
delta_recv = recv - self.daemon_bps[2]
|
||||||
self.daemon_bps = (t, sent, recv)
|
self.daemon_bps = (t, sent, recv)
|
||||||
sent_rate = deluge.common.fspeed(delta_sent / delta_time)
|
sent_rate = fspeed(delta_sent / delta_time)
|
||||||
recv_rate = deluge.common.fspeed(delta_recv / delta_time)
|
recv_rate = fspeed(delta_recv / delta_time)
|
||||||
log.debug('RPC: Sent %s (%s) Recv %s (%s)',
|
log.debug('RPC: Sent %s (%s) Recv %s (%s)', fsize(sent), sent_rate, fsize(recv), recv_rate)
|
||||||
deluge.common.fsize(sent), sent_rate, deluge.common.fsize(recv), recv_rate)
|
|
||||||
|
|
||||||
def _on_reactor_start(self):
|
def _on_reactor_start(self):
|
||||||
log.debug('_on_reactor_start')
|
log.debug('_on_reactor_start')
|
||||||
|
@ -292,7 +292,7 @@ class GtkUI(object):
|
||||||
|
|
||||||
if self.config['standalone']:
|
if self.config['standalone']:
|
||||||
def on_dialog_response(response):
|
def on_dialog_response(response):
|
||||||
if response != gtk.RESPONSE_YES:
|
if response != RESPONSE_YES:
|
||||||
# The user does not want to turn Standalone Mode off, so just quit
|
# The user does not want to turn Standalone Mode off, so just quit
|
||||||
self.mainwindow.quit()
|
self.mainwindow.quit()
|
||||||
return
|
return
|
||||||
|
@ -395,7 +395,7 @@ class GtkUI(object):
|
||||||
dialog = AuthenticationDialog(reason.value.message, reason.value.username)
|
dialog = AuthenticationDialog(reason.value.message, reason.value.username)
|
||||||
|
|
||||||
def dialog_finished(response_id, host, port):
|
def dialog_finished(response_id, host, port):
|
||||||
if response_id == gtk.RESPONSE_OK:
|
if response_id == RESPONSE_OK:
|
||||||
reactor.callLater(
|
reactor.callLater(
|
||||||
0.5, do_connect, try_counter - 1,
|
0.5, do_connect, try_counter - 1,
|
||||||
host, port, dialog.get_username(),
|
host, port, dialog.get_username(),
|
||||||
|
@ -425,7 +425,7 @@ class GtkUI(object):
|
||||||
break
|
break
|
||||||
|
|
||||||
if self.config['show_connection_manager_on_start']:
|
if self.config['show_connection_manager_on_start']:
|
||||||
if deluge.common.windows_check():
|
if windows_check():
|
||||||
# Call to simulate() required to workaround showing daemon status (see #2813)
|
# Call to simulate() required to workaround showing daemon status (see #2813)
|
||||||
reactor.simulate()
|
reactor.simulate()
|
||||||
self.connectionmanager.show()
|
self.connectionmanager.show()
|
||||||
|
|
|
@ -144,8 +144,8 @@ class IPCInterface(component.Component):
|
||||||
reactor.run()
|
reactor.run()
|
||||||
if self.factory.stop:
|
if self.factory.stop:
|
||||||
log.info('Success sending arguments to running Deluge.')
|
log.info('Success sending arguments to running Deluge.')
|
||||||
import gtk
|
from gtk.gdk import notify_startup_complete
|
||||||
gtk.gdk.notify_startup_complete()
|
notify_startup_complete()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
else:
|
else:
|
||||||
if restart_tempfile:
|
if restart_tempfile:
|
||||||
|
|
|
@ -11,10 +11,11 @@ import logging
|
||||||
|
|
||||||
import gtk
|
import gtk
|
||||||
from gobject import SIGNAL_RUN_LAST, TYPE_NONE, signal_new
|
from gobject import SIGNAL_RUN_LAST, TYPE_NONE, signal_new
|
||||||
|
from gtk.gdk import Event # pylint: disable=ungrouped-imports
|
||||||
|
|
||||||
from deluge.ui.gtkui.common import load_pickled_state_file, save_pickled_state_file
|
from deluge.ui.gtkui.common import load_pickled_state_file, save_pickled_state_file
|
||||||
|
|
||||||
signal_new('button-press-event', gtk.TreeViewColumn, SIGNAL_RUN_LAST, TYPE_NONE, (gtk.gdk.Event,))
|
signal_new('button-press-event', gtk.TreeViewColumn, SIGNAL_RUN_LAST, TYPE_NONE, (Event,))
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,13 @@ import os.path
|
||||||
from hashlib import sha1 as sha
|
from hashlib import sha1 as sha
|
||||||
|
|
||||||
import gtk
|
import gtk
|
||||||
|
from gtk.gdk import ACTION_COPY, WINDOW_STATE_ICONIFIED, WINDOW_STATE_MAXIMIZED, WINDOW_STATE_WITHDRAWN
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
from twisted.internet.error import ReactorNotRunning
|
from twisted.internet.error import ReactorNotRunning
|
||||||
|
|
||||||
import deluge.common
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
import deluge.ui.gtkui.common
|
import deluge.ui.gtkui.common
|
||||||
|
from deluge.common import fspeed, resource_filename
|
||||||
from deluge.configmanager import ConfigManager
|
from deluge.configmanager import ConfigManager
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
from deluge.ui.gtkui.dialogs import PasswordDialog
|
from deluge.ui.gtkui.dialogs import PasswordDialog
|
||||||
|
@ -73,27 +74,21 @@ class MainWindow(component.Component):
|
||||||
"'component.get(\"MainWindow\").connect_signals()'")
|
"'component.get(\"MainWindow\").connect_signals()'")
|
||||||
self.main_builder.connect_signals = patched_connect_signals
|
self.main_builder.connect_signals = patched_connect_signals
|
||||||
|
|
||||||
# Get the gtk builder file for the main window
|
# Get Gtk Builder files Main Window, New release dialog, and Tabs.
|
||||||
self.main_builder.add_from_file(deluge.common.resource_filename(
|
self.main_builder.add_from_file(resource_filename('deluge.ui.gtkui', os.path.join(
|
||||||
'deluge.ui.gtkui', os.path.join('glade', 'main_window.ui')))
|
'glade', 'main_window.ui')))
|
||||||
# The new release dialog
|
self.main_builder.add_from_file(resource_filename('deluge.ui.gtkui', os.path.join(
|
||||||
self.main_builder.add_from_file(deluge.common.resource_filename(
|
'glade', 'main_window.new_release.ui')))
|
||||||
'deluge.ui.gtkui', os.path.join('glade', 'main_window.new_release.ui')))
|
self.main_builder.add_from_file(resource_filename('deluge.ui.gtkui', os.path.join(
|
||||||
# The tabs
|
'glade', 'main_window.tabs.ui')))
|
||||||
self.main_builder.add_from_file(deluge.common.resource_filename(
|
self.main_builder.add_from_file(resource_filename('deluge.ui.gtkui', os.path.join(
|
||||||
'deluge.ui.gtkui', os.path.join('glade', 'main_window.tabs.ui')))
|
'glade', 'main_window.tabs.menu_file.ui')))
|
||||||
# The tabs file menu
|
self.main_builder.add_from_file(resource_filename('deluge.ui.gtkui', os.path.join(
|
||||||
self.main_builder.add_from_file(deluge.common.resource_filename(
|
'glade', 'main_window.tabs.menu_peer.ui')))
|
||||||
'deluge.ui.gtkui', os.path.join('glade', 'main_window.tabs.menu_file.ui')))
|
|
||||||
# The tabs peer menu
|
|
||||||
self.main_builder.add_from_file(deluge.common.resource_filename(
|
|
||||||
'deluge.ui.gtkui', os.path.join('glade', 'main_window.tabs.menu_peer.ui')))
|
|
||||||
|
|
||||||
self.window = self.main_builder.get_object('main_window')
|
self.window = self.main_builder.get_object('main_window')
|
||||||
|
|
||||||
self.window.set_icon(deluge.ui.gtkui.common.get_deluge_icon())
|
self.window.set_icon(deluge.ui.gtkui.common.get_deluge_icon())
|
||||||
self.vpaned = self.main_builder.get_object('vpaned')
|
self.vpaned = self.main_builder.get_object('vpaned')
|
||||||
|
|
||||||
self.initial_vpaned_position = self.config['window_pane_position']
|
self.initial_vpaned_position = self.config['window_pane_position']
|
||||||
|
|
||||||
# Load the window state
|
# Load the window state
|
||||||
|
@ -104,7 +99,7 @@ class MainWindow(component.Component):
|
||||||
self.is_minimized = False
|
self.is_minimized = False
|
||||||
self.restart = False
|
self.restart = False
|
||||||
|
|
||||||
self.window.drag_dest_set(gtk.DEST_DEFAULT_ALL, [('text/uri-list', 0, 80)], gtk.gdk.ACTION_COPY)
|
self.window.drag_dest_set(gtk.DEST_DEFAULT_ALL, [('text/uri-list', 0, 80)], ACTION_COPY)
|
||||||
|
|
||||||
# Connect events
|
# Connect events
|
||||||
self.window.connect('window-state-event', self.on_window_state_event)
|
self.window.connect('window-state-event', self.on_window_state_event)
|
||||||
|
@ -252,14 +247,14 @@ class MainWindow(component.Component):
|
||||||
self.config['window_height'] = event.height
|
self.config['window_height'] = event.height
|
||||||
|
|
||||||
def on_window_state_event(self, widget, event):
|
def on_window_state_event(self, widget, event):
|
||||||
if event.changed_mask & gtk.gdk.WINDOW_STATE_MAXIMIZED:
|
if event.changed_mask & WINDOW_STATE_MAXIMIZED:
|
||||||
if event.new_window_state & gtk.gdk.WINDOW_STATE_MAXIMIZED:
|
if event.new_window_state & WINDOW_STATE_MAXIMIZED:
|
||||||
log.debug('pos: %s', self.window.get_position())
|
log.debug('pos: %s', self.window.get_position())
|
||||||
self.config['window_maximized'] = True
|
self.config['window_maximized'] = True
|
||||||
elif not event.new_window_state & gtk.gdk.WINDOW_STATE_WITHDRAWN:
|
elif not event.new_window_state & WINDOW_STATE_WITHDRAWN:
|
||||||
self.config['window_maximized'] = False
|
self.config['window_maximized'] = False
|
||||||
if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED:
|
if event.changed_mask & WINDOW_STATE_ICONIFIED:
|
||||||
if event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED:
|
if event.new_window_state & WINDOW_STATE_ICONIFIED:
|
||||||
log.debug('MainWindow is minimized..')
|
log.debug('MainWindow is minimized..')
|
||||||
component.pause('TorrentView')
|
component.pause('TorrentView')
|
||||||
component.pause('StatusBar')
|
component.pause('StatusBar')
|
||||||
|
@ -302,8 +297,8 @@ class MainWindow(component.Component):
|
||||||
def update(self):
|
def update(self):
|
||||||
# Update the window title
|
# Update the window title
|
||||||
def _on_get_session_status(status):
|
def _on_get_session_status(status):
|
||||||
download_rate = deluge.common.fspeed(status['payload_download_rate'], precision=0, shortform=True)
|
download_rate = fspeed(status['payload_download_rate'], precision=0, shortform=True)
|
||||||
upload_rate = deluge.common.fspeed(status['payload_upload_rate'], precision=0, shortform=True)
|
upload_rate = fspeed(status['payload_upload_rate'], precision=0, shortform=True)
|
||||||
self.window.set_title(_('D: %s U: %s - Deluge' % (download_rate, upload_rate)))
|
self.window.set_title(_('D: %s U: %s - Deluge' % (download_rate, upload_rate)))
|
||||||
if self.config['show_rate_in_title']:
|
if self.config['show_rate_in_title']:
|
||||||
client.core.get_session_status(['payload_download_rate',
|
client.core.get_session_status(['payload_download_rate',
|
||||||
|
|
|
@ -7,24 +7,25 @@
|
||||||
# See LICENSE for more details.
|
# See LICENSE for more details.
|
||||||
#
|
#
|
||||||
|
|
||||||
import gtk
|
from gtk import ACCEL_VISIBLE, SeparatorMenuItem, accel_groups_from_object
|
||||||
|
from gtk.gdk import CONTROL_MASK, META_MASK, SHIFT_MASK
|
||||||
|
|
||||||
from deluge.configmanager import ConfigManager
|
from deluge.configmanager import ConfigManager
|
||||||
|
|
||||||
|
|
||||||
def accel_swap(item, group, skey, smod, dkey, dmod):
|
def accel_swap(item, group, skey, smod, dkey, dmod):
|
||||||
item.remove_accelerator(group, ord(skey), smod)
|
item.remove_accelerator(group, ord(skey), smod)
|
||||||
item.add_accelerator('activate', group, ord(dkey), dmod, gtk.ACCEL_VISIBLE)
|
item.add_accelerator('activate', group, ord(dkey), dmod, ACCEL_VISIBLE)
|
||||||
|
|
||||||
|
|
||||||
def accel_meta(item, group, key):
|
def accel_meta(item, group, key):
|
||||||
accel_swap(item, group, key, gtk.gdk.CONTROL_MASK, key, gtk.gdk.META_MASK)
|
accel_swap(item, group, key, CONTROL_MASK, key, META_MASK)
|
||||||
|
|
||||||
|
|
||||||
def menubar_osx(gtkui, osxapp):
|
def menubar_osx(gtkui, osxapp):
|
||||||
main_builder = gtkui.mainwindow.get_builder()
|
main_builder = gtkui.mainwindow.get_builder()
|
||||||
menubar = main_builder.get_object('menubar')
|
menubar = main_builder.get_object('menubar')
|
||||||
group = gtk.accel_groups_from_object(gtkui.mainwindow.get_window())[0]
|
group = accel_groups_from_object(gtkui.mainwindow.get_window())[0]
|
||||||
|
|
||||||
config = ConfigManager('gtkui.conf')
|
config = ConfigManager('gtkui.conf')
|
||||||
|
|
||||||
|
@ -37,8 +38,7 @@ def menubar_osx(gtkui, osxapp):
|
||||||
accel_meta(file_items[0], group, 'o')
|
accel_meta(file_items[0], group, 'o')
|
||||||
accel_meta(file_items[1], group, 'n')
|
accel_meta(file_items[1], group, 'n')
|
||||||
quit_all_item = file_items[3]
|
quit_all_item = file_items[3]
|
||||||
accel_swap(quit_all_item, group, 'q', gtk.gdk.SHIFT_MASK | gtk.gdk.CONTROL_MASK,
|
accel_swap(quit_all_item, group, 'q', SHIFT_MASK | CONTROL_MASK, 'q', SHIFT_MASK | META_MASK)
|
||||||
'q', gtk.gdk.SHIFT_MASK | gtk.gdk.META_MASK)
|
|
||||||
for item in range(2, len(file_items)): # remove quits
|
for item in range(2, len(file_items)): # remove quits
|
||||||
file_menu.remove(file_items[item])
|
file_menu.remove(file_items[item])
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ def menubar_osx(gtkui, osxapp):
|
||||||
edit_menu = menu_widget.get_submenu()
|
edit_menu = menu_widget.get_submenu()
|
||||||
edit_items = edit_menu.get_children()
|
edit_items = edit_menu.get_children()
|
||||||
pref_item = edit_items[0]
|
pref_item = edit_items[0]
|
||||||
accel_swap(pref_item, group, 'p', gtk.gdk.CONTROL_MASK, ',', gtk.gdk.META_MASK)
|
accel_swap(pref_item, group, 'p', CONTROL_MASK, ',', META_MASK)
|
||||||
edit_menu.remove(pref_item)
|
edit_menu.remove(pref_item)
|
||||||
|
|
||||||
conn_item = edit_items[1]
|
conn_item = edit_items[1]
|
||||||
|
@ -65,10 +65,10 @@ def menubar_osx(gtkui, osxapp):
|
||||||
osxapp.set_menu_bar(menubar)
|
osxapp.set_menu_bar(menubar)
|
||||||
# populate app menu
|
# populate app menu
|
||||||
osxapp.insert_app_menu_item(about_item, 0)
|
osxapp.insert_app_menu_item(about_item, 0)
|
||||||
osxapp.insert_app_menu_item(gtk.SeparatorMenuItem(), 1)
|
osxapp.insert_app_menu_item(SeparatorMenuItem(), 1)
|
||||||
osxapp.insert_app_menu_item(pref_item, 2)
|
osxapp.insert_app_menu_item(pref_item, 2)
|
||||||
if not config['standalone']:
|
if not config['standalone']:
|
||||||
osxapp.insert_app_menu_item(conn_item, 3)
|
osxapp.insert_app_menu_item(conn_item, 3)
|
||||||
if quit_all_item.get_visible():
|
if quit_all_item.get_visible():
|
||||||
osxapp.insert_app_menu_item(gtk.SeparatorMenuItem(), 4)
|
osxapp.insert_app_menu_item(SeparatorMenuItem(), 4)
|
||||||
osxapp.insert_app_menu_item(quit_all_item, 5)
|
osxapp.insert_app_menu_item(quit_all_item, 5)
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
# See LICENSE for more details.
|
# See LICENSE for more details.
|
||||||
#
|
#
|
||||||
|
|
||||||
import gtk.gdk
|
from gtk.gdk import keyval_name
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
|
@ -220,7 +220,7 @@ class OptionsTab(Tab):
|
||||||
self.button_apply.set_sensitive(True)
|
self.button_apply.set_sensitive(True)
|
||||||
|
|
||||||
def _on_key_press_event(self, widget, event):
|
def _on_key_press_event(self, widget, event):
|
||||||
keyname = gtk.gdk.keyval_name(event.keyval).lstrip('KP_').lower()
|
keyname = keyval_name(event.keyval).lstrip('KP_').lower()
|
||||||
if keyname.isdigit() or keyname in ['period', 'minus', 'delete', 'backspace']:
|
if keyname.isdigit() or keyname in ['period', 'minus', 'delete', 'backspace']:
|
||||||
if not self.button_apply.is_sensitive():
|
if not self.button_apply.is_sensitive():
|
||||||
self.button_apply.set_sensitive(True)
|
self.button_apply.set_sensitive(True)
|
||||||
|
|
|
@ -14,7 +14,7 @@ import os
|
||||||
|
|
||||||
import gtk
|
import gtk
|
||||||
from gobject import SIGNAL_RUN_FIRST, TYPE_NONE, GObject, type_register
|
from gobject import SIGNAL_RUN_FIRST, TYPE_NONE, GObject, type_register
|
||||||
from gtk import gdk, keysyms
|
from gtk import gdk, keysyms # pylint: disable=ungrouped-imports
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge.common import resource_filename
|
from deluge.common import resource_filename
|
||||||
|
@ -215,8 +215,8 @@ class ValueList(object):
|
||||||
if event.button != 3:
|
if event.button != 3:
|
||||||
# Double clicked a row, set this as the entry value
|
# Double clicked a row, set this as the entry value
|
||||||
# and close the popup
|
# and close the popup
|
||||||
if (double_click and event.type == gtk.gdk._2BUTTON_PRESS) or\
|
if (double_click and event.type == gdk._2BUTTON_PRESS) or\
|
||||||
(not double_click and event.type == gtk.gdk.BUTTON_PRESS):
|
(not double_click and event.type == gdk.BUTTON_PRESS):
|
||||||
path = self.get_selection_path()
|
path = self.get_selection_path()
|
||||||
if path:
|
if path:
|
||||||
self.set_entry_value(path, popdown=True)
|
self.set_entry_value(path, popdown=True)
|
||||||
|
@ -413,7 +413,7 @@ class StoredValuesList(ValueList):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
keyval = event.keyval
|
keyval = event.keyval
|
||||||
ctrl = event.get_state() & gtk.gdk.CONTROL_MASK
|
ctrl = event.get_state() & gdk.CONTROL_MASK
|
||||||
|
|
||||||
# Edit selected row
|
# Edit selected row
|
||||||
if (keyval in [keysyms.Left, keysyms.Right, keysyms.space]):
|
if (keyval in [keysyms.Left, keysyms.Right, keysyms.space]):
|
||||||
|
@ -422,7 +422,7 @@ class StoredValuesList(ValueList):
|
||||||
self.on_edit_path(path, self.tree_column)
|
self.on_edit_path(path, self.tree_column)
|
||||||
elif key_is_up_or_down(keyval):
|
elif key_is_up_or_down(keyval):
|
||||||
# Swap the row value
|
# Swap the row value
|
||||||
if event.get_state() & gtk.gdk.CONTROL_MASK:
|
if event.get_state() & gdk.CONTROL_MASK:
|
||||||
self.handle_list_scroll(_next=key_is_down(keyval),
|
self.handle_list_scroll(_next=key_is_down(keyval),
|
||||||
swap=True)
|
swap=True)
|
||||||
else:
|
else:
|
||||||
|
@ -483,7 +483,7 @@ class CompletionList(ValueList):
|
||||||
if ret:
|
if ret:
|
||||||
return ret
|
return ret
|
||||||
keyval = event.keyval
|
keyval = event.keyval
|
||||||
ctrl = event.get_state() & gtk.gdk.CONTROL_MASK
|
ctrl = event.get_state() & gdk.CONTROL_MASK
|
||||||
if key_is_up_or_down(keyval):
|
if key_is_up_or_down(keyval):
|
||||||
self.handle_list_scroll(_next=key_is_down(keyval))
|
self.handle_list_scroll(_next=key_is_down(keyval))
|
||||||
return True
|
return True
|
||||||
|
@ -774,8 +774,8 @@ class StoredValuesPopup(StoredValuesList, PathChooserPopup):
|
||||||
Handles scroll events from text entry, toggle button and treeview
|
Handles scroll events from text entry, toggle button and treeview
|
||||||
|
|
||||||
"""
|
"""
|
||||||
swap = event.get_state() & gtk.gdk.CONTROL_MASK
|
swap = event.get_state() & gdk.CONTROL_MASK
|
||||||
scroll_window = event.get_state() & gtk.gdk.SHIFT_MASK
|
scroll_window = event.get_state() & gdk.SHIFT_MASK
|
||||||
self.handle_list_scroll(_next=event.direction == gdk.SCROLL_DOWN,
|
self.handle_list_scroll(_next=event.direction == gdk.SCROLL_DOWN,
|
||||||
set_entry=widget != self.treeview, swap=swap, scroll_window=scroll_window)
|
set_entry=widget != self.treeview, swap=swap, scroll_window=scroll_window)
|
||||||
return True
|
return True
|
||||||
|
@ -1294,7 +1294,7 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
|
||||||
"""
|
"""
|
||||||
keyval = event.keyval
|
keyval = event.keyval
|
||||||
state = event.get_state() & gtk.accelerator_get_default_mod_mask()
|
state = event.get_state() & gtk.accelerator_get_default_mod_mask()
|
||||||
ctrl = event.get_state() & gtk.gdk.CONTROL_MASK
|
ctrl = event.get_state() & gdk.CONTROL_MASK
|
||||||
|
|
||||||
# Select new row with arrow up/down is pressed
|
# Select new row with arrow up/down is pressed
|
||||||
if key_is_up_or_down(keyval):
|
if key_is_up_or_down(keyval):
|
||||||
|
@ -1458,7 +1458,7 @@ class PathChooserComboBox(gtk.HBox, StoredValuesPopup, GObject):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
keyval = event.keyval
|
keyval = event.keyval
|
||||||
ctrl = event.get_state() & gtk.gdk.CONTROL_MASK
|
ctrl = event.get_state() & gdk.CONTROL_MASK
|
||||||
if ctrl:
|
if ctrl:
|
||||||
# Set show/hide hidden files
|
# Set show/hide hidden files
|
||||||
if is_ascii_value(keyval, 'h'):
|
if is_ascii_value(keyval, 'h'):
|
||||||
|
|
|
@ -11,25 +11,21 @@ import logging
|
||||||
import os.path
|
import os.path
|
||||||
from future_builtins import zip
|
from future_builtins import zip
|
||||||
|
|
||||||
import gtk
|
from gtk import (TREE_VIEW_COLUMN_FIXED, Builder, CellRendererPixbuf, CellRendererProgress, CellRendererText, ListStore,
|
||||||
|
TreeViewColumn)
|
||||||
|
from gtk.gdk import Pixbuf, pixbuf_new_from_file
|
||||||
|
|
||||||
import deluge.common
|
import deluge.common
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
from deluge.ui.countries import COUNTRIES
|
from deluge.ui.countries import COUNTRIES
|
||||||
from deluge.ui.gtkui.common import load_pickled_state_file, save_pickled_state_file
|
from deluge.ui.gtkui.common import icon_downloading, icon_seeding, load_pickled_state_file, save_pickled_state_file
|
||||||
from deluge.ui.gtkui.torrentdetails import Tab
|
from deluge.ui.gtkui.torrentdetails import Tab
|
||||||
from deluge.ui.gtkui.torrentview_data_funcs import cell_data_speed_down, cell_data_speed_up
|
from deluge.ui.gtkui.torrentview_data_funcs import cell_data_peer_progress, cell_data_speed_down, cell_data_speed_up
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def cell_data_progress(column, cell, model, row, data):
|
|
||||||
value = model.get_value(row, data) * 100
|
|
||||||
cell.set_property('value', value)
|
|
||||||
cell.set_property('text', '%i%%' % value)
|
|
||||||
|
|
||||||
|
|
||||||
class PeersTab(Tab):
|
class PeersTab(Tab):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Tab.__init__(self)
|
Tab.__init__(self)
|
||||||
|
@ -48,18 +44,18 @@ class PeersTab(Tab):
|
||||||
self.listview.connect('button-press-event', self._on_button_press_event)
|
self.listview.connect('button-press-event', self._on_button_press_event)
|
||||||
self.listview.connect('query-tooltip', self._on_query_tooltip)
|
self.listview.connect('query-tooltip', self._on_query_tooltip)
|
||||||
# country pixbuf, ip, client, downspeed, upspeed, country code, int_ip, seed/peer icon, progress
|
# country pixbuf, ip, client, downspeed, upspeed, country code, int_ip, seed/peer icon, progress
|
||||||
self.liststore = gtk.ListStore(gtk.gdk.Pixbuf, str, str, int, int, str, float, gtk.gdk.Pixbuf, float)
|
self.liststore = ListStore(Pixbuf, str, str, int, int, str, float, Pixbuf, float)
|
||||||
self.cached_flag_pixbufs = {}
|
self.cached_flag_pixbufs = {}
|
||||||
|
|
||||||
self.seed_pixbuf = gtk.gdk.pixbuf_new_from_file(deluge.common.get_pixmap('seeding16.png'))
|
self.seed_pixbuf = icon_seeding
|
||||||
self.peer_pixbuf = gtk.gdk.pixbuf_new_from_file(deluge.common.get_pixmap('downloading16.png'))
|
self.peer_pixbuf = icon_downloading
|
||||||
|
|
||||||
# key is ip address, item is row iter
|
# key is ip address, item is row iter
|
||||||
self.peers = {}
|
self.peers = {}
|
||||||
|
|
||||||
# Country column
|
# Country column
|
||||||
column = gtk.TreeViewColumn()
|
column = TreeViewColumn()
|
||||||
render = gtk.CellRendererPixbuf()
|
render = CellRendererPixbuf()
|
||||||
column.pack_start(render, False)
|
column.pack_start(render, False)
|
||||||
column.add_attribute(render, 'pixbuf', 0)
|
column.add_attribute(render, 'pixbuf', 0)
|
||||||
column.set_sort_column_id(5)
|
column.set_sort_column_id(5)
|
||||||
|
@ -71,11 +67,11 @@ class PeersTab(Tab):
|
||||||
self.listview.append_column(column)
|
self.listview.append_column(column)
|
||||||
|
|
||||||
# Address column
|
# Address column
|
||||||
column = gtk.TreeViewColumn(_('Address'))
|
column = TreeViewColumn(_('Address'))
|
||||||
render = gtk.CellRendererPixbuf()
|
render = CellRendererPixbuf()
|
||||||
column.pack_start(render, False)
|
column.pack_start(render, False)
|
||||||
column.add_attribute(render, 'pixbuf', 7)
|
column.add_attribute(render, 'pixbuf', 7)
|
||||||
render = gtk.CellRendererText()
|
render = CellRendererText()
|
||||||
column.pack_start(render, False)
|
column.pack_start(render, False)
|
||||||
column.add_attribute(render, 'text', 1)
|
column.add_attribute(render, 'text', 1)
|
||||||
column.set_sort_column_id(6)
|
column.set_sort_column_id(6)
|
||||||
|
@ -87,8 +83,8 @@ class PeersTab(Tab):
|
||||||
self.listview.append_column(column)
|
self.listview.append_column(column)
|
||||||
|
|
||||||
# Client column
|
# Client column
|
||||||
column = gtk.TreeViewColumn(_('Client'))
|
column = TreeViewColumn(_('Client'))
|
||||||
render = gtk.CellRendererText()
|
render = CellRendererText()
|
||||||
column.pack_start(render, False)
|
column.pack_start(render, False)
|
||||||
column.add_attribute(render, 'text', 2)
|
column.add_attribute(render, 'text', 2)
|
||||||
column.set_sort_column_id(2)
|
column.set_sort_column_id(2)
|
||||||
|
@ -100,10 +96,10 @@ class PeersTab(Tab):
|
||||||
self.listview.append_column(column)
|
self.listview.append_column(column)
|
||||||
|
|
||||||
# Progress column
|
# Progress column
|
||||||
column = gtk.TreeViewColumn(_('Progress'))
|
column = TreeViewColumn(_('Progress'))
|
||||||
render = gtk.CellRendererProgress()
|
render = CellRendererProgress()
|
||||||
column.pack_start(render, True)
|
column.pack_start(render, True)
|
||||||
column.set_cell_data_func(render, cell_data_progress, 8)
|
column.set_cell_data_func(render, cell_data_peer_progress, 8)
|
||||||
column.set_sort_column_id(8)
|
column.set_sort_column_id(8)
|
||||||
column.set_clickable(True)
|
column.set_clickable(True)
|
||||||
column.set_resizable(True)
|
column.set_resizable(True)
|
||||||
|
@ -113,8 +109,8 @@ class PeersTab(Tab):
|
||||||
self.listview.append_column(column)
|
self.listview.append_column(column)
|
||||||
|
|
||||||
# Down Speed column
|
# Down Speed column
|
||||||
column = gtk.TreeViewColumn(_('Down Speed'))
|
column = TreeViewColumn(_('Down Speed'))
|
||||||
render = gtk.CellRendererText()
|
render = CellRendererText()
|
||||||
column.pack_start(render, False)
|
column.pack_start(render, False)
|
||||||
column.set_cell_data_func(render, cell_data_speed_down, 3)
|
column.set_cell_data_func(render, cell_data_speed_down, 3)
|
||||||
column.set_sort_column_id(3)
|
column.set_sort_column_id(3)
|
||||||
|
@ -126,8 +122,8 @@ class PeersTab(Tab):
|
||||||
self.listview.append_column(column)
|
self.listview.append_column(column)
|
||||||
|
|
||||||
# Up Speed column
|
# Up Speed column
|
||||||
column = gtk.TreeViewColumn(_('Up Speed'))
|
column = TreeViewColumn(_('Up Speed'))
|
||||||
render = gtk.CellRendererText()
|
render = CellRendererText()
|
||||||
column.pack_start(render, False)
|
column.pack_start(render, False)
|
||||||
column.set_cell_data_func(render, cell_data_speed_up, 4)
|
column.set_cell_data_func(render, cell_data_speed_up, 4)
|
||||||
column.set_sort_column_id(4)
|
column.set_sort_column_id(4)
|
||||||
|
@ -181,7 +177,7 @@ class PeersTab(Tab):
|
||||||
cname = column.get_title()
|
cname = column.get_title()
|
||||||
if cname in state['columns']:
|
if cname in state['columns']:
|
||||||
cstate = state['columns'][cname]
|
cstate = state['columns'][cname]
|
||||||
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
column.set_sizing(TREE_VIEW_COLUMN_FIXED)
|
||||||
column.set_fixed_width(cstate['width'] if cstate['width'] > 0 else 10)
|
column.set_fixed_width(cstate['width'] if cstate['width'] > 0 else 10)
|
||||||
if state['sort_id'] == index and state['sort_order'] is not None:
|
if state['sort_id'] == index and state['sort_order'] is not None:
|
||||||
column.set_sort_indicator(True)
|
column.set_sort_indicator(True)
|
||||||
|
@ -220,7 +216,7 @@ class PeersTab(Tab):
|
||||||
if country not in self.cached_flag_pixbufs:
|
if country not in self.cached_flag_pixbufs:
|
||||||
# We haven't created a pixbuf for this country yet
|
# We haven't created a pixbuf for this country yet
|
||||||
try:
|
try:
|
||||||
self.cached_flag_pixbufs[country] = gtk.gdk.pixbuf_new_from_file(
|
self.cached_flag_pixbufs[country] = pixbuf_new_from_file(
|
||||||
deluge.common.resource_filename(
|
deluge.common.resource_filename(
|
||||||
'deluge',
|
'deluge',
|
||||||
os.path.join('ui', 'data', 'pixmaps', 'flags', country.lower() + '.png')))
|
os.path.join('ui', 'data', 'pixmaps', 'flags', country.lower() + '.png')))
|
||||||
|
@ -330,7 +326,7 @@ class PeersTab(Tab):
|
||||||
def _on_menuitem_add_peer_activate(self, menuitem):
|
def _on_menuitem_add_peer_activate(self, menuitem):
|
||||||
"""This is a callback for manually adding a peer"""
|
"""This is a callback for manually adding a peer"""
|
||||||
log.debug('on_menuitem_add_peer')
|
log.debug('on_menuitem_add_peer')
|
||||||
builder = gtk.Builder()
|
builder = Builder()
|
||||||
builder.add_from_file(deluge.common.resource_filename(
|
builder.add_from_file(deluge.common.resource_filename(
|
||||||
'deluge.ui.gtkui', os.path.join('glade', 'connect_peer_dialog.ui')
|
'deluge.ui.gtkui', os.path.join('glade', 'connect_peer_dialog.ui')
|
||||||
))
|
))
|
||||||
|
|
|
@ -11,27 +11,28 @@ from __future__ import division
|
||||||
|
|
||||||
from math import pi
|
from math import pi
|
||||||
|
|
||||||
import gtk
|
|
||||||
import pango
|
|
||||||
import pangocairo
|
|
||||||
from cairo import FORMAT_ARGB32, Context, ImageSurface
|
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
|
||||||
|
|
||||||
from deluge.configmanager import ConfigManager
|
from deluge.configmanager import ConfigManager
|
||||||
|
|
||||||
COLOR_STATES = ['missing', 'waiting', 'downloading', 'completed']
|
COLOR_STATES = ['missing', 'waiting', 'downloading', 'completed']
|
||||||
|
|
||||||
|
|
||||||
class PiecesBar(gtk.DrawingArea):
|
class PiecesBar(DrawingArea):
|
||||||
# Draw in response to an expose-event
|
# Draw in response to an expose-event
|
||||||
__gsignals__ = {'expose-event': 'override'}
|
__gsignals__ = {'expose-event': 'override'}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
gtk.DrawingArea.__init__(self)
|
DrawingArea.__init__(self)
|
||||||
# Get progress bar styles, in order to keep font consistency
|
# Get progress bar styles, in order to keep font consistency
|
||||||
pb = gtk.ProgressBar()
|
pb = ProgressBar()
|
||||||
pb_style = pb.get_style()
|
pb_style = pb.get_style()
|
||||||
self.text_font = pb_style.font_desc
|
self.text_font = pb_style.font_desc
|
||||||
self.text_font.set_weight(pango.WEIGHT_BOLD)
|
self.text_font.set_weight(WEIGHT_BOLD)
|
||||||
# Done with the ProgressBar styles, don't keep refs of it
|
# Done with the ProgressBar styles, don't keep refs of it
|
||||||
del pb, pb_style
|
del pb, pb_style
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ class PiecesBar(gtk.DrawingArea):
|
||||||
self.cr = None
|
self.cr = None
|
||||||
|
|
||||||
self.connect('size-allocate', self.do_size_allocate_event)
|
self.connect('size-allocate', self.do_size_allocate_event)
|
||||||
self.set_colormap(gtk.gdk.colormap_get_system())
|
self.set_colormap(colormap_get_system())
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
def do_size_allocate_event(self, widget, size):
|
def do_size_allocate_event(self, widget, size):
|
||||||
|
@ -151,14 +152,14 @@ class PiecesBar(gtk.DrawingArea):
|
||||||
# Need to recreate the cache drawing
|
# Need to recreate the cache drawing
|
||||||
self.text_overlay = ImageSurface(FORMAT_ARGB32, self.width, self.height)
|
self.text_overlay = ImageSurface(FORMAT_ARGB32, self.width, self.height)
|
||||||
ctx = Context(self.text_overlay)
|
ctx = Context(self.text_overlay)
|
||||||
pg = pangocairo.CairoContext(ctx)
|
pg = CairoContext(ctx)
|
||||||
pl = pg.create_layout()
|
pl = pg.create_layout()
|
||||||
pl.set_font_description(self.text_font)
|
pl.set_font_description(self.text_font)
|
||||||
pl.set_width(-1) # No text wrapping
|
pl.set_width(-1) # No text wrapping
|
||||||
pl.set_text(self.text)
|
pl.set_text(self.text)
|
||||||
plsize = pl.get_size()
|
plsize = pl.get_size()
|
||||||
text_width = plsize[0] // pango.SCALE
|
text_width = plsize[0] // SCALE
|
||||||
text_height = plsize[1] // pango.SCALE
|
text_height = plsize[1] // SCALE
|
||||||
area_width_without_text = self.width - text_width
|
area_width_without_text = self.width - text_width
|
||||||
area_height_without_text = self.height - text_height
|
area_height_without_text = self.height - text_height
|
||||||
ctx.move_to(area_width_without_text // 2, area_height_without_text // 2)
|
ctx.move_to(area_width_without_text // 2, area_height_without_text // 2)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import os
|
||||||
from hashlib import sha1 as sha
|
from hashlib import sha1 as sha
|
||||||
|
|
||||||
import gtk
|
import gtk
|
||||||
|
from gtk.gdk import Color
|
||||||
|
|
||||||
import deluge.common
|
import deluge.common
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
|
@ -1163,7 +1164,7 @@ class Preferences(component.Component):
|
||||||
|
|
||||||
def __set_color(self, state, from_config=False):
|
def __set_color(self, state, from_config=False):
|
||||||
if from_config:
|
if from_config:
|
||||||
color = gtk.gdk.Color(*self.gtkui_config['pieces_color_%s' % state])
|
color = Color(*self.gtkui_config['pieces_color_%s' % state])
|
||||||
log.debug('Setting %r color state from config to %s', state, (color.red, color.green, color.blue))
|
log.debug('Setting %r color state from config to %s', state, (color.red, color.green, color.blue))
|
||||||
self.builder.get_object('%s_color' % state).set_color(color)
|
self.builder.get_object('%s_color' % state).set_color(color)
|
||||||
else:
|
else:
|
||||||
|
@ -1178,6 +1179,6 @@ class Preferences(component.Component):
|
||||||
|
|
||||||
def __revert_color(self, state, from_config=False):
|
def __revert_color(self, state, from_config=False):
|
||||||
log.debug('Reverting %r color state', state)
|
log.debug('Reverting %r color state', state)
|
||||||
self.builder.get_object('%s_color' % state).set_color(gtk.gdk.Color(*self.COLOR_DEFAULTS[state]))
|
self.builder.get_object('%s_color' % state).set_color(Color(*self.COLOR_DEFAULTS[state]))
|
||||||
self.builder.get_object('revert_color_%s' % state).set_sensitive(False)
|
self.builder.get_object('revert_color_%s' % state).set_sensitive(False)
|
||||||
self.gtkui_config.apply_set_functions('pieces_colors')
|
self.gtkui_config.apply_set_functions('pieces_colors')
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
import logging
|
import logging
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
import gtk
|
|
||||||
from gobject import timeout_add
|
from gobject import timeout_add
|
||||||
|
from gtk import STOCK_SORT_DESCENDING, Builder, CellRendererText, ListStore, TreeViewColumn
|
||||||
|
|
||||||
import deluge.common
|
import deluge.common
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
|
@ -29,7 +29,7 @@ class QueuedTorrents(component.Component):
|
||||||
self.status_item = None
|
self.status_item = None
|
||||||
|
|
||||||
self.config = ConfigManager('gtkui.conf')
|
self.config = ConfigManager('gtkui.conf')
|
||||||
self.builder = gtk.Builder()
|
self.builder = Builder()
|
||||||
self.builder.add_from_file(deluge.common.resource_filename(
|
self.builder.add_from_file(deluge.common.resource_filename(
|
||||||
'deluge.ui.gtkui', os.path.join('glade', 'queuedtorrents.ui')))
|
'deluge.ui.gtkui', os.path.join('glade', 'queuedtorrents.ui')))
|
||||||
self.builder.get_object('chk_autoadd').set_active(self.config['autoadd_queued'])
|
self.builder.get_object('chk_autoadd').set_active(self.config['autoadd_queued'])
|
||||||
|
@ -45,10 +45,9 @@ class QueuedTorrents(component.Component):
|
||||||
})
|
})
|
||||||
|
|
||||||
self.treeview = self.builder.get_object('treeview')
|
self.treeview = self.builder.get_object('treeview')
|
||||||
self.treeview.append_column(
|
self.treeview.append_column(TreeViewColumn(_('Torrent'), CellRendererText(), text=0))
|
||||||
gtk.TreeViewColumn(_('Torrent'), gtk.CellRendererText(), text=0))
|
|
||||||
|
|
||||||
self.liststore = gtk.ListStore(str, str)
|
self.liststore = ListStore(str, str)
|
||||||
self.treeview.set_model(self.liststore)
|
self.treeview.set_model(self.liststore)
|
||||||
self.treeview.set_tooltip_column(1)
|
self.treeview.set_tooltip_column(1)
|
||||||
|
|
||||||
|
@ -120,7 +119,7 @@ class QueuedTorrents(component.Component):
|
||||||
# have already been added.
|
# have already been added.
|
||||||
if self.status_item is None:
|
if self.status_item is None:
|
||||||
self.status_item = component.get('StatusBar').add_item(
|
self.status_item = component.get('StatusBar').add_item(
|
||||||
stock=gtk.STOCK_SORT_DESCENDING,
|
stock=STOCK_SORT_DESCENDING,
|
||||||
text=label,
|
text=label,
|
||||||
callback=self.on_statusbar_click)
|
callback=self.on_statusbar_click)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import gtk
|
from gtk import POLICY_AUTOMATIC, Label, ScrolledWindow
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge.configmanager import ConfigManager
|
from deluge.configmanager import ConfigManager
|
||||||
|
@ -58,10 +58,10 @@ class SideBar(component.Component):
|
||||||
"""Adds a tab object to the notebook."""
|
"""Adds a tab object to the notebook."""
|
||||||
log.debug('add tab: %s', tab_name)
|
log.debug('add tab: %s', tab_name)
|
||||||
self.tabs[tab_name] = widget
|
self.tabs[tab_name] = widget
|
||||||
scrolled = gtk.ScrolledWindow()
|
scrolled = ScrolledWindow()
|
||||||
scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
scrolled.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
|
||||||
scrolled.add(widget)
|
scrolled.add(widget)
|
||||||
self.notebook.insert_page(scrolled, gtk.Label(label), -1)
|
self.notebook.insert_page(scrolled, Label(label), -1)
|
||||||
scrolled.show_all()
|
scrolled.show_all()
|
||||||
|
|
||||||
self.after_update()
|
self.after_update()
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import gtk
|
from gtk import (Builder, RadioMenuItem, status_icon_new_from_icon_name, status_icon_new_from_pixbuf,
|
||||||
|
status_icon_position_menu)
|
||||||
|
|
||||||
import deluge.common
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge.common import fspeed
|
from deluge.common import fspeed, get_pixmap, osx_check, resource_filename, windows_check
|
||||||
from deluge.configmanager import ConfigManager
|
from deluge.configmanager import ConfigManager
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
from deluge.ui.gtkui import dialogs
|
from deluge.ui.gtkui import dialogs
|
||||||
|
@ -63,9 +63,9 @@ class SystemTray(component.Component):
|
||||||
|
|
||||||
def enable(self):
|
def enable(self):
|
||||||
"""Enables the system tray icon."""
|
"""Enables the system tray icon."""
|
||||||
self.builder = gtk.Builder()
|
self.builder = Builder()
|
||||||
self.builder.add_from_file(deluge.common.resource_filename(
|
self.builder.add_from_file(resource_filename('deluge.ui.gtkui', os.path.join(
|
||||||
'deluge.ui.gtkui', os.path.join('glade', 'tray_menu.ui')))
|
'glade', 'tray_menu.ui')))
|
||||||
|
|
||||||
self.builder.connect_signals({
|
self.builder.connect_signals({
|
||||||
'on_menuitem_show_deluge_activate': self.on_menuitem_show_deluge_activate,
|
'on_menuitem_show_deluge_activate': self.on_menuitem_show_deluge_activate,
|
||||||
|
@ -103,18 +103,16 @@ class SystemTray(component.Component):
|
||||||
|
|
||||||
else:
|
else:
|
||||||
log.debug('Enabling the system tray icon..')
|
log.debug('Enabling the system tray icon..')
|
||||||
if deluge.common.windows_check() or deluge.common.osx_check():
|
if windows_check():
|
||||||
self.tray = gtk.status_icon_new_from_pixbuf(get_logo(32))
|
self.tray = status_icon_new_from_pixbuf(get_logo(32))
|
||||||
else:
|
else:
|
||||||
self.tray = gtk.status_icon_new_from_icon_name('deluge')
|
self.tray = status_icon_new_from_icon_name('deluge')
|
||||||
|
|
||||||
self.tray.connect('activate', self.on_tray_clicked)
|
self.tray.connect('activate', self.on_tray_clicked)
|
||||||
self.tray.connect('popup-menu', self.on_tray_popup)
|
self.tray.connect('popup-menu', self.on_tray_popup)
|
||||||
|
|
||||||
self.builder.get_object('download-limit-image').set_from_file(
|
self.builder.get_object('download-limit-image').set_from_file(get_pixmap('downloading16.png'))
|
||||||
deluge.common.get_pixmap('downloading16.png'))
|
self.builder.get_object('upload-limit-image').set_from_file(get_pixmap('seeding16.png'))
|
||||||
self.builder.get_object('upload-limit-image').set_from_file(
|
|
||||||
deluge.common.get_pixmap('seeding16.png'))
|
|
||||||
|
|
||||||
client.register_event_handler('ConfigValueChangedEvent', self.config_value_changed)
|
client.register_event_handler('ConfigValueChangedEvent', self.config_value_changed)
|
||||||
if client.connected():
|
if client.connected():
|
||||||
|
@ -319,8 +317,8 @@ class SystemTray(component.Component):
|
||||||
else:
|
else:
|
||||||
self.builder.get_object('menuitem_show_deluge').set_active(False)
|
self.builder.get_object('menuitem_show_deluge').set_active(False)
|
||||||
|
|
||||||
popup_function = gtk.status_icon_position_menu
|
popup_function = status_icon_position_menu
|
||||||
if deluge.common.windows_check() or deluge.common.osx_check():
|
if windows_check() or osx_check():
|
||||||
popup_function = None
|
popup_function = None
|
||||||
button = 0
|
button = 0
|
||||||
self.tray_menu.popup(None, None, popup_function, button, activate_time, status_icon)
|
self.tray_menu.popup(None, None, popup_function, button, activate_time, status_icon)
|
||||||
|
@ -353,7 +351,7 @@ class SystemTray(component.Component):
|
||||||
self.mainwindow.quit(shutdown=True)
|
self.mainwindow.quit(shutdown=True)
|
||||||
|
|
||||||
def on_tray_setbwdown(self, widget, data=None):
|
def on_tray_setbwdown(self, widget, data=None):
|
||||||
if isinstance(widget, gtk.RadioMenuItem):
|
if isinstance(widget, RadioMenuItem):
|
||||||
# ignore previous radiomenuitem value
|
# ignore previous radiomenuitem value
|
||||||
if not widget.get_active():
|
if not widget.get_active():
|
||||||
return
|
return
|
||||||
|
@ -362,7 +360,7 @@ class SystemTray(component.Component):
|
||||||
'downloading.svg')
|
'downloading.svg')
|
||||||
|
|
||||||
def on_tray_setbwup(self, widget, data=None):
|
def on_tray_setbwup(self, widget, data=None):
|
||||||
if isinstance(widget, gtk.RadioMenuItem):
|
if isinstance(widget, RadioMenuItem):
|
||||||
# ignore previous radiomenuitem value
|
# ignore previous radiomenuitem value
|
||||||
if not widget.get_active():
|
if not widget.get_active():
|
||||||
return
|
return
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import gtk
|
from gtk import SeparatorToolItem, ToolButton
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge.configmanager import ConfigManager
|
from deluge.configmanager import ConfigManager
|
||||||
|
@ -71,7 +71,7 @@ class ToolBar(component.Component):
|
||||||
|
|
||||||
def add_toolbutton(self, callback, label=None, image=None, stock=None, tooltip=None):
|
def add_toolbutton(self, callback, label=None, image=None, stock=None, tooltip=None):
|
||||||
"""Adds a toolbutton to the toolbar"""
|
"""Adds a toolbutton to the toolbar"""
|
||||||
toolbutton = gtk.ToolButton()
|
toolbutton = ToolButton()
|
||||||
if stock is not None:
|
if stock is not None:
|
||||||
toolbutton.set_stock_id(stock)
|
toolbutton.set_stock_id(stock)
|
||||||
if label is not None:
|
if label is not None:
|
||||||
|
@ -89,7 +89,7 @@ class ToolBar(component.Component):
|
||||||
|
|
||||||
def add_separator(self, position=None):
|
def add_separator(self, position=None):
|
||||||
"""Adds a separator toolitem"""
|
"""Adds a separator toolitem"""
|
||||||
sep = gtk.SeparatorToolItem()
|
sep = SeparatorToolItem()
|
||||||
if position is not None:
|
if position is not None:
|
||||||
self.toolbar.insert(sep, position)
|
self.toolbar.insert(sep, position)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import gtk
|
from gtk import CheckMenuItem, Menu, SeparatorMenuItem
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
|
@ -266,9 +266,9 @@ class TorrentDetails(component.Component):
|
||||||
|
|
||||||
def generate_menu(self):
|
def generate_menu(self):
|
||||||
"""Generates the checklist menu for all the tabs and attaches it"""
|
"""Generates the checklist menu for all the tabs and attaches it"""
|
||||||
menu = gtk.Menu()
|
menu = Menu()
|
||||||
# Create 'All' menuitem and a separator
|
# Create 'All' menuitem and a separator
|
||||||
menuitem = gtk.CheckMenuItem(self.translate_tabs['All'], True)
|
menuitem = CheckMenuItem(self.translate_tabs['All'], True)
|
||||||
menuitem.set_name('All')
|
menuitem.set_name('All')
|
||||||
|
|
||||||
all_tabs = True
|
all_tabs = True
|
||||||
|
@ -281,7 +281,7 @@ class TorrentDetails(component.Component):
|
||||||
|
|
||||||
menu.append(menuitem)
|
menu.append(menuitem)
|
||||||
|
|
||||||
menuitem = gtk.SeparatorMenuItem()
|
menuitem = SeparatorMenuItem()
|
||||||
menu.append(menuitem)
|
menu.append(menuitem)
|
||||||
|
|
||||||
# Create a list in order of tabs to create menu
|
# Create a list in order of tabs to create menu
|
||||||
|
@ -291,7 +291,7 @@ class TorrentDetails(component.Component):
|
||||||
menuitem_list.sort()
|
menuitem_list.sort()
|
||||||
|
|
||||||
for pos, name in menuitem_list:
|
for pos, name in menuitem_list:
|
||||||
menuitem = gtk.CheckMenuItem(self.translate_tabs[name], True)
|
menuitem = CheckMenuItem(self.translate_tabs[name], True)
|
||||||
menuitem.set_name(name)
|
menuitem.set_name(name)
|
||||||
menuitem.set_active(self.tabs[name].is_visible)
|
menuitem.set_active(self.tabs[name].is_visible)
|
||||||
menuitem.connect('toggled', self._on_menuitem_toggled)
|
menuitem.connect('toggled', self._on_menuitem_toggled)
|
||||||
|
|
|
@ -12,8 +12,9 @@
|
||||||
import logging
|
import logging
|
||||||
from locale import strcoll
|
from locale import strcoll
|
||||||
|
|
||||||
import gtk
|
|
||||||
from gobject import TYPE_UINT64, idle_add
|
from gobject import TYPE_UINT64, idle_add
|
||||||
|
from gtk import ENTRY_ICON_SECONDARY
|
||||||
|
from gtk.gdk import SHIFT_MASK, keyval_name
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
|
@ -210,7 +211,7 @@ class SearchBox(object):
|
||||||
self.search_pending = reactor.callLater(0.7, self.torrentview.update)
|
self.search_pending = reactor.callLater(0.7, self.torrentview.update)
|
||||||
|
|
||||||
def on_search_torrents_entry_icon_press(self, entry, icon, event):
|
def on_search_torrents_entry_icon_press(self, entry, icon, event):
|
||||||
if icon != gtk.ENTRY_ICON_SECONDARY:
|
if icon != ENTRY_ICON_SECONDARY:
|
||||||
return
|
return
|
||||||
self.clear_search()
|
self.clear_search()
|
||||||
|
|
||||||
|
@ -705,7 +706,7 @@ class TorrentView(ListView, component.Component):
|
||||||
|
|
||||||
# Handle keyboard shortcuts
|
# Handle keyboard shortcuts
|
||||||
def on_key_press_event(self, widget, event):
|
def on_key_press_event(self, widget, event):
|
||||||
keyname = gtk.gdk.keyval_name(event.keyval)
|
keyname = keyval_name(event.keyval)
|
||||||
if keyname is not None:
|
if keyname is not None:
|
||||||
func = getattr(self, 'keypress_' + keyname.lower(), None)
|
func = getattr(self, 'keypress_' + keyname.lower(), None)
|
||||||
if func:
|
if func:
|
||||||
|
@ -715,7 +716,7 @@ class TorrentView(ListView, component.Component):
|
||||||
log.debug('keypress_delete')
|
log.debug('keypress_delete')
|
||||||
torrents = self.get_selected_torrents()
|
torrents = self.get_selected_torrents()
|
||||||
if torrents:
|
if torrents:
|
||||||
if event.state & gtk.gdk.SHIFT_MASK:
|
if event.get_state() & SHIFT_MASK:
|
||||||
RemoveTorrentDialog(torrents, delete_files=True).run()
|
RemoveTorrentDialog(torrents, delete_files=True).run()
|
||||||
else:
|
else:
|
||||||
RemoveTorrentDialog(torrents).run()
|
RemoveTorrentDialog(torrents).run()
|
||||||
|
|
|
@ -12,20 +12,10 @@ from __future__ import print_function
|
||||||
import warnings
|
import warnings
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
import gtk
|
|
||||||
from gobject import GError
|
|
||||||
|
|
||||||
import deluge.common as common
|
import deluge.common as common
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
|
from deluge.ui.gtkui.common import (create_blank_pixbuf, get_pixbuf_at_size, icon_alert, icon_checking,
|
||||||
# Status icons.. Create them from file only once to avoid constantly
|
icon_downloading, icon_inactive, icon_queued, icon_seeding)
|
||||||
# re-creating them.
|
|
||||||
icon_downloading = gtk.gdk.pixbuf_new_from_file(common.get_pixmap('downloading16.png'))
|
|
||||||
icon_seeding = gtk.gdk.pixbuf_new_from_file(common.get_pixmap('seeding16.png'))
|
|
||||||
icon_inactive = gtk.gdk.pixbuf_new_from_file(common.get_pixmap('inactive16.png'))
|
|
||||||
icon_alert = gtk.gdk.pixbuf_new_from_file(common.get_pixmap('alert16.png'))
|
|
||||||
icon_queued = gtk.gdk.pixbuf_new_from_file(common.get_pixmap('queued16.png'))
|
|
||||||
icon_checking = gtk.gdk.pixbuf_new_from_file(common.get_pixmap('checking16.png'))
|
|
||||||
|
|
||||||
# Holds the info for which status icon to display based on TORRENT_STATE
|
# Holds the info for which status icon to display based on TORRENT_STATE
|
||||||
ICON_STATE = {
|
ICON_STATE = {
|
||||||
|
@ -58,6 +48,7 @@ func_last_value = {
|
||||||
'cell_data_statusicon': None,
|
'cell_data_statusicon': None,
|
||||||
'cell_data_queue': None,
|
'cell_data_queue': None,
|
||||||
'cell_data_progress': [None, None],
|
'cell_data_progress': [None, None],
|
||||||
|
'cell_data_peer_progress': None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,23 +75,12 @@ def cell_data_statusicon(column, cell, model, row, data):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def create_blank_pixbuf():
|
def set_tracker_icon(tracker_icon, cell):
|
||||||
i = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, 16, 16)
|
if tracker_icon:
|
||||||
i.fill(0x00000000)
|
pixbuf = tracker_icon.get_cached_icon()
|
||||||
return i
|
|
||||||
|
|
||||||
|
|
||||||
def set_icon(icon, cell):
|
|
||||||
if icon:
|
|
||||||
pixbuf = icon.get_cached_icon()
|
|
||||||
if pixbuf is None:
|
if pixbuf is None:
|
||||||
try:
|
pixbuf = get_pixbuf_at_size(tracker_icon.get_filename(), 16)
|
||||||
pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(icon.get_filename(), 16, 16)
|
tracker_icon.set_cached_icon(pixbuf)
|
||||||
except GError:
|
|
||||||
# Failed to load the pixbuf (Bad image file), so set a blank pixbuf
|
|
||||||
pixbuf = create_blank_pixbuf()
|
|
||||||
finally:
|
|
||||||
icon.set_cached_icon(pixbuf)
|
|
||||||
else:
|
else:
|
||||||
pixbuf = create_blank_pixbuf()
|
pixbuf = create_blank_pixbuf()
|
||||||
|
|
||||||
|
@ -118,15 +98,15 @@ def cell_data_trackericon(column, cell, model, row, data):
|
||||||
if host:
|
if host:
|
||||||
if not component.get('TrackerIcons').has(host):
|
if not component.get('TrackerIcons').has(host):
|
||||||
# Set blank icon while waiting for the icon to be loaded
|
# Set blank icon while waiting for the icon to be loaded
|
||||||
set_icon(None, cell)
|
set_tracker_icon(None, cell)
|
||||||
component.get('TrackerIcons').fetch(host)
|
component.get('TrackerIcons').fetch(host)
|
||||||
func_last_value['cell_data_trackericon'] = None
|
func_last_value['cell_data_trackericon'] = None
|
||||||
else:
|
else:
|
||||||
set_icon(component.get('TrackerIcons').get(host), cell)
|
set_tracker_icon(component.get('TrackerIcons').get(host), cell)
|
||||||
# Only set the last value when we have found the icon
|
# Only set the last value when we have found the icon
|
||||||
func_last_value['cell_data_trackericon'] = host
|
func_last_value['cell_data_trackericon'] = host
|
||||||
else:
|
else:
|
||||||
set_icon(None, cell)
|
set_tracker_icon(None, cell)
|
||||||
func_last_value['cell_data_trackericon'] = None
|
func_last_value['cell_data_trackericon'] = None
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,6 +127,14 @@ def cell_data_progress(column, cell, model, row, data):
|
||||||
cell.set_property('text', textstr)
|
cell.set_property('text', textstr)
|
||||||
|
|
||||||
|
|
||||||
|
def cell_data_peer_progress(column, cell, model, row, data):
|
||||||
|
value = model.get_value(row, data) * 100
|
||||||
|
if func_last_value['cell_data_peer_progress'] != value:
|
||||||
|
func_last_value['cell_data_peer_progress'] = value
|
||||||
|
cell.set_property('value', value)
|
||||||
|
cell.set_property('text', '%i%%' % value)
|
||||||
|
|
||||||
|
|
||||||
def cell_data_queue(column, cell, model, row, data):
|
def cell_data_queue(column, cell, model, row, data):
|
||||||
value = model.get_value(row, data)
|
value = model.get_value(row, data)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue