# # Copyright (C) 2008 Andrew Resch # # This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with # the additional special exception to link portions of this program with the OpenSSL library. # See LICENSE for more details. # import logging from datetime import datetime import gi # isort:skip (Required before Gtk import). gi.require_version('Gtk', '3.0') # isort:imports-thirdparty from gi.repository import Gtk # isort:imports-firstparty import deluge.common import deluge.component as component from deluge.plugins.pluginbase import Gtk3PluginBase from deluge.ui.client import client # isort:imports-localfolder from . import common log = logging.getLogger(__name__) class GtkUI(Gtk3PluginBase): def enable(self): log.debug('Blocklist GtkUI enable..') self.plugin = component.get('PluginManager') self.load_preferences_page() self.status_item = component.get('StatusBar').add_item( image=common.get_resource('blocklist16.png'), text='', callback=self._on_status_item_clicked, tooltip=_('Blocked IP Ranges /Whitelisted IP Ranges'), ) # Register some hooks self.plugin.register_hook('on_apply_prefs', self._on_apply_prefs) self.plugin.register_hook('on_show_prefs', self._on_show_prefs) def disable(self): log.debug('Blocklist GtkUI disable..') # Remove the preferences page self.plugin.remove_preferences_page(_('Blocklist')) # Remove status item component.get('StatusBar').remove_item(self.status_item) del self.status_item # Deregister the hooks self.plugin.deregister_hook('on_apply_prefs', self._on_apply_prefs) self.plugin.deregister_hook('on_show_prefs', self._on_show_prefs) del self.glade def update(self): def _on_get_status(status): if status['state'] == 'Downloading': self.table_info.hide() self.builder.get_object('button_check_download').set_sensitive(False) self.builder.get_object('button_force_download').set_sensitive(False) self.builder.get_object('image_up_to_date').hide() self.status_item.set_text( 'Downloading %.2f%%' % (status['file_progress'] * 100) ) self.progress_bar.set_text( 'Downloading %.2f%%' % (status['file_progress'] * 100) ) self.progress_bar.set_fraction(status['file_progress']) self.progress_bar.show() elif status['state'] == 'Importing': self.table_info.hide() self.builder.get_object('button_check_download').set_sensitive(False) self.builder.get_object('button_force_download').set_sensitive(False) self.builder.get_object('image_up_to_date').hide() self.status_item.set_text('Importing ' + str(status['num_blocked'])) self.progress_bar.set_text('Importing %s' % (status['num_blocked'])) self.progress_bar.pulse() self.progress_bar.show() elif status['state'] == 'Idle': self.progress_bar.hide() self.builder.get_object('button_check_download').set_sensitive(True) self.builder.get_object('button_force_download').set_sensitive(True) if status['up_to_date']: self.builder.get_object('image_up_to_date').show() else: self.builder.get_object('image_up_to_date').hide() self.table_info.show() self.status_item.set_text('%(num_blocked)s/%(num_whited)s' % status) self.builder.get_object('label_filesize').set_text( deluge.common.fsize(status['file_size']) ) self.builder.get_object('label_modified').set_text( datetime.fromtimestamp(status['file_date']).strftime('%c') ) self.builder.get_object('label_type').set_text(status['file_type']) self.builder.get_object('label_url').set_text(status['file_url']) client.blocklist.get_status().addCallback(_on_get_status) def _on_show_prefs(self): def _on_get_config(config): log.trace('Loaded config: %s', config) self.builder.get_object('entry_url').set_text(config['url']) self.builder.get_object('spin_check_days').set_value( config['check_after_days'] ) self.builder.get_object('chk_import_on_start').set_active( config['load_on_start'] ) self.populate_whitelist(config['whitelisted']) client.blocklist.get_config().addCallback(_on_get_config) def _on_apply_prefs(self): config = {} config['url'] = self.builder.get_object('entry_url').get_text().strip() config['check_after_days'] = self.builder.get_object( 'spin_check_days' ).get_value_as_int() config['load_on_start'] = self.builder.get_object( 'chk_import_on_start' ).get_active() config['whitelisted'] = [ ip[0] for ip in self.whitelist_model if ip[0] != 'IP HERE' ] client.blocklist.set_config(config) def _on_button_check_download_clicked(self, widget): self._on_apply_prefs() client.blocklist.check_import() def _on_button_force_download_clicked(self, widget): self._on_apply_prefs() client.blocklist.check_import(force=True) def _on_status_item_clicked(self, widget, event): component.get('Preferences').show(_('Blocklist')) def load_preferences_page(self): """Initializes the preferences page and adds it to the preferences dialog""" # Load the preferences page self.builder = Gtk.Builder() self.builder.add_from_file(common.get_resource('blocklist_pref.ui')) self.whitelist_frame = self.builder.get_object('whitelist_frame') self.progress_bar = self.builder.get_object('progressbar') self.table_info = self.builder.get_object('table_info') # Hide the progress bar initially self.progress_bar.hide() self.table_info.show() # Create the whitelisted model self.build_whitelist_model_treeview() self.builder.connect_signals( { 'on_button_check_download_clicked': self._on_button_check_download_clicked, 'on_button_force_download_clicked': self._on_button_force_download_clicked, 'on_whitelist_add_clicked': ( self.on_add_button_clicked, self.whitelist_treeview, ), 'on_whitelist_remove_clicked': ( self.on_delete_button_clicked, self.whitelist_treeview, ), } ) # Set button icons self.builder.get_object('image_download').set_from_file( common.get_resource('blocklist_download24.png') ) self.builder.get_object('image_import').set_from_file( common.get_resource('blocklist_import24.png') ) # Update the preferences page with config values from the core self._on_show_prefs() # Add the page to the preferences dialog self.plugin.add_preferences_page( _('Blocklist'), self.builder.get_object('blocklist_prefs_box') ) def build_whitelist_model_treeview(self): self.whitelist_treeview = self.builder.get_object('whitelist_treeview') treeview_selection = self.whitelist_treeview.get_selection() treeview_selection.connect( 'changed', self.on_whitelist_treeview_selection_changed ) self.whitelist_model = Gtk.ListStore(str, bool) renderer = Gtk.CellRendererText() renderer.connect('edited', self.on_cell_edited, self.whitelist_model) renderer.ip = 0 column = Gtk.TreeViewColumn('IPs', renderer, text=0, editable=1) column.set_expand(True) self.whitelist_treeview.append_column(column) self.whitelist_treeview.set_model(self.whitelist_model) def on_cell_edited(self, cell, path_string, new_text, model): # iter = model.get_iter_from_string(path_string) # path = model.get_path(iter)[0] try: ip = common.IP.parse(new_text) model.set(model.get_iter_from_string(path_string), 0, ip.address) except common.BadIP as ex: model.remove(model.get_iter_from_string(path_string)) from deluge.ui.gtkui import dialogs d = dialogs.ErrorDialog(_('Bad IP address'), ex.message) d.run() def on_whitelist_treeview_selection_changed(self, selection): model, selected_connection_iter = selection.get_selected() if selected_connection_iter: self.builder.get_object('whitelist_delete').set_property('sensitive', True) else: self.builder.get_object('whitelist_delete').set_property('sensitive', False) def on_add_button_clicked(self, widget, treeview): model = treeview.get_model() model.set(model.append(), 0, 'IP HERE', 1, True) def on_delete_button_clicked(self, widget, treeview): selection = treeview.get_selection() model, selected_iter = selection.get_selected() if selected_iter: # path = model.get_path(iter)[0] model.remove(selected_iter) def populate_whitelist(self, whitelist): self.whitelist_model.clear() for ip in whitelist: self.whitelist_model.set(self.whitelist_model.append(), 0, ip, 1, True)