import tkinter as tk import tkinter.ttk as ttk from tkinter import filedialog import validators APP_STATE_1 = 'no valid files selected' APP_STATE_2 = 'no valid fields selected' APP_STATE_3 = 'ok, single files' APP_STATE_4 = 'ok, multiple files' class StatusPanel(tk.Frame): def __init__(self, parent): tk.Frame.__init__(self, parent.master) self._parent = parent self.label = tk.Label(self, bd=1, relief=tk.SUNKEN, anchor=tk.S) self.label.pack(fill=tk.X) self.pack(side=tk.BOTTOM, fill=tk.X) def set_text(self, text): self.label.config(text=text) self.label.update_idletasks() def clear_text(self): self.set_text('') class FilePanel(tk.Frame): def __init__(self, parent): tk.Frame.__init__(self, parent.master) self._parent = parent self.btn_files = tk.Button(self, text="Select Files", command=self._parent.select_files) self.btn_files.pack(pady=5, padx=5) self.label = tk.Label(self, anchor=tk.SW) self.label.pack(fill=tk.X, pady=5, padx=5) ttk.Separator(self, orient=tk.HORIZONTAL).pack(side=tk.BOTTOM, fill=tk.X) self.pack(side=tk.TOP, fill=tk.X) def set_text(self, text): self.label.config(text=text) self.label.update_idletasks() def clear_text(self): self.set_text('') class FieldPanel(tk.Frame): def __init__(self, parent): tk.Frame.__init__(self, parent.master) self._parent = parent self.is_single = tk.BooleanVar() self.is_single.set(True) self.rbtn_single = tk.Radiobutton( self, text='single excel files', variable=self.is_single, value=True, command=self.disable_listbox) self.rbtn_combine = tk.Radiobutton( self, text='one combined excel file', variable=self.is_single, value=False, command=self.enable_listbox) self.rbtn_single.pack(anchor=tk.W) self.rbtn_combine.pack(anchor=tk.W) self.listbox = tk.Listbox(self, selectmode=tk.MULTIPLE, activestyle='none', height=19) self.listbox.pack(fill=tk.X, ipady=5, ipadx=5, ) self.listbox.bind('<>', self._parent.toggle_run_button) self.pack(side=tk.TOP, fill=tk.X) def disable_radio_btn(self): self.rbtn_single.config(state="disabled") self.rbtn_combine.config(state="disabled") def disable_listbox(self): self.listbox.config(state="disabled") self._parent.toggle_run_button() def disable(self): self.disable_listbox() self.disable_radio_btn() def enable_radio_btn(self): self.rbtn_single.config(state="normal") self.rbtn_combine.config(state="normal") self.is_single.set(True) def enable_listbox(self): self.listbox.config(state="normal") self._parent.toggle_run_button() def enable(self): self.enable_listbox() self.enable_radio_btn() def set_listbox_content(self, choices, selection): self.enable_listbox() current = self.listbox.size() self.listbox.selection_clear(0, current) self.listbox.delete(0,current) for i, element in enumerate(choices): self.listbox.insert(tk.END, element) if element in selection: self.listbox.selection_set(i) self.disable_listbox() class ActionPanel(tk.Frame): def __init__(self, parent): tk.Frame.__init__(self, parent.master) self._parent = parent self.btn_go = tk.Button(self, text="GO!", command=self._parent.convert_files) self.btn_go.pack(side=tk.LEFT, pady=5, padx=5) self.btn_quit = tk.Button(self, text="Quit", command=self._parent.quit) self.btn_quit.pack(side=tk.RIGHT, pady=5, padx=5) self.pack(side=tk.BOTTOM, fill=tk.X) def disable(self): self.btn_go.config(state='disabled') def enable(self): self.btn_go.config(state='active') class Application(tk.Frame): def __init__(self, master): master.minsize(height=330, width=300) tk.Frame.__init__(self, master) self._master = master self.pack(fill=tk.BOTH) self.file_validator = None self.validated_files = None self.status_panel = StatusPanel(self) self.file_panel = FilePanel(self) self.field_panel = FieldPanel(self) self.action_panel = ActionPanel(self) self.reset() def reset(self): self.status_panel.clear_text() self.field_panel.disable() self.action_panel.disable() self.file_validator = None self.validated_files = None def select_files(self): self.reset() self.file_panel.clear_text() opts = { 'initialdir': '~/_signalyse test', 'filetypes': [('Signalyse Statistics', '.stx'), ('Signalyse Data', '.dat'), ('Sensovation Data', '.csv')], 'multiple': True} file_selection = tk.filedialog.askopenfilename(**opts) if not isinstance(file_selection, tuple) or len(file_selection) == 0: return self.file_validator = validators.guess_validator(file_selection) if self.file_validator is None: return self.validated_files = [f for f in validators.validate_files(file_selection, self.file_validator)] status = '%d of %d valid %s files found' % (len(self.validated_files), len(file_selection), self.file_validator.type) self.file_panel.set_text(status) if self._state == APP_STATE_1: return self.reset() self.field_panel.enable_radio_btn() self.field_panel.set_listbox_content(self.file_validator.data_fields, self.file_validator.defaults) self.toggle_run_button() def toggle_run_button(self, event=None): self.action_panel.disable() if self._state in (APP_STATE_3, APP_STATE_4): self.action_panel.enable() def quit(self): self._master.destroy() def convert_files(self): state = self._state if state not in (APP_STATE_3, APP_STATE_4): return self.reset() i = len(self.validated_files) if state == APP_STATE_3: text = 'Converting %d data files to %d excel files ...' % (i, i) self.status_panel.set_text(text) self._convert_to_single_files() else: text = 'Combining %d data files into one excel file ...' % i self.status_panel.set_text(text) self._combine_data_files() self.status_panel.set_text(text + ' Done') @property def _state(self): c = self.field_panel.rbtn_single.config() if not self.validated_files or c['state'] == 'disabled': return APP_STATE_1 elif self.field_panel.is_single.get(): return APP_STATE_3 elif self.field_panel.listbox.curselection(): return APP_STATE_4 else: return APP_STATE_2 def _convert_to_single_files(self): pass def _combine_data_files(self): pass