Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Retry: create the GUI script file attr_form_gui.py in /mnt/data and report result.
- import os, textwrap, sys
- OUTFILE = "/mnt/data/attr_form_gui.py"
- code = r'''"""
- attr_form_gui.py
- Phase 3: Dynamic GUI form that builds widgets based on attribute_properties JSON and YAML config.
- Saves completed work entries into work_properties table as JSON.
- Requires: ttkbootstrap, pyyaml
- Run: python attr_form_gui.py
- """
- import os, sqlite3, json, yaml, datetime, random, string, sys
- import tkinter as tk
- from tkinter import ttk, messagebox, simpledialog
- import ttkbootstrap as tb
- DB_PATH = "wdyd4.db"
- YAML_PATH = "attributes_config.yaml"
- # ---------- Phase1 utilities (embedded) ----------
- def load_config(config_path=YAML_PATH):
- if not os.path.exists(config_path):
- return {"attributes": [], "attribute_properties": [], "maximum_binded_attribute_support": 1}
- with open(config_path, "r", encoding="utf-8") as f:
- cfg = yaml.safe_load(f) or {}
- cfg.setdefault("attributes", [])
- cfg.setdefault("attribute_properties", [])
- cfg.setdefault("maximum_binded_attribute_support", 1)
- return cfg
- def formWorkID(prefix="WDY"):
- now = datetime.datetime.utcnow()
- core = now.strftime("%y%m%d%H%M%S%f")[:-3]
- suffix = ''.join(random.choices(string.ascii_uppercase + string.digits, k=2))
- return f"{prefix}{core}{suffix}"
- def _get_db_conn(db_path=DB_PATH):
- if not os.path.exists(db_path):
- raise FileNotFoundError(f"DB not found at {db_path}")
- return sqlite3.connect(db_path)
- def get_attribute_properties(attr_name, db_path=DB_PATH):
- conn = _get_db_conn(db_path)
- cur = conn.cursor()
- cur.execute("SELECT properties_json FROM attribute_properties WHERE attribute_name = ?", (attr_name,))
- row = cur.fetchone()
- conn.close()
- if not row: return None
- try:
- return json.loads(row[0])
- except Exception:
- return row[0]
- def get_dropdown_items(attr_name, db_path=DB_PATH):
- props = get_attribute_properties(attr_name, db_path=db_path)
- if not props or not isinstance(props, dict): return []
- for key in ("DropdownItems","dropdownitems","dropdown_items","dropdown"):
- if key in props:
- val = props[key]
- if isinstance(val, list): return val
- try:
- parsed = json.loads(val)
- if isinstance(parsed, list): return parsed
- except Exception:
- pass
- return []
- def get_default_value(attr_name, db_path=DB_PATH):
- props = get_attribute_properties(attr_name, db_path=db_path)
- if not props or not isinstance(props, dict): return None
- for key in ("DefaultValue","Default","defaultvalue","default"):
- if key in props: return props[key]
- return None
- def is_flag_true(attr_name, flag, db_path=DB_PATH):
- props = get_attribute_properties(attr_name, db_path=db_path)
- if not props or not isinstance(props, dict): return False
- if flag in props: return bool(props[flag])
- alt = flag.replace(" ", "").replace("_","").lower()
- for k,v in props.items():
- if k.replace(" ","").replace("_","").lower() == alt:
- return bool(v)
- return False
- # ---------- Phase2 DB helpers (embedded) ----------
- def ensure_work_tables(db_path=DB_PATH):
- conn = _get_db_conn(db_path); cur = conn.cursor()
- cur.execute("""CREATE TABLE IF NOT EXISTS work_properties (
- work_id TEXT PRIMARY KEY, user_name TEXT, properties_json TEXT, created_at TEXT)""")
- conn.commit(); conn.close()
- def list_attributes(db_path=DB_PATH):
- conn = _get_db_conn(db_path); cur = conn.cursor()
- cur.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='Attributes'")
- if not cur.fetchone():
- conn.close(); return []
- cur.execute("SELECT attributeName FROM Attributes ORDER BY attributeID")
- rows = [r[0] for r in cur.fetchall()]; conn.close(); return rows
- def insert_final_work(work_id, user_name, properties_dict, db_path=DB_PATH):
- conn = _get_db_conn(db_path); cur = conn.cursor()
- cur.execute("INSERT OR REPLACE INTO work_properties (work_id, user_name, properties_json, created_at) VALUES (?, ?, ?, ?)",
- (work_id, user_name, json.dumps(properties_dict, ensure_ascii=False), datetime.datetime.utcnow().isoformat()))
- conn.commit(); conn.close()
- # ---------- GUI widget constructors ----------
- def DrawTheDateEntry(frame, attr_name, default=None):
- lbl = ttk.Label(frame, text=attr_name + " (Date):")
- ent = ttk.Entry(frame)
- if default:
- ent.insert(0, default)
- lbl.pack(fill="x", padx=4, pady=(4,0))
- ent.pack(fill="x", padx=4, pady=(0,6))
- return ent
- def DrawEntryWidget(frame, attr_name, default=None):
- lbl = ttk.Label(frame, text=attr_name + ":")
- ent = ttk.Entry(frame)
- if default:
- ent.insert(0, default)
- lbl.pack(fill="x", padx=4, pady=(4,0))
- ent.pack(fill="x", padx=4, pady=(0,6))
- return ent
- def DrawTheCombobox(frame, attr_name, items, default=None):
- lbl = ttk.Label(frame, text=attr_name + " (Select):")
- combo = ttk.Combobox(frame, values=items)
- if default:
- combo.set(default)
- lbl.pack(fill="x", padx=4, pady=(4,0))
- combo.pack(fill="x", padx=4, pady=(0,6))
- btn = ttk.Button(frame, text="Add item", command=lambda: handleAddDropdownItem(attr_name, combo))
- btn.pack(anchor="e", padx=4, pady=(0,6))
- return combo
- def handleAddDropdownItem(attr_name, combobox_widget):
- new_item = simpledialog.askstring("Add dropdown item", f"New item for {attr_name}:")
- if not new_item: return
- props = get_attribute_properties(attr_name) or {}
- items = props.get("DropdownItems", [])
- if not isinstance(items, list): items = []
- items.append(new_item)
- props["DropdownItems"] = items
- conn = _get_db_conn()
- cur = conn.cursor()
- cur.execute("UPDATE attribute_properties SET properties_json = ? WHERE attribute_name = ?", (json.dumps(props, ensure_ascii=False), attr_name))
- conn.commit(); conn.close()
- combobox_widget['values'] = items
- combobox_widget.set(new_item)
- messagebox.showinfo("Added", f"Added '{new_item}' to {attr_name} dropdown items.")
- # ---------- Main form builder ----------
- class DynamicFormApp:
- def __init__(self, master, user_name="default"):
- self.master = master
- self.user_name = user_name
- master.title("WDYD Dynamic Form")
- ensure_work_tables()
- self.cfg = load_config()
- self.universal = self._build_universal_dict()
- self.mandatory_attrs = self.universal.get("Mandatory", [])
- if not self.mandatory_attrs:
- self.mandatory_attrs = list_attributes()
- self.widgets = {}
- self._build_ui()
- def _build_universal_dict(self):
- keys = ["Mandatory","HasDropdown","IsDate","HasDefault","HasBinded","CanHaveMultipleValueInLifetime"]
- d = {k: [] for k in keys}
- conn = _get_db_conn(); cur = conn.cursor()
- cur.execute("SELECT attribute_name, properties_json FROM attribute_properties")
- for name, pjson in cur.fetchall():
- try:
- props = json.loads(pjson)
- except Exception:
- continue
- for k in keys:
- for pk, pv in props.items():
- if pk.replace(" ", "").lower() == k.replace(" ",").lower():
- if pv:
- d[k].append(name)
- break
- conn.close()
- return d
- def _build_ui(self):
- style = tb.Style(theme="litera")
- frame = ttk.Frame(self.master, padding=12)
- frame.pack(fill="both", expand=True)
- form_area = ttk.Frame(frame)
- form_area.pack(fill="both", expand=True)
- for attr in self.mandatory_attrs:
- if is_flag_true(attr, "IsDate"):
- default = get_default_value(attr)
- wid = DrawTheDateEntry(form_area, attr, default=default)
- elif is_flag_true(attr, "HasDropdown"):
- items = get_dropdown_items(attr)
- default = get_default_value(attr)
- wid = DrawTheCombobox(form_area, attr, items, default=default)
- else:
- default = get_default_value(attr)
- wid = DrawEntryWidget(form_area, attr, default=default)
- self.widgets[attr] = wid
- btn = ttk.Button(frame, text="Submit", bootstyle="success", command=self.submit)
- btn.pack(pady=8)
- def submit(self):
- data = {}
- for attr, widget in self.widgets.items():
- try:
- val = widget.get()
- except Exception:
- val = ""
- data[attr] = val
- wid = formWorkID()
- insert_final_work(wid, self.user_name, data)
- messagebox.showinfo("Saved", f"Work saved with ID: {wid}")
- def main():
- root = tb.Window(themename="litera")
- app = DynamicFormApp(root)
- root.mainloop()
- if __name__ == "__main__":
- main()
- '''
- try:
- with open(OUTFILE, "w", encoding="utf-8") as f:
- f.write(code)
- created = True
- except Exception as e:
- created = False
- err = str(e)
- {"created_file": OUTFILE, "created": created, "error": err if not created else None}
Advertisement
Add Comment
Please, Sign In to add comment