# Custom from model import * from appstate import * # External from imgui_bundle import ( imgui, imgui_ctx, immapp, imgui_md, im_file_dialog, hello_imgui ) # Built In from typing import List import shelve from pathlib import Path from datetime import datetime def file_info(path: Path) -> None: stat = path.stat() modified = datetime.fromtimestamp(stat.st_atime) created = datetime.fromtimestamp(stat.st_ctime) format = '%c' data = { "File": path.name, "Size": f"{stat.st_size/100} KB", "Modified": modified.strftime(format), "Created": created.strftime(format) } if imgui.begin_table("File Info", 2): imgui.table_setup_column(" ", 0) imgui.table_setup_column(" ") for k, v in data.items(): imgui.push_id(k) imgui.table_next_row() imgui.table_next_column() imgui.text(k) imgui.table_next_column() imgui.text(v) imgui.pop_id() imgui.end_table() @immapp.static(inited=False, res=False) def select_file(app_state: AppState): statics = select_file if not statics.inited: statics.res = None statics.current = None with shelve.open("state") as state: statics.current = Path(state["DB"]) statics.inited = True imgui_md.render("# Database Manager") file_info(statics.current) if imgui.button("Open File"): im_file_dialog.FileDialog.instance().open("SelectDatabase", "Open Database", "Database File (*.json;*.db){.json,.db}") if im_file_dialog.FileDialog.instance().is_done("SelectDatabase"): if im_file_dialog.FileDialog.instance().has_result(): statics.res = im_file_dialog.FileDialog.instance().get_result() LOG_INFO(f"Load File {statics.res}") im_file_dialog.FileDialog.instance().close() if statics.res: filename = statics.res.filename() info = Path(statics.res.path()) imgui.separator() file_info(info) file = None if imgui.button("Load"): if not db.is_closed(): db.close() if statics.res.extension() == '.json': file = filename.removesuffix('.json') file = file + '.db' db.init(file) db.connect(reuse_if_open=True) db.create_tables([Class, Student, Lecture, Submission]) load_from_json(str(info)) LOG_INFO(f"Successfully created {file}") if statics.res.extension() == '.db': file = str(statics.res.path()) db.init(file) db.connect(reuse_if_open=True) db.create_tables([Class, Student, Lecture, Submission]) LOG_INFO(f"Successfully loaded {filename}") with shelve.open("state") as state: state["DB"] = file app_state.update() statics.res = None @immapp.static(inited=False) def table(app_state: AppState) -> None: statics = table if not statics.inited: statics.class_id = None statics.lectures = None statics.points = list() statics.inited = True if statics.class_id != app_state.current_class_id: statics.class_id = app_state.current_class_id statics.lectures = Lecture.select().where(Lecture.class_id == statics.class_id) statics.data = dict() for student in Student.select().where(Student.class_id == statics.class_id): subs = Submission.select().where(Submission.student_id == student.id) points = [sub.points for sub in subs] statics.data[f"{student.prename} {student.surname}"] = points if not statics.lectures: imgui.text("No Lecture queried") return table_flags = ( imgui.TableFlags_.row_bg.value | imgui.TableFlags_.borders.value | imgui.TableFlags_.resizable.value | imgui.TableFlags_.sizing_stretch_same.value ) if imgui.begin_table("Overview", len(statics.lectures)+1, table_flags): imgui.table_setup_column("Students") for n, lecture in enumerate(statics.lectures, start=1): imgui.table_setup_column(f"{n}. {lecture.title} ({lecture.points})") imgui.table_setup_scroll_freeze(1, 1) imgui.table_headers_row() for k, v in statics.data.items(): imgui.push_id(k) imgui.table_next_row() imgui.table_next_column() imgui.text(k) for points in v: imgui.table_next_column() if points.is_integer(): points = int(points) imgui.text(str(points)) imgui.pop_id() imgui.end_table() @immapp.static(inited=False) def class_editor() -> None: statics = class_editor if not statics.inited: statics.classes = None statics.selected = 0 statics.inited = True statics.classes = Class.select() imgui_md.render("# Edit Classes") _, statics.selected = imgui.combo("Classes", statics.selected, [c.name for c in statics.classes]) imgui.text(statics.classes[statics.selected].name) def database_editor(app_state: AppState) -> None: class_editor() def database_docking_splits() -> List[hello_imgui.DockingSplit]: split_main_command = hello_imgui.DockingSplit() split_main_command.initial_dock = "MainDockSpace" split_main_command.new_dock = "CommandSpace" split_main_command.direction = imgui.Dir.down split_main_command.ratio = 0.3 # Log Space split_main_command2 = hello_imgui.DockingSplit() split_main_command2.initial_dock = "CommandSpace" split_main_command2.new_dock = "CommandSpace2" split_main_command2.direction = imgui.Dir.right split_main_command2.ratio = 0.3 split_main_misc = hello_imgui.DockingSplit() split_main_misc.initial_dock = "MainDockSpace" split_main_misc.new_dock = "MiscSpace" split_main_misc.direction = imgui.Dir.left split_main_misc.ratio = 0.2 splits = [split_main_misc, split_main_command, split_main_command2] return splits def set_database_editor_layout(app_state: AppState) -> List[hello_imgui.DockableWindow]: file_dialog = hello_imgui.DockableWindow() file_dialog.label = "Database" file_dialog.dock_space_name = "MiscSpace" file_dialog.gui_function = lambda: select_file(app_state) log = hello_imgui.DockableWindow() log.label = "Logs" log.dock_space_name = "CommandSpace2" log.gui_function = hello_imgui.log_gui table_view = hello_imgui.DockableWindow() table_view.label = "Table" table_view.dock_space_name = "MainDockSpace" table_view.gui_function = lambda: table(app_state) editor = hello_imgui.DockableWindow() editor.label = "Editor" editor.dock_space_name = "CommandSpace" editor.gui_function = lambda: database_editor(app_state) return [ file_dialog, log, table_view, editor ] def database_editor_layout(app_state: AppState) -> hello_imgui.DockingParams: docking_params = hello_imgui.DockingParams() docking_params.layout_name = "Database Editor" docking_params.docking_splits = database_docking_splits() docking_params.dockable_windows = set_database_editor_layout(app_state) return docking_params