diff options
| author | Jonathan McCrohan <jmccrohan@gmail.com> | 2013-03-22 21:26:55 +0000 | 
|---|---|---|
| committer | Jonathan McCrohan <jmccrohan@gmail.com> | 2013-03-22 21:26:55 +0000 | 
| commit | 9a91a98255fd67175130915a6b519f080d9f7aa8 (patch) | |
| tree | 46b93ee79f63961926cb5e639ecddda93c719386 | |
| parent | f2c42d2c57feb8cc7cfca8dfdd9d1ee2ca788c81 (diff) | |
| download | transmission-remote-cli-9a91a98255fd67175130915a6b519f080d9f7aa8.tar.gz | |
Imported Upstream version 1.5.0upstream/1.5.0
| -rw-r--r-- | NEWS | 15 | ||||
| -rw-r--r-- | README.md | 2 | ||||
| -rwxr-xr-x | transmission-remote-cli | 275 | 
3 files changed, 217 insertions, 75 deletions
@@ -1,3 +1,18 @@ +1.5.0  2013-03-21 +    BUGFIXES: +        - Torrents should no longer become 'isolated' for seemingly no reason + +    - Support for Transmission version 2.80 +    - Open files with 'xdg-open' (or something else) +    - Limited support for queues (increase/decrease, sort) +    - Better performance when scrolling through many torrents +    - Submit torrents to daemon via RPC request, not file path +    - Tab completion for files and directories +    - Ctrl+u deletes from cursor to beginning in dialogs +    - Peer download rate estimates become invalid after 60 seconds without +      update + +  1.4.7  2013-01-10      - Support for Transmission version 2.76 @@ -5,7 +5,7 @@ A console client for the BitTorrent client [Transmission](http://www.transmissio  ## Distributions -- [Arch Linux](https://aur.archlinux.org/packages.php?K=transmission-remote-cli) +- [Arch Linux](https://www.archlinux.org/packages/community/any/transmission-remote-cli/)  - [Debian](http://packages.debian.org/search?keywords=transmission-remote-cli)  - [Fedora](https://admin.fedoraproject.org/pkgdb/acls/list/?searchwords=transmission-remote-cli)  - [OpenSUSE](http://software.opensuse.org/package/transmission-remote-cli?search_term=transmission-remote-cli) diff --git a/transmission-remote-cli b/transmission-remote-cli index 75c20d3..da494c7 100755 --- a/transmission-remote-cli +++ b/transmission-remote-cli @@ -16,12 +16,12 @@  # http://www.gnu.org/licenses/gpl-3.0.txt                              #  ######################################################################## -VERSION = '1.4.7' +VERSION = '1.5.0'  TRNSM_VERSION_MIN = '1.90' -TRNSM_VERSION_MAX = '2.76' +TRNSM_VERSION_MAX = '2.80'  RPC_VERSION_MIN = 8 -RPC_VERSION_MAX = 14 +RPC_VERSION_MAX = 15  # error codes  CONNECTION_ERROR = 1 @@ -58,8 +58,9 @@ import locale  import curses  import curses.ascii  from textwrap import wrap -from subprocess import call +from subprocess import call, Popen  import netrc +import glob  # optional features provided by non-standard modules @@ -114,6 +115,7 @@ config.set('Filtering', 'invert', 'False')  config.add_section('Misc')  config.set('Misc', 'compact_list', 'False')  config.set('Misc', 'torrentname_is_progressbar', 'True') +config.set('Misc', 'file_viewer', 'xdg-open %%s')  config.add_section('Colors')  config.set('Colors', 'title_seed',       'bg:green,fg:black')  config.set('Colors', 'title_download',   'bg:blue,fg:black') @@ -269,7 +271,6 @@ class Transmission:      STATUS_DOWNLOAD      = 4   # Downloading      STATUS_SEED_WAIT     = 5   # Queued to seed      STATUS_SEED          = 6   # Seeding -    STATUS_ISOLATED      = 7   # Torrent can't find peers      TAG_TORRENT_LIST    = 7      TAG_TORRENT_DETAILS = 77 @@ -336,6 +337,11 @@ class Transmission:              Transmission.STATUS_SEED          = 1 << 3              Transmission.STATUS_STOPPED       = 1 << 4 +        # Queue was implemented in Transmission v2.4 +        if self.rpc_version >= 14: +            self.LIST_FIELDS.append('queuePosition'); +            self.DETAIL_FIELDS.append('queuePosition'); +           # set up request list          self.requests = {'torrent-list':                               TransmissionRequest(host, port, path, 'torrent-get', self.TAG_TORRENT_LIST, {'fields': self.LIST_FIELDS}), @@ -405,8 +411,7 @@ class Transmission:                      t['leechers'] = max(map(lambda x: x['leecherCount'], t['trackerStats']))                  except ValueError:                      t['seeders']  = t['leechers'] = -1 -                if not self.can_has_peers(t): -                    t['status'] = Transmission.STATUS_ISOLATED +                t['isIsolated'] = not self.can_has_peers(t)              if response['tag'] == self.TAG_TORRENT_LIST:                  self.torrent_cache = response['arguments']['torrents'] @@ -441,28 +446,32 @@ class Transmission:                  self.peer_progress_cache[peerid] = {'last_progress':peer['progress'], 'last_update':time.time(),                                                      'download_speed':0, 'time_left':0} +            this_peer = self.peer_progress_cache[peerid] +            this_torrent = self.torrent_details_cache +              # estimate how fast a peer is downloading              if peer['progress'] < 1:                  this_time = time.time() -                time_diff = this_time - self.peer_progress_cache[peerid]['last_update'] -                progress_diff = peer['progress'] - self.peer_progress_cache[peerid]['last_progress'] -                if self.peer_progress_cache[peerid]['last_progress'] and progress_diff > 0 and time_diff > 5: -                    downloaded = self.torrent_details_cache['totalSize'] * progress_diff -                    avg_speed  = downloaded / time_diff - -                    if self.peer_progress_cache[peerid]['download_speed'] > 0:  # make it less jumpy -                        avg_speed = (self.peer_progress_cache[peerid]['download_speed'] + avg_speed) /2 - -                    download_left = self.torrent_details_cache['totalSize'] - \ -                        (self.torrent_details_cache['totalSize']*peer['progress']) -                    time_left  = download_left / avg_speed - -                    self.peer_progress_cache[peerid]['last_update']    = this_time  # remember update time -                    self.peer_progress_cache[peerid]['download_speed'] = avg_speed -                    self.peer_progress_cache[peerid]['time_left']      = time_left - -                self.peer_progress_cache[peerid]['last_progress'] = peer['progress']  # remember progress -            self.torrent_details_cache['peers'][index].update(self.peer_progress_cache[peerid]) +                time_diff = this_time - this_peer['last_update'] +                progress_diff = peer['progress'] - this_peer['last_progress'] +                if this_peer['last_progress'] and progress_diff > 0 and time_diff > 5: +                    download_left = this_torrent['totalSize'] - \ +                        (this_torrent['totalSize']*peer['progress']) +                    downloaded = this_torrent['totalSize'] * progress_diff + +                    this_peer['download_speed'] = \ +                        norm.add(peerid+':download_speed', downloaded/time_diff, 10) +                    this_peer['time_left']   = download_left/this_peer['download_speed'] +                    this_peer['last_update'] = this_time + +                # infrequent progress updates lead to increasingly inaccurate +                # estimates, so we go back to <guessing> +                elif time_diff > 60: +                    this_peer['download_speed'] = 0 +                    this_peer['time_left']      = 0 +                    this_peer['last_update']    = time.time() +                this_peer['last_progress'] = peer['progress']  # remember progress +            this_torrent['peers'][index].update(this_peer)              # resolve and locate peer's ip              if features['dns'] and not self.hosts_cache.has_key(ip): @@ -591,13 +600,33 @@ class Transmission:              request.send_request()              self.wait_for_torrentlist_update() +    def decrease_queue_position(self, torrent_id): +        request = TransmissionRequest(self.host, self.port, self.path, 'queue-move-up', 1, +                                          {'ids': [torrent_id]}) +        request.send_request() +        self.wait_for_torrentlist_update() + +    def increase_queue_position(self, torrent_id): +        request = TransmissionRequest(self.host, self.port, self.path, 'queue-move-down', 1, +                                          {'ids': [torrent_id]}) +        request.send_request() +        self.wait_for_torrentlist_update()      def toggle_turtle_mode(self):          self.set_option('alt-speed-enabled', not self.status_cache['alt-speed-enabled'])      def add_torrent(self, location): -        request = TransmissionRequest(self.host, self.port, self.path, 'torrent-add', 1, {'filename': location}) +        args = {} +        try: +            with  open(location, 'rb') as fp: +                args['metainfo'] = unicode(base64.b64encode(fp.read())) +        # If the file doesnt exist or we cant open it, then it is either a url or needs to +        # be open by the server +        except IOError: +            args['filename'] = location + +        request = TransmissionRequest(self.host, self.port, self.path, 'torrent-add', 1, args)          request.send_request()          response = request.get_response()          if response['result'] != 'success': @@ -730,16 +759,16 @@ class Transmission:              status = 'verifying'          elif torrent['status'] == Transmission.STATUS_CHECK_WAIT:              status = 'will verify' +        elif torrent['isIsolated']: +            status = 'isolated'          elif torrent['status'] == Transmission.STATUS_DOWNLOAD:              status = ('idle','downloading')[torrent['rateDownload'] > 0]          elif torrent['status'] == Transmission.STATUS_DOWNLOAD_WAIT: -            status = 'will download' +            status = 'will download (%d)' % torrent['queuePosition']          elif torrent['status'] == Transmission.STATUS_SEED:              status = 'seeding'          elif torrent['status'] == Transmission.STATUS_SEED_WAIT: -            status = 'will seed' -        elif torrent['status'] == Transmission.STATUS_ISOLATED: -            status = 'isolated' +            status = 'will seed (%d)' % torrent['queuePosition']          else:              status = 'unknown state'          return status @@ -749,27 +778,22 @@ class Transmission:          recently, or if DHT is enabled for this torrent and globally, False          otherwise. """ -        # torrent has trackers +        # Torrent has trackers?          if torrent['trackerStats']: -            has_connected = any([tracker['hasAnnounced'] or tracker['hasScraped'] -                                 for tracker in torrent['trackerStats']]) -            if has_connected: +            # Did we try to connect a tracker? +            if any([tracker['hasAnnounced'] for tracker in torrent['trackerStats']]):                  for tracker in torrent['trackerStats']: -                    if tracker['hasScraped'] and \ -                            tracker['lastScrapeTime'] >= tracker['lastAnnounceTime'] and \ -                            tracker['lastScrapeSucceeded']: -                        return True -                    elif tracker['hasAnnounced'] and \ -                            tracker['lastAnnounceTime'] > tracker['lastScrapeTime'] and \ -                            tracker['lastAnnounceSucceeded']: +                    if tracker['lastAnnounceSucceeded']:                          return True +            # We didn't try yet; assume at least one is online              else: -                # If no tracker has been queried (yet), assume at least one is online                  return True -        # torrent can make use of DHT +        # Torrent can use DHT? +        # ('dht-enabled' may be missing; assume DHT is available until we can say for sure)          if not self.status_cache.has_key('dht-enabled') or \                  (self.status_cache['dht-enabled'] and not torrent['isPrivate']):              return True +        # No ways of finding peers remaining          return False      def get_bandwidth_priority(self, torrent): @@ -798,6 +822,7 @@ class Interface:          self.sort_orders    = parse_sort_str(config.get('Sorting', 'order'))          self.compact_list   = config.getboolean('Misc', 'compact_list')          self.torrentname_is_progressbar = config.getboolean('Misc', 'torrentname_is_progressbar') +        self.file_viewer    = config.get('Misc', 'file_viewer')          self.torrents         = server.get_torrent_list(self.sort_orders)          self.stats            = server.get_global_stats() @@ -832,7 +857,7 @@ class Interface:              curses.KEY_BACKSPACE:   self.leave_details,              ord('q'):               self.go_back_or_quit,              ord('o'):               self.o_key, -            ord('\n'):              self.select_torrent_detail_view, +            ord('\n'):              self.enter_key,              curses.KEY_RIGHT:       self.right_key,              ord('l'):               self.l_key,              ord('s'):               self.show_sort_order_menu, @@ -845,6 +870,8 @@ class Interface:              ord('t'):               self.t_key,              ord('+'):               self.bandwidth_priority,              ord('-'):               self.bandwidth_priority, +            ord('J'):               lambda c: self.move_queue('up'), +            ord('K'):               lambda c: self.move_queue('down'),              ord('p'):               self.pause_unpause_torrent,              ord('P'):               self.pause_unpause_all_torrent,              ord('v'):               self.verify_torrent, @@ -887,8 +914,13 @@ class Interface:              ('status','S_tatus'), ('uploadedEver','Up_loaded'),              ('rateUpload','_Upload Speed'), ('rateDownload','_Download Speed'),              ('uploadRatio','_Ratio'), ('peersConnected','P_eers'), -            ('downloadDir', 'L_ocation'), ('reverse','Re_verse') -        ] +            ('downloadDir', 'L_ocation') ] + +        # queue was implemmented in transmission 2.4 +        if server.get_rpc_version() >= 14: +            self.sort_options.append(('queuePosition', '_Queue Position')) + +        self.sort_options.append(('reverse','Re_verse'))          try: @@ -965,15 +997,16 @@ class Interface:                  self.torrent_title_width -= self.rateDownload_width + 2          elif self.torrents: -            visible_torrents = self.torrents[self.scrollpos/self.tlist_item_height : self.scrollpos/self.tlist_item_height + self.torrents_per_page + 1] -            self.rateDownload_width = self.get_rateDownload_width(visible_torrents) -            self.rateUpload_width   = self.get_rateUpload_width(visible_torrents) - +            self.visible_torrents_start = self.scrollpos/self.tlist_item_height +            self.visible_torrents = self.torrents[self.visible_torrents_start : self.scrollpos/self.tlist_item_height + self.torrents_per_page + 1] +            self.rateDownload_width = self.get_rateDownload_width(self.visible_torrents) +            self.rateUpload_width   = self.get_rateUpload_width(self.visible_torrents)              self.torrent_title_width = self.width - self.rateUpload_width - 2              # show downloading column only if any downloading torrents are visible -            if filter(lambda x: x['status']==Transmission.STATUS_DOWNLOAD, visible_torrents): +            if filter(lambda x: x['status']==Transmission.STATUS_DOWNLOAD, self.visible_torrents):                  self.torrent_title_width -= self.rateDownload_width + 2          else: +            self.visible_torrents = []              self.torrent_title_width = 80      def get_rateDownload_width(self, torrents): @@ -1067,7 +1100,7 @@ class Interface:              self.select_unselect_file(c)          # Torrent list          elif self.selected_torrent == -1: -            self.select_torrent_detail_view(c) +            self.enter_key(c)      def a_key(self, c):          # File list @@ -1091,7 +1124,7 @@ class Interface:      def l_key(self, c):          if self.focus > -1 and self.selected_torrent == -1: -            self.select_torrent_detail_view(c) +            self.enter_key(c)          elif self.selected_torrent > -1:              self.file_pritority_or_switch_details(c) @@ -1117,25 +1150,30 @@ class Interface:      def right_key(self, c):          if self.focus > -1 and self.selected_torrent == -1: -            self.select_torrent_detail_view(c) +            self.enter_key(c)          else:              self.file_pritority_or_switch_details(c)      def add_torrent(self): -        location = self.dialog_input_text("Add torrent from file or URL", os.getcwd()) +        location = self.dialog_input_text("Add torrent from file or URL", homedir2tilde(os.getcwd()+os.sep), tab_complete='all')          if location: -            error = server.add_torrent(location) +            error = server.add_torrent(tilde2homedir(location))              if error:                  msg = wrap("Couldn't add torrent \"%s\":" % location)                  msg.extend(wrap(error, self.width-4))                  self.dialog_ok("\n".join(msg)) -    def select_torrent_detail_view(self, c): +    def enter_key(self, c): +        # Torrent list          if self.focus > -1 and self.selected_torrent == -1:              self.screen.clear()              self.selected_torrent = self.focus              server.set_torrent_details_id(self.torrents[self.focus]['id'])              server.wait_for_details_update() +        # File list +        elif self.selected_torrent > -1 and self.details_category_focus == 1: +            self.open_torrent_file(c) +      def show_sort_order_menu(self, c):          if self.selected_torrent == -1: @@ -1220,6 +1258,15 @@ class Interface:          elif c == ord('+') and self.focus > -1:              server.increase_bandwidth_priority(self.torrents[self.focus]['id']) +    def move_queue(self, direction): +        # queue was implemmented in Transmission v2.4 +        if server.get_rpc_version() >= 14: +            if direction == 'up' and self.focus > -1: +                server.increase_queue_position(self.torrents[self.focus]['id']) +            elif direction == 'down' and self.focus > -1: +                server.decrease_queue_position(self.torrents[self.focus]['id']) + +      def pause_unpause_torrent(self, c):          if self.focus > -1:              if self.selected_torrent > -1: @@ -1436,6 +1483,24 @@ class Interface:                  else:                      self.selected_files = range(0, len(self.torrent_details['files'])) +    def open_torrent_file(self, c): +        if self.focus_detaillist >= 0: +            details = server.get_torrent_details() +            file_server_index = self.file_index_map[self.focus_detaillist] +            file_name = details['files'][file_server_index]['name'] +            download_dir = details['downloadDir'] + +            viewer_cmd=[] +            for argstr in self.file_viewer.split(" "): +                viewer_cmd.append(argstr.replace('%s',download_dir + file_name)) +            try: +                self.restore_screen() +                call(viewer_cmd) +                self.get_screen_size() +            except OSError, err: +                self.get_screen_size() +                self.dialog_ok("%s:\n%s" % (" ".join(viewer_cmd), err)) +      def move_in_details(self, c):          if self.selected_torrent > -1:              if c == ord("\t"): @@ -1459,7 +1524,7 @@ class Interface:          if self.focus > -1:              location = homedir2tilde(self.torrents[self.focus]['downloadDir'])              msg = 'Move "%s" from\n%s to' % (self.torrents[self.focus]['name'], location) -            path = self.dialog_input_text(msg, location) +            path = self.dialog_input_text(msg, location, tab_complete='dirs')              if path:                  server.move_torrent(self.torrents[self.focus]['id'], tilde2homedir(path)) @@ -1501,7 +1566,7 @@ class Interface:              self.torrents = [t for t in self.torrents if t['status'] == Transmission.STATUS_CHECK \                                   or t['status'] == Transmission.STATUS_CHECK_WAIT]          elif self.filter_list == 'isolated': -            self.torrents = [t for t in self.torrents if t['status'] == Transmission.STATUS_ISOLATED] +            self.torrents = [t for t in self.torrents if t['isIsolated']]          # invert list?          if self.filter_inverse:              self.torrents = [t for t in unfiltered if t not in self.torrents] @@ -1556,13 +1621,13 @@ class Interface:          self.manage_layout()          ypos = 0 -        for i in range(len(self.torrents)): -            ypos += self.draw_torrentlist_item(self.torrents[i], -                                               (i == self.focus), +        for i in range(len(self.visible_torrents)): +            ypos += self.draw_torrentlist_item(self.visible_torrents[i], +                                               (i == self.focus-self.visible_torrents_start),                                                 self.compact_list,                                                 ypos) -        self.pad.refresh(self.scrollpos,0, 1,0, self.mainview_height,self.width-1) +        self.pad.refresh(0,0, 1,0, self.mainview_height,self.width-1)          self.screen.refresh() @@ -1633,7 +1698,9 @@ class Interface:          size = '| ' + size          title = ljust_columns(torrent['name'], width - len(size)) + size -        if torrent['status'] == Transmission.STATUS_SEED or \ +        if torrent['isIsolated']: +            color = curses.color_pair(self.colors.id('title_error')) +        elif torrent['status'] == Transmission.STATUS_SEED or \             torrent['status'] == Transmission.STATUS_SEED_WAIT:              color = curses.color_pair(self.colors.id('title_seed'))          elif torrent['status'] == Transmission.STATUS_STOPPED: @@ -1641,8 +1708,6 @@ class Interface:          elif torrent['status'] == Transmission.STATUS_CHECK or \               torrent['status'] == Transmission.STATUS_CHECK_WAIT:              color = curses.color_pair(self.colors.id('title_verify')) -        elif torrent['status'] == Transmission.STATUS_ISOLATED: -            color = curses.color_pair(self.colors.id('title_error'))          elif torrent['rateDownload'] == 0:              color = curses.color_pair(self.colors.id('title_idle'))          elif torrent['percentDone'] < 100: @@ -1672,7 +1737,7 @@ class Interface:          peers = ''          parts = [server.get_status(torrent)] -        if torrent['status'] == Transmission.STATUS_ISOLATED and torrent['peersConnected'] <= 0: +        if torrent['isIsolated'] and torrent['peersConnected'] <= 0:              if not torrent['trackerStats']:                  parts[0] = "Unable to find peers without trackers and DHT disabled"              else: @@ -1812,7 +1877,7 @@ class Interface:              info[-1].append("no transmission in progress")          info.append(['Ratio: ', '%.2f copies distributed' % copies_distributed]) -        norm_upload_rate = norm.add('%s:rateUpload' % t['id'], t['rateUpload'], 15) +        norm_upload_rate = norm.add('%s:rateUpload' % t['id'], t['rateUpload'], 50)          if norm_upload_rate > 0:              target_ratio = self.get_target_ratio()              bytes_left   = (max(t['downloadedEver'],t['sizeWhenDone']) * target_ratio) - t['uploadedEver'] @@ -2411,7 +2476,8 @@ class Interface:          else:              help = [('Move with','cursor keys'), ('q','Back to List')]              if self.details_category_focus == 1 and self.focus_detaillist > -1: -                help = [('space','(De)Select File'), +                help = [('enter', 'Open File'), +                        ('space','(De)Select File'),                          ('left/right','De-/Increase Priority'),                          ('escape','Unfocus/-select')] + help              elif self.details_category_focus == 2: @@ -2439,6 +2505,10 @@ class Interface:                    "              a  Add torrent\n" + \                    "          Del/r  Remove torrent and keep content\n" + \                    "    Shift+Del/R  Remove torrent and delete content\n" + +        # Queue was implemented in Transmission v2.4 +        if server.get_rpc_version() >= 14: +            message += "            K/J  Increase/decrease Queue Position for focused torrent\n"          # Torrent list          if self.selected_torrent == -1:              message += "              /  Search in torrent list\n" + \ @@ -2579,7 +2649,12 @@ class Interface:              elif c == 27 or c == curses.KEY_BREAK:                  return -1 -    def dialog_input_text(self, message, input='', on_change=None, on_enter=None): + +    # tab_complete values: +    #               'all': complete with any files/directories +    #              'dirs': complete only with directories +    #     any false value: do not complete +    def dialog_input_text(self, message, input='', on_change=None, on_enter=None, tab_complete=None):          width  = self.width - 4          textwidth = self.width - 8          height = message.count("\n") + 4 @@ -2617,6 +2692,11 @@ class Interface:              elif index < len(input) and c == curses.ascii.ctrl(ord('k')):                  input = input[:index]                  if on_change: on_change(input) +            elif c == curses.ascii.ctrl(ord('u')): +                # Delete from cursor until beginning of line +                input = input[index:] +                index = 0 +                if on_change: on_change(input)              elif c == curses.KEY_HOME or c == curses.ascii.ctrl(ord('a')):                  index = 0              elif c == curses.KEY_END or c == curses.ascii.ctrl(ord('e')): @@ -2631,6 +2711,16 @@ class Interface:                  input = input[:index] + chr(c) + (index < len(input) and input[index:] or '')                  index += 1                  if on_change: on_change(input) +            elif c == ord('\t') and tab_complete: +                possible_choices = glob.glob(tilde2homedir(input)+'*') +                if tab_complete == 'dirs': +                    possible_choices = [ d for d in possible_choices if os.path.isdir(d) ] +                if(possible_choices): +                    input = os.path.commonprefix(possible_choices) +                    if len(possible_choices) == 1 and os.path.isdir(input) and input.endswith(os.sep) == False: +                        input += os.sep +                    input = homedir2tilde(input) +                    index = len(input)              if on_change: win.redrawwin()      def dialog_search_torrentlist(self, c): @@ -2787,13 +2877,20 @@ class Interface:                  options.append(('_Micro Transport Protocol', ('disabled','enabled')[self.stats['utp-enabled']]))              options.append(('_Global Peer Limit', "%d" % self.stats['peer-limit-global']))              options.append(('Peer Limit per _Torrent', "%d" % self.stats['peer-limit-per-torrent'])) -            options.append(('_Seed Ratio Limit', "%s" % ('unlimited',self.stats['seedRatioLimit'])[self.stats['seedRatioLimited']]))              options.append(('T_urtle Mode UL Limit', "%dK" % self.stats['alt-speed-up']))              options.append(('Tu_rtle Mode DL Limit', "%dK" % self.stats['alt-speed-down'])) +            options.append(('_Seed Ratio Limit', "%s" % ('unlimited',self.stats['seedRatioLimit'])[self.stats['seedRatioLimited']])) +            # queue was implemented in Transmission v2.4 +            if server.get_rpc_version() >= 14: +                options.append(('Do_wnload Queue Size', "%s" % ('disabled',self.stats['download-queue-size'])[self.stats['download-queue-enabled']])) +                options.append(('S_eed Queue Size', "%s" % ('disabled',self.stats['seed-queue-size'])[self.stats['seed-queue-enabled']]))              options.append(('Title is Progress _Bar', ('no','yes')[self.torrentname_is_progressbar])) +            options.append(('File _Viewer', "%s" % self.file_viewer)) +              max_len = max([sum([len(re.sub('_', '', x)) for x in y[0]]) for y in options]) -            win = self.window(len(options)+2, max_len+15, '', "Global Options") +            win_width = min(max(len(self.file_viewer)+5, 15), self.width+max_len) +            win = self.window(len(options)+2, max_len+win_width, '', "Global Options")              line_num = 1              for option in options: @@ -2869,6 +2966,36 @@ class Interface:                      server.set_option('alt-speed-down', limit)              elif c == ord('b'):                  self.torrentname_is_progressbar = not self.torrentname_is_progressbar +            # Queue was implemmented in Transmission v2.4 +            elif c == ord('w') and server.get_rpc_version() >= 14: +                queue_size = self.dialog_input_number('Download Queue size', +                                                      (0, self.stats['download-queue-size'])[self.stats['download-queue-enabled']], +                                                      allow_negative_one = False) +                if queue_size != -128: +                    if queue_size == 0: +                        server.set_option('download-queue-enabled', False) +                    elif queue_size > 0: +                        if not self.stats['download-queue-enabled']: +                            server.set_option('download-queue-enabled', True) +                        server.set_option('download-queue-size', queue_size) +            # Queue was implemmented in Transmission v2.4 +            elif c == ord('e') and server.get_rpc_version() >= 14: +                queue_size = self.dialog_input_number('Seed Queue size', +                                                      (0, self.stats['seed-queue-size'])[self.stats['seed-queue-enabled']], +                                                      allow_negative_one = False) +                if queue_size != -128: +                    if queue_size == 0: +                        server.set_option('seed-queue-enabled', False) +                    elif queue_size > 0: +                        if not self.stats['seed-queue-enabled']: +                            server.set_option('seed-queue-enabled', True) +                        server.set_option('seed-queue-size', queue_size) + +            elif c == ord('v'): +                viewer = self.dialog_input_text('File Viewer\nExample: xdg-viewer %s', self.file_viewer) +                if viewer: +                    config.set('Misc', 'file_viewer', viewer.replace('%s','%%s')) +                    self.file_viewer=viewer              self.draw_torrent_list() @@ -3065,7 +3192,7 @@ def debug(data):      if cmd_args.DEBUG:          file = open("debug.log", 'a')          if type(data) == type(str()): -            file.write(self.enc(data)) +            file.write(data)          else:              import pprint              pp = pprint.PrettyPrinter(indent=4)  | 
