More updates to Editor
This commit is contained in:
Voussoir 2015-03-04 21:52:03 -08:00
parent 214b657ead
commit 6f6c8fb5b1
3 changed files with 76 additions and 33 deletions

View file

@ -1,6 +1,4 @@
Editor Editor
========== ==========
A neat idea that I would one day like to make into a website or something. Users read and write text files simply by choosing the file name. If it exists, the text is returned to them for editing. If it does not, it will be created when they press Save. No logins and no file security. Since it's using a database instead of actual txt files, there are no filename character restrictions, only a maximum title length for sanity's sake. A neat idea that would make for a fun website. Users read and write text files by choosing the file name. If it exists, the text is returned to them for editing. If it does not, it will be created when they press Save. No logins and no file security. Since it's using a database instead of actual txt files, there are no filename character restrictions, only a maximum title length and a couple self-imposed rules for sanity's sake.
For now, it's just a tkinter toy.

View file

@ -5,7 +5,8 @@ import random
class Editor: class Editor:
def __init__(self): def __init__(self):
self.WINDOWS_BADCHARS = '\\/?:*"><|' #self.WINDOWS_BADCHARS = '\\/?:*"><|'
self.windowtitle = 'Editor'
self.sql = sqlite3.connect('textfiles.db') self.sql = sqlite3.connect('textfiles.db')
self.cur = self.sql.cursor() self.cur = self.sql.cursor()
@ -23,6 +24,7 @@ class Editor:
self.maximum_title = 64 self.maximum_title = 64
self.t = tkinter.Tk() self.t = tkinter.Tk()
self.t.title(self.windowtitle)
self.w = 450 self.w = 450
self.h = 350 self.h = 350
self.screenwidth = self.t.winfo_screenwidth() self.screenwidth = self.t.winfo_screenwidth()
@ -34,98 +36,115 @@ class Editor:
self.geometrystring = '%dx%d+%d+%d' % (self.windowwidth, self.windowheight, self.windowx, self.windowy) self.geometrystring = '%dx%d+%d+%d' % (self.windowwidth, self.windowheight, self.windowx, self.windowy)
self.t.geometry(self.geometrystring) self.t.geometry(self.geometrystring)
self.reserved_filenames = ['random', 'list']
self.has_filenames_changed = True
self.entities = [] self.entities = []
self.filename = None self.filename = None
self.gui_build_fileloader()
def start(self):
self.gui_build_fileloader()
self.t.mainloop() self.t.mainloop()
def annihilate(self): def annihilate(self):
for x in self.entities: while len(self.entities) > 0:
try: self.entities[0].destroy()
x.grid_forget() del self.entities[0]
x.pack_forget()
except:
pass
x.destroy()
def gui_build_fileloader(self, *b): def gui_build_fileloader(self, *b):
self.annihilate() self.annihilate()
self.t.title(self.windowtitle)
###
self.frame_fileloader = tkinter.Frame(self.t) self.frame_fileloader = tkinter.Frame(self.t)
self.entities.append(self.frame_fileloader) self.entities.append(self.frame_fileloader)
#
self.entry_filename = tkinter.Entry(self.frame_fileloader, font=self.font_large, justify='right') self.entry_filename = tkinter.Entry(self.frame_fileloader, font=self.font_large, justify='right')
self.entry_filename.grid(row=0, column=0, columnspan=3) self.entry_filename.grid(row=0, column=0, columnspan=3)
self.entry_filename.focus_set() self.entry_filename.focus_set()
self.entry_filename.bind("<Return>", self.loadfile_smart) self.entry_filename.bind("<Return>", self.loadfile_smart)
self.entities.append(self.entry_filename) self.entities.append(self.entry_filename)
#
self.label_filename = tkinter.Label(self.frame_fileloader, font=self.font_large, text='.txt') self.label_filename = tkinter.Label(self.frame_fileloader, font=self.font_large, text='.txt')
self.label_filename.grid(row=0, column=3) self.label_filename.grid(row=0, column=3)
self.entities.append(self.label_filename) self.entities.append(self.label_filename)
#
self.button_fileloader = tkinter.Button(self.frame_fileloader, font=self.font_large, text='Load', command=self.loadfile_smart) self.button_fileloader = tkinter.Button(self.frame_fileloader, font=self.font_large, text='Load', command=self.loadfile_smart)
self.button_fileloader.grid(row=1, column=1, pady=10) self.button_fileloader.grid(row=1, column=1, pady=10)
self.entities.append(self.button_fileloader) self.entities.append(self.button_fileloader)
width = self.t.winfo_width() #
height = self.t.winfo_height()
if min([width, height]) < 20:
width = self.w
height = self.h
self.frame_fileloader.pack(expand=True, anchor='center') self.frame_fileloader.pack(expand=True, anchor='center')
#self.frame_fileloader.place(x=width/2, y=(height/2)-10, anchor='center') #self.frame_fileloader.place(x=width/2, y=(height/2)-10, anchor='center')
def gui_build_editor(self, filetext, *b): def gui_build_editor(self, filetext, *b):
self.annihilate() self.annihilate()
###
self.frame_toolbar = tkinter.Frame(self.t) self.frame_toolbar = tkinter.Frame(self.t)
self.frame_toolbar.pack() self.frame_toolbar.pack()
self.entities.append(self.frame_toolbar) self.entities.append(self.frame_toolbar)
#
self.button_back = tkinter.Button(self.frame_toolbar, text='back', command=self.gui_build_fileloader, font=self.font_small) self.button_back = tkinter.Button(self.frame_toolbar, text='back', command=self.gui_build_fileloader, font=self.font_small)
self.button_back.grid(row=0, column=0) self.button_back.grid(row=0, column=0)
self.entities.append(self.button_back) self.entities.append(self.button_back)
#
self.label_filename = tkinter.Label(self.frame_toolbar, text=self.filename, font=self.font_small) self.label_filename = tkinter.Label(self.frame_toolbar, text=self.filename, font=self.font_small)
self.label_filename.grid(row=0, column=1, padx=20) self.label_filename.grid(row=0, column=1, padx=70)
self.entities.append(self.label_filename) self.entities.append(self.label_filename)
#
self.button_save = tkinter.Button(self.frame_toolbar, text='save', command=self.savefile_smart, font=self.font_small) self.button_save = tkinter.Button(self.frame_toolbar, text='save', command=self.savefile_smart, font=self.font_small)
self.button_save.grid(row=0, column=2) self.button_save.grid(row=0, column=2)
self.entities.append(self.button_save) self.entities.append(self.button_save)
#
self.label_filesize = tkinter.Label(self.frame_toolbar, text='', font=self.font_small) self.label_filesize = tkinter.Label(self.frame_toolbar, text='', font=self.font_small)
self.label_filesize.grid(row=1, column=0, columnspan=10) self.label_filesize.grid(row=1, column=0, columnspan=3)
self.entities.append(self.label_filesize) self.entities.append(self.label_filesize)
self.text_editor = tkinter.Text(self.t, wrap='word', font=self.font_med) #
self.scrollbar_editor = tkinter.Scrollbar(self.t)
self.scrollbar_editor.pack(side='right', fill='y')
self.text_editor = tkinter.Text(self.t, wrap='word', font=self.font_med, yscrollcommand=self.scrollbar_editor.set)
self.scrollbar_editor.configure(command=self.text_editor.yview)
self.text_editor.insert('end', filetext) self.text_editor.insert('end', filetext)
self.text_editor.pack(expand=True, fill='both') self.text_editor.pack(expand=True, fill='both')
self.text_editor.focus_set() self.text_editor.focus_set()
self.text_editor.bind('<Control-s>', self.savefile_smart) self.text_editor.bind('<Control-s>', self.savefile_smart)
self.text_editor.bind('<Control-w>', self.gui_build_fileloader) self.text_editor.bind('<Control-w>', self.gui_build_fileloader)
self.entities.append(self.text_editor) self.entities.append(self.text_editor)
self.entities.append(self.scrollbar_editor)
###
def savefile_smart(self, *b): def savefile_smart(self, *b):
try: try:
filetext = self.text_editor.get('0.0', 'end') filetext = self.text_editor.get('0.0', 'end')
self.savefile(self.filename, filetext)
filesize = len(filetext) - 1 filesize = len(filetext) - 1
self.label_filesize.configure(text=self.filesizestring(filesize)) try:
self.savefile(self.filename, filetext)
self.label_filesize.configure(text=self.filesizestring(filesize))
except EditorException as ee:
self.label_filesize.configure(text=ee.args[0])
except NameError: except NameError:
# text editor does not exist for some reason # text editor does not exist for some reason
return return
def savefile(self, filename, filetext): def savefile(self, filename, filetext, permissions=False):
if filename is None:
raise EditorException('Please enter a filename')
if permissions is False and filename in self.reserved_filenames:
print('This file is restricted. You are not permitted to modify it.')
raise EditorException("Restricted file")
filename = filename.replace(' ', '_')
filetext = filetext[:-1] filetext = filetext[:-1]
# Text widget seems to add \n to the end at all times # Text widget seems to add \n to the end at all times
# So remove it. # So remove it.
if self.filename is None:
return False
filesize = len(filetext) filesize = len(filetext)
namesize = len(filename) namesize = len(filename)
if filesize > self.maximum_characters: if filesize > self.maximum_characters:
diff = filesize-self.maximum_characters diff = filesize-self.maximum_characters
print('File exceeds maximum character limit. %d / %d (-%d)' % (filesize, self.maximum_characters, diff)) sizeerror = 'too big: %d / %d (-%d)' % (filesize, self.maximum_characters, diff)
return False print('File exceeds maximum character limit. %s' % sizeerror)
raise EditorException(sizeerror)
elif namesize > self.maximum_title: elif namesize > self.maximum_title:
diff = namesize - self.maximum_title diff = namesize - self.maximum_title
print('Filename exceeds maximum character limit: %d / %d (-%d)' % (namesize, self.maximum_title, diff)) sizeerror = '%d / %d (-%d)' % (namesize, self.maximum_title, diff)
return False print('Filename exceeds maximum character limit: %s' % sizeerror)
raise EditorException('Filename too big: %s' % sizeerror)
sha = self.sha(filename) sha = self.sha(filename)
self.cur.execute('SELECT * FROM textfiles WHERE id=?', [sha]) self.cur.execute('SELECT * FROM textfiles WHERE id=?', [sha])
@ -133,12 +152,19 @@ class Editor:
if filesize == 0: if filesize == 0:
print('Deleting %s' % filename) print('Deleting %s' % filename)
self.cur.execute('DELETE FROM textfiles WHERE id=?', [sha]) self.cur.execute('DELETE FROM textfiles WHERE id=?', [sha])
if fetch:
# If fetch: It previously existed and is now deleted
# If not fetch: User just created this workspace, and
# is now closing it without adding anything
# so nothing has changed on disk.
self.has_filenames_changed = True
else: else:
if fetch: if fetch:
self.cur.execute('UPDATE textfiles SET filename=?, filetext=? WHERE id=?', [filename, filetext, sha]) self.cur.execute('UPDATE textfiles SET filename=?, filetext=? WHERE id=?', [filename, filetext, sha])
else: else:
self.cur.execute('INSERT INTO textfiles VALUES(?, ?, ?)', [sha, filename, filetext]) self.cur.execute('INSERT INTO textfiles VALUES(?, ?, ?)', [sha, filename, filetext])
print('Wrote %s: %s' % (filename, self.filesizestring(filesize))) print('Wrote %s: %s' % (filename, self.filesizestring(filesize)))
self.has_filenames_changed = True
self.sql.commit() self.sql.commit()
return True return True
@ -157,11 +183,15 @@ class Editor:
filetext = self.loadfile(filename) filetext = self.loadfile(filename)
if filetext is not None: if filetext is not None:
self.gui_build_editor(filetext) self.gui_build_editor(filetext)
self.t.title(filename)
return return
def loadfile(self, filename): def loadfile(self, filename):
if filename == 'random': if filename == 'random':
filename = self.loadrandom() filename = self.loadrandom()
if filename == 'list':
self.generate_listfile()
filename = filename.replace(' ', '_')
if len(filename) < 1: if len(filename) < 1:
return None return None
if len(filename) > self.maximum_title: if len(filename) > self.maximum_title:
@ -185,6 +215,17 @@ class Editor:
return "" return ""
return random.choice(fetch)[1] return random.choice(fetch)[1]
def generate_listfile(self):
if self.has_filenames_changed:
print('Refreshing list file')
self.cur.execute('SELECT * FROM textfiles')
fetch = self.cur.fetchall()
fetch = [x[1] for x in fetch]
fetch.sort(key=lambda x:x.lower())
fetch = '\n'.join(fetch)
self.savefile('list', fetch, permissions=True)
self.has_filenames_changed = False
def strip_to_filename(self, s): def strip_to_filename(self, s):
for bad in self.WINDOWS_BADCHARS: for bad in self.WINDOWS_BADCHARS:
s = s.replace(bad, '') s = s.replace(bad, '')
@ -197,4 +238,8 @@ class Editor:
sha = sha.hexdigest() sha = sha.hexdigest()
return sha return sha
class EditorException(Exception):
pass
editor = Editor() editor = Editor()
editor.start()

Binary file not shown.