#2093: [win32] 'open-with' does not work for non-acsii torrents
------------------------+---------------------------------------------------
Reporter: IAmTheClaw | Owner: Cas
Type: bug | Status: assigned
Priority: minor | Milestone: 1.3.6
Component: core | Version: 1.3.5
Keywords: |
------------------------+---------------------------------------------------
Comment(by gazpachoking):
This seems to work, tested on Windows 7 x64. Some other people should test
it though, I'm never quite sure with this encoding stuff.
{{{
#!diff
Index: deluge/ui/gtkui/addtorrentdialog.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP
<+>#\n# addtorrentdialog.py\n#\n# Copyright (C) 2007 Andrew Resch
<[email protected]>\n#\n# Deluge is free software.\n#\n# You may
redistribute it and/or modify it under the terms of the\n# GNU General
Public License, as published by the Free Software\n# Foundation; either
version 3 of the License, or (at your option)\n# any later version.\n#\n#
deluge is distributed in the hope that it will be useful,\n# but WITHOUT
ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.\n# See the GNU General Public License
for more details.\n#\n# You should have received a copy of the GNU General
Public License\n# along with deluge. If not, write to:\n# The Free
Software Foundation, Inc.,\n# 51 Franklin Street, Fifth Floor\n#
Boston, MA 02110-1301, USA.\n#\n# In addition, as a special exception,
the copyright holders give\n# permission to link the code of portions
of this program with the OpenSSL\n# library.\n# You must obey the
GNU General Public License in all respects for all of\n# the code used
other than OpenSSL. If you modify file(s) with this\n# exception, you
may extend this exception to your version of the file(s),\n# but you
are not obligated to do so. If you do not wish to do so, delete\n# this
exception statement from your version. If you delete this exception\n#
statement from all source files in the program, then also delete it
here.\n#\n#\n\n\nimport pygtk\npygtk.require('2.0')\nimport gtk\nimport
gobject\nimport base64\nimport logging\nimport os\nfrom urlparse import
urljoin\n\nimport twisted.web.client\nimport twisted.web.error\nfrom
deluge.ui.client import client\nfrom deluge.httpdownloader import
download_file\nimport deluge.component as component\nimport listview\nfrom
deluge.configmanager import ConfigManager\nimport deluge.common\nimport
deluge.ui.common\nimport dialogs\nimport common\n\nlog =
logging.getLogger(__name__)\n\nclass
AddTorrentDialog(component.Component):\n def __init__(self):\n
component.Component.__init__(self, \"AddTorrentDialog\")\n
self.builder = gtk.Builder()\n # The base dialog\n
self.builder.add_from_file(deluge.common.resource_filename(\n
\"deluge.ui.gtkui\", os.path.join(\"glade\", \"add_torrent_dialog.ui\")\n
))\n # The infohash dialog\n
self.builder.add_from_file(deluge.common.resource_filename(\n
\"deluge.ui.gtkui\", os.path.join(\"glade\",
\"add_torrent_dialog.infohash.ui\")\n ))\n # The url
dialog\n
self.builder.add_from_file(deluge.common.resource_filename(\n
\"deluge.ui.gtkui\", os.path.join(\"glade\",
\"add_torrent_dialog.url.ui\")\n ))\n\n self.dialog =
self.builder.get_object(\"dialog_add_torrent\")\n\n
self.dialog.connect(\"delete-event\", self._on_delete_event)\n\n
self.builder.connect_signals({\n \"on_button_file_clicked\":
self._on_button_file_clicked,\n \"on_button_url_clicked\":
self._on_button_url_clicked,\n \"on_button_hash_clicked\":
self._on_button_hash_clicked,\n \"on_button_remove_clicked\":
self._on_button_remove_clicked,\n
\"on_button_trackers_clicked\": self._on_button_trackers_clicked,\n
\"on_button_cancel_clicked\": self._on_button_cancel_clicked,\n
\"on_button_add_clicked\": self._on_button_add_clicked,\n
\"on_button_apply_clicked\": self._on_button_apply_clicked,\n
\"on_button_revert_clicked\": self._on_button_revert_clicked,\n
\"on_alocation_toggled\": self._on_alocation_toggled,\n
\"on_chk_move_completed_toggled\": self._on_chk_move_completed_toggled\n
})\n\n self.torrent_liststore = gtk.ListStore(str, str, str)\n
#download?, path, filesize, sequence number, inconsistent?\n
self.files_treestore = gtk.TreeStore(bool, str, gobject.TYPE_UINT64,\n
gobject.TYPE_INT64, bool, str)\n
self.files_treestore.set_sort_column_id(1, gtk.SORT_ASCENDING)\n\n
# Holds the files info\n self.files = {}\n self.infos = {}\n
self.core_config = {}\n self.options = {}\n\n
self.previous_selected_torrent = None\n\n\n self.listview_torrents
= self.builder.get_object(\"listview_torrents\")\n
self.listview_files = self.builder.get_object(\"listview_files\")\n\n
render = gtk.CellRendererText()\n column =
gtk.TreeViewColumn(_(\"Torrent\"), render, text=1)\n
self.listview_torrents.append_column(column)\n\n render =
gtk.CellRendererToggle()\n render.connect(\"toggled\",
self._on_file_toggled)\n column = gtk.TreeViewColumn(None, render,
active=0, inconsistent=4)\n
self.listview_files.append_column(column)\n\n column =
gtk.TreeViewColumn(_(\"Filename\"))\n render =
gtk.CellRendererPixbuf()\n column.pack_start(render, False)\n
column.add_attribute(render, \"stock-id\", 5)\n render =
gtk.CellRendererText()\n render.set_property(\"editable\", True)\n
render.connect(\"edited\", self._on_filename_edited)\n
column.pack_start(render, True)\n column.add_attribute(render,
\"text\", 1)\n column.set_expand(True)\n
self.listview_files.append_column(column)\n\n render =
gtk.CellRendererText()\n column = gtk.TreeViewColumn(_(\"Size\"))\n
column.pack_start(render)\n column.set_cell_data_func(render,
listview.cell_data_size, 2)\n
self.listview_files.append_column(column)\n\n
self.listview_torrents.set_model(self.torrent_liststore)\n
self.listview_files.set_model(self.files_treestore)\n\n
self.listview_files.get_selection().set_mode(gtk.SELECTION_MULTIPLE)\n
self.listview_torrents.get_selection().connect(\"changed\",\n
self._on_torrent_changed)\n\n # Get default config values from the
core\n self.core_keys = [\n \"compact_allocation\",\n
\"max_connections_per_torrent\",\n
\"max_upload_slots_per_torrent\",\n
\"max_upload_speed_per_torrent\",\n
\"max_download_speed_per_torrent\",\n
\"prioritize_first_last_pieces\",\n \"sequential_download\",\n
\"download_location\",\n \"add_paused\",\n
\"move_completed\",\n \"move_completed_path\"\n ]\n
self.core_config = {}\n\n
self.builder.get_object(\"notebook1\").connect(\"switch-page\",
self._on_switch_page)\n\n def start(self):\n
self.update_core_config()\n\n def show(self, focus=False):\n
return self.update_core_config(True, focus)\n\n def _show(self,
focus=False):\n if client.is_localhost():\n
self.builder.get_object(\"button_location\").show()\n
self.builder.get_object(\"entry_download_path\").hide()\n
self.builder.get_object(\"button_move_completed_location\").show()\n
self.builder.get_object(\"entry_move_completed_path\").hide()\n
else:\n self.builder.get_object(\"button_location\").hide()\n
self.builder.get_object(\"entry_download_path\").show()\n
self.builder.get_object(\"button_move_completed_location\").hide()\n
self.builder.get_object(\"entry_move_completed_path\").show()\n\n
self.dialog.set_transient_for(component.get(\"MainWindow\").window)\n
self.dialog.present()\n if focus:\n
self.dialog.window.focus()\n\n return None\n\n def hide(self):\n
self.dialog.hide()\n self.files = {}\n self.infos = {}\n
self.options = {}\n self.previous_selected_torrent = None\n
self.torrent_liststore.clear()\n self.files_treestore.clear()\n
self.dialog.set_transient_for(component.get(\"MainWindow\").window)\n
return None\n\n def update_core_config(self, show=False,
focus=False):\n def _on_config_values(config):\n
self.core_config = config\n self.set_default_options()\n
if show:\n self._show(focus)\n\n # Send requests to
the core for these config values\n return
client.core.get_config_values(self.core_keys).addCallback(_on_config_values)\n\n
def add_from_files(self, filenames):\n import os.path\n
new_row = None\n\n for filename in filenames:\n #
Convert the path to unicode\n filename = unicode(filename)\n\n
# Get the torrent data from the torrent file\n try:\n
info = deluge.ui.common.TorrentInfo(filename)\n except
Exception, e:\n log.debug(\"Unable to open torrent file:
%s\", e)\n dialogs.ErrorDialog(_(\"Invalid File\"), e,
self.dialog).run()\n continue\n\n if
info.info_hash in self.files:\n log.debug(\"Trying to add a
duplicate torrent!\")\n dialogs.ErrorDialog(\n
_(\"Duplicate Torrent\"),\n _(\"You cannot add the same
torrent twice.\"),\n self.dialog\n
).run()\n continue\n\n name = \"%s (%s)\" %
(info.name, os.path.split(filename)[-1])\n new_row =
self.torrent_liststore.append(\n [info.info_hash,
info.name, filename])\n self.files[info.info_hash] =
info.files\n self.infos[info.info_hash] = info.filedata\n
self.listview_torrents.get_selection().select_iter(new_row)\n\n
self.set_default_options()\n
self.save_torrent_options(new_row)\n\n (model, row) =
self.listview_torrents.get_selection().get_selected()\n if not row
and new_row:\n
self.listview_torrents.get_selection().select_iter(new_row)\n\n def
add_from_magnets(self, uris):\n import base64\n new_row =
None\n\n for uri in uris:\n s =
uri.split(\"&\")[0][20:]\n if len(s) == 32:\n
info_hash = base64.b32decode(s).encode(\"hex\")\n elif len(s)
== 40:\n info_hash = s\n if info_hash in
self.infos:\n log.debug(\"Torrent already in list!\")\n
continue\n name = None\n for i in
uri.split(\"&\"):\n if i[:3] == \"dn=\":\n
name = \"%s (%s)\" % (i.split(\"=\")[1], uri)\n if not name:\n
name = uri\n new_row = self.torrent_liststore.append(\n
[info_hash, name, uri])\n self.files[info_hash] = []\n
self.infos[info_hash] = None\n
self.listview_torrents.get_selection().select_iter(new_row)\n
self.set_default_options()\n
self.save_torrent_options(new_row)\n\n (model, row) =
self.listview_torrents.get_selection().get_selected()\n if not row
and new_row:\n
self.listview_torrents.get_selection().select_iter(new_row)\n\n def
_on_torrent_changed(self, treeselection):\n (model, row) =
treeselection.get_selected()\n if row is None or not
model.iter_is_valid(row):\n self.files_treestore.clear()\n
self.previous_selected_torrent = None\n return\n\n if
model[row][0] not in self.files:\n
self.files_treestore.clear()\n self.previous_selected_torrent =
None\n return\n\n # Save the previous torrents options\n
self.save_torrent_options()\n # Update files list\n
files_list = self.files[model.get_value(row, 0)]\n\n
self.prepare_file_store(files_list)\n\n if self.core_config ==
{}:\n self.update_core_config()\n\n # Update the options
frame\n self.update_torrent_options(model.get_value(row, 0))\n\n
self.previous_selected_torrent = row\n\n def _on_switch_page(self,
widget, page, page_num):\n # Save the torrent options when
switching notebook pages\n self.save_torrent_options()\n\n def
prepare_file_store(self, files):\n
self.listview_files.set_model(None)\n
self.files_treestore.clear()\n split_files = { }\n i = 0\n
for file in files:\n self.prepare_file(\n file,
file[\"path\"], i, file[\"download\"], split_files\n )\n
i += 1\n self.add_files(None, split_files)\n
self.listview_files.set_model(self.files_treestore)\n
self.listview_files.expand_row(\"0\", False)\n\n def prepare_file(self,
file, file_name, file_num, download, files_storage):\n
first_slash_index = file_name.find(os.path.sep)\n if
first_slash_index == -1:\n files_storage[file_name] =
(file_num, file, download)\n else:\n file_name_chunk =
file_name[:first_slash_index+1]\n if file_name_chunk not in
files_storage:\n files_storage[file_name_chunk] = { }\n
self.prepare_file(file, file_name[first_slash_index+1:],\n
file_num, download, files_storage[file_name_chunk])\n\n def
add_files(self, parent_iter, split_files):\n ret = 0\n for
key,value in split_files.iteritems():\n if
key.endswith(os.path.sep):\n chunk_iter =
self.files_treestore.append(parent_iter,\n
[True, key, 0, -1, False, gtk.STOCK_DIRECTORY])\n
chunk_size = self.add_files(chunk_iter, value)\n
self.files_treestore.set(chunk_iter, 2, chunk_size)\n ret
+= chunk_size\n else:\n
self.files_treestore.append(parent_iter, [\n value[2],
key, value[1][\"size\"],\n value[0], False,
gtk.STOCK_FILE\n ])\n\n if parent_iter and
self.files_treestore.iter_has_child(parent_iter):\n #
Iterate through the children and see what we should label the\n
# folder, download true, download false or inconsistent.\n
itr = self.files_treestore.iter_children(parent_iter)\n
download = []\n download_value = False\n
inconsistent = False\n while itr:\n
download.append(self.files_treestore.get_value(itr, 0))\n
itr = self.files_treestore.iter_next(itr)\n\n if
sum(download) == len(download):\n download_value =
True\n elif sum(download) == 0:\n
download_value = False\n else:\n
inconsistent = True\n\n
self.files_treestore.set_value(parent_iter, 0, download_value)\n
self.files_treestore.set_value(parent_iter, 4, inconsistent)\n\n
ret += value[1][\"size\"]\n return ret\n\n def
update_torrent_options(self, torrent_id):\n if torrent_id not in
self.options:\n self.set_default_options()\n
return\n\n options = self.options[torrent_id]\n\n if
client.is_localhost():\n
self.builder.get_object(\"button_location\").set_current_folder(\n
options[\"download_location\"])\n
self.builder.get_object(\"button_move_completed_location\").set_current_folder(\n
options[\"move_completed_path\"])\n else:\n
self.builder.get_object(\"entry_download_path\").set_text(\n
options[\"download_location\"])\n
self.builder.get_object(\"entry_move_completed_path\").set_text(\n
options[\"move_completed_path\"])\n\n
self.builder.get_object(\"radio_full\").set_active(\n not
options[\"compact_allocation\"])\n
self.builder.get_object(\"radio_compact\").set_active(\n
options[\"compact_allocation\"])\n
self.builder.get_object(\"spin_maxdown\").set_value(\n
options[\"max_download_speed\"])\n
self.builder.get_object(\"spin_maxup\").set_value(\n
options[\"max_upload_speed\"])\n
self.builder.get_object(\"spin_maxconnections\").set_value(\n
options[\"max_connections\"])\n
self.builder.get_object(\"spin_maxupslots\").set_value(\n
options[\"max_upload_slots\"])\n
self.builder.get_object(\"chk_paused\").set_active(\n
options[\"add_paused\"])\n
self.builder.get_object(\"chk_prioritize\").set_active(\n
options[\"prioritize_first_last_pieces\"])\n
self.builder.get_object(\"chk_sequential_download\").set_active(\n
options[\"sequential_download\"])\n
self.builder.get_object(\"chk_move_completed\").set_active(\n
options[\"move_completed\"])\n\n def save_torrent_options(self,
row=None):\n # Keeps the torrent options dictionary up-to-date with
what the user has\n # selected.\n if row is None:\n
if self.previous_selected_torrent and \\\n
self.torrent_liststore.iter_is_valid(self.previous_selected_torrent):\n
row = self.previous_selected_torrent\n else:\n
return\n\n torrent_id = self.torrent_liststore.get_value(row,
0)\n\n if torrent_id in self.options:\n options =
self.options[torrent_id]\n else:\n options = {}\n\n
if client.is_localhost():\n options[\"download_location\"] =
\\\n
self.builder.get_object(\"button_location\").get_filename()\n
options[\"move_completed_path\"] = \\\n
self.builder.get_object(\"button_move_completed_location\").get_filename()\n
else:\n options[\"download_location\"] = \\\n
self.builder.get_object(\"entry_download_path\").get_text()\n
options[\"move_completed_path\"] = \\\n
self.builder.get_object(\"entry_move_completed_path\").get_text()\n
options[\"compact_allocation\"] = \\\n
self.builder.get_object(\"radio_compact\").get_active()\n\n if
options[\"compact_allocation\"]:\n # We need to make sure all
the files are set to download\n def set_download_true(model,
path, itr):\n model[path][0] = True\n
self.files_treestore.foreach(set_download_true)\n
self.update_treeview_toggles(self.files_treestore.get_iter_first())\n\n
options[\"max_download_speed\"] = \\\n
self.builder.get_object(\"spin_maxdown\").get_value()\n
options[\"max_upload_speed\"] = \\\n
self.builder.get_object(\"spin_maxup\").get_value()\n
options[\"max_connections\"] = \\\n
self.builder.get_object(\"spin_maxconnections\").get_value_as_int()\n
options[\"max_upload_slots\"] = \\\n
self.builder.get_object(\"spin_maxupslots\").get_value_as_int()\n
options[\"add_paused\"] = \\\n
self.builder.get_object(\"chk_paused\").get_active()\n
options[\"prioritize_first_last_pieces\"] = \\\n
self.builder.get_object(\"chk_prioritize\").get_active()\n
options[\"sequential_download\"] = \\\n
self.builder.get_object(\"radio_full\").get_active() and \\\n
self.builder.get_object(\"chk_sequential_download\").get_active() or
False\n options[\"move_completed\"] = \\\n
self.builder.get_object(\"chk_move_completed\").get_active()\n\n
self.options[torrent_id] = options\n\n # Save the file priorities\n
files_priorities = self.build_priorities(\n
self.files_treestore.get_iter_first(), {}\n )\n\n if
len(files_priorities) > 0:\n for i, file_dict in
enumerate(self.files[torrent_id]):\n
file_dict[\"download\"] = files_priorities[i]\n\n def
build_priorities(self, iter, priorities):\n while iter is not
None:\n if self.files_treestore.iter_has_child(iter):\n
self.build_priorities(self.files_treestore.iter_children(iter),\n
priorities)\n elif not self.files_treestore.get_value(iter,
1).endswith(os.path.sep):\n
priorities[self.files_treestore.get_value(iter, 3)] = \\\n
self.files_treestore.get_value(iter, 0)\n iter =
self.files_treestore.iter_next(iter)\n return priorities\n\n def
set_default_options(self):\n if client.is_localhost():\n
self.builder.get_object(\"button_location\").set_current_folder(\n
self.core_config[\"download_location\"])\n
self.builder.get_object(\"button_move_completed_location\").set_current_folder(\n
self.core_config[\"move_completed_path\"])\n else:\n
self.builder.get_object(\"entry_download_path\").set_text(\n
self.core_config[\"download_location\"])\n
self.builder.get_object(\"entry_move_completed_path\").set_text(\n
self.core_config[\"move_completed_path\"])\n\n
self.builder.get_object(\"radio_compact\").set_active(\n
self.core_config[\"compact_allocation\"])\n
self.builder.get_object(\"radio_full\").set_active(\n not
self.core_config[\"compact_allocation\"])\n
self.builder.get_object(\"spin_maxdown\").set_value(\n
self.core_config[\"max_download_speed_per_torrent\"])\n
self.builder.get_object(\"spin_maxup\").set_value(\n
self.core_config[\"max_upload_speed_per_torrent\"])\n
self.builder.get_object(\"spin_maxconnections\").set_value(\n
self.core_config[\"max_connections_per_torrent\"])\n
self.builder.get_object(\"spin_maxupslots\").set_value(\n
self.core_config[\"max_upload_slots_per_torrent\"])\n
self.builder.get_object(\"chk_paused\").set_active(\n
self.core_config[\"add_paused\"])\n
self.builder.get_object(\"chk_prioritize\").set_active(\n
self.core_config[\"prioritize_first_last_pieces\"])\n
self.builder.get_object(\"chk_sequential_download\").set_active(\n
self.core_config[\"sequential_download\"])\n
self.builder.get_object(\"chk_move_completed\").set_active(\n
self.core_config[\"move_completed\"])\n\n def get_file_priorities(self,
torrent_id):\n # A list of priorities\n files_list = []\n\n
for file_dict in self.files[torrent_id]:\n if not
file_dict[\"download\"]:\n files_list.append(0)\n
else:\n files_list.append(1)\n\n return
files_list\n\n def _on_file_toggled(self, render, path):\n #
Check to see if we can change file priorities\n (model, row) =
self.listview_torrents.get_selection().get_selected()\n if
self.options[model[row][0]][\"compact_allocation\"]:\n def
on_answer(response):\n if response == gtk.RESPONSE_YES:\n
self.options[model[row][0]][\"compact_allocation\"] = False\n
self.update_torrent_options(model[row][0])\n\n d =
dialogs.YesNoDialog(\n _(\"Unable to set file
priority!\"),\n _(\"File prioritization is unavailable when
using Compact \"\n \"allocation. Would you like to
switch to Full allocation?\"),\n self.dialog\n
).run()\n d.addCallback(on_answer)\n\n return\n
(model, paths) = self.listview_files.get_selection().get_selected_rows()\n
if len(paths) > 1:\n for path in paths:\n row =
model.get_iter(path)\n self.toggle_iter(row)\n
else:\n row = model.get_iter(path)\n
self.toggle_iter(row)\n
self.update_treeview_toggles(self.files_treestore.get_iter_first())\n\n
def toggle_iter(self, iter, toggle_to=None):\n if toggle_to is
None:\n toggle_to = not self.files_treestore.get_value(iter,
0)\n self.files_treestore.set_value(iter, 0, toggle_to)\n if
self.files_treestore.iter_has_child(iter):\n child =
self.files_treestore.iter_children(iter)\n while child is not
None:\n self.toggle_iter(child, toggle_to)\n
child = self.files_treestore.iter_next(child)\n\n def
update_treeview_toggles(self, iter):\n TOGGLE_INCONSISTENT = -1\n
this_level_toggle = None\n while iter is not None:\n if
self.files_treestore.iter_has_child(iter):\n toggle =
self.update_treeview_toggles(\n
self.files_treestore.iter_children(iter))\n if toggle ==
TOGGLE_INCONSISTENT:\n
self.files_treestore.set_value(iter, 4, True)\n else:\n
self.files_treestore.set_value(iter, 0, toggle)\n #set
inconsistent to false\n
self.files_treestore.set_value(iter, 4, False)\n else:\n
toggle = self.files_treestore.get_value(iter, 0)\n if
this_level_toggle is None:\n this_level_toggle = toggle\n
elif this_level_toggle != toggle:\n this_level_toggle =
TOGGLE_INCONSISTENT\n iter =
self.files_treestore.iter_next(iter)\n return this_level_toggle\n\n
def _on_button_file_clicked(self, widget):\n
log.debug(\"_on_button_file_clicked\")\n # Setup the
filechooserdialog\n chooser = gtk.FileChooserDialog(\n
_(\"Choose a .torrent file\"),\n None,\n
gtk.FILE_CHOOSER_ACTION_OPEN,\n buttons=(gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN,\n
gtk.RESPONSE_OK)\n )\n\n
chooser.set_transient_for(self.dialog)\n
chooser.set_select_multiple(True)\n chooser.set_property(\"skip-
taskbar-hint\", True)\n chooser.set_local_only(False)\n\n #
Add .torrent and * file filters\n file_filter = gtk.FileFilter()\n
file_filter.set_name(_(\"Torrent files\"))\n
file_filter.add_pattern(\"*.\" + \"torrent\")\n
chooser.add_filter(file_filter)\n file_filter = gtk.FileFilter()\n
file_filter.set_name(_(\"All files\"))\n
file_filter.add_pattern(\"*\")\n
chooser.add_filter(file_filter)\n\n # Load the 'default_load_path'
from the config\n self.config = ConfigManager(\"gtkui.conf\")\n
if self.config[\"default_load_path\"] is not None:\n
chooser.set_current_folder(self.config[\"default_load_path\"])\n\n
# Run the dialog\n response = chooser.run()\n\n if response
== gtk.RESPONSE_OK:\n result = chooser.get_filenames()\n
self.config[\"default_load_path\"] = chooser.get_current_folder()\n
else:\n chooser.destroy()\n return\n\n
chooser.destroy()\n self.add_from_files(result)\n\n def
_on_button_url_clicked(self, widget):\n
log.debug(\"_on_button_url_clicked\")\n dialog =
self.builder.get_object(\"url_dialog\")\n entry =
self.builder.get_object(\"entry_url\")\n\n
dialog.set_default_response(gtk.RESPONSE_OK)\n
dialog.set_transient_for(self.dialog)\n entry.grab_focus()\n\n
text = (gtk.clipboard_get(selection='PRIMARY').wait_for_text() or\n
gtk.clipboard_get().wait_for_text())\n if text:\n text =
text.strip()\n if deluge.common.is_url(text) or
deluge.common.is_magnet(text):\n entry.set_text(text)\n\n
dialog.show_all()\n response = dialog.run()\n\n if response
== gtk.RESPONSE_OK:\n url =
entry.get_text().decode(\"utf-8\")\n else:\n url =
None\n\n entry.set_text(\"\")\n dialog.hide()\n\n #
This is where we need to fetch the .torrent file from the URL and\n
# add it to the list.\n log.debug(\"url: %s\", url)\n if
url:\n if deluge.common.is_url(url):\n
self.add_from_url(url)\n elif deluge.common.is_magnet(url):\n
self.add_from_magnets([url])\n else:\n
dialogs.ErrorDialog(\n _(\"Invalid URL\"),\n
\"%s %s\" % (url, _(\"is not a valid URL.\")),\n
self.dialog\n ).run()\n\n def add_from_url(self, url):\n
dialog = gtk.Dialog(\n _(\"Downloading...\"),\n
flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT |
gtk.DIALOG_NO_SEPARATOR,\n parent=self.dialog)\n
dialog.set_transient_for(self.dialog)\n\n pb = gtk.ProgressBar()\n
dialog.vbox.pack_start(pb, True, True)\n dialog.show_all()\n\n
# Create a tmp file path\n import tempfile\n import
os.path\n tmp_file = os.path.join(tempfile.gettempdir(),
url.split(\"/\")[-1])\n\n def on_part(data, current_length,
total_length):\n if total_length:\n percent =
float(current_length) / float(total_length)\n
pb.set_fraction(percent)\n pb.set_text(\"%.2f%% (%s / %s)\"
% (\n percent * 100,\n
deluge.common.fsize(current_length),\n
deluge.common.fsize(total_length)))\n else:\n
pb.pulse()\n pb.set_text(\"%s\" %
deluge.common.fsize(current_length))\n\n def
on_download_success(result):\n log.debug(\"Download
success!\")\n self.add_from_files([result])\n
dialog.destroy()\n\n def on_download_fail(result):\n if
result.check(twisted.web.error.PageRedirect):\n new_url =
urljoin(url, result.getErrorMessage().split(\" to \")[1])\n
result = download_file(new_url, tmp_file, on_part)\n
result.addCallbacks(on_download_success, on_download_fail)\n
elif result.check(twisted.web.client.PartialDownloadError):\n
result = download_file(url, tmp_file, on_part, allow_compression=False)\n
result.addCallbacks(on_download_success, on_download_fail)\n
else:\n log.debug(\"Download failed: %s\", result)\n
dialog.destroy()\n dialogs.ErrorDialog(\n
_(\"Download Failed\"), \"%s %s\" % (_(\"Failed to download:\"), url),\n
details=result.getErrorMessage(), parent=self.dialog\n
).run()\n return result\n\n d = download_file(url,
tmp_file, on_part)\n d.addCallbacks(on_download_success,
on_download_fail)\n\n def _on_button_hash_clicked(self, widget):\n
log.debug(\"_on_button_hash_clicked\")\n dialog =
self.builder.get_object(\"dialog_infohash\")\n entry =
self.builder.get_object(\"entry_hash\")\n textview =
self.builder.get_object(\"text_trackers\")\n\n
dialog.set_default_response(gtk.RESPONSE_OK)\n
dialog.set_transient_for(self.dialog)\n entry.grab_focus()\n
dialog.show_all()\n response = dialog.run()\n if response ==
gtk.RESPONSE_OK and len(entry.get_text()) == 40:\n trackers =
[]\n b = textview.get_buffer()\n lines =
b.get_text(b.get_start_iter(), b.get_end_iter()).strip().split(\"\\n\")\n
log.debug(\"lines: %s\", lines)\n for l in lines:\n
if deluge.common.is_url(l):\n trackers.append(l)\n
# Convert the information to a magnet uri, this is just easier to\n
# handle this way.\n log.debug(\"trackers: %s\", trackers)\n
magnet = deluge.common.create_magnet_uri(\n
infohash=entry.get_text().decode(\"utf-8\"),\n
trackers=trackers)\n log.debug(\"magnet uri: %s\", magnet)\n
self.add_from_magnets([magnet])\n\n entry.set_text(\"\")\n
textview.get_buffer().set_text(\"\")\n dialog.hide()\n\n def
_on_button_remove_clicked(self, widget):\n
log.debug(\"_on_button_remove_clicked\")\n (model, row) =
self.listview_torrents.get_selection().get_selected()\n if row is
None:\n return\n\n torrent_id = model.get_value(row,
0)\n\n model.remove(row)\n del self.files[torrent_id]\n
del self.infos[torrent_id]\n\n def _on_button_trackers_clicked(self,
widget):\n log.debug(\"_on_button_trackers_clicked\")\n\n def
_on_button_cancel_clicked(self, widget):\n
log.debug(\"_on_button_cancel_clicked\")\n self.hide()\n\n def
_on_button_add_clicked(self, widget):\n
log.debug(\"_on_button_add_clicked\")\n # Save the options for
selected torrent prior to adding\n (model, row) =
self.listview_torrents.get_selection().get_selected()\n if row is
not None:\n self.save_torrent_options(row)\n\n row =
self.torrent_liststore.get_iter_first()\n while row != None:\n
torrent_id = self.torrent_liststore.get_value(row, 0)\n
filename = self.torrent_liststore.get_value(row, 2)\n try:\n
options = self.options[torrent_id]\n except KeyError:\n
options = None\n\n file_priorities =
self.get_file_priorities(torrent_id)\n if options != None:\n
options[\"file_priorities\"] = file_priorities\n\n if
deluge.common.is_magnet(filename):\n del
options[\"file_priorities\"]\n
client.core.add_torrent_magnet(filename, options)\n else:\n
client.core.add_torrent_file(\n
os.path.split(filename)[-1],\n
base64.encodestring(self.infos[torrent_id]),\n
options)\n\n row = self.torrent_liststore.iter_next(row)\n\n
self.hide()\n\n def _on_button_apply_clicked(self, widget):\n
log.debug(\"_on_button_apply_clicked\")\n (model, row) =
self.listview_torrents.get_selection().get_selected()\n if row is
None:\n return\n\n self.save_torrent_options(row)\n\n
# The options we want all the torrents to have\n options =
self.options[model.get_value(row, 0)]\n\n # Set all the torrent
options\n row = model.get_iter_first()\n while row !=
None:\n torrent_id = model.get_value(row, 0)\n
self.options[torrent_id] = options\n row =
model.iter_next(row)\n\n def _on_button_revert_clicked(self, widget):\n
log.debug(\"_on_button_revert_clicked\")\n (model, row) =
self.listview_torrents.get_selection().get_selected()\n if row is
None:\n return\n\n del self.options[model.get_value(row,
0)]\n self.set_default_options()\n\n def
_on_chk_move_completed_toggled(self, widget):\n value =
widget.get_active()\n
self.builder.get_object(\"button_move_completed_location\").set_sensitive(value)\n
self.builder.get_object(\"entry_move_completed_path\").set_sensitive(value)\n\n
def _on_delete_event(self, widget, event):\n self.hide()\n
return True\n\n def get_file_path(self, row, path=\"\"):\n if
not row:\n return path\n\n path =
self.files_treestore[row][1] + path\n return
self.get_file_path(self.files_treestore.iter_parent(row), path)\n\n def
_on_filename_edited(self, renderer, path, new_text):\n index =
self.files_treestore[path][3]\n\n new_text =
new_text.strip(os.path.sep)\n\n # Return if the text hasn't
changed\n if new_text == self.files_treestore[path][1]:\n
return\n\n # Get the tree iter\n itr =
self.files_treestore.get_iter(path)\n\n # Get the torrent_id\n
(model, row) = self.listview_torrents.get_selection().get_selected()\n
torrent_id = model[row][0]\n\n if \"mapped_files\" not in
self.options[torrent_id]:\n
self.options[torrent_id][\"mapped_files\"] = {}\n\n if index >
-1:\n # We're renaming a file! Yay! That's easy!\n
parent = self.files_treestore.iter_parent(itr)\n file_path =
os.path.join(self.get_file_path(parent), new_text)\n\n if
os.path.sep in new_text:\n # There are folders in this
path, so we need to create them\n # and then move the file
iter to top\n split_text = new_text.split(os.path.sep)\n
for s in split_text[:-1]:\n parent =
self.files_treestore.append(parent,\n
[True, s, 0, -1, False, gtk.STOCK_DIRECTORY])\n\n
self.files_treestore[itr][1] = split_text[-1]\n
common.reparent_iter(self.files_treestore, itr, parent)\n
else:\n # Update the row's text\n
self.files_treestore[itr][1] = new_text\n\n # Update the
mapped_files dict in the options with the index and new\n #
file path.\n # We'll send this to the core when adding the
torrent so it knows\n # what to rename before adding.\n
self.options[torrent_id][\"mapped_files\"][index] = file_path\n
self.files[torrent_id][index]['path'] = file_path\n else:\n
# Folder!\n def walk_tree(row):\n if not row:\n
return\n\n # Get the file path base once, since it will be
the same for\n # all siblings\n
file_path_base = self.get_file_path(\n
self.files_treestore.iter_parent(row)\n )\n\n
# Iterate through all the siblings at this level\n while
row:\n # We recurse if there are children\n
if self.files_treestore.iter_has_child(row):\n
walk_tree(self.files_treestore.iter_children(row))\n\n
index = self.files_treestore[row][3]\n\n if index >
-1:\n # Get the new full path for this file\n
file_path = file_path_base + self.files_treestore[row][1]\n\n
# Update the file path in the mapped_files dict\n
self.options[torrent_id][\"mapped_files\"][index] = file_path\n
self.files[torrent_id][index]['path'] = file_path\n\n #
Get the next siblings iter\n row =
self.files_treestore.iter_next(row)\n\n # Update the treestore
row first so that when walking the tree\n # we can construct
the new proper paths\n\n # We need to check if this folder has
been split\n if os.path.sep in new_text:\n #
It's been split, so we need to add new folders and then re-parent\n
# itr.\n parent = self.files_treestore.iter_parent(itr)\n
split_text = new_text.split(os.path.sep)\n for s in
split_text[:-1]:\n # We don't iterate over the last
item because we'll just use\n # the existing itr and
change the text\n parent =
self.files_treestore.append(parent, [\n True, s +
os.path.sep, 0, -1, False, gtk.STOCK_DIRECTORY\n ])\n\n
self.files_treestore[itr][1] = split_text[-1] + os.path.sep\n\n
# Now re-parent itr to parent\n
common.reparent_iter(self.files_treestore, itr, parent)\n
itr = parent\n\n # We need to re-expand the view because it
might contracted\n # if we change the root iter\n
self.listview_files.expand_row(\"0\", False)\n else:\n
# This was a simple folder rename without any splits, so just\n
# change the path for itr\n self.files_treestore[itr][1] =
new_text + os.path.sep\n\n # Walk through the tree from 'itr'
and add all the new file paths\n # to the 'mapped_files'
option\n walk_tree(itr)\n\n def _on_alocation_toggled(self,
widget):\n full_allocation_active =
self.builder.get_object(\"radio_full\").get_active()\n
self.builder.get_object(\"chk_prioritize\").set_sensitive(full_allocation_active)\n
self.builder.get_object(\"chk_sequential_download\").set_sensitive(full_allocation_active)\n
===================================================================
--- deluge/ui/gtkui/addtorrentdialog.py (revision
0c1dd44cd66dde63bfd33b6eb58d90342cefcb64)
+++ deluge/ui/gtkui/addtorrentdialog.py (revision )
@@ -41,6 +41,7 @@
import base64
import logging
import os
+import sys
from urlparse import urljoin
import twisted.web.client
@@ -214,7 +215,7 @@
for filename in filenames:
# Convert the path to unicode
- filename = unicode(filename)
+ filename = unicode(filename, sys.getfilesystemencoding())
# Get the torrent data from the torrent file
try:
}}}
--
Ticket URL: <http://dev.deluge-torrent.org/ticket/2093#comment:4>
Deluge <http://deluge-torrent.org/>
Deluge project
--
You received this message because you are subscribed to the Google Groups
"Deluge Dev" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/deluge-dev?hl=en.