home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 February / maximum-cd-2011-02.iso / DiscContents / digsby_setup85.exe / lib / gui / imwin / imwin_ctrl.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-11-24  |  21.6 KB  |  588 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. import sys
  6. import wx
  7. from wx import EVT_BUTTON, MessageBox, PyTimer
  8. from operator import attrgetter
  9. from traceback import print_exc
  10. from logging import getLogger
  11. log = getLogger('imwinctrl')
  12. info = log.info
  13. info_s = getattr(log, 'info_s', log.info)
  14. from util import traceguard
  15. from util.primitives.funcs import Delegate
  16. from common import profile, prefprop, pref
  17. from common.message import Message
  18. from gui.infobox.htmlgeneration import GetInfo
  19. from imwin_tofrom import IMControl, EmailControl, SMSControl
  20. from gui.toolbox import check_destroyed, calllimit
  21. from common.sms import SMS_MAX_LENGTH
  22.  
  23. class ImWinCtrl(object):
  24.     
  25.     def __init__(self):
  26.         self.IMControl = IMControl(self, self.capsbar, self.To, self.From)
  27.         self.IMControl.OnSelection += self.FocusTextCtrl
  28.         (self.IMControl.OnSwitchContact,) += (lambda c: self.set_conversation(c.protocol.convo_for(c)))
  29.         self.EmailControl = EmailControl(self.To, self.From)
  30.         (self.EmailControl.OnLoseFocus,) += (lambda : self._emailpanel.subject_input.SetFocus())
  31.         self.SMSControl = SMSControl(self.To, self.From)
  32.         self.SMSControl.OnLoseFocus += self.FocusTextCtrl
  33.         self.controllers = {
  34.             'im': self.IMControl,
  35.             'email': self.EmailControl,
  36.             'sms': self.SMSControl }
  37.         self.mode = None
  38.         self.convo = None
  39.         self.typing = None
  40.         self.typing_status = None
  41.         self.typing_timer = None
  42.         self.clear_typing_timer = wx.PyTimer(self.on_clear_typing_timer)
  43.         self.GetButton('im').Bind((EVT_BUTTON,), (lambda e: self.set_mode('im', toggle_tofrom = True)))
  44.         for mode in ('email', 'sms', 'info'):
  45.             self.GetButton(mode).Bind(EVT_BUTTON, (lambda e, mode = (mode,): self.set_mode(mode)))
  46.         
  47.         self.GetButton('video').Bind((EVT_BUTTON,), (lambda e: self.on_video()))
  48.         multichat = self.GetButton('multichat')
  49.  
  50.     send_typing = prefprop('privacy.send_typing_notifications', True)
  51.     typed_delay = prefprop('messaging.typed_delay', 5)
  52.     
  53.     def message(self, messageobj, convo = None, mode = 'im', meta = None):
  54.         info('%r', self)
  55.         info_s('  messageobj: %r', messageobj)
  56.         info('       convo: %r', convo)
  57.         info('        mode: %r', mode)
  58.         info('        meta: %r', meta)
  59.         if messageobj is None:
  60.             self.set_conversation(convo)
  61.             self.set_mode(mode)
  62.             self.IMControl.SetConvo(convo)
  63.             if convo.ischat:
  64.                 self.show_roomlist(True)
  65.             
  66.         elif (messageobj.get('sms', False) or convo.buddy.sms) and not profile.blist.on_buddylist(convo.buddy):
  67.             if self.convo is None:
  68.                 self.set_conversation(convo)
  69.             
  70.             if self.mode != 'sms':
  71.                 self.set_mode('sms')
  72.             
  73.             self.show_message(messageobj)
  74.         else:
  75.             convo = messageobj.conversation
  76.             if self.mode is None:
  77.                 self.set_mode(mode)
  78.             
  79.             self.show_message(messageobj)
  80.             self.set_conversation(convo)
  81.  
  82.     
  83.     def set_mode(self, mode, toggle_tofrom = False):
  84.         self.Frozen().__enter__()
  85.         
  86.         try:
  87.             oldmode = getattr(self, 'mode', None)
  88.             self.on_mode_change(oldmode, mode, toggle_tofrom)
  89.             self.show_controls(mode)
  90.             self.on_mode_changed(mode)
  91.         finally:
  92.             pass
  93.  
  94.  
  95.     Mode = property(attrgetter('mode'), set_mode)
  96.     
  97.     def on_mode_change(self, oldmode, mode, toggle_tofrom = False):
  98.         if oldmode != mode and mode in ('email', 'sms'):
  99.             self.ShowToFrom(True)
  100.         elif mode == 'info':
  101.             self.ShowToFrom(False)
  102.         
  103.         if mode == 'sms' and oldmode != 'sms':
  104.             (wx.CallAfter,)((lambda : self.input_area.tc.SetMaxLength(SMS_MAX_LENGTH)))
  105.         elif oldmode == 'sms' and mode != 'sms':
  106.             (wx.CallAfter,)((lambda : self.input_area.tc.SetMaxLength(0)))
  107.         
  108.         for m in ('im', 'email', 'sms'):
  109.             if mode == m and oldmode != m:
  110.                 wx.CallAfter(self.controllers[mode].Apply)
  111.                 break
  112.                 continue
  113.         
  114.         if mode == 'im':
  115.             if self.convo.ischat:
  116.                 self.ShowToFrom(False)
  117.             elif oldmode != 'im':
  118.                 self.ShowToFrom(self.IMControl.HasChoices)
  119.             elif toggle_tofrom:
  120.                 self.ShowToFrom(not (self.capsbar.ToFromShown))
  121.             
  122.         
  123.         if oldmode is not None:
  124.             self.GetButton(oldmode).Active(False)
  125.         
  126.         self.GetButton(mode).Active(True)
  127.  
  128.     
  129.     def on_mode_changed(self, mode):
  130.         if mode in ('im', 'sms'):
  131.             self.on_message_area_shown()
  132.             if self.IsActive():
  133.                 if sys.platform.startswith('darwin'):
  134.                     wx.CallAfter(self.FocusTextCtrl)
  135.                 else:
  136.                     self.FocusTextCtrl()
  137.             
  138.         elif mode == 'info':
  139.             self.set_profile_html(self.Buddy)
  140.             self.profile_html.SetFocus()
  141.         elif mode == 'email':
  142.             self._emailpanel.subject_input.SetFocus()
  143.         
  144.  
  145.     
  146.     def on_send_message(self):
  147.         if getattr(self, 'on_send_message_' + self.mode, (lambda a: pass))():
  148.             self.Top.on_sent_message(self.mode, self)
  149.         
  150.  
  151.     
  152.     def on_send_message_im(self):
  153.         val = self.input_area.GetFormattedValue()
  154.         if not val.format_as('plaintext'):
  155.             return None
  156.         self.history.commit(val.format_as('plaintext'))
  157.         if self.set_conversation_from_combos():
  158.             self.convo.send_message(val)
  159.             self.ClearAndFocus()
  160.             return True
  161.  
  162.     
  163.     def on_send_email(self, *a):
  164.         to = self.EmailControl.ToEmail
  165.         frm = self.EmailControl.FromAccount
  166.         if to is None:
  167.             return wx.MessageBox(_('Please add an email address for this buddy by clicking the "To:" box.'), _('Compose email to %s') % self.Buddy.name)
  168.         epanel = self._emailpanel
  169.         
  170.         def success(*a):
  171.             log.info('Email send success')
  172.             profile.blist.add_tofrom('email', to, frm)
  173.             epanel.Clear()
  174.             epanel.SetStatusMessage(_('Message Sent'))
  175.             epanel.send_button.Enable(True)
  176.             epanel.openin.Enable(True)
  177.             import hooks
  178.             hooks.notify('digsby.statistics.email.sent_from_imwindow')
  179.  
  180.         
  181.         def error(*a):
  182.             log.info('Email send error')
  183.             epanel.SetStatusMessage(_('Failed to Send Email'))
  184.             epanel.send_button.Enable(True)
  185.             epanel.openin.Enable(True)
  186.  
  187.         epanel.SetStatusMessage(_('Sending...'))
  188.         epanel.send_button.Enable(False)
  189.         epanel.openin.Enable(False)
  190.         subject = self._get_email_subject()
  191.         body = self._get_email_body()
  192.         frm.OnClickSend(to = to, subject = subject, body = body, success = success, error = error)
  193.  
  194.     
  195.     def _get_email_subject(self):
  196.         return self._emailpanel.subject_input.Value
  197.  
  198.     
  199.     def _get_email_body(self):
  200.         body = self._emailpanel.email_input_area.Value
  201.         if pref('email.signature.enabled', type = bool, default = False):
  202.             footer = u'\r\n' + pref('email.signature.value', type = unicode, default = u'\r\n_______________________________________________________________\r\nSent using Digsby - http://email.digsby.com')
  203.         else:
  204.             footer = ''
  205.         return body + footer
  206.  
  207.     
  208.     def on_send_message_sms(self):
  209.         if not self.input_area.Value:
  210.             return None
  211.         to = self.SMSControl.ToSMS
  212.         frm = self.SMSControl.FromAccount
  213.         if to is None:
  214.             MessageBox(_('Please add an SMS number first.'), _('Send SMS Message'))
  215.         elif frm is None:
  216.             MessageBox(_('You are not signed in to any accounts which can send SMS messages.'), _('Send SMS Message'))
  217.         else:
  218.             message = self.input_area.Value
  219.             
  220.             def on_success():
  221.                 self.show_message(Message(buddy = frm.self_buddy, message = message[:SMS_MAX_LENGTH], conversation = self.convo, type = 'outgoing'))
  222.                 self.ClearAndFocus()
  223.  
  224.             
  225.             def on_error(errstr = None):
  226.                 if errstr is not None:
  227.                     more = _('\nThe error message received was:\n\t%s') % errstr
  228.                 else:
  229.                     more = ''
  230.                 MessageBox(_('There was an error in sending your SMS message.') + more, _('Send SMS Message Error'), style = wx.ICON_ERROR)
  231.  
  232.             import hooks
  233.             hooks.notify('digsby.statistics.sms.sent')
  234.             frm.send_sms(to, message[:SMS_MAX_LENGTH], success = on_success, error = on_error)
  235.  
  236.     
  237.     def on_edit_email(self):
  238.         to = self.EmailControl.ToEmail
  239.         frm = self.EmailControl.FromAccount
  240.         if to is not None and frm is not None:
  241.             frm.OnComposeEmail(to = to, subject = self._emailpanel.subject_input.Value, body = self._emailpanel.email_input_area.Value)
  242.         
  243.  
  244.     
  245.     def set_conversation_from_combos(self):
  246.         if self.ischat:
  247.             return self.convo.protocol.connected
  248.         to = self.IMControl.Buddy
  249.         frm = self.IMControl.Account
  250.         if frm is None:
  251.             return False
  252.         convo = self.convo
  253.         return True
  254.  
  255.     
  256.     def on_close(self):
  257.         if getattr(self, '_closed', False):
  258.             log.warning('FIXME: imwin_ctrl.on_close was called more than once!!!')
  259.             return None
  260.         self._closed = True
  261.         del self.capsbar.buddy_callback
  262.         del self.capsbar
  263.         import hooks
  264.         hooks.notify('digsby.overlay_icon_updated', self)
  265.         plugin_hub = plugin_hub
  266.         import plugin_manager
  267.         plugin_hub.act('digsby.im.conversation.close.async', self.convo)
  268.         self.unlink_observers()
  269.         if self.convo is not None:
  270.             self.unwatch_conversation(self.convo)
  271.             
  272.             try:
  273.                 self.convo.explicit_exit()
  274.             except Exception:
  275.                 getattr(self, '_closed', False)
  276.                 getattr(self, '_closed', False)
  277.                 print_exc()
  278.             except:
  279.                 getattr(self, '_closed', False)<EXCEPTION MATCH>Exception
  280.             
  281.  
  282.         getattr(self, '_closed', False)
  283.  
  284.     
  285.     def Conversation(self):
  286.         return self.convo
  287.  
  288.     Conversation = property(Conversation)
  289.     
  290.     def Buddy(self):
  291.         return self.IMControl.Buddy
  292.  
  293.     Buddy = property(Buddy)
  294.     
  295.     def SMS(self):
  296.         return self.SMSControl.get_contact_sms()
  297.  
  298.     SMS = property(SMS)
  299.     
  300.     def set_conversation(self, convo, meta = None):
  301.         if convo is self.convo:
  302.             return None
  303.         shouldShowToFrom = False
  304.         if self.convo is not None:
  305.             self.unwatch_conversation(self.convo)
  306.             self.convo.exit()
  307.             if not self.convo.ischat:
  308.                 shouldShowToFrom = True
  309.             
  310.         
  311.         self.convo = convo
  312.         self.watch_conversation(convo)
  313.         if self.is_roomlist_constructed():
  314.             self.roomlist.SetConversation(convo)
  315.         
  316.         contact = None if meta is not None else convo.buddy
  317.         self.capsbar.ApplyCaps(convo = convo)
  318.         self.IMControl.SetConvo(convo, meta)
  319.         if shouldShowToFrom and not (self.convo.ischat):
  320.             self.ShowToFrom(shouldShowToFrom)
  321.         
  322.         self.EmailControl.SetContact(contact)
  323.         self.SMSControl.SetContact(contact)
  324.         self.update_icon()
  325.         self.update_title()
  326.         self.choose_message_formatting()
  327.         self.convo.play_queued_messages()
  328.         if convo.ischat:
  329.             
  330.             def after():
  331.                 self.show_roomlist(True)
  332.  
  333.             after = (wx.CallAfter,)(after)
  334.         
  335.  
  336.     
  337.     def _update_caps_and_title(self, *a):
  338.         
  339.         def after():
  340.             self.capsbar.ApplyCaps(convo = self.convo)
  341.             self.update_title()
  342.             if self.convo.ischat and not getattr(self, 'roomlist_has_been_shown', False):
  343.                 log.info('showing roomlist...')
  344.                 self.toggle_roomlist()
  345.             
  346.  
  347.         after = (wx.CallAfter,)(after)
  348.  
  349.     
  350.     def watch_conversation(self, convo):
  351.         plugin_hub = plugin_hub
  352.         import plugin_manager
  353.         plugin_hub.act('digsby.im.conversation.open.async', convo)
  354.         convo.typing_status.add_observer(self.typing_status_changed)
  355.         convo.add_observer(self._update_caps_and_title, 'ischat')
  356.         buddy = convo.buddy
  357.         buddy.add_observer(self.buddy_status_changed, 'status')
  358.         buddy.add_observer(self.buddy_info_changed)
  359.         if convo.ischat:
  360.             convo.room_list.add_observer(self.chat_buddies_changed)
  361.             convo.conversation_reconnected.add_unique(self.on_conversation_reconnected)
  362.         
  363.         convo.protocol.add_observer(self._on_convo_proto_state_change, 'state')
  364.  
  365.     
  366.     def on_conversation_reconnected(self, convo):
  367.         
  368.         def gui():
  369.             log.warning('on_conversation_reconnected: %r', convo)
  370.             self.set_conversation(convo)
  371.             convo.system_message(_('Reconnected'))
  372.  
  373.         gui = (None, wx.CallAfter)(gui)
  374.  
  375.     
  376.     def chat_buddies_changed(self, *a):
  377.         wx.CallAfter(self.update_title)
  378.  
  379.     
  380.     def unwatch_conversation(self, convo = None):
  381.         if convo is None:
  382.             convo = self.convo
  383.         
  384.         if convo is not None:
  385.             buddy = convo.buddy
  386.             convo.remove_observer(self._update_caps_and_title, 'ischat')
  387.             convo.typing_status.remove_observer(self.typing_status_changed)
  388.             if buddy is not None:
  389.                 buddy.remove_observer(self.buddy_status_changed, 'status')
  390.                 buddy.remove_observer(self.buddy_info_changed)
  391.             
  392.             convo.room_list.remove_observer(self.chat_buddies_changed)
  393.             convo.conversation_reconnected.remove_maybe(self.on_conversation_reconnected)
  394.             convo.protocol.remove_observer(self._on_convo_proto_state_change, 'state')
  395.         
  396.  
  397.     
  398.     def _on_convo_proto_state_change(self, proto, attr, old, new):
  399.         
  400.         def after():
  401.             if self.convo.ischat and new == proto.Statuses.OFFLINE:
  402.                 self.update_title()
  403.             
  404.  
  405.         after = (None, None, wx.CallAfter)(after)
  406.  
  407.     
  408.     def show_status(self, update, ondone = None):
  409.         
  410.         cb = lambda u = (None, update): self.show_message(u, ondone)
  411.         
  412.         try:
  413.             timer = self._statustimer
  414.         except AttributeError:
  415.             timer = self._statustimer = wx.PyTimer(cb)
  416.  
  417.         timer.SetCallback(cb)
  418.         if not self._statustimer.IsRunning():
  419.             self._statustimer.Start(250, True)
  420.         
  421.  
  422.     
  423.     def buddy_info_changed(self, *a):
  424.         if self.mode == 'info':
  425.             self.set_profile_html(self.Buddy)
  426.         
  427.  
  428.     buddy_info_changed = calllimit(1)(buddy_info_changed)
  429.     
  430.     def buddy_status_changed(self, *a):
  431.         wx.CallAfter(self._buddy_status_changed)
  432.  
  433.     
  434.     def _buddy_status_changed(self):
  435.         if check_destroyed(self):
  436.             return None
  437.         if self.convo.ischat:
  438.             return None
  439.         self.capsbar.ApplyCaps(self.Buddy)
  440.  
  441.     
  442.     def typing_status_changed(self, *a):
  443.         typing = self.convo.typing_status.get(self.convo.buddy, None)
  444.         typing_clear_time_secs = pref('messaging.typing_notifications.clear_after', default = 30, type = int)
  445.         if typing_clear_time_secs > 0:
  446.             if typing is not None:
  447.                 self.clear_typing_timer.StartOneShot(1000 * typing_clear_time_secs)
  448.             else:
  449.                 self.clear_typing_timer.Stop()
  450.         
  451.         self.on_typing(typing)
  452.  
  453.     
  454.     def on_typing(self, typing):
  455.         self.typing = typing
  456.         self.update_title()
  457.         self.update_icon()
  458.  
  459.     
  460.     def on_clear_typing_timer(self):
  461.         if not wx.IsDestroyed(self):
  462.             self.on_typing(None)
  463.         
  464.  
  465.     
  466.     def choose_message_formatting(self):
  467.         plain = False
  468.         conv = self.convo
  469.         
  470.         try:
  471.             plain = conv.message_formatting == 'plaintext'
  472.         except AttributeError:
  473.             
  474.             try:
  475.                 plain = conv.protocol.message_formatting == 'plaintext'
  476.             except AttributeError:
  477.                 pass
  478.             except:
  479.                 None<EXCEPTION MATCH>AttributeError
  480.             
  481.  
  482.             None<EXCEPTION MATCH>AttributeError
  483.  
  484.         self.plainttext = plain
  485.  
  486.     
  487.     def show_message(self, messageobj, ondone = None):
  488.         c = messageobj.conversation
  489.         b = messageobj.buddy
  490.         t = messageobj.type
  491.         buddyid = None if b is not None else None
  492.         if buddyid is None:
  493.             next = False
  494.         else:
  495.             next = getattr(self, 'last_buddy', None) == buddyid
  496.         self.last_buddy = buddyid
  497.         self.message_area.format_message(t, messageobj, next = next)
  498.         if ondone is not None:
  499.             pass
  500.         
  501.  
  502.     
  503.     def set_profile_html(self, buddy):
  504.         profilewindow = self.profile_html
  505.         
  506.         try:
  507.             html = GetInfo(self.Buddy, showprofile = True, showhide = False, overflow_hidden = False)
  508.         except Exception:
  509.             print_exc()
  510.             html = buddy.name
  511.  
  512.         self.Frozen().__enter__()
  513.         
  514.         try:
  515.             profilewindow.SetHTML(html)
  516.         finally:
  517.             pass
  518.  
  519.  
  520.     
  521.     def on_text_changed(self, e):
  522.         e.Skip()
  523.         oldConvo = self.convo
  524.         if not (self.send_typing) and self.Mode != 'im' or not self.set_conversation_from_combos():
  525.             return None
  526.         txt = self.input_area.Value
  527.         if len(txt) == 0:
  528.             if self.typing_status != None:
  529.                 self.typing_status = None
  530.                 self.convo.send_typing_status(None)
  531.             
  532.             if self.typing_timer:
  533.                 self.typing_timer.Stop()
  534.                 self.typing_timer = None
  535.             
  536.         elif self.typing_status != 'typing':
  537.             self.typing_status = 'typing'
  538.             self.convo.send_typing_status(self.typing_status)
  539.         
  540.         self.cancel_timer()
  541.         self.typing_timer = PyTimer(self.send_typed)
  542.         self.typing_timer.Start(self.typed_delay * 1000, True)
  543.  
  544.     
  545.     def send_typed(self, *e):
  546.         if self.typing_status != 'typed':
  547.             self.typing_status = 'typed'
  548.             self.convo.send_typing_status(self.typing_status)
  549.         
  550.  
  551.     
  552.     def cancel_timer(self):
  553.         if self.typing_timer:
  554.             self.typing_timer.Stop()
  555.             self.typing_timer = None
  556.         
  557.  
  558.     
  559.     def on_message_area_shown(self):
  560.         if hasattr(self, 'message_area') and not (self.message_area.inited):
  561.             if hasattr(self, 'convo'):
  562.                 self.init_message_area(self.convo.name, self.convo.buddy, show_history = not (self.convo.ischat))
  563.             else:
  564.                 self.init_message_area('', None)
  565.             self.input_area.tc.Bind(wx.EVT_TEXT, self.on_text_changed)
  566.             ImWinDropTarget = ImWinDropTarget
  567.             import gui.imwin.imwindnd
  568.             self.SetDropTarget(ImWinDropTarget(self))
  569.         
  570.  
  571.     
  572.     def on_video(self):
  573.         import hooks
  574.         hooks.notify('digsby.video_chat.requested')
  575.         buddy = self.Buddy
  576.         VideoChatWindow = VideoChatWindow
  577.         import gui.video.webvideo
  578.         if VideoChatWindow.RaiseExisting():
  579.             self.convo.system_message(_('You can only have one audio/video call at a time.'))
  580.             log.info('video window already up')
  581.         else:
  582.             log.info('requesting video chat')
  583.             VideoChat = VideoChat
  584.             import digsby.videochat
  585.             VideoChat(buddy)
  586.  
  587.  
  588.