fixed store translation
This commit is contained in:
parent
b61d72740b
commit
b5567bf498
3 changed files with 184 additions and 19 deletions
15
database.py
15
database.py
|
|
@ -149,4 +149,17 @@ def delete_translation_record(translation_id):
|
||||||
""", (translation_id,))
|
""", (translation_id,))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
finally:
|
finally:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
def insert_translation_record(es_text, en_text, source_context, tags, notes):
|
||||||
|
"""Inserts a completely fresh record into the translations table."""
|
||||||
|
conn = get_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
try:
|
||||||
|
cursor.execute("""
|
||||||
|
INSERT INTO translations (es_text, en_text, source_context, tags, notes)
|
||||||
|
VALUES (?, ?, ?, ?, ?);
|
||||||
|
""", (es_text, en_text, source_context, tags, notes))
|
||||||
|
conn.commit()
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
Binary file not shown.
|
|
@ -15,6 +15,9 @@ class SandboxTab(QWidget):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
|
# Internal tracking variable to distinguish edits vs new entries
|
||||||
|
self.selected_translation_id = None
|
||||||
|
|
||||||
# Main layout structure
|
# Main layout structure
|
||||||
main_layout = QVBoxLayout(self)
|
main_layout = QVBoxLayout(self)
|
||||||
main_layout.setContentsMargins(30, 20, 30, 20)
|
main_layout.setContentsMargins(30, 20, 30, 20)
|
||||||
|
|
@ -30,14 +33,17 @@ class SandboxTab(QWidget):
|
||||||
self.txt_english = QLineEdit()
|
self.txt_english = QLineEdit()
|
||||||
self.txt_english.setPlaceholderText("Enter English phrase or word...")
|
self.txt_english.setPlaceholderText("Enter English phrase or word...")
|
||||||
self.txt_english.setStyleSheet("padding: 6px; font-size: 14px;")
|
self.txt_english.setStyleSheet("padding: 6px; font-size: 14px;")
|
||||||
|
self.txt_english.textChanged.connect(self.handle_live_filter)
|
||||||
|
|
||||||
self.txt_spanish = QLineEdit()
|
self.txt_spanish = QLineEdit()
|
||||||
self.txt_spanish.setPlaceholderText("Introduce la frase en español...")
|
self.txt_spanish.setPlaceholderText("Introduce la frase en español...")
|
||||||
self.txt_spanish.setStyleSheet("padding: 6px; font-size: 14px;")
|
self.txt_spanish.setStyleSheet("padding: 6px; font-size: 14px;")
|
||||||
|
self.txt_spanish.textChanged.connect(self.handle_live_filter)
|
||||||
|
|
||||||
self.txt_context = QLineEdit()
|
self.txt_context = QLineEdit()
|
||||||
self.txt_context.setPlaceholderText("e.g., Camino 2027, Café, Market conversation...")
|
self.txt_context.setPlaceholderText("e.g., Camino 2027, Café, Market conversation...")
|
||||||
self.txt_context.setStyleSheet("padding: 6px; font-size: 14px;")
|
self.txt_context.setStyleSheet("padding: 6px; font-size: 14px;")
|
||||||
|
self.txt_context.textChanged.connect(self.handle_live_filter)
|
||||||
|
|
||||||
self.txt_notes = QLineEdit()
|
self.txt_notes = QLineEdit()
|
||||||
self.txt_notes.setPlaceholderText("Grammar rules, formal vs informal nuances...")
|
self.txt_notes.setPlaceholderText("Grammar rules, formal vs informal nuances...")
|
||||||
|
|
@ -93,6 +99,7 @@ class SandboxTab(QWidget):
|
||||||
|
|
||||||
# --- SECTION 3: DATA COMMIT CONTROL BAR ---
|
# --- SECTION 3: DATA COMMIT CONTROL BAR ---
|
||||||
control_layout = QHBoxLayout()
|
control_layout = QHBoxLayout()
|
||||||
|
control_layout.setSpacing(15)
|
||||||
|
|
||||||
self.btn_save = QPushButton("Save Translation Record")
|
self.btn_save = QPushButton("Save Translation Record")
|
||||||
self.btn_save.setCursor(Qt.CursorShape.PointingHandCursor)
|
self.btn_save.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||||
|
|
@ -109,6 +116,21 @@ class SandboxTab(QWidget):
|
||||||
""")
|
""")
|
||||||
self.btn_save.clicked.connect(self.commit_translation_record)
|
self.btn_save.clicked.connect(self.commit_translation_record)
|
||||||
|
|
||||||
|
self.btn_new_record = QPushButton("Create New Record")
|
||||||
|
self.btn_new_record.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||||
|
self.btn_new_record.setStyleSheet("""
|
||||||
|
QPushButton {
|
||||||
|
background-color: #27AE60;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
QPushButton:hover { background-color: #219653; }
|
||||||
|
""")
|
||||||
|
self.btn_new_record.clicked.connect(self.prepare_for_new_record)
|
||||||
|
|
||||||
self.btn_clear = QPushButton("Clear Fields")
|
self.btn_clear = QPushButton("Clear Fields")
|
||||||
self.btn_clear.setCursor(Qt.CursorShape.PointingHandCursor)
|
self.btn_clear.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||||
self.btn_clear.setStyleSheet("""
|
self.btn_clear.setStyleSheet("""
|
||||||
|
|
@ -122,9 +144,10 @@ class SandboxTab(QWidget):
|
||||||
}
|
}
|
||||||
QPushButton:hover { background-color: #95A5A6; }
|
QPushButton:hover { background-color: #95A5A6; }
|
||||||
""")
|
""")
|
||||||
self.btn_clear.clicked.connect(self.clear_input_fields)
|
self.btn_clear.clicked.connect(self.clear_all_fields_manually)
|
||||||
|
|
||||||
control_layout.addWidget(self.btn_save)
|
control_layout.addWidget(self.btn_save)
|
||||||
|
control_layout.addWidget(self.btn_new_record)
|
||||||
control_layout.addWidget(self.btn_clear)
|
control_layout.addWidget(self.btn_clear)
|
||||||
control_layout.addStretch()
|
control_layout.addStretch()
|
||||||
|
|
||||||
|
|
@ -137,6 +160,9 @@ class SandboxTab(QWidget):
|
||||||
self.table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
|
self.table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
|
||||||
self.table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers)
|
self.table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers)
|
||||||
|
|
||||||
|
# Wire up row selection change signals to auto-populate form
|
||||||
|
self.table.itemSelectionChanged.connect(self.handle_row_selection)
|
||||||
|
|
||||||
# Tweak display headers to scale nicely
|
# Tweak display headers to scale nicely
|
||||||
header = self.table.horizontalHeader()
|
header = self.table.horizontalHeader()
|
||||||
header.setSectionResizeMode(0, QHeaderView.ResizeMode.ResizeToContents)
|
header.setSectionResizeMode(0, QHeaderView.ResizeMode.ResizeToContents)
|
||||||
|
|
@ -147,7 +173,8 @@ class SandboxTab(QWidget):
|
||||||
|
|
||||||
main_layout.addWidget(self.table)
|
main_layout.addWidget(self.table)
|
||||||
|
|
||||||
# Populate live view from storage layout tracking engines
|
# Master cache of unfiltered row records to enable instant filtering loops
|
||||||
|
self.all_cached_records = []
|
||||||
self.reload_table_display()
|
self.reload_table_display()
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
|
@ -164,56 +191,181 @@ class SandboxTab(QWidget):
|
||||||
if text:
|
if text:
|
||||||
subprocess.Popen(["say", "-v", "Monica", text])
|
subprocess.Popen(["say", "-v", "Monica", text])
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def handle_live_filter(self):
|
||||||
|
"""Filters the visible database entries based on current text input criteria."""
|
||||||
|
# Temporary block signals to prevent selection loops from fighting text changes
|
||||||
|
self.table.blockSignals(True)
|
||||||
|
|
||||||
|
filter_en = self.txt_english.text().lower().strip()
|
||||||
|
filter_es = self.txt_spanish.text().lower().strip()
|
||||||
|
filter_ctx = self.txt_context.text().lower().strip()
|
||||||
|
|
||||||
|
self.table.setRowCount(0)
|
||||||
|
visible_row_index = 0
|
||||||
|
|
||||||
|
for row in self.all_cached_records:
|
||||||
|
val_en = (row["en_text"] or "").lower()
|
||||||
|
val_es = (row["es_text"] or "").lower()
|
||||||
|
val_ctx = (row["source_context"] or "").lower()
|
||||||
|
|
||||||
|
# Look for matches across English, Spanish, and Source Context
|
||||||
|
if (filter_en in val_en) and (filter_es in val_es) and (filter_ctx in val_ctx):
|
||||||
|
self.table.insertRow(visible_row_index)
|
||||||
|
|
||||||
|
item_id = QTableWidgetItem(str(row["translation_id"]))
|
||||||
|
item_en = QTableWidgetItem(row["en_text"])
|
||||||
|
item_es = QTableWidgetItem(row["es_text"])
|
||||||
|
item_ctx = QTableWidgetItem(row["source_context"] or "")
|
||||||
|
item_nts = QTableWidgetItem(row["notes"] or "")
|
||||||
|
|
||||||
|
item_id.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
|
||||||
|
self.table.setItem(visible_row_index, 0, item_id)
|
||||||
|
self.table.setItem(visible_row_index, 1, item_en)
|
||||||
|
self.table.setItem(visible_row_index, 2, item_es)
|
||||||
|
self.table.setItem(visible_row_index, 3, item_ctx)
|
||||||
|
self.table.setItem(visible_row_index, 4, item_nts)
|
||||||
|
|
||||||
|
# If we have an active editing ID, highlight that specific row during re-renders
|
||||||
|
if self.selected_translation_id == row["translation_id"]:
|
||||||
|
self.table.selectRow(visible_row_index)
|
||||||
|
|
||||||
|
visible_row_index += 1
|
||||||
|
|
||||||
|
self.table.blockSignals(False)
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def handle_row_selection(self):
|
||||||
|
"""Populates the input forms when a user clicks a row in the table view."""
|
||||||
|
selected_ranges = self.table.selectedRanges()
|
||||||
|
if not selected_ranges:
|
||||||
|
return
|
||||||
|
|
||||||
|
row_idx = selected_ranges[0].topRow()
|
||||||
|
id_item = self.table.item(row_idx, 0)
|
||||||
|
if not id_item:
|
||||||
|
return
|
||||||
|
|
||||||
|
target_id = int(id_item.text())
|
||||||
|
|
||||||
|
# Locate item match within memory cache store elements
|
||||||
|
record = next((r for r in self.all_cached_records if r["translation_id"] == target_id), None)
|
||||||
|
if record:
|
||||||
|
# Block line edit text tracking temporarily so populating fields doesn't trigger filter loops
|
||||||
|
self.txt_english.blockSignals(True)
|
||||||
|
self.txt_spanish.blockSignals(True)
|
||||||
|
self.txt_context.blockSignals(True)
|
||||||
|
self.txt_notes.blockSignals(True)
|
||||||
|
|
||||||
|
self.selected_translation_id = record["translation_id"]
|
||||||
|
self.txt_english.setText(record["en_text"])
|
||||||
|
self.txt_spanish.setText(record["es_text"])
|
||||||
|
self.txt_context.setText(record["source_context"] or "")
|
||||||
|
self.txt_notes.setText(record["notes"] or "")
|
||||||
|
|
||||||
|
self.txt_english.blockSignals(False)
|
||||||
|
self.txt_spanish.blockSignals(False)
|
||||||
|
self.txt_context.blockSignals(False)
|
||||||
|
self.txt_notes.blockSignals(False)
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def prepare_for_new_record(self):
|
||||||
|
"""Clears selection state so next click on 'Save' inserts fresh rows without scrubbing fields."""
|
||||||
|
self.selected_translation_id = None
|
||||||
|
self.table.blockSignals(True)
|
||||||
|
self.table.clearSelection()
|
||||||
|
self.table.blockSignals(False)
|
||||||
|
QMessageBox.information(self, "Status Shift", "Ready to insert a new record using the current field content.")
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def commit_translation_record(self):
|
def commit_translation_record(self):
|
||||||
"""Extracts text metrics out of input wrappers and saves down to database engine storage."""
|
"""Saves current text blocks. Dynamically detects insert vs edit based on selections."""
|
||||||
en_text = self.txt_english.text().strip()
|
en_text = self.txt_english.text().strip()
|
||||||
es_text = self.txt_spanish.text().strip()
|
es_text = self.txt_spanish.text().strip()
|
||||||
context = self.txt_context.text().strip()
|
context = self.txt_context.text().strip()
|
||||||
notes = self.txt_notes.text().strip()
|
notes = self.txt_notes.text().strip()
|
||||||
|
tags = "" # Default empty placeholder string to fit the backend DB method signature
|
||||||
|
|
||||||
if not en_text or not es_text:
|
if not en_text or not es_text:
|
||||||
QMessageBox.warning(self, "Validation Alert", "Both English and Spanish base text blocks are required.")
|
QMessageBox.warning(self, "Validation Alert", "Both English and Spanish base text blocks are required.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Call explicit writing handlers down to SQLite database layer
|
try:
|
||||||
database.insert_translation_explicit(en_text, es_text, context, notes)
|
if self.selected_translation_id is not None:
|
||||||
|
# Direct match for database.update_translation_record signature:
|
||||||
# Wipe structural field items cleanly on completions loop
|
# (translation_id, es_text, en_text, source_context, tags, notes)
|
||||||
self.clear_input_fields()
|
database.update_translation_record(
|
||||||
|
self.selected_translation_id, es_text, en_text, context, tags, notes
|
||||||
# Sync state out across the rest of the app window elements
|
)
|
||||||
self.reload_table_display()
|
else:
|
||||||
self.data_mutated.emit()
|
# Direct match for database.insert_translation_record signature:
|
||||||
|
# (es_text, en_text, source_context, tags, notes)
|
||||||
|
database.insert_translation_record(
|
||||||
|
es_text, en_text, context, tags, notes
|
||||||
|
)
|
||||||
|
|
||||||
|
# Clear pointer state values on successful writing commits
|
||||||
|
self.selected_translation_id = None
|
||||||
|
|
||||||
|
# Wipe inputs cleanly and sync UI layers
|
||||||
|
self.clear_input_fields()
|
||||||
|
self.reload_table_display()
|
||||||
|
self.data_mutated.emit()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
QMessageBox.critical(self, "Database Commit Safeguard", f"Failed writing database operations:\n{str(e)}")
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
def clear_all_fields_manually(self):
|
||||||
|
"""Clears explicit states alongside visual row highlights simultaneously."""
|
||||||
|
self.selected_translation_id = None
|
||||||
|
self.table.blockSignals(True)
|
||||||
|
self.table.clearSelection()
|
||||||
|
self.table.blockSignals(False)
|
||||||
|
self.clear_input_fields()
|
||||||
|
self.reload_table_display()
|
||||||
|
|
||||||
def clear_input_fields(self):
|
def clear_input_fields(self):
|
||||||
"""Flushes transient cache items out of form line elements."""
|
"""Flushes transient text inside line editors without running filtering rules."""
|
||||||
|
self.txt_english.blockSignals(True)
|
||||||
|
self.txt_spanish.blockSignals(True)
|
||||||
|
self.txt_context.blockSignals(True)
|
||||||
|
self.txt_notes.blockSignals(True)
|
||||||
|
|
||||||
self.txt_english.clear()
|
self.txt_english.clear()
|
||||||
self.txt_spanish.clear()
|
self.txt_spanish.clear()
|
||||||
self.txt_context.clear()
|
self.txt_context.clear()
|
||||||
self.txt_notes.clear()
|
self.txt_notes.clear()
|
||||||
|
|
||||||
|
self.txt_english.blockSignals(False)
|
||||||
|
self.txt_spanish.blockSignals(False)
|
||||||
|
self.txt_context.blockSignals(False)
|
||||||
|
self.txt_notes.blockSignals(False)
|
||||||
|
|
||||||
def reload_table_display(self):
|
def reload_table_display(self):
|
||||||
"""Refetches database rows and populates the master dashboard grid view."""
|
"""Refetches database rows and populates the master dashboard grid view."""
|
||||||
|
self.table.blockSignals(True)
|
||||||
self.table.setRowCount(0)
|
self.table.setRowCount(0)
|
||||||
records = database.get_all_translations_explicit()
|
|
||||||
|
|
||||||
for idx, row in enumerate(records):
|
# Keep internal reference arrays synced cleanly
|
||||||
|
self.all_cached_records = database.get_all_translations_explicit()
|
||||||
|
|
||||||
|
for idx, row in enumerate(self.all_cached_records):
|
||||||
self.table.insertRow(idx)
|
self.table.insertRow(idx)
|
||||||
|
|
||||||
# Form clean mapping cell entities
|
|
||||||
item_id = QTableWidgetItem(str(row["translation_id"]))
|
item_id = QTableWidgetItem(str(row["translation_id"]))
|
||||||
item_en = QTableWidgetItem(row["en_text"])
|
item_en = QTableWidgetItem(row["en_text"])
|
||||||
item_es = QTableWidgetItem(row["es_text"])
|
item_es = QTableWidgetItem(row["es_text"])
|
||||||
item_ctx = QTableWidgetItem(row["source_context"] or "")
|
item_ctx = QTableWidgetItem(row["source_context"] or "")
|
||||||
item_nts = QTableWidgetItem(row["notes"] or "")
|
item_nts = QTableWidgetItem(row["notes"] or "")
|
||||||
|
|
||||||
# Align center the ID key indices
|
|
||||||
item_id.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
|
item_id.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
|
||||||
self.table.setItem(idx, 0, item_id)
|
self.table.setItem(idx, 0, item_id)
|
||||||
self.table.setItem(idx, 1, item_en)
|
self.table.setItem(idx, 1, item_en)
|
||||||
self.table.setItem(idx, 2, item_es)
|
self.table.setItem(idx, 2, item_es)
|
||||||
self.table.setItem(idx, 3, item_ctx)
|
self.table.setItem(idx, 3, item_ctx)
|
||||||
self.table.setItem(idx, 4, item_nts)
|
self.table.setItem(idx, 4, item_nts)
|
||||||
|
|
||||||
|
self.table.blockSignals(False)
|
||||||
Loading…
Reference in a new issue