else
More updates to Editor
This commit is contained in:
parent
214b657ead
commit
6f6c8fb5b1
3 changed files with 76 additions and 33 deletions
|
@ -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.
|
105
Editor/editor.py
105
Editor/editor.py
|
@ -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
|
||||
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:
|
||||
# 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
|
||||
|
||||
editor = Editor()
|
||||
class EditorException(Exception):
|
||||
pass
|
||||
|
||||
editor = Editor()
|
||||
editor.start()
|
Binary file not shown.
Loading…
Reference in a new issue