Changeset f0f3ded in flexograder


Ignore:
Timestamp:
01/14/26 12:52:10 (23 hours ago)
Author:
Enrico Schwass <ennoausberlin@…>
Branches:
master
Children:
64883b1
Parents:
705a7df
Message:

add support for profile and os abstractions

Location:
flexograder
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • flexograder/environment.py

    r705a7df rf0f3ded  
    1 from pathlib import Path
    21import json
    32import sqlite3
    43
    5 from flexoentity import SQLiteEntityBackend, EntityManager, RuntimeBackend
     4from flexoentity import SQLiteEntityBackend, RuntimeBackend, DomainManager, Domain
    65
    76from flexograder.core_entities.exam import Exam
    87from flexograder.core_entities.question_catalog import QuestionCatalog
    9 from flexograder.core_entities.exam_elements import ChoiceQuestion, ExamElement, element_factory
     8from flexograder.core_entities.exam_elements import ExamElement, element_factory
    109from flexograder.core_entities.flexo_user import FlexoUser
    1110from flexograder.managers.catalog_manager import CatalogManager
     
    2221
    2322        return [
    24             question_factory(json.loads(r["json"]))
     23            element_factory(json.loads(r["json"]))
    2524            for r in rows
    2625        ]
     
    3534            return None
    3635
    37         return question_factory(json.loads(row["json"]))
     36        return element_factory(json.loads(row["json"]))
     37
    3838
    3939class Environment:
     
    4747    """
    4848
    49     def __init__(self, registry):
     49    def __init__(self, profile, registry):
     50        self.profile = profile
    5051        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"
    5354
    5455        self.remote_conn = sqlite3.connect("/srv/flexo/remote.db")
    5556        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
    5669        self.user_manager = UserManager(
    5770            local_backend=RuntimeBackend(FlexoUser),
     
    88101        )
    89102
    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 
    97103    def hydrate_from_sqlite(self):
    98104        """
  • flexograder/gui/gui.py

    r705a7df rf0f3ded  
    77from pathlib import Path
    88from uuid import uuid4
    9 from dataclasses import dataclass
    109from 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
     10from flexoentity import logger, Domain, EntityType, FlexOID, EntityRegistry
     11from flexograder.os.application import Application
    1512from flexograder.core_entities.exam import Exam
    1613from flexograder.core_entities.exam_elements import element_factory
    1714from flexograder.core_entities.question_catalog import QuestionCatalog
    18 from flexograder.managers.catalog_manager import CatalogManager
    19 from flexograder.managers.exam_manager import ExamManager
    20 from flexograder.managers.user_manager import UserManager
    2115from flexograder.core_entities.flexo_user import FlexoUser
    22 from .domain_management_dialog import DomainManagementDialog
    23 from .menu import AppMenu
    24 from .actions_panel import ActionsPanel
    25 from .select_panel import SelectPanel
    26 from .detail_panel import DetailPanel
    27 from .option_question_editor import OptionQuestionEditorDialog
    28 from .default_question_editor import DefaultQuestionEditorDialog
    29 from .help_dialog import OrgHelpDialog
    30 from .create_exam_dialog import ExamDialog
    31 from .exam_layout_editor import ExamLayoutDialog
     16from flexograder.gui.domain_management_dialog import DomainManagementDialog
     17from flexograder.gui.menu import AppMenu
     18from flexograder.gui.actions_panel import ActionsPanel
     19from flexograder.gui.select_panel import SelectPanel
     20from flexograder.gui.detail_panel import DetailPanel
     21from flexograder.gui.option_question_editor import OptionQuestionEditorDialog
     22from flexograder.gui.default_question_editor import DefaultQuestionEditorDialog
     23from flexograder.gui.help_dialog import OrgHelpDialog
     24from flexograder.gui.create_exam_dialog import ExamDialog
     25from flexograder.gui.exam_layout_editor import ExamLayoutDialog
    3226# from .session_manager import SessionManager
    3327
     
    3529    def __init__(self):
    3630        super().__init__()
     31        app = Application()
     32        app.initialize()
     33        self.environment = app.environment
     34        print(self.environment)
    3735        self.geometry("1000x600")
    3836        self.title("flex-o-grader")
    3937        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)
    4240
    4341        self.option_add("*Font", default_font)
     
    5452            "Flexo.Treeview",
    5553            font=default_font,
    56             rowheight=26   # <-- THIS fixes squashing
     54            rowheight=40   # <-- THIS fixes squashing on Mac and Windows
    5755        )
    5856
    5957        self.registry = EntityRegistry()
    60         #        self.environment = self.setup_environment(registry=self.registry)
     58
     59        # FIXME: Lets the platform abstraction handle the user
     60
    6161        # user_id = os.environ.get("USER_ID")
    6262        user_name = getpass.getuser()
     
    6767                                             username=user_name, full_name=user_name,
    6868                                             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
    7573
    7674        self.registry.register_source(lambda: self.catalog_manager.all_questions())
     
    7876        self.registry.register_source(lambda: self.user_manager.all_users())
    7977
    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.user
    8678
    8779        self.status_var = tk.StringVar(value="No catalog loaded")
     
    308300        catalog = QuestionCatalog.from_dict(data)
    309301        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)
    312304        self.catalog_manager.add_catalog(catalog)
    313305        self.catalog_manager.set_active(catalog.flexo_id)
     
    318310            messagebox.showerror("Catalog not found", "No catalog lef")
    319311            return
    320         self.catalog_manager.delete(self.active_catalog.flexo_id)
     312        self.catalog_manager.delete(self.active_catalog.flexo_id, delete_flag=False)
    321313        titles = self.catalog_manager.list_titles()
    322314        if len(titles) == 0:
     
    343335        title = current_catalog.title
    344336        version = current_catalog.version
    345         active_user = self.env.user_manager.active_user
     337        active_user = self.environment.user_manager.active_user
    346338        status = (
    347339            f"User: {active_user.full_name}({active_user.user_id}) | "
     
    360352    def edit_exam_dialog(self, exam):
    361353        if not exam:
    362             exam = self.env.exam_manager.get_active()
     354            exam = self.environment.exam_manager.get_active()
    363355        dialog = ExamDialog(self, title="Edit Metadata", exam=exam)
    364356
     
    375367            exam.add_default_id_form()
    376368        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)
    379371        self.refresh_all()
    380372
    381373    def create_exam_dialog(self):
    382374        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:
    384376            raise ValueError(f"Exam {exam.flexo_id} already exists.")
    385377        self.edit_exam_dialog(exam)
     
    406398        if question.subtype in ("SingleChoiceQuestion", "MultipleChoiceQuestion"):
    407399            return OptionQuestionEditorDialog(parent, question.to_dict(),
    408                                               self.domain_manager, editing=editing)
     400                                              self.environment.domain_manager, editing=editing)
    409401
    410402        if question.subtype in ("IDForm", "TextQuestion"):
    411403            # even though InstructionBlock may subclass Question,
    412404            # 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)
    414406
    415407        # 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)
    417409
    418410    def add_question(self):
     
    440432
    441433        dlg = OptionQuestionEditorDialog(self, question_dict,
    442                                          domain_manager=self.domain_manager, editing=False)
     434                                         domain_manager=self.environment.domain_manager, editing=False)
    443435        self.wait_window(dlg)
    444436        if dlg.result:
     
    531523            return
    532524        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))
    534526            for each in self.exam_manager.domains():
    535                 self.domain_manager.add_or_update(each)
     527                self.environment.domain_manager.add_or_update(each)
    536528        except Exception as e:
    537529            messagebox.showerror("Error", f"Could not load exam:\n{e}")
     
    545537
    546538        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():
    548540                Domain.with_domain_id(each)
    549541        exam = Exam.from_dict(data)  # or however you deserialize
     
    798790
    799791    def manage_domain(self):
    800         dlg = DomainManagementDialog(self, self.domain_manager)
     792        dlg = DomainManagementDialog(self, self.environment.domain_manager)
    801793        self.wait_window(dlg)
    802794        return
  • flexograder/managers/catalog_manager.py

    r705a7df rf0f3ded  
    173173        return catalog
    174174
    175     def delete(self, catalog_id: str) -> bool:
     175    def delete(self, catalog_id: str, delete_flag=False) -> bool:
    176176        """Delete a catalog from memory and disk."""
    177177        if catalog_id in self._catalogs:
    178178            del self._catalogs[catalog_id]
    179179            # 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}")
    185186            if self._active_id == catalog_id:
    186187                self._active_id = None
Note: See TracChangeset for help on using the changeset viewer.