def gui_construct(self): from gui.buddylist.buddylist import BuddyList from gui.infobox.infobox import InfoBox # the main buddy list self.infobox = InfoBox(self) self.buddylist = BuddyList(self, self.infobox, keyhandler=self.on_buddylist_char) self.buddylist.infobox_scrollers.update([InfoBox, AccountList]) self.buddylist.Bind(wx.EVT_KEY_DOWN, self.on_buddylist_key) self.buddylist.Bind(wx.EVT_SCROLLWIN_THUMBTRACK, self.on_blist_thumbtrack) self.buddylist.Bind(wx.EVT_SCROLLWIN_THUMBRELEASE, self.on_blist_thumbrelease) self.statuscombo = StatusCombo(self, self.buddylist, profile.statuses) self.statuscombo.OnActivateSearch += self.on_activate_search self.statuscombo.OnDeactivateSearch += self.on_deactivate_search self.status = PanelFrame(self, self.statuscombo, 'statuspanel') self.blist = PanelFrame(self, self.buddylist, 'buddiespanel') def labelcallback(a, acctlist): if getattr(a, 'alias', None) is not None: out = a.alias else: atypecount = len([ acct.protocol_info().name for acct in acctlist if acct.enabled and acct.protocol_info().name == a.protocol_info().name ]) out = a.protocol_info().name if atypecount == 1 else ( '%s' % a.display_name) if a.state != a.Statuses.CHECKING and profile.account_manager.state_desc( a): return out + (' (%s)' % profile.account_manager.state_desc(a)) else: if hasattr(a, 'count_text_callback'): return a.count_text_callback(out) elif hasattr(a, 'count') and a.count is not None: return out + (' (%s)' % a.count) else: return out # panel for all active email accounts self.elist = PanelFrame( self, AccountList(self, profile.emailaccounts, self.infobox, skinkey='emailpanel', prefkey='buddylist.emailpanel', onDoubleClick=lambda a: a.OnClickInboxURL(), labelCallback=lambda a: labelcallback( a, profile.emailaccounts)), 'emailpanel') def foo(a): if a.state != a.Statuses.CHECKING: bar = profile.account_manager.state_desc(a) else: bar = a.count return '%s (%s)' % (a.display_name, bar) # panel for all active social network accounts def DoubleClickAction(a): url = a.DefaultAction() self.infobox.DoubleclickHide() if url is not None: wx.LaunchDefaultBrowser(url) def leave_slist(e): # since slist may call infobox.DoubleClickHide, it needs to invalidate # it as well. e.Skip() self.infobox.InvalidateDoubleclickHide() self.slist = PanelFrame( self, AccountList(self, profile.socialaccounts, self.infobox, skinkey='socialpanel', prefkey='buddylist.socialpanel', onDoubleClick=DoubleClickAction, labelCallback=lambda a: labelcallback( a, profile.socialaccounts)), 'socialpanel') self.slist.panel.Bind(wx.EVT_LEAVE_WINDOW, leave_slist) self.clist = ConnectionsPanel(self) self.infobox.Befriend(self.blist) self.infobox.Befriend(self.elist) self.infobox.Befriend(self.slist) # construct the main menu if not newMenubar: from gui.buddylist import buddylistmenu self.menubar = buddylistmenu.create_main_menu(self) if self.menubar.native: self.Top.SetMenuBar(self.menubar) else: asumenu = False parent = self.Parent if platformName != "mac": asumenu = True parent = self self.menubar = menus.set_menubar( parent, menubar.digsbyWxMenuBar(), umenu=asumenu) #@UndefinedVariable
def gui_construct(self): from gui.buddylist.buddylist import BuddyList from gui.infobox.infobox import InfoBox # the main buddy list self.infobox = InfoBox(self) self.buddylist = BuddyList(self, self.infobox, keyhandler = self.on_buddylist_char) self.buddylist.infobox_scrollers.update([InfoBox, AccountList]) self.buddylist.Bind(wx.EVT_KEY_DOWN, self.on_buddylist_key) self.buddylist.Bind(wx.EVT_SCROLLWIN_THUMBTRACK, self.on_blist_thumbtrack) self.buddylist.Bind(wx.EVT_SCROLLWIN_THUMBRELEASE, self.on_blist_thumbrelease) self.statuscombo = StatusCombo(self, self.buddylist, profile.statuses) self.statuscombo.OnActivateSearch += self.on_activate_search self.statuscombo.OnDeactivateSearch += self.on_deactivate_search self.status = PanelFrame(self, self.statuscombo, 'statuspanel') self.blist = PanelFrame(self, self.buddylist, 'buddiespanel') def labelcallback(a, acctlist): if getattr(a, 'alias', None) is not None: out = a.alias else: atypecount = len([acct.protocol_info().name for acct in acctlist if acct.enabled and acct.protocol_info().name == a.protocol_info().name]) out = a.protocol_info().name if atypecount == 1 else ('%s' % a.display_name) if a.state != a.Statuses.CHECKING and profile.account_manager.state_desc(a): return out + (' (%s)' % profile.account_manager.state_desc(a)) else: if hasattr(a, 'count_text_callback'): return a.count_text_callback(out) elif hasattr(a, 'count') and a.count is not None: return out + (' (%s)' % a.count) else: return out # panel for all active email accounts self.elist = PanelFrame(self, AccountList(self, profile.emailaccounts, self.infobox, skinkey = 'emailpanel', prefkey = 'buddylist.emailpanel', onDoubleClick = lambda a: a.OnClickInboxURL(), labelCallback = lambda a: labelcallback(a, profile.emailaccounts)), 'emailpanel' ) def foo(a): if a.state != a.Statuses.CHECKING: bar = profile.account_manager.state_desc(a) else: bar = a.count return '%s (%s)' % (a.display_name, bar) # panel for all active social network accounts def DoubleClickAction(a): url = a.DefaultAction() self.infobox.DoubleclickHide() if url is not None: wx.LaunchDefaultBrowser(url) def leave_slist(e): # since slist may call infobox.DoubleClickHide, it needs to invalidate # it as well. e.Skip() self.infobox.InvalidateDoubleclickHide() self.slist = PanelFrame(self, AccountList(self, profile.socialaccounts, self.infobox, skinkey = 'socialpanel', prefkey = 'buddylist.socialpanel', onDoubleClick = DoubleClickAction, labelCallback = lambda a: labelcallback(a, profile.socialaccounts)), 'socialpanel' ) self.slist.panel.Bind(wx.EVT_LEAVE_WINDOW, leave_slist) self.clist = ConnectionsPanel(self) self.infobox.Befriend(self.blist) self.infobox.Befriend(self.elist) self.infobox.Befriend(self.slist) # construct the main menu if not newMenubar: from gui.buddylist import buddylistmenu self.menubar = buddylistmenu.create_main_menu(self) if self.menubar.native: self.Top.SetMenuBar(self.menubar) else: asumenu = False parent = self.Parent if platformName != "mac": asumenu = True parent = self self.menubar = menus.set_menubar(parent, menubar.digsbyWxMenuBar(),umenu=asumenu) #@UndefinedVariable
class BuddyListPanel(SimplePanel): 'Holds the buddy list.' def __init__(self, parent=None): SimplePanel.__init__(self, parent) self.Sizer = wx.BoxSizer(wx.VERTICAL) link = profile.prefs.link #@UndefinedVariable # setup and layout GUI self.tray_icons = [] self.gui_construct() rebuild = self.rebuild_panels rebuild() # Watch always on top changes def ontop_changed(val): docker = wx.GetTopLevelParent(self).docker if docker.docked and docker.AutoHide: return p = wx.GetTopLevelParent(self) if val: p.WindowStyle = p.WindowStyle | wx.STAY_ON_TOP else: p.WindowStyle = p.WindowStyle & ~wx.STAY_ON_TOP self.unlinkers = [ link(*a) for a in [( 'buddylist.always_on_top', ontop_changed, True, self ), ('buddylist.order', lambda v: self.gui_layout(), False, self), ('buddylist.show_status', rebuild, False), ( 'buddylist.show_email_as', rebuild, False), ('buddylist.show_social_as', rebuild, False), ('buddylist.show_menubar', lambda v: self.gui_layout(), False, self), ('social.display_attr', rebuild, False), ('email.display_attr', rebuild, False), ('buddylist.show_in_taskbar', lambda val: wx.CallAfter(lambda: setattr( self.Top, 'OnTaskbar', val)), True, self)] ] # link docking preferences link = profile.localprefs.link docker = wx.GetTopLevelParent(self).docker self.unlinkers += [ link(*a) for a in [ ('buddylist.dock.autohide', lambda v: docker.SetAutoHide(bool(v)), True, docker), ('buddylist.dock.enabled', lambda v: docker.SetEnabled(bool(v)), True, docker), ('buddylist.dock.revealms', lambda v: setattr( docker, 'RevealDurationMs', try_this(lambda: int(v), 300)), True, docker), ] ] self.unlinkers.append( profile.prefs.link( 'buddylist.dock.slide_velocity', lambda v: wx.CallAfter(docker.SetVelocity, int(v)), obj=docker)) #@UndefinedVariable self.unlinkers.append( Storage(unlink=profile.emailaccounts.add_list_observer( rebuild, rebuild, 'enabled').disconnect)) self.unlinkers.append( Storage(unlink=profile.socialaccounts.add_list_observer( rebuild, rebuild, 'enabled').disconnect)) # don't ever let this control take focus self.Bind(wx.EVT_SET_FOCUS, lambda e: self.blist.SetFocus()) def UpdateSkin(self): wx.CallAfter(self.Layout) @bind('buddylist.infobox.selectnext') def SelectNext(self): self.blist.RotateContact(forward=True) @bind('buddylist.infobox.selectprev') def SelectPrev(self): self.blist.RotateContact(forward=False) def GetMaxRequiredSize(self): """ This method doesn't quite work as it needs to for Mac. buddylist.GetVirtualSize() does not give us the right size because we want the size it needs to display without scrolling, but the VirtualSize grows as the actual control size grows. i.e. once the control size is larger than the virtual size, the virtual size simply returns the control size. Also, for some reason, the virtual size reported on Mac is about 20 pixels less than what is needed to actually display the contents. """ size = self.buddylist.GetVirtualSize() size.y += self.statuscombo.GetSize().y size.y += self.elist.GetSize().y size.y += self.clist.GetVirtualSize().y return size def on_blist_thumbtrack(self, event): event.Skip() if pref('search.buddylist.show_hint', True) and not self.statuscombo.searchHintShown: self.statuscombo.ShowSearchHint() def on_blist_thumbrelease(self, event): event.Skip() if self.statuscombo.searchHintShown: self.statuscombo.HideSearchHint() def gui_construct(self): from gui.buddylist.buddylist import BuddyList from gui.infobox.infobox import InfoBox # the main buddy list self.infobox = InfoBox(self) self.buddylist = BuddyList(self, self.infobox, keyhandler=self.on_buddylist_char) self.buddylist.infobox_scrollers.update([InfoBox, AccountList]) self.buddylist.Bind(wx.EVT_KEY_DOWN, self.on_buddylist_key) self.buddylist.Bind(wx.EVT_SCROLLWIN_THUMBTRACK, self.on_blist_thumbtrack) self.buddylist.Bind(wx.EVT_SCROLLWIN_THUMBRELEASE, self.on_blist_thumbrelease) self.statuscombo = StatusCombo(self, self.buddylist, profile.statuses) self.statuscombo.OnActivateSearch += self.on_activate_search self.statuscombo.OnDeactivateSearch += self.on_deactivate_search self.status = PanelFrame(self, self.statuscombo, 'statuspanel') self.blist = PanelFrame(self, self.buddylist, 'buddiespanel') def labelcallback(a, acctlist): if getattr(a, 'alias', None) is not None: out = a.alias else: atypecount = len([ acct.protocol_info().name for acct in acctlist if acct.enabled and acct.protocol_info().name == a.protocol_info().name ]) out = a.protocol_info().name if atypecount == 1 else ( '%s' % a.display_name) if a.state != a.Statuses.CHECKING and profile.account_manager.state_desc( a): return out + (' (%s)' % profile.account_manager.state_desc(a)) else: if hasattr(a, 'count_text_callback'): return a.count_text_callback(out) elif hasattr(a, 'count') and a.count is not None: return out + (' (%s)' % a.count) else: return out # panel for all active email accounts self.elist = PanelFrame( self, AccountList(self, profile.emailaccounts, self.infobox, skinkey='emailpanel', prefkey='buddylist.emailpanel', onDoubleClick=lambda a: a.OnClickInboxURL(), labelCallback=lambda a: labelcallback( a, profile.emailaccounts)), 'emailpanel') def foo(a): if a.state != a.Statuses.CHECKING: bar = profile.account_manager.state_desc(a) else: bar = a.count return '%s (%s)' % (a.display_name, bar) # panel for all active social network accounts def DoubleClickAction(a): url = a.DefaultAction() self.infobox.DoubleclickHide() if url is not None: wx.LaunchDefaultBrowser(url) def leave_slist(e): # since slist may call infobox.DoubleClickHide, it needs to invalidate # it as well. e.Skip() self.infobox.InvalidateDoubleclickHide() self.slist = PanelFrame( self, AccountList(self, profile.socialaccounts, self.infobox, skinkey='socialpanel', prefkey='buddylist.socialpanel', onDoubleClick=DoubleClickAction, labelCallback=lambda a: labelcallback( a, profile.socialaccounts)), 'socialpanel') self.slist.panel.Bind(wx.EVT_LEAVE_WINDOW, leave_slist) self.clist = ConnectionsPanel(self) self.infobox.Befriend(self.blist) self.infobox.Befriend(self.elist) self.infobox.Befriend(self.slist) # construct the main menu if not newMenubar: from gui.buddylist import buddylistmenu self.menubar = buddylistmenu.create_main_menu(self) if self.menubar.native: self.Top.SetMenuBar(self.menubar) else: asumenu = False parent = self.Parent if platformName != "mac": asumenu = True parent = self self.menubar = menus.set_menubar( parent, menubar.digsbyWxMenuBar(), umenu=asumenu) #@UndefinedVariable @bind('BuddyList.Accounts.ToggleShow') def ToggleConnPanel(self): self.clist.ToggleState() def gui_layout(self, layoutNow=True): assert wx.IsMainThread() elems = ['status', 'blist', 'clist', 'slist', 'elist'] searching = self.Searching panel_order = pref('buddylist.order', elems) email_view = pref('buddylist.show_email_as', 'panel') in ('panel', 'both') and len( self.elist.active) social_view = pref('buddylist.show_social_as', 'panel') in ('panel', 'both') and len( self.slist.active) status_view = searching or pref('buddylist.show_status', True) viewable = Storage() with self.Frozen(): self.Sizer.Clear() # remove all children, but don't delete. show_menu = pref('buddylist.show_menubar', True) if not config.platform == 'mac': if show_menu: self.Sizer.Add(self.menubar.SizableWindow, 0, EXPAND) self.menubar.Show(show_menu) if searching or (hasattr(self, 'status') and status_view): viewable.status = (self.status, 0, EXPAND) viewable.blist = (self.blist, 1, EXPAND) viewable.clist = (self.clist, 0, EXPAND) if email_view: viewable.elist = (self.elist, 0, EXPAND) if social_view: viewable.slist = (self.slist, 0, EXPAND) AddInOrder(self.Sizer, *panel_order, **viewable) self.status.Show(status_view) self.elist.Show(email_view) self.slist.Show(social_view) if layoutNow: self.Layout() def rebuild_panels(self, *a): wx.CallAfter(self._rebuild_panels) @calllimit(1) def _rebuild_panels(self): trayaccts = [] if pref('buddylist.show_email_as', 'panel') in ('systray', 'both'): trayaccts += [a for a in profile.emailaccounts] if pref('buddylist.show_social_as', 'panel') in ('systray', 'both'): trayaccts += [a for a in profile.socialaccounts] with self.Frozen(): if trayaccts: shown = [a for (a, icon) in self.tray_icons] enabled = [a for a in trayaccts if a.enabled] icons = dict(self.tray_icons) e, s = set(enabled), set(shown) # remove tray icons no longer needed do(icons.pop(acct).Destroy() for acct in s - e) # add new ones, indexed by their positions in the accounts list for acct in sorted(e - s, key=lambda a: enabled.index(a), reverse=True): try: icons[acct] = AccountTrayIcon.create( acct, self.infobox) except Exception: print_exc() self.tray_icons = icons.items() else: # destroy all tray icons do(icon.Destroy() for acct, icon in self.tray_icons) self.tray_icons = {} wx.CallAfter(self.gui_layout) def on_destroy(self): log.info('BuddylistPanel.on_destroy') for linker in self.unlinkers: linker.unlink() self.elist.OnClose() self.slist.OnClose() log.info('destroying account tray icons') for acct, icon in self.tray_icons: try: log.info("destroying account tray icon %r...", icon) icon.Destroy() log.info('ok') except Exception: print_exc() # # searchbox functionality # def start_search(self, e=None): self.statuscombo.search(e) if not self.status.IsShown(): self.gui_layout() def on_buddylist_char(self, e): if e.KeyCode not in disallowed_search_keys: with self.Frozen(): # the key event will be emulated on the search box self.start_search(e) if e is not None: e.Skip() def on_buddylist_key(self, e): if e.Modifiers == wx.MOD_CMD and e.KeyCode == ord('F'): self.start_search() else: e.Skip() @property def Searching(self): 'Returns True if the searchbox has focus.' status = getattr(self, 'statuscombo', None) return status is not None and status.searching def on_activate_search(self): self.infobox.Hide() def on_deactivate_search(self): if not pref('buddylist.show_status', True): self.gui_layout()
class BuddyListPanel(SimplePanel): 'Holds the buddy list.' def __init__( self, parent = None ): SimplePanel.__init__(self, parent) self.Sizer = wx.BoxSizer(wx.VERTICAL) link = profile.prefs.link #@UndefinedVariable # setup and layout GUI self.tray_icons = [] self.gui_construct() rebuild = self.rebuild_panels rebuild() # Watch always on top changes def ontop_changed(val): docker = wx.GetTopLevelParent(self).docker if docker.docked and docker.AutoHide: return p = wx.GetTopLevelParent(self) if val: p.WindowStyle = p.WindowStyle | wx.STAY_ON_TOP else: p.WindowStyle = p.WindowStyle & ~wx.STAY_ON_TOP self.unlinkers = [link(*a) for a in [ ('buddylist.always_on_top', ontop_changed, True, self), ('buddylist.order', lambda v: self.gui_layout(), False, self), ('buddylist.show_status', rebuild, False), ('buddylist.show_email_as', rebuild, False), ('buddylist.show_social_as', rebuild, False), ('buddylist.show_menubar', lambda v: self.gui_layout(), False, self), ('social.display_attr', rebuild, False), ('email.display_attr', rebuild, False), ('buddylist.show_in_taskbar', lambda val: wx.CallAfter(lambda: setattr(self.Top, 'OnTaskbar', val)), True, self) ]] # link docking preferences link = profile.localprefs.link docker = wx.GetTopLevelParent(self).docker self.unlinkers += [link(*a) for a in [ ('buddylist.dock.autohide', lambda v: docker.SetAutoHide(bool(v)), True, docker), ('buddylist.dock.enabled', lambda v: docker.SetEnabled(bool(v)), True, docker), ('buddylist.dock.revealms', lambda v: setattr(docker, 'RevealDurationMs', try_this(lambda: int(v), 300)), True, docker), ]] self.unlinkers.append(profile.prefs.link('buddylist.dock.slide_velocity', lambda v: wx.CallAfter(docker.SetVelocity,int(v)), obj = docker)) #@UndefinedVariable self.unlinkers.append(Storage(unlink = profile.emailaccounts.add_list_observer (rebuild, rebuild, 'enabled').disconnect)) self.unlinkers.append(Storage(unlink = profile.socialaccounts.add_list_observer(rebuild, rebuild, 'enabled').disconnect)) # don't ever let this control take focus self.Bind(wx.EVT_SET_FOCUS, lambda e:self.blist.SetFocus()) def UpdateSkin(self): wx.CallAfter(self.Layout) @bind('buddylist.infobox.selectnext') def SelectNext(self): self.blist.RotateContact(forward = True) @bind('buddylist.infobox.selectprev') def SelectPrev(self): self.blist.RotateContact(forward = False) def GetMaxRequiredSize(self): """ This method doesn't quite work as it needs to for Mac. buddylist.GetVirtualSize() does not give us the right size because we want the size it needs to display without scrolling, but the VirtualSize grows as the actual control size grows. i.e. once the control size is larger than the virtual size, the virtual size simply returns the control size. Also, for some reason, the virtual size reported on Mac is about 20 pixels less than what is needed to actually display the contents. """ size = self.buddylist.GetVirtualSize() size.y += self.statuscombo.GetSize().y size.y += self.elist.GetSize().y size.y += self.clist.GetVirtualSize().y return size def on_blist_thumbtrack(self, event): event.Skip() if pref('search.buddylist.show_hint', True) and not self.statuscombo.searchHintShown: self.statuscombo.ShowSearchHint() def on_blist_thumbrelease(self, event): event.Skip() if self.statuscombo.searchHintShown: self.statuscombo.HideSearchHint() def gui_construct(self): from gui.buddylist.buddylist import BuddyList from gui.infobox.infobox import InfoBox # the main buddy list self.infobox = InfoBox(self) self.buddylist = BuddyList(self, self.infobox, keyhandler = self.on_buddylist_char) self.buddylist.infobox_scrollers.update([InfoBox, AccountList]) self.buddylist.Bind(wx.EVT_KEY_DOWN, self.on_buddylist_key) self.buddylist.Bind(wx.EVT_SCROLLWIN_THUMBTRACK, self.on_blist_thumbtrack) self.buddylist.Bind(wx.EVT_SCROLLWIN_THUMBRELEASE, self.on_blist_thumbrelease) self.statuscombo = StatusCombo(self, self.buddylist, profile.statuses) self.statuscombo.OnActivateSearch += self.on_activate_search self.statuscombo.OnDeactivateSearch += self.on_deactivate_search self.status = PanelFrame(self, self.statuscombo, 'statuspanel') self.blist = PanelFrame(self, self.buddylist, 'buddiespanel') def labelcallback(a, acctlist): if getattr(a, 'alias', None) is not None: out = a.alias else: atypecount = len([acct.protocol_info().name for acct in acctlist if acct.enabled and acct.protocol_info().name == a.protocol_info().name]) out = a.protocol_info().name if atypecount == 1 else ('%s' % a.display_name) if a.state != a.Statuses.CHECKING and profile.account_manager.state_desc(a): return out + (' (%s)' % profile.account_manager.state_desc(a)) else: if hasattr(a, 'count_text_callback'): return a.count_text_callback(out) elif hasattr(a, 'count') and a.count is not None: return out + (' (%s)' % a.count) else: return out # panel for all active email accounts self.elist = PanelFrame(self, AccountList(self, profile.emailaccounts, self.infobox, skinkey = 'emailpanel', prefkey = 'buddylist.emailpanel', onDoubleClick = lambda a: a.OnClickInboxURL(), labelCallback = lambda a: labelcallback(a, profile.emailaccounts)), 'emailpanel' ) def foo(a): if a.state != a.Statuses.CHECKING: bar = profile.account_manager.state_desc(a) else: bar = a.count return '%s (%s)' % (a.display_name, bar) # panel for all active social network accounts def DoubleClickAction(a): url = a.DefaultAction() self.infobox.DoubleclickHide() if url is not None: wx.LaunchDefaultBrowser(url) def leave_slist(e): # since slist may call infobox.DoubleClickHide, it needs to invalidate # it as well. e.Skip() self.infobox.InvalidateDoubleclickHide() self.slist = PanelFrame(self, AccountList(self, profile.socialaccounts, self.infobox, skinkey = 'socialpanel', prefkey = 'buddylist.socialpanel', onDoubleClick = DoubleClickAction, labelCallback = lambda a: labelcallback(a, profile.socialaccounts)), 'socialpanel' ) self.slist.panel.Bind(wx.EVT_LEAVE_WINDOW, leave_slist) self.clist = ConnectionsPanel(self) self.infobox.Befriend(self.blist) self.infobox.Befriend(self.elist) self.infobox.Befriend(self.slist) # construct the main menu if not newMenubar: from gui.buddylist import buddylistmenu self.menubar = buddylistmenu.create_main_menu(self) if self.menubar.native: self.Top.SetMenuBar(self.menubar) else: asumenu = False parent = self.Parent if platformName != "mac": asumenu = True parent = self self.menubar = menus.set_menubar(parent, menubar.digsbyWxMenuBar(),umenu=asumenu) #@UndefinedVariable @bind('BuddyList.Accounts.ToggleShow') def ToggleConnPanel(self): self.clist.ToggleState() def gui_layout(self, layoutNow = True): assert wx.IsMainThread() elems = ['status', 'blist','clist', 'slist', 'elist'] searching = self.Searching panel_order = pref('buddylist.order', elems) email_view = pref('buddylist.show_email_as', 'panel') in ('panel', 'both') and len(self.elist.active) social_view = pref('buddylist.show_social_as', 'panel') in ('panel', 'both') and len(self.slist.active) status_view = searching or pref('buddylist.show_status', True) viewable = Storage() with self.Frozen(): self.Sizer.Clear() # remove all children, but don't delete. show_menu = pref('buddylist.show_menubar', True) if not config.platform == 'mac': if show_menu: self.Sizer.Add(self.menubar.SizableWindow, 0, EXPAND) self.menubar.Show(show_menu) if searching or (hasattr(self, 'status') and status_view): viewable.status = (self.status, 0, EXPAND) viewable.blist = (self.blist, 1, EXPAND) viewable.clist = (self.clist, 0, EXPAND) if email_view: viewable.elist = (self.elist, 0, EXPAND) if social_view: viewable.slist = (self.slist, 0, EXPAND) AddInOrder(self.Sizer, *panel_order, **viewable) self.status.Show(status_view) self.elist.Show(email_view) self.slist.Show(social_view) if layoutNow: self.Layout() def rebuild_panels(self, *a): wx.CallAfter(self._rebuild_panels) @calllimit(1) def _rebuild_panels(self): trayaccts = [] if pref('buddylist.show_email_as', 'panel') in ('systray', 'both'): trayaccts += [a for a in profile.emailaccounts] if pref('buddylist.show_social_as', 'panel') in ('systray', 'both'): trayaccts += [a for a in profile.socialaccounts] with self.Frozen(): if trayaccts: shown = [a for (a, icon) in self.tray_icons] enabled = [a for a in trayaccts if a.enabled] icons = dict(self.tray_icons) e, s = set(enabled), set(shown) # remove tray icons no longer needed do(icons.pop(acct).Destroy() for acct in s - e) # add new ones, indexed by their positions in the accounts list for acct in sorted(e - s, key = lambda a: enabled.index(a), reverse = True): try: icons[acct] = AccountTrayIcon.create(acct, self.infobox) except Exception: print_exc() self.tray_icons = icons.items() else: # destroy all tray icons do(icon.Destroy() for acct, icon in self.tray_icons) self.tray_icons = {} wx.CallAfter(self.gui_layout) def on_destroy(self): log.info('BuddylistPanel.on_destroy') for linker in self.unlinkers: linker.unlink() self.elist.OnClose() self.slist.OnClose() log.info('destroying account tray icons') for acct, icon in self.tray_icons: try: log.info("destroying account tray icon %r...", icon) icon.Destroy() log.info('ok') except Exception: print_exc() # # searchbox functionality # def start_search(self, e = None): self.statuscombo.search(e) if not self.status.IsShown(): self.gui_layout() def on_buddylist_char(self, e): if e.KeyCode not in disallowed_search_keys: with self.Frozen(): # the key event will be emulated on the search box self.start_search(e) if e is not None: e.Skip() def on_buddylist_key(self, e): if e.Modifiers == wx.MOD_CMD and e.KeyCode == ord('F'): self.start_search() else: e.Skip() @property def Searching(self): 'Returns True if the searchbox has focus.' status = getattr(self, 'statuscombo', None) return status is not None and status.searching def on_activate_search(self): self.infobox.Hide() def on_deactivate_search(self): if not pref('buddylist.show_status', True): self.gui_layout()