def __init__(self, parent): wx.StatusBar.__init__(self, parent, style=wx.ST_SIZEGRIP) # On Linux/OS X the resize handle and icons overlap, therefore we add an extra field. # On Windows this field is automatically set to 1 when the wx.ST_SIZEGRIP is set. self.SetFieldsCount(7) self.SetStatusStyles([wx.SB_FLAT] * 7) self.SetStatusWidths([-1, 250, 50, 19, 19, 19, 19]) self._gui_image_manager = GuiImageManager.getInstance() self.guiutility = GUIUtility.getInstance() self.utility = self.guiutility.utility self.library_manager = self.guiutility.library_manager self.ff_checkbox = wx.CheckBox(self, -1, 'Family filter', style=wx.ALIGN_RIGHT) self.ff_checkbox.Bind(wx.EVT_CHECKBOX, self.OnCheckbox) self.ff_checkbox.SetValue(self.guiutility.getFamilyFilter()) self.speed_down_icon = self._gui_image_manager.getBitmap(self, u"arrow", self.GetBackgroundColour(), state=0) self.speed_down_sbmp = wx.StaticBitmap(self, -1, self.speed_down_icon) self.speed_down_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_down = wx.StaticText(self, -1, '') self.speed_down.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_up_icon = self.speed_down_icon.ConvertToImage().Rotate90().Rotate90().ConvertToBitmap() self.speed_up_sbmp = wx.StaticBitmap(self, -1, self.speed_up_icon) self.speed_up_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.speed_up = wx.StaticText(self, -1, '') self.speed_up.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.free_space_icon = self._gui_image_manager.getImage(u"drive.png") self.free_space_sbmp = wx.StaticBitmap(self, -1, self.free_space_icon) self.free_space = wx.StaticText(self, -1, '') self.searchConnectionImages = [u"progressbarEmpty.png", u"progressbarFull.png"] self.searchConnectionImages = [self._gui_image_manager.getImage(image) for image in self.searchConnectionImages] self.activityImages = [u"statusbar_activity.png", u"statusbar_noactivity.png"] self.activityImages = [self._gui_image_manager.getImage(image) for image in self.activityImages] self.connection = HorizontalGauge(self, self.searchConnectionImages[0], self.searchConnectionImages[1]) self.activity = wx.StaticBitmap(self, -1, self.activityImages[1]) self.activity_timer = None self.channelconnections = 0 self.bmp_firewall_warning = self._gui_image_manager.getImage(u"statusbar_warning.png") self.bmp_firewall_ok = self._gui_image_manager.getImage(u"statusbar_ok.png") self.firewallStatus = ActionButton(self, -1, self.bmp_firewall_warning) self.firewallStatus.SetSize((16, 16)) self.firewallStatus.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) self.firewallStatus.SetToolTipString('Port status unknown') self.firewallStatus.Enable(False) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_warning) self.SetTransferSpeeds(0, 0) self.Bind(wx.EVT_SIZE, self.OnSize) self.library_manager.add_download_state_callback(self.RefreshTransferSpeed)
class SRstatusbar(wx.StatusBar): def __init__(self, parent): wx.StatusBar.__init__(self, parent, style=wx.ST_SIZEGRIP) # On Linux/OS X the resize handle and icons overlap, therefore we add an extra field. # On Windows this field is automatically set to 1 when the wx.ST_SIZEGRIP is set. self.SetFieldsCount(7) self.SetStatusStyles([wx.SB_FLAT] * 7) self.SetStatusWidths([-1, 250, 50, 19, 19, 19, 19]) self._gui_image_manager = GuiImageManager.getInstance() self.guiutility = GUIUtility.getInstance() self.utility = self.guiutility.utility self.library_manager = self.guiutility.library_manager self.ff_checkbox = wx.CheckBox(self, -1, 'Family filter', style=wx.ALIGN_RIGHT) self.ff_checkbox.Bind(wx.EVT_CHECKBOX, self.OnCheckbox) self.ff_checkbox.SetValue(self.guiutility.getFamilyFilter()) self.speed_down_icon = self._gui_image_manager.getBitmap(self, u"arrow", self.GetBackgroundColour(), state=0) self.speed_down_sbmp = wx.StaticBitmap(self, -1, self.speed_down_icon) self.speed_down_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_down = wx.StaticText(self, -1, '') self.speed_down.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_up_icon = self.speed_down_icon.ConvertToImage().Rotate90().Rotate90().ConvertToBitmap() self.speed_up_sbmp = wx.StaticBitmap(self, -1, self.speed_up_icon) self.speed_up_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.speed_up = wx.StaticText(self, -1, '') self.speed_up.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.free_space_icon = self._gui_image_manager.getImage(u"drive.png") self.free_space_sbmp = wx.StaticBitmap(self, -1, self.free_space_icon) self.free_space = wx.StaticText(self, -1, '') self.searchConnectionImages = [u"progressbarEmpty.png", u"progressbarFull.png"] self.searchConnectionImages = [self._gui_image_manager.getImage(image) for image in self.searchConnectionImages] self.activityImages = [u"statusbar_activity.png", u"statusbar_noactivity.png"] self.activityImages = [self._gui_image_manager.getImage(image) for image in self.activityImages] self.connection = HorizontalGauge(self, self.searchConnectionImages[0], self.searchConnectionImages[1]) self.activity = wx.StaticBitmap(self, -1, self.activityImages[1]) self.activity_timer = None self.channelconnections = 0 self.bmp_firewall_warning = self._gui_image_manager.getImage(u"statusbar_warning.png") self.bmp_firewall_ok = self._gui_image_manager.getImage(u"statusbar_ok.png") self.firewallStatus = ActionButton(self, -1, self.bmp_firewall_warning) self.firewallStatus.SetSize((16, 16)) self.firewallStatus.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) self.firewallStatus.SetToolTipString('Port status unknown') self.firewallStatus.Enable(False) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_warning) self.SetTransferSpeeds(0, 0) self.Bind(wx.EVT_SIZE, self.OnSize) self.library_manager.add_download_state_callback(self.RefreshTransferSpeed) @forceWxThread def RefreshFreeSpace(self, space): if space >= 0: space_str = size_format(space, truncate=1) space_label = space_str.replace(' ', '') space_tooltip = 'You currently have %s of disk space available on your default download location.' % space_str self.free_space.SetLabel(space_label) self.free_space.SetToolTipString(space_tooltip) self.free_space.Show(True) self.free_space_sbmp.SetToolTipString(space_tooltip) self.free_space_sbmp.Show(True) else: self.free_space.Show(False) self.free_space_sbmp.Show(False) self.Reposition() def RefreshTransferSpeed(self, dslist, magnetlist): if not self: return total_down, total_up = 0.0, 0.0 for ds in dslist: total_down += ds.get_current_speed(DOWNLOAD) total_up += ds.get_current_speed(UPLOAD) self.SetTransferSpeeds(total_down, total_up) @warnWxThread def SetTransferSpeeds(self, down, up): self.speed_down.SetLabel(speed_format(down)) self.speed_up.SetLabel(speed_format(up)) self.Reposition() def SetGlobalMaxSpeed(self, direction, value): if direction in [UPLOAD, DOWNLOAD]: if direction == UPLOAD: self.utility.write_config('maxuploadrate', value) self.guiutility.utility.session.set_max_upload_speed(value) else: self.utility.write_config('maxdownloadrate', value) self.guiutility.utility.session.set_max_download_speed(value) def GetSpeedChoices(self, value): values = round_range(max(0, value)) if value != 0 else range(0, 1000, 100) values = [value or -1 for value in values] if value != 0 and value not in values: values.append(value) values.sort() values.append(0) return [('unlimited' if value == 0 else ('0' if value == -1 else str(value)), value) for value in values] def OnDownloadPopup(self, event): menu = wx.Menu() current = self.utility.read_config('maxdownloadrate') value_tuples = self.GetSpeedChoices(current) for value_str, value in value_tuples: itemid = wx.NewId() menu.AppendRadioItem(itemid, value_str) menu.Bind(wx.EVT_MENU, lambda x, v=value: self.SetGlobalMaxSpeed(DOWNLOAD, v), id=itemid) menu.Check(itemid, current == value) self.speed_down.PopupMenu(menu, event.GetPosition()) menu.Destroy() self.speed_down.Layout() def OnUploadPopup(self, event): menu = wx.Menu() current = self.utility.read_config('maxuploadrate') value_tuples = self.GetSpeedChoices(current) for value_str, value in value_tuples: itemid = wx.NewId() menu.AppendRadioItem(itemid, value_str) menu.Bind(wx.EVT_MENU, lambda x, v=value: self.SetGlobalMaxSpeed(UPLOAD, v), id=itemid) menu.Check(itemid, current == value) self.speed_up.PopupMenu(menu, event.GetPosition()) menu.Destroy() self.speed_up.Layout() def OnCheckbox(self, event): checkbox = event.GetEventObject() checkbox.Enable(False) wx.CallLater(1000, checkbox.Enable, True) wx.CallLater(100, self.__toggleFF, event.GetEventObject().GetValue()) @warnWxThread def __toggleFF(self, newvalue): if newvalue != self.guiutility.getFamilyFilter(): self.guiutility.toggleFamilyFilter(newvalue) @warnWxThread def SetConnections(self, connectionPercentage, totalConnections, channelConnections): self.connection.SetPercentage(connectionPercentage) self.connection.SetToolTipString('Connected to %d peers' % totalConnections) self.channelconnections = channelConnections def GetConnections(self): return self.connection.GetPercentage() def GetChannelConnections(self): return self.channelconnections @warnWxThread def onReachable(self, event=None): if not self.guiutility.firewall_restart: self.firewallStatus.SetBitmapLabel(self.bmp_firewall_ok) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_ok) self.firewallStatus.SetToolTipString('Port is working') @warnWxThread def IsReachable(self): if not self.guiutility.firewall_restart: return self.firewallStatus.GetBitmapLabel() == self.bmp_firewall_ok return False @warnWxThread def onActivity(self, msg): if self.activity_timer: self.activity_timer.Stop() def revert(): if not self: return self.activity.SetBitmap(self.activityImages[1]) self.activity.Refresh() self.activity.SetBitmap(self.activityImages[0]) self.activity.Refresh() self.activity.SetToolTipString(msg) self.activity_timer = wx.CallLater(300, revert) def OnSize(self, event): self.Reposition() def Reposition(self): self.Freeze() rect = self.GetFieldRect(0) self.ff_checkbox.SetPosition((rect.x + 2, rect.y + 2)) self.ff_checkbox.SetSize((-1, rect.height - 4)) rect = self.GetFieldRect(1) x = rect.x + rect.width - 15 for control in reversed([self.speed_down_sbmp, self.speed_down, self.speed_up_sbmp, self.speed_up]): spacer = 10 if not isinstance(control, wx.StaticBitmap) else 7 x -= control.GetSize()[0] + spacer yAdd = (rect.height - control.GetSize()[1]) / 2 control.SetPosition((x, rect.y + yAdd)) rect = self.GetFieldRect(2) x = rect.x + rect.width for control in [self.free_space, self.free_space_sbmp]: size = control.GetSize() yAdd = (rect.height - size[1]) / 2 x -= size[0] + 5 control.SetPosition((x, rect.y + yAdd)) rect = self.GetFieldRect(3) size = self.connection.GetSize() yAdd = (rect.height - size[1]) / 2 xAdd = (rect.width - size[0]) / 2 self.connection.SetPosition((rect.x + xAdd, rect.y + yAdd)) rect = self.GetFieldRect(4) size = self.activity.GetSize() yAdd = (rect.height - size[1]) / 2 xAdd = (rect.width - size[0]) / 2 self.activity.SetPosition((rect.x + xAdd, rect.y + yAdd)) rect = self.GetFieldRect(5) size = self.firewallStatus.GetSize() yAdd = (rect.height - size[1]) / 2 xAdd = (rect.width - size[0]) / 2 self.firewallStatus.SetPosition((rect.x + xAdd, rect.y + yAdd)) self.sizeChanged = False self.Thaw()
class TopSearchPanel(FancyPanel): def __init__(self, parent): self._logger = logging.getLogger(self.__class__.__name__) self._logger.debug("TopSearchPanel: __init__") self.loaded_bitmap = None self.guiutility = GUIUtility.getInstance() self.utility = self.guiutility.utility self.installdir = self.utility.getPath() self.tdb = self.utility.session.open_dbhandler(NTFY_TORRENTS) self.collectedTorrents = {} FancyPanel.__init__(self, parent, border=wx.BOTTOM) self.SetBorderColour(SEPARATOR_GREY) self.SetBackgroundColour(GRADIENT_LGREY, GRADIENT_DGREY) self.AddComponents() self.Bind(wx.EVT_SIZE, self.OnResize) def AddComponents(self): self.SetForegroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)) self._logger.debug("TopSearchPanel: OnCreate") gui_image_manager = GuiImageManager.getInstance() # TODO martijn: on OS X, the wx.SearchCtrl element is bugged (doesn't show a placeholder unless focussed). # for now, we replaced the occurrences of wx.SearchCtrl with wx.TextCtrl elements. if sys.platform == 'darwin': self.searchField = wx.TextCtrl(self, -1, style=wx.TE_PROCESS_ENTER) self.searchField.Bind(wx.EVT_TEXT_ENTER, self.OnSearchKeyDown) self.searchField.SetHint('Search Files or Channels') self.searchField.SetMinSize((400, 22)) else: self.searchFieldPanel = FancyPanel(self, radius=5, border=wx.ALL) self.searchFieldPanel.SetBorderColour(SEPARATOR_GREY, highlight=TRIBLER_RED) self.searchField = TextCtrlAutoComplete( self.searchFieldPanel, style=wx.NO_BORDER, entrycallback=self.complete) # Since we have set the style to wx.NO_BORDER, the default height will be # too large. Therefore, we need to set the correct height. _, height = self.GetTextExtent("Gg") self.searchField.SetMinSize((-1, height)) self.searchFieldPanel.SetMinSize((400, 25)) self.searchFieldPanel.SetBackgroundColour( self.searchField.GetBackgroundColour()) self.searchField.Bind(wx.EVT_KILL_FOCUS, self.searchFieldPanel.OnKillFocus) self.searchField.Bind(wx.EVT_TEXT_ENTER, self.OnSearchKeyDown) self.go = ProgressButton(self, -1) self.go.SetMinSize((50, 25)) self.go.Bind(wx.EVT_LEFT_UP, self.OnSearchKeyDown) ag_fname = os.path.join(self.guiutility.utility.getPath(), LIBRARYNAME, 'Main', 'vwxGUI', 'images', 'search_new.gif') self.ag = wx.animate.GIFAnimationCtrl(self, -1, ag_fname) self.ag.UseBackgroundColour(True) self.ag.SetBackgroundColour(wx.Colour(244, 244, 244)) self.ag.Hide() download_bmp = gui_image_manager.getImage(u"download.png") self.download_btn = ActionButton(self, -1, download_bmp) self.download_btn.Enable(False) upload_bmp = gui_image_manager.getImage(u"upload.png") self.upload_btn = ActionButton(self, -1, upload_bmp) self.upload_btn.Enable(False) stop_bmp = gui_image_manager.getImage(u"pause.png") self.stop_btn = ActionButton(self, -1, stop_bmp) self.stop_btn.Enable(False) delete_bmp = gui_image_manager.getImage(u"delete.png") self.delete_btn = ActionButton(self, -1, delete_bmp) self.delete_btn.Enable(False) play_bmp = gui_image_manager.getImage(u"play.png") self.play_btn = ActionButton(self, -1, play_bmp) self.play_btn.Enable(False) add_bmp = gui_image_manager.getImage(u"add.png") self.add_btn = ActionButton(self, -1, add_bmp) self.SetButtonHandler(self.add_btn, self.OnAdd, 'Download an external torrent.') settings_bmp = gui_image_manager.getImage(u"settings.png") self.settings_btn = ActionButton(self, -1, settings_bmp) self.SetButtonHandler(self.settings_btn, self.OnSettings, 'Change settings.') mainSizer = wx.BoxSizer(wx.HORIZONTAL) if sys.platform != 'darwin': vSizer = wx.BoxSizer(wx.VERTICAL) vSizer.AddStretchSpacer() vSizer.Add( self.searchField, 0, wx.EXPAND | wx.RESERVE_SPACE_EVEN_IF_HIDDEN | wx.LEFT | wx.RIGHT, 5) vSizer.AddStretchSpacer() self.searchFieldPanel.SetSizer(vSizer) vSizer.Layout() # Add searchbox etc. self.searchSizer = wx.BoxSizer(wx.VERTICAL) searchBoxSizer = wx.BoxSizer(wx.HORIZONTAL) if sys.platform == 'darwin': searchBoxSizer.Add(self.searchField, 1, wx.CENTER | wx.RESERVE_SPACE_EVEN_IF_HIDDEN) else: searchBoxSizer.Add(self.searchFieldPanel, 1, wx.CENTER | wx.RESERVE_SPACE_EVEN_IF_HIDDEN) searchBoxSizer.Add(self.go, 0, wx.CENTER | wx.LEFT | wx.RESERVE_SPACE_EVEN_IF_HIDDEN, 5) # add searchbutton searchBoxSizer.Add(self.ag, 0, wx.CENTER | wx.LEFT | wx.RESERVE_SPACE_EVEN_IF_HIDDEN, 5) # add animation self.searchSizer.Add(searchBoxSizer, 1, wx.EXPAND) # finished searchSizer, add to mainSizer mainSizer.Add(self.searchSizer, 0, wx.EXPAND | wx.LEFT, 10) mainSizer.AddSpacer((40, 0)) # add buttons buttonSizer = wx.BoxSizer(wx.HORIZONTAL) buttonSizer.Add(self.download_btn, 0, wx.CENTER | wx.RIGHT, 5) buttonSizer.Add(self.upload_btn, 0, wx.CENTER | wx.RIGHT, 5) buttonSizer.Add(self.stop_btn, 0, wx.CENTER | wx.RIGHT, 5) buttonSizer.Add(self.delete_btn, 0, wx.CENTER | wx.RIGHT, 5) buttonSizer.Add(self.play_btn, 0, wx.CENTER | wx.RIGHT, 5) buttonSizer.AddSpacer((35, 0)) buttonSizer.AddStretchSpacer() buttonSizer.Add(self.add_btn, 0, wx.CENTER | wx.RIGHT, 5) buttonSizer.Add(self.settings_btn, 0, wx.CENTER | wx.RIGHT, 5) mainSizer.Add(buttonSizer, 1, wx.EXPAND) self.SetSizer(mainSizer) self.Layout() def OnResize(self, event): self.Refresh() event.Skip() def OnSearchKeyDown(self, event=None): if self.go.IsEnabled(): self._logger.debug("TopSearchPanel: OnSearchKeyDown") if getattr(self.searchField, 'ShowDropDown', False): self.searchField.ShowDropDown(False) self.guiutility.dosearch() self.go.Enable(False) wx.CallLater(2500, self.go.Enable, True) def OnSettings(self, event): self.guiutility.ShowPage('settings') def OnAdd(self, event): dlg = AddTorrent(None, self.guiutility.frame) dlg.CenterOnParent() dlg.ShowModal() dlg.Destroy() def OnStats(self, event): self.guiutility.ShowPage('stats') def StartSearch(self): if getattr(self.searchField, 'ShowDropDown', False): self.searchField.ShowDropDown(False) self.guiutility.frame.searchlist.ResetBottomWindow() self.Freeze() self.go.SetValue(0) self.guiutility.frame.top_bg.ag.Play() self.guiutility.frame.top_bg.ag.Show() self.Thaw() def ShowSearching(self, max): if not self or not self.go: return self.go.SetRange(max + 16) cancelWorker(u"FakeResult") startWorker(None, self.FakeResult, uId=u"FakeResult", delay=0.25, workerType="ThreadPool") @forceWxThread def FakeResult(self, times=1): if not self: return newValue = min(self.go.GetValue() + 1, self.go.GetRange()) if times < 16: self.go.SetValue(newValue) startWorker(None, self.FakeResult, wargs=(times + 1, ), uId=u"FakeResult", delay=0.25, workerType="ThreadPool") def NewResult(self): maxValue = self.go.GetRange() newValue = min(self.go.GetValue() + 1, maxValue) self.guiutility.frame.top_bg.go.SetValue(newValue) if newValue == maxValue: return True return False def SetFinished(self): self.Freeze() self.ag.Stop() self.ag.Hide() self.go.SetValue(self.go.GetRange()) self.Layout() self.Thaw() def complete(self, term): ignore_list = ["http://", "https://", "magnet:"] for ignore in ignore_list: if term.startswith(ignore): return [] """autocompletes term.""" if len(term) > 1: return self.tdb.getAutoCompleteTerms(term, max_terms=7) return [] def SearchFocus(self): if self.guiutility.guiPage == 'home': if getattr(self.GetParent(), 'home', False): self.GetParent().home.SearchFocus() else: self.searchField.SetFocus() self.searchField.SelectAll() def AddCollectedTorrent(self, coltorrent): self.collectedTorrents[coltorrent.infohash] = coltorrent self.TorrentsChanged() def GetSelectedTorrents(self): torrents = None page = self.guiutility.guiPage if page in [ 'search_results', 'selectedchannel', 'playlist', 'my_files' ]: list = self.guiutility.GetSelectedPage() items = list.GetExpandedItems() torrents = [ item[1].original_data for item in items if isinstance(item[1].original_data, Torrent) or isinstance(item[1].original_data, CollectedTorrent) ] return torrents def TorrentsChanged(self): self.RefreshTorrents(self.GetSelectedTorrents()) def RefreshTorrents(self, torrents): inDownloads = self.guiutility.guiPage == 'my_files' if torrents: isMultiple = len(torrents) > 1 usedCollectedTorrents = set() # we have 7 different states, able to resume seeding, resume downloading, # download, stop seeding, stop downloading, delete, or play # TODO(emilon): This is so ugly. At least we should use a named tuple. states = [0, 0, 0, 0, 0, 0, 0] for torrent in torrents: if 'stopped' in torrent.state: if 'completed' in torrent.state: states[0] += 1 else: states[1] += 1 elif not torrent.state: states[2] += 1 if 'active' in torrent.state: if 'completed' in torrent.state: states[3] += 1 else: states[4] += 1 if torrent.state or inDownloads: states[5] += 1 if "metadata" not in torrent.state and torrent.infohash in self.collectedTorrents: coltorrent = self.collectedTorrents[torrent.infohash] if coltorrent.isPlayable(): states[6] += 1 usedCollectedTorrents.add(torrent.infohash) else: # If the torrent isn't collected we assume its playable and let the core cancel the VOD if it isn't. states[6] += 1 enableDownload = states[1] + states[2] if enableDownload: if isMultiple: self.SetButtonHandler( self.download_btn, self.OnDownload, 'Resume downloading %d torrent(s).' % enableDownload) elif states[1]: self.SetButtonHandler(self.download_btn, self.OnResume, 'Resume downloading this torrent.') else: self.SetButtonHandler(self.download_btn, self.OnDownload, 'Start downloading this torrent.') else: self.SetButtonHandler(self.download_btn, None) enableUpload = states[0] if enableUpload: if isMultiple: self.SetButtonHandler( self.upload_btn, self.OnUpload, 'Resume seeding %d torrent(s).' % enableUpload) else: self.SetButtonHandler(self.upload_btn, self.OnUpload, 'Resume seeding this torrent.') else: self.SetButtonHandler(self.upload_btn, None) enableStop = states[3] + states[4] if enableStop: if isMultiple: self.SetButtonHandler(self.stop_btn, self.OnStop, 'Stop %d torrent(s).' % enableStop) elif states[3]: self.SetButtonHandler(self.stop_btn, self.OnStop, 'Stop seeding this torrent.') else: self.SetButtonHandler(self.stop_btn, self.OnStop, 'Stop downloading this torrent.') else: self.SetButtonHandler(self.stop_btn, None) if states[5] > 1: self.SetButtonHandler(self.delete_btn, self.OnDelete, 'Delete %d torrent(s).' % states[5]) elif states[5]: self.SetButtonHandler(self.delete_btn, self.OnDelete, 'Delete this torrent.') else: self.SetButtonHandler(self.delete_btn, None) if isMultiple: self.SetButtonHandler( self.play_btn, self.OnPlay, 'Start playing one of the selected torrents.') elif states[6]: self.SetButtonHandler(self.play_btn, self.OnPlay, 'Start playing this torrent.') else: self.SetButtonHandler(self.play_btn, None) for infohash in self.collectedTorrents.keys(): if infohash not in usedCollectedTorrents: del self.collectedTorrents[infohash] else: self.ClearButtonHandlers() def SetButtonHandler(self, button, handler=None, tooltip=None): button.Enable(bool(handler)) if handler: button.Bind(wx.EVT_LEFT_UP, handler) if tooltip and sys.platform != 'darwin': button.SetToolTipString(tooltip) else: button.SetToolTip(None) else: button.SetToolTip(None) def ClearButtonHandlers(self): self.SetButtonHandler(self.download_btn, None) self.SetButtonHandler(self.upload_btn, None) self.SetButtonHandler(self.play_btn, None) self.SetButtonHandler(self.stop_btn, None) self.SetButtonHandler(self.delete_btn, None) def OnDownload(self, event=None, torrents=None): refresh_library = False torrents = torrents if torrents is not None else self.GetSelectedTorrents( ) for torrent in torrents: if 'stopped' in torrent.state: self.guiutility.library_manager.resumeTorrent(torrent) else: if self.guiutility.frame.selectedchannellist.IsShownOnScreen(): self.guiutility.frame.selectedchannellist.StartDownload( torrent) else: self.guiutility.torrentsearch_manager.downloadTorrent( torrent) refresh_library = True if event: button = event.GetEventObject() button.Enable(False) wx.CallLater(3000, button.Enable, True) if refresh_library: wx.CallLater( 1000, self.guiutility.frame.librarylist.do_or_schedule_refresh, True) def OnUpload(self, event): for torrent in self.GetSelectedTorrents(): if 'completed' in torrent.state: self.guiutility.library_manager.resumeTorrent(torrent) if event: button = event.GetEventObject() button.Enable(False) def OnPlay(self, event): # Select the first playable torrent or not collected torrent. Return if none can be found torrent = None for t in self.GetSelectedTorrents(): if t.infohash in self.collectedTorrents: coltor = self.collectedTorrents[t.infohash] if coltor.isPlayable(): torrent = coltor break else: torrent = t break if not torrent: return self.guiutility.library_manager.playTorrent(torrent.infohash) button = event.GetEventObject() button.Enable(False) def OnResume(self, event=None): for torrent in self.GetSelectedTorrents(): self.guiutility.library_manager.resumeTorrent(torrent) if event: button = event.GetEventObject() button.Enable(False) def OnStop(self, event=None): for torrent in self.GetSelectedTorrents(): self.guiutility.library_manager.stopTorrent(torrent.infohash) if event: button = event.GetEventObject() button.Enable(False) def OnDelete(self, event=None, silent=False, delete=False): torrents = self.GetSelectedTorrents() if not silent: dlg = RemoveTorrent(None, torrents) button_id = dlg.ShowModal() else: button_id = wx.ID_DELETE if delete else wx.ID_DEFAULT refresh_library = False if button_id in [wx.ID_DEFAULT, wx.ID_DELETE]: for torrent in torrents: self.guiutility.library_manager.deleteTorrent( torrent, button_id == wx.ID_DELETE) refresh_library = True if not silent: if dlg.newName: if dlg.newName.IsChanged(): dlg2 = wx.MessageDialog( None, 'Do you want to save your changes made to this torrent?', 'Save changes?', wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION) if dlg2.ShowModal() == wx.ID_YES: self.guiutility.channelsearch_manager.modifyTorrent( torrent.channel.id, torrent.channeltorrent_id, {'name': dlg.newName.GetValue()}) dlg2.Destroy() dlg.Destroy() if refresh_library: wx.CallLater( 1000, self.guiutility.frame.librarylist.do_or_schedule_refresh, True)
def AddComponents(self): self.SetForegroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)) self._logger.debug("TopSearchPanel: OnCreate") gui_image_manager = GuiImageManager.getInstance() # TODO martijn: on OS X, the wx.SearchCtrl element is bugged (doesn't show a placeholder unless focussed). # for now, we replaced the occurrences of wx.SearchCtrl with wx.TextCtrl elements. if sys.platform == 'darwin': self.searchField = wx.TextCtrl(self, -1, style=wx.TE_PROCESS_ENTER) self.searchField.Bind(wx.EVT_TEXT_ENTER, self.OnSearchKeyDown) self.searchField.SetHint('Search Files or Channels') self.searchField.SetMinSize((400, 22)) else: self.searchFieldPanel = FancyPanel(self, radius=5, border=wx.ALL) self.searchFieldPanel.SetBorderColour(SEPARATOR_GREY, highlight=TRIBLER_RED) self.searchField = TextCtrlAutoComplete( self.searchFieldPanel, style=wx.NO_BORDER, entrycallback=self.complete) # Since we have set the style to wx.NO_BORDER, the default height will be # too large. Therefore, we need to set the correct height. _, height = self.GetTextExtent("Gg") self.searchField.SetMinSize((-1, height)) self.searchFieldPanel.SetMinSize((400, 25)) self.searchFieldPanel.SetBackgroundColour( self.searchField.GetBackgroundColour()) self.searchField.Bind(wx.EVT_KILL_FOCUS, self.searchFieldPanel.OnKillFocus) self.searchField.Bind(wx.EVT_TEXT_ENTER, self.OnSearchKeyDown) self.go = ProgressButton(self, -1) self.go.SetMinSize((50, 25)) self.go.Bind(wx.EVT_LEFT_UP, self.OnSearchKeyDown) ag_fname = os.path.join(self.guiutility.utility.getPath(), LIBRARYNAME, 'Main', 'vwxGUI', 'images', 'search_new.gif') self.ag = wx.animate.GIFAnimationCtrl(self, -1, ag_fname) self.ag.UseBackgroundColour(True) self.ag.SetBackgroundColour(wx.Colour(244, 244, 244)) self.ag.Hide() download_bmp = gui_image_manager.getImage(u"download.png") self.download_btn = ActionButton(self, -1, download_bmp) self.download_btn.Enable(False) upload_bmp = gui_image_manager.getImage(u"upload.png") self.upload_btn = ActionButton(self, -1, upload_bmp) self.upload_btn.Enable(False) stop_bmp = gui_image_manager.getImage(u"pause.png") self.stop_btn = ActionButton(self, -1, stop_bmp) self.stop_btn.Enable(False) delete_bmp = gui_image_manager.getImage(u"delete.png") self.delete_btn = ActionButton(self, -1, delete_bmp) self.delete_btn.Enable(False) play_bmp = gui_image_manager.getImage(u"play.png") self.play_btn = ActionButton(self, -1, play_bmp) self.play_btn.Enable(False) add_bmp = gui_image_manager.getImage(u"add.png") self.add_btn = ActionButton(self, -1, add_bmp) self.SetButtonHandler(self.add_btn, self.OnAdd, 'Download an external torrent.') settings_bmp = gui_image_manager.getImage(u"settings.png") self.settings_btn = ActionButton(self, -1, settings_bmp) self.SetButtonHandler(self.settings_btn, self.OnSettings, 'Change settings.') mainSizer = wx.BoxSizer(wx.HORIZONTAL) if sys.platform != 'darwin': vSizer = wx.BoxSizer(wx.VERTICAL) vSizer.AddStretchSpacer() vSizer.Add( self.searchField, 0, wx.EXPAND | wx.RESERVE_SPACE_EVEN_IF_HIDDEN | wx.LEFT | wx.RIGHT, 5) vSizer.AddStretchSpacer() self.searchFieldPanel.SetSizer(vSizer) vSizer.Layout() # Add searchbox etc. self.searchSizer = wx.BoxSizer(wx.VERTICAL) searchBoxSizer = wx.BoxSizer(wx.HORIZONTAL) if sys.platform == 'darwin': searchBoxSizer.Add(self.searchField, 1, wx.CENTER | wx.RESERVE_SPACE_EVEN_IF_HIDDEN) else: searchBoxSizer.Add(self.searchFieldPanel, 1, wx.CENTER | wx.RESERVE_SPACE_EVEN_IF_HIDDEN) searchBoxSizer.Add(self.go, 0, wx.CENTER | wx.LEFT | wx.RESERVE_SPACE_EVEN_IF_HIDDEN, 5) # add searchbutton searchBoxSizer.Add(self.ag, 0, wx.CENTER | wx.LEFT | wx.RESERVE_SPACE_EVEN_IF_HIDDEN, 5) # add animation self.searchSizer.Add(searchBoxSizer, 1, wx.EXPAND) # finished searchSizer, add to mainSizer mainSizer.Add(self.searchSizer, 0, wx.EXPAND | wx.LEFT, 10) mainSizer.AddSpacer((40, 0)) # add buttons buttonSizer = wx.BoxSizer(wx.HORIZONTAL) buttonSizer.Add(self.download_btn, 0, wx.CENTER | wx.RIGHT, 5) buttonSizer.Add(self.upload_btn, 0, wx.CENTER | wx.RIGHT, 5) buttonSizer.Add(self.stop_btn, 0, wx.CENTER | wx.RIGHT, 5) buttonSizer.Add(self.delete_btn, 0, wx.CENTER | wx.RIGHT, 5) buttonSizer.Add(self.play_btn, 0, wx.CENTER | wx.RIGHT, 5) buttonSizer.AddSpacer((35, 0)) buttonSizer.AddStretchSpacer() buttonSizer.Add(self.add_btn, 0, wx.CENTER | wx.RIGHT, 5) buttonSizer.Add(self.settings_btn, 0, wx.CENTER | wx.RIGHT, 5) mainSizer.Add(buttonSizer, 1, wx.EXPAND) self.SetSizer(mainSizer) self.Layout()
class EmbeddedPlayerPanel(wx.Panel): """ The Embedded Player consists of a VLCWindow and the media controls such as Play/Pause buttons and Volume Control. """ VIDEO_SIZE = (320, 240) def __init__(self, parent, utility, vlcwrap, bg): wx.Panel.__init__(self, parent, -1) self.utility = utility self.guiutility = utility.guiUtility self.parent = parent self.SetBackgroundColour(DEFAULT_BACKGROUND) self.volume = 0.48 self.oldvolume = 0.48 self.estduration = None self.fullscreenwindow = None self.download = None self.update = True self.timeoffset = None vSizer = wx.BoxSizer(wx.VERTICAL) self.vlcwrap = vlcwrap if vlcwrap: self.vlcwin = VLCWindow(self, vlcwrap) self.vlcwin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vSizer.Add(self.vlcwin, 1, wx.EXPAND, 0) self.logowin = LogoWindow(self) self.logowin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vSizer.Add(self.logowin, 1, wx.EXPAND, 0) self.ctrlpanel = FancyPanel(self, border=wx.TOP) self.ctrlpanel.SetMinSize((-1, 30)) self.ctrlpanel.SetBorderColour(SEPARATOR_GREY) self.ctrlpanel.SetBackgroundColour(GRADIENT_LGREY, GRADIENT_DGREY) self.ctrlsizer = wx.BoxSizer(wx.HORIZONTAL) self.slider = VideoSlider(self.ctrlpanel) self.slider.Enable(False) self.timeposition = TransparentText(self.ctrlpanel, -1, "--:-- / --:--") self.bmp_muted = wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_muted.png")) self.bmp_unmuted = wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_unmuted.png")) self.mute = ActionButton(self.ctrlpanel, -1, self.bmp_unmuted) self.mute.Bind(wx.EVT_LEFT_UP, self.MuteClicked) self.bmp_pause = wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_pause.png")) self.bmp_play = wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_play.png")) self.ppbtn = ActionButton(self.ctrlpanel, -1, self.bmp_play) self.ppbtn.Bind(wx.EVT_LEFT_UP, self.PlayPause) self.ppbtn.Enable(False) self.sbtn = ActionButton(self.ctrlpanel, -1, wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_stop.png"))) self.sbtn.Bind(wx.EVT_LEFT_UP, self.OnStop) self.sbtn.Enable(False) self.volctrl = VideoVolume(self.ctrlpanel, -1) self.volctrl.SetVolumeHandler(self.OnVolumeChanged) self.volctrl.SetValue(self.volume) self.volctrl.SetMinSize((30, 17)) self.fsbtn = ActionButton(self.ctrlpanel, -1, wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_fullscreen.png"))) self.fsbtn.Bind(wx.EVT_LEFT_UP, self.FullScreen) self.fsbtn.Enable(False) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.ppbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.sbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.slider, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5) self.ctrlsizer.Add(self.timeposition, 0, wx.ALIGN_CENTER_VERTICAL) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.mute, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((5, -1)) self.ctrlsizer.Add(self.volctrl, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.fsbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlpanel.SetSizer(self.ctrlsizer) vSizer.Add(self.ctrlpanel, 0, wx.ALIGN_BOTTOM | wx.EXPAND) self.SetSizer(vSizer) self.playtimer = None self.timer = None if self.vlcwrap: self.SetMinSize((EmbeddedPlayerPanel.VIDEO_SIZE[0], -1)) self.vlcwin.Show(True) self.logowin.Show(False) self.ctrlsizer.ShowItems(True) self.guiutility.frame.Layout() def OnVolumeChanged(self, volume): if self.mute.GetBitmapLabel() == self.bmp_muted: # unmute self.mute.SetBitmapLabel(self.bmp_unmuted, recreate=True) self.volume = volume self.oldvolume = self.volume self.SetVolume(self.volume) def MuteClicked(self, event): if self.mute.GetBitmapLabel() == self.bmp_muted: self.volume = self.oldvolume else: self.volume = 0 self.volctrl.SetValue(self.volume) self.SetVolume(self.volume) self.mute.SetBitmapLabel(self.bmp_unmuted if self.mute.GetBitmapLabel() == self.bmp_muted else self.bmp_muted, recreate=True) @warnWxThread def Load(self, url, streaminfo=None): if DEBUG: print >> sys.stderr, "embedplay: Load:", url, streaminfo, currentThread().getName() if streaminfo is not None: self.estduration = streaminfo.get('estduration', None) self.download = VideoPlayer.getInstance().get_vod_download() # 19/02/10 Boudewijn: no self.slider when self.vlcwrap is None # 26/05/09 Boudewijn: when using the external player we do not have a vlcwrap if self.vlcwrap: self.slider.Enable(True) # Arno, 2009-02-17: If we don't do this VLC gets the wrong playlist somehow self.vlcwrap.stop() self.vlcwrap.playlist_clear() self.vlcwrap.load(url, streaminfo=streaminfo) # Enable update of progress slider wx.CallAfter(self.slider.SetValue, 0) if self.timer is None: self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.UpdateSlider) self.timer.Start(500) self.fsbtn.Enable(True) self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(True) self.sbtn.Enable(True) def StartPlay(self): """ Start playing the new item after VLC has stopped playing the old one """ if DEBUG: print >> sys.stderr, "embedplay: PlayWhenStopped" self.playtimer = DelayTimer(self) @warnWxThread def Play(self, evt=None): if DEBUG: print >> sys.stderr, "embedplay: Play pressed" # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: if self.GetState() != MEDIASTATE_PLAYING: self.HideLoading() self.vlcwrap.start() self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(True) elif DEBUG: print >> sys.stderr, "embedplay: Play pressed, already playing" @warnWxThread def Pause(self, evt=None, gui_vod_event=False): if DEBUG: print >> sys.stderr, "embedplay: Pause pressed" # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: if self.GetState() == MEDIASTATE_PLAYING: self.vlcwrap.pause() self.ppbtn.SetBitmapLabel(self.bmp_play, recreate=True) if gui_vod_event: self.ppbtn.Enable(False) self.ShowLoading() elif DEBUG: print >> sys.stderr, "embedplay: Pause pressed, not playing" @warnWxThread def Resume(self, evt=None): if DEBUG: print >> sys.stderr, "embedplay: Resume pressed" if self.vlcwrap: if self.GetState() != MEDIASTATE_PLAYING: self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(True) self.HideLoading() self.vlcwrap.resume() @warnWxThread def PlayPause(self, evt=None): if DEBUG: print >> sys.stderr, "embedplay: PlayPause pressed" # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: if self.GetState() in [MEDIASTATE_ENDED, MEDIASTATE_STOPPED]: # Ensures that the related download also starts self.guiutility.library_manager.startLastVODTorrent() else: self.vlcwrap.resume() self.ppbtn.SetBitmapLabel(self.bmp_play if self.ppbtn.GetBitmapLabel() == self.bmp_pause else self.bmp_pause, recreate=True) self.ppbtn.Enable(True) @warnWxThread def Seek(self, evt=None): if DEBUG: print >> sys.stderr, "embedplay: Seek" # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(not bool(self.download)) position = self.slider.GetValue() self.update = False try: if self.download: self.download.pause_vod() self.download.vod_seekpos = None self.ShowLoading() self.vlcwrap.set_media_position_relative(position, self.GetState() in [MEDIASTATE_ENDED, MEDIASTATE_STOPPED]) length = self.vlcwrap.get_stream_information_length() length = length / 1000 if length > 0 else (self.estduration or (self.download and self.download.get_vod_duration())) time_position = length * position self.timeoffset = time_position - (self.vlcwrap.get_media_position() / 1000) self.update = True except: print_exc() if DEBUG: print >> sys.stderr, 'embedplay: Could not seek' def FullScreen(self, evt=None): # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap and self.fsbtn.IsEnabled(): self._ToggleFullScreen() def OnFullScreenKey(self, event): if event.GetUnicodeKey() == wx.WXK_ESCAPE: self._ToggleFullScreen() elif event.GetUnicodeKey() == wx.WXK_SPACE: self._TogglePause() def _TogglePause(self): if self.GetState() == MEDIASTATE_PLAYING: self.vlcwrap.pause() else: self.vlcwrap.resume() @warnWxThread def _ToggleFullScreen(self): if isinstance(self.parent, wx.Frame): # are we shown in popup frame if self.ctrlsizer.IsShown(0): # we are not in fullscreen -> ctrlsizer is showing self.parent.ShowFullScreen(True) self.ctrlsizer.ShowItems(False) self.Layout() # Niels: 07-03-2012, only evt_close seems to work :( quitId = wx.NewId() pauseId = wx.NewId() self.parent.Bind(wx.EVT_MENU, lambda event: self._ToggleFullScreen(), id=quitId) self.parent.Bind(wx.EVT_MENU, lambda event: self._TogglePause(), id=pauseId) self.parent.Bind(wx.EVT_CLOSE, lambda event: self._ToggleFullScreen()) self.parent.Bind(wx.EVT_LEFT_DCLICK, lambda event: self._ToggleFullScreen()) accelerators = [(wx.ACCEL_NORMAL, wx.WXK_ESCAPE, quitId), (wx.ACCEL_CTRL, wx.WXK_SPACE, pauseId)] self.parent.SetAcceleratorTable(wx.AcceleratorTable(accelerators)) else: self.parent.ShowFullScreen(False) self.ctrlsizer.ShowItems(True) self.Layout() self.parent.SetAcceleratorTable(wx.NullAcceleratorTable) self.parent.Unbind(wx.EVT_CLOSE) else: # saving media player state cur_time = self.vlcwrap.get_media_position() cur_state = self.vlcwrap.get_our_state() self.vlcwrap.stop() if not self.fullscreenwindow: # create a new top level frame where to attach the vlc widget and # render the fullscreen video self.fullscreenwindow = wx.Frame(None, title="FullscreenVLC") self.fullscreenwindow.SetBackgroundColour("BLACK") eventPanel = wx.Panel(self.fullscreenwindow) eventPanel.SetBackgroundColour(wx.BLACK) eventPanel.Bind(wx.EVT_KEY_DOWN, lambda event: self.OnFullScreenKey(event)) self.fullscreenwindow.Bind(wx.EVT_CLOSE, lambda event: self._ToggleFullScreen()) self.fullscreenwindow.ShowFullScreen(True) eventPanel.SetFocus() self.vlcwrap.set_window(self.fullscreenwindow) else: self.TellLVCWrapWindow4Playback() self.fullscreenwindow.Destroy() self.fullscreenwindow = None # restoring state if cur_state == MEDIASTATE_PLAYING: self.vlcwrap.start(cur_time) elif cur_state == MEDIASTATE_PAUSED: self.vlcwrap.start(cur_time) def doPause(cur_time): self.vlcwrap.pause() self.vlcwrap.set_media_position(cur_time) wx.CallLater(500, doPause, cur_time) def Save(self, evt=None): # save media content in different directory if self.save_button.isToggled(): self.save_callback() def SetVolume(self, volume, evt=None): if DEBUG: print >> sys.stderr, "embedplay: SetVolume:", self.volume # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: self.vlcwrap.sound_set_volume(volume) def OnStop(self, event=None): if self.vlcwrap and self.sbtn.IsEnabled(): self.Stop() self.ppbtn.Enable(True) # Ensures that the related download also stops. self.guiutility.library_manager.stopLastVODTorrent() @forceWxThread def Stop(self): if DEBUG: print >> sys.stderr, "embedplay: Stop" # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: self.vlcwrap.stop() self.timeposition.SetLabel('--:-- / --:--') self.slider.SetValue(0) self.fsbtn.Enable(False) self.sbtn.Enable(False) self.ppbtn.SetBitmapLabel(self.bmp_play, recreate=True) self.slider.Enable(False) self.HideLoading() if self.timer is not None: self.timer.Stop() def GetState(self): """ Returns the state of VLC as summarized by Fabian: MEDIASTATE_PLAYING, MEDIASTATE_PAUSED, MEDIASTATE_ENDED, MEDIASTATE_STOPPED """ # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: status = self.vlcwrap.get_our_state() if DEBUG: print >> sys.stderr, "embedplay: GetState", status return status # catchall return MEDIASTATE_STOPPED def Reset(self): self.Stop() self.slider.SetPieces([]) @forceWxThread def UpdateStatus(self, progress, progress_consec, pieces_complete): self.logowin.loading.SetValue(progress) if self.vlcwrap: self.slider.SetPieces(pieces_complete) @warnWxThread def UpdateSlider(self, evt): # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap and self.update: if self.GetState() not in [MEDIASTATE_ENDED, MEDIASTATE_STOPPED]: length = self.vlcwrap.get_stream_information_length() length = length / 1000 if length > 0 else (self.estduration or (self.download and self.download.get_vod_duration())) cur = self.vlcwrap.get_media_position() / 1000 if length and self.timeoffset: cur += self.timeoffset if cur >= 0 and length: self.slider.SetValue(float(cur) / length) cur_str = self.FormatTime(float(cur)) if cur >= 0 else '--:--' length_str = self.FormatTime(length) if length else '--:--' self.timeposition.SetLabel('%s / %s' % (cur_str, length_str)) self.ctrlsizer.Layout() elif self.GetState() == MEDIASTATE_ENDED: self.OnStop(None) def FormatTime(self, s): longformat = time.strftime('%d:%H:%M:%S', time.gmtime(s)) if longformat.startswith('01:'): longformat = longformat[3:] while longformat.startswith('00:') and len(longformat) > len('00:00'): longformat = longformat[3:] return longformat def TellLVCWrapWindow4Playback(self): if self.vlcwrap: self.vlcwin.tell_vclwrap_window_for_playback() def ShowLoading(self): if self.vlcwrap: self.logowin.loading.SetValue(0.0) self.logowin.show_loading() self.logowin.Show(True) self.vlcwin.Show(False) self.Layout() def HideLoading(self): if self.vlcwrap: self.logowin.hide_loading() self.logowin.Show(False) self.vlcwin.Show(True) self.Layout()
def __init__(self, parent, utility, vlcwrap, bg): wx.Panel.__init__(self, parent, -1) self.utility = utility self.guiutility = utility.guiUtility self.parent = parent self.SetBackgroundColour(DEFAULT_BACKGROUND) self.volume = 0.48 self.oldvolume = 0.48 self.estduration = None self.fullscreenwindow = None self.download = None self.update = True self.timeoffset = None vSizer = wx.BoxSizer(wx.VERTICAL) self.vlcwrap = vlcwrap if vlcwrap: self.vlcwin = VLCWindow(self, vlcwrap) self.vlcwin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vSizer.Add(self.vlcwin, 1, wx.EXPAND, 0) self.logowin = LogoWindow(self) self.logowin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vSizer.Add(self.logowin, 1, wx.EXPAND, 0) self.ctrlpanel = FancyPanel(self, border=wx.TOP) self.ctrlpanel.SetMinSize((-1, 30)) self.ctrlpanel.SetBorderColour(SEPARATOR_GREY) self.ctrlpanel.SetBackgroundColour(GRADIENT_LGREY, GRADIENT_DGREY) self.ctrlsizer = wx.BoxSizer(wx.HORIZONTAL) self.slider = VideoSlider(self.ctrlpanel) self.slider.Enable(False) self.timeposition = TransparentText(self.ctrlpanel, -1, "--:-- / --:--") self.bmp_muted = wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_muted.png")) self.bmp_unmuted = wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_unmuted.png")) self.mute = ActionButton(self.ctrlpanel, -1, self.bmp_unmuted) self.mute.Bind(wx.EVT_LEFT_UP, self.MuteClicked) self.bmp_pause = wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_pause.png")) self.bmp_play = wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_play.png")) self.ppbtn = ActionButton(self.ctrlpanel, -1, self.bmp_play) self.ppbtn.Bind(wx.EVT_LEFT_UP, self.PlayPause) self.ppbtn.Enable(False) self.sbtn = ActionButton(self.ctrlpanel, -1, wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_stop.png"))) self.sbtn.Bind(wx.EVT_LEFT_UP, self.OnStop) self.sbtn.Enable(False) self.volctrl = VideoVolume(self.ctrlpanel, -1) self.volctrl.SetVolumeHandler(self.OnVolumeChanged) self.volctrl.SetValue(self.volume) self.volctrl.SetMinSize((30, 17)) self.fsbtn = ActionButton(self.ctrlpanel, -1, wx.Bitmap(os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "video_fullscreen.png"))) self.fsbtn.Bind(wx.EVT_LEFT_UP, self.FullScreen) self.fsbtn.Enable(False) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.ppbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.sbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.slider, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5) self.ctrlsizer.Add(self.timeposition, 0, wx.ALIGN_CENTER_VERTICAL) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.mute, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((5, -1)) self.ctrlsizer.Add(self.volctrl, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.fsbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlpanel.SetSizer(self.ctrlsizer) vSizer.Add(self.ctrlpanel, 0, wx.ALIGN_BOTTOM | wx.EXPAND) self.SetSizer(vSizer) self.playtimer = None self.timer = None if self.vlcwrap: self.SetMinSize((EmbeddedPlayerPanel.VIDEO_SIZE[0], -1)) self.vlcwin.Show(True) self.logowin.Show(False) self.ctrlsizer.ShowItems(True) self.guiutility.frame.Layout()
def __init__(self, parent): wx.StatusBar.__init__(self, parent, style=wx.ST_SIZEGRIP) # On Linux/OS X the resize handle and icons overlap, therefore we add an extra field. # On Windows this field is automatically set to 1 when the wx.ST_SIZEGRIP is set. self.SetFieldsCount(6) self.SetStatusStyles([wx.SB_FLAT] * 6) self.SetStatusWidths([-1, 250, 19, 19, 19, 19]) self.guiutility = GUIUtility.getInstance() self.utility = self.guiutility.utility self.library_manager = self.guiutility.library_manager self.uelog = UserEventLogDBHandler.getInstance() self.ff_checkbox = wx.CheckBox(self, -1, 'Family filter', style=wx.ALIGN_RIGHT) self.ff_checkbox.Bind(wx.EVT_CHECKBOX, self.OnCheckbox) self.ff_checkbox.SetValue(self.guiutility.getFamilyFilter()) self.speed_down_icon = NativeIcon.getInstance().getBitmap( self, 'arrow', self.GetBackgroundColour(), state=0) self.speed_down_sbmp = wx.StaticBitmap(self, -1, self.speed_down_icon) self.speed_down_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_down = StaticText(self, -1, '', style=wx.ST_NO_AUTORESIZE) self.speed_down.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_up_icon = self.speed_down_icon.ConvertToImage().Rotate90( ).Rotate90().ConvertToBitmap() self.speed_up_sbmp = wx.StaticBitmap(self, -1, self.speed_up_icon) self.speed_up_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.speed_up = StaticText(self, -1, '', style=wx.ST_NO_AUTORESIZE) self.speed_up.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.searchConnectionImages = [ 'progressbarEmpty.png', 'progressbarFull.png' ] self.searchConnectionImages = [ os.path.join(self.guiutility.vwxGUI_path, 'images', image) for image in self.searchConnectionImages ] self.searchConnectionImages = [ wx.Bitmap(image, wx.BITMAP_TYPE_ANY) for image in self.searchConnectionImages ] self.activityImages = [ 'statusbar_activity.png', 'statusbar_noactivity.png' ] self.activityImages = [ os.path.join(self.guiutility.vwxGUI_path, 'images', image) for image in self.activityImages ] self.activityImages = [ wx.Bitmap(image, wx.BITMAP_TYPE_ANY) for image in self.activityImages ] self.connection = HorizontalGauge(self, self.searchConnectionImages[0], self.searchConnectionImages[1]) self.activity = wx.StaticBitmap(self, -1, self.activityImages[1]) self.activity_timer = None self.channelconnections = 0 self.bmp_firewall_warning = wx.Bitmap( os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "statusbar_warning.png")) self.bmp_firewall_ok = wx.Bitmap( os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "statusbar_ok.png")) self.firewallStatus = ActionButton(self, -1, self.bmp_firewall_warning) self.firewallStatus.SetSize((16, 16)) self.firewallStatus.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) self.firewallStatus.SetToolTipString('Port status unknown') self.firewallStatus.Enable(False) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_warning) self.SetTransferSpeeds(0, 0) self.Bind(wx.EVT_SIZE, self.OnSize) self.library_manager.add_download_state_callback( self.RefreshTransferSpeed)
class SRstatusbar(wx.StatusBar): def __init__(self, parent): wx.StatusBar.__init__(self, parent, style=wx.ST_SIZEGRIP) # On Linux/OS X the resize handle and icons overlap, therefore we add an extra field. # On Windows this field is automatically set to 1 when the wx.ST_SIZEGRIP is set. self.SetFieldsCount(6) self.SetStatusStyles([wx.SB_FLAT] * 6) self.SetStatusWidths([-1, 250, 19, 19, 19, 19]) self.guiutility = GUIUtility.getInstance() self.utility = self.guiutility.utility self.library_manager = self.guiutility.library_manager self.uelog = UserEventLogDBHandler.getInstance() self.ff_checkbox = wx.CheckBox(self, -1, 'Family filter', style=wx.ALIGN_RIGHT) self.ff_checkbox.Bind(wx.EVT_CHECKBOX, self.OnCheckbox) self.ff_checkbox.SetValue(self.guiutility.getFamilyFilter()) self.speed_down_icon = NativeIcon.getInstance().getBitmap( self, 'arrow', self.GetBackgroundColour(), state=0) self.speed_down_sbmp = wx.StaticBitmap(self, -1, self.speed_down_icon) self.speed_down_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_down = StaticText(self, -1, '', style=wx.ST_NO_AUTORESIZE) self.speed_down.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_up_icon = self.speed_down_icon.ConvertToImage().Rotate90( ).Rotate90().ConvertToBitmap() self.speed_up_sbmp = wx.StaticBitmap(self, -1, self.speed_up_icon) self.speed_up_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.speed_up = StaticText(self, -1, '', style=wx.ST_NO_AUTORESIZE) self.speed_up.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.searchConnectionImages = [ 'progressbarEmpty.png', 'progressbarFull.png' ] self.searchConnectionImages = [ os.path.join(self.guiutility.vwxGUI_path, 'images', image) for image in self.searchConnectionImages ] self.searchConnectionImages = [ wx.Bitmap(image, wx.BITMAP_TYPE_ANY) for image in self.searchConnectionImages ] self.activityImages = [ 'statusbar_activity.png', 'statusbar_noactivity.png' ] self.activityImages = [ os.path.join(self.guiutility.vwxGUI_path, 'images', image) for image in self.activityImages ] self.activityImages = [ wx.Bitmap(image, wx.BITMAP_TYPE_ANY) for image in self.activityImages ] self.connection = HorizontalGauge(self, self.searchConnectionImages[0], self.searchConnectionImages[1]) self.activity = wx.StaticBitmap(self, -1, self.activityImages[1]) self.activity_timer = None self.channelconnections = 0 self.bmp_firewall_warning = wx.Bitmap( os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "statusbar_warning.png")) self.bmp_firewall_ok = wx.Bitmap( os.path.join(self.utility.getPath(), LIBRARYNAME, "Main", "vwxGUI", "images", "statusbar_ok.png")) self.firewallStatus = ActionButton(self, -1, self.bmp_firewall_warning) self.firewallStatus.SetSize((16, 16)) self.firewallStatus.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) self.firewallStatus.SetToolTipString('Port status unknown') self.firewallStatus.Enable(False) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_warning) self.SetTransferSpeeds(0, 0) self.Bind(wx.EVT_SIZE, self.OnSize) self.library_manager.add_download_state_callback( self.RefreshTransferSpeed) def RefreshTransferSpeed(self, dslist, magnetlist): total_down, total_up = 0.0, 0.0 for ds in dslist: total_down += ds.get_current_speed(DOWNLOAD) total_up += ds.get_current_speed(UPLOAD) self.SetTransferSpeeds(total_down * 1024, total_up * 1024) def SetTransferSpeeds(self, down, up): self.speed_down.SetLabel(self.utility.speed_format_new(down)) self.speed_up.SetLabel(self.utility.speed_format_new(up)) self.Reposition() def SetGlobalMaxSpeed(self, direction, value): if direction in [UPLOAD, DOWNLOAD]: if direction == UPLOAD: self.utility.setMaxUp(value) else: self.utility.setMaxDown(value) value = 0 if value == 'unlimited' else ( -1 if int(value) == 0 else int(value)) self.guiutility.app.ratelimiter.set_global_max_speed( direction, value) def OnDownloadPopup(self, event): menu = wx.Menu() curr_valdown = self.utility.getMaxDown() # values = ['75', '300', '600'] values = self.utility.round_range( int(curr_valdown)) if curr_valdown.isdigit() else range( 0, 1000, 100) values = map(str, values) if curr_valdown.isdigit() and curr_valdown not in values: values.append(curr_valdown) values.sort(cmp=lambda x, y: cmp(int(x), int(y))) values.append('unlimited') for valdown in values: itemid = wx.NewId() menu.AppendRadioItem(itemid, str(valdown)) menu.Bind(wx.EVT_MENU, lambda x, valdown=valdown: self.SetGlobalMaxSpeed( DOWNLOAD, valdown), id=itemid) menu.Check(itemid, curr_valdown == str(valdown)) self.speed_down.PopupMenu(menu, event.GetPosition()) menu.Destroy() self.speed_down.Layout() def OnUploadPopup(self, event): menu = wx.Menu() curr_valup = self.utility.getMaxUp() # values = ['0', '50', '100'] values = self.utility.round_range( int(curr_valup)) if curr_valup.isdigit() else range(0, 1000, 100) values = map(str, values) if curr_valup.isdigit() and curr_valup not in values: values.append(curr_valup) values.sort(cmp=lambda x, y: cmp(int(x), int(y))) values.append('unlimited') for valup in values: itemid = wx.NewId() menu.AppendRadioItem(itemid, str(valup)) menu.Bind( wx.EVT_MENU, lambda x, valup=valup: self.SetGlobalMaxSpeed(UPLOAD, valup), id=itemid) menu.Check(itemid, curr_valup == str(valup)) self.speed_up.PopupMenu(menu, event.GetPosition()) menu.Destroy() self.speed_up.Layout() def OnCheckbox(self, event): checkbox = event.GetEventObject() checkbox.Enable(False) wx.CallLater(1000, checkbox.Enable, True) wx.CallLater(100, self.__toggleFF, event.GetEventObject().GetValue()) def __toggleFF(self, newvalue): if newvalue != self.guiutility.getFamilyFilter(): self.guiutility.toggleFamilyFilter(newvalue) def db_callback(): self.uelog.addEvent( message="SRstatusbar: user toggled family filter", type=2) startWorker(None, db_callback, retryOnBusy=True) def SetConnections(self, connectionPercentage, totalConnections, channelConnections): self.connection.SetPercentage(connectionPercentage) self.connection.SetToolTipString('Connected to %d peers' % totalConnections) self.channelconnections = channelConnections def GetConnections(self): return self.connection.GetPercentage() def GetChannelConnections(self): return self.channelconnections def onReachable(self, event=None): if not self.guiutility.firewall_restart: self.firewallStatus.SetBitmapLabel(self.bmp_firewall_ok) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_ok) self.firewallStatus.SetToolTipString('Port is working') def IsReachable(self): if not self.guiutility.firewall_restart: return self.firewallStatus.GetBitmapLabel() == self.bmp_firewall_ok return False def onActivity(self, msg): if self.activity_timer: self.activity_timer.Stop() def revert(): self.activity.SetBitmap(self.activityImages[1]) self.activity.Refresh() self.activity.SetBitmap(self.activityImages[0]) self.activity.Refresh() self.activity.SetToolTipString(msg) self.activity_timer = wx.CallLater(300, revert) def format_bytes(self, bytes): if bytes < 1000: return '%d B' % bytes if bytes < 1024: return '%1.1f KB' % (bytes / 1024.0) if bytes < 1022796: return '%d KB' % (bytes // 1024) if bytes < 1048576: return '%1.1f MB' % (bytes // 1048576.0) if bytes < 1047527425: return '%d MB' % (bytes // 1048576) if bytes < 1073741824: return '%1.1f GB' % (bytes // 1073741824.0) return '%d GB' % (bytes // 1073741824) def OnSize(self, event): self.Reposition() def Reposition(self): self.Freeze() rect = self.GetFieldRect(0) self.ff_checkbox.SetPosition((rect.x + 2, rect.y + 2)) self.ff_checkbox.SetSize((-1, rect.height - 4)) rect = self.GetFieldRect(1) x = rect.x + rect.width - 15 for control in reversed([ self.speed_down_sbmp, self.speed_down, self.speed_up_sbmp, self.speed_up ]): spacer = 10 if not isinstance(control, wx.StaticBitmap) else 7 x -= control.GetSize()[0] + spacer yAdd = (rect.height - control.GetSize()[1]) / 2 control.SetPosition((x, rect.y + yAdd)) rect = self.GetFieldRect(2) size = self.connection.GetSize() yAdd = (rect.height - size[1]) / 2 xAdd = (rect.width - size[0]) / 2 self.connection.SetPosition((rect.x + xAdd, rect.y + yAdd)) rect = self.GetFieldRect(3) size = self.activity.GetSize() yAdd = (rect.height - size[1]) / 2 xAdd = (rect.width - size[0]) / 2 self.activity.SetPosition((rect.x + xAdd, rect.y + yAdd)) rect = self.GetFieldRect(4) size = self.firewallStatus.GetSize() yAdd = (rect.height - size[1]) / 2 xAdd = (rect.width - size[0]) / 2 self.firewallStatus.SetPosition((rect.x + xAdd, rect.y + yAdd)) self.sizeChanged = False self.Thaw()
def __init__(self, parent, utility, vlcwrap, bg_color): wx.Panel.__init__(self, parent, -1) self._logger = logging.getLogger(self.__class__.__name__) self._gui_image_manager = GuiImageManager.getInstance() self.utility = utility self.guiutility = utility.guiUtility self.videoplayer = self.guiutility.videoplayer self.parent = parent self.SetBackgroundColour(bg_color) self.fullscreenwindow = None self.download = None self.download_hash = None self.update = True self.timeoffset = None self.oldvolume = 0 vSizer = wx.BoxSizer(wx.VERTICAL) self.vlcwrap = vlcwrap if vlcwrap: self.vlcwin = VLCWindow(self, vlcwrap) self.vlcwin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vSizer.Add(self.vlcwin, 1, wx.EXPAND, 0) self.logowin = LogoWindow(self) self.logowin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vSizer.Add(self.logowin, 1, wx.EXPAND, 0) self.ctrlpanel = FancyPanel(self, border=wx.TOP) self.ctrlpanel.SetMinSize((-1, 30)) self.ctrlpanel.SetBorderColour(SEPARATOR_GREY) self.ctrlpanel.SetBackgroundColour(GRADIENT_LGREY, GRADIENT_DGREY) self.ctrlsizer = wx.BoxSizer(wx.HORIZONTAL) self.slider = VideoSlider(self.ctrlpanel) self.slider.Enable(False) self.timeposition = TransparentText(self.ctrlpanel, -1, "--:-- / --:--") self.bmp_muted = self._gui_image_manager.getImage( u"video_muted.png") self.bmp_unmuted = self._gui_image_manager.getImage( u"video_unmuted.png") self.mute = ActionButton(self.ctrlpanel, -1, self.bmp_unmuted) self.mute.Bind(wx.EVT_LEFT_UP, self.MuteClicked) self.bmp_pause = self._gui_image_manager.getImage( u"video_pause.png") self.bmp_play = self._gui_image_manager.getImage(u"video_play.png") self.ppbtn = ActionButton(self.ctrlpanel, -1, self.bmp_play) self.ppbtn.Bind(wx.EVT_LEFT_UP, self.PlayPause) self.ppbtn.Enable(False) self.sbtn = ActionButton( self.ctrlpanel, -1, self._gui_image_manager.getImage(u"video_stop.png")) self.sbtn.Bind(wx.EVT_LEFT_UP, self.OnStop) self.sbtn.Enable(False) self.volctrl = VideoVolume(self.ctrlpanel, -1) self.volctrl.SetVolumeHandler(self.OnVolumeChanged) self.volctrl.SetMinSize((30, 17)) self.volctrl.Enable(False) self.fsbtn = ActionButton( self.ctrlpanel, -1, self._gui_image_manager.getImage(u"video_fullscreen.png")) self.fsbtn.Bind(wx.EVT_LEFT_UP, self.FullScreen) self.fsbtn.Enable(False) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.ppbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.sbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.slider, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5) self.ctrlsizer.Add(self.timeposition, 0, wx.ALIGN_CENTER_VERTICAL) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.mute, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((5, -1)) self.ctrlsizer.Add(self.volctrl, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.fsbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlpanel.SetSizer(self.ctrlsizer) vSizer.Add(self.ctrlpanel, 0, wx.ALIGN_BOTTOM | wx.EXPAND) self.notifier = self.guiutility.utility.session.notifier self.SetSizer(vSizer) self.playtimer = None self.timer = None if self.vlcwrap: self.SetMinSize((EmbeddedPlayerPanel.VIDEO_SIZE[0], -1)) self.vlcwin.Show(True) self.logowin.Show(False) self.ctrlsizer.ShowItems(True) self.guiutility.frame.Layout() self.guiutility.library_manager.add_download_state_callback( self.OnStatesCallback) self.guiutility.utility.session.add_observer( self.OnVideoBuffering, NTFY_TORRENTS, [NTFY_VIDEO_BUFFERING]) self.videoplayer.set_internalplayer_callback(self.LoadAndStartPlay)
class EmbeddedPlayerPanel(wx.Panel): """ The Embedded Player consists of a VLCWindow and the media controls such as Play/Pause buttons and Volume Control. """ VIDEO_SIZE = (320, 240) def __init__(self, parent, utility, vlcwrap, bg_color): wx.Panel.__init__(self, parent, -1) self._logger = logging.getLogger(self.__class__.__name__) self._gui_image_manager = GuiImageManager.getInstance() self.utility = utility self.guiutility = utility.guiUtility self.videoplayer = self.guiutility.videoplayer self.parent = parent self.SetBackgroundColour(bg_color) self.fullscreenwindow = None self.download = None self.download_hash = None self.update = True self.timeoffset = None self.oldvolume = 0 vSizer = wx.BoxSizer(wx.VERTICAL) self.vlcwrap = vlcwrap if vlcwrap: self.vlcwin = VLCWindow(self, vlcwrap) self.vlcwin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vSizer.Add(self.vlcwin, 1, wx.EXPAND, 0) self.logowin = LogoWindow(self) self.logowin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vSizer.Add(self.logowin, 1, wx.EXPAND, 0) self.ctrlpanel = FancyPanel(self, border=wx.TOP) self.ctrlpanel.SetMinSize((-1, 30)) self.ctrlpanel.SetBorderColour(SEPARATOR_GREY) self.ctrlpanel.SetBackgroundColour(GRADIENT_LGREY, GRADIENT_DGREY) self.ctrlsizer = wx.BoxSizer(wx.HORIZONTAL) self.slider = VideoSlider(self.ctrlpanel) self.slider.Enable(False) self.timeposition = TransparentText(self.ctrlpanel, -1, "--:-- / --:--") self.bmp_muted = self._gui_image_manager.getImage( u"video_muted.png") self.bmp_unmuted = self._gui_image_manager.getImage( u"video_unmuted.png") self.mute = ActionButton(self.ctrlpanel, -1, self.bmp_unmuted) self.mute.Bind(wx.EVT_LEFT_UP, self.MuteClicked) self.bmp_pause = self._gui_image_manager.getImage( u"video_pause.png") self.bmp_play = self._gui_image_manager.getImage(u"video_play.png") self.ppbtn = ActionButton(self.ctrlpanel, -1, self.bmp_play) self.ppbtn.Bind(wx.EVT_LEFT_UP, self.PlayPause) self.ppbtn.Enable(False) self.sbtn = ActionButton( self.ctrlpanel, -1, self._gui_image_manager.getImage(u"video_stop.png")) self.sbtn.Bind(wx.EVT_LEFT_UP, self.OnStop) self.sbtn.Enable(False) self.volctrl = VideoVolume(self.ctrlpanel, -1) self.volctrl.SetVolumeHandler(self.OnVolumeChanged) self.volctrl.SetMinSize((30, 17)) self.volctrl.Enable(False) self.fsbtn = ActionButton( self.ctrlpanel, -1, self._gui_image_manager.getImage(u"video_fullscreen.png")) self.fsbtn.Bind(wx.EVT_LEFT_UP, self.FullScreen) self.fsbtn.Enable(False) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.ppbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.sbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.slider, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5) self.ctrlsizer.Add(self.timeposition, 0, wx.ALIGN_CENTER_VERTICAL) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.mute, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((5, -1)) self.ctrlsizer.Add(self.volctrl, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlsizer.Add(self.fsbtn, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) self.ctrlsizer.AddSpacer((10, -1)) self.ctrlpanel.SetSizer(self.ctrlsizer) vSizer.Add(self.ctrlpanel, 0, wx.ALIGN_BOTTOM | wx.EXPAND) self.notifier = self.guiutility.utility.session.notifier self.SetSizer(vSizer) self.playtimer = None self.timer = None if self.vlcwrap: self.SetMinSize((EmbeddedPlayerPanel.VIDEO_SIZE[0], -1)) self.vlcwin.Show(True) self.logowin.Show(False) self.ctrlsizer.ShowItems(True) self.guiutility.frame.Layout() self.guiutility.library_manager.add_download_state_callback( self.OnStatesCallback) self.guiutility.utility.session.add_observer( self.OnVideoBuffering, NTFY_TORRENTS, [NTFY_VIDEO_BUFFERING]) self.videoplayer.set_internalplayer_callback(self.LoadAndStartPlay) def OnVideoBuffering(self, subject, changeType, torrent_tuple): if not self: return download_hash, _, is_buffering = torrent_tuple if self.download and self.download.get_def().get_infohash( ) == download_hash: @forceWxThread def do_gui(): if is_buffering: self.Pause(gui_vod_event=True) else: self.Resume() do_gui() def OnStatesCallback(self, dslist, magnetlist): if not self or not self.download: return for ds in dslist: if ds.get_download() == self.download and self.download.get_mode( ) == DLMODE_VOD: if ds.get_status() == DLSTATUS_HASHCHECKING: progress = ds.get_progress() label = 'Checking\n%d%%' % (progress * 100) elif ds.get_status() == DLSTATUS_STOPPED_ON_ERROR: progress = 0 label = 'Loading\nfailed' else: progress = ds.get_vod_prebuffering_progress() label = 'Loading\n%d%%' % (progress * 100) pieces_complete = ds.get_pieces_complete( ) if ds.get_progress() < 1.0 else [True] self.UpdateStatus(label, progress, pieces_complete) def OnVolumeChanged(self, volume): if self.mute.GetBitmapLabel() == self.bmp_muted: # unmute self.mute.SetBitmapLabel(self.bmp_unmuted, recreate=True) self.volume = volume self.oldvolume = self.volume self.SetVolume(self.volume) def MuteClicked(self, event): if self.mute.GetBitmapLabel() == self.bmp_muted: self.volume = self.oldvolume else: self.volume = 0 self.volctrl.SetValue(self.volume) self.SetVolume(self.volume) self.mute.SetBitmapLabel( self.bmp_unmuted if self.mute.GetBitmapLabel() == self.bmp_muted else self.bmp_muted, recreate=True) @forceWxThread def LoadAndStartPlay(self, url, download): self.Load(url, download) self.StartPlay() @warnWxThread def Load(self, url, download): self._logger.debug("embedplay: Load: %s %s", url, currentThread().getName()) self.download = download self.download_hash = download.get_def().get_infohash() # 19/02/10 Boudewijn: no self.slider when self.vlcwrap is None # 26/05/09 Boudewijn: when using the external player we do not have a vlcwrap if self.vlcwrap: self.slider.Enable(False) # Arno, 2009-02-17: If we don't do this VLC gets the wrong playlist somehow self.vlcwrap.stop() self.vlcwrap.load(url) # Enable update of progress slider wx.CallAfter(self.slider.SetValue, 0) if self.timer is None: self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.UpdateSlider) self.timer.Start(500) self.volume = self.vlcwrap.sound_get_volume() self.oldvolume = self.vlcwrap.sound_get_volume() self.volctrl.SetValue(self.volume) self.volctrl.Enable(True) self.fsbtn.Enable(True) self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(True) self.sbtn.Enable(True) def StartPlay(self): """ Start playing the new item after VLC has stopped playing the old one """ self._logger.debug("embedplay: PlayWhenStopped") self.playtimer = DelayTimer(self) @warnWxThread def Play(self, evt=None): self._logger.debug("embedplay: Play pressed") # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: if self.GetState() != MEDIASTATE_PLAYING: self.vlcwrap.start() self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(True) else: self._logger.debug("embedplay: Play pressed, already playing") @warnWxThread def Pause(self, evt=None, gui_vod_event=False): self._logger.debug("embedplay: Pause pressed") if self.vlcwrap: if self.GetState() == MEDIASTATE_PLAYING: self.vlcwrap.pause() self.ppbtn.SetBitmapLabel(self.bmp_play, recreate=True) if gui_vod_event: self.ppbtn.Enable(False) self.ShowLoading() @warnWxThread def Resume(self, evt=None): self._logger.debug("embedplay: Resume pressed") if self.vlcwrap: if self.GetState() != MEDIASTATE_PLAYING: self.vlcwrap.resume() self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(True) self.slider.Enable(True) self.HideLoading() @warnWxThread def PlayPause(self, evt=None): self._logger.debug("embedplay: PlayPause pressed") # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: if self.GetState() in [MEDIASTATE_ENDED, MEDIASTATE_STOPPED]: # Ensures that the related download also starts self.guiutility.library_manager.startLastVODTorrent() else: self.vlcwrap.resume() self.ppbtn.SetBitmapLabel( self.bmp_play if self.ppbtn.GetBitmapLabel() == self.bmp_pause else self.bmp_pause, recreate=True) self.ppbtn.Enable(True) @warnWxThread def Seek(self, evt=None): self._logger.debug("embedplay: Seek") # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: self.ppbtn.SetBitmapLabel(self.bmp_pause, recreate=True) self.ppbtn.Enable(self.download.get_progress() == 1.0) position = self.slider.GetValue() self.update = False try: self.Pause(gui_vod_event=True) self.videoplayer.seek(position) self.vlcwrap.set_media_position_relative( position, self.GetState() in [MEDIASTATE_ENDED, MEDIASTATE_STOPPED]) length = self.vlcwrap.get_stream_information_length() length = length / 1000 if length > 0 else self.videoplayer.get_vod_duration( self.download_hash) time_position = length * position self.timeoffset = time_position - ( self.vlcwrap.get_media_position() / 1000) self.update = True except: print_exc() self._logger.debug('embedplay: Could not seek') def FullScreen(self, evt=None): # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap and self.fsbtn.IsEnabled(): self._ToggleFullScreen() def OnFullScreenKey(self, event): if event.GetUnicodeKey() == wx.WXK_ESCAPE: self._ToggleFullScreen() elif event.GetUnicodeKey() == wx.WXK_SPACE: self._TogglePause() def _TogglePause(self): if self.GetState() == MEDIASTATE_PLAYING: self.vlcwrap.pause() else: self.vlcwrap.resume() @warnWxThread def _ToggleFullScreen(self): # saving media player state cur_time = self.vlcwrap.get_media_position() cur_state = self.vlcwrap.get_our_state() self.vlcwrap.stop() if not self.fullscreenwindow: # create a new top level frame where to attach the vlc widget and # render the fullscreen video self.fullscreenwindow = wx.Frame(None, title="FullscreenVLC") self.fullscreenwindow.SetBackgroundColour("BLACK") eventPanel = wx.Panel(self.fullscreenwindow) eventPanel.SetBackgroundColour(wx.BLACK) eventPanel.Bind(wx.EVT_KEY_DOWN, lambda event: self.OnFullScreenKey(event)) self.fullscreenwindow.Bind(wx.EVT_CLOSE, lambda event: self._ToggleFullScreen()) self.fullscreenwindow.Show() self.fullscreenwindow.ShowFullScreen(True) eventPanel.SetFocus() self.vlcwrap.set_window(self.fullscreenwindow) else: self.vlcwrap.set_window(self.vlcwin) self.fullscreenwindow.Destroy() self.fullscreenwindow = None # restoring state if cur_state == MEDIASTATE_PLAYING: self.vlcwrap.start(cur_time) elif cur_state == MEDIASTATE_PAUSED: self.vlcwrap.start(cur_time) def doPause(cur_time): self.vlcwrap.pause() self.vlcwrap.set_media_position(cur_time) wx.CallLater(500, doPause, cur_time) def SetVolume(self, volume, evt=None): self._logger.debug("embedplay: SetVolume: %s", self.volume) # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: self.vlcwrap.sound_set_volume(volume) def OnStop(self, event=None): if self.vlcwrap and self.sbtn.IsEnabled(): self.Stop() self.ppbtn.Enable(True) # Ensures that the related download also stops. self.guiutility.library_manager.stopLastVODTorrent() @forceWxThread def Stop(self): self._logger.debug("embedplay: Stop") # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: self.vlcwrap.stop() self.timeposition.SetLabel('--:-- / --:--') self.slider.SetValue(0) self.timeoffset = None self.fsbtn.Enable(False) self.sbtn.Enable(False) self.ppbtn.SetBitmapLabel(self.bmp_play, recreate=True) self.slider.Enable(False) self.HideLoading() if self.timer is not None: self.timer.Stop() def GetState(self): """ Returns the state of VLC as summarized by Fabian: MEDIASTATE_PLAYING, MEDIASTATE_PAUSED, MEDIASTATE_ENDED, MEDIASTATE_STOPPED """ # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap: status = self.vlcwrap.get_our_state() self._logger.debug("embedplay: GetState %s", status) return status # catchall return MEDIASTATE_STOPPED def Reset(self): self.Stop() self.slider.SetPieces([]) @forceWxThread def UpdateStatus(self, label, progress, pieces_complete): self.logowin.loading.SetValue(progress) self.logowin.loading.SetLabel(label) if self.vlcwrap: self.slider.SetPieces(pieces_complete) @warnWxThread def UpdateSlider(self, evt): # Boudewijn, 26/05/09: when using the external player we do not have a vlcwrap if self.vlcwrap and self.update: if self.GetState() not in [MEDIASTATE_ENDED, MEDIASTATE_STOPPED]: length = self.vlcwrap.get_stream_information_length() length = length / 1000 if length > 0 else self.videoplayer.get_vod_duration( self.download_hash) cur = self.vlcwrap.get_media_position() / 1000 if length and self.timeoffset: cur += self.timeoffset if cur >= 0 and length: self.slider.SetValue(float(cur) / length) cur_str = self.FormatTime(float(cur)) if cur >= 0 else '--:--' length_str = self.FormatTime(length) if length else '--:--' self.timeposition.SetLabel('%s / %s' % (cur_str, length_str)) self.ctrlsizer.Layout() elif self.GetState() == MEDIASTATE_ENDED: download, fileindex = (self.videoplayer.get_vod_download(), self.videoplayer.get_vod_fileindex()) self.OnStop(None) if download: self.notifier.notify( NTFY_TORRENTS, NTFY_VIDEO_ENDED, (download.get_def().get_infohash(), fileindex)) if self.fullscreenwindow: self._ToggleFullScreen() def FormatTime(self, s): longformat = time.strftime('%d:%H:%M:%S', time.gmtime(s)) if longformat.startswith('01:'): longformat = longformat[3:] while longformat.startswith('00:') and len(longformat) > len('00:00'): longformat = longformat[3:] return longformat def ShowLoading(self): if self.vlcwrap: self.logowin.loading.SetValue(0.0) self.logowin.show_loading() self.logowin.Show(True) self.vlcwin.Show(False) self.Layout() def HideLoading(self): if self.vlcwrap: self.logowin.hide_loading() self.logowin.Show(False) self.vlcwin.Show(True) self.Layout() def RecreateVLCWindow(self): if self.vlcwrap: vlcwin = VLCWindow(self, self.vlcwrap) vlcwin.SetMinSize(EmbeddedPlayerPanel.VIDEO_SIZE) vlcwin.Show(self.vlcwin.IsShown()) self.GetSizer().Replace(self.vlcwin, vlcwin) self.vlcwin.Destroy() self.vlcwin = vlcwin
class SRstatusbar(wx.StatusBar): def __init__(self, parent): wx.StatusBar.__init__(self, parent, style=wx.ST_SIZEGRIP) self._gui_image_manager = GuiImageManager.getInstance() self.guiutility = GUIUtility.getInstance() self.utility = self.guiutility.utility self.library_manager = self.guiutility.library_manager self.ff_checkbox = wx.CheckBox(self, -1, 'Family filter', style=wx.ALIGN_RIGHT) self.ff_checkbox.Bind(wx.EVT_CHECKBOX, self.OnCheckbox) self.ff_checkbox.SetValue(self.guiutility.getFamilyFilter()) self.tunnel_contrib = wx.StaticText(self, -1, '') self.tunnel_contrib.SetToolTipString('Total Anonymity Contribution') self.tunnel_contribNet = wx.StaticText(self, -1, '') self.tunnel_contribNet.SetToolTipString( 'Anonymity Contribution Balance') self.speed_down_icon = self._gui_image_manager.getBitmap( self, u"arrow", self.GetBackgroundColour(), state=0) self.speed_down_sbmp = wx.StaticBitmap(self, -1, self.speed_down_icon) self.speed_down_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_down = wx.StaticText(self, -1, '') self.speed_down.Bind(wx.EVT_RIGHT_UP, self.OnDownloadPopup) self.speed_up_icon = self.speed_down_icon.ConvertToImage().Rotate90( ).Rotate90().ConvertToBitmap() self.speed_up_sbmp = wx.StaticBitmap(self, -1, self.speed_up_icon) self.speed_up_sbmp.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.speed_up = wx.StaticText(self, -1, '') self.speed_up.Bind(wx.EVT_RIGHT_UP, self.OnUploadPopup) self.free_space_icon = self._gui_image_manager.getImage(u"drive.png") self.free_space_sbmp = wx.StaticBitmap(self, -1, self.free_space_icon) self.free_space = wx.StaticText(self, -1, '') self.searchConnectionImages = [ u"progressbarEmpty.png", u"progressbarFull.png" ] self.searchConnectionImages = [ self._gui_image_manager.getImage(image) for image in self.searchConnectionImages ] self.activityImages = [ u"statusbar_activity.png", u"statusbar_noactivity.png" ] self.activityImages = [ self._gui_image_manager.getImage(image) for image in self.activityImages ] self.connection = HorizontalGauge(self, self.searchConnectionImages[0], self.searchConnectionImages[1]) self.connection.SetBackgroundColour(self.GetBackgroundColour()) self.activity = wx.StaticBitmap(self, -1, self.activityImages[1]) self.activity_timer = None self.channelconnections = 0 self.bmp_firewall_warning = self._gui_image_manager.getImage( u"statusbar_warning.png") self.bmp_firewall_ok = self._gui_image_manager.getImage( u"statusbar_ok.png") self.firewallStatus = ActionButton(self, -1, self.bmp_firewall_warning) self.firewallStatus.SetSize((16, 16)) self.firewallStatus.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) self.firewallStatus.SetToolTipString('Port status unknown') self.firewallStatus.Enable(False) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_warning) # On Linux/OS X the resize handle and icons overlap, therefore we add an extra field. # On Windows this field is automatically set to 1 when the wx.ST_SIZEGRIP (parent class constructor) is set. self.fields = [ (-1, wx.SB_FLAT, [self.ff_checkbox]), (100, wx.SB_FLAT, [self.tunnel_contrib, self.tunnel_contribNet]), (200, wx.SB_FLAT, [ self.speed_down_sbmp, self.speed_down, self.speed_up_sbmp, self.speed_up ]), (75, wx.SB_FLAT, [self.free_space_sbmp, self.free_space]), (19, wx.SB_FLAT, [self.connection]), (19, wx.SB_FLAT, [self.activity]), (19, wx.SB_FLAT, [self.firewallStatus]) ] if sys.platform != "win32": self.fields.append((19, wx.SB_FLAT, [])) self.SetFieldsCount(len(self.fields)) self.SetStatusWidths([field[0] for field in self.fields]) self.SetStatusStyles([field[1] for field in self.fields]) self.SetTransferSpeeds(speed_format(0), speed_format(0)) self.Bind(wx.EVT_SIZE, self.OnSize) self.library_manager.add_download_state_callback( self.RefreshTransferSpeed) def UpdateTunnelContrib(self): totalup = ( sum(_barter_statistics.bartercast[ BartercastStatisticTypes.TUNNELS_BYTES_SENT].values()) + sum(_barter_statistics.bartercast[ BartercastStatisticTypes.TUNNELS_RELAY_BYTES_SENT].values()) + sum(_barter_statistics.bartercast[ BartercastStatisticTypes.TUNNELS_EXIT_BYTES_SENT].values())) totaldown = ( sum(_barter_statistics.bartercast[ BartercastStatisticTypes.TUNNELS_BYTES_RECEIVED].values()) + sum(_barter_statistics.bartercast[ BartercastStatisticTypes.TUNNELS_RELAY_BYTES_RECEIVED].values( )) + sum(_barter_statistics.bartercast[ BartercastStatisticTypes.TUNNELS_EXIT_BYTES_RECEIVED].values()) ) self.SetTunnelContrib(totalup + totaldown, totalup - totaldown) @warnWxThread def SetTunnelContrib(self, totalcontrib, netcontrib): self.tunnel_contrib.SetLabel('Total: %s' % size_format(totalcontrib, truncate=2)) self.tunnel_contribNet.SetLabel('Balance: %s' % size_format(netcontrib, truncate=2)) self.Reposition() @forceWxThread def RefreshFreeSpace(self, space): if space >= 0: space_str = size_format(space, truncate=1) space_label = space_str.replace(' ', '') space_tooltip = 'You currently have %s of disk space available on your default download location.' % space_str self.free_space.SetLabel(space_label) self.free_space.Show(True) self.free_space_sbmp.Show(True) # TODO martijn: we disabled some tooltips that are periodically updated on OS X. # There seems to be a bug (in wx3) where the tooltip would always show when being updated. if sys.platform != 'darwin': self.free_space_sbmp.SetToolTipString(space_tooltip) self.free_space.SetToolTipString(space_tooltip) else: self.free_space.Show(False) self.free_space_sbmp.Show(False) self.Reposition() def RefreshTransferSpeed(self, dslist, magnetlist): if not self: return self.UpdateTunnelContrib() total_down, total_up = get_download_upload_speed(dslist) self.SetTransferSpeeds(speed_format(total_down), speed_format(total_up)) @warnWxThread def SetTransferSpeeds(self, down, up): self.speed_down.SetLabel(down) self.speed_up.SetLabel(up) self.Reposition() def SetGlobalMaxSpeed(self, direction, value): if direction in [UPLOAD, DOWNLOAD]: if direction == UPLOAD: self.utility.write_config('maxuploadrate', value) self.guiutility.utility.session.set_max_upload_speed(value) else: self.utility.write_config('maxdownloadrate', value) self.guiutility.utility.session.set_max_download_speed(value) def GetSpeedChoices(self, value): values = round_range(max(0, value)) if value != 0 else range( 0, 1000, 100) values = [value or -1 for value in values] if value != 0 and value not in values: values.append(value) values.sort() values.append(0) return [('unlimited' if value == 0 else ('0' if value == -1 else str(value)), value) for value in values] def OnDownloadPopup(self, event): menu = wx.Menu() current = self.utility.read_config('maxdownloadrate') value_tuples = self.GetSpeedChoices(current) for value_str, value in value_tuples: itemid = wx.NewId() menu.AppendRadioItem(itemid, value_str) menu.Bind(wx.EVT_MENU, lambda x, v=value: self.SetGlobalMaxSpeed(DOWNLOAD, v), id=itemid) menu.Check(itemid, current == value) self.speed_down.PopupMenu(menu, event.GetPosition()) menu.Destroy() self.speed_down.Layout() def OnUploadPopup(self, event): menu = wx.Menu() current = self.utility.read_config('maxuploadrate') value_tuples = self.GetSpeedChoices(current) for value_str, value in value_tuples: itemid = wx.NewId() menu.AppendRadioItem(itemid, value_str) menu.Bind(wx.EVT_MENU, lambda x, v=value: self.SetGlobalMaxSpeed(UPLOAD, v), id=itemid) menu.Check(itemid, current == value) self.speed_up.PopupMenu(menu, event.GetPosition()) menu.Destroy() self.speed_up.Layout() def OnCheckbox(self, event): checkbox = event.GetEventObject() checkbox.Enable(False) wx.CallLater(1000, checkbox.Enable, True) wx.CallLater(100, self.__toggleFF, event.GetEventObject().GetValue()) @warnWxThread def __toggleFF(self, newvalue): if newvalue != self.guiutility.getFamilyFilter(): self.guiutility.toggleFamilyFilter(newvalue) @warnWxThread def SetConnections(self, connectionPercentage, totalConnections, channelConnections): self.connection.SetPercentage(connectionPercentage) if sys.platform != 'darwin': self.connection.SetToolTipString('Connected to %d peers' % totalConnections) self.channelconnections = channelConnections def GetConnections(self): return self.connection.GetPercentage() def GetChannelConnections(self): return self.channelconnections @warnWxThread def onReachable(self, event=None): if not self.guiutility.firewall_restart: self.firewallStatus.SetBitmapLabel(self.bmp_firewall_ok) self.firewallStatus.SetBitmapDisabled(self.bmp_firewall_ok) self.firewallStatus.SetToolTipString('Port is working') @warnWxThread def IsReachable(self): if not self.guiutility.firewall_restart: return self.firewallStatus.GetBitmapLabel() == self.bmp_firewall_ok return False @warnWxThread def onActivity(self, msg): if self.activity_timer: self.activity_timer.Stop() def revert(): if not self: return self.activity.SetBitmap(self.activityImages[1]) self.activity.Refresh() self.activity.SetBitmap(self.activityImages[0]) self.activity.Refresh() if sys.platform != 'darwin': self.activity.SetToolTipString(msg) self.activity_timer = wx.CallLater(300, revert) def OnSize(self, event): self.Reposition() def Reposition(self): self.Freeze() # default spacing rules # - field has 1 control, center it # - field has -1 width (fill), skip it # - starting from the right align all controls with 10 spacing between them, or 7 if it it a bitmap for field_index, field in enumerate(self.fields): if field[0] == -1: continue rect = self.GetFieldRect(field_index) if len(field[2]) == 1: control = field[2][0] control.SetPosition( (rect.x + (rect.width - control.GetSize()[0]) / 2, rect.y + (rect.height - control.GetSize()[1]) / 2)) else: x = rect.x + rect.width for control in reversed(field[2]): spacer = 10 if not isinstance(control, wx.StaticBitmap) else 7 x -= control.GetSize()[0] + spacer control.SetPosition( (x, rect.y + (rect.height - control.GetSize()[1]) / 2)) # any other layout work not covered by the default rules should happen here. rect = self.GetFieldRect(0) self.ff_checkbox.SetPosition((rect.x + 2, rect.y + 2)) self.ff_checkbox.SetSize((-1, rect.height - 4)) self.sizeChanged = False self.Thaw()