Added support for adding torrents by infohash
Fixes to magnet uri stuff
This commit is contained in:
parent
3afb542f06
commit
ee9a5a19c1
|
@ -319,6 +319,12 @@ def is_url(url):
|
||||||
import re
|
import re
|
||||||
return bool(re.search('^(https?|ftp)://', url))
|
return bool(re.search('^(https?|ftp)://', url))
|
||||||
|
|
||||||
|
def is_magnet(uri):
|
||||||
|
"""Returns True if uri is a valid bittorrent magnet uri."""
|
||||||
|
if uri[:20] == "magnet:?xt=urn:btih:":
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def fetch_url(url):
|
def fetch_url(url):
|
||||||
"""Downloads a torrent file from a given
|
"""Downloads a torrent file from a given
|
||||||
URL and checks the file's validity."""
|
URL and checks the file's validity."""
|
||||||
|
@ -351,3 +357,16 @@ def pythonize(var):
|
||||||
if isinstance(var, klass):
|
if isinstance(var, klass):
|
||||||
return klass(var)
|
return klass(var)
|
||||||
return var
|
return var
|
||||||
|
|
||||||
|
def create_magnet_uri(infohash, name=None, trackers=[]):
|
||||||
|
from base64 import b32encode
|
||||||
|
uri = "magnet:?xt=urn:btih:" + b32encode(infohash.decode("hex"))
|
||||||
|
if name:
|
||||||
|
uri = uri + "&dn=" + name
|
||||||
|
if trackers:
|
||||||
|
for t in trackers:
|
||||||
|
uri = uri + "&tr=" + t
|
||||||
|
|
||||||
|
return uri
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -401,7 +401,12 @@ class Core(
|
||||||
def export_add_torrent_magnets(self, uris, options):
|
def export_add_torrent_magnets(self, uris, options):
|
||||||
for uri in uris:
|
for uri in uris:
|
||||||
log.debug("Attempting to add by magnet uri: %s", uri)
|
log.debug("Attempting to add by magnet uri: %s", uri)
|
||||||
torrent_id = self.torrents.add(magnet=uri, options=options[uris.index(uri)])
|
try:
|
||||||
|
option = options[uris.index(uri)]
|
||||||
|
except IndexError:
|
||||||
|
option = None
|
||||||
|
|
||||||
|
torrent_id = self.torrents.add(magnet=uri, options=option)
|
||||||
|
|
||||||
# Run the plugin hooks for 'post_torrent_add'
|
# Run the plugin hooks for 'post_torrent_add'
|
||||||
self.plugins.run_post_torrent_add(torrent_id)
|
self.plugins.run_post_torrent_add(torrent_id)
|
||||||
|
|
|
@ -419,6 +419,9 @@ class Torrent:
|
||||||
|
|
||||||
def get_file_progress(self):
|
def get_file_progress(self):
|
||||||
"""Returns the file progress as a list of floats.. 0.0 -> 1.0"""
|
"""Returns the file progress as a list of floats.. 0.0 -> 1.0"""
|
||||||
|
if not self.handle.has_metadata():
|
||||||
|
return 0.0
|
||||||
|
|
||||||
file_progress = self.handle.file_progress()
|
file_progress = self.handle.file_progress()
|
||||||
ret = []
|
ret = []
|
||||||
for i,f in enumerate(self.files):
|
for i,f in enumerate(self.files):
|
||||||
|
|
|
@ -61,7 +61,6 @@ class AddTorrentDialog(component.Component):
|
||||||
"on_button_file_clicked": self._on_button_file_clicked,
|
"on_button_file_clicked": self._on_button_file_clicked,
|
||||||
"on_button_url_clicked": self._on_button_url_clicked,
|
"on_button_url_clicked": self._on_button_url_clicked,
|
||||||
"on_button_hash_clicked": self._on_button_hash_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_remove_clicked": self._on_button_remove_clicked,
|
||||||
"on_button_trackers_clicked": self._on_button_trackers_clicked,
|
"on_button_trackers_clicked": self._on_button_trackers_clicked,
|
||||||
"on_button_cancel_clicked": self._on_button_cancel_clicked,
|
"on_button_cancel_clicked": self._on_button_cancel_clicked,
|
||||||
|
@ -70,9 +69,6 @@ class AddTorrentDialog(component.Component):
|
||||||
"on_button_revert_clicked": self._on_button_revert_clicked
|
"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)
|
self.torrent_liststore = gtk.ListStore(str, str, str)
|
||||||
#download?, path, filesize, sequence number, inconsistent?
|
#download?, path, filesize, sequence number, inconsistent?
|
||||||
self.files_treestore = gtk.TreeStore(bool, str, gobject.TYPE_UINT64,
|
self.files_treestore = gtk.TreeStore(bool, str, gobject.TYPE_UINT64,
|
||||||
|
@ -258,11 +254,14 @@ class AddTorrentDialog(component.Component):
|
||||||
|
|
||||||
def _on_torrent_changed(self, treeselection):
|
def _on_torrent_changed(self, treeselection):
|
||||||
(model, row) = treeselection.get_selected()
|
(model, row) = treeselection.get_selected()
|
||||||
self.files_treestore.clear()
|
|
||||||
|
|
||||||
if row is None:
|
if row is None:
|
||||||
|
self.files_treestore.clear()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Save the previous torrents options
|
||||||
|
self.save_torrent_options()
|
||||||
|
|
||||||
# Update files list
|
# Update files list
|
||||||
files_list = self.files[model.get_value(row, 0)]
|
files_list = self.files[model.get_value(row, 0)]
|
||||||
|
|
||||||
|
@ -271,32 +270,33 @@ class AddTorrentDialog(component.Component):
|
||||||
if self.core_config == {}:
|
if self.core_config == {}:
|
||||||
self.update_core_config()
|
self.update_core_config()
|
||||||
|
|
||||||
# Save the previous torrents options
|
|
||||||
self.save_torrent_options()
|
|
||||||
# Update the options frame
|
# Update the options frame
|
||||||
self.update_torrent_options(model.get_value(row, 0))
|
self.update_torrent_options(model.get_value(row, 0))
|
||||||
|
|
||||||
self.previous_selected_torrent = row
|
self.previous_selected_torrent = row
|
||||||
|
|
||||||
def prepare_file_store(self, files):
|
def prepare_file_store(self, files):
|
||||||
|
self.listview_files.set_model(None)
|
||||||
|
self.files_treestore.clear()
|
||||||
split_files = { }
|
split_files = { }
|
||||||
i = 0
|
i = 0
|
||||||
for file in files:
|
for file in files:
|
||||||
self.prepare_file(file, file["path"], i, split_files)
|
self.prepare_file(file, file["path"], i, file["download"], split_files)
|
||||||
i += 1
|
i += 1
|
||||||
self.add_files(None, split_files)
|
self.add_files(None, split_files)
|
||||||
|
self.listview_files.set_model(self.files_treestore)
|
||||||
|
self.listview_files.expand_row("0", False)
|
||||||
|
|
||||||
def prepare_file(self, file, file_name, file_num, files_storage):
|
def prepare_file(self, file, file_name, file_num, download, files_storage):
|
||||||
log.debug("file_name: %s", file_name)
|
|
||||||
first_slash_index = file_name.find("/")
|
first_slash_index = file_name.find("/")
|
||||||
if first_slash_index == -1:
|
if first_slash_index == -1:
|
||||||
files_storage[file_name] = (file_num, file)
|
files_storage[file_name] = (file_num, file, download)
|
||||||
else:
|
else:
|
||||||
file_name_chunk = file_name[:first_slash_index+1]
|
file_name_chunk = file_name[:first_slash_index+1]
|
||||||
if file_name_chunk not in files_storage:
|
if file_name_chunk not in files_storage:
|
||||||
files_storage[file_name_chunk] = { }
|
files_storage[file_name_chunk] = { }
|
||||||
self.prepare_file(file, file_name[first_slash_index+1:],
|
self.prepare_file(file, file_name[first_slash_index+1:],
|
||||||
file_num, files_storage[file_name_chunk])
|
file_num, download, files_storage[file_name_chunk])
|
||||||
|
|
||||||
def add_files(self, parent_iter, split_files):
|
def add_files(self, parent_iter, split_files):
|
||||||
ret = 0
|
ret = 0
|
||||||
|
@ -308,8 +308,29 @@ class AddTorrentDialog(component.Component):
|
||||||
self.files_treestore.set(chunk_iter, 2, chunk_size)
|
self.files_treestore.set(chunk_iter, 2, chunk_size)
|
||||||
ret += chunk_size
|
ret += chunk_size
|
||||||
else:
|
else:
|
||||||
self.files_treestore.append(parent_iter, [True, key,
|
self.files_treestore.append(parent_iter, [value[2], key,
|
||||||
value[1]["size"], value[0], False, gtk.STOCK_FILE])
|
value[1]["size"], value[0], False, gtk.STOCK_FILE])
|
||||||
|
|
||||||
|
# Iterate through the children and see what we should label the
|
||||||
|
# folder, download true, download false or inconsistent.
|
||||||
|
itr = self.files_treestore.iter_children(parent_iter)
|
||||||
|
download = []
|
||||||
|
download_value = False
|
||||||
|
inconsistent = False
|
||||||
|
while itr:
|
||||||
|
download.append(self.files_treestore.get_value(itr, 0))
|
||||||
|
itr = self.files_treestore.iter_next(itr)
|
||||||
|
|
||||||
|
if sum(download) == len(download):
|
||||||
|
download_value = True
|
||||||
|
elif sum(download) == 0:
|
||||||
|
download_value = False
|
||||||
|
else:
|
||||||
|
inconsistent = True
|
||||||
|
|
||||||
|
self.files_treestore.set_value(parent_iter, 0, download_value)
|
||||||
|
self.files_treestore.set_value(parent_iter, 4, inconsistent)
|
||||||
|
|
||||||
ret += value[1]["size"]
|
ret += value[1]["size"]
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@ -379,9 +400,11 @@ class AddTorrentDialog(component.Component):
|
||||||
# Save the file priorities
|
# Save the file priorities
|
||||||
files_priorities = self.build_priorities(
|
files_priorities = self.build_priorities(
|
||||||
self.files_treestore.get_iter_first(), {})
|
self.files_treestore.get_iter_first(), {})
|
||||||
|
log.debug("fp: %s", len(files_priorities))
|
||||||
|
|
||||||
for i, file_dict in enumerate(self.files[torrent_id]):
|
if len(files_priorities) > 0:
|
||||||
file_dict["download"] = files_priorities[i]
|
for i, file_dict in enumerate(self.files[torrent_id]):
|
||||||
|
file_dict["download"] = files_priorities[i]
|
||||||
|
|
||||||
def build_priorities(self, iter, priorities):
|
def build_priorities(self, iter, priorities):
|
||||||
while iter is not None:
|
while iter is not None:
|
||||||
|
@ -532,7 +555,7 @@ class AddTorrentDialog(component.Component):
|
||||||
text = clip.wait_for_text()
|
text = clip.wait_for_text()
|
||||||
if text:
|
if text:
|
||||||
text = text.strip()
|
text = text.strip()
|
||||||
if deluge.common.is_url(text):
|
if deluge.common.is_url(text) or deluge.common.is_magnet(text):
|
||||||
entry.set_text(text)
|
entry.set_text(text)
|
||||||
|
|
||||||
dialog.show_all()
|
dialog.show_all()
|
||||||
|
@ -547,7 +570,10 @@ class AddTorrentDialog(component.Component):
|
||||||
# add it to the list.
|
# add it to the list.
|
||||||
log.debug("url: %s", url)
|
log.debug("url: %s", url)
|
||||||
if url != None:
|
if url != None:
|
||||||
self.add_from_url(url)
|
if deluge.common.is_url(url):
|
||||||
|
self.add_from_url(url)
|
||||||
|
elif deluge.common.is_magnet(url):
|
||||||
|
self.add_from_magnets([url])
|
||||||
|
|
||||||
entry.set_text("")
|
entry.set_text("")
|
||||||
dialog.hide()
|
dialog.hide()
|
||||||
|
@ -566,45 +592,34 @@ class AddTorrentDialog(component.Component):
|
||||||
|
|
||||||
def _on_button_hash_clicked(self, widget):
|
def _on_button_hash_clicked(self, widget):
|
||||||
log.debug("_on_button_hash_clicked")
|
log.debug("_on_button_hash_clicked")
|
||||||
|
dialog = self.glade.get_widget("dialog_infohash")
|
||||||
def _on_button_magnet_clicked(self, widget):
|
entry = self.glade.get_widget("entry_hash")
|
||||||
log.debug("_on_button_magnet_clicked")
|
textview = self.glade.get_widget("text_trackers")
|
||||||
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_default_response(gtk.RESPONSE_OK)
|
||||||
dialog.set_transient_for(self.dialog)
|
dialog.set_transient_for(self.dialog)
|
||||||
entry.grab_focus()
|
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()
|
dialog.show_all()
|
||||||
response = dialog.run()
|
response = dialog.run()
|
||||||
|
if response == gtk.RESPONSE_OK and len(entry.get_text()) == 40:
|
||||||
if response == gtk.RESPONSE_OK:
|
trackers = []
|
||||||
uri = entry.get_text().decode("utf_8")
|
b = textview.get_buffer()
|
||||||
else:
|
lines = b.get_text(b.get_start_iter(), b.get_end_iter()).strip().split("\n")
|
||||||
uri = None
|
log.debug("lines: %s", lines)
|
||||||
|
for l in lines:
|
||||||
log.debug("magnet uri: %s", uri)
|
if deluge.common.is_url(l):
|
||||||
if uri:
|
trackers.append(l)
|
||||||
self.add_from_magnets([uri])
|
# Convert the information to a magnet uri, this is just easier to
|
||||||
|
# handle this way.
|
||||||
|
log.debug("trackers: %s", trackers)
|
||||||
|
magnet = deluge.common.create_magnet_uri(
|
||||||
|
infohash=entry.get_text().decode("utf_8"),
|
||||||
|
trackers=trackers)
|
||||||
|
log.debug("magnet uri: %s", magnet)
|
||||||
|
self.add_from_magnets([magnet])
|
||||||
|
|
||||||
entry.set_text("")
|
entry.set_text("")
|
||||||
|
textview.get_buffer().set_text("")
|
||||||
dialog.hide()
|
dialog.hide()
|
||||||
|
|
||||||
def _on_button_remove_clicked(self, widget):
|
def _on_button_remove_clicked(self, widget):
|
||||||
|
@ -651,7 +666,7 @@ class AddTorrentDialog(component.Component):
|
||||||
if options != None:
|
if options != None:
|
||||||
options["file_priorities"] = file_priorities
|
options["file_priorities"] = file_priorities
|
||||||
|
|
||||||
if filename[:20] == "magnet:?xt=urn:btih:":
|
if deluge.common.is_magnet(filename):
|
||||||
torrent_magnets.append(filename)
|
torrent_magnets.append(filename)
|
||||||
del options["file_priorities"]
|
del options["file_priorities"]
|
||||||
torrent_magnet_options.append(options)
|
torrent_magnet_options.append(options)
|
||||||
|
|
|
@ -61,8 +61,10 @@ class DbusInterface(dbus.service.Object, component.Component):
|
||||||
# Convert the paths to absolutes
|
# Convert the paths to absolutes
|
||||||
new_args = []
|
new_args = []
|
||||||
for arg in args:
|
for arg in args:
|
||||||
if not deluge.common.is_url(arg):
|
if not deluge.common.is_url(arg) and not deluge.common.is_magnet(arg):
|
||||||
new_args.append(os.path.abspath(arg))
|
new_args.append(os.path.abspath(arg))
|
||||||
|
else:
|
||||||
|
new_args.append(arg)
|
||||||
args = new_args
|
args = new_args
|
||||||
|
|
||||||
# Send the args to the running session
|
# Send the args to the running session
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||||
<!--Generated with glade3 3.4.5 on Tue Sep 9 03:09:06 2008 -->
|
<!--Generated with glade3 3.4.5 on Thu Sep 11 23:06:35 2008 -->
|
||||||
<glade-interface>
|
<glade-interface>
|
||||||
<widget class="GtkDialog" id="dialog_add_torrent">
|
<widget class="GtkDialog" id="dialog_add_torrent">
|
||||||
<property name="height_request">560</property>
|
<property name="height_request">560</property>
|
||||||
|
@ -255,39 +255,6 @@
|
||||||
<property name="position">2</property>
|
<property name="position">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</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>
|
<child>
|
||||||
<widget class="GtkButton" id="button_remove">
|
<widget class="GtkButton" id="button_remove">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -331,7 +298,7 @@
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">False</property>
|
<property name="fill">False</property>
|
||||||
<property name="position">4</property>
|
<property name="position">3</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -571,7 +538,7 @@
|
||||||
<property name="n_columns">2</property>
|
<property name="n_columns">2</property>
|
||||||
<property name="column_spacing">10</property>
|
<property name="column_spacing">10</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkSpinButton" id="spin_maxupslots">
|
<widget class="GtkSpinButton" id="spin_maxdown">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">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="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
@ -581,26 +548,61 @@
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
<property name="left_attach">1</property>
|
||||||
<property name="right_attach">2</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="x_options"></property>
|
||||||
<property name="y_options"></property>
|
<property name="y_options"></property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkSpinButton" id="spin_maxconnections">
|
<widget class="GtkLabel" id="label11">
|
||||||
<property name="visible">True</property>
|
<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="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="xalign">0</property>
|
||||||
<property name="adjustment">-1 -1 9999 1 10 10</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>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
|
||||||
<property name="right_attach">2</property>
|
|
||||||
<property name="top_attach">2</property>
|
<property name="top_attach">2</property>
|
||||||
<property name="bottom_attach">3</property>
|
<property name="bottom_attach">3</property>
|
||||||
<property name="x_options"></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>
|
<property name="y_options"></property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
@ -623,61 +625,7 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkLabel" id="label14">
|
<widget class="GtkSpinButton" id="spin_maxconnections">
|
||||||
<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="visible">True</property>
|
||||||
<property name="can_focus">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="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
@ -687,6 +635,25 @@
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
<property name="left_attach">1</property>
|
||||||
<property name="right_attach">2</property>
|
<property name="right_attach">2</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="bottom_attach">3</property>
|
||||||
|
<property name="x_options"></property>
|
||||||
|
<property name="y_options"></property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<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>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="adjustment">-1 -1 9999 1 10 10</property>
|
||||||
|
</widget>
|
||||||
|
<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="x_options"></property>
|
||||||
<property name="y_options"></property>
|
<property name="y_options"></property>
|
||||||
</packing>
|
</packing>
|
||||||
|
@ -1145,11 +1112,11 @@
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="GtkDialog" id="dialog_magnet">
|
<widget class="GtkDialog" id="dialog_infohash">
|
||||||
<property name="width_request">462</property>
|
<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="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="border_width">5</property>
|
||||||
<property name="title" translatable="yes">Add Magnet URI</property>
|
<property name="title" translatable="yes">Add Infohash</property>
|
||||||
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
|
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
|
||||||
<property name="destroy_with_parent">True</property>
|
<property name="destroy_with_parent">True</property>
|
||||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
||||||
|
@ -1174,6 +1141,7 @@
|
||||||
<widget class="GtkImage" id="image_dialog_magnet">
|
<widget class="GtkImage" id="image_dialog_magnet">
|
||||||
<property name="visible">True</property>
|
<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="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="stock">gtk-revert-to-saved</property>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
@ -1184,7 +1152,7 @@
|
||||||
<widget class="GtkLabel" id="label16">
|
<widget class="GtkLabel" id="label16">
|
||||||
<property name="visible">True</property>
|
<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="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="label" translatable="yes"><b>From Infohash</b></property>
|
||||||
<property name="use_markup">True</property>
|
<property name="use_markup">True</property>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
|
@ -1218,7 +1186,7 @@
|
||||||
<widget class="GtkLabel" id="label23">
|
<widget class="GtkLabel" id="label23">
|
||||||
<property name="visible">True</property>
|
<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="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>
|
<property name="label" translatable="yes">Infohash:</property>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
@ -1226,7 +1194,7 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkEntry" id="entry_magnet">
|
<widget class="GtkEntry" id="entry_hash">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="has_focus">True</property>
|
<property name="has_focus">True</property>
|
||||||
|
@ -1245,6 +1213,44 @@
|
||||||
<property name="position">2</property>
|
<property name="position">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkHBox" id="hbox15">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="spacing">5</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkLabel" id="label22">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="yalign">0</property>
|
||||||
|
<property name="label" translatable="yes">Trackers:</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkScrolledWindow" id="scrolledwindow3">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||||
|
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||||
|
<property name="shadow_type">GTK_SHADOW_IN</property>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkTextView" id="text_trackers">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="position">3</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
|
|
|
@ -88,6 +88,7 @@ def process_args(args):
|
||||||
return
|
return
|
||||||
config = ConfigManager("gtkui.conf")
|
config = ConfigManager("gtkui.conf")
|
||||||
for arg in args:
|
for arg in args:
|
||||||
|
log.debug("arg: %s", arg)
|
||||||
if deluge.common.is_url(arg):
|
if deluge.common.is_url(arg):
|
||||||
log.debug("Attempting to add %s from external source..",
|
log.debug("Attempting to add %s from external source..",
|
||||||
arg)
|
arg)
|
||||||
|
@ -95,7 +96,14 @@ def process_args(args):
|
||||||
component.get("AddTorrentDialog").add_from_url(arg)
|
component.get("AddTorrentDialog").add_from_url(arg)
|
||||||
component.get("AddTorrentDialog").show(config["focus_add_dialog"])
|
component.get("AddTorrentDialog").show(config["focus_add_dialog"])
|
||||||
else:
|
else:
|
||||||
client.add_torrent_url(arg)
|
client.add_torrent_url(arg, None)
|
||||||
|
elif deluge.common.is_magnet(arg):
|
||||||
|
log.debug("Attempting to add %s from external source..", arg)
|
||||||
|
if config["interactive_add"]:
|
||||||
|
component.get("AddTorrentDialog").add_from_magnets([arg])
|
||||||
|
component.get("AddTorrentDialog").show(config["focus_add_dialog"])
|
||||||
|
else:
|
||||||
|
client.add_torrent_magnets([arg], [])
|
||||||
else:
|
else:
|
||||||
# Just a file
|
# Just a file
|
||||||
log.debug("Attempting to add %s from external source..",
|
log.debug("Attempting to add %s from external source..",
|
||||||
|
|
|
@ -168,11 +168,24 @@ class QueuedTorrents(component.Component):
|
||||||
# Add all the torrents in the liststore
|
# Add all the torrents in the liststore
|
||||||
def add_torrent(model, path, iter, data):
|
def add_torrent(model, path, iter, data):
|
||||||
torrent_path = model.get_value(iter, 1)
|
torrent_path = model.get_value(iter, 1)
|
||||||
if self.config["interactive_add"]:
|
if deluge.common.is_url(torrent_path):
|
||||||
component.get("AddTorrentDialog").add_from_files([torrent_path])
|
if self.config["interactive_add"]:
|
||||||
component.get("AddTorrentDialog").show(self.config["focus_add_dialog"])
|
component.get("AddTorrentDialog").add_from_url(torrent_path)
|
||||||
|
component.get("AddTorrentDialog").show(self.config["focus_add_dialog"])
|
||||||
|
else:
|
||||||
|
client.add_torrent_url(torrent_path, None)
|
||||||
|
elif deluge.common.is_magnet(torrent_path):
|
||||||
|
if self.config["interactive_add"]:
|
||||||
|
component.get("AddTorrentDialog").add_from_magnets([torrent_path])
|
||||||
|
component.get("AddTorrentDialog").show(self.config["focus_add_dialog"])
|
||||||
|
else:
|
||||||
|
client.add_magnet_uris([torrent_path], [])
|
||||||
else:
|
else:
|
||||||
client.add_torrent_file([torrent_path])
|
if self.config["interactive_add"]:
|
||||||
|
component.get("AddTorrentDialog").add_from_files([torrent_path])
|
||||||
|
component.get("AddTorrentDialog").show(self.config["focus_add_dialog"])
|
||||||
|
else:
|
||||||
|
client.add_torrent_file([torrent_path])
|
||||||
|
|
||||||
self.liststore.foreach(add_torrent, None)
|
self.liststore.foreach(add_torrent, None)
|
||||||
del self.queue[:]
|
del self.queue[:]
|
||||||
|
|
Loading…
Reference in New Issue