comparison frontends/primitivus/primitivus @ 159:2fa58703f1b7

Primitivus: notification bar, first draft - popup queue is now managed - notifications can auto-hide when nothing to show - ctrl-n show next notification Primitivus: ctrl-s allow to temporarily hide a popup Primitivus: cards in card_game now answer to mouse click Primitivus: notification is shown when invalid card is played in card_game Primitivus: SelectableText has now methods get_text and set_text
author Goffi <goffi@goffi.org>
date Wed, 04 Aug 2010 17:57:51 +0800
parents 13888bdb72b6
children b318d2b58887
comparison
equal deleted inserted replaced
158:74aaf230a7c3 159:2fa58703f1b7
55 ('other_nick', 'dark cyan,bold', 'default'), 55 ('other_nick', 'dark cyan,bold', 'default'),
56 ('menubar', 'light gray,bold', 'dark red'), 56 ('menubar', 'light gray,bold', 'dark red'),
57 ('selected_menu', 'light gray,bold', 'dark green'), 57 ('selected_menu', 'light gray,bold', 'dark green'),
58 ('menuitem', 'light gray,bold', 'dark red'), 58 ('menuitem', 'light gray,bold', 'dark red'),
59 ('menuitem_focus', 'light gray,bold', 'dark green'), 59 ('menuitem_focus', 'light gray,bold', 'dark green'),
60 ('notifs', 'black,bold', 'yellow'),
60 ('card_neutral', 'dark gray', 'white', 'standout,underline'), 61 ('card_neutral', 'dark gray', 'white', 'standout,underline'),
61 ('card_neutral_selected', 'dark gray', 'dark green', 'standout,underline'), 62 ('card_neutral_selected', 'dark gray', 'dark green', 'standout,underline'),
62 ('card_special', 'brown', 'white', 'standout,underline'), 63 ('card_special', 'brown', 'white', 'standout,underline'),
63 ('card_special_selected', 'brown', 'dark green', 'standout,underline'), 64 ('card_special_selected', 'brown', 'dark green', 'standout,underline'),
64 ('card_red', 'dark red', 'white', 'standout,underline'), 65 ('card_red', 'dark red', 'white', 'standout,underline'),
78 79
79 class PrimitivusApp(QuickApp): 80 class PrimitivusApp(QuickApp):
80 81
81 def __init__(self): 82 def __init__(self):
82 self.CM = QuickContactManagement() #FIXME: not the best place 83 self.CM = QuickContactManagement() #FIXME: not the best place
83 QuickApp.__init__(self) #XXX: yes it's an unusual place for the constructor of a parent class, but the init order is important 84 QuickApp.__init__(self)
84 85
85 ## main loop setup ## 86 ## main loop setup ##
86 self.main_widget = ProfileManager(self) 87 self.main_widget = ProfileManager(self)
87 self.loop = urwid.MainLoop(self.main_widget, const_PALETTE, event_loop=urwid.GLibEventLoop(), input_filter=self.inputFilter, unhandled_input=self.keyHandler) 88 self.loop = urwid.MainLoop(self.main_widget, const_PALETTE, event_loop=urwid.GLibEventLoop(), input_filter=self.inputFilter, unhandled_input=self.keyHandler)
88 89
89 ##misc setup## 90 ##misc setup##
90 self.chat_wins=ChatList(self) 91 self.chat_wins=ChatList(self)
92 self.notBar = custom_widgets.NotificationBar()
93 urwid.connect_signal(self.notBar,'change',self.onNotification)
94 self.__saved_overlay = None
91 95
92 def debug(self): 96 def debug(self):
93 """convenient method to reset screen and launch pdb""" 97 """convenient method to reset screen and launch pdb"""
94 import os 98 import os
95 os.system('reset') 99 os.system('reset')
109 self.i = 0 113 self.i = 0
110 self.loop.set_alarm_in(0,lambda a,b: self.postInit()) 114 self.loop.set_alarm_in(0,lambda a,b: self.postInit())
111 self.loop.run() 115 self.loop.run()
112 116
113 def inputFilter(self, input, raw): 117 def inputFilter(self, input, raw):
118 if self.__saved_overlay and input != ['ctrl s']:
119 return
114 for i in input: 120 for i in input:
115 if isinstance(i,tuple): 121 if isinstance(i,tuple):
116 if i[0] == 'mouse press': 122 if i[0] == 'mouse press':
117 if i[1] == 4: #Mouse wheel up 123 if i[1] == 4: #Mouse wheel up
118 input[input.index(i)] = 'up' 124 input[input.index(i)] = 'up'
127 self.main_widget.header = self.menu_roller 133 self.main_widget.header = self.menu_roller
128 else: 134 else:
129 self.main_widget.header = None 135 self.main_widget.header = None
130 except AttributeError: 136 except AttributeError:
131 pass 137 pass
138 elif input == 'ctrl n':
139 """User wants to see next notification"""
140 self.notBar.showNext()
141 elif input == 'ctrl s':
142 """User wants to (un)hide overlay window"""
143 if isinstance(self.loop.widget,urwid.Overlay):
144 self.__saved_overlay = self.loop.widget
145 self.loop.widget = self.main_widget
146 else:
147 if self.__saved_overlay:
148 self.loop.widget = self.__saved_overlay
149 self.__saved_overlay = None
150
132 elif input == 'ctrl d' and 'D' in self.bridge.getVersion(): #Debug only for dev versions 151 elif input == 'ctrl d' and 'D' in self.bridge.getVersion(): #Debug only for dev versions
133 self.debug() 152 self.debug()
134 elif input == 'f2': #user wants to (un)hide the contact_list 153 elif input == 'f2': #user wants to (un)hide the contact_list
135 try: 154 try:
136 center_widgets = self.center_part.widget_list 155 center_widgets = self.center_part.widget_list
188 207
189 def __buildMainWidget(self): 208 def __buildMainWidget(self):
190 self.contactList = ContactList(self, self.CM, on_click = self.contactSelected, on_change=lambda w: self.redraw()) 209 self.contactList = ContactList(self, self.CM, on_click = self.contactSelected, on_change=lambda w: self.redraw())
191 #self.center_part = urwid.Columns([('weight',2,self.contactList),('weight',8,Chat('',self))]) 210 #self.center_part = urwid.Columns([('weight',2,self.contactList),('weight',8,Chat('',self))])
192 self.center_part = urwid.Columns([('weight',2,self.contactList), ('weight',8,urwid.Filler(urwid.Text('')))]) 211 self.center_part = urwid.Columns([('weight',2,self.contactList), ('weight',8,urwid.Filler(urwid.Text('')))])
193 editBar = custom_widgets.AdvancedEdit('> ') 212 self.editBar = custom_widgets.AdvancedEdit('> ')
194 urwid.connect_signal(editBar,'click',self.onTextEntered) 213 urwid.connect_signal(self.editBar,'click',self.onTextEntered)
195 self.menu_roller = self.__buildMenuRoller() 214 self.menu_roller = self.__buildMenuRoller()
196 self.main_widget = custom_widgets.FocusFrame(self.center_part, header=self.menu_roller, footer=editBar, focus_part='footer') 215 self.main_widget = custom_widgets.FocusFrame(self.center_part, header=self.menu_roller, footer=self.editBar, focus_part='footer')
197 return self.main_widget 216 return self.main_widget
198 217
199 def plug_profile(self, profile_key='@DEFAULT@'): 218 def plug_profile(self, profile_key='@DEFAULT@'):
200 self.loop.widget = self.__buildMainWidget() 219 self.loop.widget = self.__buildMainWidget()
201 QuickApp.plug_profile(self, profile_key) 220 QuickApp.plug_profile(self, profile_key)
202 221
203 def removePopUp(self, widget=None): 222 def removePopUp(self, widget=None):
223 "Remove current pop-up, and if there is other in queue, show it"
204 self.loop.widget = self.main_widget 224 self.loop.widget = self.main_widget
225 next_popup = self.notBar.getNextPopup()
226 if next_popup:
227 #we still have popup to show, we display it
228 self.showPopUp(next_popup)
205 229
206 def showPopUp(self, pop_up_widget): 230 def showPopUp(self, pop_up_widget):
207 display_widget = urwid.Overlay(pop_up_widget, self.main_widget, 'center', ('relative', 40), 'middle', ('relative', 40)) 231 "Show a pop-up window if possible, else put it in queue"
208 self.loop.widget = display_widget 232 if not isinstance(self.loop.widget,urwid.Overlay):
233 display_widget = urwid.Overlay(pop_up_widget, self.main_widget, 'center', ('relative', 40), 'middle', ('relative', 40))
234 self.loop.widget = display_widget
235 else:
236 self.notBar.addPopUp(pop_up_widget)
237
238 def notify(self, message):
239 self.notBar.addMessage(message)
209 240
210 def contactSelected(self, contact_list): 241 def contactSelected(self, contact_list):
211 contact = contact_list.get_contact() 242 contact = contact_list.get_contact()
212 if contact: 243 if contact:
213 assert(len(self.center_part.widget_list)==2) 244 assert(len(self.center_part.widget_list)==2)
230 return 261 return
231 QuickApp.newMessage(self, from_jid, msg, type, to_jid, profile) 262 QuickApp.newMessage(self, from_jid, msg, type, to_jid, profile)
232 sender = JID(from_jid) 263 sender = JID(from_jid)
233 if JID(self.contactList.selected).short != sender.short: 264 if JID(self.contactList.selected).short != sender.short:
234 self.contactList.putAlert(sender) 265 self.contactList.putAlert(sender)
266
267 def onNotification(self, notBar):
268 """Called when a new notification has been received"""
269 if not isinstance(self.main_widget, custom_widgets.FocusFrame):
270 #if we are not in the main configuration, we ignore the notifications bar
271 return
272 if isinstance(self.main_widget.footer,custom_widgets.AdvancedEdit):
273 if not self.notBar.canHide():
274 #the notification bar is not visible and has usefull informations, we show it
275 pile = urwid.Pile([self.notBar, self.editBar])
276 self.main_widget.footer = pile
277 else:
278 if not isinstance(self.main_widget.footer, urwid.Pile):
279 error(_("INTERNAL ERROR: Unexpected class for main widget's footer"))
280 assert(False)
281 if self.notBar.canHide():
282 #No notification left, we can hide the bar
283 self.main_widget.footer = self.editBar
235 284
236 def actionResult(self, type, id, data): 285 def actionResult(self, type, id, data):
237 if not id in self.current_action_ids: 286 if not id in self.current_action_ids:
238 debug (_('unknown id, ignoring')) 287 debug (_('unknown id, ignoring'))
239 return 288 return