ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/ns_dev/Python/NinoCode/Active_prgs/Gromulus/models.py
Revision: 990
Committed: Mon Mar 9 21:20:37 2026 UTC (2 weeks, 4 days ago) by nino.borges
Content type: text/x-python
File size: 4296 byte(s)
Log Message:
Gromulus v1.5: user metadata save workflow, schema expansion, and UI refactor

- Added user-editable game metadata workflow with explicit Save button (no autosave).
- Added dirty-state tracking and Save/Discard/Cancel prompts when navigating away or closing with unsaved changes.
- Added DB schema support for new metadata fields:
  - 
  - , 
  - , 
  - , 
  - , 
- Wired UI to user-first metadata precedence with  fallback for release date, genre, cooperative, max players, and description.
- Added release date display/storage conversion:
  - GUI display 
  - DB storage 
- Refactored main game info panel:
  - moved hash/file/No-Intro/TOSEC detail fields into  modal
  - added compact TOSEC/NoIntro match indicators
  - added Favorite, Release Date, Genre, Cooperative, Max Players, Description, and User Notes controls
- Enhanced artwork previews from prior update:
  - larger preview boxes
  - aspect-ratio-preserving scaling
  - click-to-open full-size modal viewer
- Updated schema/documentation files to stay aligned:
  - 
  - 
  - canonical DB utility schema/migration logic

File Contents

# Content
1 """SQLAlchemy schema definitions for the current Gromulus SQLite database.
2
3 This module is intentionally written with SQLAlchemy Core ``Table`` objects
4 instead of ORM declarative classes so it can represent tables that do not
5 have primary keys (for example ``no_intro_main`` and ``tosec_main``).
6 """
7
8 from sqlalchemy import (
9 Column,
10 ForeignKey,
11 Index,
12 Integer,
13 MetaData,
14 Table,
15 Text,
16 UniqueConstraint,
17 )
18
19
20 metadata = MetaData()
21
22
23 main_app_system = Table(
24 "main_app_system",
25 metadata,
26 Column("id", Integer, primary_key=True, autoincrement=True, nullable=False),
27 Column("name", Text),
28 Column("short_name", Text),
29 Column("relative_file_path", Text),
30 )
31
32
33 main_app = Table(
34 "main_app",
35 metadata,
36 Column("id", Integer, primary_key=True, autoincrement=True, nullable=False),
37 Column("game_name", Text),
38 Column("game_name_scraped", Text),
39 Column("container_file_name", Text),
40 Column("description", Text),
41 Column("description_scraped", Text),
42 Column("system_console", Integer),
43 Column("system_console_scraped", Text),
44 Column("path_to_screenshot_box", Text),
45 Column("path_to_screenshot_title", Text),
46 Column("path_to_screenshot_ingame", Text),
47 Column("path_to_video", Text),
48 Column("user_notes", Text),
49 Column("container_md5_hash", Text),
50 Column("version", Text),
51 Column("favorite_game", Integer),
52 Column("release_date", Text),
53 Column("release_date_scraped", Text),
54 Column("game_genre", Text),
55 Column("game_genre_scraped", Text),
56 Column("cooperative", Text),
57 Column("cooperative_scraped", Text),
58 Column("max_players", Text),
59 Column("max_players_scraped", Text),
60 )
61
62
63 main_app_file_hash = Table(
64 "main_app_file_hash",
65 metadata,
66 Column("id", Integer, primary_key=True, autoincrement=True, nullable=False),
67 Column("file_name", Text),
68 Column("file_md5_hash", Text),
69 Column("container_file_id", Integer, ForeignKey("main_app.id"), nullable=False),
70 )
71
72
73 no_intro_system = Table(
74 "no_intro_system",
75 metadata,
76 Column("id", Integer, primary_key=True, nullable=False),
77 Column("name", Text),
78 Column("description", Text),
79 Column("dat_version", Text),
80 )
81
82
83 no_intro_main = Table(
84 "no_intro_main",
85 metadata,
86 Column("game_name", Text),
87 Column("no_intro_id", Text),
88 Column("clone_of_id", Text),
89 Column("description", Text),
90 Column("rom_name", Text),
91 Column("crc", Text),
92 Column("md5", Text),
93 Column("sha1", Text),
94 Column("sha256", Text),
95 Column("status", Text),
96 Column("no_intro_system_id", Integer, ForeignKey("no_intro_system.id"), nullable=False),
97 Column("app_system_id", Integer),
98 )
99
100
101 tosec_main = Table(
102 "tosec_main",
103 metadata,
104 Column("game_name", Text),
105 Column("description", Text),
106 Column("rom_name", Text),
107 Column("crc", Text),
108 Column("md5", Text),
109 Column("sha1", Text),
110 Column("system_id", Integer, ForeignKey("no_intro_system.id"), nullable=False),
111 Column("app_system_id", Integer),
112 )
113
114
115 dat_import_history = Table(
116 "dat_import_history",
117 metadata,
118 Column("id", Integer, primary_key=True, autoincrement=True),
119 Column("app_system_id", Integer, ForeignKey("main_app_system.id"), nullable=False),
120 Column("source", Text, nullable=False),
121 Column("dat_name", Text),
122 Column("dat_description", Text),
123 Column("dat_version", Text),
124 Column("imported_at", Text, nullable=False),
125 Column("entry_count", Integer, nullable=False, default=0),
126 UniqueConstraint("app_system_id", "source", name="uq_dat_import_history_system_source"),
127 )
128
129
130 Index("idx_main_app_md5", main_app.c.container_md5_hash)
131 Index("idx_main_app_system", main_app.c.system_console)
132 Index("idx_no_intro_md5", no_intro_main.c.md5)
133 Index("idx_tosec_md5", tosec_main.c.md5)
134 Index("idx_no_intro_system_md5", no_intro_main.c.app_system_id, no_intro_main.c.md5)
135 Index("idx_tosec_system_md5", tosec_main.c.app_system_id, tosec_main.c.md5)
136 Index("idx_dat_import_system_source", dat_import_history.c.app_system_id, dat_import_history.c.source)
137
138
139 __all__ = [
140 "metadata",
141 "main_app_system",
142 "main_app",
143 "main_app_file_hash",
144 "no_intro_system",
145 "no_intro_main",
146 "tosec_main",
147 "dat_import_history",
148 ]