Advertisement
Guest User

Untitled

a guest
May 21st, 2019
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.60 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # coding: UTF-8
  3.  
  4. # code extracted from nigiri
  5. # Got running on current version and Python3
  6.  
  7. import os
  8. import datetime
  9. import sys
  10. import traceback
  11. import re
  12. import logging
  13. import locale
  14.  
  15. import urwid
  16. from urwid import MetaSignals
  17.  
  18.  
  19. class ExtendedListBox(urwid.ListBox):
  20. """
  21. Listbow widget with embeded autoscroll
  22. """
  23.  
  24. __metaclass__ = urwid.MetaSignals
  25. signals = ["set_auto_scroll"]
  26.  
  27.  
  28. def set_auto_scroll(self, switch):
  29. if type(switch) != bool:
  30. return
  31. self._auto_scroll = switch
  32. urwid.emit_signal(self, "set_auto_scroll", switch)
  33.  
  34.  
  35. auto_scroll = property(lambda s: s._auto_scroll, set_auto_scroll)
  36.  
  37.  
  38. def __init__(self, body):
  39. urwid.ListBox.__init__(self, body)
  40. self.auto_scroll = True
  41.  
  42.  
  43. def switch_body(self, body):
  44. if self.body:
  45. urwid.disconnect_signal(body, "modified", self._invalidate)
  46.  
  47. self.body = body
  48. self._invalidate()
  49.  
  50. urwid.connect_signal(body, "modified", self._invalidate)
  51.  
  52.  
  53. def keypress(self, size, key):
  54. urwid.ListBox.keypress(self, size, key)
  55.  
  56. if key in ("page up", "page down"):
  57. logging.debug("focus = %d, len = %d" % (self.get_focus()[1], len(self.body)))
  58. if self.get_focus()[1] == len(self.body)-1:
  59. self.auto_scroll = True
  60. else:
  61. self.auto_scroll = False
  62. logging.debug("auto_scroll = %s" % (self.auto_scroll))
  63.  
  64.  
  65. def scroll_to_bottom(self):
  66. logging.debug("current_focus = %s, len(self.body) = %d" % (self.get_focus()[1], len(self.body)))
  67.  
  68. if self.auto_scroll:
  69. # at bottom -> scroll down
  70. self.set_focus(len(self.body)-1)
  71.  
  72.  
  73.  
  74. """
  75. -------context-------
  76. | --inner context---- |
  77. || HEADER ||
  78. || ||
  79. || BODY ||
  80. || ||
  81. || DIVIDER ||
  82. | ------------------- |
  83. | FOOTER |
  84. ---------------------
  85.  
  86. inner context = context.body
  87. context.body.body = BODY
  88. context.body.header = HEADER
  89. context.body.footer = DIVIDER
  90. context.footer = FOOTER
  91.  
  92. HEADER = Notice line (urwid.Text)
  93. BODY = Extended ListBox
  94. DIVIDER = Divider with information (urwid.Text)
  95. FOOTER = Input line (Ext. Edit)
  96. """
  97.  
  98.  
  99. class MainWindow(object):
  100.  
  101. __metaclass__ = MetaSignals
  102. signals = ["quit","keypress"]
  103.  
  104. _palette = [
  105. ('divider','black','dark cyan', 'standout'),
  106. ('text','light gray', 'default'),
  107. ('bold_text', 'light gray', 'default', 'bold'),
  108. ("body", "text"),
  109. ("footer", "text"),
  110. ("header", "text"),
  111. ]
  112.  
  113. for type, bg in (
  114. ("div_fg_", "dark cyan"),
  115. ("", "default")):
  116. for name, color in (
  117. ("red","dark red"),
  118. ("blue", "dark blue"),
  119. ("green", "dark green"),
  120. ("yellow", "yellow"),
  121. ("magenta", "dark magenta"),
  122. ("gray", "light gray"),
  123. ("white", "white"),
  124. ("black", "black")):
  125. _palette.append( (type + name, color, bg) )
  126.  
  127.  
  128. def __init__(self, sender="1234567890"):
  129. self.shall_quit = False
  130. self.sender = sender
  131.  
  132.  
  133. def main(self):
  134. """
  135. Entry point to start UI
  136. """
  137.  
  138. self.ui = urwid.raw_display.Screen()
  139. self.ui.register_palette(self._palette)
  140. self.build_interface()
  141. self.ui.run_wrapper(self.run)
  142.  
  143.  
  144. def run(self):
  145. """
  146. Setup input handler, invalidate handler to
  147. automatically redraw the interface if needed.
  148.  
  149. Start mainloop.
  150. """
  151.  
  152. # I don't know what the callbacks are for yet,
  153. # it's a code taken from the nigiri project
  154. def input_cb(key):
  155. if self.shall_quit:
  156. raise urwid.ExitMainLoop
  157. self.keypress(self.size, key)
  158.  
  159. self.size = self.ui.get_cols_rows()
  160.  
  161. self.main_loop = urwid.MainLoop(
  162. self.context,
  163. screen=self.ui,
  164. handle_mouse=False,
  165. unhandled_input=input_cb,
  166. )
  167.  
  168. def call_redraw(*x):
  169. self.draw_interface()
  170. invalidate.locked = False
  171. return True
  172.  
  173. inv = urwid.canvas.CanvasCache.invalidate
  174.  
  175. def invalidate (cls, *a, **k):
  176. inv(*a, **k)
  177.  
  178. if not invalidate.locked:
  179. invalidate.locked = True
  180. self.main_loop.set_alarm_in(0, call_redraw)
  181.  
  182. invalidate.locked = False
  183. urwid.canvas.CanvasCache.invalidate = classmethod(invalidate)
  184.  
  185. try:
  186. self.main_loop.run()
  187. except KeyboardInterrupt:
  188. self.quit()
  189.  
  190.  
  191. def quit(self, exit=True):
  192. """
  193. Stops the ui, exits the application (if exit=True)
  194. """
  195. urwid.emit_signal(self, "quit")
  196.  
  197. self.shall_quit = True
  198.  
  199. if exit:
  200. sys.exit(0)
  201.  
  202.  
  203. def build_interface(self):
  204. """
  205. Call the widget methods to build the UI
  206. """
  207.  
  208. self.header = urwid.Text("Chat")
  209. self.footer = urwid.Edit("> ")
  210. self.divider = urwid.Text("Initializing.")
  211.  
  212. self.generic_output_walker = urwid.SimpleListWalker([])
  213. self.body = ExtendedListBox(
  214. self.generic_output_walker)
  215.  
  216.  
  217. self.header = urwid.AttrWrap(self.header, "divider")
  218. self.footer = urwid.AttrWrap(self.footer, "footer")
  219. self.divider = urwid.AttrWrap(self.divider, "divider")
  220. self.body = urwid.AttrWrap(self.body, "body")
  221.  
  222. self.footer.set_wrap_mode("space")
  223.  
  224. main_frame = urwid.Frame(self.body,
  225. header=self.header,
  226. footer=self.divider)
  227.  
  228. self.context = urwid.Frame(main_frame, footer=self.footer)
  229.  
  230. self.divider.set_text(("divider",
  231. ("Send message:")))
  232.  
  233. self.context.set_focus("footer")
  234.  
  235.  
  236. def draw_interface(self):
  237. self.main_loop.draw_screen()
  238.  
  239.  
  240. def keypress(self, size, key):
  241. """
  242. Handle user inputs
  243. """
  244.  
  245. urwid.emit_signal(self, "keypress", size, key)
  246.  
  247. # scroll the top panel
  248. if key in ("page up","page down"):
  249. self.body.keypress (size, key)
  250.  
  251. # resize the main windows
  252. elif key == "window resize":
  253. self.size = self.ui.get_cols_rows()
  254.  
  255. elif key in ("ctrl d", 'ctrl c'):
  256. self.quit()
  257.  
  258. elif key == "enter":
  259. # Parse data or (if parse failed)
  260. # send it to the current world
  261. text = self.footer.get_edit_text()
  262.  
  263. self.footer.set_edit_text(" "*len(text))
  264. self.footer.set_edit_text("")
  265.  
  266. if text in ('quit', 'q'):
  267. self.quit()
  268.  
  269. if text.strip():
  270. self.print_sent_message(text)
  271. self.print_received_message('Answer')
  272.  
  273. else:
  274. self.context.keypress (size, key)
  275.  
  276.  
  277. def print_sent_message(self, text):
  278. """
  279. Print a received message
  280. """
  281.  
  282. self.print_text('[%s] You:' % self.get_time())
  283. self.print_text(text)
  284.  
  285.  
  286. def print_received_message(self, text):
  287. """
  288. Print a sent message
  289. """
  290.  
  291. header = urwid.Text('[%s] System:' % self.get_time())
  292. header.set_align_mode('right')
  293. self.print_text(header)
  294. text = urwid.Text(text)
  295. text.set_align_mode('right')
  296. self.print_text(text)
  297.  
  298.  
  299. def print_text(self, text):
  300. """
  301. Print the given text in the _current_ window
  302. and scroll to the bottom.
  303. You can pass a Text object or a string
  304. """
  305.  
  306. walker = self.generic_output_walker
  307.  
  308. if not isinstance(text, urwid.Text):
  309. text = urwid.Text(text)
  310.  
  311. walker.append(text)
  312.  
  313. self.body.scroll_to_bottom()
  314.  
  315.  
  316. def get_time(self):
  317. """
  318. Return formated current datetime
  319. """
  320. return datetime.datetime.now().strftime('%H:%M:%S')
  321.  
  322.  
  323. def except_hook(extype, exobj, extb, manual=False):
  324. if not manual:
  325. try:
  326. main_window.quit(exit=False)
  327. except NameError:
  328. pass
  329.  
  330. message = _("An error occured:\n%(divider)s\n%(traceback)s\n"\
  331. "%(exception)s\n%(divider)s" % {
  332. "divider": 20*"-",
  333. "traceback": "".join(traceback.format_tb(extb)),
  334. "exception": extype.__name__+": "+str(exobj)
  335. })
  336.  
  337. logging.error(message)
  338.  
  339. print >> sys.stderr, message
  340.  
  341.  
  342. def setup_logging():
  343. """ set the path of the logfile to tekka.logfile config
  344. value and create it (including path) if needed.
  345. After that, add a logging handler for exceptions
  346. which reports exceptions catched by the logger
  347. to the tekka_excepthook. (DBus uses this)
  348. """
  349. try:
  350. class ExceptionHandler(logging.Handler):
  351. """ handler for exceptions caught with logging.error.
  352. dump those exceptions to the exception handler.
  353. """
  354. def emit(self, record):
  355. if record.exc_info:
  356. except_hook(*record.exc_info)
  357.  
  358. logfile = '/tmp/chat.log'
  359. logdir = os.path.dirname(logfile)
  360.  
  361. if not os.path.exists(logdir):
  362. os.makedirs(logdir)
  363.  
  364. logging.basicConfig(filename=logfile, level=logging.DEBUG,
  365. filemode="w")
  366.  
  367. logging.getLogger("").addHandler(ExceptionHandler())
  368.  
  369. except BaseException, e:
  370. print >> sys.stderr, "Logging init error: %s" % (e)
  371.  
  372.  
  373. if __name__ == "__main__":
  374. setup_logging()
  375.  
  376. main_window = MainWindow()
  377.  
  378. sys.excepthook = except_hook
  379.  
  380. main_window.main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement