📄 __init__.py
字号:
# The contents of this file are subject to the BitTorrent Open Source License# Version 1.1 (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 Matt Chisholm and Greg Hazelfrom __future__ import divisionimport ostry: import wxversionexcept: passelse: # doesn't work in py2exe try: wxversion.select('2.6') except: pass import wximport wx.gridimport wxPythonimport tracebackimport bisectfrom BitTorrent.translation import _from UserDict import UserDictfrom BitTorrent import zurllibfrom BitTorrent.platform import image_root, desktop, bttimeimport BitTorrent.stackthreading as threadingfrom BitTorrent.defer import ThreadedDeferredvs = wxPython.__version__min_wxpython = "2.6"assert vs >= min_wxpython, _("wxPython version %s or newer required") % min_wxpythonassert 'unicode' in wx.PlatformInfo, _("The Unicode versions of wx and wxPython are required")text_wrappable = wx.__version__[4] >= '2'# used in BTAppprofile = Falseclass Amaturefile(object): def start(self): pass def stop(self): passif profile: import hotshot import hotshot.stats prof_file_name = 'ui.mainloop.prof'def gui_wrap(_f, *args, **kwargs): wx.the_app.CallAfter(_f, *args, **kwargs)SPACING = 8 # default pixels between widgetsPORT_RANGE = 5 # how many ports to tryWILDCARD = "Torrent files (*.torrent)|*.torrent|"\ "All files (*.*)|*.*"def list_themes(): def _lt(): themes = [] tr = os.path.join(image_root, 'themes') ld = os.listdir(tr) for d in ld: if os.path.isdir(os.path.join(tr, d)): themes.append(d) return themes df = ThreadedDeferred(None, _lt, daemon=True) df.start() return dfclass ImageLibrary(object): def __init__(self, image_root): self.image_root = image_root self._data = {} def get(self, key, size=None, base=None): if base is None: base = self.image_root if self._data.has_key((key, size)): return self._data[(key, size)]## utorrent_toolbar = os.path.join(base, "toolbar.bmp")## if os.path.exists(utorrent_toolbar):## try:## assert False, "Use wx.Bitmap instead"## i = wx.Image(utorrent_toolbar, wx.BITMAP_TYPE_BMP)## i.SetMaskFromImage(i, 0, 0, 0)## iw = 24## ih = i.GetHeight()## self._data["search"] = i.GetSubImage(wx.Rect(9 * iw, 0, iw, ih))## self._data["stop"] = i.GetSubImage(wx.Rect(5 * iw, 0, iw, ih))## self._data["start"] = i.GetSubImage(wx.Rect(4 * iw, 0, iw, ih))## self._data["info"] = i.GetSubImage(wx.Rect(11 * iw, 0, iw, ih))## self._data["launch"] = i.GetSubImage(wx.Rect(0 * iw, 0, iw, ih))## self._data["remove"] = i.GetSubImage(wx.Rect(3 * iw, 0, iw, ih))## except:## pass## utorrent_tstatus = os.path.join(base, "tstatus.bmp")## if os.path.exists(utorrent_tstatus):## try:## assert False, "Use wx.Bitmap instead"## i = wx.Image(utorrent_tstatus, wx.BITMAP_TYPE_BMP)## i.SetMaskFromImage(i, 0, 0, 0)## iw = 16## ih = i.GetHeight()## self._data[os.path.join("torrentstate", "created")] = i.GetSubImage(## wx.Rect(12 * iw, 0, iw, ih))## self._data[os.path.join("torrentstate", "starting")] = i.GetSubImage(## wx.Rect(12 * iw, 0, iw, ih))## self._data[os.path.join("torrentstate", "paused")] = i.GetSubImage(## wx.Rect(3 * iw, 0, iw, ih))## self._data[os.path.join("torrentstate", "downloading")] = i.GetSubImage(## wx.Rect(0 * iw, 0, iw, ih))## self._data[os.path.join("torrentstate", "finishing")] = i.GetSubImage(## wx.Rect(7 * iw, 0, iw, ih))## self._data[os.path.join("torrentstate", "seeding")] = i.GetSubImage(## wx.Rect(1 * iw, 0, iw, ih))## self._data[os.path.join("torrentstate", "stopped")] = i.GetSubImage(## wx.Rect(2 * iw, 0, iw, ih))## self._data[os.path.join("torrentstate", "complete")] = i.GetSubImage(## wx.Rect(7 * iw, 0, iw, ih))## self._data[os.path.join("torrentstate", "error")] = i.GetSubImage(## wx.Rect(6 * iw, 0, iw, ih))## self._data[os.path.join("torrentstate", "unknown")] = i.GetSubImage(## wx.Rect(6 * iw, 0, iw, ih))## except:## pass name = os.path.join(base, *key) ext = '.png' if size is not None: sized_name = name + '_%d' % size + ext if os.path.exists(sized_name): name = sized_name else: name += ext else: name += ext if not os.path.exists(name): assert False, "No such image file: %s" % name i = wx.Image(name, wx.BITMAP_TYPE_PNG) assert i.Ok(), "The image (%s) is not valid." % name self._data[(key, size)] = i return iclass ThemeLibrary(ImageLibrary): def __init__(self, themes_root, theme_name): self.themes_root = themes_root for t in (theme_name, 'default'): image_root = os.path.join(themes_root, 'themes', t) if os.path.exists(image_root): self.theme_name = t ImageLibrary.__init__(self, image_root) return assert False, 'default theme path "%s" must exist' % image_root def get(self, key, size=None): try: return ImageLibrary.get(self, key, size=size) except AssertionError, e: # Fall back to default theme. # Should probably log this to make theme developers happy. return ImageLibrary.get(self, key, size=size, base=os.path.join(self.themes_root, 'themes', 'default'))class XSizer(wx.BoxSizer): notfirst = wx.ALL direction = wx.HORIZONTAL def __init__(self, **k): wx.BoxSizer.__init__(self, self.direction) def Add(self, widget, proportion=0, flag=0, border=SPACING): flag = flag | self.notfirst wx.BoxSizer.Add(self, widget, proportion=proportion, flag=flag, border=border) def AddFirst(self, widget, proportion=0, flag=0, border=SPACING): flag = flag | wx.ALL self.Add(widget, proportion=proportion, flag=flag, border=border)class VSizer(XSizer): notfirst = wx.BOTTOM|wx.LEFT|wx.RIGHT direction = wx.VERTICALclass HSizer(XSizer): notfirst = wx.BOTTOM|wx.RIGHT|wx.TOP direction = wx.HORIZONTALclass LabelValueFlexGridSizer(wx.FlexGridSizer): def __init__(self, parent_widget, *a, **k): wx.FlexGridSizer.__init__(self, *a, **k) self.parent_widget = parent_widget def add_label(self, label): h = ElectroStaticText(self.parent_widget, label=label) f = h.GetFont() f.SetWeight(wx.FONTWEIGHT_BOLD) h.SetFont(f) self.Add(h) def add_value(self, value, dotify=False): t = ElectroStaticText(self.parent_widget, id=wx.ID_ANY, label="", dotify=dotify) self.Add(t, flag=wx.FIXED_MINSIZE|wx.GROW) t.SetLabel(value) return t def add_pair(self, label, value, dotify_value=False): self.add_label(label) t = self.add_value(value, dotify=dotify_value) return tclass ElectroStaticText(wx.StaticText): def __init__(self, parent, id=wx.ID_ANY, label='', dotify=False): wx.StaticText.__init__(self, parent, id, label) self.label = label self._string = self.label if dotify: self.Bind(wx.EVT_PAINT, self.DotifyOnPaint) def SetLabel(self, label): if label != self.label: self.label = label self._string = self.label wx.StaticText.SetLabel(self, self.label) def dotdotdot(self, label, width, max_width): label_reverse = label[::-1] beginning_values = self.dc.GetPartialTextExtents(label) ending_values = self.dc.GetPartialTextExtents(label_reverse) halfwidth = (width - self.dc.GetTextExtent("...")[0]) / 2 beginning = bisect.bisect_left(beginning_values, halfwidth) ending = bisect.bisect_left(ending_values, halfwidth) if ending > 0: string = label[:beginning] + "..." + label[(0 - ending):] else: string = label[:beginning] + "..." return string def DotifyOnPaint(self, event): self.dc = wx.PaintDC(self) self.dc.SetFont(self.GetFont()) width = self.GetSize().width str_width = self.dc.GetTextExtent(self._string)[0] max_width = self.dc.GetTextExtent(self.label)[0] if width >= max_width: self._string = self.label elif width != str_width: string = self.dotdotdot(self.label, width, max_width) self._string = string wx.StaticText.SetLabel(self, self._string) event.Skip()class ElectroStaticBitmap(wx.Window): def __init__(self, parent, bitmap, *a, **k): wx.Window.__init__(self, parent, *a, **k) self.bitmap = bitmap self.SetMinSize((self.bitmap.GetWidth(), self.bitmap.GetHeight())) self.Bind(wx.EVT_PAINT, self.OnPaint) def OnPaint(self, event): dc = wx.PaintDC(self) dc.SetBackground(wx.Brush(self.GetBackgroundColour())) dc.DrawBitmap(self.bitmap, 0, 0, True) def GetSize(self): return wx.Size(self.bitmap.GetWidth(), self.bitmap.GetHeight())class Validator(wx.TextCtrl): valid_chars = '1234567890' minimum = None maximum = None cast = int def __init__(self, parent, option_name, config, setfunc): wx.TextCtrl.__init__(self, parent) self.option_name = option_name self.config = config self.setfunc = setfunc self.SetValue(str(config[option_name])) self.SetBestFittingSize((self.width,-1)) self.Bind(wx.EVT_CHAR, self.text_inserted) self.Bind(wx.EVT_KILL_FOCUS, self.focus_out) def get_value(self): value = None try: value = self.cast(self.GetValue()) except ValueError: pass return value def set_value(self, value): self.SetValue(str(value)) self.setfunc(self.option_name, value) def focus_out(self, event): # guard against the the final focus lost event on wxMAC if self.IsBeingDeleted(): return value = self.get_value() if value is None: self.SetValue(str(self.config[self.option_name])) 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, event): key = event.KeyCode() if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255: event.Skip() return if (self.valid_chars is not None) and (chr(key) not in self.valid_chars): return event.Skip()class IPValidator(Validator): valid_chars = '1234567890.' width = 128 cast = strclass PortValidator(Validator): width = 64 minimum = 1024 maximum = 65535 def add_end(self, end_name): self.end_option_name = end_name def set_value(self, value): self.SetValue(str(value)) self.setfunc(self.option_name, value) self.setfunc(self.end_option_name, value+PORT_RANGE)class RatioValidator(Validator): width = 48 minimum = 0class MinutesValidator(Validator): width = 48 minimum = 1class PathDialogButton(wx.Button): def __init__(self, parent, gen_dialog, setfunc=None, label=_("&Browse...")): wx.Button.__init__(self, parent, label=label) self.gen_dialog = gen_dialog self.setfunc = setfunc self.Bind(wx.EVT_BUTTON, self.choose)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -