class MakeTorrentWindow(BTFrameWithSizer): panel_class = MakeTorrentPanel def __init__(self, parent, config): BTFrameWithSizer.__init__( self, parent, style=wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.RESIZE_BORDER ) # HERE HACK. I added RESIZE_BORDER because the window doesn't resize properly when Advanced button is pressed. --Dave self.parent = parent self.SetTitle(_("%s Publisher") % (app_name)) self.config = config self.tracker_list = [] if self.config['tracker_list']: self.tracker_list = self.config['tracker_list'].split(',') ## widgets # file widgets self.top_text = wx.StaticText(self.panel, label=_("Publish this file/directory:")) self.dir_text = wx.StaticText( self.panel, label=_("(Directories will become batch torrents)")) # title widgets self.title_label = wx.StaticText(self.panel, label=_("Title")) self.title = wx.TextCtrl(self.panel) self.title.SetValue(self.config['title']) # Comment widgets self.comment_label = wx.StaticText(self.panel, label=_("Comments:")) self.comment_text = wx.TextCtrl(self.panel, style=wx.TE_MULTILINE, size=(-1, 50)) self.comment_text.SetValue(self.config['comment']) # horizontal line self.simple_advanced_line = wx.StaticLine(self.panel, style=wx.LI_HORIZONTAL) # piece size widgets self.piece_size_label = wx.StaticText(self.panel, label=_("Piece size:")) self.piece_size = wx.Choice(self.panel) self.piece_size.Append(_("Auto")) self.piece_size.offset = 15 for i in range(7): self.piece_size.Append(str(Size(2**(i + self.piece_size.offset)))) self.piece_size.SetSelection(0) # Announce URL / Tracker widgets self.tracker_radio = wx.RadioButton(self.panel, label=_("Use &tracker:"), style=wx.RB_GROUP) self.tracker_radio.group = [ self.tracker_radio, ] self.tracker_radio.value = True self.announce_entry = wx.ComboBox(self.panel, style=wx.CB_DROPDOWN, choices=self.tracker_list) self.tracker_radio.entry = self.announce_entry if self.tracker_radio.GetValue(): self.announce_entry.Enable(True) else: self.announce_entry.Enable(False) if self.config['tracker_name']: self.announce_entry.SetValue(self.config['tracker_name']) elif len(self.tracker_list): self.announce_entry.SetValue(self.tracker_list[0]) else: self.announce_entry.SetValue('http://my.tracker:6969/announce') # DHT / Trackerless widgets self.dht_radio = wx.RadioButton(self.panel, label=_("Use &DHT:")) self.tracker_radio.group.append(self.dht_radio) self.dht_radio.value = False self.dht_nodes_box = wx.StaticBox(self.panel, label=_("Nodes (optional):")) self.dht_nodes = NodeList(self.panel, 'router.bittorrent.com:6881') self.dht_radio.entry = self.dht_nodes for w in self.tracker_radio.group: w.Bind(wx.EVT_RADIOBUTTON, self.toggle_tracker_dht) for w in self.tracker_radio.group: if w.value == bool(self.config['use_tracker']): w.SetValue(True) else: w.SetValue(False) if self.config['use_tracker']: self.dht_nodes.Disable() else: self.announce_entry.Disable() # Button widgets self.quitbutton = wx.Button(self.panel, label=_("&Close")) self.quitbutton.Bind(wx.EVT_BUTTON, self.quit) self.makebutton = wx.Button(self.panel, label=_("&Publish")) self.makebutton.Bind(wx.EVT_BUTTON, self.make) self.makebutton.Enable(False) self.advancedbutton = wx.Button(self.panel, label=_("&Advanced")) self.advancedbutton.Bind(wx.EVT_BUTTON, self.toggle_advanced) self.simplebutton = wx.Button(self.panel, label=_("&Simple")) self.simplebutton.Bind(wx.EVT_BUTTON, self.toggle_advanced) ## sizers # file sizers def setfunc(path): self.config['torrent_dir'] = path path = '' if self.config.has_key('torrent_dir') and self.config['torrent_dir']: path = self.config['torrent_dir'] elif self.config.has_key('open_from') and self.config['open_from']: path = self.config['open_from'] elif self.config.has_key('save_in') and self.config['save_in']: path = self.config['save_in'] self.choose_file_sizer = ChooseFileOrDirectorySizer(self.panel, path, setfunc=setfunc) self.choose_file_sizer.pathbox.Bind(wx.EVT_TEXT, self.check_buttons) self.box = self.panel.sizer self.box.AddFirst(self.top_text, flag=wx.ALIGN_LEFT) self.box.Add(self.choose_file_sizer, flag=wx.GROW) self.box.Add(self.dir_text, flag=wx.ALIGN_LEFT) self.box.Add(wx.StaticLine(self.panel, style=wx.LI_HORIZONTAL), flag=wx.GROW) # Ye Olde Flexe Gryde Syzer self.table = wx.FlexGridSizer(5, 2, SPACING, SPACING) # Title self.table.Add(self.title_label, flag=wx.ALIGN_CENTER_VERTICAL) self.table.Add(self.title, flag=wx.GROW) # Comments self.table.Add(self.comment_label, flag=wx.ALIGN_CENTER_VERTICAL) self.table.Add(self.comment_text, flag=wx.GROW) # separator self.table.Add((0, 0), 0) self.table.Add(self.simple_advanced_line, flag=wx.GROW) # Piece size sizers self.table.Add(self.piece_size_label, flag=wx.ALIGN_CENTER_VERTICAL) self.table.Add(self.piece_size, flag=wx.GROW) # Announce URL / Tracker sizers self.table.Add(self.tracker_radio, flag=wx.ALIGN_CENTER_VERTICAL) self.table.Add(self.announce_entry, flag=wx.GROW) # DHT / Trackerless sizers self.table.Add(self.dht_radio, flag=wx.ALIGN_CENTER_VERTICAL) self.dht_nodes_sizer = wx.StaticBoxSizer(self.dht_nodes_box, wx.VERTICAL) self.dht_nodes_sizer.Add(self.dht_nodes, flag=wx.ALL, border=SPACING) self.table.Add(self.dht_nodes_sizer, flag=wx.GROW) # add table self.table.AddGrowableCol(1) self.box.Add(self.table, flag=wx.GROW) self.box.Add(wx.StaticLine(self.panel, style=wx.LI_HORIZONTAL), flag=wx.GROW) # Button sizers self.buttonbox = HSizer() self.buttonbox.AddFirst(self.advancedbutton) self.buttonbox.Add(self.simplebutton) self.buttonbox.Add(self.quitbutton) self.buttonbox.Add(self.makebutton) self.box.Add(self.buttonbox, flag=wx.ALIGN_RIGHT, border=0) # bind a bunch of things to check_buttons self.announce_entry.Bind(wx.EVT_TEXT, self.check_buttons) self.choose_file_sizer.pathbox.Bind(wx.EVT_TEXT, self.check_buttons) # radio buttons are checked in toggle_tracker_dht minwidth = self.GetBestSize()[0] self.SetMinSize(wx.Size(minwidth, -1)) # Flip advanced once because toggle_advanced flips it back self.advanced = True self.toggle_advanced(None) if self.config['verbose']: self.toggle_advanced(None) self.check_buttons() self.Show() self.Bind(wx.EVT_CLOSE, self.quit) def Fit(self): self.panel.Fit() self.SetClientSize(self.panel.GetSize()) def quit(self, event=None): self.save_config() if self.parent: self.Show(False) else: self.Destroy() def toggle_advanced(self, event): show = not self.advanced if show: # reinstate the StaticBoxSizer before Show() self.table.Add(self.dht_nodes_sizer, flag=wx.GROW) else: # detach the StaticBoxSizer before Show(False) self.table.Detach(self.dht_nodes_sizer) for w in ( self.simple_advanced_line, self.piece_size, self.piece_size_label, self.tracker_radio, self.announce_entry, self.dht_radio, self.dht_nodes, self.dht_nodes_box, self.simplebutton, ): w.Show(show) self.advancedbutton.Show(self.advanced) if show: self.dht_nodes_sizer.Layout() self.dht_nodes_sizer.Fit(self) self.table.Layout() self.table.Fit(self) self.sizer.RecalcSizes() self.sizer.Fit(self) self.advanced = show def toggle_tracker_dht(self, event): widget = event.GetEventObject() self.config['use_tracker'] = widget.value for e in [self.announce_entry, self.dht_nodes]: if widget.entry is e: e.Enable(True) else: e.Enable(False) self.check_buttons() def get_piece_size_exponent(self): i = self.piece_size.GetSelection() if i == 0: # Auto exp = 0 else: exp = i - 1 + self.piece_size.offset self.config['piece_size_pow2'] = exp return exp def get_file(self): return self.choose_file_sizer.get_choice() def get_announce(self): if self.config['use_tracker']: announce = self.announce_entry.GetValue() self.config['tracker_name'] = announce else: announce = self.dht_nodes.GetValue() return announce def make(self, widget): file_name = self.get_file() piece_size_exponent = self.get_piece_size_exponent() announce = self.get_announce() title = self.title.GetValue() comment = self.comment_text.GetValue() if self.config['use_tracker']: self.add_tracker(announce) errored = False if not errored: d = ProgressDialog(self, [ file_name, ], announce, piece_size_exponent, title, comment, self.config) d.main() def check_buttons(self, *widgets): file_name = self.get_file() tracker = self.announce_entry.GetValue() if file_name not in (None, '') and os.path.exists(file_name): if self.config['use_tracker']: if len(tracker) >= len('http://x.cc'): self.makebutton.Enable(True) else: self.makebutton.Enable(False) else: self.makebutton.Enable(True) else: self.makebutton.Enable(False) def save_config(self): def error_callback(error, string): print string configfile.save_global_config(self.config, 'maketorrent', error_callback, ui_options) def add_tracker(self, tracker_name): try: self.tracker_list.pop(self.tracker_list.index(tracker_name)) except ValueError: pass self.tracker_list[0:0] = [ tracker_name, ] self.config['tracker_list'] = ','.join(self.tracker_list) if not self.announce_entry.IsEmpty(): self.announce_entry.Clear() for t in self.tracker_list: self.announce_entry.Append(t)
class AppearanceSettingsPanel(SettingsPanel): label = _("Appearance") pb_config_key = 'progressbar_style' # sample data sample_value = 0.4 sample_data = { 'h': SparseSet(), 't': SparseSet(), } sample_data['h'].add(0, 80) sample_data['t'].add(80, 100) for i in range(20, 0, -1): s = SparseSet() s.add(200 - i * 5, 200 - (i - 1) * 5) sample_data[i - 1] = s del i, s def __init__(self, parent, *a, **k): SettingsPanel.__init__(self, parent, *a, **k) # widgets self.gauge_box = wx.StaticBox(self, label=_("Progress bar style:")) self.gauge_sizer = wx.StaticBoxSizer(self.gauge_box, wx.VERTICAL) self.null_radio = wx.RadioButton( self, label=_("&None (just show percent complete)"), style=wx.RB_GROUP) self.null_radio.value = 0 self.simple_radio = wx.RadioButton(self, label=_("&Ordinary progress bar")) self.simple_radio.value = 1 self.simple_sample = self.new_sample(SimpleDownloadGauge, 1) self.moderate_radio = wx.RadioButton(self, label=_("&Detailed progress bar")) self.moderate_radio.value = 2 msg = _( "(shows the percentage of complete, transferring, available and missing pieces in the torrent)" ) if not text_wrappable: half = len(msg) // 2 for i in xrange(half): if msg[half + i] == ' ': msg = msg[:half + i + 1] + '\n' + msg[half + i + 1:] break elif msg[half - i] == ' ': msg = msg[:half - i + 1] + '\n' + msg[half - i + 1:] break self.moderate_text = ElectroStaticText(self, wx.ID_ANY, msg) if text_wrappable: self.moderate_text.Wrap(250) self.moderate_sample = self.new_sample(ModerateDownloadGauge, 2) self.fancy_radio = wx.RadioButton(self, label=_("&Piece bar")) self.fancy_radio.value = 3 self.fancy_text = ElectroStaticText( self, wx.ID_ANY, _("(shows the status of each piece in the torrent)")) if text_wrappable: self.fancy_text.Wrap(250) # generate random sample data r = set(xrange(200)) self.sample_data = {} for key, count in (('h', 80), ('t', 20)) + tuple([(i, 5) for i in range(19)]): self.sample_data[key] = SparseSet() for d in random.sample(r, count): self.sample_data[key].add(d) r.remove(d) for d in r: self.sample_data[0].add(d) self.fancy_sample = self.new_sample(FancyDownloadGauge, 3) # sizers gauge = wx.TOP | wx.LEFT | wx.RIGHT extra = wx.TOP | wx.LEFT | wx.RIGHT | wx.GROW self.gauge_sizer.Add(self.null_radio, flag=gauge, border=SPACING) self.gauge_sizer.AddSpacer((SPACING, SPACING)) self.gauge_sizer.Add(self.simple_radio, flag=gauge, border=SPACING) self.gauge_sizer.Add(self.simple_sample, flag=extra, border=SPACING) self.gauge_sizer.AddSpacer((SPACING, SPACING)) self.gauge_sizer.Add(self.moderate_radio, flag=gauge, border=SPACING) self.gauge_sizer.Add(self.moderate_sample, flag=extra, border=SPACING) self.gauge_sizer.Add(self.moderate_text, flag=extra, border=SPACING) self.gauge_sizer.AddSpacer((SPACING, SPACING)) self.gauge_sizer.Add(self.fancy_radio, flag=gauge, border=SPACING) self.gauge_sizer.Add(self.fancy_sample, flag=extra, border=SPACING) self.gauge_sizer.Add(self.fancy_text, flag=extra, border=SPACING) self.sizer.AddFirst(self.gauge_sizer, flag=wx.GROW) # setup self.pb_group = (self.null_radio, self.simple_radio, self.moderate_radio, self.fancy_radio) for r in self.pb_group: r.Bind(wx.EVT_RADIOBUTTON, self.radio) if r.value == wx.the_app.config[self.pb_config_key]: r.SetValue(True) else: r.SetValue(False) # toolbar widgets self.toolbar_box = wx.StaticBox(self, label=_("Toolbar style:")) self.toolbar_text = CheckButton( self, _("Show text"), self.settings_window, 'toolbar_text', self.settings_window.config['toolbar_text'], wx.the_app.reset_toolbar_style) self.toolbar_size_text = ElectroStaticText(self, id=wx.ID_ANY, label=_("Icon size:")) self.toolbar_size_choice = wx.Choice(self, choices=(_("Small"), _("Normal"), _("Large"))) self.toolbar_config_to_choice(wx.the_app.config['toolbar_size']) self.toolbar_size_choice.Bind(wx.EVT_CHOICE, self.toolbar_choice_to_config) # toolbar sizers self.toolbar_sizer = HSizer() self.toolbar_sizer.AddFirst(self.toolbar_text, flag=wx.ALIGN_CENTER_VERTICAL) line = wx.StaticLine(self, id=wx.ID_ANY, style=wx.VERTICAL) self.toolbar_sizer.Add(line, flag=wx.ALIGN_CENTER_VERTICAL | wx.GROW) self.toolbar_sizer.Add(self.toolbar_size_text, flag=wx.ALIGN_CENTER_VERTICAL) self.toolbar_sizer.Add(self.toolbar_size_choice, flag=wx.GROW | wx.ALIGN_TOP, proportion=1) self.toolbar_box_sizer = wx.StaticBoxSizer(self.toolbar_box, wx.VERTICAL) self.toolbar_box_sizer.Add(self.toolbar_sizer, flag=wx.GROW) self.sizer.Add(self.toolbar_box_sizer, flag=wx.GROW) if wx.the_app.config['debug']: # the T-Word widgets self.themes = [] self.theme_choice = wx.Choice(self, choices=[]) self.theme_choice.Enable(False) self.theme_choice.Bind(wx.EVT_CHOICE, self.set_theme) self.restart_hint = ElectroStaticText( self, id=wx.ID_ANY, label=_("(Changing themes requires restart.)")) self.theme_static_box = wx.StaticBox(self, label=_("Theme:")) # the T-Word sizers self.theme_sizer = VSizer() self.theme_sizer.AddFirst(self.theme_choice, flag=wx.GROW | wx.ALIGN_RIGHT) self.theme_sizer.Add(self.restart_hint, flag=wx.GROW | wx.ALIGN_RIGHT) self.theme_static_box_sizer = wx.StaticBoxSizer( self.theme_static_box, wx.VERTICAL) self.theme_static_box_sizer.Add(self.theme_sizer, flag=wx.GROW) self.sizer.Add(self.theme_static_box_sizer, flag=wx.GROW) self.get_themes() def get_themes(self): def _callback(themes): self.themes.extend(themes) self.theme_choice.AppendItems(strings=themes) curr_theme = wx.the_app.config['theme'] if curr_theme not in self.themes: self.settings_window.setfunc('theme', 'default') curr_theme = wx.the_app.config['theme'] curr_idx = self.themes.index(curr_theme) self.theme_choice.SetSelection(curr_idx) self.theme_choice.Enable(True) def callback(themes): gui_wrap(_callback, themes) df = list_themes() df.addCallback(callback) df.getResult() def set_theme(self, e): i = self.theme_choice.GetSelection() t = self.themes[i] self.settings_window.setfunc('theme', t) def toolbar_choice_to_config(self, *a): i = self.toolbar_size_choice.GetSelection(), size = 8 * (i[0] + 2) self.settings_window.setfunc('toolbar_size', size) wx.the_app.reset_toolbar_style() def toolbar_config_to_choice(self, value): i = (value // 8) - 2 self.toolbar_size_choice.SetSelection(i) def new_sample(self, sample_class, value): sample = sample_class(self, size=wx.Size(-1, 20), style=wx.SUNKEN_BORDER) # I happen to know 200 is the right number because I looked. sample.SetValue(self.sample_value, 'running', (200, 0, self.sample_data)) sample.Bind(wx.EVT_LEFT_DOWN, self.sample) sample.Bind(wx.EVT_CONTEXT_MENU, None) sample.value = value return sample def radio(self, event): widget = event.GetEventObject() value = widget.value self.settings_window.setfunc(self.pb_config_key, value) gui_wrap(wx.the_app.main_window.torrentlist.change_gauge_type, value) def sample(self, event): self.radio(event) pb = event.GetEventObject() value = pb.value for p in self.pb_group: if p.value == value: p.SetValue(True) break