comparison src/browser/libervia_main.py @ 467:97c72fe4a5f2

browser_side: import fixes: - moved browser modules in a sat_browser packages, to avoid import conflicts with std lib (e.g. logging), and let pyjsbuild work normaly - refactored bad import practices: classes are most of time not imported directly, module is imported instead.
author Goffi <goffi@goffi.org>
date Mon, 09 Jun 2014 22:15:26 +0200
parents 07433bd892ee
children 830b50593597
comparison
equal deleted inserted replaced
466:01880aa8ea2d 467:97c72fe4a5f2
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19
20 import pyjd # this is dummy in pyjs 20 import pyjd # this is dummy in pyjs
21 21
22 ### logging configuration ### 22 ### logging configuration ###
23 import logging 23 from sat_browser import logging
24 logging.configure() 24 logging.configure()
25 from sat.core.log import getLogger 25 from sat.core.log import getLogger
26 log = getLogger(__name__) 26 log = getLogger(__name__)
27 ### 27 ###
28 28
35 from pyjamas.ui.KeyboardListener import KEY_ESCAPE 35 from pyjamas.ui.KeyboardListener import KEY_ESCAPE
36 from pyjamas.Timer import Timer 36 from pyjamas.Timer import Timer
37 from pyjamas import Window, DOM 37 from pyjamas import Window, DOM
38 from pyjamas.JSONService import JSONProxy 38 from pyjamas.JSONService import JSONProxy
39 39
40 from register import RegisterBox 40 from sat_browser import register
41 from contact import ContactPanel 41 from sat_browser import contact
42 from base_widget import WidgetsPanel 42 from sat_browser import base_widget
43 from panels import MicroblogItem 43 from sat_browser import panels
44 import panels 44 from sat_browser import dialog
45 import dialog 45 from sat_browser import jid
46 from jid import JID 46 from sat_browser import xmlui
47 from xmlui import XMLUI 47 from sat_browser import html_tools
48 from html_tools import html_sanitize 48 from sat_browser import notification
49 from notification import Notification 49
50 50 from sat_browser.constants import Const as C
51 from constants import Const as C
52 51
53 52
54 MAX_MBLOG_CACHE = 500 # Max microblog entries kept in memories 53 MAX_MBLOG_CACHE = 500 # Max microblog entries kept in memories
55 54
56 # Set to true to not create a new LiberviaWidget when a similar one 55 # Set to true to not create a new LiberviaWidget when a similar one
57 # already exist (i.e. a chat panel with the same target). Instead 56 # already exist (i.e. a chat panel with the same target). Instead
58 # the existing widget will be eventually removed from its parent 57 # the existing widget will be eventually removed from its parent
59 # and added to new WidgetsPanel, or replaced to the expected 58 # and added to new base_widget.WidgetsPanel, or replaced to the expected
60 # position if the previous and the new parent are the same. 59 # position if the previous and the new parent are the same.
61 REUSE_EXISTING_LIBERVIA_WIDGETS = True 60 REUSE_EXISTING_LIBERVIA_WIDGETS = True
62 61
63 62
64 class LiberviaJsonProxy(JSONProxy): 63 class LiberviaJsonProxy(JSONProxy):
176 self._selected_listeners = set() 175 self._selected_listeners = set()
177 self.bridge = BridgeCall() 176 self.bridge = BridgeCall()
178 self.bridge_signals = BridgeSignals(self) 177 self.bridge_signals = BridgeSignals(self)
179 self.uni_box = None 178 self.uni_box = None
180 self.status_panel = HTML('<br />') 179 self.status_panel = HTML('<br />')
181 self.contact_panel = ContactPanel(self) 180 self.contact_panel = contact.ContactPanel(self)
182 self.panel = panels.MainPanel(self) 181 self.panel = panels.MainPanel(self)
183 self.discuss_panel = self.panel.discuss_panel 182 self.discuss_panel = self.panel.discuss_panel
184 self.tab_panel = self.panel.tab_panel 183 self.tab_panel = self.panel.tab_panel
185 self.tab_panel.addTabListener(self) 184 self.tab_panel.addTabListener(self)
186 self.libervia_widgets = set() # keep track of all actives LiberviaWidgets 185 self.libervia_widgets = set() # keep track of all actives LiberviaWidgets
187 self.room_list = [] # list of rooms 186 self.room_list = [] # list of rooms
188 self.mblog_cache = [] # used to keep our own blog entries in memory, to show them in new mblog panel 187 self.mblog_cache = [] # used to keep our own blog entries in memory, to show them in new mblog panel
189 self.avatars_cache = {} # keep track of jid's avatar hash (key=jid, value=file) 188 self.avatars_cache = {} # keep track of jid's avatar hash (key=jid, value=file)
190 self._register_box = None 189 self._register_box = None
191 RootPanel().add(self.panel) 190 RootPanel().add(self.panel)
192 self.notification = Notification() 191 self.notification = notification.Notification()
193 DOM.addEventPreview(self) 192 DOM.addEventPreview(self)
194 self._register = RegisterCall() 193 self._register = RegisterCall()
195 self._register.call('getMenus', self.panel.menu.createMenus) 194 self._register.call('getMenus', self.panel.menu.createMenus)
196 self._register.call('registerParams', None) 195 self._register.call('registerParams', None)
197 self._register.call('isRegistered', self._isRegisteredCB) 196 self._register.call('isRegistered', self._isRegisteredCB)
202 def addSelectedListener(self, callback): 201 def addSelectedListener(self, callback):
203 self._selected_listeners.add(callback) 202 self._selected_listeners.add(callback)
204 203
205 def getSelected(self): 204 def getSelected(self):
206 wid = self.tab_panel.getCurrentPanel() 205 wid = self.tab_panel.getCurrentPanel()
207 if not isinstance(wid, WidgetsPanel): 206 if not isinstance(wid, base_widget.WidgetsPanel):
208 log.error("Tab widget is not a WidgetsPanel, can't get selected widget") 207 log.error("Tab widget is not a base_widget.WidgetsPanel, can't get selected widget")
209 return None 208 return None
210 return wid.selected 209 return wid.selected
211 210
212 def setSelected(self, widget): 211 def setSelected(self, widget):
213 """Define the selected widget""" 212 """Define the selected widget"""
214 widgets_panel = self.tab_panel.getCurrentPanel() 213 widgets_panel = self.tab_panel.getCurrentPanel()
215 if not isinstance(widgets_panel, WidgetsPanel): 214 if not isinstance(widgets_panel, base_widget.WidgetsPanel):
216 return 215 return
217 216
218 selected = widgets_panel.selected 217 selected = widgets_panel.selected
219 218
220 if selected == widget: 219 if selected == widget:
291 """Create a new tab and eventually add a widget in 290 """Create a new tab and eventually add a widget in
292 @param label: label of the tab 291 @param label: label of the tab
293 @param wid: LiberviaWidget to add 292 @param wid: LiberviaWidget to add
294 @param select: True to select the added tab 293 @param select: True to select the added tab
295 """ 294 """
296 widgets_panel = WidgetsPanel(self) 295 widgets_panel = base_widget.WidgetsPanel(self)
297 self.tab_panel.add(widgets_panel, label) 296 self.tab_panel.add(widgets_panel, label)
298 widgets_panel.addWidget(wid) 297 widgets_panel.addWidget(wid)
299 if select: 298 if select:
300 self.tab_panel.selectTab(self.tab_panel.getWidgetCount() - 1) 299 self.tab_panel.selectTab(self.tab_panel.getWidgetCount() - 1)
301 return widgets_panel 300 return widgets_panel
314 self.notification.notify(title, body) 313 self.notification.notify(title, body)
315 314
316 def _isRegisteredCB(self, result): 315 def _isRegisteredCB(self, result):
317 registered, warning = result 316 registered, warning = result
318 if not registered: 317 if not registered:
319 self._register_box = RegisterBox(self.logged) 318 self._register_box = register.RegisterBox(self.logged)
320 self._register_box.centerBox() 319 self._register_box.centerBox()
321 self._register_box.show() 320 self._register_box.show()
322 if warning: 321 if warning:
323 dialog.InfoDialog(_('Security warning'), warning).show() 322 dialog.InfoDialog(_('Security warning'), warning).show()
324 self._tryAutoConnect(skip_validation=not not warning) 323 self._tryAutoConnect(skip_validation=not not warning)
393 def _actionCb(self, data): 392 def _actionCb(self, data):
394 if not data: 393 if not data:
395 # action was a one shot, nothing to do 394 # action was a one shot, nothing to do
396 pass 395 pass
397 elif "xmlui" in data: 396 elif "xmlui" in data:
398 ui = XMLUI(self, xml_data=data['xmlui']) 397 ui = xmlui.XMLUI(self, xml_data=data['xmlui'])
399 options = ['NO_CLOSE'] if ui.type == 'form' else [] 398 options = ['NO_CLOSE'] if ui.type == 'form' else []
400 _dialog = dialog.GenericDialog(ui.title, ui, options=options) 399 _dialog = dialog.GenericDialog(ui.title, ui, options=options)
401 ui.setCloseCb(_dialog.close) 400 ui.setCloseCb(_dialog.close)
402 _dialog.show() 401 _dialog.show()
403 else: 402 else:
418 if data is None: 417 if data is None:
419 data = {} 418 data = {}
420 self.bridge.call('launchAction', (self._actionCb, self._actionEb), callback_id, data) 419 self.bridge.call('launchAction', (self._actionCb, self._actionEb), callback_id, data)
421 420
422 def _getContactsCB(self, contacts_data): 421 def _getContactsCB(self, contacts_data):
423 for contact in contacts_data: 422 for contact_ in contacts_data:
424 jid, attributes, groups = contact 423 jid, attributes, groups = contact_
425 self._newContactCb(jid, attributes, groups) 424 self._newContactCb(jid, attributes, groups)
426 425
427 def _getSignalsCB(self, signal_data): 426 def _getSignalsCB(self, signal_data):
428 self.bridge_signals.call('getSignals', self._getSignalsCB) 427 self.bridge_signals.call('getSignals', self._getSignalsCB)
429 log.debug("Got signal ==> name: %s, params: %s" % (signal_data[0], signal_data[1])) 428 log.debug("Got signal ==> name: %s, params: %s" % (signal_data[0], signal_data[1]))
485 elif name == 'entityDataUpdated': 484 elif name == 'entityDataUpdated':
486 self._entityDataUpdatedCb(*args) 485 self._entityDataUpdatedCb(*args)
487 elif name == 'chatStateReceived': 486 elif name == 'chatStateReceived':
488 self._chatStateReceivedCb(*args) 487 self._chatStateReceivedCb(*args)
489 488
490 def _getParamsUICB(self, xmlui): 489 def _getParamsUICB(self, xml_ui):
491 """Hide the parameters item if there's nothing to display""" 490 """Hide the parameters item if there's nothing to display"""
492 if not xmlui: 491 if not xml_ui:
493 self.panel.menu.removeItemParams() 492 self.panel.menu.removeItemParams()
494 493
495 def _ownBlogsFills(self, mblogs): 494 def _ownBlogsFills(self, mblogs):
496 #put our own microblogs in cache, then fill all panels with them 495 #put our own microblogs in cache, then fill all panels with them
497 for publisher in mblogs: 496 for publisher in mblogs:
501 continue 500 continue
502 if 'groups' in mblog: 501 if 'groups' in mblog:
503 _groups = set(mblog['groups'].split() if mblog['groups'] else []) 502 _groups = set(mblog['groups'].split() if mblog['groups'] else [])
504 else: 503 else:
505 _groups = None 504 _groups = None
506 mblog_entry = MicroblogItem(mblog) 505 mblog_entry = panels.MicroblogItem(mblog)
507 self.mblog_cache.append((_groups, mblog_entry)) 506 self.mblog_cache.append((_groups, mblog_entry))
508 507
509 if len(self.mblog_cache) > MAX_MBLOG_CACHE: 508 if len(self.mblog_cache) > MAX_MBLOG_CACHE:
510 del self.mblog_cache[0:len(self.mblog_cache - MAX_MBLOG_CACHE)] 509 del self.mblog_cache[0:len(self.mblog_cache - MAX_MBLOG_CACHE)]
511 for lib_wid in self.libervia_widgets: 510 for lib_wid in self.libervia_widgets:
515 for event_data in self.init_cache: # so we have to send all the cached events 514 for event_data in self.init_cache: # so we have to send all the cached events
516 self._personalEventCb(*event_data) 515 self._personalEventCb(*event_data)
517 del self.init_cache 516 del self.init_cache
518 517
519 def _getProfileJidCB(self, jid): 518 def _getProfileJidCB(self, jid):
520 self.whoami = JID(jid) 519 self.whoami = jid.JID(jid)
521 #we can now ask our status 520 #we can now ask our status
522 self.bridge.call('getPresenceStatuses', self._getPresenceStatusesCb) 521 self.bridge.call('getPresenceStatuses', self._getPresenceStatusesCb)
523 #the rooms where we are 522 #the rooms where we are
524 self.bridge.call('getRoomsJoined', self._getRoomsJoinedCb) 523 self.bridge.call('getRoomsJoined', self._getRoomsJoinedCb)
525 #and if there is any subscription request waiting for us 524 #and if there is any subscription request waiting for us
539 538
540 def _personalEventCb(self, sender, event_type, data): 539 def _personalEventCb(self, sender, event_type, data):
541 if not self.initialised: 540 if not self.initialised:
542 self.init_cache.append((sender, event_type, data)) 541 self.init_cache.append((sender, event_type, data))
543 return 542 return
544 sender = JID(sender).bare 543 sender = jid.JID(sender).bare
545 if event_type == "MICROBLOG": 544 if event_type == "MICROBLOG":
546 if not 'content' in data: 545 if not 'content' in data:
547 log.warning("No content found in microblog data") 546 log.warning("No content found in microblog data")
548 return 547 return
549 if 'groups' in data: 548 if 'groups' in data:
550 _groups = set(data['groups'].split() if data['groups'] else []) 549 _groups = set(data['groups'].split() if data['groups'] else [])
551 else: 550 else:
552 _groups = None 551 _groups = None
553 mblog_entry = MicroblogItem(data) 552 mblog_entry = panels.MicroblogItem(data)
554 553
555 for lib_wid in self.libervia_widgets: 554 for lib_wid in self.libervia_widgets:
556 if isinstance(lib_wid, panels.MicroblogPanel): 555 if isinstance(lib_wid, panels.MicroblogPanel):
557 self.addBlogEntry(lib_wid, sender, _groups, mblog_entry) 556 self.addBlogEntry(lib_wid, sender, _groups, mblog_entry)
558 557
586 def addBlogEntry(self, mblog_panel, sender, _groups, mblog_entry): 585 def addBlogEntry(self, mblog_panel, sender, _groups, mblog_entry):
587 """Check if an entry can go in MicroblogPanel and add to it 586 """Check if an entry can go in MicroblogPanel and add to it
588 @param mblog_panel: MicroblogPanel instance 587 @param mblog_panel: MicroblogPanel instance
589 @param sender: jid of the entry sender 588 @param sender: jid of the entry sender
590 @param _groups: groups which can receive this entry 589 @param _groups: groups which can receive this entry
591 @param mblog_entry: MicroblogItem instance""" 590 @param mblog_entry: panels.MicroblogItem instance"""
592 if mblog_entry.type == "comment" or mblog_panel.isJidAccepted(sender) or (_groups == None and self.whoami and sender == self.whoami.bare) \ 591 if mblog_entry.type == "comment" or mblog_panel.isJidAccepted(sender) or (_groups == None and self.whoami and sender == self.whoami.bare) \
593 or (_groups and _groups.intersection(mblog_panel.accepted_groups)): 592 or (_groups and _groups.intersection(mblog_panel.accepted_groups)):
594 mblog_panel.addEntry(mblog_entry) 593 mblog_panel.addEntry(mblog_entry)
595 594
596 def FillMicroblogPanel(self, mblog_panel): 595 def FillMicroblogPanel(self, mblog_panel):
667 self.setSelected(lib_wid) 666 self.setSelected(lib_wid)
668 lib_wid.refresh() 667 lib_wid.refresh()
669 return lib_wid 668 return lib_wid
670 669
671 def _newMessageCb(self, from_jid, msg, msg_type, to_jid, extra): 670 def _newMessageCb(self, from_jid, msg, msg_type, to_jid, extra):
672 _from = JID(from_jid) 671 _from = jid.JID(from_jid)
673 _to = JID(to_jid) 672 _to = jid.JID(to_jid)
674 other = _to if _from.bare == self.whoami.bare else _from 673 other = _to if _from.bare == self.whoami.bare else _from
675 lib_wid = self.getLiberviaWidget(panels.ChatPanel, other, ignoreOtherTabs=False) 674 lib_wid = self.getLiberviaWidget(panels.ChatPanel, other, ignoreOtherTabs=False)
676 self.displayNotification(_from, msg) 675 self.displayNotification(_from, msg)
677 if msg_type == 'headline' and from_jid == self._defaultDomain: 676 if msg_type == 'headline' and from_jid == self._defaultDomain:
678 try: 677 try:
689 self.contact_panel.updateContact(other.bare, {}, [C.GROUP_NOT_IN_ROSTER]) 688 self.contact_panel.updateContact(other.bare, {}, [C.GROUP_NOT_IN_ROSTER])
690 # The message has not been shown, we must indicate it 689 # The message has not been shown, we must indicate it
691 self.contact_panel.setContactMessageWaiting(other.bare, True) 690 self.contact_panel.setContactMessageWaiting(other.bare, True)
692 691
693 def _presenceUpdateCb(self, entity, show, priority, statuses): 692 def _presenceUpdateCb(self, entity, show, priority, statuses):
694 entity_jid = JID(entity) 693 entity_jid = jid.JID(entity)
695 if self.whoami and self.whoami == entity_jid: # XXX: QnD way to get our presence/status 694 if self.whoami and self.whoami == entity_jid: # XXX: QnD way to get our presence/status
696 self.status_panel.setPresence(show) 695 self.status_panel.setPresence(show)
697 if statuses: 696 if statuses:
698 self.status_panel.setStatus(statuses.values()[0]) 697 self.status_panel.setStatus(statuses.values()[0])
699 else: 698 else:
700 self.contact_panel.setConnected(entity_jid.bare, entity_jid.resource, show, priority, statuses) 699 self.contact_panel.setConnected(entity_jid.bare, entity_jid.resource, show, priority, statuses)
701 700
702 def _roomJoinedCb(self, room_jid, room_nicks, user_nick): 701 def _roomJoinedCb(self, room_jid, room_nicks, user_nick):
703 _target = JID(room_jid) 702 _target = jid.JID(room_jid)
704 if _target not in self.room_list: 703 if _target not in self.room_list:
705 self.room_list.append(_target) 704 self.room_list.append(_target)
706 chat_panel = panels.ChatPanel(self, _target, type_='group') 705 chat_panel = panels.ChatPanel(self, _target, type_='group')
707 chat_panel.setUserNick(user_nick) 706 chat_panel.setUserNick(user_nick)
708 if _target.node.startswith('sat_tarot_'): # XXX: it's not really beautiful, but it works :) 707 if _target.node.startswith('sat_tarot_'): # XXX: it's not really beautiful, but it works :)
714 chat_panel.setPresents(room_nicks) 713 chat_panel.setPresents(room_nicks)
715 chat_panel.historyPrint() 714 chat_panel.historyPrint()
716 chat_panel.refresh() 715 chat_panel.refresh()
717 716
718 def _roomLeftCb(self, room_jid, room_nicks, user_nick): 717 def _roomLeftCb(self, room_jid, room_nicks, user_nick):
719 # FIXME: room_list contains JID instances so why MUST we do 718 # FIXME: room_list contains jid.JID instances so why MUST we do
720 # 'remove(room_jid)' and not 'remove(JID(room_jid))' ????!! 719 # 'remove(room_jid)' and not 'remove(jid.JID(room_jid))' ????!!
721 # This looks like a pyjamas bug --> check/report 720 # This looks like a pyjamas bug --> check/report
722 try: 721 try:
723 self.room_list.remove(room_jid) 722 self.room_list.remove(room_jid)
724 except KeyError: 723 except KeyError:
725 pass 724 pass
774 for sub in waiting_sub: 773 for sub in waiting_sub:
775 self._subscribeCb(waiting_sub[sub], sub) 774 self._subscribeCb(waiting_sub[sub], sub)
776 775
777 def _subscribeCb(self, sub_type, entity): 776 def _subscribeCb(self, sub_type, entity):
778 if sub_type == 'subscribed': 777 if sub_type == 'subscribed':
779 dialog.InfoDialog('Subscription confirmation', 'The contact <b>%s</b> has added you to his/her contact list' % html_sanitize(entity)).show() 778 dialog.InfoDialog('Subscription confirmation', 'The contact <b>%s</b> has added you to his/her contact list' % html_tools.html_sanitize(entity)).show()
780 self.getEntityMBlog(entity) 779 self.getEntityMBlog(entity)
781 780
782 elif sub_type == 'unsubscribed': 781 elif sub_type == 'unsubscribed':
783 dialog.InfoDialog('Subscription refusal', 'The contact <b>%s</b> has refused to add you in his/her contact list' % html_sanitize(entity)).show() 782 dialog.InfoDialog('Subscription refusal', 'The contact <b>%s</b> has refused to add you in his/her contact list' % html_tools.html_sanitize(entity)).show()
784 #TODO: remove microblogs from panels 783 #TODO: remove microblogs from panels
785 784
786 elif sub_type == 'subscribe': 785 elif sub_type == 'subscribe':
787 #The user want to subscribe to our presence 786 #The user want to subscribe to our presence
788 _dialog = None 787 _dialog = None
789 msg = HTML('The contact <b>%s</b> want to add you in his/her contact list, do you accept ?' % html_sanitize(entity)) 788 msg = HTML('The contact <b>%s</b> want to add you in his/her contact list, do you accept ?' % html_tools.html_sanitize(entity))
790 789
791 def ok_cb(ignore): 790 def ok_cb(ignore):
792 self.bridge.call('subscription', None, "subscribed", entity, '', _dialog.getSelectedGroups()) 791 self.bridge.call('subscription', None, "subscribed", entity, '', _dialog.getSelectedGroups())
793 792
794 def cancel_cb(ignore): 793 def cancel_cb(ignore):
822 """ 821 """
823 if from_jid_s == '@ALL@': 822 if from_jid_s == '@ALL@':
824 target = '@ALL@' 823 target = '@ALL@'
825 nick = C.ALL_OCCUPANTS 824 nick = C.ALL_OCCUPANTS
826 else: 825 else:
827 from_jid = JID(from_jid_s) 826 from_jid = jid.JID(from_jid_s)
828 target = from_jid.bare 827 target = from_jid.bare
829 nick = from_jid.resource 828 nick = from_jid.resource
830 829
831 for lib_wid in self.libervia_widgets: 830 for lib_wid in self.libervia_widgets:
832 if isinstance(lib_wid, panels.ChatPanel): 831 if isinstance(lib_wid, panels.ChatPanel):