comparison cagou/core/cagou_main.py @ 312:772c170b47a9

Python3 port: /!\ Cagou now runs with Python 3.6+ Port has been done in the same way as for backend (check backend commit b2d067339de3 message for details).
author Goffi <goffi@goffi.org>
date Tue, 13 Aug 2019 19:14:22 +0200
parents f55b60659ec1
children 86566968837a
comparison
equal deleted inserted replaced
311:a0d978d3ce84 312:772c170b47a9
22 import glob 22 import glob
23 import sys 23 import sys
24 from sat.core.i18n import _ 24 from sat.core.i18n import _
25 from . import kivy_hack 25 from . import kivy_hack
26 kivy_hack.do_hack() 26 kivy_hack.do_hack()
27 from constants import Const as C 27 from .constants import Const as C
28 from sat.core import log as logging 28 from sat.core import log as logging
29 log = logging.getLogger(__name__) 29 log = logging.getLogger(__name__)
30 from sat.core import exceptions 30 from sat.core import exceptions
31 from sat_frontends.quick_frontend.quick_app import QuickApp 31 from sat_frontends.quick_frontend.quick_app import QuickApp
32 from sat_frontends.quick_frontend import quick_widgets 32 from sat_frontends.quick_frontend import quick_widgets
47 elif bridge_name in ('pb', 'embedded'): 47 elif bridge_name in ('pb', 'embedded'):
48 kivy.support.install_twisted_reactor() 48 kivy.support.install_twisted_reactor()
49 from kivy.app import App 49 from kivy.app import App
50 from kivy.lang import Builder 50 from kivy.lang import Builder
51 from kivy import properties 51 from kivy import properties
52 import xmlui 52 from . import xmlui
53 from profile_manager import ProfileManager 53 from .profile_manager import ProfileManager
54 from kivy.clock import Clock 54 from kivy.clock import Clock
55 from kivy.uix.label import Label 55 from kivy.uix.label import Label
56 from kivy.uix.boxlayout import BoxLayout 56 from kivy.uix.boxlayout import BoxLayout
57 from kivy.uix.floatlayout import FloatLayout 57 from kivy.uix.floatlayout import FloatLayout
58 from kivy.uix.screenmanager import (ScreenManager, Screen, 58 from kivy.uix.screenmanager import (ScreenManager, Screen,
62 from kivy.core.window import Window 62 from kivy.core.window import Window
63 from kivy.animation import Animation 63 from kivy.animation import Animation
64 from kivy.metrics import dp 64 from kivy.metrics import dp
65 from kivy import utils as kivy_utils 65 from kivy import utils as kivy_utils
66 from kivy.config import Config as KivyConfig 66 from kivy.config import Config as KivyConfig
67 from cagou_widget import CagouWidget 67 from .cagou_widget import CagouWidget
68 from . import widgets_handler 68 from . import widgets_handler
69 from .common import IconButton 69 from .common import IconButton
70 from . import menu 70 from . import menu
71 from . import dialog 71 from . import dialog
72 from importlib import import_module 72 from importlib import import_module
76 import cagou.kv 76 import cagou.kv
77 try: 77 try:
78 from plyer import notification 78 from plyer import notification
79 except ImportError: 79 except ImportError:
80 notification = None 80 notification = None
81 log.warning(_(u"Can't import plyer, some features disabled")) 81 log.warning(_("Can't import plyer, some features disabled"))
82 82
83 83
84 ## platform specific settings ## 84 ## platform specific settings ##
85 85
86 if kivy_utils.platform == "android": 86 if kivy_utils.platform == "android":
151 151
152 def open(self, widget): 152 def open(self, widget):
153 self.clear_widgets() 153 self.clear_widgets()
154 for n in self.notes: 154 for n in self.notes:
155 kwargs = { 155 kwargs = {
156 u'title': n.title, 156 'title': n.title,
157 u'message': n.message, 157 'message': n.message,
158 u'level': n.level 158 'level': n.level
159 } 159 }
160 if n.symbol is not None: 160 if n.symbol is not None:
161 kwargs[u'symbol'] = n.symbol 161 kwargs['symbol'] = n.symbol
162 if n.action is not None: 162 if n.action is not None:
163 kwargs[u'action'] = n.action 163 kwargs['action'] = n.action
164 self.add_widget(NoteDrop(title=n.title, message=n.message, level=n.level, 164 self.add_widget(NoteDrop(title=n.title, message=n.message, level=n.level,
165 symbol=n.symbol, action=n.action)) 165 symbol=n.symbol, action=n.action))
166 self.add_widget(self.clear_btn) 166 self.add_widget(self.clear_btn)
167 super(NotesDrop, self).open(widget) 167 super(NotesDrop, self).open(widget)
168 168
192 """ 192 """
193 self.notifs_icon.addNotif(callback, *args, **kwargs) 193 self.notifs_icon.addNotif(callback, *args, **kwargs)
194 194
195 def addNote(self, title, message, level, symbol, action): 195 def addNote(self, title, message, level, symbol, action):
196 kwargs = { 196 kwargs = {
197 u'title': title, 197 'title': title,
198 u'message': message, 198 'message': message,
199 u'level': level 199 'level': level
200 } 200 }
201 if symbol is not None: 201 if symbol is not None:
202 kwargs[u'symbol'] = symbol 202 kwargs['symbol'] = symbol
203 if action is not None: 203 if action is not None:
204 kwargs[u'action'] = action 204 kwargs['action'] = action
205 note = Note(**kwargs) 205 note = Note(**kwargs)
206 self.notes.append(note) 206 self.notes.append(note)
207 if self.notes_event is None: 207 if self.notes_event is None:
208 self.notes_event = Clock.schedule_interval(self._displayNextNote, 5) 208 self.notes_event = Clock.schedule_interval(self._displayNextNote, 5)
209 self._displayNextNote() 209 self._displayNextNote()
317 # a settings screen when pressing F1 or platform specific key 317 # a settings screen when pressing F1 or platform specific key
318 return 318 return
319 319
320 def build(self): 320 def build(self):
321 Window.bind(on_keyboard=self.key_input) 321 Window.bind(on_keyboard=self.key_input)
322 wid = CagouRootWidget(Label(text=u"Loading please wait")) 322 wid = CagouRootWidget(Label(text="Loading please wait"))
323 if sys.platform == 'android': 323 if sys.platform == 'android':
324 # we don't want menu on Android 324 # we don't want menu on Android
325 wid.root_menus.height = 0 325 wid.root_menus.height = 0
326 return wid 326 return wid
327 327
411 service.start(mActivity, argument) 411 service.start(mActivity, argument)
412 self.service = service 412 self.service = service
413 413
414 bridge_module = dynamic_import.bridge(bridge_name, 'sat_frontends.bridge') 414 bridge_module = dynamic_import.bridge(bridge_name, 'sat_frontends.bridge')
415 if bridge_module is None: 415 if bridge_module is None:
416 log.error(u"Can't import {} bridge".format(bridge_name)) 416 log.error("Can't import {} bridge".format(bridge_name))
417 sys.exit(3) 417 sys.exit(3)
418 else: 418 else:
419 log.debug(u"Loading {} bridge".format(bridge_name)) 419 log.debug("Loading {} bridge".format(bridge_name))
420 super(Cagou, self).__init__(bridge_factory=bridge_module.Bridge, 420 super(Cagou, self).__init__(bridge_factory=bridge_module.Bridge,
421 xmlui=xmlui, 421 xmlui=xmlui,
422 check_options=quick_utils.check_options, 422 check_options=quick_utils.check_options,
423 connect_bridge=False) 423 connect_bridge=False)
424 self._import_kv() 424 self._import_kv()
430 'downloads_dir') 430 'downloads_dir')
431 if not os.path.exists(self.downloads_dir): 431 if not os.path.exists(self.downloads_dir):
432 try: 432 try:
433 os.makedirs(self.downloads_dir) 433 os.makedirs(self.downloads_dir)
434 except OSError as e: 434 except OSError as e:
435 log.warnings(_(u"Can't create downloads dir: {reason}").format(reason=e)) 435 log.warnings(_("Can't create downloads dir: {reason}").format(reason=e))
436 self.app.default_avatar = os.path.join(self.media_dir, "misc/default_avatar.png") 436 self.app.default_avatar = os.path.join(self.media_dir, "misc/default_avatar.png")
437 self.app.icon = os.path.join(self.media_dir, 437 self.app.icon = os.path.join(self.media_dir,
438 "icons/muchoslava/png/cagou_profil_bleu_96.png") 438 "icons/muchoslava/png/cagou_profil_bleu_96.png")
439 self._plg_wids = [] # main widgets plugins 439 self._plg_wids = [] # main widgets plugins
440 self._plg_wids_transfer = [] # transfer widgets plugins 440 self._plg_wids_transfer = [] # transfer widgets plugins
454 'no_certificate_validation', 454 'no_certificate_validation',
455 C.BOOL_FALSE)) 455 C.BOOL_FALSE))
456 if not self.tls_validation: 456 if not self.tls_validation:
457 from cagou.core import patches 457 from cagou.core import patches
458 patches.apply() 458 patches.apply()
459 log.warning(u"SSL certificate validation is disabled, this is unsecure!") 459 log.warning("SSL certificate validation is disabled, this is unsecure!")
460 460
461 @property 461 @property
462 def visible_widgets(self): 462 def visible_widgets(self):
463 for w_list in self._visible_widgets.itervalues(): 463 for w_list in self._visible_widgets.values():
464 for w in w_list: 464 for w in w_list:
465 yield w 465 yield w
466 466
467 @QuickApp.sync.setter 467 @QuickApp.sync.setter
468 def sync(self, state): 468 def sync(self, state):
570 else: 570 else:
571 raise exceptions.InternalError("base.kv is missing") 571 raise exceptions.InternalError("base.kv is missing")
572 572
573 for kv_file in kv_files: 573 for kv_file in kv_files:
574 Builder.load_file(kv_file) 574 Builder.load_file(kv_file)
575 log.debug(u"kv file {} loaded".format(kv_file)) 575 log.debug("kv file {} loaded".format(kv_file))
576 576
577 def _import_plugins(self): 577 def _import_plugins(self):
578 """import all plugins""" 578 """import all plugins"""
579 self.default_wid = None 579 self.default_wid = None
580 plugins_path = os.path.dirname(cagou.plugins.__file__) 580 plugins_path = os.path.dirname(cagou.plugins.__file__)
581 plugin_glob = u"plugin*." + C.PLUGIN_EXT 581 plugin_glob = "plugin*." + C.PLUGIN_EXT
582 plug_lst = [os.path.splitext(p)[0] for p in 582 plug_lst = [os.path.splitext(p)[0] for p in
583 map(os.path.basename, glob.glob(os.path.join(plugins_path, 583 map(os.path.basename, glob.glob(os.path.join(plugins_path,
584 plugin_glob)))] 584 plugin_glob)))]
585 585
586 imported_names_main = set() # used to avoid loading 2 times 586 imported_names_main = set() # used to avoid loading 2 times
589 for plug in plug_lst: 589 for plug in plug_lst:
590 plugin_path = 'cagou.plugins.' + plug 590 plugin_path = 'cagou.plugins.' + plug
591 591
592 # we get type from plugin name 592 # we get type from plugin name
593 suff = plug[7:] 593 suff = plug[7:]
594 if u'_' not in suff: 594 if '_' not in suff:
595 log.error(u"invalid plugin name: {}, skipping".format(plug)) 595 log.error("invalid plugin name: {}, skipping".format(plug))
596 continue 596 continue
597 plugin_type = suff[:suff.find(u'_')] 597 plugin_type = suff[:suff.find('_')]
598 598
599 # and select the variable to use according to type 599 # and select the variable to use according to type
600 if plugin_type == C.PLUG_TYPE_WID: 600 if plugin_type == C.PLUG_TYPE_WID:
601 imported_names = imported_names_main 601 imported_names = imported_names_main
602 default_factory = self._defaultFactoryMain 602 default_factory = self._defaultFactoryMain
603 elif plugin_type == C.PLUG_TYPE_TRANSFER: 603 elif plugin_type == C.PLUG_TYPE_TRANSFER:
604 imported_names = imported_names_transfer 604 imported_names = imported_names_transfer
605 default_factory = self._defaultFactoryTransfer 605 default_factory = self._defaultFactoryTransfer
606 else: 606 else:
607 log.error(u"unknown plugin type {type_} for plugin {file_}, skipping" 607 log.error("unknown plugin type {type_} for plugin {file_}, skipping"
608 .format( 608 .format(
609 type_ = plugin_type, 609 type_ = plugin_type,
610 file_ = plug 610 file_ = plug
611 )) 611 ))
612 continue 612 continue
621 plugin_info['plugin_file'] = plug 621 plugin_info['plugin_file'] = plug
622 plugin_info['plugin_type'] = plugin_type 622 plugin_info['plugin_type'] = plugin_type
623 623
624 if 'platforms' in plugin_info: 624 if 'platforms' in plugin_info:
625 if sys.platform not in plugin_info['platforms']: 625 if sys.platform not in plugin_info['platforms']:
626 log.info(u"{plugin_file} is not used on this platform, skipping" 626 log.info("{plugin_file} is not used on this platform, skipping"
627 .format(**plugin_info)) 627 .format(**plugin_info))
628 continue 628 continue
629 629
630 # import name is used to differentiate plugins 630 # import name is used to differentiate plugins
631 if 'import_name' not in plugin_info: 631 if 'import_name' not in plugin_info:
632 plugin_info['import_name'] = plug 632 plugin_info['import_name'] = plug
633 if plugin_info['import_name'] in imported_names: 633 if plugin_info['import_name'] in imported_names:
634 log.warning(_(u"there is already a plugin named {}, " 634 log.warning(_("there is already a plugin named {}, "
635 u"ignoring new one").format(plugin_info['import_name'])) 635 "ignoring new one").format(plugin_info['import_name']))
636 continue 636 continue
637 if plugin_info['import_name'] == C.WID_SELECTOR: 637 if plugin_info['import_name'] == C.WID_SELECTOR:
638 if plugin_type != C.PLUG_TYPE_WID: 638 if plugin_type != C.PLUG_TYPE_WID:
639 log.error(u"{import_name} import name can only be used with {type_} " 639 log.error("{import_name} import name can only be used with {type_} "
640 u"type, skipping {name}".format(type_=C.PLUG_TYPE_WID, 640 "type, skipping {name}".format(type_=C.PLUG_TYPE_WID,
641 **plugin_info)) 641 **plugin_info))
642 continue 642 continue
643 # if WidgetSelector exists, it will be our default widget 643 # if WidgetSelector exists, it will be our default widget
644 self.default_wid = plugin_info 644 self.default_wid = plugin_info
645 645
649 name_start = 8 + len(plugin_type) 649 name_start = 8 + len(plugin_type)
650 plugin_info['name'] = plug[name_start:] 650 plugin_info['name'] = plug[name_start:]
651 651
652 # we need to load the kv file 652 # we need to load the kv file
653 if 'kv_file' not in plugin_info: 653 if 'kv_file' not in plugin_info:
654 plugin_info['kv_file'] = u'{}.kv'.format(plug) 654 plugin_info['kv_file'] = '{}.kv'.format(plug)
655 kv_path = os.path.join(plugins_path, plugin_info['kv_file']) 655 kv_path = os.path.join(plugins_path, plugin_info['kv_file'])
656 if not os.path.exists(kv_path): 656 if not os.path.exists(kv_path):
657 log.debug(u"no kv found for {plugin_file}".format(**plugin_info)) 657 log.debug("no kv found for {plugin_file}".format(**plugin_info))
658 else: 658 else:
659 Builder.load_file(kv_path) 659 Builder.load_file(kv_path)
660 660
661 # what is the main class ? 661 # what is the main class ?
662 main_cls = getattr(mod, plugin_info['main']) 662 main_cls = getattr(mod, plugin_info['main'])
667 if 'factory' not in plugin_info: 667 if 'factory' not in plugin_info:
668 plugin_info['factory'] = default_factory 668 plugin_info['factory'] = default_factory
669 669
670 # icons 670 # icons
671 for size in ('small', 'medium'): 671 for size in ('small', 'medium'):
672 key = u'icon_{}'.format(size) 672 key = 'icon_{}'.format(size)
673 try: 673 try:
674 path = plugin_info[key] 674 path = plugin_info[key]
675 except KeyError: 675 except KeyError:
676 path = C.DEFAULT_WIDGET_ICON.format(media=self.media_dir) 676 path = C.DEFAULT_WIDGET_ICON.format(media=self.media_dir)
677 else: 677 else:
680 path = C.DEFAULT_WIDGET_ICON.format(media=self.media_dir) 680 path = C.DEFAULT_WIDGET_ICON.format(media=self.media_dir)
681 plugin_info[key] = path 681 plugin_info[key] = path
682 682
683 plugins_set.append(plugin_info) 683 plugins_set.append(plugin_info)
684 if not self._plg_wids: 684 if not self._plg_wids:
685 log.error(_(u"no widget plugin found")) 685 log.error(_("no widget plugin found"))
686 return 686 return
687 687
688 # we want widgets sorted by names 688 # we want widgets sorted by names
689 self._plg_wids.sort(key=lambda p: p['name'].lower()) 689 self._plg_wids.sort(key=lambda p: p['name'].lower())
690 self._plg_wids_transfer.sort(key=lambda p: p['name'].lower()) 690 self._plg_wids_transfer.sort(key=lambda p: p['name'].lower())
697 if type_ == C.PLUG_TYPE_WID: 697 if type_ == C.PLUG_TYPE_WID:
698 return self._plg_wids 698 return self._plg_wids
699 elif type_ == C.PLUG_TYPE_TRANSFER: 699 elif type_ == C.PLUG_TYPE_TRANSFER:
700 return self._plg_wids_transfer 700 return self._plg_wids_transfer
701 else: 701 else:
702 raise KeyError(u"{} plugin type is unknown".format(type_)) 702 raise KeyError("{} plugin type is unknown".format(type_))
703 703
704 def getPluggedWidgets(self, type_=C.PLUG_TYPE_WID, except_cls=None): 704 def getPluggedWidgets(self, type_=C.PLUG_TYPE_WID, except_cls=None):
705 """get available widgets plugin infos 705 """get available widgets plugin infos
706 706
707 @param type_(unicode): type of widgets to get 707 @param type_(unicode): type of widgets to get
725 exist and be of the same value in requested plugin info 725 exist and be of the same value in requested plugin info
726 @return (dict, None): found plugin info or None 726 @return (dict, None): found plugin info or None
727 """ 727 """
728 plugins_set = self._getPluginsSet(type_) 728 plugins_set = self._getPluginsSet(type_)
729 for plugin_info in plugins_set: 729 for plugin_info in plugins_set:
730 for k, w in kwargs.iteritems(): 730 for k, w in kwargs.items():
731 try: 731 try:
732 if plugin_info[k] != w: 732 if plugin_info[k] != w:
733 continue 733 continue
734 except KeyError: 734 except KeyError:
735 continue 735 continue
736 return plugin_info 736 return plugin_info
737 737
738 ## widgets handling 738 ## widgets handling
739 739
740 def newWidget(self, widget): 740 def newWidget(self, widget):
741 log.debug(u"new widget created: {}".format(widget)) 741 log.debug("new widget created: {}".format(widget))
742 if isinstance(widget, quick_chat.QuickChat) and widget.type == C.CHAT_GROUP: 742 if isinstance(widget, quick_chat.QuickChat) and widget.type == C.CHAT_GROUP:
743 self.addNote(u"", _(u"room {} has been joined").format(widget.target)) 743 self.addNote("", _("room {} has been joined").format(widget.target))
744 744
745 def switchWidget(self, old, new): 745 def switchWidget(self, old, new):
746 """Replace old widget by new one 746 """Replace old widget by new one
747 747
748 old(CagouWidgetn None): CagouWidget instance or a child 748 old(CagouWidgetn None): CagouWidget instance or a child
759 if isinstance(w, CagouWidget): 759 if isinstance(w, CagouWidget):
760 to_change = w 760 to_change = w
761 break 761 break
762 762
763 if to_change is None: 763 if to_change is None:
764 raise exceptions.InternalError(u"no CagouWidget found when " 764 raise exceptions.InternalError("no CagouWidget found when "
765 u"trying to switch widget") 765 "trying to switch widget")
766 766
767 wrapper = to_change.parent 767 wrapper = to_change.parent
768 while wrapper is not None and not(isinstance(wrapper, widgets_handler.WHWrapper)): 768 while wrapper is not None and not(isinstance(wrapper, widgets_handler.WHWrapper)):
769 wrapper = wrapper.parent 769 wrapper = wrapper.parent
770 770
771 if wrapper is None: 771 if wrapper is None:
772 raise exceptions.InternalError(u"no wrapper found") 772 raise exceptions.InternalError("no wrapper found")
773 773
774 wrapper.changeWidget(new) 774 wrapper.changeWidget(new)
775 self.selected_widget = new 775 self.selected_widget = new
776 776
777 def _addVisibleWidget(self, widget): 777 def _addVisibleWidget(self, widget):
816 if isinstance(widget, quick_widgets.QuickWidget): 816 if isinstance(widget, quick_widgets.QuickWidget):
817 for w in self.widgets.getWidgetInstances(widget): 817 for w in self.widgets.getWidgetInstances(widget):
818 if w.parent is None and w != widget: 818 if w.parent is None and w != widget:
819 to_delete.append(w) 819 to_delete.append(w)
820 for w in to_delete: 820 for w in to_delete:
821 log.debug(u"cleaning widget: {wid}".format(wid=w)) 821 log.debug("cleaning widget: {wid}".format(wid=w))
822 self.widgets.deleteWidget(w) 822 self.widgets.deleteWidget(w)
823 823
824 def getOrClone(self, widget): 824 def getOrClone(self, widget):
825 """Get a QuickWidget if it has not parent set else clone it 825 """Get a QuickWidget if it has not parent set else clone it
826 826
871 # FIXME: Q&D way to get chat plugin, should be replaced by a clean method 871 # FIXME: Q&D way to get chat plugin, should be replaced by a clean method
872 # in host 872 # in host
873 plg_infos = [p for p in self.getPluggedWidgets() 873 plg_infos = [p for p in self.getPluggedWidgets()
874 if action in p['import_name']][0] 874 if action in p['import_name']][0]
875 except IndexError: 875 except IndexError:
876 log.warning(u"No plugin widget found to do {action}".format(action=action)) 876 log.warning("No plugin widget found to do {action}".format(action=action))
877 else: 877 else:
878 factory = plg_infos['factory'] 878 factory = plg_infos['factory']
879 self.switchWidget(None, 879 self.switchWidget(None,
880 factory(plg_infos, target=target, profiles=profiles)) 880 factory(plg_infos, target=target, profiles=profiles))
881 881
883 883
884 def _menusGetCb(self, backend_menus): 884 def _menusGetCb(self, backend_menus):
885 main_menu = self.app.root.root_menus 885 main_menu = self.app.root.root_menus
886 self.menus.addMenus(backend_menus) 886 self.menus.addMenus(backend_menus)
887 self.menus.addMenu(C.MENU_GLOBAL, 887 self.menus.addMenu(C.MENU_GLOBAL,
888 (_(u"Help"), _(u"About")), 888 (_("Help"), _("About")),
889 callback=main_menu.onAbout) 889 callback=main_menu.onAbout)
890 main_menu.update(C.MENU_GLOBAL) 890 main_menu.update(C.MENU_GLOBAL)
891 891
892 ## bridge handlers ## 892 ## bridge handlers ##
893 893
900 for widget in self.widgets.getWidgets(quick_chat.QuickChat, profiles=(profile,)): 900 for widget in self.widgets.getWidgets(quick_chat.QuickChat, profiles=(profile,)):
901 if widget.type == C.CHAT_ONE2ONE and widget.target == bare_jid: 901 if widget.type == C.CHAT_ONE2ONE and widget.target == bare_jid:
902 widget.onOTRState(state, dest_jid, profile) 902 widget.onOTRState(state, dest_jid, profile)
903 903
904 def _debugHandler(self, action, parameters, profile): 904 def _debugHandler(self, action, parameters, profile):
905 if action == u"visible_widgets_dump": 905 if action == "visible_widgets_dump":
906 from pprint import pformat 906 from pprint import pformat
907 log.info(u"Visible widgets dump:\n{data}".format( 907 log.info("Visible widgets dump:\n{data}".format(
908 data=pformat(self._visible_widgets))) 908 data=pformat(self._visible_widgets)))
909 else: 909 else:
910 return super(Cagou, self)._debugHandler(action, parameters, profile) 910 return super(Cagou, self)._debugHandler(action, parameters, profile)
911 911
912 ## misc ## 912 ## misc ##
914 def plugging_profiles(self): 914 def plugging_profiles(self):
915 self.app.root.changeWidget(widgets_handler.WidgetsHandler()) 915 self.app.root.changeWidget(widgets_handler.WidgetsHandler())
916 self.bridge.menusGet("", C.NO_SECURITY_LIMIT, callback=self._menusGetCb) 916 self.bridge.menusGet("", C.NO_SECURITY_LIMIT, callback=self._menusGetCb)
917 917
918 def setPresenceStatus(self, show='', status=None, profile=C.PROF_KEY_NONE): 918 def setPresenceStatus(self, show='', status=None, profile=C.PROF_KEY_NONE):
919 log.info(u"Profile presence status set to {show}/{status}".format(show=show, 919 log.info("Profile presence status set to {show}/{status}".format(show=show,
920 status=status)) 920 status=status))
921 921
922 def errback(self, failure_, title=_('error'), 922 def errback(self, failure_, title=_('error'),
923 message=_(u'error while processing: {msg}')): 923 message=_('error while processing: {msg}')):
924 self.addNote(title, message.format(msg=failure_), level=C.XMLUI_DATA_LVL_WARNING) 924 self.addNote(title, message.format(msg=failure_), level=C.XMLUI_DATA_LVL_WARNING)
925 925
926 def addNote(self, title, message, level=C.XMLUI_DATA_LVL_INFO, symbol=None, 926 def addNote(self, title, message, level=C.XMLUI_DATA_LVL_INFO, symbol=None,
927 action=None): 927 action=None):
928 """add a note (message which disappear) to root widget's header""" 928 """add a note (message which disappear) to root widget's header"""
980 False, 980 False,
981 answer_data) 981 answer_data)
982 ) 982 )
983 self.addNotifWidget(wid) 983 self.addNotifWidget(wid)
984 else: 984 else:
985 log.warning(_(u"unknown dialog type: {dialog_type}").format(dialog_type=type)) 985 log.warning(_("unknown dialog type: {dialog_type}").format(dialog_type=type))
986 986
987 987
988 def desktop_notif(self, message, title=u'', duration=5000): 988 def desktop_notif(self, message, title='', duration=5000):
989 global notification
989 if notification is not None: 990 if notification is not None:
990 try: 991 try:
991 notification.notify(title=title, 992 notification.notify(title=title,
992 message=message, 993 message=message,
993 app_name=C.APP_NAME, 994 app_name=C.APP_NAME,
994 app_icon=self.app.icon, 995 app_icon=self.app.icon,
995 timeout = duration) 996 timeout = duration)
996 except Exception as e: 997 except Exception as e:
997 log.warning(_(u"Can't use notifications, disabling: {msg}").format( 998 log.warning(_("Can't use notifications, disabling: {msg}").format(
998 msg = e)) 999 msg = e))
999 global notification
1000 notification = None 1000 notification = None