#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.

Reply via email to