Last active
September 27, 2021 05:13
Revisions
-
theScottyJam revised this gist
Sep 5, 2021 . 1 changed file with 4 additions and 0 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,8 @@ #!/usr/bin/env python3 # https://superuser.com/a/1251013/57284 # https://gist.github.com/theScottyJam/ae19299c8d71a21c75f2abd96daea9f8 from pathlib import Path import tkinter as tk from tkinter import ttk @@ -46,6 +49,7 @@ def mk_file(template, filename): try: shutil.copy2(src_file, dst_file) os.utime(dst_file) except Exception as e: return str(e) -
theScottyJam revised this gist
Sep 16, 2017 . 1 changed file with 11 additions and 0 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -33,6 +33,7 @@ def main(): window.destroy() def mk_file(template, filename): """ Create a new file using by coping the chosen template to `current directory/filename` """ src_file = TEMPLATES_DIR/template dst_file = target_dir/filename @@ -68,6 +69,7 @@ def __init__(self, templates, on_create_file): self.selected_template = None def show(self): """ Creates and displays the file naming dialog """ self.window = tk.Tk() self.window.style = ttk.Style() self.window.style.theme_use('default') @@ -79,6 +81,7 @@ def show(self): self.window.destroy() def render(self, window): """ Renders the window and attaches event listeners """ self.render_body(window) self.render_buttons(window) @@ -96,6 +99,8 @@ def render(self, window): window.protocol("WM_DELETE_WINDOW", self.close_window) def render_body(self, window): """ Renders the main body of the window, which includes the template choosing box and the filename textbox """ body = ttk.Frame(window) # listbox @@ -130,6 +135,7 @@ def render_body(self, window): self.on_select_template() def render_buttons(self, window): """ Renders the buttons at the bottom of the window """ button_bar = ttk.Frame(window) self.cancel_button = ttk.Button(button_bar, text="Cancel", width=10, command=self.close_window) @@ -140,6 +146,7 @@ def render_buttons(self, window): button_bar.pack() def set_error(self, text): """ Displays some text to the user """ self.err_label.config(text=text) self.textbox.selection_range(0, tk.END) self.error_is_shown = True @@ -148,6 +155,7 @@ def set_error(self, text): # Event listeners def on_textbox_change(self, *args): """ Called when the user changes the file name """ if not self.ingore_textbox_change == True: self.filename_has_changed = True self.err_label.config(text='') @@ -156,6 +164,7 @@ def on_textbox_change(self, *args): self.filename_has_changed = False def on_select_template(self, event=None): """ Called when the user selects a different template """ self.selected_template = self.templates[ int(self.listbox.curselection()[0]) ] if not self.filename_has_changed: self.ingore_textbox_change = True @@ -170,6 +179,7 @@ def select_one_down(self, event): def select_one_up(self, event): self.move_selection(-1) def move_selection(self, amount): """ Changes the template selection. """ cur_selection = self.listbox.curselection()[0] new_selection = int(cur_selection) + amount if new_selection < 0: @@ -185,6 +195,7 @@ def close_window(self, event=None): self.window.quit() def apply_values(self, event=None): """ Usually called with OK is pushed """ message = self.on_create_file(self.selected_template, self.textbox.get()) if message: self.set_error(message) -
theScottyJam created this gist
Sep 16, 2017 .There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,195 @@ #!/usr/bin/env python3 from pathlib import Path import tkinter as tk from tkinter import ttk import os import shutil TEMPLATES_DIR = Path('~/Templates').expanduser() target_dir = None def main(): global target_dir # The following gets the selected item(s) from nautilus. selected = os.environ.get('NAUTILUS_SCRIPT_SELECTED_FILE_PATHS', os.curdir) # We're only going to use the first if multiple are selected. target_dir = Path( selected.split('\n')[0] ).resolve().parent templates = [f.name for f in TEMPLATES_DIR.iterdir()] templates.sort() if templates: prompt = FilenamePrompt(templates, mk_file) prompt.show() else: window = tk.Tk() window.title('Error') label = tk.Label(window, text="Error: You don't have any templates inside ~/Templates") label.grid(row=0) label.pack(padx=10, pady=10) window.protocol("WM_DELETE_WINDOW", window.quit) window.mainloop() window.destroy() def mk_file(template, filename): src_file = TEMPLATES_DIR/template dst_file = target_dir/filename if filename == '': return 'Please provide a file name' if not dst_file.parent.is_dir(): # If the inputed text has a "/" with an non-existant folder before it. return 'That folder does not exist' if dst_file.is_file(): return 'That file already exists' try: shutil.copy2(src_file, dst_file) except Exception as e: return str(e) class FilenamePrompt(): def __init__(self, templates, on_create_file): """ templates is a list of strings that will appear in the menu. on_create_file is what gets called when the user pushes ok. It gets passes the selected template, and the file name the user chose. If an error occures, that error should return as a string that will get shown to the user. Otherwise, None should be returned. """ self.templates = templates self.on_create_file = on_create_file self.filename_has_changed = False # Sets to true as soon as the user alters the content of the textbox. # This can be set to true if this class wants to alter the textbox value without triggering other consequences. self.ingore_textbox_change = False self.error_is_shown = False self.selected_template = None def show(self): self.window = tk.Tk() self.window.style = ttk.Style() self.window.style.theme_use('default') self.window.title('New Document') self.window.resizable(False, False) self.render(self.window) self.window.mainloop() self.window.destroy() def render(self, window): self.render_body(window) self.render_buttons(window) # Tab order self.listbox.lower() self.textbox.lower() self.ok_button.lower() self.cancel_button.lower() # Event listeners window.bind('<Return>', self.apply_values) window.bind('<Escape>', self.close_window) window.bind('<Down>', self.select_one_down) window.bind('<Up>', self.select_one_up) window.protocol("WM_DELETE_WINDOW", self.close_window) def render_body(self, window): body = ttk.Frame(window) # listbox self.listbox = tk.Listbox(window, selectmode=tk.SINGLE, width=40, selectbackground='#8af', exportselection=False) self.listbox.bind('<<ListboxSelect>>', self.on_select_template) self.listbox.pack() for template in self.templates: self.listbox.insert(tk.END, template) # The following auto-resizes the listbox based on the content inside. self.listbox.config(height=0) # textbox ttk.Label(body, text="File name: ").grid(row=0) self.textbox_var = tk.StringVar() self.textbox_var.trace('w', self.on_textbox_change) self.textbox = ttk.Entry(body, textvariable=self.textbox_var) self.textbox.grid(row=0, column=1) body.pack(padx=5, pady=5) # error label err_label_frame = ttk.Frame(window) self.err_label = tk.Label(err_label_frame, fg='#a00') self.err_label.grid(row=0) err_label_frame.pack() # autoselects the first listbox item self.listbox.select_set(0) self.on_select_template() def render_buttons(self, window): button_bar = ttk.Frame(window) self.cancel_button = ttk.Button(button_bar, text="Cancel", width=10, command=self.close_window) self.cancel_button.pack(side=tk.LEFT, padx=5, pady=5) self.ok_button = ttk.Button(button_bar, text="OK", width=10, command=self.apply_values, default=tk.ACTIVE) self.ok_button.pack(side=tk.LEFT, padx=5, pady=5) button_bar.pack() def set_error(self, text): self.err_label.config(text=text) self.textbox.selection_range(0, tk.END) self.error_is_shown = True self.textbox.focus_set() # Event listeners def on_textbox_change(self, *args): if not self.ingore_textbox_change == True: self.filename_has_changed = True self.err_label.config(text='') if self.textbox.get() == '': # We'll allow the textbox content to change if it's currently empty. self.filename_has_changed = False def on_select_template(self, event=None): self.selected_template = self.templates[ int(self.listbox.curselection()[0]) ] if not self.filename_has_changed: self.ingore_textbox_change = True self.textbox_var.set(self.selected_template) self.ingore_textbox_change = False self.textbox.selection_range(0, tk.END) self.window.after_idle(self.textbox.focus) def select_one_down(self, event): self.move_selection(1) def select_one_up(self, event): self.move_selection(-1) def move_selection(self, amount): cur_selection = self.listbox.curselection()[0] new_selection = int(cur_selection) + amount if new_selection < 0: new_selection = 0 if new_selection >= len(self.templates): new_selection = len(self.templates) - 1 self.listbox.selection_clear(cur_selection) self.listbox.select_set(new_selection) self.on_select_template() def close_window(self, event=None): self.window.quit() def apply_values(self, event=None): message = self.on_create_file(self.selected_template, self.textbox.get()) if message: self.set_error(message) return self.window.quit() if __name__ == '__main__': main()