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
==========
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.
For now, it's just a tkinter toy.
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.

View file

@ -5,7 +5,8 @@ import random
class Editor:
def __init__(self):
self.WINDOWS_BADCHARS = '\\/?:*"><|'
#self.WINDOWS_BADCHARS = '\\/?:*"><|'
self.windowtitle = 'Editor'
self.sql = sqlite3.connect('textfiles.db')
self.cur = self.sql.cursor()
@ -23,6 +24,7 @@ class Editor:
self.maximum_title = 64
self.t = tkinter.Tk()
self.t.title(self.windowtitle)
self.w = 450
self.h = 350
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.t.geometry(self.geometrystring)
self.reserved_filenames = ['random', 'list']
self.has_filenames_changed = True
self.entities = []
self.filename = None
self.gui_build_fileloader()
def start(self):
self.gui_build_fileloader()
self.t.mainloop()
def annihilate(self):
for x in self.entities:
try:
x.grid_forget()
x.pack_forget()
except:
pass
x.destroy()
while len(self.entities) > 0:
self.entities[0].destroy()
del self.entities[0]
def gui_build_fileloader(self, *b):
self.annihilate()
self.t.title(self.windowtitle)
###
self.frame_fileloader = tkinter.Frame(self.t)
self.entities.append(self.frame_fileloader)
#
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.focus_set()
self.entry_filename.bind("<Return>", self.loadfile_smart)
self.entities.append(self.entry_filename)
#
self.label_filename = tkinter.Label(self.frame_fileloader, font=self.font_large, text='.txt')
self.label_filename.grid(row=0, column=3)
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.grid(row=1, column=1, pady=10)
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.place(x=width/2, y=(height/2)-10, anchor='center')
def gui_build_editor(self, filetext, *b):
self.annihilate()
###
self.frame_toolbar = tkinter.Frame(self.t)
self.frame_toolbar.pack()
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.grid(row=0, column=0)
self.entities.append(self.button_back)
#
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.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.entities.append(self.button_save)
#
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.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.pack(expand=True, fill='both')
self.text_editor.focus_set()
self.text_editor.bind('<Control-s>', self.savefile_smart)
self.text_editor.bind('<Control-w>', self.gui_build_fileloader)
self.entities.append(self.text_editor)
self.entities.append(self.scrollbar_editor)
###
def savefile_smart(self, *b):
try:
filetext = self.text_editor.get('0.0', 'end')
self.savefile(self.filename, filetext)
filesize = len(filetext) - 1
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:
# text editor does not exist for some reason
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]
# Text widget seems to add \n to the end at all times
# So remove it.
if self.filename is None:
return False
filesize = len(filetext)
namesize = len(filename)
if filesize > self.maximum_characters:
diff = filesize-self.maximum_characters
print('File exceeds maximum character limit. %d / %d (-%d)' % (filesize, self.maximum_characters, diff))
return False
sizeerror = 'too big: %d / %d (-%d)' % (filesize, self.maximum_characters, diff)
print('File exceeds maximum character limit. %s' % sizeerror)
raise EditorException(sizeerror)
elif namesize > self.maximum_title:
diff = namesize - self.maximum_title
print('Filename exceeds maximum character limit: %d / %d (-%d)' % (namesize, self.maximum_title, diff))
return False
sizeerror = '%d / %d (-%d)' % (namesize, self.maximum_title, diff)
print('Filename exceeds maximum character limit: %s' % sizeerror)
raise EditorException('Filename too big: %s' % sizeerror)
sha = self.sha(filename)
self.cur.execute('SELECT * FROM textfiles WHERE id=?', [sha])
@ -133,12 +152,19 @@ class Editor:
if filesize == 0:
print('Deleting %s' % filename)
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:
if fetch:
self.cur.execute('UPDATE textfiles SET filename=?, filetext=? WHERE id=?', [filename, filetext, sha])
else:
self.cur.execute('INSERT INTO textfiles VALUES(?, ?, ?)', [sha, filename, filetext])
print('Wrote %s: %s' % (filename, self.filesizestring(filesize)))
self.has_filenames_changed = True
self.sql.commit()
return True
@ -157,11 +183,15 @@ class Editor:
filetext = self.loadfile(filename)
if filetext is not None:
self.gui_build_editor(filetext)
self.t.title(filename)
return
def loadfile(self, filename):
if filename == 'random':
filename = self.loadrandom()
if filename == 'list':
self.generate_listfile()
filename = filename.replace(' ', '_')
if len(filename) < 1:
return None
if len(filename) > self.maximum_title:
@ -185,6 +215,17 @@ class Editor:
return ""
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):
for bad in self.WINDOWS_BADCHARS:
s = s.replace(bad, '')
@ -197,4 +238,8 @@ class Editor:
sha = sha.hexdigest()
return sha
class EditorException(Exception):
pass
editor = Editor()
editor.start()

Binary file not shown.