Changeset f0f3ded in flexograder
- Timestamp:
- 01/14/26 12:52:10 (23 hours ago)
- Branches:
- master
- Children:
- 64883b1
- Parents:
- 705a7df
- Location:
- flexograder
- Files:
-
- 2 added
- 3 edited
-
environment.py (modified) (5 diffs)
-
gui/gui.py (modified) (15 diffs)
-
managers/catalog_manager.py (modified) (1 diff)
-
os/application.py (added)
-
os/profile.py (added)
Legend:
- Unmodified
- Added
- Removed
-
flexograder/environment.py
r705a7df rf0f3ded 1 from pathlib import Path2 1 import json 3 2 import sqlite3 4 3 5 from flexoentity import SQLiteEntityBackend, EntityManager, RuntimeBackend4 from flexoentity import SQLiteEntityBackend, RuntimeBackend, DomainManager, Domain 6 5 7 6 from flexograder.core_entities.exam import Exam 8 7 from flexograder.core_entities.question_catalog import QuestionCatalog 9 from flexograder.core_entities.exam_elements import ChoiceQuestion,ExamElement, element_factory8 from flexograder.core_entities.exam_elements import ExamElement, element_factory 10 9 from flexograder.core_entities.flexo_user import FlexoUser 11 10 from flexograder.managers.catalog_manager import CatalogManager … … 22 21 23 22 return [ 24 question_factory(json.loads(r["json"]))23 element_factory(json.loads(r["json"])) 25 24 for r in rows 26 25 ] … … 35 34 return None 36 35 37 return question_factory(json.loads(row["json"])) 36 return element_factory(json.loads(row["json"])) 37 38 38 39 39 class Environment: … … 47 47 """ 48 48 49 def __init__(self, registry): 49 def __init__(self, profile, registry): 50 self.profile = profile 50 51 self.registry = registry 51 self.base_dir = self._resolve_base_dir()52 self.db_path = self.base_dir/ "flexo.db"52 self.base_dir = profile.paths.user_data 53 self.db_path = profile.paths.user_data / "flexo.db" 53 54 54 55 self.remote_conn = sqlite3.connect("/srv/flexo/remote.db") 55 56 self.remote_conn.row_factory = sqlite3.Row 57 58 self.domain_manager = DomainManager( 59 local_backend=RuntimeBackend(Domain), 60 staging_backend=RuntimeBackend(Domain), 61 permanent_backend=SQLiteEntityBackend( 62 Domain, 63 self.remote_conn, 64 "DOMAINS" 65 ), 66 registry=self.registry 67 ) 68 56 69 self.user_manager = UserManager( 57 70 local_backend=RuntimeBackend(FlexoUser), … … 88 101 ) 89 102 90 def _resolve_base_dir(self) -> Path:91 """92 Resolve OS-specific writable application data directory.93 Prototype: user-local only.94 """95 return Path.home() / ".flexograder"96 97 103 def hydrate_from_sqlite(self): 98 104 """ -
flexograder/gui/gui.py
r705a7df rf0f3ded 7 7 from pathlib import Path 8 8 from uuid import uuid4 9 from dataclasses import dataclass10 9 from datetime import datetime 11 from flexoentity import logger, Domain, DomainManager, EntityType, FlexOID, CompositeBackend 12 from flexoentity import SQLiteEntityBackend, EntityRegistry 13 from flexograder.environment import Environment 14 # from flexograder.managers.flexo_environment import FlexoEnvironment 10 from flexoentity import logger, Domain, EntityType, FlexOID, EntityRegistry 11 from flexograder.os.application import Application 15 12 from flexograder.core_entities.exam import Exam 16 13 from flexograder.core_entities.exam_elements import element_factory 17 14 from flexograder.core_entities.question_catalog import QuestionCatalog 18 from flexograder.managers.catalog_manager import CatalogManager19 from flexograder.managers.exam_manager import ExamManager20 from flexograder.managers.user_manager import UserManager21 15 from flexograder.core_entities.flexo_user import FlexoUser 22 from .domain_management_dialog import DomainManagementDialog23 from .menu import AppMenu24 from .actions_panel import ActionsPanel25 from .select_panel import SelectPanel26 from .detail_panel import DetailPanel27 from .option_question_editor import OptionQuestionEditorDialog28 from .default_question_editor import DefaultQuestionEditorDialog29 from .help_dialog import OrgHelpDialog30 from .create_exam_dialog import ExamDialog31 from .exam_layout_editor import ExamLayoutDialog16 from flexograder.gui.domain_management_dialog import DomainManagementDialog 17 from flexograder.gui.menu import AppMenu 18 from flexograder.gui.actions_panel import ActionsPanel 19 from flexograder.gui.select_panel import SelectPanel 20 from flexograder.gui.detail_panel import DetailPanel 21 from flexograder.gui.option_question_editor import OptionQuestionEditorDialog 22 from flexograder.gui.default_question_editor import DefaultQuestionEditorDialog 23 from flexograder.gui.help_dialog import OrgHelpDialog 24 from flexograder.gui.create_exam_dialog import ExamDialog 25 from flexograder.gui.exam_layout_editor import ExamLayoutDialog 32 26 # from .session_manager import SessionManager 33 27 … … 35 29 def __init__(self): 36 30 super().__init__() 31 app = Application() 32 app.initialize() 33 self.environment = app.environment 34 print(self.environment) 37 35 self.geometry("1000x600") 38 36 self.title("flex-o-grader") 39 37 self.tk.call("tk", "scaling", 1.0) 40 default_font = font.Font(family="DejaVu Sans", size=14)41 # default_font.configure(size=14) # increase from default (usually 9–10)38 font_family = app.environment.profile.ui.font_body 39 default_font = font.Font(family=font_family, size=11) 42 40 43 41 self.option_add("*Font", default_font) … … 54 52 "Flexo.Treeview", 55 53 font=default_font, 56 rowheight= 26 # <-- THIS fixes squashing54 rowheight=40 # <-- THIS fixes squashing on Mac and Windows 57 55 ) 58 56 59 57 self.registry = EntityRegistry() 60 # self.environment = self.setup_environment(registry=self.registry) 58 59 # FIXME: Lets the platform abstraction handle the user 60 61 61 # user_id = os.environ.get("USER_ID") 62 62 user_name = getpass.getuser() … … 67 67 username=user_name, full_name=user_name, 68 68 user_id=user_name, email="") 69 self.env = Environment(self.registry) 70 self.env.hydrate_from_sqlite() 71 72 self.exam_manager = self.env.exam_manager 73 self.catalog_manager = self.env.catalog_manager 74 self.question_manager = self.env.question_manager 69 70 self.exam_manager = self.environment.exam_manager 71 self.catalog_manager = self.environment.catalog_manager 72 self.question_manager = self.environment.question_manager 75 73 76 74 self.registry.register_source(lambda: self.catalog_manager.all_questions()) … … 78 76 self.registry.register_source(lambda: self.user_manager.all_users()) 79 77 80 81 # self.domain_manager = self.environment.manager_for(Domain)82 83 # self.user_manager = self.environment.manager_for(FlexoUser)84 # self.user_manager.add(self.user)85 # self.user_manager.active_user = self.user86 78 87 79 self.status_var = tk.StringVar(value="No catalog loaded") … … 308 300 catalog = QuestionCatalog.from_dict(data) 309 301 for domain in catalog.domains: 310 if domain not in self. domain_manager.all():311 self. domain_manager.add(domain)302 if domain not in self.environment.domain_manager.all(): 303 self.environment.domain_manager.add(domain) 312 304 self.catalog_manager.add_catalog(catalog) 313 305 self.catalog_manager.set_active(catalog.flexo_id) … … 318 310 messagebox.showerror("Catalog not found", "No catalog lef") 319 311 return 320 self.catalog_manager.delete(self.active_catalog.flexo_id )312 self.catalog_manager.delete(self.active_catalog.flexo_id, delete_flag=False) 321 313 titles = self.catalog_manager.list_titles() 322 314 if len(titles) == 0: … … 343 335 title = current_catalog.title 344 336 version = current_catalog.version 345 active_user = self.env .user_manager.active_user337 active_user = self.environment.user_manager.active_user 346 338 status = ( 347 339 f"User: {active_user.full_name}({active_user.user_id}) | " … … 360 352 def edit_exam_dialog(self, exam): 361 353 if not exam: 362 exam = self.env .exam_manager.get_active()354 exam = self.environment.exam_manager.get_active() 363 355 dialog = ExamDialog(self, title="Edit Metadata", exam=exam) 364 356 … … 375 367 exam.add_default_id_form() 376 368 exam._update_fingerprint() 377 self.env .exam_manager.add_exam(exam)378 self.env .exam_manager.set_active(exam.flexo_id)369 self.environment.exam_manager.add_exam(exam) 370 self.environment.exam_manager.set_active(exam.flexo_id) 379 371 self.refresh_all() 380 372 381 373 def create_exam_dialog(self): 382 374 exam = Exam.with_domain_id("EX") 383 if exam.flexo_id in self.env .exam_manager.exams:375 if exam.flexo_id in self.environment.exam_manager.exams: 384 376 raise ValueError(f"Exam {exam.flexo_id} already exists.") 385 377 self.edit_exam_dialog(exam) … … 406 398 if question.subtype in ("SingleChoiceQuestion", "MultipleChoiceQuestion"): 407 399 return OptionQuestionEditorDialog(parent, question.to_dict(), 408 self. domain_manager, editing=editing)400 self.environment.domain_manager, editing=editing) 409 401 410 402 if question.subtype in ("IDForm", "TextQuestion"): 411 403 # even though InstructionBlock may subclass Question, 412 404 # it doesn’t need options 413 return DefaultQuestionEditorDialog(parent, question.to_dict(), self. domain_manager)405 return DefaultQuestionEditorDialog(parent, question.to_dict(), self.environment.domain_manager) 414 406 415 407 # Fallback for any unknown or simple Question subclass 416 return DefaultQuestionEditorDialog(parent, question.to_dict(), self. domain_manager)408 return DefaultQuestionEditorDialog(parent, question.to_dict(), self.environment.domain_manager) 417 409 418 410 def add_question(self): … … 440 432 441 433 dlg = OptionQuestionEditorDialog(self, question_dict, 442 domain_manager=self. domain_manager, editing=False)434 domain_manager=self.environment.domain_manager, editing=False) 443 435 self.wait_window(dlg) 444 436 if dlg.result: … … 531 523 return 532 524 try: 533 self.env .exam_manager.add_exam(Exam.from_json_file(path))525 self.environment.exam_manager.add_exam(Exam.from_json_file(path)) 534 526 for each in self.exam_manager.domains(): 535 self. domain_manager.add_or_update(each)527 self.environment.domain_manager.add_or_update(each) 536 528 except Exception as e: 537 529 messagebox.showerror("Error", f"Could not load exam:\n{e}") … … 545 537 546 538 for each in self.find_all_domain_ids(data, set()): 547 if each not in self. domain_manager.all_domain_ids():539 if each not in self.environment.domain_manager.all_domain_ids(): 548 540 Domain.with_domain_id(each) 549 541 exam = Exam.from_dict(data) # or however you deserialize … … 798 790 799 791 def manage_domain(self): 800 dlg = DomainManagementDialog(self, self. domain_manager)792 dlg = DomainManagementDialog(self, self.environment.domain_manager) 801 793 self.wait_window(dlg) 802 794 return -
flexograder/managers/catalog_manager.py
r705a7df rf0f3ded 173 173 return catalog 174 174 175 def delete(self, catalog_id: str ) -> bool:175 def delete(self, catalog_id: str, delete_flag=False) -> bool: 176 176 """Delete a catalog from memory and disk.""" 177 177 if catalog_id in self._catalogs: 178 178 del self._catalogs[catalog_id] 179 179 # Delete files matching pattern 180 for file in self._base_path.glob(f"*{catalog_id}*.json"): 181 try: 182 file.unlink() 183 except Exception as e: 184 logger.warning(f"[WARN] Could not delete {file}: {e}") 180 if delete_flag: 181 for file in self._base_path.glob(f"*{catalog_id}*.json"): 182 try: 183 file.unlink() 184 except Exception as e: 185 logger.warning(f"[WARN] Could not delete {file}: {e}") 185 186 if self._active_id == catalog_id: 186 187 self._active_id = None
Note:
See TracChangeset
for help on using the changeset viewer.
