def each(hook_identifier, *a, **k): impls = k.pop('impls', [k.pop('impl', None)]) for impl in impls: for hook in Hook(hook_identifier, impl): try: yield hook(*a, **k) except Exception: traceback.print_exc()
def get_image_load_paths(paths): 'Returns a list of paths from which skin images can be loaded.' image_load_paths = [p.parent for p in paths] for pathhook in Hook('digsby.skin.load.skinpaths'): hook_paths = pathhook() if hook_paths is not None: image_load_paths.extend(hook_paths) return image_load_paths
def syn(identifier, *args, **kwargs): ret = True for hook in Hook(identifier): #_log.info('HOOK: %s',repr(hook)) try: ret = hook(*args, **kwargs) if not ret: ret = False except Exception: traceback.print_exc() return ret
def first(hook_identifier, *a, **k): impls = k.pop('impls', [k.pop('impl', None)]) raise_exceptions = k.pop('raise_hook_exceptions', False) for impl in impls: for hook in Hook(hook_identifier, impl=impl): try: v = hook(*a, **k) if v is not None: return v except Exception: if raise_exceptions: raise traceback.print_exc() return None
def reduce(hook_identifier, arg, *args, **kwargs): ''' Passes arg to the first Hook found for hook_identifier. The return value of that hook goes to the next hook, and so on. The return value of the last Hook becomes the return value of this function. ''' raise_exceptions = kwargs.pop('raise_exceptions', False) impls = kwargs.pop('impls', [kwargs.pop('impl', None)]) for impl in impls: for hook in Hook(hook_identifier, impl): if raise_exceptions: arg = hook(arg, *args, **kwargs) else: try: arg = hook(arg, *args, **kwargs) except Exception: traceback.print_exc() return arg
def group_profile_statuses(): msgs = sorted((c for c in profile.statuses), key=lambda msg: msg.away) j = -1 for j, msg in enumerate(msgs): if msg.away: break else: j = -1 if j == -1: j = len(msgs) avail_msgs = msgs[:j] avail_msgs.insert(0, StatusMessage.Available.copy()) away_msgs = msgs[j:] away_msgs.insert(0, StatusMessage.Away.copy()) return avail_msgs, away_msgs, filter( None, [s() for s in Hook('digsby.im.statusmessages')])
def on_status_messages_changed(self, *a): ''' Invoked when a status message changes, or the user status list changes. Rebuilds the status menu items. ''' log.info('on_status_messages_changed, updating menu') self.RemoveAllItems() additem = self.additem def add_status_item(pname, name): additem([skin.get('statusicons.%s' % pname), name], method=getattr(self, 'on_' + pname)) # Available add_status_item('available', _('Available')) # user statuses self.sortedstatuses = msgs = sorted([c for c in profile.statuses], key=lambda msg: msg.away) # Find where to insert the special "Away" status item j = -1 found = False for j, msg in enumerate(msgs): if msg.away: found = True break for i, msg in enumerate(msgs): if found and i == j: add_status_item('away', _('Away')) online_image = skin.get( 'statusicons.away' if msg.away else 'statusicons.available') additem([online_image, msg.title], method=lambda mi, msg=msg: self.setandshow(msg), id=i) if not found or j == -1: add_status_item('away', _('Away')) # Custom... additem(_('Custom...'), method=self.on_custom) self.AppendSeparator() if global_status_enabled(): additem([skin.get('icons.globalstatus'), _('Global Status')], method=self.on_global) log.info('updating status menu with %d extra statuses', len(Hook('digsby.im.statusmessages'))) for msg in Hook('digsby.im.statusmessages'): message = msg() if message is None: continue additem([message.icon, message.title], method=lambda mi, msg=msg: self.setandshow(msg())) if global_status_enabled(): additem([skin.get('statusicons.promote'), _('Promote Digsby!')], method=self.on_promote) # Invisible additem([skin.get('statusicons.invisible'), _('Invisible')], self.on_invisible) # Offline self.offline_item = None self.on_offline_allowed()
def __init__(self, parent, buddylist, statuses, get_status_method=get_profile_status, set_status_method=set_profile_status): ''' StatusCombo constructor. parent - a wx.Window parent window statuses - an observable list of StatusMessage objects ''' self.buddylist = buddylist self.buddylist.Bind(wx.EVT_KEY_DOWN, self.on_buddylist_key) self.searching = False self.searchHintShown = False if not getattr(StatusCombo, 'searchThresholdRegistered', False) and pref('search.buddylist.show_hint', True): def SearchThresholdReached(*a, **k): if pref('search.buddylist.show_hint', True): setpref('search.buddylist.show_hint', False) Hook('digsby.achievements.threshold', 'buddylist.search').register(SearchThresholdReached) StatusCombo.searchThresholdRegistered = True self.offline_item = None self.get_profile_status = get_status_method self.set_profile_status = set_status_method status = self.get_profile_status() UberCombo.__init__(self, parent, skinkey='combobox', typeable=True, valuecallback=self.on_text_lose_focus, empty_text=getattr(status, 'hint', status.title.title()), maxmenuheight=15) self.buttoncallback = self.on_status_button self.cbutton = UberButton(self, -1, skin=self.cbuttonskin) self.cbutton.Bind(wx.EVT_BUTTON, self._on_left_button) self.content.Insert(0, self.cbutton, 0, wx.EXPAND) self.cbutton.BBind(RIGHT_UP=self.on_status_button_right_click, LEFT_DOWN=self.on_status_button_left_click, LEFT_UP=self.on_status_button_left_up) self.display.Bind( wx.EVT_LEFT_DOWN, lambda e: (e.Skip(), setattr(self, 'oldValue', self.Value))) # the on_allow_status_changes method is called when the list of connected # im accounts changes size. if all accounts are offline this control # becomes disabled.. #profile.account_manager.connected_accounts.add_observer(self.on_allow_status_changes) profile.account_manager.connected_accounts.add_observer( self.on_offline_allowed, obj=self) # Listen on status messages (changes, additions, deletes). _obs_link = statuses.add_list_observer(self.on_status_messages_changed, self.on_status_messages_changed) self.Bind( wx.EVT_WINDOW_DESTROY, lambda e: (log.info('status combo removing observers'), e.Skip(), _obs_link.disconnect())) self.on_status_messages_changed(statuses) # when the profile's status changes, update to reflect it profile.add_observer(self.on_profile_status_changed, 'status') # Display the current status. self.show_status(self.get_profile_status()) # Timer for committing status messages after a delay. self.timer = wx.PyTimer(self.SetFocus) self.Bind(wx.EVT_TEXT, self.on_typing) self.button_timer = wx.PyTimer(self.on_status_button_right_click) textbind = self.TextField.Bind textbind(wx.EVT_SET_FOCUS, lambda e: setattr(self, 'skipenter', False)) textbind(wx.EVT_KEY_DOWN, self._on_key_down) textbind(wx.EVT_TEXT_ENTER, self._on_enter) self.DropDownButton.Bind(wx.EVT_LEFT_DOWN, self._dbutton_left) self.OnActivateSearch = Delegate() self.OnDeactivateSearch = Delegate()
def create_main_menu(parent): 'Returns the main menu object.' menu = MenuBar(parent, skinkey='menubar') digsby = Menu(parent) view = Menu(parent) tools = Menu(parent) help = Menu(parent) def makeadd(m): return (lambda title, callback=None, id=-1: m.AddItem( title, callback=callback, id=id)) # # My Status # mystatus = Menu(parent, onshow=update_statuses) add = makeadd(mystatus) add(_('&New Status Message...'), new_status_message) add(_('&Edit Status Messages...'), lambda: prefsdialog_show('status')) mystatus.AddSep() from gui.protocols import add_group def add_chat(): import gui.chatgui gui.chatgui.join_chat() # # Digsby # digsby.AddSubMenu(mystatus, _('My Status')) add = makeadd(digsby) add(_('My &Accounts...'), lambda: prefsdialog_show('accounts')) digsby.AddSep() sendimitem = add(_('&New IM...\tCtrl+N'), ShowNewIMDialog) if pref('messaging.groupchat.enabled', False): groupchatitem = add(_('New Group C&hat...\tCtrl+Shift+N'), add_chat) else: groupchatitem = None digsby.AddSep() addcontactitem = add(_('Add &Contact...\tCtrl+A'), lambda: AddContactDialog.MakeOrShow()) addgroupitem = add(_('Add &Group...\tCtrl+Shift+A'), lambda: add_group()) renameitem = add(_('&Rename Selection'), lambda: parent.blist.rename_selected()) deleteitem = add( _('&Delete Selection...'), lambda: parent.blist.delete_blist_item(parent.blist.SelectedItem)) digsby.AddSep() add(_('Sign &Off Digsby (%s)') % profile.name, lambda: profile.signoff()) # wx.App handles this for proper shutdown. add(_('E&xit Digsby'), id=wx.ID_EXIT) def on_digsby_show(_m): b = parent.blist.SelectedItem allow_add = any(x.allow_contact_add for x in profile.account_manager.connected_accounts) for item in (sendimitem, groupchatitem, addcontactitem, addgroupitem): if item is not None: item.Enable(allow_add) if not allow_rename(b): renameitem.SetItemLabel(_('&Rename Selection')) deleteitem.SetItemLabel(_('&Delete Selection')) renameitem.Enable(False) deleteitem.Enable(False) else: renameitem.SetItemLabel( _('&Rename {name}').format(name=getattr(b, 'alias', b.name))) deleteitem.SetItemLabel( _('&Delete {name}').format(name=getattr(b, 'alias', b.name))) renameitem.Enable(True) deleteitem.Enable(True) # # View # add = makeadd(view) view.AddPrefCheck('buddylist.always_on_top', _('&Always On Top')) add(_('Skins...\tCtrl+S'), lambda: prefsdialog_show('appearance')) view.AddSep() view.AddPrefCheck('buddylist.show_menubar', _('&Menu Bar')) def on_menubar(val): if not val: wx.MessageBox( _('You can bring back the menubar by right clicking ' 'on the digsby icon in the task tray.'), _('Hide Menu Bar')) profile.prefs.link('buddylist.show_menubar', lambda val: wx.CallAfter(on_menubar, val), False, menu) view.AddPrefCheck('buddylist.show_status', _('Status Panel')) add(_('Arrange &Panels...'), callback=lambda *_a: edit_buddylist_order(parent)) view.AddSep() view.AddPrefCheck('buddylist.show_mobile', _('Show &Mobile Contacts\tCtrl+M')) view.AddPrefCheck('buddylist.show_offline', _('Show &Offline Contacts\tCtrl+O')) groupoffline = view.AddPrefCheck('buddylist.group_offline', _('&Group Offline Contacts\tCtrl+G')) hideoffline = view.AddPrefCheck('buddylist.hide_offline_groups', _('&Hide Offline Groups')) groupby = Menu(parent) add = makeadd(groupby) groupby.sorttypes = [] # sort by sortby = Menu(parent) add = makeadd(sortby) sortby.sorttypes = [] sort_models = profile.blist.sort_models group_by = sort_models[0] sort_by = sort_models[1] then_by = sort_models[2] def addsort(model, view, sortstr, title): def set(model=model, view=view, sortstr=sortstr): model.selection = [v[0] for v in model.values].index(sortstr) view[model.selection].Check(True) mi = view.AddCheckItem(title, set) view.sorttypes.append(sortstr) return mi sort_names = dict( (('none', _('&None')), ('status', _('&Status')), ('name', _('N&ame')), ('log', _('&Log Size')), ('service', _('Ser&vice')))) def addsorts(model, view, names): for name in names: addsort(model=model, view=view, sortstr=name, title=sort_names[name]) addsorts(model=group_by, view=groupby, names=[k for k, _v in GROUP_BY_CHOICES]) groupby.AddSep() groupby.AddItem(_('Advan&ced...'), callback=lambda: prefsdialog_show('contact_list')) addsorts(model=sort_by, view=sortby, names=[k for k, _v in SORT_BY_CHOICES]) sortby.AddSep() def sortby_adv_click(): sortby[-1].Check(then_by.selection > 0) prefsdialog_show('contact_list') sortby.AddCheckItem(_('Advan&ced...'), callback=sortby_adv_click) sortby_adv = sortby[-1] groupby.reset_watcher = reset_checks_SortOptionWatcher( model=group_by, view=groupby, names=GROUP_BY_CHOICES) sortby.reset_watcher = reset_checks_SortOptionWatcher( model=sort_by, view=sortby, names=SORT_BY_CHOICES) sortby.adv_watcher = reset_check_AdvWatcher(model=then_by, view=sortby_adv) view.AddSep() view.AddSubMenu(groupby, _('&Group By')) view.AddSubMenu(sortby, _('&Sort By')) # # Tools # add = makeadd(tools) add(_('&Preferences...\tCtrl+P'), id=wx.ID_PREFERENCES, callback=lambda: prefsdialog_show('accounts')) add(_('Buddy List &Search\tCtrl+F'), parent.start_search) add(_('&File Transfer History\tCtrl+J'), FileTransferDialog.Display) def pb_show(): from gui.pastbrowser import PastBrowser PastBrowser.MakeOrShow() add(_('&Chat History\tCtrl+H'), pb_show) # # Help # add = makeadd(help) add(_('&Documentation'), lambda: wx.LaunchDefaultBrowser('http://wiki.digsby.com')) add(_('Support &Forums'), lambda: wx.LaunchDefaultBrowser('http://forum.digsby.com')) help.AddSep() add(_('&Submit Bug Report'), do_diagnostic) add(_('Su&ggest a Feature'), send_features_email) help.AddSep() if getattr(sys, 'DEV', False) or pref('debug.console', False): add(_('Show Debug Console'), wx.GetApp().toggle_crust) help.AddSep() add(_('Su&pport Digsby'), lambda: support.SupportFrame.MakeOrShow(parent)) for hook in Hook("digsby.help.actions"): help_menu_items = hook() for item in help_menu_items: add(*item) def on_view_show(_m): sortstatus = pref('buddylist.sortby').startswith('*status') showoffline = pref('buddylist.show_offline') hidegroups = pref('buddylist.hide_offline_groups') groupoff = pref('buddylist.group_offline') groupoffline.Enable(not sortstatus and showoffline) groupoffline.Check(groupoff and (not sortstatus and showoffline)) hideoffline.Enable(not sortstatus) hideoffline.Check((sortstatus and not showoffline) or (not sortstatus and hidegroups)) digsbyMenuName = _('&Digsby') if config.platformName == "mac": digsbyMenuName = _("&File") menu.Append(digsby, digsbyMenuName, onshow=on_digsby_show) menu.Append(view, _('&View'), onshow=on_view_show) menu.Append(tools, _('&Tools'), onshow=lambda m: on_accounts_entries(parent, m)) menu.Append(help, _('&Help')) return menu
def setup(self): if self.did_setup: warnings.warn('reinitialized AddOn CountTracker') return self.did_setup = True from peak.util.plugins import Hook Hook('digsby.im.msg.async', 'stats_counter').register(self.im) Hook('digsby.statistics.emoticons.box_viewed', 'stats_counter').register(self.emoticon_box_viewed) Hook('digsby.statistics.emoticons.chosen', 'stats_counter').register(self.emoticon_chosen) Hook('digsby.video_chat.requested', 'stats_counter').register(self.video_chat_requested) Hook('digsby.statistics.sms.sent', 'stats_counter').register(self.sms_sent) Hook('digsby.statistics.logviewer.log_viewed', 'stats_counter').register(self.log_viewed) Hook('digsby.statistics.prefs.prefs_opened', 'stats_counter').register(self.prefs_opened) Hook('digsby.statistics.imwin.imwin_created', 'stats_counter').register(self.imwin_created) Hook('digsby.statistics.imwin.imwin_engage', 'stats_counter').register(self.imwin_engage) Hook('digsby.statistics.infobox.shown', 'stats_counter').register(self.infobox_shown) Hook('digsby.statistics.contact_added', 'stats_counter').register(self.contact_added) Hook('digsby.statistics.ui.select_status', 'stats_counter').register(self.ui_select_status) Hook('digsby.statistics.ui.dialogs.add_contact.created', 'stats_counter').register(self.contact_add_dialog) Hook('digsby.app.exit', 'stats_counter').register(self.flush) Hook('digsby.stats_counter.important_threshold', 'stats_counter').register(self.important) for hook_name, server_side_name in simple_incrementers: Hook(hook_name, 'stats_counter').register(self.self_incrementer(server_side_name)) Hook('digsby.statistics.feed_ads.citygrid.click_cents', 'stats_counter').register(self.citygrid_click) Hook('digsby.research.run_time', 'stats_counter').register(self.research_run_time)
def register(hook_identifier, cb, impl=None): return Hook(hook_identifier, impl).register(cb)
trees.append(load_skinfile(f)) except Exception, e: errors.append(e) del e else: successful = True if not successful: MessageBox('There was an error loading skin "%s":\n\n%s' % (skin, '\n'.join(str(e) for e in errors)), 'Skin Error') # trees can also be supplied via Hook from gui.skin import SkinStorage to_skinstorage = dictrecurse(SkinStorage) for hook in Hook('digsby.skin.load.trees'): hook_trees = hook() if hook_trees is not None: # transform all mappings provided by plugins into SkinStorage # objects # TODO: why is dictrecurse not a deepcopy? trees[insert_position:insert_position] = (to_skinstorage(deepcopy(t)) for t in hook_trees) return trees def get_image_load_paths(paths): 'Returns a list of paths from which skin images can be loaded.' image_load_paths = [p.parent for p in paths]