?? btdownloadgui.py
字號:
#!/usr/bin/env python# The contents of this file are subject to the BitTorrent Open Source License# Version 1.0 (the License). You may not copy or use this file, in either# source code or executable form, except in compliance with the License. You# may obtain a copy of the License at http://www.bittorrent.com/license/.## Software distributed under the License is distributed on an AS IS basis,# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License# for the specific language governing rights and limitations under the# License.# Written by Uoti Urpala and Matt Chisholmfrom __future__ import divisionimport sysassert sys.version_info >= (2, 3), "Install Python 2.3 or greater"import itertoolsimport mathimport osimport threadingimport datetimeimport randomimport gtkimport pangoimport gobjectimport webbrowserfrom urllib import quote, url2pathnamefrom BitTorrent import configfilefrom BitTorrent import HELP_URL, DONATE_URLfrom BitTorrent import is_frozen_exefrom BitTorrent.parseargs import parseargs, makeHelpfrom BitTorrent import version, doc_rootfrom BitTorrent.defaultargs import get_defaultsfrom BitTorrent import TorrentQueuefrom BitTorrent.TorrentQueue import RUNNING, QUEUED, KNOWN, ASKING_LOCATIONfrom BitTorrent.controlsocket import ControlSocketfrom BitTorrent import BTFailure, INFO, WARNING, ERROR, CRITICALfrom BitTorrent import OpenPathfrom BitTorrent import Desktopfrom BitTorrent import ClientIdentifierfrom BitTorrent import path_wrapfrom BitTorrent.GUI import * defaults = get_defaults('btdownloadgui')defaults.extend((('donated' , '', ''), # the version that the user last donated for ('notified', '', ''), # the version that the user was last notified of ))NAG_FREQUENCY = 3PORT_RANGE = 5defconfig = dict([(name, value) for (name, value, doc) in defaults])del name, value, docui_options = 'max_upload_rate minport maxport '\ 'next_torrent_time next_torrent_ratio '\ 'last_torrent_ratio '\ 'ask_for_save save_in ip start_torrent_behavior '\ 'close_with_rst '\ 'min_uploads max_uploads max_initiate '\ 'max_allow_in max_files_open display_interval '\ 'pause donated notified'.split()advanced_ui_options_index = 11if is_frozen_exe: ui_options.append('progressbar_hack') defproghack = 0 wv = sys.getwindowsversion() if (wv[3], wv[0], wv[1]) == (2, 5, 1): # turn on progress bar hack by default for Win XP defproghack = 1 defaults.extend((('progressbar_hack' , defproghack, ''),)) main_torrent_dnd_tip = 'drag to reorder'torrent_menu_tip = 'right-click for menu'torrent_tip_format = '%s:\n %s\n %s'rate_label = ' rate: %s'speed_classes = { ( 4, 5): 'dialup' , ( 6, 14): 'DSL/cable 128k up', ( 15, 29): 'DSL/cable 256k up', ( 30, 91): 'DSL 768k up' , ( 92, 137): 'T1' , ( 138, 182): 'T1/E1' , ( 183, 249): 'E1' , ( 250, 5446): 'T3' , (5447,18871): 'OC3' , }def find_dir(path): if os.path.isdir(path): return path directory, garbage = os.path.split(path) while directory: if os.access(directory, os.F_OK) and os.access(directory, os.W_OK): return directory directory, garbage = os.path.split(directory) if garbage == '': break return Nonedef smart_dir(path): path = find_dir(path) if path is None: path = Desktop.desktop return pathdef build_menu(menu_items, accel_group=None): menu = gtk.Menu() for label,func in menu_items: if label == '----': s = gtk.SeparatorMenuItem() s.show() menu.add(s) else: item = gtk.MenuItem(label) if func is not None: item.connect("activate", func) else: item.set_sensitive(False) if accel_group is not None: accel_index = label.find('_') if accel_index > -1: accel_key = label[accel_index+1] item.add_accelerator("activate", accel_group, ord(accel_key), gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) item.show() menu.add(item) return menuclass Validator(gtk.Entry): valid_chars = '1234567890' minimum = None maximum = None cast = int def __init__(self, option_name, config, setfunc): gtk.Entry.__init__(self) self.option_name = option_name self.config = config self.setfunc = setfunc self.set_text(str(config[option_name])) self.set_size_request(self.width,-1) self.connect('insert-text', self.text_inserted) self.connect('focus-out-event', self.focus_out) def get_value(self): value = None try: value = self.cast(self.get_text()) except ValueError: pass return value def set_value(self, value): self.set_text(str(value)) self.setfunc(self.option_name, value) def focus_out(self, entry, widget): value = self.get_value() if value is None: return if (self.minimum is not None) and (value < self.minimum): value = self.minimum if (self.maximum is not None) and (value > self.maximum): value = self.maximum self.set_value(value) def text_inserted(self, entry, input, position, user_data): for i in input: if (self.valid_chars is not None) and (i not in self.valid_chars): self.emit_stop_by_name('insert-text') return Trueclass IPValidator(Validator): valid_chars = '1234567890.' width = 128 cast = strclass PortValidator(Validator): width = 64 minimum = 0 maximum = 65535 def add_end(self, end_name): self.end_option_name = end_name def set_value(self, value): self.set_text(str(value)) self.setfunc(self.option_name, value) self.setfunc(self.end_option_name, value+PORT_RANGE)class PercentValidator(Validator): width = 48 minimum = 0class MinutesValidator(Validator): width = 48 minimum = 1class RateSliderBox(gtk.VBox): base = 10 multiplier = 4 max_exponent = 3.3 def __init__(self, config, torrentqueue): gtk.VBox.__init__(self, homogeneous=False) self.config = config self.torrentqueue = torrentqueue if self.config['max_upload_rate'] < self.slider_to_rate(0): self.config['max_upload_rate'] = self.slider_to_rate(0) self.rate_slider_label = gtk.Label( self.value_to_label(self.config['max_upload_rate'])) self.rate_slider_adj = gtk.Adjustment( self.rate_to_slider(self.config['max_upload_rate']), 0, self.max_exponent, 0.01, 0.1) self.rate_slider = gtk.HScale(self.rate_slider_adj) self.rate_slider.set_draw_value(False) self.rate_slider_adj.connect('value_changed', self.set_max_upload_rate) self.pack_start(self.rate_slider_label , expand=False, fill=False) self.pack_start(self.rate_slider , expand=False, fill=False) if False: # this shows the legend for the slider self.rate_slider_legend = gtk.HBox(homogeneous=True) for i in range(int(self.max_exponent+1)): label = gtk.Label(str(self.slider_to_rate(i))) alabel = halign(label, i/self.max_exponent) self.rate_slider_legend.pack_start(alabel, expand=True, fill=True) self.pack_start(self.rate_slider_legend, expand=False, fill=False) def start(self): self.set_max_upload_rate(self.rate_slider_adj) def rate_to_slider(self, value): return math.log(value/self.multiplier, self.base) def slider_to_rate(self, value): return int(round(self.base**value * self.multiplier)) def value_to_label(self, value): conn_type = '' for key, conn in speed_classes.items(): min_v, max_v = key if min_v <= value <= max_v: conn_type = ' (%s)'%conn break label = 'Maximum upload'+(rate_label % Rate(value*1024)) + \ conn_type return label def set_max_upload_rate(self, adj): option = 'max_upload_rate' value = self.slider_to_rate(adj.get_value()) self.config[option] = value self.torrentqueue.set_config(option, value) self.rate_slider_label.set_text(self.value_to_label(int(value)))class StopStartButton(gtk.Button): stop_tip = 'Temporarily stop all running torrents' start_tip = 'Resume downloading' def __init__(self, main): gtk.Button.__init__(self) self.main = main self.connect('clicked', self.toggle) self.stop_image = gtk.Image() self.stop_image.set_from_stock('bt-pause', gtk.ICON_SIZE_BUTTON) self.stop_image.show() self.start_image = gtk.Image() self.start_image.set_from_stock('bt-play', gtk.ICON_SIZE_BUTTON) self.start_image.show() self.has_image = False def toggle(self, widget): self.set_paused(not self.main.config['pause']) def set_paused(self, paused): if paused: if self.has_image: self.remove(self.stop_image) self.add(self.start_image) self.main.tooltips.set_tip(self, self.start_tip) self.main.stop_queue() else: if self.has_image: self.remove(self.start_image) self.add(self.stop_image) self.main.tooltips.set_tip(self, self.stop_tip ) self.main.restart_queue() self.has_image = Trueclass VersionWindow(Window): def __init__(self, main, newversion, download_url): Window.__init__(self) self.set_title('New %s version available'%app_name) self.set_border_width(SPACING) self.set_resizable(gtk.FALSE) self.main = main self.newversion = newversion self.download_url = download_url self.connect('destroy', lambda w: self.main.window_closed('version')) self.vbox = gtk.VBox(spacing=SPACING) self.hbox = gtk.HBox(spacing=SPACING) self.image = gtk.Image() self.image.set_from_stock(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_DIALOG) self.hbox.pack_start(self.image) self.label = gtk.Label() self.label.set_markup( ("A newer version of %s is available.\n" % app_name) + ("You are using %s, and the new version is %s.\n" % (version, newversion)) + ("You can always get the latest version from \n%s" % self.download_url) ) self.label.set_selectable(True) self.hbox.pack_start(self.label) self.vbox.pack_start(self.hbox) self.bbox = gtk.HBox(spacing=SPACING) self.closebutton = gtk.Button('Download _later') self.closebutton.connect('clicked', self.close)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -