Example #1
0
def metacontact_buddy_menu(menu, mc):
    lenmc = len(mc)

    for contact in mc:
        # add a service specific menu for each contact in the metacontact
        contact_menu = Menu(menu.Window)

        # search_bases = False means we'll get the actions specific to the buddy's service
        actions.menu(menu.Window, contact, contact_menu, search_bases=False)

        if contact_menu[0].IsSeparator():
            contact_menu.RemoveItem(contact_menu[0])

        if lenmc > 2:
            contact_menu.AddSep()
            contact_menu.AddItem(_('&Remove from Merged Contact'),
                                 callback=lambda contact=contact: mc.manager.
                                 remove(mc, contact))

        # use the contact's service icon for the submenu (greyed out if offline)
        icon = contact.serviceicon
        if not contact.online:
            icon = icon.Greyed

        menu.AddSubMenu(contact_menu, contact.name, bitmap=icon)
Example #2
0
    def on_fbar_context_menu(self, e):
        # TODO: why isn't the IM window's formatting bar its own subclass!?

        from gui.uberwidgets.umenu import UMenu
        m = UMenu(self)
        m.AddItem(_('Hide Formatting Bar'), callback = lambda: wx.CallAfter(setpref, 'messaging.show_formatting_bar', False))
        m.PopupMenu()
Example #3
0
    def popup(self):
        if hasattr(self, '_menu') and self._menu: self._menu.Destroy()
        from gui.uberwidgets.umenu import UMenu
        menu = UMenu(self)
        if not self.data.type == 'fb':
            menu.AddItem(_('&Edit'), callback=lambda: self.on_edit())
        menu.AddItem(_('&Delete'), callback=lambda: self.on_delete())
        menu.AddSep()
        common.actions.menu(self, self.data, menu)

        self._menu = menu
        return menu
Example #4
0
    def popup(self):
        if hasattr(self, '_menu') and self._menu: self._menu.Destroy()
        menu = UMenu(self)

        menu.AddItem(_('&Edit'),   callback = lambda: self.on_edit())
        menu.AddItem(_('&Remove'), callback = lambda: self.on_delete())

        menu.AddSep()
        actions.menu(self, self.data, menu)

        self._menu = menu
        return menu
Example #5
0
def yahoo_buddy_menu(menu, contact):
    '''
    Appends a Yahoo-specific "Stealth Settings" submenu to "menu".

    account   - YahooProtocol object
    menu      - a UMenu
    selection - the selected Contact object or None
    '''
    menu_title = _('&Stealth Settings')

    stealth_menu = Menu(menu.Window)
    enable = stealth_menu.Enable
    a = stealth_menu.AddCheckItem

    name = getattr(contact, 'name', _('Selection'))

    # append an item for each stealth option
    items = [
        a(_('Appear Online to {name}').format(name=name),
          callback=lambda: contact.set_stealth_session(False)),
        a(_('Appear Offline to {name}').format(name=name),
          callback=lambda: contact.set_stealth_session(True)),
        a(_('Appear Permanently Offline to {name}').format(name=name),
          callback=lambda: contact.set_stealth_perm(True))
    ]

    # append a separator and a link to the webpage explaining stealth mode
    stealth_menu.AddSep()
    a(_('Learn More (URL)'),
      callback=lambda: wx.LaunchDefaultBrowser(
          'http://messenger.yahoo.com/stealth.php'))

    online, offline, perm = items

    # items are disabled unless a yahoo buddy is selected
    if contact is None or contact.service != 'yahoo':
        for item in items:
            enable(item.Id, False)
            item.Check(False)
    else:
        invisible = profile.status.invisible
        enable(online.Id, True)
        enable(offline.Id, invisible)
        enable(perm.Id, True)

        if contact.stealth_perm:
            perm.Check(True)
        elif invisible and contact.stealth_session:
            offline.Check(True)
        elif not invisible or not contact.stealth_session:
            online.Check(True)

    menu.AddSubMenu(stealth_menu, menu_title)
    def __OnContextMenu(self, e):
        from gui.uberwidgets.umenu import UMenu
        from gui.toolbox import std_textctrl_menu

        with UMenu.Reuse(self) as menu:
            self.AddSuggestionsToMenu(menu)
            std_textctrl_menu(self, menu)
Example #7
0
    def __init__(self, parent):
        super(ConnectionList, self).__init__(parent)

        #set here so that when a profile change occurs the reference updates correctly
        global accounts
        accounts = profile.account_manager.accounts

        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)

        self.Sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetScrollRate(0, 1)
        self.SetSkinKey('accountpanels', True)
        self.ShowAll = False

        self.oldaccounts = []
        self.panels = {}

        accounts.add_observer(self.WhenListChanges)
        profile.account_manager.add_observer(self.InitShow, 'accounts_loaded')

        self.menu = UMenu(self)

        Bind = self.Bind
        Bind(wx.EVT_PAINT, self.OnPaint)
        Bind(wx.EVT_ERASE_BACKGROUND, lambda e: None)
        Bind(wx.EVT_SIZE, self.OnSize)
        self.BindWheel(self)
        Bind(wx.EVT_SCROLLWIN_LINEDOWN,
             lambda e: self.Scroll(0, self.ViewStart[1] + SCROLLCONST))
        Bind(wx.EVT_SCROLLWIN_LINEUP,
             lambda e: self.Scroll(0, self.ViewStart[1] - SCROLLCONST))
        Bind(wx.EVT_SCROLLWIN, lambda e:
             (e.Skip(), wx.CallAfter(self.Refresh)))
        Bind(wx.EVT_KEY_DOWN, self.OnKey)
Example #8
0
def default_umenu(tc):
    from gui.uberwidgets.umenu import UMenu
    m = UMenu(tc)

    # spelling suggestions and options
    if isinstance(tc, SpellCheckTextCtrlMixin):
        tc.AddSuggestionsToMenu(m)

    m.AddItem(_('Copy'),  id = wx.ID_COPY,  callback = tc.Copy)
    m.AddItem(_('Paste'), id = wx.ID_PASTE, callback = tc.Paste)
    m.AddSep()

    from gui.toolbox import add_rtl_checkbox
    add_rtl_checkbox(tc, m)

    return m
Example #9
0
    def __init__(
            self,
            parent,
            accts,
            infobox,
            skinkey,
            prefkey=None,
            onDoubleClick=None,  # a callable taking an acct
            labelCallback=None,  # a callable: acct -> unicode
    ):
        wx.VListBox.__init__(self, parent)
        self.SetSkinKey(skinkey)

        self.prefkey = prefkey
        self.unlocked = pref(self.prefkey + '.unlocked', True)

        self._obs_link = None
        self.infobox = infobox
        infobox.Befriend(self)

        self.accts = accts

        self.willreconaccts = set()

        self.itemheight = 0
        self.UpdateSkin()

        Bind = self.Bind
        Bind(wx.EVT_MOTION, self.OnMouseMotion)
        Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseOut)
        Bind(wx.EVT_RIGHT_UP, self.OnRightUp)
        Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
        Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDblClick)
        Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnMouseLost)

        self.BuildList()

        self.menu = UMenu(self)

        self.OnDoubleClick = Delegate(
            [onDoubleClick] if onDoubleClick is not None else [])
        self.labelCallback = labelCallback

        self.BindObservers()
Example #10
0
    def popup(self):
        try:
            return self._popupmenu
        except AttributeError:
            self._popupmenu = menu = UMenu(self)

            menu.AddItem(_('&Edit'), callback=self.on_edit)
            menu.AddItem(_('&Remove'), callback=self.on_delete)
            return menu
Example #11
0
    def CreatePopupMenu(self):
        buddy_frame = wx.FindWindowByName('Buddy List')

        # TODO: fix skinned menus so that they don't need to be told they are in the system tray!
        umenu = UMenu(buddy_frame, onshow=None, windowless=True)

        add_hidden_convo_menu_items(umenu)

        statuscombo.add_global_to_menu(umenu, _('Set &Global Status...'))
        statmenu = UMenu(
            buddy_frame,
            onshow=None)  #statuscombo.create_status_menu(add_custom = True)
        statuscombo.status_menu(statmenu, add_custom=True, add_promote=True)
        umenu.AddSubMenu(statmenu, _('Set IM &Status'))

        umenu.AddSep()

        show_hide = umenu.AddItem(_('Show &Buddy List'),
                                  id=actionIDs.ShowBuddyList)
        if buddy_frame:
            docker = getattr(buddy_frame, 'docker', None)

            if docker:
                disable_hide = docker.Enabled and docker.docked and docker.AutoHide
                show_hide.label = _(
                    'Hide &Buddy List') if buddy_frame.Shown else _(
                        'Show &Buddy List')
                show_hide.Enable(not disable_hide)

        # The menubar is the "app" menubar on Mac and thus cannot be hidden.
        if platformName != 'mac':
            umenu.AddPrefCheck('buddylist.show_menubar', _('Show Menu Bar'))

        umenu.AddItem(_('&Preferences...'), id=wx.ID_PREFERENCES)

        # Mac gets this menu item standard on the Dock, don't duplicate it.
        if platformName != 'mac':
            umenu.AddSep()
            umenu.AddItem(_('E&xit Digsby'), id=wx.ID_EXIT)

        # since status items are created dynamically, we must bind to them on the fly.
        self.SetupStatusHandlers()

        return umenu
Example #12
0
    def build_actionsbar_menu(self):
        m = UMenu(self, onshow=self.update_actionsbar_menu)

        c = self._actionsbar_checks = {}
        for name, label in [('icons', _('Icons Only')),
                            ('text', _('Text Only')),
                            ('next', _('Icons Next to Text')),
                            ('above', _('Icons Above Text'))]:

            def cb(name=name):
                with self.Frozen():
                    setpref(action_icons_key, name)

            c[name] = m.AddCheckItem(label, callback=cb)

        m.AddSep()
        m.AddItem(
            _('Hide Actions Bar'),
            callback=lambda: setpref('messaging.show_actions_bar', False))

        return m
Example #13
0
    def addmenu(self):
        try:
            return self.add_popup
        except AttributeError:
            self.add_popup = menu = UMenu(self)
            protocols = common.protocolmeta.protocols
            emailprotocols = common.protocolmeta.emailprotocols

            for p in emailprotocols.keys():
                menu.AddItem(protocols[p].name,
                             callback=lambda p=p: self.add_account(p),
                             bitmap=skin.get('serviceicons.' + p, None))
            return menu
Example #14
0
    def ShowMenu(self, e):
        self._menutab = e.EventObject

        try:
            menu = self._tabmenu
        except AttributeError:
            from gui.uberwidgets.umenu import UMenu
            menu = self._tabmenu = UMenu(self)
            menu.AddItem('Close &Other Tabs', id = CLOSE_OTHER_TABS)
            menu.AddSep()
            menu.AddItem('&Close Tab', id = CLOSE_TAB)

        menu.PopupMenu()
    def GenMenu(self):
        m = UMenu(self)

        # spelling suggestions and options
        if isinstance(self, SpellCheckTextCtrlMixin):
            if self.AddSuggestionsToMenu(m):
                m.AddSep()

        m.AddItem(_('Cut'),   id = wx.ID_CUT,   callback = self.Cut)
        m.AddItem(_('Copy'),  id = wx.ID_COPY,  callback = self.Copy)
        m.AddItem(_('Paste'), id = wx.ID_PASTE, callback = self.Paste)
        m.AddSep()
        m.AddItem(_('Select All'), id = wx.ID_SELECTALL, callback = lambda: self.SetSelection(0, self.GetLastPosition()))
        m.AddSep()

        from gui.toolbox import add_rtl_checkbox
        add_rtl_checkbox(self, m)

        return m
Example #16
0
def GetTextCtrlMenu(self):
    from gui.uberwidgets.umenu import UMenu

    m, tc = UMenu(self), self.input_area.tc

    # spelling suggestions and options
    from gui.spellchecktextctrlmixin import add_spelling_suggestions
    if add_spelling_suggestions(tc, m):
        m.AddSep()

    m.AddItem(
        _('Copy'), id=wx.ID_COPY,
        callback=tc.Copy)  # todo: disable if "not tc.CanCopy()" when shown.
    m.AddItem(_('Paste'), id=wx.ID_PASTE, callback=tc.Paste)
    m.AddSep()

    m.AddPrefCheck('messaging.show_actions_bar', _('Show &Actions Bar'))
    m.AddPrefCheck('messaging.show_formatting_bar', _('Show &Formatting Bar'))
    m.AddPrefCheck('messaging.show_send_button', _('Show Send Button'))
    m.AddSep()
    gui.toolbox.add_rtl_checkbox(tc, m)

    return m
Example #17
0
    def popup(self):
        if not hasattr(self, '_menu') or not self._menu:
            self._menu = menu = UMenu(self)
        else:
            menu = self._menu
            menu.RemoveAllItems()

        menu.AddItem(_('&Edit'), callback=lambda: self.on_edit())
        menu.AddItem(_('&Remove'), callback=lambda: self.on_delete())

        if self.data.enabled:
            menu.AddSep()
            common.actions.menu(self, self.data, menu)

        return menu
Example #18
0
    def __init__(self, acct, infobox=None):

        # This method doesn't run for PyObjC icons (see initWithAccount instead), so it's okay
        # to put wx and Observable code in here.

        self.acct = acct
        self.infobox = infobox
        from gui.uberwidgets.umenu import UMenu
        self._menu = UMenu(wx.FindWindowByName('Buddy List'),
                           onshow=self.update_menu)

        # generate unique tray icon IDs for each account that are persistent
        # across program runs (specifically, for Windows' tray icon hiding options)
        trayid = hash('accounttrayicon_' + acct.protocol + '_' + acct.name)

        super(AccountTrayIcon, self).__init__(acct.icon,
                                              menu=self._menu,
                                              id=trayid)

        self.Bind(wx.EVT_TASKBAR_LEFT_DOWN, self.on_click)
        self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.on_double_click)

        self.register_observers(acct, self.on_account_updated)
        self.on_account_updated()
Example #19
0
def refresh_wx_tree():
    '''
    Calls "UpdateSkin" on every GUI control that has it, descending from top
    level windows down through their children.
    '''

    # UMenus aren't necessarily wx Children accessible
    # through the widget tree--skip them on the tree descent
    from gui.uberwidgets.umenu import UMenu
    skip = (UMenu, )

    for window in GetTopLevelWindows():
        with window.FrozenQuick():
            _updateskin(window, skip)

    # now update menus
    UMenu.CallAll(UMenu.UpdateSkin)
Example #20
0
    def xfer_popup(self):
        list = self
        try:
            return list._popupmenu
        except AttributeError:
            pass

        list._popupmenu = menu = UMenu(self, onshow=self.on_rightclick_show)

        menu.open = menu.AddItem(_('&Open'),
                                 callback=lambda: list._menurow.on_open())
        menu.openfolder = menu.AddItem(
            _('Open &Containing Folder'),
            callback=lambda: list._menurow.on_open_folder())
        menu.AddSep()
        menu.remove = menu.AddItem(_('&Remove'),
                                   callback=lambda: list._menurow.on_remove())
        return menu
Example #21
0
    def initWithAccount(self, acct, infobox):
        with nspool():
            self.acct = acct
            self.infobox = infobox
            from gui.uberwidgets.umenu import UMenu
            self._menu = UMenu(wx.FindWindowByName('Buddy List'),
                               onshow=self.update_menu)
            statusbar = NSStatusBar.systemStatusBar()
            self.statusitem = statusbar.statusItemWithLength_(
                NSVariableStatusItemLength)

            self.statusitem.setTarget_(self)
            self.statusitem.setAction_("itemClicked:")

            # set up our observer
            self.observer = Notifier(self)
            acct.add_observer(self.observer.on_account_updated,
                              'count',
                              'state',
                              obj=self.observer)
            self.on_account_updated()
Example #22
0
    def __init__(self,parent):
        SimplePanel.__init__(self, parent, wx.FULL_REPAINT_ON_RESIZE)

        self.BackgroundColour = wx.WHITE

        self.Sizer = wx.BoxSizer(HORIZONTAL)
        sz = wx.BoxSizer(HORIZONTAL)

        self.Sizer.Add(sz,1,EXPAND|ALL,3)

        leftcol = wx.BoxSizer(VERTICAL)

        acctcombo = self.acctcombo = UberCombo(self, value='',skinkey='AppDefaults.PrefCombo')
        acctcont = PrefPanel(self,acctcombo,_('Account'))


        leftcol.Add(acctcont,0,EXPAND|ALL,3)

        buddylist = self.buddylist = ListOBuddies(self)
        self.buddies_panel = buddycont = PrefPanel(self, buddylist, _('Buddy'))
        leftcol.Add(buddycont, 1, EXPAND | TOPLESS, 3)

        style = wx.NO_BORDER | CAL_SUNDAY_FIRST | CAL_SEQUENTIAL_MONTH_SELECTION | CAL_SHOW_HOLIDAYS
        cal = self.cal = CalendarCtrl(self, -1, wx.DateTime.Now(), wx.DefaultPosition, wx.DefaultSize, style)

        cal.SetForegroundColour(wx.Color(160, 160, 160))
        cal.SetHolidayColours(wx.BLACK, wx.WHITE)
        cal.SetHeaderColours(Color(160, 160, 160), Color(239, 239, 239))

        calcont = PrefPanel(self,cal,_('Date'))
        leftcol.Add(calcont, 0, EXPAND | TOPLESS, 3)

        sz.Add(leftcol, 0, EXPAND)

        viewpanel = wx.Panel(self)

        viewer = self.viewer = PastBrowserWebkitWindow(viewpanel)
#        viewer.SetMouseWheelZooms(True)
        finder = self.finder = FindBar(viewpanel,viewer)

        menu = UMenu(viewer)
        menu.AddItem(_('Copy'),  id = wx.ID_COPY,  callback = lambda *a: viewer.Copy())

        viewer.BindWheel(self)
        viewer.BindScrollWin(self)
        viewer.Bind(wx.EVT_CONTEXT_MENU,
                    lambda e: (menu.GetItemById(wx.ID_COPY).Enable(viewer.CanCopy()),
                               menu.PopupMenu(event = e)))

        viewer.Bind(wx.EVT_KEY_DOWN,self.OnKeyDown)
        finder.TextControl.Bind(wx.EVT_KEY_DOWN,self.OnKeyDown)

        nav  = BoxSizer(wx.HORIZONTAL)

        prev = self.prev = UberButton(viewpanel, label = '<-', skin = BUTTON_SKIN)
        next = self.next = UberButton(viewpanel, label = '->', skin = BUTTON_SKIN)

        datelabel = wx.StaticText(viewpanel, -1, style = wx.ALIGN_CENTER| wx.ST_NO_AUTORESIZE)
        datelabel.SetMinSize((140, -1))


        prev.Bind(wx.EVT_BUTTON, lambda e: self.Flip(-1))
        next.Bind(wx.EVT_BUTTON, lambda e: self.Flip( 1))

        nav.AddStretchSpacer(1)
        nav.AddMany([(prev, 0, wx.EXPAND | wx.ALIGN_CENTER),
                     (datelabel, 0, wx.EXPAND | wx.ALIGN_CENTER),
                     (next, 0, wx.EXPAND | wx.ALIGN_CENTER)])
        nav.AddStretchSpacer(1)


        viewpanel.Sizer = wx.BoxSizer(wx.VERTICAL)
        viewpanel.Sizer.AddMany([ (nav,    0, EXPAND),
                                  (viewer, 1, EXPAND),
                                  (finder, 0, EXPAND) ])

        sz.Add(PrefPanel(self, viewpanel, _('Conversation Log')), 1, EXPAND | ALL, 3)

        Bind = self.Bind
        Bind(wx.EVT_PAINT, self.OnPaint)

        def OnAcct(*a):
            '''
            Handle selection of a new account from the Account drop down
            '''
            if self.GroupChatsSelected():
                from collections import defaultdict
                self.groupchats = defaultdict(list)
                for g in GetGroupChats():
                    d = g['time']
                    key = DateTimeFromDMY(d.day, d.month-1, d.year)
                    self.groupchats[key].append(g)

                #dates = sorted((g['date'], g) for g in
                self.dates = sorted(self.groupchats.keys())
                UpdateCal()
                self.buddies_panel.SetTitle(_('Chats'))
            else:
                buddylist.SetList(GetBuddies(acctcombo.Value.id), BuddyRenderer())
                OnBuddy()
                self.buddies_panel.SetTitle(_('Buddy'))

        def OnBuddy(*a):
            '''
            Handels selection of a buddy from the buddy pannel
            '''

            if not self.GroupChatsSelected():
                self.dates = GetDates(buddylist.SelectedBuddy.dir)
                UpdateCal()
            else:
                ViewLogForFile(buddylist.SelectedItem['file'], do_aliases=False)

        def UpdateCal():
            '''
            Switches the date to the last date conversed with the selected budy
            '''
            self.next.Enable(True)
            self.prev.Enable(True)
            if self.dates:
                self.cal.Date = self.dates[-1]

            self.cal.Enable(True)
            OnCalChange()

        def OnCalChange(*a):
            '''
            Update the Calendar UI to a new date
            '''
            caldate = cal.Date

            currentyear   = caldate.GetYear()
            currentmonth  = caldate.GetMonth()
            relevantdates = frozenset(date.GetDay() for date in self.dates
                                      if date.GetYear() == currentyear and
                                      date.GetMonth() == currentmonth and date.GetDay())
            SetHoliday, SetAttr = cal.SetHoliday, cal.SetAttr

            for i in xrange(1, 32):
                if i in relevantdates:
                    SetHoliday(i)
                else:
                    SetAttr(i, CalendarDateAttr(Color(160,160,160)))


            OnDayChange()

        self.OnCalChange = OnCalChange

        def ViewLogForDay(date):
            '''
            Load the log file for the specified date for the currently selected buddy
            '''
            logpath = logpath_for_date(buddylist.SelectedBuddy, date)
            ViewLogForFile(logpath)

        def ViewLogForFile(logpath, do_aliases=True):
            '''
            Update the log viewer with the file specified
            '''
            with viewer.Frozen():
                viewer.SetPageSource(logpath.text('utf-8', 'replace'), logpath.url())
                viewer.RunScript('window.scroll(0, 0);')

                if do_aliases:
                    substitue_aliases()

                import hooks
                hooks.notify('digsby.statistics.logviewer.log_viewed')

        def substitue_aliases():
            '''
            Swap out buddy names with their allies
            '''
            import gui
            with open(gui.skin.resourcedir() / 'html' / 'jquery-1.3.2.js', 'rb') as f:
                viewer.RunScript(f.read())
            buddy = buddylist.SelectedBuddy
            aliases = IAliasProvider(profile())
            import simplejson as json
            names = set(json.loads(viewer.RunScript("var foo = []; $('.buddy').each(function(){foo.push($(this).html())}); JSON.stringify(foo);")))
            for name in names:
                alias = aliases.get_alias(name, buddy.service, buddy.protocol) or name
                viewer.RunScript(SUBHTML % (json.dumps(name), json.dumps(alias)))

        def OnDayChange(*a):
            '''
            Show the log for the day selected in the clander
            '''
            date = cal.Date
            self.date = date

            datelabel.SetLabel(date.FormatDate())

            if cal.GetAttr(date.GetDay()).IsHoliday():
                if self.GroupChatsSelected():
                    chats = sorted(self.groupchats[date], key=lambda g: g['time'], reverse=True)
                    buddylist.SetList(chats, GroupChatRenderer())
                    if chats:
                        ViewLogForFile(chats[0]['file'], do_aliases=False)
                else:
                    ViewLogForDay(date)
            else:
                year  = str(date.GetYear())
                month = date.GetMonth()
                month = wx.DateTime.GetMonthName(int(month))
                day   = str(date.GetDay())

                specific_day_string = _('{month}, {day}, {year}').format(month=month, day=day, year=year)

                if self.GroupChatsSelected():
                    msg = _("There are no chat logs for {specific_day_string}.").format(specific_day_string=specific_day_string)
                else:
                    msg = _("There are no chat logs for {specific_day_string} with {name}.").format(specific_day_string=specific_day_string, name=buddylist.SelectedBuddy.name)

                viewer.SetPageSource(msg, 'file:///C:/')

            viewer.SetFocus()


            wx.CallAfter(cal.Refresh)
        self.OnDayChange = OnDayChange

        acctcombo.SetCallbacks(value = OnAcct)
        buddylist.Bind(wx.EVT_LISTBOX, OnBuddy)

        cBind = cal.Bind
        cBind(EVT_CALENDAR_YEAR, OnCalChange)
        cBind(EVT_CALENDAR_MONTH, OnCalChange)
        cBind(EVT_CALENDAR_SEL_CHANGED, OnDayChange)

        acctcombo.SetItems(MakeAccountItems(), 0)
Example #23
0
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
Example #24
0
def GetMenu(self):
    try:
        self._menu.Destroy()
    except AttributeError:
        pass

    from gui.uberwidgets.umenu import UMenu
    m = UMenu(self, onshow=self._onpopupshown)

    self._menu = m
    self._topid = id(self.Top)

    self.keep_on_top = m.AddCheckItem(_('&Keep on Top'),
                                      callback=self.Top.ToggleOnTop)
    self.view_past_chats_item = m.AddItem(_('&View Past Chats'),
                                          callback=self._on_view_past_chats)

    m.AddSep()

    add, addcheck, setmode = m.AddItem, m.AddCheckItem, self.set_mode

    c = self.capsbuttons = {}
    buddy = self.Buddy
    for bname, caption in buttons:
        if bname == 'files':
            c[bname] = add(caption, callback=lambda: self.Buddy.send_file())
        else:
            if buddy is None or (bname == 'sms' and 'SMS' not in buddy.caps):
                continue

            c[bname] = addcheck(
                caption,
                callback=lambda b=bname: setmode(b, toggle_tofrom=b == 'im'))

    m.AddSep()

    self.edit_items = {}
    self.edit_items['Copy'] = add(_('Copy\tCtrl+C'), id=wx.ID_COPY)

    # add a "Copy Link" item if the mouse is hovering over a link
    message_area = getattr(self, 'message_area', None)
    if message_area is not None:  # may not be created yet.
        ctrl = wx.FindWindowAtPointer()
        if ctrl is message_area:
            info = ctrl.HitTest(ctrl.ScreenToClient(wx.GetMousePosition()))
            if info.Link:
                add(_('Copy &Link'),
                    callback=lambda: clipboard.copy(info.Link))

    self.paste_item = self.edit_items['Paste'] = add(_('Paste\tCtrl+V'),
                                                     id=wx.ID_PASTE)
    self.paste_index = len(self._menu) - 1

    if pref('debug.message_area.show_edit_source', False):
        add(_('Edit Source'), callback=lambda: self.message_area.EditSource())
    if pref('debug.message_area.show_jsconsole', False):
        from gui.browser import jsconsole
        add(_('&Javascript Console'),
            callback=lambda: jsconsole.show_console())

    # text size menu
    if message_area is not None and message_area.IsShownOnScreen():
        textsize_menu = UMenu(self)
        self.textbigger = textsize_menu.AddItem(
            _('&Increase Text Size\tCtrl+='),
            callback=message_area.IncreaseTextSize)
        self.textsmaller = textsize_menu.AddItem(
            _('&Decrease Text Size\tCtrl+-'),
            callback=message_area.DecreaseTextSize)
        textsize_menu.AddSep()
        textsize_menu.AddItem(_('&Reset Text Size\tCtrl+0'),
                              callback=message_area.ResetTextSize)

        m.AddSubMenu(textsize_menu, _('&Text Size'))

    m.AddSep()

    # these checkboxes affect a global preference that immediately takes effect in
    # all open ImWins
    self.roomlist_item = m.AddCheckItem(_('Show &Room List'),
                                        callback=self.toggle_roomlist)
    self.actions_item = m.AddPrefCheck('messaging.show_actions_bar',
                                       _('Show &Actions Bar'))
    self.formatting_item = m.AddPrefCheck('messaging.show_formatting_bar',
                                          _('Show &Formatting Bar'))

    return self._menu
Example #25
0
 def context_menu(self):
     try:
         return self._context_menu
     except AttributeError:
         self._context_menu = UMenu(self, _('BuddyList Popup'))
         return self._context_menu
Example #26
0
 def OnContextMenu(self, event):
     from gui.uberwidgets.umenu import UMenu
     m = UMenu(self)
     m.AddItem(_('Hide Formatting Bar'), callback = lambda: wx.CallAfter(setpref, 'messaging.show_formatting_bar', False))
     m.PopupMenu()
Example #27
0
def menu(parent,
         obj,
         menu=None,
         cls=None,
         search_bases=True,
         filter=lambda func: True):
    'Builds or adds to an existing menu with actions for the specified object.'

    from gui.uberwidgets.umenu import UMenu

    actions = forclass(cls if cls is not None else obj, search_bases)
    menu = menu if menu is not None else UMenu(parent)

    # For each action defined in the YAML
    names = set()
    for action in actions:

        #
        # ---- means separator
        #
        if isinstance(action, basestring) and action.startswith('--'):
            menu.AddSep()
            continue
        #
        # method: a function to call
        #
        elif 'method' in action:
            introspect.import_function(action['method'])(menu, obj)
            continue

        name = action['call']
        if name in names: continue
        else: names.add(name)

        # the actual function
        func = getattr(obj, name, None)
        if func is None: continue

        gui_name = action['name']

        try:
            # read precondition lambda and "needs" from the @action annotations
            precondition, needslist = getattr(obj, '_actions')[name]
        except KeyError, _e:
            # ...if there is no @action annotating the method, just call it
            precondition, needslist = lambda v: True, []

        if needslist:
            import gui.userform as userform
            callback = partial(userform.getinput,
                               obj,
                               parent,
                               needslist,
                               func,
                               title=gui_name.replace('&', ''))
        elif 'gui' in action:
            gui = introspect.import_function(action['gui'])

            if not hasattr(gui, 'Prompt'):
                callback = lambda gui=gui, func=func: gui(obj, func)
            else:

                def callback(gui=gui, func=func):
                    gui(None, obj).Prompt(func)

        else:
            callback = func

        # Preconditions
        # - None:  Don't show menu item
        # - False: Show disabled menu item
        # - True:  Show menu item

        result = precondition(obj) if precondition is not None else True

        if filter(func) and (precondition is None or result is not None):
            name = action_name(obj, gui_name)
            menu.AddItem(name, callback=callback).Enable(bool(result))
Example #28
0
class AccountList(wx.VListBox, UberWidget):
    'Shows a list of active accounts with counts of new items'

    def __init__(
            self,
            parent,
            accts,
            infobox,
            skinkey,
            prefkey=None,
            onDoubleClick=None,  # a callable taking an acct
            labelCallback=None,  # a callable: acct -> unicode
    ):
        wx.VListBox.__init__(self, parent)
        self.SetSkinKey(skinkey)

        self.prefkey = prefkey
        self.unlocked = pref(self.prefkey + '.unlocked', True)

        self._obs_link = None
        self.infobox = infobox
        infobox.Befriend(self)

        self.accts = accts

        self.willreconaccts = set()

        self.itemheight = 0
        self.UpdateSkin()

        Bind = self.Bind
        Bind(wx.EVT_MOTION, self.OnMouseMotion)
        Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseOut)
        Bind(wx.EVT_RIGHT_UP, self.OnRightUp)
        Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
        Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDblClick)
        Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnMouseLost)

        self.BuildList()

        self.menu = UMenu(self)

        self.OnDoubleClick = Delegate(
            [onDoubleClick] if onDoubleClick is not None else [])
        self.labelCallback = labelCallback

        self.BindObservers()

    def OnClose(self, e=None):
        """
           Unbinds observer when this widget closes
        """
        log.info('OnClose: %r', self)
        self.UnbindObservers()

    def WhenOrderPrefChanged(self, sortorder):
        if self.order != sortorder:
            self.order = sortorder
            active = dict([(acct.id, acct) for acct in self.active])
            self.active = [active[id] for id in sortorder if id in active]
            self.Refresh()

    def WhenUnlockedPrefChanged(self, unlcoked):
        self.unlocked = pref(self.prefkey + '.unlocked', True)

    def BindObservers(self):
        """
            Sets up observers on a list of accounts
        """
        self._obs_link = self.accts.add_list_observer(
            self.BuildList, self.WhenStateChanged, 'state', 'enabled', 'count',
            'offline_reason', 'alerts', 'alias')
        profile.prefs.link(self.prefkey + '.order', self.WhenOrderPrefChanged,
                           False)
        profile.prefs.link(self.prefkey + '.unlocked',
                           self.WhenUnlockedPrefChanged, False)

    def UnbindObservers(self):
        'Removes observers on a list of accounts'

        if self._obs_link is not None:
            self._obs_link.disconnect()
            self._obs_link = None

    def CalledAfterRefreshLine(self, acct):
        try:
            self.RefreshLine(self.active.index(acct))
        except ValueError:
            self.Refresh()

    def WhenStateChanged(self, acct, attr, old, new):
        'This handles all changes on an account level.'

        #update new item count
        if attr in ('count', 'alerts', 'alias'):
            wx.CallAfter(self.CalledAfterRefreshLine, acct)
        #rebuild list when account is disabled or enabled
        elif attr == 'enabled':
            wx.CallAfter(self.BuildList)
        #Offline reason has changed, set up message
        elif attr == 'state' or attr == 'offline_reason':
            if acct.offline_reason == acct.Reasons.WILL_RECONNECT:
                self.willreconaccts.add(acct)
            else:
                self.willreconaccts.discard(acct)

            if len(self.willreconaccts):
                refreshtimer().Register(self)
            else:
                refreshtimer().UnRegister(self)

            self.Refresh()

    def OnMouseOut(self, event=None):
        """
            Make sure selection gets updated on mouse out
        """
        i = self.Selection
        if i != -1:
            self.RefreshLine(i)

        self.Selection = -1

    def OnMouseWheel(self, e):
        # foward mouse wheel events to the infobox.
        if self.infobox.IsShown():
            self.infobox.on_mousewheel(e)

    def OnMouseMotion(self, event):
        """
            Selection gets update and infobox gets requested on mouse over item
        """

        mp = event.Position
        hit = self.HitTest(mp)
        dragging = event.Dragging()
        selection = self.Selection
        active = self.active

        if self.unlocked and event.LeftIsDown(
        ) and dragging and self.HasCapture() and -1 not in (
                selection, hit) and hit != selection:
            item = active[selection]
            active.pop(selection)
            active.insert(hit, item)

            sortorder = self.order
            sortorder.remove(item.id)
            i = sortorder.index(active[hit - 1].id) + 1 if hit > 0 else 0
            sortorder.insert(i, item.id)
            setpref(self.prefkey + '.order', sortorder)

            self.Refresh()

        self.Selection = hit
        self.TryShowInfobox(hit)

    def OnLeftUp(self, event):

        while self.HasCapture():
            self.ReleaseMouse()

        if not self.ClientRect.Contains(event.Position):
            self.OnMouseOut(event)

    def OnMouseLost(self, event):
        if not self.ClientRect.Contains(
                self.ScreenToClient(wx.GetMousePosition())):
            self.OnMouseOut()

    def OnLeftDown(self, event):
        self.infobox.quickshow = True
        self.TryShowInfobox(self.Selection)

        if not self.HasCapture():
            self.CaptureMouse()

    def TryShowInfobox(self, i):
        if pref('infobox.show', True) and i >= 0:
            p = self.Parent
            pl = p.ClientToScreen(
                (0, self.Position.y + self.OnMeasureItem(0) * i))
            pr = pl + (p.Size.width, 0)

            self.infobox.Display(pl, pr, self.active[i])

    def OnLeftDblClick(self, event):
        """
            performs the action associated with the list on DOuble Click
        """
        self.OnDoubleClick(self.active[self.Selection])
        self.infobox.Hide()

    def ToggleOrderLock(self):
        self.unlocked = not self.unlocked
        setpref(self.prefkey + '.unlocked', self.unlocked)

    def OnRightUp(self, event):
        """
            Generate and open menu on right click
        """
        if self.Selection >= 0:
            # populate the popup menu with actions
            self.menu.RemoveAllItems()

            acct = self.active[self.Selection]
            if hasattr(getattr(acct, 'menu_actions', None), '__call__'):
                acct.menu_actions(self.menu)
            elif isinstance(acct, EmailAccount):
                #HAX: an ugly hack until Email-specific actions are removed from EmailAccount.
                actions.menu(wx.FindWindowByName('Buddy List'),
                             acct,
                             menu=self.menu,
                             search_bases=False,
                             cls=EmailAccount)
            else:
                actions.menu(wx.FindWindowByName('Buddy List'),
                             acct,
                             menu=self.menu)

            self.menu.AddSep()

            #            if self.prefkey is not None:
            #                unlockitem = self.menu.AddCheckItem(_('Allow Rearrange'), callback = self.ToggleOrderLock)
            #                unlockitem.Check(self.unlocked)

            self.menu.PopupMenu()

    def BuildList(self, *__):
        """
            When the account list changes rebuild the list of items to display.
            Then it recalculates size needs.
        """

        try:
            self.__i += 1
        except:
            self.__i = 1

        accts = self.accts

        sortorder = pref(self.prefkey + '.order')
        self.order = sortorder[:]

        if not len(sortorder):
            sortorder = [acct.id for acct in accts]
        elif len(sortorder) != len(accts) or set(
                acct.id for acct in accts) != set(sortorder):
            for acct in accts:
                if acct.id not in sortorder:
                    i = accts.index(acct)
                    i = sortorder.index(self.accts[i -
                                                   1].id) + 1 if i > 0 else 0
                    sortorder.insert(i, acct.id)

        sortset = set(sortorder)
        if len(sortorder) != len(sortset):
            cleansortorder = []
            for i in sortorder:
                if i in sortset:
                    cleansortorder.append(i)
                    sortset.remove(i)
            sortorder = cleansortorder

        if self.order != sortorder:
            setpref(self.prefkey + '.order', sortorder)

        active = dict([(acct.id, acct) for acct in accts if acct.enabled])
        self.active = [active[id] for id in sortorder if id in active]

        with self.Frozen():
            self.ItemCount = len(self.active)
            self.Size = self.MinSize = wx.Size(
                -1, self.ItemCount * self.itemheight)
            self.Top.Layout()
            self.Top.Refresh()

        self.Refresh()

    def UpdateSkin(self):
        """
            The usual
        """
        skinget = lambda s, default: skin('%s.%s' % (self.skinkey, s), default)

        self.padding = skinget('padding', lambda: wx.Point(3, 3))
        self.Font = skinget('font', default_font)
        self.iconsize = skinget('iconsize', 16)
        self.itemheight = max(self.iconsize,
                              self.Font.LineHeight) + self.padding.y * 2

        default_color = SkinColor(wx.Color(225, 255, 225))
        self.bg = skinget('backgrounds.normal', default_color)
        self.selbg = skinget('backgrounds.hover', default_color)

        self.fontcolor = skinget('fontcolors.normal', wx.BLACK)
        self.selfontcolor = skinget('fontcolors.hover', wx.BLACK)

        self.MinSize = wx.Size(-1, self.itemheight * self.ItemCount)

    def OnMeasureItem(self, n):
        "Returns the predetermined item height"

        return self.itemheight

    def OnDrawBackground(self, dc, rect, n):
        getattr(self,
                'selbg' if self.Selection == n else 'bg').Draw(dc, rect, n)

    def OnDrawItem(self, dc, rect, n):
        'Draw the foreground content of the item.'

        dc.Font = self.Font
        dc.TextForeground = self.selfontcolor if n == self.Selection else self.fontcolor

        acct = self.active[n]
        iconsize = self.iconsize

        if (hasattr(acct, 'count')
                and acct.count > 0) or not should_grey(acct):
            icon = acct.icon.Resized(iconsize)
        else:
            icon = acct.icon.Greyed.Resized(iconsize)

        pad = self.padding.x

        dc.DrawBitmap(icon, rect.x + pad,
                      rect.y + self.itemheight / 2 - icon.Height / 2, True)

        xoff = iconsize + 2 * pad
        textRect = wx.Rect(
            rect.x + xoff,
            rect.y + self.itemheight / 2 - dc.Font.LineHeight / 2,
            rect.width - xoff, dc.Font.LineHeight)
        dc.DrawTruncatedText(self.labelCallback(acct), textRect)
Example #29
0
class AccountTrayIcon(baseAccountTrayClass):
    @classmethod
    def create(cls, acct, infobox):
        ###
        ### TODO: this is less awful, but still awful
        ###

        trayClass = ITrayIconProvider(acct).tray_icon_class()

        if config.platform == 'mac':
            object = trayClass.alloc().init()
            object.initWithAccount(acct, infobox)
            return object
        else:
            return trayClass(acct, infobox)

    def __init__(self, acct, infobox=None):

        # This method doesn't run for PyObjC icons (see initWithAccount instead), so it's okay
        # to put wx and Observable code in here.

        self.acct = acct
        self.infobox = infobox
        from gui.uberwidgets.umenu import UMenu
        self._menu = UMenu(wx.FindWindowByName('Buddy List'),
                           onshow=self.update_menu)

        # generate unique tray icon IDs for each account that are persistent
        # across program runs (specifically, for Windows' tray icon hiding options)
        trayid = hash('accounttrayicon_' + acct.protocol + '_' + acct.name)

        super(AccountTrayIcon, self).__init__(acct.icon,
                                              menu=self._menu,
                                              id=trayid)

        self.Bind(wx.EVT_TASKBAR_LEFT_DOWN, self.on_click)
        self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.on_double_click)

        self.register_observers(acct, self.on_account_updated)
        self.on_account_updated()

    def update_menu(self, event=None):
        self._menu.RemoveAllItems()
        actions.menu(wx.FindWindowByName('Buddy List'),
                     self.acct,
                     cls=type(self.acct),
                     menu=self._menu)

    def on_click(self, e=None):
        try:
            dclick_timer = self.dclick_timer
        except AttributeError:
            dclick_timer = self.dclick_timer = wx.PyTimer(lambda: None)

        if dclick_timer.IsRunning():
            self.on_double_click()
            dclick_timer.Stop()
        else:
            dclick_timer.StartOneShot(GetDoubleClickTime())
            self.show_infobox()

        e.Skip()

    def on_double_click(self, e=None):
        if self.infobox.IsShown():
            self.infobox.Hide()

        url = self.acct.DefaultAction()

        if url is not None:
            wx.LaunchDefaultBrowser(url)

    def show_infobox(self):
        if not self.infobox: return

        info = self.infobox

        if info.IsShown() and getattr(info, 'account', None) is self.acct:
            info.Hide()
        else:
            pt = self.get_infobox_tray_position()
            info.ShowFromTray(pt, self.acct)
            #            info.Show()

            # tell the infobox to gain focus, so the mousewheel works
            wx.CallAfter(info.do_focus)

    def get_infobox_tray_position(self):
        #TODO: find taskbar position from the correct HWND. this code assumes the mouse
        # is on the same display as the tray, and that the tray is on the bottom of the
        # "client area" rectangle returned by wxDisplay
        try:
            import cgui
            r = cgui.GetTrayRect()
            pt = Point(r.Right - r.Width / 2, r.Bottom - r.Height / 2)

            display = Monitor.GetFromPoint(pt, find_near=True)
            rect = display.GetClientArea()
            distances = []

            for p in ('TopLeft', 'TopRight', 'BottomLeft', 'BottomRight'):
                corner = getattr(rect, p)
                distances.append((corner, corner.DistanceTo(pt), p))

            distances.sort(key=itemgetter(1))
            corner, distance, name = distances[0]
            return corner

        except Exception:
            print_exc()
            return Monitor.GetFromPointer().ClientArea.BottomRight

    def Destroy(self):
        self._destroyed = True

        if not config.platform == 'mac':
            self.unregister_observers(self.acct, self.on_account_updated)

        return super(AccountTrayIcon, self).Destroy()

    @property
    def count_string(self):
        acct = self.acct
        if acct.offline_reason != acct.Reasons.NONE:
            count = 'X'
        else:
            count = getattr(acct, 'count', 0)

        return count

    def on_account_updated(self, obj=None, attr=None, old=None, new=None):
        obj_or_event = obj
        if not self or getattr(self, '_destroyed', False):
            return

        acct = self.acct
        count = self.count_string

        if acct.enabled:
            # todo: remove this lame way figure out icon size
            icon = acct.icon.PIL.Resized(self._IconSize)

            if self.should_show_count() and count:
                # place text in the corner
                icon = draw_tiny_text(icon, str(count)).WX

            if pref('trayicons.email.gray_on_empty',
                    True) and count in (0, 'X') and should_grey(acct):
                icon = icon.WXB.Greyed

            self.SetIcon(icon, self.Tooltip)

    def should_show_count(self):
        return pref('trayicons.email.show_count', True)

    @property
    def Tooltip(self):
        return ''
Example #30
0
    f.Bind(wx.EVT_MENU, lambda e: msg('%s %s %s' % (e, e.EventType, e.Id)))

    f.Bind(wx.EVT_CLOSE, lambda e: app.ExitMainLoop())
    p = wx.Panel(f)
    f.CenterOnScreen()

    p.Sizer = wx.BoxSizer(wx.VERTICAL)

    bar = UMenuBar(p, p.Sizer)
    bmps = [
        wx.Bitmap('..\\..\\..\\res\\%s.png' % aa)
        for aa in ('online', 'away', 'offline')
    ]

    m = UMenu(f)
    m.AddItem('&Preferences\tCtrl+P',
              callback=lambda: msg('prefs'),
              bitmap=skin.get('serviceicons.aim'))
    accounts_item = m.AddItem('&Accounts\tCtrl+A',
                              callback=lambda: msg('show accounts!'))

    m.AddSep()

    sub = UMenu(f)
    g = sub.AddItem('one', callback=lambda: msg('one!'))
    sub.AddItem('two\tCtrl+T', bitmap=bmps[1])
    three = sub.AddItem('three', bitmap=bmps[2])

    sub4 = UMenu(f)
    sub4.AddItem('foo1')
Example #31
0
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