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