Advertisement
maroph

text_editor4.py

Dec 9th, 2019
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.83 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. # Tested with
  4. # Python 3.8.0 on Windows 10 (mainly)
  5. # Python 3.7.3 on Raspbian 10.2
  6. #
  7. # Known bug on Raspbian with Python 3.7.3
  8. # (works under Windows 10 with Python 3.8.0):
  9. # Start the app, click Help/About and than exit the app.
  10. # After closing the info box the app thinks, there is unsaved text
  11. # in the editor.
  12. # I have the same effect also in some other situations on Raspbian 10.2
  13. # and not on Windows 10
  14. # IMHO: this seems to be a problem in the underlying TK implementation.
  15.  
  16. from guizero import App, Box, Combo, MenuBar, Slider, Text, TextBox
  17. from pathlib import Path
  18.  
  19. app_name = 'Simple Text Editor'
  20. app_version = '4'
  21. app_verdate = '09-DEC-2019'
  22.  
  23. app_version_string = app_name + ' v' + app_version + ' (' + app_verdate + ')'
  24.  
  25. app = App(title=app_name, bg='slategray', width=800, height=600)
  26.  
  27. # remember the last folder in use, default: . - the current folder
  28. folder = '.'
  29. # True: no unsaved text in the editor
  30. text_saved = True
  31. # True: dark mode is enabled
  32. dark_mode = False
  33.  
  34.  
  35. # get the current folder ins use from the complete file path, stored in file_name_text_box.value
  36. def get_folder():
  37.     global file_name_text_box
  38.  
  39.     name = file_name_text_box.value
  40.     if name is None:
  41.         return '.'
  42.     elif len(name) == 0:
  43.         return '.'
  44.     else:
  45.         return Path(name).parent
  46.  
  47.  
  48. # show some version information
  49. def about_editor():
  50.     global app_version_string
  51.  
  52.     app.info('About', app_version_string + "\nA simple Python guizero based text editor")
  53.     return
  54.  
  55.  
  56. # open a file, selected in a file selector box, in the editor and
  57. # store the file name in file_name_text_box.value
  58. def open_file():
  59.     global text_saved
  60.     global app
  61.     global editor
  62.     global file_name_text_box
  63.  
  64.     if not text_saved:
  65.         resp = app.yesno('Warning', 'You have unsaved text in the editor - proceed?')
  66.         if not resp:
  67.             return
  68.  
  69.     f = get_folder()
  70.     name = app.select_file('Open file', folder=f, filetypes=[["Text files", "*.txt"], ["Markdown files", "*.md"]], save=False)
  71.     if name is None:
  72.         text_saved = True
  73.         return
  74.     if len(name) == 0:
  75.         text_saved = True
  76.         return
  77.  
  78.     try:
  79.         with open(name, "r") as f:
  80.             editor.value = f.read()
  81.     except Exception as e:
  82.         app.error('Read Error', 'Error in reading file: ' + str(e))
  83.         return
  84.  
  85.     file_name_text_box.value= name
  86.     text_saved = True
  87.  
  88.  
  89. # save the text in the editor the the file name, stored in file_name_text_box.value
  90. def save_file():
  91.     global text_saved
  92.     global file_name_text_box
  93.  
  94.     name = file_name_text_box.value
  95.     if name is None:
  96.         save_as_file()
  97.         return
  98.     if len(name) == 0:
  99.         save_as_file()
  100.         return
  101.  
  102.     try:
  103.         with open(name, "w") as f:
  104.             f.write(editor.value)
  105.     except Exception as e:
  106.         app.error('Write Error', 'Error in reading file: ' + str(e))
  107.         return
  108.  
  109.     text_saved = True
  110.  
  111.  
  112. # save the text in the editor into  a file, selected in a file selector box and
  113. # store the name in file_name_text_box.value
  114. def save_as_file():
  115.     global text_saved
  116.     global app
  117.     global file_name_text_box
  118.  
  119.     f = get_folder()
  120.  
  121.     name = app.select_file('Save file', folder=f, filetypes=[["Text files", "*.txt"], ["Markdown files", "*.md"]], save=True)
  122.     if name is None:
  123.         return
  124.     if len(name) == 0:
  125.         return
  126.  
  127.     try:
  128.         with open(name, "w") as f:
  129.             f.write(editor.value)
  130.     except Exception as e:
  131.         app.error('Write Error', 'Error in reading file: ' + str(e))
  132.         return
  133.  
  134.     file_name_text_box.value = name
  135.     text_saved = True
  136.  
  137.  
  138. # remove all text from the editor and set the file name to '' in file_name_text_box.value
  139. def new_file():
  140.     global text_saved
  141.     global app
  142.     global file_name_text_box
  143.     global editor
  144.     global char_count_text_box
  145.  
  146.     if not text_saved:
  147.         resp = app.yesno('Warning', 'You have unsaved text in the editor - proceed?')
  148.         if not resp:
  149.             return
  150.  
  151.     file_name_text_box.value = ''
  152.     editor.value = ''
  153.     char_count_text_box.value = '0'
  154.     text_saved = True
  155.  
  156.  
  157. # close the editor app
  158. def exit_app():
  159.     global text_saved
  160.     global app
  161.  
  162.     if not text_saved:
  163.         resp = app.yesno('Warning', 'You have unsaved text in the editor - proceed?')
  164.         if not resp:
  165.             return
  166.     app.destroy()
  167.  
  168.  
  169. def change_font():
  170.     global editor
  171.     global font
  172.  
  173.     editor.font = font.value
  174.  
  175.  
  176. def change_text_color():
  177.     global editor
  178.     global text_color
  179.  
  180.     editor.text_color = text_color.value
  181.  
  182.  
  183. def change_text_size():
  184.     global editor
  185.     global size
  186.  
  187.     editor.text_size = size.value
  188.     editor.resize(1, 1)
  189.     editor.resize("fill", "fill")
  190.  
  191.  
  192. # get number of characters in the editor
  193. # observation: even if editor.value is '' the len(editor.value) is 1
  194. def get_number_of_text_chars():
  195.     global editor
  196.  
  197.     chars = len(editor.value)
  198.     if chars > 0:
  199.         return chars -1
  200.     else:
  201.         return 0
  202.  
  203.  
  204. # wil be called by any change in the editor's text area
  205. def count_text_chars():
  206.     global text_saved
  207.     global char_count_text_box
  208.  
  209.     char_count_text_box.value = get_number_of_text_chars()
  210.     text_saved = False
  211.  
  212.  
  213. def toggle_status_line():
  214.     global status_box
  215.  
  216.     if status_box.visible:
  217.         status_box.visible = False
  218.     else:
  219.         status_box.visible = True
  220.  
  221.  
  222. def toggle_char_count():
  223.     global char_count_box
  224.  
  225.     if char_count_box.visible:
  226.         char_count_box.visible = False
  227.     else:
  228.         char_count_box.visible = True
  229.  
  230.  
  231. def toggle_preferences_controls():
  232.     global preferences_controls
  233.  
  234.     if preferences_controls.visible:
  235.         preferences_controls.visible = False
  236.     else:
  237.         preferences_controls.visible = True
  238.  
  239.  
  240. def toggle_dark_mode():
  241.     global dark_mode
  242.     global editor
  243.     global text_color
  244.  
  245.     if dark_mode:
  246.         dark_mode = False
  247.         editor.bg = 'white'
  248.         editor.text_color = text_color.value
  249.         text_color.visible = True
  250.     else:
  251.         dark_mode = True
  252.         editor.bg = '#0f0f0f'
  253.         editor.text_color = 'white'
  254.         text_color.visible = False
  255.  
  256.  
  257. # same handling as if clicked o 'File/Exit'
  258. app.when_closed = exit_app
  259.  
  260. # create the app's menu bar and the related menu items
  261. menubar = MenuBar(app,
  262.                   # menu bar
  263.                   toplevel=["File", "Options", "Help"],
  264.                   # menu items
  265.                   options=[
  266.                       # File
  267.                       [
  268.                           # items in File
  269.                           ["New", new_file],
  270.                           ["Open...", open_file],
  271.                           ["Save", save_file],
  272.                           ["Save as...", save_as_file],
  273.                           ["Exit", exit_app]
  274.                       ],
  275.                       # Options
  276.                       [
  277.                           # items in Options
  278.                           ["Toggle status line", toggle_status_line],
  279.                           ["Toggle char count", toggle_char_count],
  280.                           ["Toggle preferences", toggle_preferences_controls],
  281.                           ["Toggle dark mode", toggle_dark_mode]
  282.                       ],
  283.                       # Help
  284.                       [
  285.                           # items in Help
  286.                           ["About", about_editor]
  287.                       ]
  288.                   ])
  289.  
  290.  
  291. # create the status line, copntains: file name and character count
  292. status_box = Box(app, width='fill', border=True)
  293. file_name_label = Text(status_box, text='File: ', align="left")
  294. file_name_text_box = TextBox(status_box, text='', width='fill', align="left", enabled=False)
  295. file_name_text_box.bg = 'white'
  296. char_count_box = Box(status_box, width='fill', border=True)
  297. char_count_text_box = TextBox(char_count_box, text='', width='20', align="right", enabled=False)
  298. char_count_label = Text(char_count_box, text='Chars: ', align="right")
  299. char_count_text_box.value = '0'
  300. text_saved = True
  301.  
  302.  
  303. # create the preferences line
  304. preferences_controls = Box(app, align="top", width="fill", border=True)
  305. font = Combo(preferences_controls, options=["Courier", "Times New Roman", "Verdana"], align="left", selected='Courier', command=change_font)
  306. size = Slider(preferences_controls,  align="left", command=change_text_size, start=10, end=18)
  307. size.value = 10
  308. text_color = Combo(preferences_controls, options=['black', 'blue', 'red', 'magenta'], align="left", selected='black', command=change_text_color)
  309.  
  310.  
  311. # create the editor
  312. editor = TextBox(app, multiline=True, height="fill", width="fill", text='', scrollbar=True)
  313. editor.bg = 'white'
  314. editor.font = font.value
  315. editor.text_size = size.value
  316. editor.text_color = text_color.value
  317. editor.update_command(count_text_chars)
  318. editor.focus()
  319.  
  320. app.display()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement