Holger Frey
8 years ago
3 changed files with 193 additions and 25 deletions
@ -1,46 +1,145 @@
@@ -1,46 +1,145 @@
|
||||
import tkinter as tk |
||||
import tkinter.ttk as ttk |
||||
from tkinter import filedialog |
||||
|
||||
import validators |
||||
|
||||
class StatusBar(tk.Frame): |
||||
class StatusPanel(tk.Frame): |
||||
|
||||
def __init__(self, master): |
||||
tk.Frame.__init__(self, master) |
||||
self.label = tk.Label(self, bd=1, relief=tk.SUNKEN, anchor=tk.SW) |
||||
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(self, text): |
||||
def set_text(self, text): |
||||
self.label.config(text=text) |
||||
self.label.update_idletasks() |
||||
|
||||
def clear(self): |
||||
self.label.config(text="") |
||||
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') |
||||
self.listbox.pack(fill=tk.X, ipady=5, ipadx=5) |
||||
self.listbox.insert(0, "HELLO") |
||||
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") |
||||
|
||||
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") |
||||
|
||||
def enable(self): |
||||
self.enable_listbox() |
||||
self.enable_radio_btn() |
||||
|
||||
|
||||
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.quit) |
||||
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.geometry("500x500") |
||||
master.minsize(height=100, width=100) |
||||
master.minsize(height=330, width=200) |
||||
tk.Frame.__init__(self, master) |
||||
self._master = master |
||||
self.pack(fill=tk.BOTH) |
||||
self.status = StatusBar(self.master) |
||||
self.create_widgets() |
||||
self.status_panel = StatusPanel(self) |
||||
self.file_panel = FilePanel(self) |
||||
self.field_panel = FieldPanel(self) |
||||
self.action_panel = ActionPanel(self) |
||||
self.reset() |
||||
|
||||
def create_widgets(self): |
||||
self.btn_files = tk.Button(self, text="Select Files", command=self.selected_files) |
||||
self.btn_files.pack(side=tk.LEFT, pady=5, padx=5) |
||||
self.btn_quit = tk.Button(self, text="Quit", command=self.quit) |
||||
self.btn_quit.pack(side=tk.RIGHT, pady=5, padx=5) |
||||
def reset(self): |
||||
self.field_panel.disable() |
||||
self.action_panel.disable() |
||||
self.file_validator = None |
||||
self.validated_files = None |
||||
|
||||
def selected_files(self): |
||||
def select_files(self): |
||||
self.reset() |
||||
self.file_panel.clear_text() |
||||
opts = { |
||||
'initialdir': '~', |
||||
'filetypes': [('text files', '.txt'), ('python files', '.py')], |
||||
'multiple':True} |
||||
result = tk.filedialog.askopenfilename(**opts) |
||||
print(type(result), ':', result) |
||||
'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 len(self.validated_files) == 0: |
||||
self.reset() |
||||
return |
||||
self.field_panel.enable_radio_btn() |
||||
|
||||
|
||||
|
||||
def quit(self): |
||||
self._master.destroy() |
||||
|
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
import os |
||||
|
||||
from collections import namedtuple |
||||
|
||||
class ValidationError(ValueError): |
||||
pass |
||||
|
||||
Validator = namedtuple('Validator', 'type validate extension') |
||||
DataFile = namedtuple('DataFile', 'path separator') |
||||
|
||||
def validate_stx(lines): |
||||
iterator = iter(lines) |
||||
line = next(iterator) |
||||
if not line.startswith('Report_Format\t2'): |
||||
raise ValidationError('1 Unsupported File;' + line) |
||||
for line in iterator: |
||||
if line.startswith('Probe_Name\t'): |
||||
break |
||||
else: |
||||
raise ValidationError('1 Unsupported File') |
||||
for line in iterator: |
||||
probe_name, rest = line.split('\t', 1) |
||||
separator = ',' if rest.count(',') > rest.count('.') else '.' |
||||
return separator |
||||
else: |
||||
raise ValidationError('No Data Present') |
||||
|
||||
|
||||
def validate_dat(lines): |
||||
iterator = iter(lines) |
||||
if not next(iterator).startswith('Report_Format\t2'): |
||||
raise ValidationError('Unsupported File') |
||||
for line in iterator: |
||||
if line.startswith('Dot_Number\t'): |
||||
break |
||||
else: |
||||
raise ValidationError('Unsupported File') |
||||
for line in iterator: |
||||
probe_name, rest = line.split('\t', 3) |
||||
separator = ',' if rest.count(',') > rest.count('.') else '.' |
||||
return separator |
||||
else: |
||||
raise ValidationError('No Data Present') |
||||
|
||||
def validate_csv(lines): |
||||
pass |
||||
|
||||
validation_map = { |
||||
'.stx': Validator('Signalyse Statistic Files', validate_stx, '.stx'), |
||||
'.dat': Validator('Signalyse Data Files', validate_dat, '.dat'), |
||||
'.csv': Validator('Sensovation Data Files', validate_csv, '.csv') |
||||
} |
||||
|
||||
def guess_validator(unvalidated): |
||||
# get the validation method by examining the first file |
||||
_, extension = os.path.splitext(unvalidated[0]) |
||||
return validation_map.get(extension, None) |
||||
|
||||
def validate_files(unvalidated, selected_validator): |
||||
# get the validation method by examining the first file |
||||
for file_path in unvalidated: |
||||
try: |
||||
with open(file_path, mode='r', encoding='utf-8') as file_handle: |
||||
separator = selected_validator.validate(file_handle) |
||||
yield DataFile(file_path, separator) |
||||
except (IOError, UnicodeError, ValidationError) as e: |
||||
print(e) |
Loading…
Reference in new issue