diff options
Diffstat (limited to 'deluge/plugins/WebUi/deluge_webui')
-rw-r--r-- | deluge/plugins/WebUi/deluge_webui/__init__.py | 40 | ||||
-rw-r--r-- | deluge/plugins/WebUi/deluge_webui/common.py | 23 | ||||
-rw-r--r-- | deluge/plugins/WebUi/deluge_webui/core.py | 120 | ||||
-rw-r--r-- | deluge/plugins/WebUi/deluge_webui/data/config.ui | 129 | ||||
-rw-r--r-- | deluge/plugins/WebUi/deluge_webui/data/config.ui~ | 126 | ||||
-rw-r--r-- | deluge/plugins/WebUi/deluge_webui/gtkui.py | 100 | ||||
-rw-r--r-- | deluge/plugins/WebUi/deluge_webui/tests/__init__.py | 0 | ||||
-rw-r--r-- | deluge/plugins/WebUi/deluge_webui/tests/test_plugin_webui.py | 49 |
8 files changed, 587 insertions, 0 deletions
diff --git a/deluge/plugins/WebUi/deluge_webui/__init__.py b/deluge/plugins/WebUi/deluge_webui/__init__.py new file mode 100644 index 0000000..a3d2980 --- /dev/null +++ b/deluge/plugins/WebUi/deluge_webui/__init__.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2009 Damien Churchill <damoxc@gmail.com> +# +# Basic plugin template created by: +# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com> +# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com> +# +# 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. +# + +from __future__ import unicode_literals + +from deluge.plugins.init import PluginInitBase + + +class CorePlugin(PluginInitBase): + def __init__(self, plugin_name): + from .core import Core as _pluginCls + + self._plugin_cls = _pluginCls + super(CorePlugin, self).__init__(plugin_name) + + +class GtkUIPlugin(PluginInitBase): + def __init__(self, plugin_name): + from .gtkui import GtkUI as _pluginCls + + self._plugin_cls = _pluginCls + super(GtkUIPlugin, self).__init__(plugin_name) + + +class WebUIPlugin(PluginInitBase): + def __init__(self, plugin_name): + from webui import WebUI as _pluginCls + + self._plugin_cls = _pluginCls + super(WebUIPlugin, self).__init__(plugin_name) diff --git a/deluge/plugins/WebUi/deluge_webui/common.py b/deluge/plugins/WebUi/deluge_webui/common.py new file mode 100644 index 0000000..4c9db09 --- /dev/null +++ b/deluge/plugins/WebUi/deluge_webui/common.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# +# Basic plugin template created by: +# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com> +# 2007-2009 Andrew Resch <andrewresch@gmail.com> +# 2009 Damien Churchill <damoxc@gmail.com> +# 2010 Pedro Algarvio <pedro@algarvio.me> +# 2017 Calum Lind <calumlind+deluge@gmail.com> +# +# 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. +# + +from __future__ import unicode_literals + +import os.path + +from pkg_resources import resource_filename + + +def get_resource(filename): + return resource_filename(__package__, os.path.join('data', filename)) diff --git a/deluge/plugins/WebUi/deluge_webui/core.py b/deluge/plugins/WebUi/deluge_webui/core.py new file mode 100644 index 0000000..cc3330f --- /dev/null +++ b/deluge/plugins/WebUi/deluge_webui/core.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2009 Damien Churchill <damoxc@gmail.com> +# +# Basic plugin template created by: +# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com> +# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com> +# +# 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. +# + +from __future__ import unicode_literals + +import logging + +from twisted.internet import defer +from twisted.internet.error import CannotListenError + +import deluge.component as component +from deluge import configmanager +from deluge.core.rpcserver import export +from deluge.plugins.pluginbase import CorePluginBase + +try: + from deluge.ui.web import server +except ImportError: + server = False + +log = logging.getLogger(__name__) + +DEFAULT_PREFS = {'enabled': False, 'ssl': False, 'port': 8112} + + +class Core(CorePluginBase): + server = None + + def enable(self): + self.config = configmanager.ConfigManager('web_plugin.conf', DEFAULT_PREFS) + if self.config['enabled']: + self.start_server() + + def disable(self): + self.stop_server() + + def update(self): + pass + + def _on_stop(self, *args): + return self.start_server() + + @export + def got_deluge_web(self): + """Status of deluge-web module installation. + + Check if deluge.ui.web.server modulge is installed and has been successfully imported. + + Returns: + bool: True is deluge-web is installed and available, otherwise False. + + """ + + return bool(server) + + def start_server(self): + if not self.server: + if not self.got_deluge_web(): + return False + + try: + self.server = component.get('DelugeWeb') + except KeyError: + self.server = server.DelugeWeb(daemon=False) + + self.server.port = self.config['port'] + self.server.https = self.config['ssl'] + try: + self.server.start() + except CannotListenError as ex: + log.warning('Failed to start WebUI server: %s', ex) + raise + return True + + def stop_server(self): + if self.server: + return self.server.stop() + return defer.succeed(True) + + def restart_server(self): + return self.stop_server().addCallback(self._on_stop) + + @export + def set_config(self, config): + """Sets the config dictionary.""" + + action = None + if 'enabled' in config: + if config['enabled'] != self.config['enabled']: + action = config['enabled'] and 'start' or 'stop' + + if 'ssl' in config: + if not action: + action = 'restart' + + for key in config: + self.config[key] = config[key] + self.config.save() + + if action == 'start': + return self.start_server() + elif action == 'stop': + return self.stop_server() + elif action == 'restart': + return self.restart_server() + + @export + def get_config(self): + """Returns the config dictionary.""" + return self.config.config diff --git a/deluge/plugins/WebUi/deluge_webui/data/config.ui b/deluge/plugins/WebUi/deluge_webui/data/config.ui new file mode 100644 index 0000000..18647a4 --- /dev/null +++ b/deluge/plugins/WebUi/deluge_webui/data/config.ui @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.22.1 --> +<interface> + <requires lib="gtk+" version="3.0"/> + <object class="GtkAdjustment" id="adjustment1"> + <property name="upper">99999</property> + <property name="value">8112</property> + <property name="step_increment">1</property> + <property name="page_increment">10</property> + </object> + <object class="GtkWindow" id="window1"> + <property name="can_focus">False</property> + <child> + <placeholder/> + </child> + <child> + <object class="GtkBox" id="prefs_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkFrame" id="settings_frame"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label_xalign">0</property> + <property name="shadow_type">none</property> + <child> + <object class="GtkAlignment" id="settings_alignment"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="top_padding">10</property> + <property name="left_padding">12</property> + <child> + <object class="GtkBox" id="settings_vbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">5</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkCheckButton" id="enabled_checkbutton"> + <property name="label" translatable="yes">Enable web interface</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="ssl_checkbutton"> + <property name="label" translatable="yes">Enable SSL</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="port_hbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">5</property> + <child> + <object class="GtkLabel" id="port_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Listening port:</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkSpinButton" id="port_spinbutton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">●</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="adjustment">adjustment1</property> + <property name="numeric">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </object> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="settings_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes"><b>Settings</b></property> + <property name="use_markup">True</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + </child> + </object> +</interface> diff --git a/deluge/plugins/WebUi/deluge_webui/data/config.ui~ b/deluge/plugins/WebUi/deluge_webui/data/config.ui~ new file mode 100644 index 0000000..101f60d --- /dev/null +++ b/deluge/plugins/WebUi/deluge_webui/data/config.ui~ @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <requires lib="gtk+" version="3.0"/> + <!-- interface-naming-policy toplevel-contextual --> + <object class="GtkAdjustment" id="adjustment1"> + <property name="upper">99999</property> + <property name="value">8112</property> + <property name="step_increment">1</property> + <property name="page_increment">10</property> + </object> + <object class="GtkWindow" id="window1"> + <property name="can_focus">False</property> + <child> + <object class="GtkVBox" id="prefs_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkFrame" id="settings_frame"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label_xalign">0</property> + <property name="shadow_type">none</property> + <child> + <object class="GtkAlignment" id="settings_alignment"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="top_padding">10</property> + <property name="left_padding">12</property> + <child> + <object class="GtkVBox" id="settings_vbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">5</property> + <child> + <object class="GtkCheckButton" id="enabled_checkbutton"> + <property name="label" translatable="yes">Enable web interface</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="ssl_checkbutton"> + <property name="label" translatable="yes">Enable SSL</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="port_hbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">5</property> + <child> + <object class="GtkLabel" id="port_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Listening port:</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkSpinButton" id="port_spinbutton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">●</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="primary_icon_sensitive">True</property> + <property name="secondary_icon_sensitive">True</property> + <property name="adjustment">adjustment1</property> + <property name="numeric">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </object> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="settings_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes"><b>Settings</b></property> + <property name="use_markup">True</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + </child> + </object> +</interface> diff --git a/deluge/plugins/WebUi/deluge_webui/gtkui.py b/deluge/plugins/WebUi/deluge_webui/gtkui.py new file mode 100644 index 0000000..ca3a16e --- /dev/null +++ b/deluge/plugins/WebUi/deluge_webui/gtkui.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2009 Damien Churchill <damoxc@gmail.com> +# +# Basic plugin template created by: +# Copyright (C) 2008 Martijn Voncken <mvoncken@gmail.com> +# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com> +# +# 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. +# + +from __future__ import unicode_literals + +import logging + +from gi.repository import Gtk + +import deluge.component as component +from deluge.plugins.pluginbase import Gtk3PluginBase +from deluge.ui.client import client + +from .common import get_resource + +log = logging.getLogger(__name__) + + +class GtkUI(Gtk3PluginBase): + def enable(self): + self.builder = Gtk.Builder() + self.builder.add_from_file(get_resource('config.ui')) + + component.get('Preferences').add_page( + _('WebUi'), self.builder.get_object('prefs_box') + ) + component.get('PluginManager').register_hook( + 'on_apply_prefs', self.on_apply_prefs + ) + component.get('PluginManager').register_hook( + 'on_show_prefs', self.on_show_prefs + ) + client.webui.get_config().addCallback(self.cb_get_config) + client.webui.got_deluge_web().addCallback(self.cb_chk_deluge_web) + + def disable(self): + component.get('Preferences').remove_page(_('WebUi')) + component.get('PluginManager').deregister_hook( + 'on_apply_prefs', self.on_apply_prefs + ) + component.get('PluginManager').deregister_hook( + 'on_show_prefs', self.on_show_prefs + ) + + def on_apply_prefs(self): + if not self.have_web: + return + log.debug('applying prefs for WebUi') + config = { + 'enabled': self.builder.get_object('enabled_checkbutton').get_active(), + 'ssl': self.builder.get_object('ssl_checkbutton').get_active(), + 'port': self.builder.get_object('port_spinbutton').get_value_as_int(), + } + client.webui.set_config(config) + + def on_show_prefs(self): + client.webui.get_config().addCallback(self.cb_get_config) + + def cb_get_config(self, config): + """Callback for on show_prefs.""" + self.builder.get_object('enabled_checkbutton').set_active(config['enabled']) + self.builder.get_object('ssl_checkbutton').set_active(config['ssl']) + self.builder.get_object('port_spinbutton').set_value(config['port']) + + def cb_chk_deluge_web(self, have_web): + self.have_web = have_web + if have_web: + return + self.builder.get_object('settings_vbox').set_sensitive(False) + + vbox = self.builder.get_object('prefs_box') + + hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, spacing=0) + icon = Gtk.Image.new_from_icon_name('dialog-error', Gtk.IconSize.BUTTON) + icon.set_padding(5, 5) + hbox.pack_start(icon, False, False, 0) + + label = Gtk.Label( + _( + 'The Deluge web interface is not installed, ' + 'please install the\ninterface and try again' + ) + ) + label.set_alignment(0, 0.5) + label.set_padding(5, 5) + hbox.pack_start(label, False, False, 0) + + vbox.pack_start(hbox, False, False, 10) + vbox.reorder_child(hbox, 0) + vbox.show_all() diff --git a/deluge/plugins/WebUi/deluge_webui/tests/__init__.py b/deluge/plugins/WebUi/deluge_webui/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/deluge/plugins/WebUi/deluge_webui/tests/__init__.py diff --git a/deluge/plugins/WebUi/deluge_webui/tests/test_plugin_webui.py b/deluge/plugins/WebUi/deluge_webui/tests/test_plugin_webui.py new file mode 100644 index 0000000..56e1cc0 --- /dev/null +++ b/deluge/plugins/WebUi/deluge_webui/tests/test_plugin_webui.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2016 bendikro <bro.devel+deluge@gmail.com> +# +# 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. +# + +from __future__ import unicode_literals + +from twisted.trial import unittest + +import deluge.component as component +from deluge.core.core import Core +from deluge.core.rpcserver import RPCServer +from deluge.tests import common +from deluge.tests.basetest import BaseTestCase + +common.disable_new_release_check() + + +class WebUIPluginTestCase(BaseTestCase): + def set_up(self): + common.set_tmp_config_dir() + self.rpcserver = RPCServer(listen=False) + self.core = Core() + return component.start() + + def tear_down(self): + def on_shutdown(result): + del self.rpcserver + del self.core + + return component.shutdown().addCallback(on_shutdown) + + def test_enable_webui(self): + if 'WebUi' not in self.core.get_available_plugins(): + raise unittest.SkipTest('WebUi plugin not available for testing') + + d = self.core.enable_plugin('WebUi') + + def result_cb(result): + if 'WebUi' not in self.core.get_enabled_plugins(): + self.fail('Failed to enable WebUi plugin') + self.assertTrue(result) + + d.addBoth(result_cb) + return d |