From 13cdd95e27401ee0befef75da4e34ce0e6e0447f Mon Sep 17 00:00:00 2001 From: Manning Date: Tue, 16 Jul 2024 14:52:18 -0400 Subject: [PATCH 01/14] User interface for inputting variables --- aviary/variable_info/variables.py | 4 +- user_input.py | 225 ++++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 user_input.py diff --git a/aviary/variable_info/variables.py b/aviary/variable_info/variables.py index d2d31cfc6..9af80b45d 100644 --- a/aviary/variable_info/variables.py +++ b/aviary/variable_info/variables.py @@ -155,7 +155,7 @@ class Design: FINENESS = 'aircraft:design:fineness' FIXED_EQUIPMENT_MASS = 'aircraft:design:fixed_equipment_mass' FIXED_USEFUL_LOAD = 'aircraft:design:fixed_useful_load' - IJEFF = 'ijeff' + IJEFF = 'aircraft:design:ijeff' LAMINAR_FLOW_LOWER = 'aircraft:design:laminar_flow_lower' LAMINAR_FLOW_UPPER = 'aircraft:design:laminar_flow_upper' @@ -237,7 +237,7 @@ class Engine: PROPELLER_DIAMETER = 'aircraft:engine:propeller_diameter' PROPELLER_INTEGRATED_LIFT_COEFFICIENT = \ 'aircraft:engine:propeller_integrated_lift_coefficient' - PROPELLER_TIP_MACH_MAX = 'propeller_tip_mach_max' + PROPELLER_TIP_MACH_MAX = 'aircraft:engine:propeller_tip_mach_max' PROPELLER_TIP_SPEED_MAX = 'aircraft:engine:propeller_tip_speed_max' PYLON_FACTOR = 'aircraft:engine:pylon_factor' REFERENCE_DIAMETER = 'aircraft:engine:reference_diameter' diff --git a/user_input.py b/user_input.py new file mode 100644 index 000000000..3ae8daefb --- /dev/null +++ b/user_input.py @@ -0,0 +1,225 @@ +import numpy as np +import csv +from tkinter import * +import aviary.api as av +from copy import deepcopy +import math +import tkinter as tk +import tkinter.ttk as ttk +data = deepcopy(av.CoreMetaData) +list_values = list(data.values()) +list_keys = list(data.keys()) +list_len = len(list_values) +root = Tk() +wid=1200 +hei=800 +root.geometry("%dx%d" % (wid,hei)) +root.title("Model Aircraft Input") + +headers=[] +name_each_subhead = [] +entries_per_subhead = [] +old_subhead ='' +for key in list_keys: + if ':' in key: + subhead = key.split(':')[1] + header=key.split(':')[0] + if subhead == old_subhead: + entries_per_subhead[-1] += 1 + else: + entries_per_subhead.append(1) + name_each_subhead.append(subhead) + headers.append(header) + old_subhead = subhead + else: + entries_per_subhead.append(1) + name_each_subhead.append(key) + headers.append('dynamic') +rows_per_subhead=[] +compound_subheaders=[] +v=0 +for num in entries_per_subhead: + rows = math.ceil(num/4) + rows_per_subhead.append(rows) + compound_subheaders.append(v) + v+=1 +compound_data_rows=[0] +for i,nums in enumerate(rows_per_subhead): + val=sum(rows_per_subhead[:i+1]) + compound_data_rows.append(val) + if len(compound_data_rows)==87: + break +compound_data_entries=[] +for i, nums in enumerate(entries_per_subhead): + val = sum(entries_per_subhead[:i+1]) + compound_data_entries.append(val) +index_list=[] +number = 0 +mini_list=[0] +for num in compound_data_entries: + for i in range(number,num): + if number < num-1: + number +=1 + mini_list.append(number) + index_list.append(mini_list) + mini_list=[] + +class DoubleScrolledFrame: + """ + https://gist.github.com/novel-yet-trivial/2841b7b640bba48928200ff979204115 + """ + def __init__(self, master, **kwargs): + width = wid + height = hei + self.outer = tk.Frame(master, **kwargs) + + self.vsb = ttk.Scrollbar(self.outer, orient=tk.VERTICAL) + self.vsb.grid(row=0, column=1, sticky='ns') + self.hsb = ttk.Scrollbar(self.outer, orient=tk.HORIZONTAL) + self.hsb.grid(row=1, column=0, sticky='ew') + self.canvas = tk.Canvas(self.outer, highlightthickness=0, width=width, height=height) + self.canvas.grid(row=0, column=0, sticky='nsew') + self.outer.rowconfigure(0, weight=1) + self.outer.columnconfigure(0, weight=1) + self.canvas['yscrollcommand'] = self.vsb.set + self.canvas['xscrollcommand'] = self.hsb.set + # mouse scroll does not seem to work with just "bind"; You have + # to use "bind_all". Therefore to use multiple windows you have + # to bind_all in the current widget + self.canvas.bind("", self._bind_mouse) + self.canvas.bind("", self._unbind_mouse) + self.vsb['command'] = self.canvas.yview + self.hsb['command'] = self.canvas.xview + + self.inner = tk.Frame(self.canvas) + # pack the inner Frame into the Canvas with the topleft corner 4 pixels offset + self.canvas.create_window(4, 4, window=self.inner, anchor='nw') + self.inner.bind("", self._on_frame_configure) + + self.outer_attr = set(dir(tk.Widget)) + + def __getattr__(self, item): + if item in self.outer_attr: + # geometry attributes etc (eg pack, destroy, tkraise) are passed on to self.outer + return getattr(self.outer, item) + else: + # all other attributes (_w, children, etc) are passed to self.inner + return getattr(self.inner, item) + + def _on_frame_configure(self, event=None): + x1, y1, x2, y2 = self.canvas.bbox("all") + height = self.canvas.winfo_height() + width = self.canvas.winfo_width() + self.canvas.config(scrollregion = (0,0, max(x2, width), max(y2, height))) + + def _bind_mouse(self, event=None): + self.canvas.bind_all("<4>", self._on_mousewheel) + self.canvas.bind_all("<5>", self._on_mousewheel) + self.canvas.bind_all("", self._on_mousewheel) + + def _unbind_mouse(self, event=None): + self.canvas.unbind_all("<4>") + self.canvas.unbind_all("<5>") + self.canvas.unbind_all("") + + def _on_mousewheel(self, event): + """Linux uses event.num; Windows / Mac uses event.delta""" + func = self.canvas.xview_scroll if event.state & 1 else self.canvas.yview_scroll + if event.num == 4 or event.delta > 0: + func(-1, "units" ) + elif event.num == 5 or event.delta < 0: + func(1, "units" ) + + def __str__(self): + return str(self.outer) +myframe = DoubleScrolledFrame(root) +myframe.pack() + +notebook=ttk.Notebook(myframe) +notebook.pack(fill='both', expand=True, anchor='center') +frame1=ttk.Frame(notebook) +frame2=ttk.Frame(notebook) +frame3=ttk.Frame(notebook) +frame4=ttk.Frame(notebook) +notebook.add(frame1,text="Aircraft") +notebook.add(frame2,text="Dynamic") +notebook.add(frame3,text="Mission") +notebook.add(frame4,text="Settings") + + +# list_of_inputs = [] +tempdict = {} +def info(): + list_of_lists = [] + for i,(key,value) in enumerate(zip(data.keys(),data.values())): + unit = value["units"] + if key in tempdict.keys(): + list_of_lists.append([f'{key},{tempdict[key].get()},{unit}']) + else: + list_of_lists.append([f'{key},{value["default_value"]},{unit}']) + # if list_of_inputs[i].get() != "": + # list_of_lists.append([f'{key},{list_of_inputs[i].get()},{unit}']) + # else: + # list_of_lists.append([f'{key},{value["default_value"]},{unit}']) + + with open('Aircraft_Model.csv', 'w', newline='') as i: + writer = csv.writer(i,delimiter=';',quoting=csv.QUOTE_MINIMAL) + for sublist in list_of_lists: + writer.writerow(sublist) + + +for i in range(len(name_each_subhead)): + if headers[i] == 'aircraft': + subhead = ttk.Label(frame1,justify='center', text=name_each_subhead[i],font=('TkDefaultFont',15,'bold')) + button = ttk.Button(frame1,text = name_each_subhead[i], width = "20", command = lambda i=i: fxn(i, frame1)) + subhead.grid(row=compound_data_rows[i]+compound_subheaders[i],columnspan=1,sticky='n',pady=10) + button.grid(row=compound_data_rows[i]+compound_subheaders[i],column=2,sticky='n',pady=10) + elif headers[i] == 'dynamic': + subhead = ttk.Label(frame2,justify='center', text=name_each_subhead[i],font=('TkDefaultFont',15,'bold')) + button = ttk.Button(frame2,text = name_each_subhead[i], width = "20", command = lambda i=i: fxn(i, frame2)) + subhead.grid(row=compound_data_rows[i]+compound_subheaders[i],columnspan=1,sticky='n',pady=10) + button.grid(row=compound_data_rows[i]+compound_subheaders[i],column=2,sticky='n',pady=10) + elif headers[i] == 'mission': + subhead = ttk.Label(frame3,justify='center', text=name_each_subhead[i],font=('TkDefaultFont',15,'bold')) + button = ttk.Button(frame3,text = name_each_subhead[i], width = "20", command = lambda i=i: fxn(i, frame3)) + subhead.grid(row=compound_data_rows[i]+compound_subheaders[i],columnspan=1,sticky='n',pady=10) + button.grid(row=compound_data_rows[i]+compound_subheaders[i],column=2,sticky='n',pady=10) + elif headers[i] == "settings": + subhead = ttk.Label(frame4,justify='center', text=name_each_subhead[i],font=('TkDefaultFont',15,'bold')) + button = ttk.Button(frame4,text = name_each_subhead[i], width = "20", command = lambda i=i: fxn(i, frame4)) + subhead.grid(row=compound_data_rows[i]+compound_subheaders[i],columnspan=1,sticky='n',pady=10) + button.grid(row=compound_data_rows[i]+compound_subheaders[i],column=2,sticky='n',pady=10) + +rows = math.ceil(list_len/4) +def fxn(x,frame): + num_rows = rows_per_subhead[x] + num=0 + for row in range(num_rows): + if num < entries_per_subhead[x]: + for col in range(3): + print(x, num) + i = index_list[x][num] + user_input = StringVar(value=f'{list_values[i]["default_value"]}') + + input_title = ttk.Label(frame,justify='left', text=f'{list_keys[i]}') + input_title.grid(row = (row+compound_subheaders[x]+compound_data_rows[x]+1),column=col,pady=10,padx=1,sticky='nw') + + user_input_entry = ttk.Entry(frame,width='10',textvariable=user_input) + user_input_entry.grid(row = (row+compound_subheaders[x]+compound_data_rows[x]+1),column=col,pady=30,padx=1,sticky='w') + + input_unit = ttk.Label(frame,justify='left', text=f'{list_values[i]["units"]}') + input_unit.grid(row = (row+compound_subheaders[x]+compound_data_rows[x]+1),column=col,pady=30,padx=75,sticky='w') + + input_desc = ttk.Label(frame,wraplength=120,justify='left', text=f'{list_values[i]["desc"]}') + input_desc.grid(row = (row+compound_subheaders[x]+compound_data_rows[x]+1),column=col,pady=30,padx=150,sticky='w') + + # list_of_inputs.append(user_input) + tempdict[list_keys[i]] = user_input + num+=1 + if num == entries_per_subhead[x]: + break + else: + break +button_main = ttk.Button(root,text = "Submit", width = "20", command = info) +button_main.pack(before=notebook,pady=10) +root.mainloop() \ No newline at end of file From 8e9872d544194d87fec8d87760b4e4ce9491918f Mon Sep 17 00:00:00 2001 From: Manning Date: Tue, 23 Jul 2024 14:42:52 -0400 Subject: [PATCH 02/14] 'v1.0' --- user_input.py | 232 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 197 insertions(+), 35 deletions(-) diff --git a/user_input.py b/user_input.py index 3ae8daefb..791f16c9d 100644 --- a/user_input.py +++ b/user_input.py @@ -1,11 +1,14 @@ -import numpy as np import csv -from tkinter import * -import aviary.api as av -from copy import deepcopy import math +from tkinter import * import tkinter as tk import tkinter.ttk as ttk +from tkinter import messagebox +from tkinter import filedialog +import aviary.api as av +from copy import deepcopy + + data = deepcopy(av.CoreMetaData) list_values = list(data.values()) list_keys = list(data.keys()) @@ -39,7 +42,7 @@ compound_subheaders=[] v=0 for num in entries_per_subhead: - rows = math.ceil(num/4) + rows = math.ceil(num/3) rows_per_subhead.append(rows) compound_subheaders.append(v) v+=1 @@ -63,6 +66,69 @@ mini_list.append(number) index_list.append(mini_list) mini_list=[] + +file_contents={} +file_name=StringVar(value='Aircraft_Model.csv') +file_data=[] +def Open(): + file_ = filedialog.askopenfilename(title = "Select a Model", + filetypes = (('All files', '*'),)) + file_name.set(file_) + file = open(file_) + for line in file: + line = line.strip() + for i in range(len(list_keys)): + if ',' in line: + name = line.split(',')[0] + numbers = line.split(',')[1:] + if len(numbers) > 1: + fixed = numbers[:-1][0] + else: + fixed = numbers[0] + if "[" in fixed and "]" in fixed: + temp = fixed.replace("[","").replace("]","") + fixed = [float(num) for num in temp.split(",")] + elif "," in fixed: + for num in fixed.split(","): + num = float(num) + elif "FALSE" in fixed.upper() or "TRUE" in fixed.upper(): + fixed = fixed + else: + try: fixed = float(fixed) + except ValueError: pass + + variable = StringVar(value=name) + if variable.get() == list_keys[i]: + file_contents[variable.get()]=fixed + else: pass + + for i in range(len(list_keys)): + check=0 + for key in file_contents: + if list_keys[i] == key: + check+=1 + file_data.append(file_contents[key]) + else: pass + if check != 1: + file_data.append(list_values[i]["default_value"]) + return file_contents, file_name, file_data + +filesaveas=StringVar(value='Aircraft_Model.csv') +checksaveas=IntVar(value=0) +def Saveas(): + files = [('CSV', '*.csv'), + ('Text Document', '*.txt'), + ('All Files', '*.*')] + file__ = filedialog.asksaveasfile(filetypes = files, defaultextension = files) + rename = str(file__).split("'")[1] + filesaveas.set(value=rename) + checksaveas.set(value=1) + info(file_contents,file_name,file_data,checksaveas,filesaveas) + return filesaveas, checksaveas + +def About(): + messagebox.showinfo(title='About', message='v1.0 - 2024') + class DoubleScrolledFrame: """ @@ -135,37 +201,57 @@ def __str__(self): myframe = DoubleScrolledFrame(root) myframe.pack() -notebook=ttk.Notebook(myframe) +notebook=ttk.Notebook(myframe.inner) notebook.pack(fill='both', expand=True, anchor='center') frame1=ttk.Frame(notebook) frame2=ttk.Frame(notebook) frame3=ttk.Frame(notebook) frame4=ttk.Frame(notebook) +frame5=ttk.Frame(notebook) notebook.add(frame1,text="Aircraft") notebook.add(frame2,text="Dynamic") notebook.add(frame3,text="Mission") notebook.add(frame4,text="Settings") +notebook.add(frame5,text="Search") - -# list_of_inputs = [] tempdict = {} -def info(): - list_of_lists = [] +def info(file_contents=file_contents, file_name=file_name, file_data=file_data, checksaveas=checksaveas, filesaveas=filesaveas): + print(checksaveas.get()) + list_of_lists = [] for i,(key,value) in enumerate(zip(data.keys(),data.values())): - unit = value["units"] - if key in tempdict.keys(): - list_of_lists.append([f'{key},{tempdict[key].get()},{unit}']) - else: - list_of_lists.append([f'{key},{value["default_value"]},{unit}']) - # if list_of_inputs[i].get() != "": - # list_of_lists.append([f'{key},{list_of_inputs[i].get()},{unit}']) - # else: - # list_of_lists.append([f'{key},{value["default_value"]},{unit}']) - - with open('Aircraft_Model.csv', 'w', newline='') as i: - writer = csv.writer(i,delimiter=';',quoting=csv.QUOTE_MINIMAL) - for sublist in list_of_lists: - writer.writerow(sublist) + unit = value["units"] + if file_name.get() == 'Aircraft_Model.csv': + if key in tempdict.keys(): + list_of_lists.append([f'{key},{tempdict[key].get()},{unit}']) + else: + list_of_lists.append([f'{key},{value["default_value"]},{unit}']) + else: + if key in tempdict.keys(): + list_of_lists.append([f'{key},{tempdict[key].get()},{unit}']) + elif key in file_contents.keys(): + list_of_lists.append([f'{key},{file_data[i]},{unit}']) + else: + list_of_lists.append([f'{key},{value["default_value"]},{unit}']) + if file_name.get() == 'Aircraft_Model.csv' and checksaveas.get() != 1: + with open('Aircraft_Model.csv', 'w', newline='') as i: + writer = csv.writer(i,delimiter=';',quoting=csv.QUOTE_MINIMAL) + for sublist in list_of_lists: + writer.writerow(sublist) + elif file_name.get() == 'Aircraft_Model.csv' and checksaveas.get() == 1: + with open(filesaveas.get(), 'w', newline='') as i: + writer = csv.writer(i,delimiter=';',quoting=csv.QUOTE_MINIMAL) + for sublist in list_of_lists: + writer.writerow(sublist) + elif file_name.get() != 'Aircraft_Model.csv' and checksaveas.get() == 1: + with open(filesaveas.get(), 'w', newline='') as i: + writer = csv.writer(i,delimiter=';',quoting=csv.QUOTE_MINIMAL) + for sublist in list_of_lists: + writer.writerow(sublist) + else: + with open(file_name.get(), 'w', newline='') as i: + writer = csv.writer(i,delimiter=';',quoting=csv.QUOTE_MINIMAL) + for sublist in list_of_lists: + writer.writerow(sublist) for i in range(len(name_each_subhead)): @@ -190,8 +276,7 @@ def info(): subhead.grid(row=compound_data_rows[i]+compound_subheaders[i],columnspan=1,sticky='n',pady=10) button.grid(row=compound_data_rows[i]+compound_subheaders[i],column=2,sticky='n',pady=10) -rows = math.ceil(list_len/4) -def fxn(x,frame): +def fxn(x,frame,file_name=file_name,file_contents=file_contents,file_data=file_data): num_rows = rows_per_subhead[x] num=0 for row in range(num_rows): @@ -199,27 +284,104 @@ def fxn(x,frame): for col in range(3): print(x, num) i = index_list[x][num] - user_input = StringVar(value=f'{list_values[i]["default_value"]}') - - input_title = ttk.Label(frame,justify='left', text=f'{list_keys[i]}') + user_input = StringVar(value=f'{list_values[i]["default_value"]}') + if file_name.get() != 'Aircraft_Model.csv': + for key in list_keys: + if key in file_contents.keys(): + user_input = StringVar(value=f'{file_data[i]}') + + input_title = ttk.Label(frame,justify='left',font=('TkDefaultFont',12), text=f'{list_keys[i]}') input_title.grid(row = (row+compound_subheaders[x]+compound_data_rows[x]+1),column=col,pady=10,padx=1,sticky='nw') user_input_entry = ttk.Entry(frame,width='10',textvariable=user_input) user_input_entry.grid(row = (row+compound_subheaders[x]+compound_data_rows[x]+1),column=col,pady=30,padx=1,sticky='w') - input_unit = ttk.Label(frame,justify='left', text=f'{list_values[i]["units"]}') + input_unit = ttk.Label(frame,justify='left',font=('TkDefaultFont',10), text=f'{list_values[i]["units"]}') input_unit.grid(row = (row+compound_subheaders[x]+compound_data_rows[x]+1),column=col,pady=30,padx=75,sticky='w') - input_desc = ttk.Label(frame,wraplength=120,justify='left', text=f'{list_values[i]["desc"]}') + input_desc = ttk.Label(frame,wraplength=120,justify='left',font=('TkDefaultFont',10), text=f'{list_values[i]["desc"]}') input_desc.grid(row = (row+compound_subheaders[x]+compound_data_rows[x]+1),column=col,pady=30,padx=150,sticky='w') - # list_of_inputs.append(user_input) tempdict[list_keys[i]] = user_input num+=1 if num == entries_per_subhead[x]: break - else: - break + else: break + +def Searchfxn(x,y,add_row,frame,file_name=file_name,file_contents=file_contents,file_data=file_data): + i = index_list[x][y] + user_input = StringVar(value=f'{list_values[i]["default_value"]}') + if file_name.get() != 'Aircraft_Model.csv': + for key in list_keys: + if key in file_contents.keys(): + user_input = StringVar(value=f'{file_data[i]}') + + input_title = ttk.Label(frame,justify='left',font=('TkDefaultFont',12), text=f'{list_keys[i]}') + input_title.grid(row = 4+add_row,column=0,pady=10,padx=1,sticky='nw') + + user_input_entry = ttk.Entry(frame,width='10',textvariable=user_input) + user_input_entry.grid(row = 5+add_row,column=0,pady=10,padx=1,sticky='w') + + input_unit = ttk.Label(frame,justify='left',font=('TkDefaultFont',10), text=f'{list_values[i]["units"]}') + input_unit.grid(row = 5+add_row,column=1,pady=10,padx=20,sticky='w') + + input_desc = ttk.Label(frame,wraplength=120,justify='left',font=('TkDefaultFont',10), text=f'{list_values[i]["desc"]}') + input_desc.grid(row = 5+add_row,column=3,pady=10,padx=20,sticky='w') + + tempdict[list_keys[i]] = user_input + +searcheader=ttk.Frame(frame5) +searcheader.pack() +searchcontents=ttk.Frame(frame5) +searchcontents.pack(after=searcheader) + +def Clear(frame=searchcontents): + frame.destroy() + +def Search(keyword): + searchcontents=ttk.Frame(frame5) + searchcontents.pack(after=searcheader) + add_row=0 + for i, key in enumerate(list_keys): + var = key.split(':')[-1] + if var == keyword: + add_row+=2 + count=0 + for row in index_list: + count2=0 + for col in row: + if i == col: + Searchfxn(count,count2,add_row,searchcontents) + count2+=1 + count+=1 + return searchcontents + +Search_input = StringVar(value='Enter Variable Name') +Search_label = ttk.Label(searcheader,justify='center', text='Search variable name',font=('TkDefaultFont',15,'bold')) +Search_label.grid(row=2,column=0) +Search_entry = ttk.Entry(searcheader,width='30',textvariable=Search_input) +Search_entry.grid(row=3, column=0) +Search_button = ttk.Button(searcheader, text = 'Search', width = "10", command = lambda i=i:Search(Search_input.get())) +Search_button.grid(row=3, column=1) +Clear_button = ttk.Button(searcheader, text = 'Clear', width = "10", command = lambda:Clear(searchcontents)) +Clear_button.grid(row=3, column=2) + + +menubar = Menu(root) +filemenu = Menu(menubar, tearoff=0) +filemenu.add_command(label='Open', command=Open) +filemenu.add_command(label='Save', command=info) +filemenu.add_command(label='Save as...', command=Saveas) +filemenu.add_separator() +filemenu.add_command(label="Exit", command=root.quit) +menubar.add_cascade(label="File", menu=filemenu) +helpmenu = Menu(menubar, tearoff=0) +helpmenu.add_command(label="About...", command=About) +menubar.add_cascade(label="Help", menu=helpmenu) +root.config(menu=menubar) + + + button_main = ttk.Button(root,text = "Submit", width = "20", command = info) -button_main.pack(before=notebook,pady=10) +button_main.pack(before=notebook,pady=10) root.mainloop() \ No newline at end of file From a94c8d1ea7554d73fb5c81102e934efa9fc9c898 Mon Sep 17 00:00:00 2001 From: Manning Date: Tue, 23 Jul 2024 14:46:48 -0400 Subject: [PATCH 03/14] 'v1.0' --- user_input.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/user_input.py b/user_input.py index 791f16c9d..eb1783bf6 100644 --- a/user_input.py +++ b/user_input.py @@ -149,16 +149,12 @@ def __init__(self, master, **kwargs): self.outer.columnconfigure(0, weight=1) self.canvas['yscrollcommand'] = self.vsb.set self.canvas['xscrollcommand'] = self.hsb.set - # mouse scroll does not seem to work with just "bind"; You have - # to use "bind_all". Therefore to use multiple windows you have - # to bind_all in the current widget self.canvas.bind("", self._bind_mouse) self.canvas.bind("", self._unbind_mouse) self.vsb['command'] = self.canvas.yview self.hsb['command'] = self.canvas.xview self.inner = tk.Frame(self.canvas) - # pack the inner Frame into the Canvas with the topleft corner 4 pixels offset self.canvas.create_window(4, 4, window=self.inner, anchor='nw') self.inner.bind("", self._on_frame_configure) @@ -166,10 +162,8 @@ def __init__(self, master, **kwargs): def __getattr__(self, item): if item in self.outer_attr: - # geometry attributes etc (eg pack, destroy, tkraise) are passed on to self.outer return getattr(self.outer, item) else: - # all other attributes (_w, children, etc) are passed to self.inner return getattr(self.inner, item) def _on_frame_configure(self, event=None): From a650e52b7543fa1d0815b39fdcbbc4611738ee58 Mon Sep 17 00:00:00 2001 From: Manning Date: Tue, 23 Jul 2024 14:50:21 -0400 Subject: [PATCH 04/14] 'v1.0' --- user_input.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/user_input.py b/user_input.py index eb1783bf6..7eadf7f5f 100644 --- a/user_input.py +++ b/user_input.py @@ -210,7 +210,6 @@ def __str__(self): tempdict = {} def info(file_contents=file_contents, file_name=file_name, file_data=file_data, checksaveas=checksaveas, filesaveas=filesaveas): - print(checksaveas.get()) list_of_lists = [] for i,(key,value) in enumerate(zip(data.keys(),data.values())): unit = value["units"] @@ -276,7 +275,6 @@ def fxn(x,frame,file_name=file_name,file_contents=file_contents,file_data=file_d for row in range(num_rows): if num < entries_per_subhead[x]: for col in range(3): - print(x, num) i = index_list[x][num] user_input = StringVar(value=f'{list_values[i]["default_value"]}') if file_name.get() != 'Aircraft_Model.csv': From 3f178a1e64f0f2df201b7a9485a4b1e20afc7978 Mon Sep 17 00:00:00 2001 From: Manning Date: Wed, 24 Jul 2024 16:08:54 -0400 Subject: [PATCH 05/14] 'v1.0' --- user_input.py | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/user_input.py b/user_input.py index 7eadf7f5f..7fa627af2 100644 --- a/user_input.py +++ b/user_input.py @@ -126,6 +126,24 @@ def Saveas(): info(file_contents,file_name,file_data,checksaveas,filesaveas) return filesaveas, checksaveas +def Instructions(): + message = 'This tool can be used to help input information about an aircraft model.\n\n'+\ + 'Enter in the desired values for your model and press "Submit" to generate '+\ + 'a CSV named "Aircraft_Model" which can be used at Levels 1 and 2 of Aviary.\n\n'+\ + 'Use "Edit"->"Open" to continue editing a previously defined model.\n'+\ + 'Use "Edit"->"Save" to submit your entries to a CSV file (this has the same effect '+\ + 'as the "Submit" button).\n'+\ + 'Use "Edit"->"Save as..." to save the file and all new commits to a new file name/location.\n'+\ + '*this will change where all new inforamtion is Submitted\n'+\ + 'Use "Edit"->"Exit" to end the program.\n'+\ + '*make sure all progress is saved before exiting\n\n'+\ + 'The "Search" tab can be used to quickly search and edit values\n'+\ + 'Use the "Search" button to find a variable name and "Clear" to clear searched results\n'+\ + '*When searching for a variable, the name must be the last term in the string '+\ + 'i.e: "*:*:variable_name" (when applicable)\n'+\ + '*Values entered in for a variable and then cleared using the "Clear" button WILL save' + messagebox.showinfo(title='Instructions', message=message) + def About(): messagebox.showinfo(title='About', message='v1.0 - 2024') @@ -282,7 +300,7 @@ def fxn(x,frame,file_name=file_name,file_contents=file_contents,file_data=file_d if key in file_contents.keys(): user_input = StringVar(value=f'{file_data[i]}') - input_title = ttk.Label(frame,justify='left',font=('TkDefaultFont',12), text=f'{list_keys[i]}') + input_title = ttk.Label(frame,justify='left',font=('TkDefaultFont',10,'bold'), text=f'{list_keys[i]}') input_title.grid(row = (row+compound_subheaders[x]+compound_data_rows[x]+1),column=col,pady=10,padx=1,sticky='nw') user_input_entry = ttk.Entry(frame,width='10',textvariable=user_input) @@ -308,17 +326,21 @@ def Searchfxn(x,y,add_row,frame,file_name=file_name,file_contents=file_contents, if key in file_contents.keys(): user_input = StringVar(value=f'{file_data[i]}') - input_title = ttk.Label(frame,justify='left',font=('TkDefaultFont',12), text=f'{list_keys[i]}') + input_title = ttk.Label(frame,justify='left',font=('TkDefaultFont',10,'bold'), text=f'{list_keys[i]}') input_title.grid(row = 4+add_row,column=0,pady=10,padx=1,sticky='nw') + searchwidgets.append(input_title) user_input_entry = ttk.Entry(frame,width='10',textvariable=user_input) - user_input_entry.grid(row = 5+add_row,column=0,pady=10,padx=1,sticky='w') + user_input_entry.grid(row = 5+add_row,column=0,pady=10,padx=1,sticky='w') + searchwidgets.append(user_input_entry) input_unit = ttk.Label(frame,justify='left',font=('TkDefaultFont',10), text=f'{list_values[i]["units"]}') input_unit.grid(row = 5+add_row,column=1,pady=10,padx=20,sticky='w') + searchwidgets.append(input_unit) input_desc = ttk.Label(frame,wraplength=120,justify='left',font=('TkDefaultFont',10), text=f'{list_values[i]["desc"]}') input_desc.grid(row = 5+add_row,column=3,pady=10,padx=20,sticky='w') + searchwidgets.append(input_desc) tempdict[list_keys[i]] = user_input @@ -326,10 +348,7 @@ def Searchfxn(x,y,add_row,frame,file_name=file_name,file_contents=file_contents, searcheader.pack() searchcontents=ttk.Frame(frame5) searchcontents.pack(after=searcheader) - -def Clear(frame=searchcontents): - frame.destroy() - +searchwidgets = [] def Search(keyword): searchcontents=ttk.Frame(frame5) searchcontents.pack(after=searcheader) @@ -346,7 +365,9 @@ def Search(keyword): Searchfxn(count,count2,add_row,searchcontents) count2+=1 count+=1 - return searchcontents +def Clear(): + for widget in searchwidgets: + widget.destroy() Search_input = StringVar(value='Enter Variable Name') Search_label = ttk.Label(searcheader,justify='center', text='Search variable name',font=('TkDefaultFont',15,'bold')) @@ -355,7 +376,7 @@ def Search(keyword): Search_entry.grid(row=3, column=0) Search_button = ttk.Button(searcheader, text = 'Search', width = "10", command = lambda i=i:Search(Search_input.get())) Search_button.grid(row=3, column=1) -Clear_button = ttk.Button(searcheader, text = 'Clear', width = "10", command = lambda:Clear(searchcontents)) +Clear_button = ttk.Button(searcheader, text = 'Clear', width = "10", command = lambda : Clear()) Clear_button.grid(row=3, column=2) @@ -368,12 +389,12 @@ def Search(keyword): filemenu.add_command(label="Exit", command=root.quit) menubar.add_cascade(label="File", menu=filemenu) helpmenu = Menu(menubar, tearoff=0) +helpmenu.add_command(label="Instructions", command=Instructions) helpmenu.add_command(label="About...", command=About) menubar.add_cascade(label="Help", menu=helpmenu) root.config(menu=menubar) - button_main = ttk.Button(root,text = "Submit", width = "20", command = info) button_main.pack(before=notebook,pady=10) root.mainloop() \ No newline at end of file From dce5dedcc03814b965147ca21b6b13a2032aa1f3 Mon Sep 17 00:00:00 2001 From: Manning Date: Thu, 25 Jul 2024 10:18:10 -0400 Subject: [PATCH 06/14] 'v1.0' --- user_input.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/user_input.py b/user_input.py index 7fa627af2..c6277df0a 100644 --- a/user_input.py +++ b/user_input.py @@ -70,6 +70,7 @@ file_contents={} file_name=StringVar(value='Aircraft_Model.csv') file_data=[] +box=[] def Open(): file_ = filedialog.askopenfilename(title = "Select a Model", filetypes = (('All files', '*'),)) @@ -108,9 +109,12 @@ def Open(): if list_keys[i] == key: check+=1 file_data.append(file_contents[key]) + box.append(1) else: pass if check != 1: file_data.append(list_values[i]["default_value"]) + box.append(1) + return file_contents, file_name, file_data filesaveas=StringVar(value='Aircraft_Model.csv') From be237eb6013f94a80b9a39f2a643ba8dde0ff749 Mon Sep 17 00:00:00 2001 From: Manning Date: Fri, 26 Jul 2024 12:40:14 -0400 Subject: [PATCH 07/14] 'v1.0' --- user_input.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 79 insertions(+), 8 deletions(-) diff --git a/user_input.py b/user_input.py index c6277df0a..4bac6e90c 100644 --- a/user_input.py +++ b/user_input.py @@ -97,24 +97,91 @@ def Open(): else: try: fixed = float(fixed) except ValueError: pass - variable = StringVar(value=name) if variable.get() == list_keys[i]: file_contents[variable.get()]=fixed else: pass - for i in range(len(list_keys)): check=0 - for key in file_contents: + for key in file_contents.keys(): if list_keys[i] == key: check+=1 file_data.append(file_contents[key]) - box.append(1) else: pass if check != 1: file_data.append(list_values[i]["default_value"]) - box.append(1) - +def Openextra(): + file_ = filedialog.askopenfilename(title = "Select a Model", + filetypes = (('All files', '*'),)) + file_name.set(file_) + file = open(file_) + for line in file: + line = line.strip() + for i in range(len(list_keys)): + if ',' in line: + name = line.split(',')[0] + numbers = line.split(',')[1:] + if len(numbers) > 1: + fixed = numbers[:-1][0] + else: + fixed = numbers[0] + if "[" in fixed and "]" in fixed: + temp = fixed.replace("[","").replace("]","") + fixed = [float(num) for num in temp.split(",")] + elif "," in fixed: + for num in fixed.split(","): + num = float(num) + elif "FALSE" in fixed.upper() or "TRUE" in fixed.upper(): + fixed = fixed + else: + try: fixed = float(fixed) + except ValueError: pass + variable = StringVar(value=name) + if variable.get() == list_keys[i]: + file_contents[variable.get()]=fixed + else: pass + for i in range(len(list_keys)): + check=0 + for key in file_contents.keys(): + if list_keys[i] == key: + check+=1 + file_data.append(file_contents[key]) + else: pass + if check != 1: + file_data.append(list_values[i]["default_value"]) + cont=[] + x=[] + old='' + for k in file_contents.keys(): + if ':' in k: + name=k.split(':')[1] + if old==name: + continue + else: + cont.append(name) + else: + name=k + if old==name: + continue + else: + cont.append(name) + old=name + for n in name_each_subhead: + for i in cont: + if n==i: + x.append('y') + break + else: + x.append('n') + for i in range(len(name_each_subhead)): + if headers[i] == 'aircraft' and x[i]=='y': + fxn(i,frame1) + elif headers[i] == 'dynamic'and x[i]=='y': + fxn(i,frame2) + elif headers[i] == 'mission'and x[i]=='y': + fxn(i,frame3) + elif headers[i] == "settings"and x[i]=='y': + fxn(i,frame4) return file_contents, file_name, file_data filesaveas=StringVar(value='Aircraft_Model.csv') @@ -134,7 +201,10 @@ def Instructions(): message = 'This tool can be used to help input information about an aircraft model.\n\n'+\ 'Enter in the desired values for your model and press "Submit" to generate '+\ 'a CSV named "Aircraft_Model" which can be used at Levels 1 and 2 of Aviary.\n\n'+\ - 'Use "Edit"->"Open" to continue editing a previously defined model.\n'+\ + '**Not all values are required to successfully optimize a given model**\n\n'+\ + 'Use "Edit"->"Open" to open a previously defined model to continue editing.\n'+\ + 'Use "Edit"->"Open & Display" to open a previously defined model and all instances where edits were made\n'+\ + '*Larger files may cause the interface to run slower\n'+\ 'Use "Edit"->"Save" to submit your entries to a CSV file (this has the same effect '+\ 'as the "Submit" button).\n'+\ 'Use "Edit"->"Save as..." to save the file and all new commits to a new file name/location.\n'+\ @@ -145,7 +215,7 @@ def Instructions(): 'Use the "Search" button to find a variable name and "Clear" to clear searched results\n'+\ '*When searching for a variable, the name must be the last term in the string '+\ 'i.e: "*:*:variable_name" (when applicable)\n'+\ - '*Values entered in for a variable and then cleared using the "Clear" button WILL save' + '*Values entered in for a variable and then cleared using the "Clear" button will still save' messagebox.showinfo(title='Instructions', message=message) def About(): @@ -387,6 +457,7 @@ def Clear(): menubar = Menu(root) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label='Open', command=Open) +filemenu.add_command(label='Open & Display', command=Openextra) filemenu.add_command(label='Save', command=info) filemenu.add_command(label='Save as...', command=Saveas) filemenu.add_separator() From 5d4a6dbecc4da9bdc80402f31a1dd93c7364444b Mon Sep 17 00:00:00 2001 From: Manning Date: Mon, 29 Jul 2024 11:47:12 -0400 Subject: [PATCH 08/14] updated to autopep8 format --- user_input.py | 597 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 407 insertions(+), 190 deletions(-) diff --git a/user_input.py b/user_input.py index 4bac6e90c..d8901d4c9 100644 --- a/user_input.py +++ b/user_input.py @@ -14,19 +14,19 @@ list_keys = list(data.keys()) list_len = len(list_values) root = Tk() -wid=1200 -hei=800 -root.geometry("%dx%d" % (wid,hei)) +width_window = 1200 +height_window = 800 +root.geometry("%dx%d" % (width_window, height_window)) root.title("Model Aircraft Input") -headers=[] +headers = [] name_each_subhead = [] entries_per_subhead = [] -old_subhead ='' +old_subhead = '' for key in list_keys: if ':' in key: subhead = key.split(':')[1] - header=key.split(':')[0] + header = key.split(':')[0] if subhead == old_subhead: entries_per_subhead[-1] += 1 else: @@ -38,42 +38,44 @@ entries_per_subhead.append(1) name_each_subhead.append(key) headers.append('dynamic') -rows_per_subhead=[] -compound_subheaders=[] -v=0 +rows_per_subhead = [] +compound_subheaders = [] +v = 0 for num in entries_per_subhead: - rows = math.ceil(num/3) + rows = math.ceil(num / 3) rows_per_subhead.append(rows) compound_subheaders.append(v) - v+=1 -compound_data_rows=[0] -for i,nums in enumerate(rows_per_subhead): - val=sum(rows_per_subhead[:i+1]) + v += 1 +compound_data_rows = [0] +for i, nums in enumerate(rows_per_subhead): + val = sum(rows_per_subhead[:i + 1]) compound_data_rows.append(val) - if len(compound_data_rows)==87: + if len(compound_data_rows) == 87: break -compound_data_entries=[] +compound_data_entries = [] for i, nums in enumerate(entries_per_subhead): - val = sum(entries_per_subhead[:i+1]) + val = sum(entries_per_subhead[:i + 1]) compound_data_entries.append(val) -index_list=[] +index_list = [] number = 0 -mini_list=[0] +mini_list = [0] for num in compound_data_entries: - for i in range(number,num): - if number < num-1: - number +=1 + for i in range(number, num): + if number < num - 1: + number += 1 mini_list.append(number) index_list.append(mini_list) - mini_list=[] - -file_contents={} -file_name=StringVar(value='Aircraft_Model.csv') -file_data=[] -box=[] + mini_list = [] + +file_contents = {} +file_name = StringVar(value='Aircraft_Model.csv') +file_data = [] +box = [] + + def Open(): - file_ = filedialog.askopenfilename(title = "Select a Model", - filetypes = (('All files', '*'),)) + file_ = filedialog.askopenfilename(title="Select a Model", + filetypes=(('All files', '*'),)) file_name.set(file_) file = open(file_) for line in file: @@ -87,7 +89,7 @@ def Open(): else: fixed = numbers[0] if "[" in fixed and "]" in fixed: - temp = fixed.replace("[","").replace("]","") + temp = fixed.replace("[", "").replace("]", "") fixed = [float(num) for num in temp.split(",")] elif "," in fixed: for num in fixed.split(","): @@ -95,24 +97,30 @@ def Open(): elif "FALSE" in fixed.upper() or "TRUE" in fixed.upper(): fixed = fixed else: - try: fixed = float(fixed) - except ValueError: pass + try: + fixed = float(fixed) + except ValueError: + pass variable = StringVar(value=name) if variable.get() == list_keys[i]: - file_contents[variable.get()]=fixed - else: pass - for i in range(len(list_keys)): - check=0 + file_contents[variable.get()] = fixed + else: + pass + for i in range(len(list_keys)): + check = 0 for key in file_contents.keys(): if list_keys[i] == key: - check+=1 + check += 1 file_data.append(file_contents[key]) - else: pass + else: + pass if check != 1: file_data.append(list_values[i]["default_value"]) + + def Openextra(): - file_ = filedialog.askopenfilename(title = "Select a Model", - filetypes = (('All files', '*'),)) + file_ = filedialog.askopenfilename(title="Select a Model", + filetypes=(('All files', '*'),)) file_name.set(file_) file = open(file_) for line in file: @@ -126,7 +134,7 @@ def Openextra(): else: fixed = numbers[0] if "[" in fixed and "]" in fixed: - temp = fixed.replace("[","").replace("]","") + temp = fixed.replace("[", "").replace("]", "") fixed = [float(num) for num in temp.split(",")] elif "," in fixed: for num in fixed.split(","): @@ -134,90 +142,99 @@ def Openextra(): elif "FALSE" in fixed.upper() or "TRUE" in fixed.upper(): fixed = fixed else: - try: fixed = float(fixed) - except ValueError: pass + try: + fixed = float(fixed) + except ValueError: + pass variable = StringVar(value=name) if variable.get() == list_keys[i]: - file_contents[variable.get()]=fixed - else: pass - for i in range(len(list_keys)): - check=0 + file_contents[variable.get()] = fixed + else: + pass + for i in range(len(list_keys)): + check = 0 for key in file_contents.keys(): if list_keys[i] == key: - check+=1 + check += 1 file_data.append(file_contents[key]) - else: pass + else: + pass if check != 1: file_data.append(list_values[i]["default_value"]) - cont=[] - x=[] - old='' + cont = [] + x = [] + old = '' for k in file_contents.keys(): if ':' in k: - name=k.split(':')[1] - if old==name: + name = k.split(':')[1] + if old == name: continue else: cont.append(name) else: - name=k - if old==name: + name = k + if old == name: continue else: cont.append(name) - old=name + old = name for n in name_each_subhead: for i in cont: - if n==i: + if n == i: x.append('y') break else: x.append('n') for i in range(len(name_each_subhead)): - if headers[i] == 'aircraft' and x[i]=='y': - fxn(i,frame1) - elif headers[i] == 'dynamic'and x[i]=='y': - fxn(i,frame2) - elif headers[i] == 'mission'and x[i]=='y': - fxn(i,frame3) - elif headers[i] == "settings"and x[i]=='y': - fxn(i,frame4) + if headers[i] == 'aircraft' and x[i] == 'y': + BuildDataEntry(i, frame1) + elif headers[i] == 'dynamic' and x[i] == 'y': + BuildDataEntry(i, frame2) + elif headers[i] == 'mission' and x[i] == 'y': + BuildDataEntry(i, frame3) + elif headers[i] == "settings" and x[i] == 'y': + BuildDataEntry(i, frame4) return file_contents, file_name, file_data -filesaveas=StringVar(value='Aircraft_Model.csv') -checksaveas=IntVar(value=0) + +filesaveas = StringVar(value='Aircraft_Model.csv') +checksaveas = IntVar(value=0) + + def Saveas(): files = [('CSV', '*.csv'), ('Text Document', '*.txt'), ('All Files', '*.*')] - file__ = filedialog.asksaveasfile(filetypes = files, defaultextension = files) + file__ = filedialog.asksaveasfile(filetypes=files, defaultextension=files) rename = str(file__).split("'")[1] filesaveas.set(value=rename) checksaveas.set(value=1) - info(file_contents,file_name,file_data,checksaveas,filesaveas) + WritetoCSV(file_contents, file_name, file_data, checksaveas, filesaveas) return filesaveas, checksaveas + def Instructions(): - message = 'This tool can be used to help input information about an aircraft model.\n\n'+\ - 'Enter in the desired values for your model and press "Submit" to generate '+\ - 'a CSV named "Aircraft_Model" which can be used at Levels 1 and 2 of Aviary.\n\n'+\ - '**Not all values are required to successfully optimize a given model**\n\n'+\ - 'Use "Edit"->"Open" to open a previously defined model to continue editing.\n'+\ - 'Use "Edit"->"Open & Display" to open a previously defined model and all instances where edits were made\n'+\ - '*Larger files may cause the interface to run slower\n'+\ - 'Use "Edit"->"Save" to submit your entries to a CSV file (this has the same effect '+\ - 'as the "Submit" button).\n'+\ - 'Use "Edit"->"Save as..." to save the file and all new commits to a new file name/location.\n'+\ - '*this will change where all new inforamtion is Submitted\n'+\ - 'Use "Edit"->"Exit" to end the program.\n'+\ - '*make sure all progress is saved before exiting\n\n'+\ - 'The "Search" tab can be used to quickly search and edit values\n'+\ - 'Use the "Search" button to find a variable name and "Clear" to clear searched results\n'+\ - '*When searching for a variable, the name must be the last term in the string '+\ - 'i.e: "*:*:variable_name" (when applicable)\n'+\ - '*Values entered in for a variable and then cleared using the "Clear" button will still save' + message = 'This tool can be used to help input information about an aircraft model.\n\n' +\ + 'Enter in the desired values for your model and press "Submit" to generate ' +\ + 'a CSV named "Aircraft_Model" which can be used at Levels 1 and 2 of Aviary.\n\n' +\ + '**Not all values are required to successfully optimize a given model**\n\n' +\ + 'Use "Edit"->"Open" to open a previously defined model to continue editing.\n' +\ + 'Use "Edit"->"Open & Display" to open a previously defined model and all instances where edits were made\n' +\ + '*Larger files may cause the interface to run slower\n' +\ + 'Use "Edit"->"Save" to submit your entries to a CSV file (this has the same effect ' +\ + 'as the "Submit" button).\n' +\ + 'Use "Edit"->"Save as..." to save the file and all new commits to a new file name/location.\n' +\ + '*this will change where all new inforamtion is Submitted\n' +\ + 'Use "Edit"->"Exit" to end the program.\n' +\ + '*make sure all progress is saved before exiting\n\n' +\ + 'The "Search" tab can be used to quickly search and edit values\n' +\ + 'Use the "Search" button to find a variable name and "Clear" to clear searched results\n' +\ + '*When searching for a variable, the name must be the last term in the string ' +\ + 'i.e: "*:*:variable_name" (when applicable)\n' +\ + '*Values entered in for a variable and then cleared using the "Clear" button will still save' messagebox.showinfo(title='Instructions', message=message) + def About(): messagebox.showinfo(title='About', message='v1.0 - 2024') @@ -226,16 +243,21 @@ class DoubleScrolledFrame: """ https://gist.github.com/novel-yet-trivial/2841b7b640bba48928200ff979204115 """ + def __init__(self, master, **kwargs): - width = wid - height = hei + width = width_window + height = height_window self.outer = tk.Frame(master, **kwargs) self.vsb = ttk.Scrollbar(self.outer, orient=tk.VERTICAL) self.vsb.grid(row=0, column=1, sticky='ns') self.hsb = ttk.Scrollbar(self.outer, orient=tk.HORIZONTAL) self.hsb.grid(row=1, column=0, sticky='ew') - self.canvas = tk.Canvas(self.outer, highlightthickness=0, width=width, height=height) + self.canvas = tk.Canvas( + self.outer, + highlightthickness=0, + width=width, + height=height) self.canvas.grid(row=0, column=0, sticky='nsew') self.outer.rowconfigure(0, weight=1) self.outer.columnconfigure(0, weight=1) @@ -262,7 +284,7 @@ def _on_frame_configure(self, event=None): x1, y1, x2, y2 = self.canvas.bbox("all") height = self.canvas.winfo_height() width = self.canvas.winfo_width() - self.canvas.config(scrollregion = (0,0, max(x2, width), max(y2, height))) + self.canvas.config(scrollregion=(0, 0, max(x2, width), max(y2, height))) def _bind_mouse(self, event=None): self.canvas.bind_all("<4>", self._on_mousewheel) @@ -273,97 +295,204 @@ def _unbind_mouse(self, event=None): self.canvas.unbind_all("<4>") self.canvas.unbind_all("<5>") self.canvas.unbind_all("") - + def _on_mousewheel(self, event): """Linux uses event.num; Windows / Mac uses event.delta""" - func = self.canvas.xview_scroll if event.state & 1 else self.canvas.yview_scroll + func = self.canvas.xview_scroll if event.state & 1 else self.canvas.yview_scroll if event.num == 4 or event.delta > 0: - func(-1, "units" ) + func(-1, "units") elif event.num == 5 or event.delta < 0: - func(1, "units" ) - + func(1, "units") + def __str__(self): return str(self.outer) + + myframe = DoubleScrolledFrame(root) myframe.pack() -notebook=ttk.Notebook(myframe.inner) +notebook = ttk.Notebook(myframe.inner) notebook.pack(fill='both', expand=True, anchor='center') -frame1=ttk.Frame(notebook) -frame2=ttk.Frame(notebook) -frame3=ttk.Frame(notebook) -frame4=ttk.Frame(notebook) -frame5=ttk.Frame(notebook) -notebook.add(frame1,text="Aircraft") -notebook.add(frame2,text="Dynamic") -notebook.add(frame3,text="Mission") -notebook.add(frame4,text="Settings") -notebook.add(frame5,text="Search") +frame1 = ttk.Frame(notebook) +frame2 = ttk.Frame(notebook) +frame3 = ttk.Frame(notebook) +frame4 = ttk.Frame(notebook) +frame5 = ttk.Frame(notebook) +notebook.add(frame1, text="Aircraft") +notebook.add(frame2, text="Dynamic") +notebook.add(frame3, text="Mission") +notebook.add(frame4, text="Settings") +notebook.add(frame5, text="Search") tempdict = {} -def info(file_contents=file_contents, file_name=file_name, file_data=file_data, checksaveas=checksaveas, filesaveas=filesaveas): - list_of_lists = [] - for i,(key,value) in enumerate(zip(data.keys(),data.values())): - unit = value["units"] - if file_name.get() == 'Aircraft_Model.csv': - if key in tempdict.keys(): - list_of_lists.append([f'{key},{tempdict[key].get()},{unit}']) - else: - list_of_lists.append([f'{key},{value["default_value"]},{unit}']) + + +def WritetoCSV( + file_contents=file_contents, + file_name=file_name, + file_data=file_data, + checksaveas=checksaveas, + filesaveas=filesaveas): + list_of_lists = [] + for i, (key, value) in enumerate(zip(data.keys(), data.values())): + unit = value["units"] + if file_name.get() == 'Aircraft_Model.csv': + if key in tempdict.keys(): + list_of_lists.append([f'{key},{tempdict[key].get()},{unit}']) else: - if key in tempdict.keys(): - list_of_lists.append([f'{key},{tempdict[key].get()},{unit}']) - elif key in file_contents.keys(): - list_of_lists.append([f'{key},{file_data[i]},{unit}']) - else: - list_of_lists.append([f'{key},{value["default_value"]},{unit}']) + list_of_lists.append([f'{key},{value["default_value"]},{unit}']) + else: + if key in tempdict.keys(): + list_of_lists.append([f'{key},{tempdict[key].get()},{unit}']) + elif key in file_contents.keys(): + list_of_lists.append([f'{key},{file_data[i]},{unit}']) + else: + list_of_lists.append([f'{key},{value["default_value"]},{unit}']) if file_name.get() == 'Aircraft_Model.csv' and checksaveas.get() != 1: with open('Aircraft_Model.csv', 'w', newline='') as i: - writer = csv.writer(i,delimiter=';',quoting=csv.QUOTE_MINIMAL) + writer = csv.writer(i, delimiter=';', quoting=csv.QUOTE_MINIMAL) for sublist in list_of_lists: writer.writerow(sublist) elif file_name.get() == 'Aircraft_Model.csv' and checksaveas.get() == 1: with open(filesaveas.get(), 'w', newline='') as i: - writer = csv.writer(i,delimiter=';',quoting=csv.QUOTE_MINIMAL) + writer = csv.writer(i, delimiter=';', quoting=csv.QUOTE_MINIMAL) for sublist in list_of_lists: writer.writerow(sublist) elif file_name.get() != 'Aircraft_Model.csv' and checksaveas.get() == 1: with open(filesaveas.get(), 'w', newline='') as i: - writer = csv.writer(i,delimiter=';',quoting=csv.QUOTE_MINIMAL) + writer = csv.writer(i, delimiter=';', quoting=csv.QUOTE_MINIMAL) for sublist in list_of_lists: writer.writerow(sublist) else: with open(file_name.get(), 'w', newline='') as i: - writer = csv.writer(i,delimiter=';',quoting=csv.QUOTE_MINIMAL) + writer = csv.writer(i, delimiter=';', quoting=csv.QUOTE_MINIMAL) for sublist in list_of_lists: writer.writerow(sublist) for i in range(len(name_each_subhead)): if headers[i] == 'aircraft': - subhead = ttk.Label(frame1,justify='center', text=name_each_subhead[i],font=('TkDefaultFont',15,'bold')) - button = ttk.Button(frame1,text = name_each_subhead[i], width = "20", command = lambda i=i: fxn(i, frame1)) - subhead.grid(row=compound_data_rows[i]+compound_subheaders[i],columnspan=1,sticky='n',pady=10) - button.grid(row=compound_data_rows[i]+compound_subheaders[i],column=2,sticky='n',pady=10) + subhead = ttk.Label( + frame1, + justify='center', + text=name_each_subhead[i], + font=( + 'TkDefaultFont', + 15, + 'bold')) + button = ttk.Button( + frame1, + text=name_each_subhead[i], + width="20", + command=lambda i=i: BuildDataEntry( + i, + frame1)) + subhead.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + columnspan=1, + sticky='n', + pady=10) + button.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + column=2, + sticky='n', + pady=10) elif headers[i] == 'dynamic': - subhead = ttk.Label(frame2,justify='center', text=name_each_subhead[i],font=('TkDefaultFont',15,'bold')) - button = ttk.Button(frame2,text = name_each_subhead[i], width = "20", command = lambda i=i: fxn(i, frame2)) - subhead.grid(row=compound_data_rows[i]+compound_subheaders[i],columnspan=1,sticky='n',pady=10) - button.grid(row=compound_data_rows[i]+compound_subheaders[i],column=2,sticky='n',pady=10) + subhead = ttk.Label( + frame2, + justify='center', + text=name_each_subhead[i], + font=( + 'TkDefaultFont', + 15, + 'bold')) + button = ttk.Button( + frame2, + text=name_each_subhead[i], + width="20", + command=lambda i=i: BuildDataEntry( + i, + frame2)) + subhead.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + columnspan=1, + sticky='n', + pady=10) + button.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + column=2, + sticky='n', + pady=10) elif headers[i] == 'mission': - subhead = ttk.Label(frame3,justify='center', text=name_each_subhead[i],font=('TkDefaultFont',15,'bold')) - button = ttk.Button(frame3,text = name_each_subhead[i], width = "20", command = lambda i=i: fxn(i, frame3)) - subhead.grid(row=compound_data_rows[i]+compound_subheaders[i],columnspan=1,sticky='n',pady=10) - button.grid(row=compound_data_rows[i]+compound_subheaders[i],column=2,sticky='n',pady=10) + subhead = ttk.Label( + frame3, + justify='center', + text=name_each_subhead[i], + font=( + 'TkDefaultFont', + 15, + 'bold')) + button = ttk.Button( + frame3, + text=name_each_subhead[i], + width="20", + command=lambda i=i: BuildDataEntry( + i, + frame3)) + subhead.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + columnspan=1, + sticky='n', + pady=10) + button.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + column=2, + sticky='n', + pady=10) elif headers[i] == "settings": - subhead = ttk.Label(frame4,justify='center', text=name_each_subhead[i],font=('TkDefaultFont',15,'bold')) - button = ttk.Button(frame4,text = name_each_subhead[i], width = "20", command = lambda i=i: fxn(i, frame4)) - subhead.grid(row=compound_data_rows[i]+compound_subheaders[i],columnspan=1,sticky='n',pady=10) - button.grid(row=compound_data_rows[i]+compound_subheaders[i],column=2,sticky='n',pady=10) - -def fxn(x,frame,file_name=file_name,file_contents=file_contents,file_data=file_data): + subhead = ttk.Label( + frame4, + justify='center', + text=name_each_subhead[i], + font=( + 'TkDefaultFont', + 15, + 'bold')) + button = ttk.Button( + frame4, + text=name_each_subhead[i], + width="20", + command=lambda i=i: BuildDataEntry( + i, + frame4)) + subhead.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + columnspan=1, + sticky='n', + pady=10) + button.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + column=2, + sticky='n', + pady=10) + + +def BuildDataEntry( + x, + frame, + file_name=file_name, + file_contents=file_contents, + file_data=file_data): num_rows = rows_per_subhead[x] - num=0 + num = 0 for row in range(num_rows): if num < entries_per_subhead[x]: for col in range(3): @@ -374,25 +503,75 @@ def fxn(x,frame,file_name=file_name,file_contents=file_contents,file_data=file_d if key in file_contents.keys(): user_input = StringVar(value=f'{file_data[i]}') - input_title = ttk.Label(frame,justify='left',font=('TkDefaultFont',10,'bold'), text=f'{list_keys[i]}') - input_title.grid(row = (row+compound_subheaders[x]+compound_data_rows[x]+1),column=col,pady=10,padx=1,sticky='nw') - - user_input_entry = ttk.Entry(frame,width='10',textvariable=user_input) - user_input_entry.grid(row = (row+compound_subheaders[x]+compound_data_rows[x]+1),column=col,pady=30,padx=1,sticky='w') - - input_unit = ttk.Label(frame,justify='left',font=('TkDefaultFont',10), text=f'{list_values[i]["units"]}') - input_unit.grid(row = (row+compound_subheaders[x]+compound_data_rows[x]+1),column=col,pady=30,padx=75,sticky='w') - - input_desc = ttk.Label(frame,wraplength=120,justify='left',font=('TkDefaultFont',10), text=f'{list_values[i]["desc"]}') - input_desc.grid(row = (row+compound_subheaders[x]+compound_data_rows[x]+1),column=col,pady=30,padx=150,sticky='w') + input_title = ttk.Label(frame, justify='left', font=( + 'TkDefaultFont', 10, 'bold'), text=f'{list_keys[i]}') + input_title.grid( + row=( + row + + compound_subheaders[x] + + compound_data_rows[x] + + 1), + column=col, + pady=10, + padx=1, + sticky='nw') + + user_input_entry = ttk.Entry(frame, width='10', textvariable=user_input) + user_input_entry.grid( + row=( + row + + compound_subheaders[x] + + compound_data_rows[x] + + 1), + column=col, + pady=30, + padx=1, + sticky='w') + + input_unit = ttk.Label( + frame, justify='left', font=( + 'TkDefaultFont', 10), text=f'{list_values[i]["units"]}') + input_unit.grid( + row=( + row + + compound_subheaders[x] + + compound_data_rows[x] + + 1), + column=col, + pady=30, + padx=75, + sticky='w') + + input_desc = ttk.Label( + frame, wraplength=120, justify='left', font=( + 'TkDefaultFont', 10), text=f'{list_values[i]["desc"]}') + input_desc.grid( + row=( + row + + compound_subheaders[x] + + compound_data_rows[x] + + 1), + column=col, + pady=30, + padx=150, + sticky='w') tempdict[list_keys[i]] = user_input - num+=1 + num += 1 if num == entries_per_subhead[x]: break - else: break + else: + break + -def Searchfxn(x,y,add_row,frame,file_name=file_name,file_contents=file_contents,file_data=file_data): +def Searchfxn( + x, + y, + add_row, + frame, + file_name=file_name, + file_contents=file_contents, + file_data=file_data): i = index_list[x][y] user_input = StringVar(value=f'{list_values[i]["default_value"]}') if file_name.get() != 'Aircraft_Model.csv': @@ -400,57 +579,95 @@ def Searchfxn(x,y,add_row,frame,file_name=file_name,file_contents=file_contents, if key in file_contents.keys(): user_input = StringVar(value=f'{file_data[i]}') - input_title = ttk.Label(frame,justify='left',font=('TkDefaultFont',10,'bold'), text=f'{list_keys[i]}') - input_title.grid(row = 4+add_row,column=0,pady=10,padx=1,sticky='nw') + input_title = ttk.Label( + frame, + justify='left', + font=( + 'TkDefaultFont', + 10, + 'bold'), + text=f'{list_keys[i]}') + input_title.grid(row=4 + add_row, column=0, pady=10, padx=1, sticky='nw') searchwidgets.append(input_title) - user_input_entry = ttk.Entry(frame,width='10',textvariable=user_input) - user_input_entry.grid(row = 5+add_row,column=0,pady=10,padx=1,sticky='w') - searchwidgets.append(user_input_entry) - - input_unit = ttk.Label(frame,justify='left',font=('TkDefaultFont',10), text=f'{list_values[i]["units"]}') - input_unit.grid(row = 5+add_row,column=1,pady=10,padx=20,sticky='w') + user_input_entry = ttk.Entry(frame, width='10', textvariable=user_input) + user_input_entry.grid(row=5 + add_row, column=0, pady=10, padx=1, sticky='w') + searchwidgets.append(user_input_entry) + + input_unit = ttk.Label( + frame, + justify='left', + font=( + 'TkDefaultFont', + 10), + text=f'{list_values[i]["units"]}') + input_unit.grid(row=5 + add_row, column=1, pady=10, padx=20, sticky='w') searchwidgets.append(input_unit) - input_desc = ttk.Label(frame,wraplength=120,justify='left',font=('TkDefaultFont',10), text=f'{list_values[i]["desc"]}') - input_desc.grid(row = 5+add_row,column=3,pady=10,padx=20,sticky='w') + input_desc = ttk.Label( + frame, + wraplength=120, + justify='left', + font=( + 'TkDefaultFont', + 10), + text=f'{list_values[i]["desc"]}') + input_desc.grid(row=5 + add_row, column=3, pady=10, padx=20, sticky='w') searchwidgets.append(input_desc) tempdict[list_keys[i]] = user_input -searcheader=ttk.Frame(frame5) + +searcheader = ttk.Frame(frame5) searcheader.pack() -searchcontents=ttk.Frame(frame5) +searchcontents = ttk.Frame(frame5) searchcontents.pack(after=searcheader) searchwidgets = [] + + def Search(keyword): - searchcontents=ttk.Frame(frame5) + searchcontents = ttk.Frame(frame5) searchcontents.pack(after=searcheader) - add_row=0 + add_row = 0 for i, key in enumerate(list_keys): var = key.split(':')[-1] if var == keyword: - add_row+=2 - count=0 + add_row += 2 + count = 0 for row in index_list: - count2=0 + count2 = 0 for col in row: if i == col: - Searchfxn(count,count2,add_row,searchcontents) - count2+=1 - count+=1 + Searchfxn(count, count2, add_row, searchcontents) + count2 += 1 + count += 1 + + def Clear(): for widget in searchwidgets: widget.destroy() + Search_input = StringVar(value='Enter Variable Name') -Search_label = ttk.Label(searcheader,justify='center', text='Search variable name',font=('TkDefaultFont',15,'bold')) -Search_label.grid(row=2,column=0) -Search_entry = ttk.Entry(searcheader,width='30',textvariable=Search_input) +Search_label = ttk.Label( + searcheader, + justify='center', + text='Search variable name', + font=( + 'TkDefaultFont', + 15, + 'bold')) +Search_label.grid(row=2, column=0) +Search_entry = ttk.Entry(searcheader, width='30', textvariable=Search_input) Search_entry.grid(row=3, column=0) -Search_button = ttk.Button(searcheader, text = 'Search', width = "10", command = lambda i=i:Search(Search_input.get())) +Search_button = ttk.Button( + searcheader, + text='Search', + width="10", + command=lambda i=i: Search( + Search_input.get())) Search_button.grid(row=3, column=1) -Clear_button = ttk.Button(searcheader, text = 'Clear', width = "10", command = lambda : Clear()) +Clear_button = ttk.Button(searcheader, text='Clear', width="10", command=lambda: Clear()) Clear_button.grid(row=3, column=2) @@ -458,7 +675,7 @@ def Clear(): filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label='Open', command=Open) filemenu.add_command(label='Open & Display', command=Openextra) -filemenu.add_command(label='Save', command=info) +filemenu.add_command(label='Save', command=WritetoCSV) filemenu.add_command(label='Save as...', command=Saveas) filemenu.add_separator() filemenu.add_command(label="Exit", command=root.quit) @@ -470,6 +687,6 @@ def Clear(): root.config(menu=menubar) -button_main = ttk.Button(root,text = "Submit", width = "20", command = info) -button_main.pack(before=notebook,pady=10) -root.mainloop() \ No newline at end of file +button_main = ttk.Button(root, text="Submit", width="20", command=WritetoCSV) +button_main.pack(before=notebook, pady=10) +root.mainloop() From 4b192eb37c9f005d44a93d8a73c42b35e3c41db9 Mon Sep 17 00:00:00 2001 From: Manning Date: Mon, 29 Jul 2024 14:46:59 -0400 Subject: [PATCH 09/14] name and location change --- user_input.py => aviary/interface/build_model.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename user_input.py => aviary/interface/build_model.py (100%) diff --git a/user_input.py b/aviary/interface/build_model.py similarity index 100% rename from user_input.py rename to aviary/interface/build_model.py From 9f5442ef6bcb80c0527b5d4762352f055e9f53ac Mon Sep 17 00:00:00 2001 From: Manning Date: Tue, 30 Jul 2024 14:27:49 -0400 Subject: [PATCH 10/14] Completed suggested edits --- aviary/interface/build_model.py | 1359 +++++++++++++------------- aviary/interface/cmd_entry_points.py | 8 +- 2 files changed, 694 insertions(+), 673 deletions(-) diff --git a/aviary/interface/build_model.py b/aviary/interface/build_model.py index d8901d4c9..4be42f418 100644 --- a/aviary/interface/build_model.py +++ b/aviary/interface/build_model.py @@ -1,692 +1,709 @@ +import os import csv import math -from tkinter import * import tkinter as tk import tkinter.ttk as ttk -from tkinter import messagebox -from tkinter import filedialog -import aviary.api as av +from aviary import api from copy import deepcopy -data = deepcopy(av.CoreMetaData) -list_values = list(data.values()) -list_keys = list(data.keys()) -list_len = len(list_values) -root = Tk() -width_window = 1200 -height_window = 800 -root.geometry("%dx%d" % (width_window, height_window)) -root.title("Model Aircraft Input") - -headers = [] -name_each_subhead = [] -entries_per_subhead = [] -old_subhead = '' -for key in list_keys: - if ':' in key: - subhead = key.split(':')[1] - header = key.split(':')[0] - if subhead == old_subhead: - entries_per_subhead[-1] += 1 - else: - entries_per_subhead.append(1) - name_each_subhead.append(subhead) - headers.append(header) - old_subhead = subhead - else: - entries_per_subhead.append(1) - name_each_subhead.append(key) - headers.append('dynamic') -rows_per_subhead = [] -compound_subheaders = [] -v = 0 -for num in entries_per_subhead: - rows = math.ceil(num / 3) - rows_per_subhead.append(rows) - compound_subheaders.append(v) - v += 1 -compound_data_rows = [0] -for i, nums in enumerate(rows_per_subhead): - val = sum(rows_per_subhead[:i + 1]) - compound_data_rows.append(val) - if len(compound_data_rows) == 87: - break -compound_data_entries = [] -for i, nums in enumerate(entries_per_subhead): - val = sum(entries_per_subhead[:i + 1]) - compound_data_entries.append(val) -index_list = [] -number = 0 -mini_list = [0] -for num in compound_data_entries: - for i in range(number, num): - if number < num - 1: - number += 1 - mini_list.append(number) - index_list.append(mini_list) - mini_list = [] - -file_contents = {} -file_name = StringVar(value='Aircraft_Model.csv') -file_data = [] -box = [] - - -def Open(): - file_ = filedialog.askopenfilename(title="Select a Model", - filetypes=(('All files', '*'),)) - file_name.set(file_) - file = open(file_) - for line in file: - line = line.strip() - for i in range(len(list_keys)): - if ',' in line: - name = line.split(',')[0] - numbers = line.split(',')[1:] - if len(numbers) > 1: - fixed = numbers[:-1][0] - else: - fixed = numbers[0] - if "[" in fixed and "]" in fixed: - temp = fixed.replace("[", "").replace("]", "") - fixed = [float(num) for num in temp.split(",")] - elif "," in fixed: - for num in fixed.split(","): - num = float(num) - elif "FALSE" in fixed.upper() or "TRUE" in fixed.upper(): - fixed = fixed +class build_model(): + def __init__(self): + data = deepcopy(api.CoreMetaData) + list_values = list(data.values()) + list_keys = list(data.keys()) + # list_len = len(list_values) + root = tk.Tk() + source_directory = os.path.abspath(os.path.dirname(__file__)) + root.iconphoto( + False, tk.PhotoImage( + file=os.path.join(source_directory, "aviary_logo_16.png")), + tk.PhotoImage( + file=os.path.join(source_directory, "aviary_logo_32.png"))) + width_window = 1200 + height_window = 800 + root.geometry("%dx%d" % (width_window, height_window)) + root.title("Model Aircraft Input") + + headers = [] + name_each_subhead = [] + entries_per_subhead = [] + old_subhead = '' + for key in list_keys: + if ':' in key: + subhead = key.split(':')[1] + header = key.split(':')[0] + if subhead == old_subhead: + entries_per_subhead[-1] += 1 else: - try: - fixed = float(fixed) - except ValueError: + entries_per_subhead.append(1) + name_each_subhead.append(subhead) + headers.append(header) + old_subhead = subhead + else: + entries_per_subhead.append(1) + name_each_subhead.append(key) + headers.append('dynamic') + rows_per_subhead = [] + compound_subheaders = [] + v = 0 + for num in entries_per_subhead: + rows = math.ceil(num / 3) + rows_per_subhead.append(rows) + compound_subheaders.append(v) + v += 1 + compound_data_rows = [0] + for i, nums in enumerate(rows_per_subhead): + val = sum(rows_per_subhead[:i + 1]) + compound_data_rows.append(val) + if len(compound_data_rows) == 87: + break + compound_data_entries = [] + for i, nums in enumerate(entries_per_subhead): + val = sum(entries_per_subhead[:i + 1]) + compound_data_entries.append(val) + index_list = [] + number = 0 + mini_list = [0] + for num in compound_data_entries: + for i in range(number, num): + if number < num - 1: + number += 1 + mini_list.append(number) + index_list.append(mini_list) + mini_list = [] + + file_contents = {} + file_name = tk.StringVar(value='Aircraft_Model.csv') + file_data = [] + + def Open(): + file_ = tk.filedialog.askopenfilename(title="Select a Model", + filetypes=(('All files', '*'),)) + file_name.set(file_) + file = open(file_) + for line in file: + line = line.strip() + for i in range(len(list_keys)): + if ',' in line: + name = line.split(',')[0] + numbers = line.split(',')[1:] + if len(numbers) > 1: + fixed = numbers[:-1][0] + else: + fixed = numbers[0] + if "[" in fixed and "]" in fixed: + temp = fixed.replace("[", "").replace("]", "") + fixed = [float(num) for num in temp.split(",")] + elif "," in fixed: + for num in fixed.split(","): + num = float(num) + elif "FALSE" in fixed.upper() or "TRUE" in fixed.upper(): + fixed = fixed + else: + try: + fixed = float(fixed) + except ValueError: + pass + variable = tk.StringVar(value=name) + if variable.get() == list_keys[i]: + file_contents[variable.get()] = fixed + else: + pass + for i in range(len(list_keys)): + check = 0 + for key in file_contents.keys(): + if list_keys[i] == key: + check += 1 + file_data.append(file_contents[key]) + else: + pass + if check != 1: + file_data.append(list_values[i]["default_value"]) + print(f'Model successfully imported from {file_name.get()}') + + def Openextra(): + file_ = tk.filedialog.askopenfilename(title="Select a Model", + filetypes=(('All files', '*'),)) + file_name.set(file_) + file = open(file_) + for line in file: + line = line.strip() + for i in range(len(list_keys)): + if ',' in line: + name = line.split(',')[0] + numbers = line.split(',')[1:] + if len(numbers) > 1: + fixed = numbers[:-1][0] + else: + fixed = numbers[0] + if "[" in fixed and "]" in fixed: + temp = fixed.replace("[", "").replace("]", "") + fixed = [float(num) for num in temp.split(",")] + elif "," in fixed: + for num in fixed.split(","): + num = float(num) + elif "FALSE" in fixed.upper() or "TRUE" in fixed.upper(): + fixed = fixed + else: + try: + fixed = float(fixed) + except ValueError: + pass + variable = tk.StringVar(value=name) + if variable.get() == list_keys[i]: + file_contents[variable.get()] = fixed + else: + pass + for i in range(len(list_keys)): + check = 0 + for key in file_contents.keys(): + if list_keys[i] == key: + check += 1 + file_data.append(file_contents[key]) + else: pass - variable = StringVar(value=name) - if variable.get() == list_keys[i]: - file_contents[variable.get()] = fixed + if check != 1: + file_data.append(list_values[i]["default_value"]) + cont = [] + x = [] + old = '' + for k in file_contents.keys(): + if ':' in k: + name = k.split(':')[1] + if old == name: + continue + else: + cont.append(name) else: - pass - for i in range(len(list_keys)): - check = 0 - for key in file_contents.keys(): - if list_keys[i] == key: - check += 1 - file_data.append(file_contents[key]) - else: - pass - if check != 1: - file_data.append(list_values[i]["default_value"]) - - -def Openextra(): - file_ = filedialog.askopenfilename(title="Select a Model", - filetypes=(('All files', '*'),)) - file_name.set(file_) - file = open(file_) - for line in file: - line = line.strip() - for i in range(len(list_keys)): - if ',' in line: - name = line.split(',')[0] - numbers = line.split(',')[1:] - if len(numbers) > 1: - fixed = numbers[:-1][0] + name = k + if old == name: + continue + else: + cont.append(name) + old = name + for n in name_each_subhead: + for i in cont: + if n == i: + x.append('y') + break else: - fixed = numbers[0] - if "[" in fixed and "]" in fixed: - temp = fixed.replace("[", "").replace("]", "") - fixed = [float(num) for num in temp.split(",")] - elif "," in fixed: - for num in fixed.split(","): - num = float(num) - elif "FALSE" in fixed.upper() or "TRUE" in fixed.upper(): - fixed = fixed + x.append('n') + for i in range(len(name_each_subhead)): + if headers[i] == 'aircraft' and x[i] == 'y': + BuildDataEntry(i, frame1) + elif headers[i] == 'mission' and x[i] == 'y': + BuildDataEntry(i, frame3) + elif headers[i] == "settings" and x[i] == 'y': + BuildDataEntry(i, frame4) + print(f'Model successfully imported from {file_name.get()}') + return file_contents, file_name, file_data + + filesaveas = tk.StringVar(value='Aircraft_Model.csv') + checksaveas = tk.IntVar(value=0) + + def Saveas(): + files = [('CSV', '*.csv'), + ('Text Document', '*.txt'), + ('All Files', '*.*')] + file__ = tk.filedialog.asksaveasfile(filetypes=files, defaultextension=files) + rename = str(file__).split("'")[1] + filesaveas.set(value=rename) + checksaveas.set(value=1) + WritetoCSV(file_contents, file_name, file_data, checksaveas, filesaveas) + return filesaveas, checksaveas + + def Instructions(): + message = 'This tool can be used to help input information about an aircraft model.\n\n' +\ + 'Enter in the desired values for your model and press "Submit" to generate ' +\ + 'a CSV named "Aircraft_Model" which can be used at Levels 1 and 2 of Aviary.\n' +\ + '*"Sumbit" will save "Aircraft_Model.csv" to the main "Aviary" folder unless otherwise specified.' +\ + ' if a file is opened "Submit" will automatically save to the specified file.' +\ + '**Not all values are required to successfully optimize a given model**\n\n' +\ + 'Use "Edit"->"Open" to open a previously defined model to continue editing.\n' +\ + 'Use "Edit"->"Open & Display" to open a previously defined model and all instances where edits were made.\n' +\ + '*Larger files may cause the interface to run slower.\n' +\ + 'Use "Edit"->"Save" to submit your entries to a CSV file (this has the same effect ' +\ + 'as the "Submit" button).\n' +\ + 'Use "Edit"->"Save as..." to save the file and all new commits to a new file name/location.\n' +\ + '*this will change where all new inforamtion is Submitted.\n' +\ + 'Use "Edit"->"Exit" to end the program.\n' +\ + '*make sure all progress is saved before exiting.\n\n' +\ + 'The "Search" tab can be used to quickly search and edit values.\n' +\ + 'Use the "Search" button to find a variable name and "Clear" to clear searched results.\n' +\ + '*When searching for a variable, the name must be the last term in the string ' +\ + 'i.e: "*:*:variable_name" (when applicable).\n' +\ + '*Values entered in for a variable and then cleared using the "Clear" button will still save.' + tk.messagebox.showinfo(title='Instructions', message=message) + + def About(): + tk.messagebox.showinfo(title='About', message='v1.0 - 2024') + + class DoubleScrolledFrame: + """ + https://gist.github.com/novel-yet-trivial/2841b7b640bba48928200ff979204115 + """ + + def __init__(self, master, **kwargs): + width = width_window + height = height_window + self.outer = tk.Frame(master, **kwargs) + + self.vsb = ttk.Scrollbar(self.outer, orient=tk.VERTICAL) + self.vsb.grid(row=0, column=1, sticky='ns') + self.hsb = ttk.Scrollbar(self.outer, orient=tk.HORIZONTAL) + self.hsb.grid(row=1, column=0, sticky='ew') + self.canvas = tk.Canvas( + self.outer, + highlightthickness=0, + width=width, + height=height) + self.canvas.grid(row=0, column=0, sticky='nsew') + self.outer.rowconfigure(0, weight=1) + self.outer.columnconfigure(0, weight=1) + self.canvas['yscrollcommand'] = self.vsb.set + self.canvas['xscrollcommand'] = self.hsb.set + self.canvas.bind("", self._bind_mouse) + self.canvas.bind("", self._unbind_mouse) + self.vsb['command'] = self.canvas.yview + self.hsb['command'] = self.canvas.xview + + self.inner = tk.Frame(self.canvas) + self.canvas.create_window(4, 4, window=self.inner, anchor='nw') + self.inner.bind("", self._on_frame_configure) + + self.outer_attr = set(dir(tk.Widget)) + + def __getattr__(self, item): + if item in self.outer_attr: + return getattr(self.outer, item) else: - try: - fixed = float(fixed) - except ValueError: + return getattr(self.inner, item) + + def _on_frame_configure(self, event=None): + x1, y1, x2, y2 = self.canvas.bbox("all") + height = self.canvas.winfo_height() + width = self.canvas.winfo_width() + self.canvas.config(scrollregion=(0, 0, max(x2, width), max(y2, height))) + + def _bind_mouse(self, event=None): + self.canvas.bind_all("<4>", self._on_mousewheel) + self.canvas.bind_all("<5>", self._on_mousewheel) + self.canvas.bind_all("", self._on_mousewheel) + + def _unbind_mouse(self, event=None): + self.canvas.unbind_all("<4>") + self.canvas.unbind_all("<5>") + self.canvas.unbind_all("") + + def _on_mousewheel(self, event): + """Linux uses event.num; Windows / Mac uses event.delta""" + func = self.canvas.xview_scroll if event.state & 1 else self.canvas.yview_scroll + if event.num == 4 or event.delta > 0: + func(-1, "units") + elif event.num == 5 or event.delta < 0: + func(1, "units") + + def __str__(self): + return str(self.outer) + + myframe = DoubleScrolledFrame(root) + myframe.pack() + + notebook = ttk.Notebook(myframe.inner) + notebook.pack(fill='both', expand=True, anchor='center') + frame1 = ttk.Frame(notebook) + frame3 = ttk.Frame(notebook) + frame4 = ttk.Frame(notebook) + frame5 = ttk.Frame(notebook) + notebook.add(frame1, text="Aircraft") + notebook.add(frame3, text="Mission") + notebook.add(frame4, text="Settings") + notebook.add(frame5, text="Search") + + tempdict = {} + + def WritetoCSV( + file_contents=file_contents, + file_name=file_name, + file_data=file_data, + checksaveas=checksaveas, + filesaveas=filesaveas): + list_of_lists = [] + for i, (key, value) in enumerate(zip(data.keys(), data.values())): + unit = value["units"] + if file_name.get() == 'Aircraft_Model.csv': + if key in tempdict.keys(): + list_of_lists.append([f'{key},{tempdict[key].get()},{unit}']) + elif ':' not in key: pass - variable = StringVar(value=name) - if variable.get() == list_keys[i]: - file_contents[variable.get()] = fixed + else: + list_of_lists.append([f'{key},{value["default_value"]},{unit}']) else: - pass - for i in range(len(list_keys)): - check = 0 - for key in file_contents.keys(): - if list_keys[i] == key: - check += 1 - file_data.append(file_contents[key]) - else: - pass - if check != 1: - file_data.append(list_values[i]["default_value"]) - cont = [] - x = [] - old = '' - for k in file_contents.keys(): - if ':' in k: - name = k.split(':')[1] - if old == name: - continue - else: - cont.append(name) - else: - name = k - if old == name: - continue + if key in tempdict.keys(): + list_of_lists.append([f'{key},{tempdict[key].get()},{unit}']) + elif ':' not in key: + pass + elif key in file_contents.keys(): + list_of_lists.append([f'{key},{file_data[i]},{unit}']) + else: + list_of_lists.append([f'{key},{value["default_value"]},{unit}']) + if file_name.get() == 'Aircraft_Model.csv' and checksaveas.get() != 1: + with open('Aircraft_Model.csv', 'w', newline='') as i: + writer = csv.writer(i, delimiter=';', quoting=csv.QUOTE_MINIMAL) + for sublist in list_of_lists: + writer.writerow(sublist) + elif file_name.get() == 'Aircraft_Model.csv' and checksaveas.get() == 1: + with open(filesaveas.get(), 'w', newline='') as i: + writer = csv.writer(i, delimiter=';', quoting=csv.QUOTE_MINIMAL) + for sublist in list_of_lists: + writer.writerow(sublist) + elif file_name.get() != 'Aircraft_Model.csv' and checksaveas.get() == 1: + with open(filesaveas.get(), 'w', newline='') as i: + writer = csv.writer(i, delimiter=';', quoting=csv.QUOTE_MINIMAL) + for sublist in list_of_lists: + writer.writerow(sublist) else: - cont.append(name) - old = name - for n in name_each_subhead: - for i in cont: - if n == i: - x.append('y') - break - else: - x.append('n') - for i in range(len(name_each_subhead)): - if headers[i] == 'aircraft' and x[i] == 'y': - BuildDataEntry(i, frame1) - elif headers[i] == 'dynamic' and x[i] == 'y': - BuildDataEntry(i, frame2) - elif headers[i] == 'mission' and x[i] == 'y': - BuildDataEntry(i, frame3) - elif headers[i] == "settings" and x[i] == 'y': - BuildDataEntry(i, frame4) - return file_contents, file_name, file_data - - -filesaveas = StringVar(value='Aircraft_Model.csv') -checksaveas = IntVar(value=0) - - -def Saveas(): - files = [('CSV', '*.csv'), - ('Text Document', '*.txt'), - ('All Files', '*.*')] - file__ = filedialog.asksaveasfile(filetypes=files, defaultextension=files) - rename = str(file__).split("'")[1] - filesaveas.set(value=rename) - checksaveas.set(value=1) - WritetoCSV(file_contents, file_name, file_data, checksaveas, filesaveas) - return filesaveas, checksaveas - - -def Instructions(): - message = 'This tool can be used to help input information about an aircraft model.\n\n' +\ - 'Enter in the desired values for your model and press "Submit" to generate ' +\ - 'a CSV named "Aircraft_Model" which can be used at Levels 1 and 2 of Aviary.\n\n' +\ - '**Not all values are required to successfully optimize a given model**\n\n' +\ - 'Use "Edit"->"Open" to open a previously defined model to continue editing.\n' +\ - 'Use "Edit"->"Open & Display" to open a previously defined model and all instances where edits were made\n' +\ - '*Larger files may cause the interface to run slower\n' +\ - 'Use "Edit"->"Save" to submit your entries to a CSV file (this has the same effect ' +\ - 'as the "Submit" button).\n' +\ - 'Use "Edit"->"Save as..." to save the file and all new commits to a new file name/location.\n' +\ - '*this will change where all new inforamtion is Submitted\n' +\ - 'Use "Edit"->"Exit" to end the program.\n' +\ - '*make sure all progress is saved before exiting\n\n' +\ - 'The "Search" tab can be used to quickly search and edit values\n' +\ - 'Use the "Search" button to find a variable name and "Clear" to clear searched results\n' +\ - '*When searching for a variable, the name must be the last term in the string ' +\ - 'i.e: "*:*:variable_name" (when applicable)\n' +\ - '*Values entered in for a variable and then cleared using the "Clear" button will still save' - messagebox.showinfo(title='Instructions', message=message) - - -def About(): - messagebox.showinfo(title='About', message='v1.0 - 2024') - - -class DoubleScrolledFrame: - """ - https://gist.github.com/novel-yet-trivial/2841b7b640bba48928200ff979204115 - """ + with open(file_name.get(), 'w', newline='') as i: + writer = csv.writer(i, delimiter=';', quoting=csv.QUOTE_MINIMAL) + for sublist in list_of_lists: + writer.writerow(sublist) + print(f'Model successfully Seved to {file_name.get()}') + + for i in range(len(name_each_subhead)): + if headers[i] == 'aircraft': + subhead = ttk.Label( + frame1, + justify='center', + text=name_each_subhead[i], + font=( + 'TkDefaultFont', + 15, + 'bold')) + button = ttk.Button( + frame1, + text=name_each_subhead[i], + width="20", + command=lambda i=i: BuildDataEntry( + i, + frame1)) + subhead.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + columnspan=1, + sticky='n', + pady=10) + button.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + column=2, + sticky='n', + pady=10) + elif headers[i] == 'mission': + subhead = ttk.Label( + frame3, + justify='center', + text=name_each_subhead[i], + font=( + 'TkDefaultFont', + 15, + 'bold')) + button = ttk.Button( + frame3, + text=name_each_subhead[i], + width="20", + command=lambda i=i: BuildDataEntry( + i, + frame3)) + subhead.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + columnspan=1, + sticky='n', + pady=10) + button.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + column=2, + sticky='n', + pady=10) + elif headers[i] == "settings": + subhead = ttk.Label( + frame4, + justify='center', + text=name_each_subhead[i], + font=( + 'TkDefaultFont', + 15, + 'bold')) + button = ttk.Button( + frame4, + text=name_each_subhead[i], + width="20", + command=lambda i=i: BuildDataEntry( + i, + frame4)) + subhead.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + columnspan=1, + sticky='n', + pady=10) + button.grid( + row=compound_data_rows[i] + + compound_subheaders[i], + column=2, + sticky='n', + pady=10) + + def BuildDataEntry( + x, + frame, + file_name=file_name, + file_contents=file_contents, + file_data=file_data): + num_rows = rows_per_subhead[x] + num = 0 + for row in range(num_rows): + if num < entries_per_subhead[x]: + for col in range(3): + i = index_list[x][num] + user_input = tk.StringVar( + value=f'{list_values[i]["default_value"]}') + if file_name.get() != 'Aircraft_Model.csv': + for key in list_keys: + if key in file_contents.keys(): + user_input = tk.StringVar(value=f'{file_data[i]}') + + input_title = ttk.Label(frame, justify='left', font=( + 'TkDefaultFont', 10, 'bold'), text=f'{list_keys[i]}') + input_title.grid( + row=( + row + + compound_subheaders[x] + + compound_data_rows[x] + + 1), + column=col, + pady=10, + padx=1, + sticky='nw') + + user_input_entry = ttk.Entry( + frame, width='10', textvariable=user_input) + user_input_entry.grid( + row=( + row + + compound_subheaders[x] + + compound_data_rows[x] + + 1), + column=col, + pady=30, + padx=1, + sticky='w') + + input_unit = ttk.Label( + frame, justify='left', font=( + 'TkDefaultFont', 10), text=f'{list_values[i]["units"]}') + input_unit.grid( + row=( + row + + compound_subheaders[x] + + compound_data_rows[x] + + 1), + column=col, + pady=30, + padx=75, + sticky='w') + + input_desc = ttk.Label( + frame, wraplength=120, justify='left', font=( + 'TkDefaultFont', 10), text=f'{list_values[i]["desc"]}') + input_desc.grid( + row=( + row + + compound_subheaders[x] + + compound_data_rows[x] + + 1), + column=col, + pady=30, + padx=150, + sticky='w') + + tempdict[list_keys[i]] = user_input + num += 1 + if num == entries_per_subhead[x]: + break + else: + break - def __init__(self, master, **kwargs): - width = width_window - height = height_window - self.outer = tk.Frame(master, **kwargs) - - self.vsb = ttk.Scrollbar(self.outer, orient=tk.VERTICAL) - self.vsb.grid(row=0, column=1, sticky='ns') - self.hsb = ttk.Scrollbar(self.outer, orient=tk.HORIZONTAL) - self.hsb.grid(row=1, column=0, sticky='ew') - self.canvas = tk.Canvas( - self.outer, - highlightthickness=0, - width=width, - height=height) - self.canvas.grid(row=0, column=0, sticky='nsew') - self.outer.rowconfigure(0, weight=1) - self.outer.columnconfigure(0, weight=1) - self.canvas['yscrollcommand'] = self.vsb.set - self.canvas['xscrollcommand'] = self.hsb.set - self.canvas.bind("", self._bind_mouse) - self.canvas.bind("", self._unbind_mouse) - self.vsb['command'] = self.canvas.yview - self.hsb['command'] = self.canvas.xview - - self.inner = tk.Frame(self.canvas) - self.canvas.create_window(4, 4, window=self.inner, anchor='nw') - self.inner.bind("", self._on_frame_configure) - - self.outer_attr = set(dir(tk.Widget)) - - def __getattr__(self, item): - if item in self.outer_attr: - return getattr(self.outer, item) - else: - return getattr(self.inner, item) - - def _on_frame_configure(self, event=None): - x1, y1, x2, y2 = self.canvas.bbox("all") - height = self.canvas.winfo_height() - width = self.canvas.winfo_width() - self.canvas.config(scrollregion=(0, 0, max(x2, width), max(y2, height))) - - def _bind_mouse(self, event=None): - self.canvas.bind_all("<4>", self._on_mousewheel) - self.canvas.bind_all("<5>", self._on_mousewheel) - self.canvas.bind_all("", self._on_mousewheel) - - def _unbind_mouse(self, event=None): - self.canvas.unbind_all("<4>") - self.canvas.unbind_all("<5>") - self.canvas.unbind_all("") - - def _on_mousewheel(self, event): - """Linux uses event.num; Windows / Mac uses event.delta""" - func = self.canvas.xview_scroll if event.state & 1 else self.canvas.yview_scroll - if event.num == 4 or event.delta > 0: - func(-1, "units") - elif event.num == 5 or event.delta < 0: - func(1, "units") - - def __str__(self): - return str(self.outer) - - -myframe = DoubleScrolledFrame(root) -myframe.pack() - -notebook = ttk.Notebook(myframe.inner) -notebook.pack(fill='both', expand=True, anchor='center') -frame1 = ttk.Frame(notebook) -frame2 = ttk.Frame(notebook) -frame3 = ttk.Frame(notebook) -frame4 = ttk.Frame(notebook) -frame5 = ttk.Frame(notebook) -notebook.add(frame1, text="Aircraft") -notebook.add(frame2, text="Dynamic") -notebook.add(frame3, text="Mission") -notebook.add(frame4, text="Settings") -notebook.add(frame5, text="Search") - -tempdict = {} - - -def WritetoCSV( - file_contents=file_contents, - file_name=file_name, - file_data=file_data, - checksaveas=checksaveas, - filesaveas=filesaveas): - list_of_lists = [] - for i, (key, value) in enumerate(zip(data.keys(), data.values())): - unit = value["units"] - if file_name.get() == 'Aircraft_Model.csv': - if key in tempdict.keys(): - list_of_lists.append([f'{key},{tempdict[key].get()},{unit}']) - else: - list_of_lists.append([f'{key},{value["default_value"]},{unit}']) - else: - if key in tempdict.keys(): - list_of_lists.append([f'{key},{tempdict[key].get()},{unit}']) - elif key in file_contents.keys(): - list_of_lists.append([f'{key},{file_data[i]},{unit}']) - else: - list_of_lists.append([f'{key},{value["default_value"]},{unit}']) - if file_name.get() == 'Aircraft_Model.csv' and checksaveas.get() != 1: - with open('Aircraft_Model.csv', 'w', newline='') as i: - writer = csv.writer(i, delimiter=';', quoting=csv.QUOTE_MINIMAL) - for sublist in list_of_lists: - writer.writerow(sublist) - elif file_name.get() == 'Aircraft_Model.csv' and checksaveas.get() == 1: - with open(filesaveas.get(), 'w', newline='') as i: - writer = csv.writer(i, delimiter=';', quoting=csv.QUOTE_MINIMAL) - for sublist in list_of_lists: - writer.writerow(sublist) - elif file_name.get() != 'Aircraft_Model.csv' and checksaveas.get() == 1: - with open(filesaveas.get(), 'w', newline='') as i: - writer = csv.writer(i, delimiter=';', quoting=csv.QUOTE_MINIMAL) - for sublist in list_of_lists: - writer.writerow(sublist) - else: - with open(file_name.get(), 'w', newline='') as i: - writer = csv.writer(i, delimiter=';', quoting=csv.QUOTE_MINIMAL) - for sublist in list_of_lists: - writer.writerow(sublist) - - -for i in range(len(name_each_subhead)): - if headers[i] == 'aircraft': - subhead = ttk.Label( - frame1, - justify='center', - text=name_each_subhead[i], - font=( - 'TkDefaultFont', - 15, - 'bold')) - button = ttk.Button( - frame1, - text=name_each_subhead[i], - width="20", - command=lambda i=i: BuildDataEntry( - i, - frame1)) - subhead.grid( - row=compound_data_rows[i] + - compound_subheaders[i], - columnspan=1, - sticky='n', - pady=10) - button.grid( - row=compound_data_rows[i] + - compound_subheaders[i], - column=2, - sticky='n', - pady=10) - elif headers[i] == 'dynamic': - subhead = ttk.Label( - frame2, + def Searchfxn( + x, + y, + add_row, + frame, + file_name=file_name, + file_contents=file_contents, + file_data=file_data): + i = index_list[x][y] + user_input = tk.StringVar(value=f'{list_values[i]["default_value"]}') + if file_name.get() != 'Aircraft_Model.csv': + for key in list_keys: + if key in file_contents.keys(): + user_input = tk.StringVar(value=f'{file_data[i]}') + + input_title = ttk.Label( + frame, + justify='left', + font=( + 'TkDefaultFont', + 10, + 'bold'), + text=f'{list_keys[i]}') + input_title.grid(row=4 + add_row, column=0, pady=10, padx=1, sticky='nw') + searchwidgets.append(input_title) + + user_input_entry = ttk.Entry(frame, width='10', textvariable=user_input) + user_input_entry.grid(row=5 + add_row, column=0, pady=10, padx=1, sticky='w') + searchwidgets.append(user_input_entry) + + input_unit = ttk.Label( + frame, + justify='left', + font=( + 'TkDefaultFont', + 10), + text=f'{list_values[i]["units"]}') + input_unit.grid(row=5 + add_row, column=1, pady=10, padx=20, sticky='w') + searchwidgets.append(input_unit) + + input_desc = ttk.Label( + frame, + wraplength=120, + justify='left', + font=( + 'TkDefaultFont', + 10), + text=f'{list_values[i]["desc"]}') + input_desc.grid(row=5 + add_row, column=3, pady=10, padx=20, sticky='w') + searchwidgets.append(input_desc) + + tempdict[list_keys[i]] = user_input + + searcheader = ttk.Frame(frame5) + searcheader.pack() + searchcontents = ttk.Frame(frame5) + searchcontents.pack(after=searcheader) + searchwidgets = [] + + def Search(keyword): + searchcontents = ttk.Frame(frame5) + searchcontents.pack(after=searcheader) + add_row = 0 + for i, key in enumerate(list_keys): + var = key.split(':')[-1] + if var == keyword: + add_row += 2 + count = 0 + for row in index_list: + count2 = 0 + for col in row: + if i == col: + Searchfxn(count, count2, add_row, searchcontents) + count2 += 1 + count += 1 + + def Clear(): + for widget in searchwidgets: + widget.destroy() + + Search_input = tk.StringVar(value='Enter Variable Name') + Search_label = ttk.Label( + searcheader, justify='center', - text=name_each_subhead[i], + text='Search variable name', font=( 'TkDefaultFont', 15, 'bold')) - button = ttk.Button( - frame2, - text=name_each_subhead[i], - width="20", - command=lambda i=i: BuildDataEntry( - i, - frame2)) - subhead.grid( - row=compound_data_rows[i] + - compound_subheaders[i], - columnspan=1, - sticky='n', - pady=10) - button.grid( - row=compound_data_rows[i] + - compound_subheaders[i], - column=2, - sticky='n', - pady=10) - elif headers[i] == 'mission': - subhead = ttk.Label( - frame3, - justify='center', - text=name_each_subhead[i], - font=( - 'TkDefaultFont', - 15, - 'bold')) - button = ttk.Button( - frame3, - text=name_each_subhead[i], - width="20", - command=lambda i=i: BuildDataEntry( - i, - frame3)) - subhead.grid( - row=compound_data_rows[i] + - compound_subheaders[i], - columnspan=1, - sticky='n', - pady=10) - button.grid( - row=compound_data_rows[i] + - compound_subheaders[i], - column=2, - sticky='n', - pady=10) - elif headers[i] == "settings": - subhead = ttk.Label( - frame4, - justify='center', - text=name_each_subhead[i], - font=( - 'TkDefaultFont', - 15, - 'bold')) - button = ttk.Button( - frame4, - text=name_each_subhead[i], - width="20", - command=lambda i=i: BuildDataEntry( - i, - frame4)) - subhead.grid( - row=compound_data_rows[i] + - compound_subheaders[i], - columnspan=1, - sticky='n', - pady=10) - button.grid( - row=compound_data_rows[i] + - compound_subheaders[i], - column=2, - sticky='n', - pady=10) - - -def BuildDataEntry( - x, - frame, - file_name=file_name, - file_contents=file_contents, - file_data=file_data): - num_rows = rows_per_subhead[x] - num = 0 - for row in range(num_rows): - if num < entries_per_subhead[x]: - for col in range(3): - i = index_list[x][num] - user_input = StringVar(value=f'{list_values[i]["default_value"]}') - if file_name.get() != 'Aircraft_Model.csv': - for key in list_keys: - if key in file_contents.keys(): - user_input = StringVar(value=f'{file_data[i]}') - - input_title = ttk.Label(frame, justify='left', font=( - 'TkDefaultFont', 10, 'bold'), text=f'{list_keys[i]}') - input_title.grid( - row=( - row + - compound_subheaders[x] + - compound_data_rows[x] + - 1), - column=col, - pady=10, - padx=1, - sticky='nw') - - user_input_entry = ttk.Entry(frame, width='10', textvariable=user_input) - user_input_entry.grid( - row=( - row + - compound_subheaders[x] + - compound_data_rows[x] + - 1), - column=col, - pady=30, - padx=1, - sticky='w') - - input_unit = ttk.Label( - frame, justify='left', font=( - 'TkDefaultFont', 10), text=f'{list_values[i]["units"]}') - input_unit.grid( - row=( - row + - compound_subheaders[x] + - compound_data_rows[x] + - 1), - column=col, - pady=30, - padx=75, - sticky='w') - - input_desc = ttk.Label( - frame, wraplength=120, justify='left', font=( - 'TkDefaultFont', 10), text=f'{list_values[i]["desc"]}') - input_desc.grid( - row=( - row + - compound_subheaders[x] + - compound_data_rows[x] + - 1), - column=col, - pady=30, - padx=150, - sticky='w') - - tempdict[list_keys[i]] = user_input - num += 1 - if num == entries_per_subhead[x]: - break - else: - break - - -def Searchfxn( - x, - y, - add_row, - frame, - file_name=file_name, - file_contents=file_contents, - file_data=file_data): - i = index_list[x][y] - user_input = StringVar(value=f'{list_values[i]["default_value"]}') - if file_name.get() != 'Aircraft_Model.csv': - for key in list_keys: - if key in file_contents.keys(): - user_input = StringVar(value=f'{file_data[i]}') - - input_title = ttk.Label( - frame, - justify='left', - font=( - 'TkDefaultFont', - 10, - 'bold'), - text=f'{list_keys[i]}') - input_title.grid(row=4 + add_row, column=0, pady=10, padx=1, sticky='nw') - searchwidgets.append(input_title) - - user_input_entry = ttk.Entry(frame, width='10', textvariable=user_input) - user_input_entry.grid(row=5 + add_row, column=0, pady=10, padx=1, sticky='w') - searchwidgets.append(user_input_entry) - - input_unit = ttk.Label( - frame, - justify='left', - font=( - 'TkDefaultFont', - 10), - text=f'{list_values[i]["units"]}') - input_unit.grid(row=5 + add_row, column=1, pady=10, padx=20, sticky='w') - searchwidgets.append(input_unit) - - input_desc = ttk.Label( - frame, - wraplength=120, - justify='left', - font=( - 'TkDefaultFont', - 10), - text=f'{list_values[i]["desc"]}') - input_desc.grid(row=5 + add_row, column=3, pady=10, padx=20, sticky='w') - searchwidgets.append(input_desc) - - tempdict[list_keys[i]] = user_input - - -searcheader = ttk.Frame(frame5) -searcheader.pack() -searchcontents = ttk.Frame(frame5) -searchcontents.pack(after=searcheader) -searchwidgets = [] - - -def Search(keyword): - searchcontents = ttk.Frame(frame5) - searchcontents.pack(after=searcheader) - add_row = 0 - for i, key in enumerate(list_keys): - var = key.split(':')[-1] - if var == keyword: - add_row += 2 - count = 0 - for row in index_list: - count2 = 0 - for col in row: - if i == col: - Searchfxn(count, count2, add_row, searchcontents) - count2 += 1 - count += 1 - - -def Clear(): - for widget in searchwidgets: - widget.destroy() - - -Search_input = StringVar(value='Enter Variable Name') -Search_label = ttk.Label( - searcheader, - justify='center', - text='Search variable name', - font=( - 'TkDefaultFont', - 15, - 'bold')) -Search_label.grid(row=2, column=0) -Search_entry = ttk.Entry(searcheader, width='30', textvariable=Search_input) -Search_entry.grid(row=3, column=0) -Search_button = ttk.Button( - searcheader, - text='Search', - width="10", - command=lambda i=i: Search( - Search_input.get())) -Search_button.grid(row=3, column=1) -Clear_button = ttk.Button(searcheader, text='Clear', width="10", command=lambda: Clear()) -Clear_button.grid(row=3, column=2) - - -menubar = Menu(root) -filemenu = Menu(menubar, tearoff=0) -filemenu.add_command(label='Open', command=Open) -filemenu.add_command(label='Open & Display', command=Openextra) -filemenu.add_command(label='Save', command=WritetoCSV) -filemenu.add_command(label='Save as...', command=Saveas) -filemenu.add_separator() -filemenu.add_command(label="Exit", command=root.quit) -menubar.add_cascade(label="File", menu=filemenu) -helpmenu = Menu(menubar, tearoff=0) -helpmenu.add_command(label="Instructions", command=Instructions) -helpmenu.add_command(label="About...", command=About) -menubar.add_cascade(label="Help", menu=helpmenu) -root.config(menu=menubar) - - -button_main = ttk.Button(root, text="Submit", width="20", command=WritetoCSV) -button_main.pack(before=notebook, pady=10) -root.mainloop() + Search_label.grid(row=2, column=0) + Search_entry = ttk.Entry(searcheader, width='30', textvariable=Search_input) + Search_entry.grid(row=3, column=0) + Search_button = ttk.Button( + searcheader, + text='Search', + width="10", + command=lambda i=i: Search( + Search_input.get())) + Search_button.grid(row=3, column=1) + Clear_button = ttk.Button( + searcheader, + text='Clear', + width="10", + command=lambda: Clear()) + Clear_button.grid(row=3, column=2) + + menubar = tk.Menu(root) + filemenu = tk.Menu(menubar, tearoff=0) + filemenu.add_command(label='Open', command=Open) + filemenu.add_command(label='Open & Display', command=Openextra) + filemenu.add_command(label='Save', command=WritetoCSV) + filemenu.add_command(label='Save as...', command=Saveas) + filemenu.add_separator() + filemenu.add_command(label="Exit", command=root.quit) + menubar.add_cascade(label="File", menu=filemenu) + helpmenu = tk.Menu(menubar, tearoff=0) + helpmenu.add_command(label="Instructions", command=Instructions) + helpmenu.add_command(label="About...", command=About) + menubar.add_cascade(label="Help", menu=helpmenu) + root.config(menu=menubar) + + button_main = ttk.Button(root, text="Submit", width="20", command=WritetoCSV) + button_main.pack(before=notebook, pady=10) + root.mainloop() + + +def _setup_build_model_parser(parser): + """ + Set up the command line options for the Model Building tool. + + Parameters + ---------- + parser : argparse.ArgumentParser + The parser instance. + parser : argparse subparser + The parser we're adding options to. + """ + # parser.add_argument( + # "--open", + # type=str, + # help="Open a file to continue editing.", + # ) + + # parser.add_argument( + # "--open_display", + # type=str, + # help="Open a file and all instances that have been modified to continue editing.", + # ) + pass + + +def _exec_build_model(options, user_args): + """ + Run the Model Building tool. + + Parameters + ---------- + options : argparse.Namespace + Command line options. + user_args : list of str + Args to be passed to the user script. + """ + build_model() + + +if __name__ == "__main__": + # parser = argparse.ArgumentParser() + # _build_model_setup_parser(parser) + # args = parser.parse_args() + # _exec_build_model(args, None) + build_model() diff --git a/aviary/interface/cmd_entry_points.py b/aviary/interface/cmd_entry_points.py index 71f2ff959..e8b7d2bcd 100644 --- a/aviary/interface/cmd_entry_points.py +++ b/aviary/interface/cmd_entry_points.py @@ -11,6 +11,7 @@ from aviary.visualization.dashboard import _dashboard_setup_parser, _dashboard_cmd from aviary.interface.graphical_input import _exec_flight_profile, _setup_flight_profile_parser from aviary.interface.download_models import _exec_hangar, _setup_hangar_parser +from aviary.interface.build_model import _exec_build_model, _setup_build_model_parser def _load_and_exec(script_name, user_args): @@ -58,6 +59,8 @@ def _load_and_exec(script_name, user_args): 'Converts FLOPS- or GASP-formatted aero data files into Aviary csv format.'), 'convert_prop_table': (_setup_PMC_parser, _exec_PMC, 'Converts GASP-formatted propeller map file into Aviary csv format.'), + 'build_model': (_setup_build_model_parser, _exec_build_model, + 'Build or edit an aircraft model.'), } @@ -97,10 +100,11 @@ def aviary_cmd(): cmdargs = [a for a in sys.argv[1:] if a not in ('-h',)] if len(args) == 1 and len(user_args) == 0: - if args[0] != 'draw_mission' and args[0] != 'run_mission': + if args[0] != 'draw_mission' and args[0] != 'run_mission' and args[0] != 'build_model': parser.parse_args([args[0], '-h']) - if not set(args).intersection(subs.choices) and len(args) == 1 and os.path.isfile(cmdargs[0]): + if not set(args).intersection(subs.choices) and len( + args) == 1 and os.path.isfile(cmdargs[0]): _load_and_exec(args[0], user_args) else: options, unknown = parser.parse_known_args() From 78bc14545b6847df38a62d8a4bc19da654d82a8f Mon Sep 17 00:00:00 2001 From: Manning Date: Tue, 30 Jul 2024 15:02:21 -0400 Subject: [PATCH 11/14] Update format --- aviary/interface/build_model.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/aviary/interface/build_model.py b/aviary/interface/build_model.py index 4be42f418..799248190 100644 --- a/aviary/interface/build_model.py +++ b/aviary/interface/build_model.py @@ -12,7 +12,6 @@ def __init__(self): data = deepcopy(api.CoreMetaData) list_values = list(data.values()) list_keys = list(data.keys()) - # list_len = len(list_values) root = tk.Tk() source_directory = os.path.abspath(os.path.dirname(__file__)) root.iconphoto( @@ -673,17 +672,6 @@ def _setup_build_model_parser(parser): parser : argparse subparser The parser we're adding options to. """ - # parser.add_argument( - # "--open", - # type=str, - # help="Open a file to continue editing.", - # ) - - # parser.add_argument( - # "--open_display", - # type=str, - # help="Open a file and all instances that have been modified to continue editing.", - # ) pass @@ -702,8 +690,4 @@ def _exec_build_model(options, user_args): if __name__ == "__main__": - # parser = argparse.ArgumentParser() - # _build_model_setup_parser(parser) - # args = parser.parse_args() - # _exec_build_model(args, None) build_model() From 7a911866163012958e3c4fbc332a944d61b84d33 Mon Sep 17 00:00:00 2001 From: Manning Date: Thu, 1 Aug 2024 12:11:42 -0400 Subject: [PATCH 12/14] Update to Instructions --- aviary/interface/build_model.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/aviary/interface/build_model.py b/aviary/interface/build_model.py index 799248190..73f5fd762 100644 --- a/aviary/interface/build_model.py +++ b/aviary/interface/build_model.py @@ -215,10 +215,11 @@ def Saveas(): def Instructions(): message = 'This tool can be used to help input information about an aircraft model.\n\n' +\ 'Enter in the desired values for your model and press "Submit" to generate ' +\ - 'a CSV named "Aircraft_Model" which can be used at Levels 1 and 2 of Aviary.\n' +\ - '*"Sumbit" will save "Aircraft_Model.csv" to the main "Aviary" folder unless otherwise specified.' +\ - ' if a file is opened "Submit" will automatically save to the specified file.' +\ - '**Not all values are required to successfully optimize a given model**\n\n' +\ + 'a CSV named "Aircraft_Model" which can be used at Levels 1, 2, and 3 of Aviary.\n' +\ + '*"Sumbit" will save "Aircraft_Model.csv" to the main "Aviary" folder unless otherwise specified.\n' +\ + 'If a file is opened "Submit" will automatically save to the specified file.\n\n' +\ + '*Not all values are required to successfully optimize a given model*\n' +\ + 'Default values will be used where there is no user input.\n\n' +\ 'Use "Edit"->"Open" to open a previously defined model to continue editing.\n' +\ 'Use "Edit"->"Open & Display" to open a previously defined model and all instances where edits were made.\n' +\ '*Larger files may cause the interface to run slower.\n' +\ @@ -231,7 +232,7 @@ def Instructions(): 'The "Search" tab can be used to quickly search and edit values.\n' +\ 'Use the "Search" button to find a variable name and "Clear" to clear searched results.\n' +\ '*When searching for a variable, the name must be the last term in the string ' +\ - 'i.e: "*:*:variable_name" (when applicable).\n' +\ + 'i.e: "*:*:variable_name".\n' +\ '*Values entered in for a variable and then cleared using the "Clear" button will still save.' tk.messagebox.showinfo(title='Instructions', message=message) From beabe948eb9181059957a3a4b0920cf9946780ae Mon Sep 17 00:00:00 2001 From: Manning Date: Tue, 6 Aug 2024 15:26:07 -0400 Subject: [PATCH 13/14] fixes to variable names --- aviary/variable_info/variable_meta_data.py | 24 +++++++++++----------- aviary/variable_info/variables.py | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index 3459f1f37..f82822031 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -1226,18 +1226,6 @@ desc='total mass of fixed useful load: crew, service items, trapped oil, etc', ) -add_meta_data( - Aircraft.Design.IJEFF, - meta_data=_MetaData, - historical_name={"GASP": 'INGASP.IJEFF', - "FLOPS": None, - "LEAPS1": None - }, - desc="A flag used by Jeff V. Bowles to debug GASP code during his 53 years supporting the development of GASP. " - "This flag is planted here to thank him for his hard work and dedication, Aviary wouldn't be what it is today " - "without his help.", -) - add_meta_data( Aircraft.Design.LAMINAR_FLOW_LOWER, meta_data=_MetaData, @@ -1621,6 +1609,18 @@ desc='Scaling factor for zero-lift drag coefficient' ) +add_meta_data( + Aircraft.Design.IJEFF, + meta_data=_MetaData, + historical_name={"GASP": 'INGASP.IJEFF', + "FLOPS": None, + "LEAPS1": None + }, + desc="A flag used by Jeff V. Bowles to debug GASP code during his 53 years supporting the development of GASP. " + "This flag is planted here to thank him for his hard work and dedication, Aviary wouldn't be what it is today " + "without his help.", +) + # # ______ _ _ _ _ # | ____| | | | | (_) | | diff --git a/aviary/variable_info/variables.py b/aviary/variable_info/variables.py index 9af80b45d..c23292266 100644 --- a/aviary/variable_info/variables.py +++ b/aviary/variable_info/variables.py @@ -155,7 +155,6 @@ class Design: FINENESS = 'aircraft:design:fineness' FIXED_EQUIPMENT_MASS = 'aircraft:design:fixed_equipment_mass' FIXED_USEFUL_LOAD = 'aircraft:design:fixed_useful_load' - IJEFF = 'aircraft:design:ijeff' LAMINAR_FLOW_LOWER = 'aircraft:design:laminar_flow_lower' LAMINAR_FLOW_UPPER = 'aircraft:design:laminar_flow_upper' @@ -197,6 +196,7 @@ class Design: ZERO_FUEL_MASS = 'aircraft:design:zero_fuel_mass' ZERO_LIFT_DRAG_COEFF_FACTOR = \ 'aircraft:design:zero_lift_drag_coeff_factor' + IJEFF = 'ijeff' class Electrical: HAS_HYBRID_SYSTEM = 'aircraft:electrical:has_hybrid_system' From bb03bf741c35033d26366601744b24372cebaeb8 Mon Sep 17 00:00:00 2001 From: Manning Date: Tue, 6 Aug 2024 15:29:53 -0400 Subject: [PATCH 14/14] suggested cmd changes --- aviary/interface/cmd_entry_points.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aviary/interface/cmd_entry_points.py b/aviary/interface/cmd_entry_points.py index e8b7d2bcd..9f9596cc0 100644 --- a/aviary/interface/cmd_entry_points.py +++ b/aviary/interface/cmd_entry_points.py @@ -100,7 +100,7 @@ def aviary_cmd(): cmdargs = [a for a in sys.argv[1:] if a not in ('-h',)] if len(args) == 1 and len(user_args) == 0: - if args[0] != 'draw_mission' and args[0] != 'run_mission' and args[0] != 'build_model': + if args[0] not in ('draw_mission', 'run_mission', 'build_model'): parser.parse_args([args[0], '-h']) if not set(args).intersection(subs.choices) and len(