mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-03 15:08:40 +00:00
Allow changing ownership of torrents. In order to achieve this, added deluge.core.set_torrents_owner()
, deluge.core.get_known_accounts()
, deluge.core.authmanager.get_known_accounts() and
deluge.core.torrent.set_owner()`. So far only the GtkUi has this fully implemented.
This commit is contained in:
parent
105cb52cb0
commit
e63c33c496
6 changed files with 120 additions and 12 deletions
|
@ -10,9 +10,12 @@
|
||||||
* #1247: Fix deluge-gtk from hanging on shutdown
|
* #1247: Fix deluge-gtk from hanging on shutdown
|
||||||
* #995: Rewrote tracker_icons
|
* #995: Rewrote tracker_icons
|
||||||
* Make the distinction between adding to the session new unmanaged torrents and torrents loaded from state. This will break backwards compatability.
|
* Make the distinction between adding to the session new unmanaged torrents and torrents loaded from state. This will break backwards compatability.
|
||||||
|
* Pass a copy of an event instead of passing the event arguments to the event handlers. This will break backwards compatability.
|
||||||
|
* Allow changing ownership of torrents.
|
||||||
|
|
||||||
==== GtkUI ====
|
==== GtkUI ====
|
||||||
* Fix uncaught exception when closing deluge in classic mode
|
* Fix uncaught exception when closing deluge in classic mode
|
||||||
|
* Allow changing ownership of torrents
|
||||||
|
|
||||||
==== WebUI ====
|
==== WebUI ====
|
||||||
* Migrate to ExtJS 3.1
|
* Migrate to ExtJS 3.1
|
||||||
|
|
|
@ -74,18 +74,16 @@ class AuthManager(component.Component):
|
||||||
:returns: int, the auth level for this user
|
:returns: int, the auth level for this user
|
||||||
:rtype: int
|
:rtype: int
|
||||||
|
|
||||||
|
:raises AuthenticationRequired: if aditional details are required to authenticate
|
||||||
:raises BadLoginError: if the username does not exist or password does not match
|
:raises BadLoginError: if the username does not exist or password does not match
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not username:
|
if not username:
|
||||||
raise AuthenticationRequired("Username and Password are required.",
|
raise AuthenticationRequired(
|
||||||
username)
|
"Username and Password are required.", username
|
||||||
|
)
|
||||||
|
|
||||||
if username and username not in self.__auth:
|
self.__test_existing_account(username)
|
||||||
# Let's try to re-load the file.. Maybe it's been updated
|
|
||||||
self.__load_auth_file()
|
|
||||||
if username not in self.__auth:
|
|
||||||
raise BadLoginError("Username does not exist")
|
|
||||||
|
|
||||||
if self.__auth[username][0] == password:
|
if self.__auth[username][0] == password:
|
||||||
# Return the users auth level
|
# Return the users auth level
|
||||||
|
@ -95,6 +93,21 @@ class AuthManager(component.Component):
|
||||||
else:
|
else:
|
||||||
raise BadLoginError("Password does not match")
|
raise BadLoginError("Password does not match")
|
||||||
|
|
||||||
|
def get_known_accounts(self):
|
||||||
|
"""
|
||||||
|
Returns a list of known deluge usernames.
|
||||||
|
"""
|
||||||
|
self.__load_auth_file()
|
||||||
|
return self.__auth.keys()
|
||||||
|
|
||||||
|
|
||||||
|
def __test_existing_account(self, username):
|
||||||
|
if username not in self.__auth:
|
||||||
|
# Let's try to re-load the file.. Maybe it's been updated
|
||||||
|
self.__load_auth_file()
|
||||||
|
if username not in self.__auth:
|
||||||
|
raise BadLoginError("Username does not exist")
|
||||||
|
|
||||||
def __create_localclient_account(self):
|
def __create_localclient_account(self):
|
||||||
"""
|
"""
|
||||||
Returns the string.
|
Returns the string.
|
||||||
|
|
|
@ -55,6 +55,7 @@ import deluge.common
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge.event import *
|
from deluge.event import *
|
||||||
from deluge.error import *
|
from deluge.error import *
|
||||||
|
from deluge.core.authmanager import AUTH_LEVEL_ADMIN
|
||||||
from deluge.core.torrentmanager import TorrentManager
|
from deluge.core.torrentmanager import TorrentManager
|
||||||
from deluge.core.pluginmanager import PluginManager
|
from deluge.core.pluginmanager import PluginManager
|
||||||
from deluge.core.alertmanager import AlertManager
|
from deluge.core.alertmanager import AlertManager
|
||||||
|
@ -579,6 +580,25 @@ class Core(component.Component):
|
||||||
"""Sets the path for the torrent to be moved when completed"""
|
"""Sets the path for the torrent to be moved when completed"""
|
||||||
return self.torrentmanager[torrent_id].set_move_completed_path(value)
|
return self.torrentmanager[torrent_id].set_move_completed_path(value)
|
||||||
|
|
||||||
|
@export(AUTH_LEVEL_ADMIN)
|
||||||
|
def set_torrents_owner(self, torrent_ids, username):
|
||||||
|
"""Set's the torrent owner.
|
||||||
|
|
||||||
|
:param torrent_id: the torrent_id of the torrent to remove
|
||||||
|
:type torrent_id: string
|
||||||
|
:param username: the new owner username
|
||||||
|
:type username: string
|
||||||
|
|
||||||
|
:raises DelugeError: if the username is not known
|
||||||
|
"""
|
||||||
|
if username not in self.authmanager.get_known_accounts():
|
||||||
|
raise DelugeError("Username \"%s\" is not known." % username)
|
||||||
|
if isinstance(torrent_ids, basestring):
|
||||||
|
torrent_ids = [torrent_ids]
|
||||||
|
for torrent_id in torrent_ids:
|
||||||
|
self.torrentmanager[torrent_id].set_owner(username)
|
||||||
|
return None
|
||||||
|
|
||||||
@export
|
@export
|
||||||
def get_path_size(self, path):
|
def get_path_size(self, path):
|
||||||
"""Returns the size of the file or folder 'path' and -1 if the path is
|
"""Returns the size of the file or folder 'path' and -1 if the path is
|
||||||
|
@ -801,3 +821,7 @@ class Core(component.Component):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return lt.version
|
return lt.version
|
||||||
|
|
||||||
|
@export(AUTH_LEVEL_ADMIN)
|
||||||
|
def get_known_accounts(self):
|
||||||
|
return self.authmanager.get_known_accounts()
|
||||||
|
|
|
@ -211,12 +211,13 @@ class Torrent(object):
|
||||||
for (key, value) in options.items():
|
for (key, value) in options.items():
|
||||||
if OPTIONS_FUNCS.has_key(key):
|
if OPTIONS_FUNCS.has_key(key):
|
||||||
OPTIONS_FUNCS[key](value)
|
OPTIONS_FUNCS[key](value)
|
||||||
|
|
||||||
self.options.update(options)
|
self.options.update(options)
|
||||||
|
|
||||||
def get_options(self):
|
def get_options(self):
|
||||||
return self.options
|
return self.options
|
||||||
|
|
||||||
|
def set_owner(self, account):
|
||||||
|
self.owner = account
|
||||||
|
|
||||||
def set_max_connections(self, max_connections):
|
def set_max_connections(self, max_connections):
|
||||||
self.options["max_connections"] = int(max_connections)
|
self.options["max_connections"] = int(max_connections)
|
||||||
|
|
|
@ -100,6 +100,10 @@ class MenuBar(component.Component):
|
||||||
self.torrentmenu = self.torrentmenu_glade.get_widget("torrent_menu")
|
self.torrentmenu = self.torrentmenu_glade.get_widget("torrent_menu")
|
||||||
self.menu_torrent = self.window.main_glade.get_widget("menu_torrent")
|
self.menu_torrent = self.window.main_glade.get_widget("menu_torrent")
|
||||||
|
|
||||||
|
self.menuitem_change_owner = gtk.MenuItem(_("Change Ownership"))
|
||||||
|
self.torrentmenu_glade.get_widget("options_torrent_menu").append(self.menuitem_change_owner)
|
||||||
|
|
||||||
|
|
||||||
# Attach the torrent_menu to the Torrent file menu
|
# Attach the torrent_menu to the Torrent file menu
|
||||||
self.menu_torrent.set_submenu(self.torrentmenu)
|
self.menu_torrent.set_submenu(self.torrentmenu)
|
||||||
|
|
||||||
|
@ -199,10 +203,21 @@ class MenuBar(component.Component):
|
||||||
if not self.config["classic_mode"]:
|
if not self.config["classic_mode"]:
|
||||||
self.window.main_glade.get_widget("separatormenuitem").show()
|
self.window.main_glade.get_widget("separatormenuitem").show()
|
||||||
self.window.main_glade.get_widget("menuitem_quitdaemon").show()
|
self.window.main_glade.get_widget("menuitem_quitdaemon").show()
|
||||||
|
|
||||||
# Show the Torrent menu because we're connected to a host
|
# Show the Torrent menu because we're connected to a host
|
||||||
self.menu_torrent.show()
|
self.menu_torrent.show()
|
||||||
|
|
||||||
|
# Hide the change owner submenu until we get the accounts back from the
|
||||||
|
# demon.
|
||||||
|
self.menuitem_change_owner.set_visible(False)
|
||||||
|
|
||||||
|
# Get Known accounts to allow chaning ownership
|
||||||
|
client.core.get_known_accounts().addCallback(self._on_known_accounts)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
log.debug("MenuBar stopping")
|
||||||
|
self.menuitem_change_owner.remove_submenu()
|
||||||
|
|
||||||
for widget in self.change_sensitivity:
|
for widget in self.change_sensitivity:
|
||||||
self.window.main_glade.get_widget(widget).set_sensitive(False)
|
self.window.main_glade.get_widget(widget).set_sensitive(False)
|
||||||
|
|
||||||
|
@ -212,6 +227,7 @@ class MenuBar(component.Component):
|
||||||
self.window.main_glade.get_widget("separatormenuitem").hide()
|
self.window.main_glade.get_widget("separatormenuitem").hide()
|
||||||
self.window.main_glade.get_widget("menuitem_quitdaemon").hide()
|
self.window.main_glade.get_widget("menuitem_quitdaemon").hide()
|
||||||
|
|
||||||
|
|
||||||
def update_menu(self):
|
def update_menu(self):
|
||||||
selected = component.get('TorrentView').get_selected_torrents()
|
selected = component.get('TorrentView').get_selected_torrents()
|
||||||
if not selected or len(selected) == 0:
|
if not selected or len(selected) == 0:
|
||||||
|
@ -465,3 +481,54 @@ class MenuBar(component.Component):
|
||||||
|
|
||||||
for item in items:
|
for item in items:
|
||||||
getattr(self.window.main_glade.get_widget(item), attr)()
|
getattr(self.window.main_glade.get_widget(item), attr)()
|
||||||
|
|
||||||
|
def _on_known_accounts(self, known_accounts):
|
||||||
|
log.debug("_on_known_accounts: %s", known_accounts)
|
||||||
|
if len(known_accounts) <= 1:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.menuitem_change_owner.set_visible(True)
|
||||||
|
|
||||||
|
self.change_owner_submenu = gtk.Menu()
|
||||||
|
self.change_owner_submenu_items = {}
|
||||||
|
maingroup = gtk.RadioMenuItem(None, None)
|
||||||
|
|
||||||
|
self.change_owner_submenu_items[None] = gtk.RadioMenuItem(maingroup)
|
||||||
|
|
||||||
|
for account in known_accounts:
|
||||||
|
self.change_owner_submenu_items[account] = item = gtk.RadioMenuItem(maingroup, account)
|
||||||
|
self.change_owner_submenu.append(item)
|
||||||
|
item.connect("toggled", self._on_change_owner_toggled, account)
|
||||||
|
|
||||||
|
self.change_owner_submenu.show_all()
|
||||||
|
self.change_owner_submenu_items[None].set_active(True)
|
||||||
|
self.change_owner_submenu_items[None].hide()
|
||||||
|
self.menuitem_change_owner.connect("activate", self._on_change_owner_submenu_active)
|
||||||
|
self.menuitem_change_owner.set_submenu(self.change_owner_submenu)
|
||||||
|
|
||||||
|
def _on_known_accounts_fail(self, reason):
|
||||||
|
self.menuitem_change_owner.set_visible(False)
|
||||||
|
|
||||||
|
def _on_change_owner_submenu_active(self, widget):
|
||||||
|
log.debug("_on_change_owner_submenu_active")
|
||||||
|
selected = component.get("TorrentView").get_selected_torrents()
|
||||||
|
if len(selected) > 1:
|
||||||
|
self.change_owner_submenu_items[None].set_active(True)
|
||||||
|
return
|
||||||
|
|
||||||
|
torrent_owner = component.get("TorrentView").get_torrent_status(selected[0])["owner"]
|
||||||
|
for account, item in self.change_owner_submenu_items.iteritems():
|
||||||
|
item.set_active(account == torrent_owner)
|
||||||
|
|
||||||
|
def _on_change_owner_toggled(self, widget, account):
|
||||||
|
log.debug("_on_change_owner_toggled")
|
||||||
|
update_torrents = []
|
||||||
|
selected = component.get("TorrentView").get_selected_torrents()
|
||||||
|
for torrent_id in selected:
|
||||||
|
torrent_status = component.get("TorrentView").get_torrent_status(torrent_id)
|
||||||
|
if torrent_status["owner"] != account:
|
||||||
|
update_torrents.append(torrent_id)
|
||||||
|
if update_torrents:
|
||||||
|
log.debug("Setting torrent owner \"%s\" on %s", account, update_torrents)
|
||||||
|
client.core.set_torrents_owner(update_torrents, account)
|
||||||
|
|
||||||
|
|
|
@ -197,7 +197,8 @@ class TorrentView(listview.ListView, component.Component):
|
||||||
# Register the columns menu with the listview so it gets updated
|
# Register the columns menu with the listview so it gets updated
|
||||||
# accordingly.
|
# accordingly.
|
||||||
self.register_checklist_menu(
|
self.register_checklist_menu(
|
||||||
self.window.main_glade.get_widget("menu_columns"))
|
self.window.main_glade.get_widget("menu_columns")
|
||||||
|
)
|
||||||
|
|
||||||
# Add the columns to the listview
|
# Add the columns to the listview
|
||||||
self.add_text_column("torrent_id", hidden=True)
|
self.add_text_column("torrent_id", hidden=True)
|
||||||
|
@ -253,8 +254,7 @@ class TorrentView(listview.ListView, component.Component):
|
||||||
### Connect Signals ###
|
### Connect Signals ###
|
||||||
# Connect to the 'button-press-event' to know when to bring up the
|
# Connect to the 'button-press-event' to know when to bring up the
|
||||||
# torrent menu popup.
|
# torrent menu popup.
|
||||||
self.treeview.connect("button-press-event",
|
self.treeview.connect("button-press-event", self.on_button_press_event)
|
||||||
self.on_button_press_event)
|
|
||||||
# Connect to the 'key-press-event' to know when the bring up the
|
# Connect to the 'key-press-event' to know when the bring up the
|
||||||
# torrent menu popup via keypress.
|
# torrent menu popup via keypress.
|
||||||
self.treeview.connect("key-release-event", self.on_key_press_event)
|
self.treeview.connect("key-release-event", self.on_key_press_event)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue