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
|
@ -10,9 +10,12 @@
|
|||
* #1247: Fix deluge-gtk from hanging on shutdown
|
||||
* #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.
|
||||
* 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 ====
|
||||
* Fix uncaught exception when closing deluge in classic mode
|
||||
* Allow changing ownership of torrents
|
||||
|
||||
==== WebUI ====
|
||||
* Migrate to ExtJS 3.1
|
||||
|
|
|
@ -74,18 +74,16 @@ class AuthManager(component.Component):
|
|||
:returns: int, the auth level for this user
|
||||
:rtype: int
|
||||
|
||||
:raises AuthenticationRequired: if aditional details are required to authenticate
|
||||
:raises BadLoginError: if the username does not exist or password does not match
|
||||
|
||||
"""
|
||||
if not username:
|
||||
raise AuthenticationRequired("Username and Password are required.",
|
||||
username)
|
||||
raise AuthenticationRequired(
|
||||
"Username and Password are required.", username
|
||||
)
|
||||
|
||||
if username and 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")
|
||||
self.__test_existing_account(username)
|
||||
|
||||
if self.__auth[username][0] == password:
|
||||
# Return the users auth level
|
||||
|
@ -95,6 +93,21 @@ class AuthManager(component.Component):
|
|||
else:
|
||||
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):
|
||||
"""
|
||||
Returns the string.
|
||||
|
|
|
@ -55,6 +55,7 @@ import deluge.common
|
|||
import deluge.component as component
|
||||
from deluge.event import *
|
||||
from deluge.error import *
|
||||
from deluge.core.authmanager import AUTH_LEVEL_ADMIN
|
||||
from deluge.core.torrentmanager import TorrentManager
|
||||
from deluge.core.pluginmanager import PluginManager
|
||||
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"""
|
||||
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
|
||||
def get_path_size(self, path):
|
||||
"""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
|
||||
|
||||
@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():
|
||||
if OPTIONS_FUNCS.has_key(key):
|
||||
OPTIONS_FUNCS[key](value)
|
||||
|
||||
self.options.update(options)
|
||||
|
||||
def get_options(self):
|
||||
return self.options
|
||||
|
||||
def set_owner(self, account):
|
||||
self.owner = account
|
||||
|
||||
def set_max_connections(self, 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.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
|
||||
self.menu_torrent.set_submenu(self.torrentmenu)
|
||||
|
||||
|
@ -199,10 +203,21 @@ class MenuBar(component.Component):
|
|||
if not self.config["classic_mode"]:
|
||||
self.window.main_glade.get_widget("separatormenuitem").show()
|
||||
self.window.main_glade.get_widget("menuitem_quitdaemon").show()
|
||||
|
||||
# Show the Torrent menu because we're connected to a host
|
||||
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):
|
||||
log.debug("MenuBar stopping")
|
||||
self.menuitem_change_owner.remove_submenu()
|
||||
|
||||
for widget in self.change_sensitivity:
|
||||
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("menuitem_quitdaemon").hide()
|
||||
|
||||
|
||||
def update_menu(self):
|
||||
selected = component.get('TorrentView').get_selected_torrents()
|
||||
if not selected or len(selected) == 0:
|
||||
|
@ -465,3 +481,54 @@ class MenuBar(component.Component):
|
|||
|
||||
for item in items:
|
||||
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
|
||||
# accordingly.
|
||||
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
|
||||
self.add_text_column("torrent_id", hidden=True)
|
||||
|
@ -253,15 +254,14 @@ class TorrentView(listview.ListView, component.Component):
|
|||
### Connect Signals ###
|
||||
# Connect to the 'button-press-event' to know when to bring up the
|
||||
# torrent menu popup.
|
||||
self.treeview.connect("button-press-event",
|
||||
self.on_button_press_event)
|
||||
self.treeview.connect("button-press-event", self.on_button_press_event)
|
||||
# Connect to the 'key-press-event' to know when the bring up the
|
||||
# torrent menu popup via keypress.
|
||||
self.treeview.connect("key-release-event", self.on_key_press_event)
|
||||
# Connect to the 'changed' event of TreeViewSelection to get selection
|
||||
# changes.
|
||||
self.treeview.get_selection().connect("changed",
|
||||
self.on_selection_changed)
|
||||
self.on_selection_changed)
|
||||
|
||||
self.treeview.connect("drag-drop", self.on_drag_drop)
|
||||
self.treeview.connect("key-press-event", self.on_key_press_event)
|
||||
|
|
Loading…
Reference in New Issue