comparison urwid_satext/sat_widgets.py @ 143:144bdf877d21

python 3 port (using 2to3)
author Goffi <goffi@goffi.org>
date Tue, 13 Aug 2019 08:55:41 +0200
parents 88722f920b3c
children bfab04d0a745
comparison
equal deleted inserted replaced
142:2855123621a0 143:144bdf877d21
17 # You should have received a copy of the GNU Lesser General Public License 17 # You should have received a copy of the GNU Lesser General Public License
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 urwid 20 import urwid
21 import logging as log 21 import logging as log
22 import encodings
23 utf8decode = lambda s: encodings.codecs.utf_8_decode(s)[0]
24 22
25 import uuid 23 import uuid
26 24
27 import collections 25 import collections
28 26
119 117
120 def __init__(self, *args, **kwargs): 118 def __init__(self, *args, **kwargs):
121 """Same args than Edit.__init__ with an additional keyword arg 'hidden_char' 119 """Same args than Edit.__init__ with an additional keyword arg 'hidden_char'
122 @param hidden_char: char to show instead of what is actually entered: default '*' 120 @param hidden_char: char to show instead of what is actually entered: default '*'
123 """ 121 """
124 self.hidden_char=kwargs['hidden_char'] if kwargs.has_key('hidden_char') else '*' 122 self.hidden_char=kwargs['hidden_char'] if 'hidden_char' in kwargs else '*'
125 self.__real_text='' 123 self.__real_text=''
126 super(Password, self).__init__(*args, **kwargs) 124 super(Password, self).__init__(*args, **kwargs)
127 125
128 def set_edit_text(self, text): 126 def set_edit_text(self, text):
129 self.__real_text = text 127 self.__real_text = text
193 191
194 class SurroundedText(urwid.Widget): 192 class SurroundedText(urwid.Widget):
195 """Text centered on a repeated character (like a Divider, but with a text in the center)""" 193 """Text centered on a repeated character (like a Divider, but with a text in the center)"""
196 _sizing = frozenset(['flow']) 194 _sizing = frozenset(['flow'])
197 195
198 def __init__(self,text,car=utf8decode('─')): 196 def __init__(self,text,car='─'):
199 self.text=text 197 self.text=text
200 self.car=car 198 self.car=car
201 199
202 def rows(self,size,focus=False): 200 def rows(self,size,focus=False):
203 return self.display_widget(size, focus).rows(size, focus) 201 return self.display_widget(size, focus).rows(size, focus)
205 def render(self, size, focus=False): 203 def render(self, size, focus=False):
206 return self.display_widget(size, focus).render(size, focus) 204 return self.display_widget(size, focus).render(size, focus)
207 205
208 def display_widget(self, size, focus): 206 def display_widget(self, size, focus):
209 (maxcol,) = size 207 (maxcol,) = size
210 middle = (maxcol-len(self.text))/2 208 middle = (maxcol-len(self.text))//2
211 render_text = middle * self.car + self.text + (maxcol - len(self.text) - middle) * self.car 209 render_text = middle * self.car + self.text + (maxcol - len(self.text) - middle) * self.car
212 return urwid.Text(render_text) 210 return urwid.Text(render_text)
213 211
214 212
215 class AlwaysSelectableText(urwid.WidgetWrap): 213 class AlwaysSelectableText(urwid.WidgetWrap):
231 urwid.WidgetWrap.__init__(self, urwid.Text("",align=align)) 229 urwid.WidgetWrap.__init__(self, urwid.Text("",align=align))
232 self.setSelectedText(selected_text) 230 self.setSelectedText(selected_text)
233 self.setState(selected) 231 self.setState(selected)
234 232
235 def getValue(self): 233 def getValue(self):
236 if isinstance(self.text,basestring): 234 if isinstance(self.text,str):
237 return self.text 235 return self.text
238 list_attr = self.text if isinstance(self.text, list) else [self.text] 236 list_attr = self.text if isinstance(self.text, list) else [self.text]
239 txt = "" 237 txt = ""
240 for attr in list_attr: 238 for attr in list_attr:
241 if isinstance(attr,tuple): 239 if isinstance(attr,tuple):
369 def set_label(self, label): 367 def set_label(self, label):
370 self.label = label 368 self.label = label
371 self.set_text([self.left_border, label, self.right_border]) 369 self.set_text([self.left_border, label, self.right_border])
372 370
373 371
374 class ListOption(unicode): 372 class ListOption(str):
375 """Unicode which manage label and value 373 """Unicode which manage label and value
376 374
377 This class similar to unicode, but which make the difference between value and label 375 This class similar to unicode, but which make the difference between value and label
378 label is show when use as unicode, the .value attribute contain the actual value 376 label is show when use as unicode, the .value attribute contain the actual value
379 Can be initialised with: 377 Can be initialised with:
383 """ 381 """
384 382
385 def __new__(cls, option): 383 def __new__(cls, option):
386 if (isinstance(option, cls)): 384 if (isinstance(option, cls)):
387 return option 385 return option
388 elif isinstance(option, basestring): 386 elif isinstance(option, str):
389 value = label = option 387 value = label = option
390 elif (isinstance(option, tuple) and len(option) == 2): 388 elif (isinstance(option, tuple) and len(option) == 2):
391 value, label = option 389 value, label = option
392 else: 390 else:
393 raise NotImplementedError 391 raise NotImplementedError
515 def __setitem__(self, i, y): 513 def __setitem__(self, i, y):
516 parent = super(SimpleListWalkerWithCb, self) 514 parent = super(SimpleListWalkerWithCb, self)
517 self.__cbSingle(y, self._on_new) 515 self.__cbSingle(y, self._on_new)
518 to_delete = parent.__getitem__(i) 516 to_delete = parent.__getitem__(i)
519 self.__cbSingle(to_delete, self._on_delete) 517 self.__cbSingle(to_delete, self._on_delete)
520 return parent.__setitem__(self, i, y) 518 return parent.__setitem__(i, y)
521 519
522 def __setslice__(self, i, j, y): 520 def __setslice__(self, i, j, y):
523 parent = super(SimpleListWalkerWithCb, self) 521 parent = super(SimpleListWalkerWithCb, self)
524 items_to_delete = parent.__getslice__(i,j) 522 items_to_delete = parent.__getslice__(i,j)
525 self.__cbMulti(items_to_delete, self._on_delete) 523 self.__cbMulti(items_to_delete, self._on_delete)
817 if widget == pop_up_widget: 815 if widget == pop_up_widget:
818 del self.notifs[idx] 816 del self.notifs[idx]
819 self._modQueue() 817 self._modQueue()
820 return 818 return
821 819
822 raise ValueError(u"trying to remove an unknown pop_up_widget") 820 raise ValueError("trying to remove an unknown pop_up_widget")
823 821
824 def addMessage(self, message): 822 def addMessage(self, message):
825 "Add a message to the notificatio bar" 823 "Add a message to the notificatio bar"
826 if not self.message.get_text(): 824 if not self.message.get_text():
827 self.message.set_text(('notifs',message)) 825 self.message.set_text(('notifs',message))
956 self.save_bottom = None 954 self.save_bottom = None
957 955
958 return self._w.base_widget.keypress(size, key) 956 return self._w.base_widget.keypress(size, key)
959 957
960 def checkShortcuts(self, key): 958 def checkShortcuts(self, key):
961 for shortcut in self.shortcuts.keys(): 959 for shortcut in list(self.shortcuts.keys()):
962 if key == shortcut: 960 if key == shortcut:
963 category, item, callback = self.shortcuts[shortcut] 961 category, item, callback = self.shortcuts[shortcut]
964 callback((category, item)) 962 callback((category, item))
965 return key 963 return key
966 964
968 """Create the category if new and add a menu item (if item is not None). 966 """Create the category if new and add a menu item (if item is not None).
969 967
970 @param category: category of the menu (e.g. File/Edit) 968 @param category: category of the menu (e.g. File/Edit)
971 @param item: menu item (e.g. new/close/about) 969 @param item: menu item (e.g. new/close/about)
972 @callback: method to call when item is selected""" 970 @callback: method to call when item is selected"""
973 if not category in self.menu.keys(): 971 if not category in list(self.menu.keys()):
974 self.menu_keys.append(category) 972 self.menu_keys.append(category)
975 self.menu[category] = [] 973 self.menu[category] = []
976 button = CustomButton(('menubar',category), self.onCategoryClick, 974 button = CustomButton(('menubar',category), self.onCategoryClick,
977 left_border = ('menubar',"[ "), 975 left_border = ('menubar',"[ "),
978 right_border = ('menubar'," ]")) 976 right_border = ('menubar'," ]"))
979 self._w.base_widget.addWidget(button,button.getSize()) 977 self._w.base_widget.addWidget(button,button.getSize())
980 if not item: 978 if not item:
981 return 979 return
982 self.menu[category].append((item, callback)) 980 self.menu[category].append((item, callback))
983 if shortcut: 981 if shortcut:
984 assert(shortcut not in self.shortcuts.keys()) 982 assert(shortcut not in list(self.shortcuts.keys()))
985 self.shortcuts[shortcut] = (category, item, callback) 983 self.shortcuts[shortcut] = (category, item, callback)
986 984
987 def onItemClick(self, widget): 985 def onItemClick(self, widget):
988 category = self._w.base_widget.getSelected().get_label() 986 category = self._w.base_widget.getSelected().get_label()
989 item = widget.getValue() 987 item = widget.getValue()
1031 if self.selected is None: 1029 if self.selected is None:
1032 self.columns.contents[0] = (urwid.Text(''), ('given', 0, False)) 1030 self.columns.contents[0] = (urwid.Text(''), ('given', 0, False))
1033 self.columns.contents[1] = (urwid.Text(''), ('weight', 1, False)) 1031 self.columns.contents[1] = (urwid.Text(''), ('weight', 1, False))
1034 else: 1032 else:
1035 menu_item = self.menu_items[self.selected] 1033 menu_item = self.menu_items[self.selected]
1036 name_txt = u'\u21c9 ' + menu_item.name + u' \u21c7 ' 1034 name_txt = '\u21c9 ' + menu_item.name + ' \u21c7 '
1037 current_name = ClickableText(name_txt) 1035 current_name = ClickableText(name_txt)
1038 name_len = len(name_txt) 1036 name_len = len(name_txt)
1039 current_menu = menu_item.widget 1037 current_menu = menu_item.widget
1040 current_menu.setOrigX(name_len) 1038 current_menu.setOrigX(name_len)
1041 self.columns.contents[0] = (current_name, ('given', name_len, False)) 1039 self.columns.contents[0] = (current_name, ('given', name_len, False))
1042 self.columns.contents[1] = (current_menu, ('weight', 1, False)) 1040 self.columns.contents[1] = (current_menu, ('weight', 1, False))
1043 1041
1044 def keypress(self, size, key): 1042 def keypress(self, size, key):
1045 menu_ids = self.menu_items.keys() 1043 menu_ids = list(self.menu_items.keys())
1046 try: 1044 try:
1047 idx = menu_ids.index(self.selected) 1045 idx = menu_ids.index(self.selected)
1048 except ValueError: 1046 except ValueError:
1049 return super(MenuRoller, self).keypress(size, key) 1047 return super(MenuRoller, self).keypress(size, key)
1050 1048
1074 @param name: name of the menu to add, it name already exists, menu is not added 1072 @param name: name of the menu to add, it name already exists, menu is not added
1075 @param widget: instance of Menu 1073 @param widget: instance of Menu
1076 @param menu_id: id to use of this menu, or None to generate 1074 @param menu_id: id to use of this menu, or None to generate
1077 @return: menu_id 1075 @return: menu_id
1078 """ 1076 """
1079 names = {menu_item.name: id_ for id_, menu_item in self.menu_items.iteritems()} 1077 names = {menu_item.name: id_ for id_, menu_item in self.menu_items.items()}
1080 1078
1081 if name not in names: 1079 if name not in names:
1082 id_ = menu_id or str(uuid.uuid4()) 1080 id_ = menu_id or str(uuid.uuid4())
1083 if id_ in self.menu_items: 1081 if id_ in self.menu_items:
1084 raise ValueError('Conflict: the id [{}] is already used'.format(id_)) 1082 raise ValueError('Conflict: the id [{}] is already used'.format(id_))
1109 1107
1110 def removeMenu(self, menu_id): 1108 def removeMenu(self, menu_id):
1111 del self.menu_items[menu_id] 1109 del self.menu_items[menu_id]
1112 if self.selected == menu_id: 1110 if self.selected == menu_id:
1113 try: 1111 try:
1114 self.selected = self.menu_items.iterkeys().next() 1112 self.selected = next(iter(self.menu_items.keys()))
1115 except StopIteration: 1113 except StopIteration:
1116 self.selected = None 1114 self.selected = None
1117 self._showSelected() 1115 self._showSelected()
1118 1116
1119 def checkShortcuts(self, key): 1117 def checkShortcuts(self, key):
1120 for menu_item in self.menu_items.values(): 1118 for menu_item in list(self.menu_items.values()):
1121 key = menu_item.widget.checkShortcuts(key) 1119 key = menu_item.widget.checkShortcuts(key)
1122 return key 1120 return key
1123 1121
1124 1122
1125 ## DIALOGS ## 1123 ## DIALOGS ##
1140 self.buttons['yes'] = urwid.Button(_("Yes"), kwargs.get('yes_cb'), kwargs.get('yes_value')) 1138 self.buttons['yes'] = urwid.Button(_("Yes"), kwargs.get('yes_cb'), kwargs.get('yes_value'))
1141 self.buttons['no'] = urwid.Button(_("No"), kwargs.get('no_cb'), kwargs.get('no_value')) 1139 self.buttons['no'] = urwid.Button(_("No"), kwargs.get('no_cb'), kwargs.get('no_value'))
1142 if "OK" in style: 1140 if "OK" in style:
1143 self.buttons['ok'] = urwid.Button(_("Ok"), kwargs.get('ok_cb'), kwargs.get('ok_value')) 1141 self.buttons['ok'] = urwid.Button(_("Ok"), kwargs.get('ok_cb'), kwargs.get('ok_value'))
1144 if self.buttons: 1142 if self.buttons:
1145 buttons_flow = urwid.GridFlow(self.buttons.values(), max([len(button.get_label()) for button in self.buttons.itervalues()])+4, 1, 1, 'center') 1143 buttons_flow = urwid.GridFlow(list(self.buttons.values()), max([len(button.get_label()) for button in self.buttons.values()])+4, 1, 1, 'center')
1146 body_content = urwid.SimpleListWalker(widgets_lst) 1144 body_content = urwid.SimpleListWalker(widgets_lst)
1147 frame_body = UnselectableListBox(body_content) 1145 frame_body = UnselectableListBox(body_content)
1148 frame = FocusFrame(frame_body, frame_header, buttons_flow if self.buttons else None, 'footer' if self.buttons else 'body') 1146 frame = FocusFrame(frame_body, frame_header, buttons_flow if self.buttons else None, 'footer' if self.buttons else 'body')
1149 decorated_frame = urwid.LineBox(frame) 1147 decorated_frame = urwid.LineBox(frame)
1150 urwid.WidgetWrap.__init__(self, decorated_frame) 1148 urwid.WidgetWrap.__init__(self, decorated_frame)
1328 for width,widget in self.widget_list[start_wid:end_wid+1]: 1326 for width,widget in self.widget_list[start_wid:end_wid+1]:
1329 _focus = idx == self.focus_column and focus 1327 _focus = idx == self.focus_column and focus
1330 render.append((widget.render((width,),_focus),False,_focus,width)) 1328 render.append((widget.render((width,),_focus),False,_focus,width))
1331 idx+=1 1329 idx+=1
1332 if _prev: 1330 if _prev:
1333 render.insert(0,(urwid.Text([u"◀"]).render((1,),False),False,False,1)) 1331 render.insert(0,(urwid.Text(["◀"]).render((1,),False),False,False,1))
1334 if _next: 1332 if _next:
1335 render.append((urwid.Text([u"▶"],align='right').render((1+cols_left,),False),False,False,1+cols_left)) 1333 render.append((urwid.Text(["▶"],align='right').render((1+cols_left,),False),False,False,1+cols_left))
1336 else: 1334 else:
1337 render.append((urwid.SolidCanvas(" "*cols_left, size[0], 1),False,False,cols_left)) 1335 render.append((urwid.SolidCanvas(" "*cols_left, size[0], 1),False,False,cols_left))
1338 1336
1339 return urwid.CanvasJoin(render) 1337 return urwid.CanvasJoin(render)
1340 1338
1426 1424
1427 def __init__(self): 1425 def __init__(self):
1428 self._current_tab = None 1426 self._current_tab = None
1429 self._buttons_cont = ColumnsRoller() 1427 self._buttons_cont = ColumnsRoller()
1430 self.tabs = [] 1428 self.tabs = []
1431 self._frame = FocusFrame(urwid.Filler(urwid.Text('')),urwid.Pile([self._buttons_cont,urwid.Divider(u"─")])) 1429 self._frame = FocusFrame(urwid.Filler(urwid.Text('')),urwid.Pile([self._buttons_cont,urwid.Divider("─")]))
1432 urwid.WidgetWrap.__init__(self, self._frame) 1430 urwid.WidgetWrap.__init__(self, self._frame)
1433 1431
1434 def keypress(self, size, key): 1432 def keypress(self, size, key):
1435 return self._w.keypress(size,key) 1433 return self._w.keypress(size,key)
1436 1434
1674 top_columns = self._w.widget_list[0] 1672 top_columns = self._w.widget_list[0]
1675 top_columns.widget_list[1] = label_widget 1673 top_columns.widget_list[1] = label_widget
1676 1674
1677 1675
1678 class VerticalSeparator(urwid.WidgetDecoration, urwid.WidgetWrap): 1676 class VerticalSeparator(urwid.WidgetDecoration, urwid.WidgetWrap):
1679 def __init__(self, original_widget, left_char = u"│", right_char = ''): 1677 def __init__(self, original_widget, left_char = "│", right_char = ''):
1680 """Draw a separator on left and/or right of original_widget.""" 1678 """Draw a separator on left and/or right of original_widget."""
1681 1679
1682 widgets = [original_widget] 1680 widgets = [original_widget]
1683 if left_char: 1681 if left_char:
1684 widgets.insert(0, ('fixed', 1, urwid.SolidFill(left_char))) 1682 widgets.insert(0, ('fixed', 1, urwid.SolidFill(left_char)))