import json from PyDictionary import PyDictionary # type: ignore[import-untyped] from PyQt6.QtCore import Qt, pyqtSlot from PyQt6.QtGui import ( QFont, QTextCharFormat, QTextCursor, QTextDocument, QTextListFormat, ) from PyQt6.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel from PyQt6.QtWidgets import QDialog from main import query_error from ui.EditDialog import Ui_Dialog class EditDialog(QDialog, Ui_Dialog): def __init__(self, book_id: int, person_id: int) -> None: super(EditDialog, self).__init__() self.book_id = book_id self.person_id = person_id self.setupUi(self) self.current_paragraph(self.person_id) self.paraEdit.setReadOnly(True) self.defEdit.setReadOnly(True) self.stackedWidget.setCurrentIndex(0) self.defineBtn.clicked.connect(self.defineAction) self.showBtn.clicked.connect(self.showAction) self.nextBtn.clicked.connect(self.nextAction) self.prevBtn.clicked.connect(self.prevAction) return def current_paragraph(self, person_id: int) -> None: query = QSqlQuery() query.prepare("SELECT * FROM people WHERE person_id = :person_id") query.bindValue(":person_id", person_id) query.exec() query.next() paragraph_id = query.value("paragraph_id") self.display_paragraph(paragraph_id) return def display_paragraph(self, paragraph_id: int) -> None: self.paragraph_id = paragraph_id query = QSqlQuery() query.prepare("SELECT * FROM paragraphs WHERE paragraph_id = :paragraph_id") query.bindValue(":paragraph_id", paragraph_id) query.exec() query.next() self.section_id = query.value("section_id") self.paraSequence = query.value("sequence") cursor = self.paraEdit.textCursor() cursor.movePosition(QTextCursor.MoveOperation.Start) cursor.movePosition( QTextCursor.MoveOperation.End, QTextCursor.MoveMode.KeepAnchor ) cursor.removeSelectedText() cursor.insertHtml(query.value("content")) query.prepare( "SELECT * FROM word_paragraph " "WHERE paragraph_id = :paragraph_id" ) query.bindValue(":paragraph_id", self.paragraph_id) if not query.exec(): query_error(query) def_format = QTextCharFormat() def_format.setFontUnderline(True) cursor = QTextCursor(self.paraEdit.document()) while query.next(): start = query.value("start") end = query.value("end") cursor.setPosition(start, QTextCursor.MoveMode.MoveAnchor) cursor.setPosition(end, QTextCursor.MoveMode.KeepAnchor) cursor.setCharFormat(def_format) cursor.setPosition(0) self.paraEdit.setTextCursor(cursor) return @pyqtSlot() def defineAction(self) -> None: cursor = self.paraEdit.textCursor() word = cursor.selectedText() start = cursor.selectionStart() end = cursor.selectionEnd() if start != end: word = word.strip() if len(word) == 0 or word.find(" ") >= 0: return if start > end: tmp = start start = end end = tmp query = QSqlQuery() query.prepare("SELECT * FROM words WHERE word = :word") query.bindValue(":word", word) if not query.exec(): query_error(query) if query.next(): # we have something self.defined(query.value("word_id"), start, end) return dictionary = PyDictionary() meaning = json.dumps(dictionary.meaning(word)) por = dictionary.translate(word, "pt") query.prepare( "INSERT INTO words (word, definition, translation) " "VALUES (:word, :definition, :translation)" ) query.bindValue(":word", word) query.bindValue(":definition", meaning) query.bindValue(":translation", por) if not query.exec(): query_error(query) self.defined(query.lastInsertId(), start, end) return def defined(self, word_id: int, start: int, end: int) -> None: query = QSqlQuery() query.prepare( "SELECT * FROM word_paragraph " "WHERE word_id = :word_id " "AND paragraph_id = :paragraph_id " "AND start = :start " "AND end = :end" ) query.bindValue(":word_id", word_id) query.bindValue(":paragraph_id", self.paragraph_id) query.bindValue(":start", start) query.bindValue(":end", end) if not query.exec(): query_error(query) if query.next(): return query.prepare( "INSERT INTO word_paragraph VALUES " "( :word_id, :paragraph_id, :start, :end)" ) query.bindValue(":word_id", word_id) query.bindValue(":paragraph_id", self.paragraph_id) query.bindValue(":start", start) query.bindValue(":end", end) if not query.exec(): query_error(query) def_format = QTextCharFormat() def_format.setFontUnderline(True) cursor = QTextCursor(self.paraEdit.document()) cursor.setPosition(start, QTextCursor.MoveMode.MoveAnchor) cursor.setPosition(end, QTextCursor.MoveMode.KeepAnchor) cursor.setCharFormat(def_format) return def display_definition(self) -> None: cursor = self.paraEdit.textCursor() query = QSqlQuery() query.prepare( "SELECT w.* FROM word_paragraph wp " "LEFT JOIN words w " "ON (w.word_id = wp.word_id) " "WHERE :position BETWEEN wp.start AND wp.end " "AND wp.paragraph_id = :paragraph_id" ) query.bindValue(":position", cursor.position()) query.bindValue(":paragraph_id", self.paragraph_id) print("display_definition()", cursor.position()) if not query.exec(): query_error(query) if not query.next(): return word = query.value("word") definition = json.loads(query.value("definition")) self.defEdit.document().clear() cursor = self.defEdit.textCursor() word_format = QTextCharFormat() word_format.setFontPointSize(48) word_format.setFontWeight(QFont.Weight.Bold) cursor.insertText(word, word_format) typeFormat = QTextListFormat() typeFormat.setStyle(QTextListFormat.Style.ListDisc) typeFormat.setIndent(1) defFormat = QTextListFormat() defFormat.setStyle(QTextListFormat.Style.ListCircle) defFormat.setIndent(2) word_format.setFontWeight(QFont.Weight.Normal) word_format.setFontPointSize(16) cursor.setCharFormat(word_format) for key in definition.keys(): cursor.insertList(typeFormat) cursor.insertText(key) cursor.insertList(defFormat) first = True for a_def in definition[key]: if not first: cursor.insertBlock() cursor.insertText(a_def) first = False return @pyqtSlot() def showAction(self) -> None: idx = self.stackedWidget.currentIndex() if idx == 0: self.display_definition() self.stackedWidget.setCurrentIndex(1 - idx) return def nextDefinition(self): cursor = self.paraEdit.textCursor() position = cursor.position() print(position) formats = cursor.block().textFormats() found = None for f in formats: wc = QTextCursor(cursor) wc.setPosition(f.start) wc.movePosition( QTextCursor.MoveOperation.Right, QTextCursor.MoveMode.KeepAnchor, f.length, ) word = wc.selectedText() cf = wc.charFormat() if f.start <= position: continue if not cf.fontUnderline(): continue if not found: found = f elif f.start < found.start: found = f if found: cursor.setPosition(found.start) self.paraEdit.setTextCursor(cursor) self.display_definition() return @pyqtSlot() def nextAction(self) -> None: if self.stackedWidget.currentIndex() == 1: self.nextDefinition() return paraQuery = QSqlQuery() paraQuery.prepare( "SELECT * FROM paragraphs WHERE " "section_id=:section_id AND sequence = :sequence" ) paraQuery.bindValue(":section_id", self.section_id) paraQuery.bindValue(":sequence", self.paraSequence + 1) if not paraQuery.exec(): query_error(paraQuery) if not paraQuery.next(): secQuery = QSqlQuery() secQuery.prepare( "SELECT * FROM sections WHERE book_id=:book_id " "AND sequence = " "(SELECT sequence FROM sections WHERE " "section_id = :section_id)+1" ) secQuery.bindValue(":book_id", self.book_id) secQuery.bindValue(":section_id", self.section_id) if not secQuery.exec(): query_error(secQuery) if not secQuery.next(): return self.paraSequence = 0 self.section_id = secQuery.value("section_id") paraQuery.bindValue(":section_id", self.section_id) paraQuery.bindValue(":sequence", self.paraSequence) if not paraQuery.exec(): query_error(paraQuery) paraQuery.next() self.display_paragraph(paraQuery.value("paragraph_id")) return @pyqtSlot() def prevAction(self) -> None: return