diff --git a/main.py b/main.py index f6aaea1..18b9bf3 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,8 @@ # main.py import sys import os +import random +import hashlib from PyQt6.QtWidgets import ( QApplication, QMainWindow, QWidget, QTabWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QLineEdit, QComboBox, @@ -10,6 +12,9 @@ from PyQt6.QtCore import Qt, QUrl from PyQt6.QtMultimedia import QMediaPlayer, QAudioOutput from PyQt6.QtGui import QFont +# Third-Party Anki Generation Tooling +import genanki + # Internal Project Module Imports from database.connection import init_db, get_connection from core.bulk_importer import BulkImporter @@ -41,7 +46,7 @@ class SpanishTrainerApp(QMainWindow): self.init_phrase_sandbox_tab() self.init_flashcard_reviewer_tab() - self.init_settings_tab() # Mount the new settings panel + self.init_settings_tab() # 2. Populate table grids on initialization self.refresh_crud_table() @@ -55,7 +60,6 @@ class SpanishTrainerApp(QMainWindow): conn = get_connection() cursor = conn.cursor() - # Ensure the settings table exists alongside legacy core tables cursor.execute("CREATE TABLE IF NOT EXISTS settings (key TEXT PRIMARY KEY, value TEXT);") try: @@ -398,7 +402,6 @@ class SpanishTrainerApp(QMainWindow): settings_frame.setFrameShape(QFrame.Shape.StyledPanel) form_layout = QFormLayout(settings_frame) - # Anki Export Path Form Group anki_layout = QHBoxLayout() self.line_anki_dir = QLineEdit(self.anki_export_dir) self.line_anki_dir.setReadOnly(True) @@ -407,7 +410,6 @@ class SpanishTrainerApp(QMainWindow): anki_layout.addWidget(self.line_anki_dir) anki_layout.addWidget(btn_browse_anki) - # Video Export Path Form Group video_layout = QHBoxLayout() self.line_video_dir = QLineEdit(self.video_export_dir) self.line_video_dir.setReadOnly(True) @@ -426,7 +428,6 @@ class SpanishTrainerApp(QMainWindow): self.tabs.addTab(tab, "⚙️ Settings") def handle_browse_anki_directory(self): - """Triggers a file browser directory selection for native Anki card compiles.""" directory = QFileDialog.getExistingDirectory(self, "Select Anki Export Folder", self.anki_export_dir) if directory: self.anki_export_dir = directory @@ -434,7 +435,6 @@ class SpanishTrainerApp(QMainWindow): self.save_setting_to_db("anki_export_directory", directory) def handle_browse_video_directory(self): - """Triggers a file browser directory selection for video timeline outputs.""" directory = QFileDialog.getExistingDirectory(self, "Select Video Export Folder", self.video_export_dir) if directory: self.video_export_dir = directory @@ -665,7 +665,6 @@ class SpanishTrainerApp(QMainWindow): QMessageBox.information(self, "Empty Pool", "No flashcards match your selected filter configurations.") return - import random target_id = random.choice(self.flashcard_ids_pool) try: @@ -779,17 +778,130 @@ class SpanishTrainerApp(QMainWindow): self.media_player.setPlaybackRate(rate) # ===================================================================== - # 📦 ARTIFACT EXPORT GATEWAYS (ANKI & DEPLOYMENT CODES) + # 📦 ARTIFACT EXPORT GATEWAYS (GENANKI LIVE ENGINE) # ===================================================================== def handle_export_anki_deck(self): - """Action handler loop for genanki package deployment modules.""" - QMessageBox.information( - self, "Anki Export Engine", - f"Staging packaging manifest for active view subset!\n\n" - f"Target Directory: {self.anki_export_dir}\n" - f"Currently Filtered Scope count: {len(self.flashcard_ids_pool)} cards." + """Compiles active subset into functional .apkg with bundled neural audio tracks.""" + if not self.flashcard_ids_pool: + QMessageBox.warning(self, "Export Cancelled", "The current study stack is empty. Verify your search filters.") + return + + # 1. Generate Stable Cryptographic Note Model ID + model_hash = hashlib.sha256(b"castilian_voice_trainer_model_v1").hexdigest() + model_id = int(model_hash[:13], 16) + + # Standardized Castilian Note Template Structure Definition + spanish_note_model = genanki.Model( + model_id, + 'Castilian Audio Flashcard Model', + fields=[ + {'name': 'SpanishPhrase'}, + {'name': 'EnglishTranslation'}, + {'name': 'GrammarNotes'}, + {'name': 'AudioTrack'} + ], + templates=[ + { + 'name': 'Card 1: Auditory Identification', + 'qfmt': '