mirror of
https://git.deluge-torrent.org/deluge
synced 2025-04-20 11:35:49 +00:00
Start work of magnet uri and trackerless torrent support
This commit is contained in:
parent
c906b50d11
commit
ccb53e48a9
8 changed files with 482 additions and 194 deletions
|
@ -376,7 +376,7 @@ class Core(
|
|||
}
|
||||
|
||||
|
||||
def export_add_torrent_url(self, url, save_path, options):
|
||||
def export_add_torrent_url(self, url, options):
|
||||
log.info("Attempting to add url %s", url)
|
||||
|
||||
# Get the actual filename of the torrent from the url provided.
|
||||
|
@ -398,6 +398,14 @@ class Core(
|
|||
return self.export_add_torrent_file(
|
||||
filename, filedump, options)
|
||||
|
||||
def export_add_torrent_magnets(self, uris, options):
|
||||
for uri in uris:
|
||||
log.debug("Attempting to add by magnet uri: %s", uri)
|
||||
torrent_id = self.torrents.add(magnet=uri, options=options[uris.index(uri)])
|
||||
|
||||
# Run the plugin hooks for 'post_torrent_add'
|
||||
self.plugins.run_post_torrent_add(torrent_id)
|
||||
|
||||
def export_remove_torrent(self, torrent_ids, remove_torrent, remove_data):
|
||||
log.debug("Removing torrent %s from the core.", torrent_ids)
|
||||
for torrent_id in torrent_ids:
|
||||
|
|
|
@ -80,12 +80,20 @@ class Torrent:
|
|||
self.torrent_id = str(handle.info_hash())
|
||||
|
||||
# We store the filename just in case we need to make a copy of the torrentfile
|
||||
if not filename:
|
||||
# If no filename was provided, then just use the infohash
|
||||
filename = self.torrent_id
|
||||
|
||||
self.filename = filename
|
||||
|
||||
# Holds status info so that we don't need to keep getting it from lt
|
||||
self.status = self.handle.status()
|
||||
self.torrent_info = self.handle.get_torrent_info()
|
||||
|
||||
try:
|
||||
self.torrent_info = self.handle.get_torrent_info()
|
||||
except RuntimeError:
|
||||
self.torrent_info = None
|
||||
|
||||
# Files dictionary
|
||||
self.files = self.get_files()
|
||||
|
||||
|
@ -188,12 +196,13 @@ class Torrent:
|
|||
def set_prioritize_first_last(self, prioritize):
|
||||
self.options["prioritize_first_last_pieces"] = prioritize
|
||||
if prioritize:
|
||||
if self.handle.get_torrent_info().num_files() == 1:
|
||||
# We only do this if one file is in the torrent
|
||||
priorities = [1] * self.handle.get_torrent_info().num_pieces()
|
||||
priorities[0] = 7
|
||||
priorities[-1] = 7
|
||||
self.handle.prioritize_pieces(priorities)
|
||||
if self.handle.has_metadata():
|
||||
if self.handle.get_torrent_info().num_files() == 1:
|
||||
# We only do this if one file is in the torrent
|
||||
priorities = [1] * self.handle.get_torrent_info().num_pieces()
|
||||
priorities[0] = 7
|
||||
priorities[-1] = 7
|
||||
self.handle.prioritize_pieces(priorities)
|
||||
|
||||
def set_auto_managed(self, auto_managed):
|
||||
self.options["auto_managed"] = auto_managed
|
||||
|
@ -348,11 +357,14 @@ class Torrent:
|
|||
|
||||
def get_files(self):
|
||||
"""Returns a list of files this torrent contains"""
|
||||
if self.torrent_info == None:
|
||||
if self.torrent_info == None and self.handle.has_metadata():
|
||||
torrent_info = self.handle.get_torrent_info()
|
||||
else:
|
||||
torrent_info = self.torrent_info
|
||||
|
||||
|
||||
if not torrent_info:
|
||||
return []
|
||||
|
||||
ret = []
|
||||
files = torrent_info.files()
|
||||
for index, file in enumerate(files):
|
||||
|
@ -438,7 +450,8 @@ class Torrent:
|
|||
"""Returns the status of the torrent based on the keys provided"""
|
||||
# Create the full dictionary
|
||||
self.status = self.handle.status()
|
||||
self.torrent_info = self.handle.get_torrent_info()
|
||||
if self.handle.has_metadata():
|
||||
self.torrent_info = self.handle.get_torrent_info()
|
||||
|
||||
# Adjust progress to be 0-100 value
|
||||
progress = self.status.progress * 100
|
||||
|
@ -490,14 +503,39 @@ class Torrent:
|
|||
"move_on_completed": self.options["move_completed"],
|
||||
"move_on_completed_path": self.options["move_completed_path"]
|
||||
}
|
||||
|
||||
|
||||
def ti_name():
|
||||
if self.handle.has_metadata():
|
||||
return self.torrent_info.name()
|
||||
return self.torrent_id
|
||||
def ti_priv():
|
||||
if self.handle.has_metadata():
|
||||
return self.torrent_info.priv()
|
||||
return False
|
||||
def ti_total_size():
|
||||
if self.handle.has_metadata():
|
||||
return self.torrent_info.total_size()
|
||||
return 0
|
||||
def ti_num_files():
|
||||
if self.handle.has_metadata():
|
||||
return self.torrent_info.num_files()
|
||||
return 0
|
||||
def ti_num_pieces():
|
||||
if self.handle.has_metadata():
|
||||
return self.torrent_info.num_pieces()
|
||||
return 0
|
||||
def ti_piece_length():
|
||||
if self.handle.has_metadata():
|
||||
return self.torrent_info.piece_length()
|
||||
return 0
|
||||
|
||||
fns = {
|
||||
"name": self.torrent_info.name,
|
||||
"private": self.torrent_info.priv,
|
||||
"total_size": self.torrent_info.total_size,
|
||||
"num_files": self.torrent_info.num_files,
|
||||
"num_pieces": self.torrent_info.num_pieces,
|
||||
"piece_length": self.torrent_info.piece_length,
|
||||
"name": ti_name,
|
||||
"private": ti_priv,
|
||||
"total_size": ti_total_size,
|
||||
"num_files": ti_num_files,
|
||||
"num_pieces": ti_num_pieces,
|
||||
"piece_length": ti_piece_length,
|
||||
"eta": self.get_eta,
|
||||
"ratio": self.get_ratio,
|
||||
"file_progress": self.get_file_progress,
|
||||
|
@ -507,9 +545,6 @@ class Torrent:
|
|||
"tracker_host": self.get_tracker_host
|
||||
}
|
||||
|
||||
self.status = None
|
||||
self.torrent_info = None
|
||||
|
||||
# Create the desired status dictionary and return it
|
||||
status_dict = {}
|
||||
|
||||
|
@ -524,6 +559,9 @@ class Torrent:
|
|||
elif key in fns:
|
||||
status_dict[key] = fns[key]()
|
||||
|
||||
self.status = None
|
||||
self.torrent_info = None
|
||||
|
||||
return status_dict
|
||||
|
||||
def apply_options(self):
|
||||
|
|
|
@ -239,11 +239,11 @@ class TorrentManager(component.Component):
|
|||
return str(fastresume)
|
||||
|
||||
def add(self, torrent_info=None, state=None, options=None, save_state=True,
|
||||
filedump=None, filename=None):
|
||||
filedump=None, filename=None, magnet=None):
|
||||
"""Add a torrent to the manager and returns it's torrent_id"""
|
||||
|
||||
if torrent_info is None and state is None and filedump is None:
|
||||
log.debug("You must specify a valid torrent_info or a torrent state object!")
|
||||
if torrent_info is None and state is None and filedump is None and magnet is None:
|
||||
log.debug("You must specify a valid torrent_info, torrent state or magnet.")
|
||||
return
|
||||
|
||||
log.debug("torrentmanager.add")
|
||||
|
@ -255,12 +255,12 @@ class TorrentManager(component.Component):
|
|||
except Exception, e:
|
||||
log.error("Unable to decode torrent file!: %s", e)
|
||||
|
||||
if torrent_info is None:
|
||||
if torrent_info is None and state:
|
||||
# We have no torrent_info so we need to add the torrent with information
|
||||
# from the state object.
|
||||
|
||||
# Populate the options dict from state
|
||||
options = OPTIONS
|
||||
options = OPTIONS.copy()
|
||||
options["max_connections"] = state.max_connections
|
||||
options["max_upload_slots"] = state.max_upload_slots
|
||||
options["max_upload_speed"] = state.max_upload_speed
|
||||
|
@ -284,9 +284,9 @@ class TorrentManager(component.Component):
|
|||
# We have a torrent_info object so we're not loading from state.
|
||||
# Check if options is None and load defaults
|
||||
if options == None:
|
||||
options = OPTIONS
|
||||
options = OPTIONS.copy()
|
||||
else:
|
||||
o = OPTIONS
|
||||
o = OPTIONS.copy()
|
||||
o.update(options)
|
||||
options = o
|
||||
|
||||
|
@ -316,7 +316,10 @@ class TorrentManager(component.Component):
|
|||
|
||||
handle = None
|
||||
try:
|
||||
handle = self.session.add_torrent(add_torrent_params)
|
||||
if magnet:
|
||||
handle = lt.add_magnet_uri(self.session, magnet, add_torrent_params)
|
||||
else:
|
||||
handle = self.session.add_torrent(add_torrent_params)
|
||||
except RuntimeError, e:
|
||||
log.warning("Error adding torrent: %s", e)
|
||||
|
||||
|
|
|
@ -169,7 +169,7 @@ class BaseClient(object):
|
|||
"set_torrent_prioritize_first_last", "set_torrent_auto_managed",
|
||||
"set_torrent_stop_ratio", "set_torrent_stop_at_ratio",
|
||||
"set_torrent_remove_at_ratio", "set_torrent_move_on_completed",
|
||||
"set_torrent_move_on_completed_path"]
|
||||
"set_torrent_move_on_completed_path", "add_torrent_magnets"]
|
||||
|
||||
def __init__(self):
|
||||
self.core = _core
|
||||
|
|
|
@ -61,6 +61,7 @@ class AddTorrentDialog(component.Component):
|
|||
"on_button_file_clicked": self._on_button_file_clicked,
|
||||
"on_button_url_clicked": self._on_button_url_clicked,
|
||||
"on_button_hash_clicked": self._on_button_hash_clicked,
|
||||
"on_button_magnet_clicked": self._on_button_magnet_clicked,
|
||||
"on_button_remove_clicked": self._on_button_remove_clicked,
|
||||
"on_button_trackers_clicked": self._on_button_trackers_clicked,
|
||||
"on_button_cancel_clicked": self._on_button_cancel_clicked,
|
||||
|
@ -69,6 +70,9 @@ class AddTorrentDialog(component.Component):
|
|||
"on_button_revert_clicked": self._on_button_revert_clicked
|
||||
})
|
||||
|
||||
self.glade.get_widget("image_magnet").set_from_file(
|
||||
deluge.common.get_pixmap("magnet.png"))
|
||||
|
||||
self.torrent_liststore = gtk.ListStore(str, str, str)
|
||||
#download?, path, filesize, sequence number, inconsistent?
|
||||
self.files_treestore = gtk.TreeStore(bool, str, gobject.TYPE_UINT64,
|
||||
|
@ -229,6 +233,29 @@ class AddTorrentDialog(component.Component):
|
|||
if not row and new_row:
|
||||
self.listview_torrents.get_selection().select_iter(new_row)
|
||||
|
||||
def add_from_magnets(self, uris):
|
||||
import base64
|
||||
new_row = None
|
||||
|
||||
for uri in uris:
|
||||
info_hash = base64.b32decode(uri.split("&")[0][20:]).encode("hex")
|
||||
if info_hash in self.infos:
|
||||
log.debug("Torrent already in list!")
|
||||
continue
|
||||
name = None
|
||||
for i in uri.split("&"):
|
||||
if i[:3] == "dn=":
|
||||
name = "%s (%s)" % (i.split("=")[1], uri)
|
||||
if not name:
|
||||
name = uri
|
||||
new_row = self.torrent_liststore.append(
|
||||
[info_hash, name, uri])
|
||||
self.files[info_hash] = []
|
||||
self.infos[info_hash] = None
|
||||
(model, row) = self.listview_torrents.get_selection().get_selected()
|
||||
if not row and new_row:
|
||||
self.listview_torrents.get_selection().select_iter(new_row)
|
||||
|
||||
def _on_torrent_changed(self, treeselection):
|
||||
(model, row) = treeselection.get_selected()
|
||||
self.files_treestore.clear()
|
||||
|
@ -346,8 +373,6 @@ class AddTorrentDialog(component.Component):
|
|||
self.glade.get_widget("chk_paused").get_active()
|
||||
options["prioritize_first_last_pieces"] = \
|
||||
self.glade.get_widget("chk_prioritize").get_active()
|
||||
options["default_private"] = \
|
||||
self.glade.get_widget("chk_private").get_active()
|
||||
|
||||
self.options[torrent_id] = options
|
||||
|
||||
|
@ -542,6 +567,46 @@ class AddTorrentDialog(component.Component):
|
|||
def _on_button_hash_clicked(self, widget):
|
||||
log.debug("_on_button_hash_clicked")
|
||||
|
||||
def _on_button_magnet_clicked(self, widget):
|
||||
log.debug("_on_button_magnet_clicked")
|
||||
dialog = self.glade.get_widget("dialog_magnet")
|
||||
entry = self.glade.get_widget("entry_magnet")
|
||||
self.glade.get_widget("image_dialog_magnet").set_from_file(
|
||||
deluge.common.get_pixmap("magnet.png"))
|
||||
|
||||
dialog.set_default_response(gtk.RESPONSE_OK)
|
||||
dialog.set_transient_for(self.dialog)
|
||||
entry.grab_focus()
|
||||
|
||||
if deluge.common.windows_check():
|
||||
import win32clipboard as clip
|
||||
import win32con
|
||||
clip.OpenClipboard()
|
||||
text = clip.GetClipboardData(win32con.CF_UNICODETEXT)
|
||||
clip.CloseClipboard()
|
||||
else:
|
||||
clip = gtk.clipboard_get(selection='PRIMARY')
|
||||
text = clip.wait_for_text()
|
||||
if text:
|
||||
text = text.strip()
|
||||
if text[:20] == "magnet:?xt=urn:btih:":
|
||||
entry.set_text(text)
|
||||
|
||||
dialog.show_all()
|
||||
response = dialog.run()
|
||||
|
||||
if response == gtk.RESPONSE_OK:
|
||||
uri = entry.get_text().decode("utf_8")
|
||||
else:
|
||||
uri = None
|
||||
|
||||
log.debug("magnet uri: %s", uri)
|
||||
if uri:
|
||||
self.add_from_magnets([uri])
|
||||
|
||||
entry.set_text("")
|
||||
dialog.hide()
|
||||
|
||||
def _on_button_remove_clicked(self, widget):
|
||||
log.debug("_on_button_remove_clicked")
|
||||
(model, row) = self.listview_torrents.get_selection().get_selected()
|
||||
|
@ -569,6 +634,8 @@ class AddTorrentDialog(component.Component):
|
|||
self.save_torrent_options(row)
|
||||
|
||||
torrent_filenames = []
|
||||
torrent_magnets = []
|
||||
torrent_magnet_options = []
|
||||
torrent_options = []
|
||||
|
||||
row = self.torrent_liststore.get_iter_first()
|
||||
|
@ -583,14 +650,23 @@ class AddTorrentDialog(component.Component):
|
|||
file_priorities = self.get_file_priorities(torrent_id)
|
||||
if options != None:
|
||||
options["file_priorities"] = file_priorities
|
||||
|
||||
torrent_filenames.append(filename)
|
||||
torrent_options.append(options)
|
||||
|
||||
if filename[:20] == "magnet:?xt=urn:btih:":
|
||||
torrent_magnets.append(filename)
|
||||
del options["file_priorities"]
|
||||
torrent_magnet_options.append(options)
|
||||
else:
|
||||
torrent_filenames.append(filename)
|
||||
torrent_options.append(options)
|
||||
|
||||
row = self.torrent_liststore.iter_next(row)
|
||||
|
||||
client.add_torrent_file(torrent_filenames, torrent_options)
|
||||
client.force_call()
|
||||
|
||||
if torrent_filenames:
|
||||
client.add_torrent_file(torrent_filenames, torrent_options)
|
||||
if torrent_magnets:
|
||||
client.add_torrent_magnets(torrent_magnets, torrent_magnet_options)
|
||||
|
||||
client.force_call(False)
|
||||
self.hide()
|
||||
|
||||
def _on_button_apply_clicked(self, widget):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<!--Generated with glade3 3.4.5 on Sat Aug 23 22:29:34 2008 -->
|
||||
<!--Generated with glade3 3.4.5 on Tue Sep 9 03:09:06 2008 -->
|
||||
<glade-interface>
|
||||
<widget class="GtkDialog" id="dialog_add_torrent">
|
||||
<property name="height_request">560</property>
|
||||
|
@ -142,7 +142,7 @@
|
|||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">From _File</property>
|
||||
<property name="label" translatable="yes">_File</property>
|
||||
<property name="use_underline">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
|
@ -189,7 +189,7 @@
|
|||
<widget class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">From _URL</property>
|
||||
<property name="label" translatable="yes">_URL</property>
|
||||
<property name="use_underline">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
|
@ -209,6 +209,7 @@
|
|||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="button_hash">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
|
@ -236,7 +237,7 @@
|
|||
<widget class="GtkLabel" id="label5">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">From _Hash</property>
|
||||
<property name="label" translatable="yes">Info_hash</property>
|
||||
<property name="use_underline">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
|
@ -254,6 +255,39 @@
|
|||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="button_magnet">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="on_button_magnet_clicked"/>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox15">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkImage" id="image_magnet">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label22">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Magnet URI</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="use_underline">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="button_remove">
|
||||
<property name="visible">True</property>
|
||||
|
@ -297,7 +331,7 @@
|
|||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
|
@ -537,7 +571,7 @@
|
|||
<property name="n_columns">2</property>
|
||||
<property name="column_spacing">10</property>
|
||||
<child>
|
||||
<widget class="GtkSpinButton" id="spin_maxdown">
|
||||
<widget class="GtkSpinButton" id="spin_maxupslots">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
|
@ -547,78 +581,8 @@
|
|||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label11">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Max Down Speed:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label12">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Max Up Speed:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label13">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Max Connections:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label14">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Max Upload Slots:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSpinButton" id="spin_maxup">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="xalign">1</property>
|
||||
<property name="adjustment">-1 -1 9999 1 10 10</property>
|
||||
<property name="update_policy">GTK_UPDATE_IF_VALID</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
|
@ -641,7 +605,79 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSpinButton" id="spin_maxupslots">
|
||||
<widget class="GtkSpinButton" id="spin_maxup">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="xalign">1</property>
|
||||
<property name="adjustment">-1 -1 9999 1 10 10</property>
|
||||
<property name="update_policy">GTK_UPDATE_IF_VALID</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label14">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Max Upload Slots:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label13">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Max Connections:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label12">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Max Up Speed:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label11">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Max Down Speed:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="x_options">GTK_FILL</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSpinButton" id="spin_maxdown">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
|
@ -651,8 +687,6 @@
|
|||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
|
@ -726,79 +760,6 @@
|
|||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="chk_private">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">Private</property>
|
||||
<property name="response_id">0</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHButtonBox" id="hbuttonbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="layout_style">GTK_BUTTONBOX_START</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="button_trackers">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="on_button_trackers_clicked"/>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox8">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<widget class="GtkImage" id="image6">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="stock">gtk-edit</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label16">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">_Edit Trackers</property>
|
||||
<property name="use_underline">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
|
@ -1007,7 +968,7 @@
|
|||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="no">gtk-cancel</property>
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="on_button_cancel_clicked"/>
|
||||
|
@ -1041,7 +1002,7 @@
|
|||
<property name="width_request">462</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Add Tracker</property>
|
||||
<property name="title" translatable="yes">Add URL</property>
|
||||
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
||||
|
@ -1154,7 +1115,7 @@
|
|||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="no">gtk-cancel</property>
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="response_id">-6</property>
|
||||
</widget>
|
||||
|
@ -1167,7 +1128,153 @@
|
|||
<property name="has_default">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="no">gtk-ok</property>
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="response_id">-5</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<widget class="GtkDialog" id="dialog_magnet">
|
||||
<property name="width_request">462</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Add Magnet URI</property>
|
||||
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
||||
<property name="decorated">False</property>
|
||||
<property name="has_separator">False</property>
|
||||
<child internal-child="vbox">
|
||||
<widget class="GtkVBox" id="dialog-vbox5">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox7">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox8">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkImage" id="image_dialog_magnet">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label16">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes"><b>From Magnet URI</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHSeparator" id="hseparator2">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox16">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label23">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">URI:</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkEntry" id="entry_magnet">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="has_focus">True</property>
|
||||
<property name="is_focus">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="activates_default">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child internal-child="action_area">
|
||||
<widget class="GtkHButtonBox" id="dialog-action_area5">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="layout_style">GTK_BUTTONBOX_END</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="button_magnet_add_cancel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="response_id">-6</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="button_magnet_add_ok">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="has_default">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="response_id">-5</property>
|
||||
</widget>
|
||||
|
|
54
libtorrent/bindings/python/src/magnet_uri.cpp
Normal file
54
libtorrent/bindings/python/src/magnet_uri.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Copyright Andrew Resch 2008. Use, modification and distribution is
|
||||
// subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <libtorrent/session.hpp>
|
||||
#include <libtorrent/torrent.hpp>
|
||||
#include <libtorrent/magnet_uri.hpp>
|
||||
#include <boost/python.hpp>
|
||||
#include "gil.hpp"
|
||||
|
||||
using namespace boost::python;
|
||||
using namespace libtorrent;
|
||||
|
||||
namespace {
|
||||
|
||||
torrent_handle _add_magnet_uri(session& s, std::string uri, dict params)
|
||||
{
|
||||
add_torrent_params p;
|
||||
|
||||
std::string url;
|
||||
if (params.has_key("tracker_url"))
|
||||
{
|
||||
url = extract<std::string>(params["tracker_url"]);
|
||||
p.tracker_url = url.c_str();
|
||||
}
|
||||
std::string name;
|
||||
if (params.has_key("name"))
|
||||
{
|
||||
name = extract<std::string>(params["name"]);
|
||||
p.name = name.c_str();
|
||||
}
|
||||
p.save_path = fs::path(extract<std::string>(params["save_path"]));
|
||||
|
||||
std::vector<char> resume_buf;
|
||||
if (params.has_key("resume_data"))
|
||||
{
|
||||
std::string resume = extract<std::string>(params["resume_data"]);
|
||||
resume_buf.resize(resume.size());
|
||||
std::memcpy(&resume_buf[0], &resume[0], resume.size());
|
||||
p.resume_data = &resume_buf;
|
||||
}
|
||||
p.storage_mode = extract<storage_mode_t>(params["storage_mode"]);
|
||||
p.paused = params["paused"];
|
||||
p.auto_managed = params["auto_managed"];
|
||||
p.duplicate_is_error = params["duplicate_is_error"];
|
||||
|
||||
return add_magnet_uri(s, uri, p);
|
||||
}
|
||||
}
|
||||
|
||||
void bind_magnet_uri()
|
||||
{
|
||||
def("add_magnet_uri", &_add_magnet_uri);
|
||||
}
|
|
@ -22,6 +22,7 @@ void bind_peer_plugin();
|
|||
void bind_torrent();
|
||||
void bind_peer_info();
|
||||
void bind_ip_filter();
|
||||
void bind_magnet_uri();
|
||||
|
||||
BOOST_PYTHON_MODULE(libtorrent)
|
||||
{
|
||||
|
@ -46,5 +47,6 @@ BOOST_PYTHON_MODULE(libtorrent)
|
|||
bind_torrent();
|
||||
bind_peer_info();
|
||||
bind_ip_filter();
|
||||
bind_magnet_uri();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue