home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 October / maximum-cd-2011-10.iso / DiscContents / digsby_setup.exe / lib / gui / imwin / imhub.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2011-06-22  |  18.6 KB  |  601 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. import hooks
  6. import wx
  7. from wx import GetTopLevelWindows, GetTopLevelParent, WXK_CONTROL, GetKeyState, CallLater
  8. FindFocus = wx.Window.FindFocus
  9. import threading
  10. import gui.native.helpers as helpers
  11. from util import strip_html2, odict, traceguard
  12. from util.primitives.funcs import Delegate
  13. from util.primitives.fmtstr import fmtstr
  14. from util.lrucache import lru_cache
  15. from common.notifications import fire
  16. from common.sms import normalize_sms as smsize
  17. from common.sms import validate_sms
  18. from common import profile, pref
  19. from gui.imwin.imwin_gui import ImWinPanel
  20. from traceback import print_exc
  21. from logging import getLogger
  22. log = getLogger('imhub')
  23. LOG = log.debug
  24. from gui.uberwidgets.formattedinput import get_default_format
  25. strip_html2 = lru_cache(80)(strip_html2)
  26.  
  27. def is_system_message(messageobj):
  28.     if messageobj is not None and messageobj.buddy is None:
  29.         pass
  30.     return not getattr(messageobj, 'system_message_raises', False)
  31.  
  32.  
  33. def is_announcement(message):
  34.     buddy = getattr(message, 'buddy', None)
  35.     if buddy is not None and buddy.service == 'digsby':
  36.         pass
  37.     return buddy.name == 'digsby.org'
  38.  
  39.  
  40. def on_status(status, on_done = None):
  41.     for imwin in ImWinPanel.all():
  42.         if imwin.Buddy == status.buddy:
  43.             wx.CallAfter(imwin.show_status, status, on_done)
  44.             break
  45.             continue
  46.     
  47.  
  48.  
  49. def show_announce_window(message):
  50.     AnnounceWindow = AnnounceWindow
  51.     import gui.imwin.imwin_gui
  52.     announce = AnnounceWindow(wx.FindWindowByName('Buddy List'))
  53.     announce.message(message)
  54.     wx.CallAfter(announce.Show)
  55.  
  56.  
  57. def show_announce_window_After(message):
  58.     wx.CallAfter(show_announce_window, message)
  59.  
  60. hooks.register('digsby.server.announcement', show_announce_window_After)
  61.  
  62. def pre_message_hook(message):
  63.     if is_announcement(message):
  64.         if profile.account_manager.all_accounts:
  65.             show_announce_window(message)
  66.         
  67.         return False
  68.  
  69. im_show = Delegate()
  70.  
  71. def frame_show(frame, show, no_activate = False):
  72.     if show and getattr(frame, '_starting_minimized', False):
  73.         frame.Iconize(True)
  74.         frame.Show(True)
  75.         frame._starting_minimized = False
  76.     elif no_activate:
  77.         frame.ShowNoActivate(show)
  78.     else:
  79.         frame.Show(show)
  80.  
  81.  
  82. def on_message(messageobj = None, convo = None, raisenow = False, meta = None, mode = 'im', firenots = True):
  83.     global im_show, im_show, im_show, im_show, im_show, im_show, im_show
  84.     thread_check()
  85.     ImFrame = ImFrame
  86.     import gui.imwin.imtabs
  87.     convo = None if messageobj is not None else convo
  88.     sms = None if messageobj is not None else False
  89.     if not sms:
  90.         pass
  91.     sms = getattr(convo.buddy, 'sms', False)
  92.     if pre_message_hook(messageobj) is False:
  93.         return None
  94.     system_message = is_system_message(messageobj)
  95.     print 'is_system_message', system_message, messageobj
  96.     if not raisenow:
  97.         (should_hide, isnew) = hide_message(messageobj, meta, sms, system_message)
  98.         if should_hide:
  99.             if firenots:
  100.                 fire_notifications(messageobj, None, isnew, mode, hidden = True)
  101.             
  102.             return None
  103.     
  104.     (win, isnew) = None(window_for, convo = 'meta', meta = 'sms', sms = 'system_message', system_message = 'focus' if raisenow else None, mode = mode)
  105.     if win is None:
  106.         return None
  107.     if firenots:
  108.         fire_notifications(messageobj, win, isnew, mode)
  109.     
  110.     flashnow = True
  111.     frame = GetTopLevelParent(win)
  112.     focusedImFrame = isinstance(focused_top(), ImFrame)
  113.     if isnew:
  114.         if raisenow and not focusedImFrame:
  115.             (im_show,) += (lambda : log.info('calling frame.Show on frame at %r', frame.Rect))
  116.             (im_show,) += (lambda : (wx.CallAfter,)((lambda : frame_show(frame, True)))
  117. )
  118.         elif not frame.IsShown():
  119.             (im_show,) += (lambda : log.info('calling frame.ShowNoActivate on frame at %r', frame.Rect))
  120.             (im_show,) += (lambda : (wx.CallAfter,)((lambda : frame_show(frame, True, no_activate = True)))
  121. )
  122.         
  123.     
  124.     if not focusedImFrame:
  125.         if (raisenow or isnew) and 'stealfocus' == new_action():
  126.             (im_show,) += (lambda : log.info('raising existing IM frame at %r', frame.Rect))
  127.             (None, im_show) += (lambda : raise_imwin(frame, win))
  128.         elif flashnow and messageobj is not None and not win.IsActive():
  129.             bud = messageobj.buddy
  130.             if bud is not None and bud is not messageobj.conversation.self_buddy:
  131.                 (im_show,) += (lambda : wx.CallAfter(win.Notify))
  132.             
  133.         
  134.     if not pref('fullscreen.hide_convos', True) and helpers.FullscreenApp():
  135.         im_show.call_and_clear()
  136.     else:
  137.         log.info('im_hub.on_message ignoring for now because of fullscreen (delegate is %d messages long)', len(im_show))
  138.         helpers.FullscreenAppLog()
  139.     win.message(messageobj, convo, mode, meta)
  140.     return win
  141.  
  142.  
  143. def focused_top():
  144.     focused = FindFocus()
  145.     if focused is not None:
  146.         return focused.Top
  147.  
  148.  
  149. def raise_imwin(frame, imwin):
  150.     log.info('raise_imwin: %r %r', frame, imwin)
  151.     if frame.IsIconized():
  152.         frame.Iconize(False)
  153.         event = wx.IconizeEvent(frame.Id, False)
  154.         frame.AddPendingEvent(event)
  155.     
  156.     frame.ReallyRaise()
  157.     tab = imwin.Tab
  158.     if tab is not None:
  159.         tab.SetActive(True)
  160.     
  161.  
  162.  
  163. def open(idstr):
  164.     contact = profile.blist.contact_for_idstr(idstr)
  165.     if contact is not None:
  166.         return begin_conversation(contact)
  167.  
  168.  
  169. def begin_conversation(contact, mode = 'im', forceproto = False):
  170.     thread_check()
  171.     MetaContact = MetaContact
  172.     OfflineBuddy = OfflineBuddy
  173.     import contacts.metacontacts
  174.     if isinstance(contact, OfflineBuddy):
  175.         log.info('cannot open an IM window for OfflineBuddy %r', contact)
  176.         return None
  177.     meta = isinstance(contact, OfflineBuddy) if isinstance(contact, MetaContact) else None
  178.     if forceproto:
  179.         proto = contact.protocol
  180.     else:
  181.         (contact, proto) = profile.blist.get_from(contact)
  182.     if proto is None:
  183.         log.info('cannot open an IM window for %r, no compatible protocols?', contact)
  184.         return None
  185.     convo = proto.convo_for(contact)
  186.     if contact.sms and not profile.blist.on_buddylist(contact):
  187.         mode = 'sms'
  188.     
  189.     pop_any_hidden(contact)
  190.     return on_message(convo = convo, raisenow = True, meta = meta, mode = mode)
  191.  
  192.  
  193. def window_for(convo, meta = None, sms = False, system_message = False, focus = None, mode = 'im'):
  194.     (win, meta) = find_window_for(convo, meta, sms, system_message)
  195.     if win is not None:
  196.         return (win, False)
  197.     if sms and not profile.blist.on_buddylist(convo.buddy):
  198.         convo = window_for_sms(convo)
  199.     
  200.     if system_message:
  201.         return (None, None)
  202.     win = create_imwin(convo, meta, sms, focus, mode)
  203.     return (win, True)
  204.  
  205.  
  206. def find_window_for(convo, meta = None, sms = False, system_message = False):
  207.     thread_check()
  208.     if meta is None:
  209.         metas = None if not convo.ischat else []
  210.         if metas:
  211.             meta = list(metas)[0]
  212.         
  213.     else:
  214.         metas = [
  215.             meta]
  216.     return (search_for_buddy(metas, convo, sms), meta)
  217.  
  218.  
  219. def search_for_buddy(metas, convo, sms):
  220.     for win in ImWinPanel.all():
  221.         traceguard.__enter__()
  222.         
  223.         try:
  224.             c = win.Conversation
  225.             if c is convo:
  226.                 LOG('direct conversation object match: win: %r, convo: %r', win, convo)
  227.                 return win
  228.             if convo.ischat != win.convo.ischat:
  229.                 continue
  230.             
  231.             winbud = win.Buddy
  232.             if winbud is None:
  233.                 continue
  234.             
  235.             for meta in metas:
  236.                 for contact in meta:
  237.                     if winbud == contact:
  238.                         LOG('matched %r with %r', winbud, contact)
  239.                         return win
  240.                 
  241.                 for contact in meta:
  242.                     if winbud.name == contact.name and winbud.protocol.name == contact.protocol.name:
  243.                         LOG('loosely matched %r with %r', winbud, contact)
  244.                         return win
  245.                 
  246.             
  247.             if winbud.info_key == convo.buddy.info_key:
  248.                 return win
  249.         finally:
  250.             pass
  251.  
  252.     
  253.  
  254.  
  255. def window_for_sms(convo):
  256.     log.info('window_for_sms: %r', convo)
  257.     thread_check()
  258.     buddy_sms = smsize(convo.buddy.name)
  259.     keys = []
  260.     for infokey, infodict in profile.blist.info.iteritems():
  261.         
  262.         try:
  263.             sms_numbers = infodict['sms']
  264.         except KeyError:
  265.             continue
  266.  
  267.         for s in list(sms_numbers):
  268.             
  269.             try:
  270.                 sms = smsize(s)
  271.             except ValueError:
  272.                 log.critical("invalid SMS number in infodict[%r]['sms']: %r", infokey, s)
  273.                 sms_numbers.remove(s)
  274.                 continue
  275.  
  276.             if buddy_sms == sms:
  277.                 keys += [
  278.                     infokey]
  279.                 continue
  280.         
  281.     
  282.     if not keys:
  283.         log.info('no matching sms numbers found')
  284.         return convo
  285.     conn = convo.protocol
  286.     for key in keys:
  287.         if key.startswith('Metacontact #'):
  288.             continue
  289.         
  290.         (buddyname, proto) = info_key_tuple(key)
  291.         if conn.protocol == proto and conn.has_buddy(buddyname):
  292.             return conn.convo_for(conn.get_buddy(buddyname))
  293.     
  294.     return convo
  295.  
  296.  
  297. def new_action():
  298.     return pref('conversation_window.new_action')
  299.  
  300.  
  301. def create_imwin(convo, meta, sms, focus = None, mode = 'im'):
  302.     global im_show, im_show
  303.     thread_check()
  304.     ImFrame = ImFrame
  305.     import gui.imwin.imtabs
  306.     f = None
  307.     hooks.notify('imwin.created')
  308.     focus = None if focus is None else focus
  309.     if pref('messaging.tabs.ctrl_new_window', True):
  310.         pass
  311.     ctrlDown = GetKeyState(WXK_CONTROL)
  312.     if not ctrlDown and pref('messaging.tabs.enabled', True):
  313.         for win in GetTopLevelWindows():
  314.             if isinstance(win, ImFrame):
  315.                 f = win
  316.                 if f.IsActive():
  317.                     focus = False
  318.                 
  319.                 break
  320.                 continue
  321.         
  322.     
  323.     if isinstance(focused_top(), ImFrame):
  324.         focus = False
  325.     
  326.     if getattr(wx.Window.FindFocus(), 'click_raises_imwin', False) and wx.LeftDown():
  327.         focus = True
  328.     
  329.     if f is None:
  330.         if pref('messaging.tabs.enabled', True):
  331.             id = ''
  332.         elif meta is not None:
  333.             pass
  334.         
  335.         id = convo.buddy.idstr()
  336.         f = ImFrame(startMinimized = not focus, posId = id)
  337.     
  338.     w = ImWinPanel(f)
  339.     if convo is not None:
  340.         w.set_conversation(convo, meta)
  341.     
  342.     if focus:
  343.         (None, im_show) += (lambda : raise_imwin(f, w))
  344.         (im_show,) += (lambda : w.FocusTextCtrl())
  345.     
  346.     tab = f.AddTab(w, focus = focus)
  347.     if hasattr(tab, 'OnActive'):
  348.         tab.OnActive += w.FocusTextCtrl
  349.     
  350.     hooks.notify('digsby.statistics.imwin.imwin_created')
  351.     return w
  352.  
  353.  
  354. def fire_notifications(msg, win, isnew, mode, hidden = False):
  355.     if msg is None or msg.buddy is None:
  356.         return []
  357.     convo = msg.conversation
  358.     bud = msg.buddy
  359.     
  360.     def stop_notify(win = (None, msg.buddy is None, win)):
  361.         if win:
  362.             
  363.             try:
  364.                 win.Unnotify()
  365.             except wx.PyDeadObjectError:
  366.                 pass
  367.  
  368.             if not (win.Top.AnyNotified) and pref('conversation_window.notify_flash'):
  369.                 win.Top.StopFlashing()
  370.             
  371.         
  372.         if hidden and pref('messaging.popups.close_dismisses_hidden', False):
  373.             _remove_hidden_message(bud, msg)
  374.         
  375.  
  376.     if msg.get('content_type', 'text/html') in ('text/html', 'text/xhtml'):
  377.         
  378.         try:
  379.             popup_message = strip_html2(msg.message).decode('xml')
  380.         except Exception:
  381.             print_exc()
  382.             popup_message = msg.message
  383.         except:
  384.             None<EXCEPTION MATCH>Exception
  385.         
  386.  
  387.     None<EXCEPTION MATCH>Exception
  388.     popup_message = msg.message
  389.     fire_opts = dict(buddy = bud, onuserclose = stop_notify)
  390.     if convo is not None:
  391.         pass
  392.     ischat = convo.ischat
  393.     if ischat:
  394.         skin = skin
  395.         import gui
  396.         fire_opts.update(header = _('Group Chat (%d)') % convo.chat_member_count, msg = _('%s: %s') % (bud.alias, popup_message), icon = skin.get('ActionsBar.Icons.RoomList', None), popupid = 'chat!!!%r!!!%r' % (convo.protocol.name, convo.chat_room_name))
  397.     elif bud is not None:
  398.         pass
  399.     
  400.     fire_opts.update(msg = popup_message, icon = convo.icon, popupid = msg.buddy.idstr())
  401.     if bud is not None:
  402.         
  403.         def click_popup(text):
  404.             if pop_any_hidden(bud):
  405.                 return None
  406.             if convo.ischat:
  407.                 on_message(convo = convo, raisenow = True)
  408.             else:
  409.                 begin_conversation(bud)
  410.             if win:
  411.                 
  412.                 try:
  413.                     val = win.input_area.Value
  414.                 except wx.PyDeadObjectError:
  415.                     pass
  416.  
  417.                 if not val:
  418.                     win.input_area.Value = text
  419.                     wx.CallAfter(win.TextCtrl.SetInsertionPointEnd)
  420.                 
  421.             
  422.  
  423.         fire_opts.update(onclick = click_popup)
  424.     
  425.     notification = _get_notification_types(bud, convo, win, hidden, isnew)
  426.     
  427.     def send_from_popup(text, options, convo = convo, win = win, opts = (fire_opts.copy(),)):
  428.         if not text:
  429.             return None
  430.         CallLater(200, stop_notify)
  431.         convo.send_message(fmtstr.singleformat(text, format = _get_format(win)))
  432.         if not wx.GetKeyState(wx.WXK_CONTROL):
  433.             return '> ' + text
  434.  
  435.     fire_opts['input'] = send_from_popup
  436.     return fire(notification, **fire_opts)
  437.  
  438.  
  439. def _get_notification_types(bud, convo, win, hidden, isnew):
  440.     if bud is convo.self_buddy:
  441.         notification = 'message.sent'
  442.     elif hidden:
  443.         notification = [
  444.             'message.received.hidden']
  445.         if isnew:
  446.             notification.append('message.received.initial')
  447.         
  448.     elif isnew:
  449.         notification = 'message.received.initial'
  450.     elif not win and not win.IsActive() and not wx.GetApp().IsActive() or win.Mode not in ('im', 'sms'):
  451.         notification = 'message.received.background'
  452.     else:
  453.         notification = 'message.received'
  454.     return notification
  455.  
  456.  
  457. def _get_format(win):
  458.     format = None
  459.     if win:
  460.         
  461.         try:
  462.             format = win.input_area.Format
  463.         except wx.PyDeadObjectError:
  464.             pass
  465.         except Exception:
  466.             print_exc()
  467.         except:
  468.             None<EXCEPTION MATCH>wx.PyDeadObjectError
  469.         
  470.  
  471.     None<EXCEPTION MATCH>wx.PyDeadObjectError
  472.     if format is None:
  473.         format = get_default_format()
  474.     
  475.     return format
  476.  
  477.  
  478. def show_info(buddy):
  479.     begin_conversation(buddy, mode = 'info')
  480.  
  481.  
  482. def thread_check():
  483.     if threading.currentThread().getName() != 'MainThread':
  484.         raise Exception('imhub methods must be called on the main GUI thread')
  485.     threading.currentThread().getName() != 'MainThread'
  486.  
  487.  
  488. def info_key_tuple(info_key):
  489.     i = info_key.find('_')
  490.     if i == -1:
  491.         pass
  492.     
  493.     return (info_key[:i], info_key[i + 1:])
  494.  
  495. hidden_windows = odict()
  496.  
  497. def hidden_count():
  498.     return len(hidden_windows)
  499.  
  500.  
  501. def hidden_convo_contacts():
  502.     return hidden_windows.keys()
  503.  
  504.  
  505. def hide_message(messageobj, meta, sms, system_message):
  506.     if messageobj is None:
  507.         return (False, False)
  508.     convo = messageobj.conversation
  509.     if new_action() != 'hide':
  510.         return (False, False)
  511.     (win, meta) = find_window_for(convo, meta, sms, system_message)
  512.     if win is not None:
  513.         return (False, False)
  514.     if not meta:
  515.         pass
  516.     ident = convo.buddy.info_key
  517.     _notify_hidden()
  518.     return (True, isnew)
  519.  
  520.  
  521. def pop_all_hidden():
  522.     for contact in list(hidden_windows.keys()):
  523.         pop_any_hidden(contact)
  524.     
  525.  
  526.  
  527. def pop_any_hidden(contact, notify = True):
  528.     quiet_log_messages = quiet_log_messages
  529.     import gui.imwin.messagearea
  530.     all_messages = get_any_hidden(contact)
  531.     if not all_messages:
  532.         return None
  533.     quiet_log_messages(all_messages).__enter__()
  534.     
  535.     try:
  536.         for messageobj in all_messages:
  537.             traceguard.__enter__()
  538.             
  539.             try:
  540.                 on_message(messageobj, raisenow = True, firenots = False)
  541.             finally:
  542.                 pass
  543.  
  544.     finally:
  545.         pass
  546.  
  547.  
  548.  
  549. def get_any_hidden(contact, pop = True):
  550.     keys = hidden_windows.keys()
  551.     if not keys:
  552.         return []
  553.     contacts = set()
  554.     if not isinstance(contact, basestring):
  555.         contacts.update((lambda .0: for m in .0:
  556. m.info_key)(profile.metacontacts.forbuddy(contact)))
  557.     
  558.     contact = getattr(contact, 'info_key', contact)
  559.     contacts.add(contact)
  560.     all_messages = []
  561.     for message_list in hidden_windows.values():
  562.         all_messages.extend(message_list)
  563.     
  564.     messages = []
  565.     for c in keys:
  566.         if c in contacts:
  567.             if pop:
  568.                 msgs = hidden_windows.pop(c, [])
  569.             else:
  570.                 msgs = hidden_windows.get(c, [])
  571.             messages.extend(msgs)
  572.             continue
  573.     
  574.     return messages
  575.  
  576.  
  577. def _remove_hidden_message(contact, message):
  578.     contact = getattr(contact, 'info_key', contact)
  579.     
  580.     try:
  581.         messages = hidden_windows[contact]
  582.     except KeyError:
  583.         return False
  584.  
  585.     
  586.     try:
  587.         messages.remove(message)
  588.     except ValueError:
  589.         return False
  590.  
  591.     if len(messages) == 0:
  592.         hidden_windows.pop(contact)
  593.         _notify_hidden()
  594.     
  595.     return True
  596.  
  597.  
  598. def _notify_hidden():
  599.     hooks.notify('digsby.im.message_hidden', hidden_windows)
  600.  
  601.