From d46281fda7d7f96e772e1f718a89467ed6caf4b9 Mon Sep 17 00:00:00 2001 From: "Christopher T. Johnson" Date: Tue, 25 Feb 2025 09:56:53 -0500 Subject: [PATCH] Add a new dialog to get database settings. Fixes: #5 Added a new dialog for database settings. Updated dbConfig to use QSettings. --- lib/dbConfig.py | 32 +++---- scotus-pull.py | 18 +++- setupDialog.py | 67 ++++++++++++++ ui/dbSetup.py | 176 ++++++++++++++++++++++++++++++++++++ ui/dbSetup.ui | 231 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 507 insertions(+), 17 deletions(-) create mode 100644 setupDialog.py create mode 100644 ui/dbSetup.py create mode 100644 ui/dbSetup.ui diff --git a/lib/dbConfig.py b/lib/dbConfig.py index 0099cd0..a19cd92 100644 --- a/lib/dbConfig.py +++ b/lib/dbConfig.py @@ -1,6 +1,6 @@ -from datetime import date, datetime -from decimal import Decimal +from datetime import date +from PySide6.QtCore import QSettings from pony.orm import ( # type: ignore[import-untyped] Database, LongStr, @@ -11,11 +11,8 @@ from pony.orm import ( # type: ignore[import-untyped] set_sql_debug, ) -db = Database - db = Database() - class Cases(db.Entity): # type: ignore[name-defined] case_id = PrimaryKey(int, auto=True) docket_id = Required(str) @@ -50,13 +47,18 @@ class History(db.Entity): # type: ignore[name-defined] number = Required(int) -set_sql_debug(True) -db.bind( - provider="mysql", - user="scotus", - host="ceph5", - database="scotus", - password="lechOtvirf8Om/", -) -db.generate_mapping(create_tables=True) -db.disconnect() +def updateDatabase(settings: QSettings) -> None: + set_sql_debug(True) + engine = settings.value('engine') + if engine not in ['QMYSQL', 'MARIADB']: + raise Exception(f"Unknown database engine: {engine}") + db.bind( + provider="mysql", + user=settings.value('user'), + host=settings.value('hostname'), + database=settings.value('databasename'), + password=settings.value('password'), + ) + db.generate_mapping(create_tables=True) + db.disconnect() + return diff --git a/scotus-pull.py b/scotus-pull.py index f97b94f..1d6283f 100755 --- a/scotus-pull.py +++ b/scotus-pull.py @@ -1,16 +1,21 @@ #!venv/bin/python3 import faulthandler import sys +from typing import cast -from PySide6.QtCore import QSettings +from PySide6.QtCore import QFile from PySide6.QtSql import ( QSqlDatabase, ) from PySide6.QtWidgets import ( QApplication, + QDialog, + QMainWindow, ) +from lib.dbConfig import updateDatabase from lib.utils import openSettings +from setupDialog import setupDialog faulthandler.enable() @@ -21,16 +26,25 @@ def main() -> int: # app = QApplication(sys.argv) settings = openSettings('database') + file = QFile(settings.fileName()) + if not file.exists(): + result = setupDialog().exec() + if result == QDialog.DialogCode.Rejected: + print(f"We require database credentials") + return(2) + updateDatabase(settings) db = QSqlDatabase.addDatabase("QMYSQL") db.setHostName(settings.value("hostname")) + portStr = cast(str, settings.value('port', '3306')) + db.setPort(int(portStr)) db.setDatabaseName(settings.value("databasename","scotus")) # type: ignore db.setUserName(settings.value("user","scotus")) # type: ignore db.setPassword(settings.value("password")) settings.endGroup() db.open() - import lib.dbConfig window = MainWindow() + assert isinstance(window, QMainWindow) return app.exec() diff --git a/setupDialog.py b/setupDialog.py new file mode 100644 index 0000000..0626402 --- /dev/null +++ b/setupDialog.py @@ -0,0 +1,67 @@ +from PySide6.QtCore import Slot, Qt +from PySide6.QtGui import QPalette +from PySide6.QtWidgets import QDialog, QStatusBar, QVBoxLayout, QWidget + +from lib.utils import openSettings +from ui.dbSetup import Ui_setupDialog + +class setupDialog(QDialog,Ui_setupDialog): + def __init__(self, parent: QWidget | None = None): + super(setupDialog,self).__init__(parent) + self.setupUi(self) + self.sqliteEdit.setEnabled(False) + + layout = self.layout() + assert isinstance(layout, QVBoxLayout) + self.statusBar = QStatusBar(self) + self.statusBar.setObjectName('statusBar') + where = layout.indexOf(self.buttonBox) + layout.insertWidget(where, self.statusBar) + self.pwEdit.editingFinished.connect(self.pwDone) + self.pwConfirmEdit.editingFinished.connect(self.pwDone) + return + + @Slot() + def pwDone(self): + pw = self.pwEdit.text() + confirm = self.pwConfirmEdit.text() + + if pw != confirm: + palette = self.statusBar.palette() + palette.setColor(QPalette.ColorRole.WindowText, Qt.GlobalColor.red) + self.statusBar.setPalette(palette) + self.statusBar.showMessage("Password doesn't match") + self.pwGood = False + else: + self.statusBar.clearMessage() + self.pwGood = True + return + + @Slot(int) # type: ignore + def done(self, r:int) -> None: + if r == QDialog.DialogCode.Rejected: + super(setupDialog,self).done(r) + return + self.pwDone() + if not self.pwGood: + return + super(setupDialog,self).done(r) + return + + @Slot() + def accept(self) -> None: + settings=openSettings('database') + settings.setValue('hostname', self.hostEdit.text()) + settings.setValue('databasename', self.dbEdit.text()) + settings.setValue('user',self.userEdit.text()) + settings.setValue('password', self.pwEdit.text()) + settings.setValue('port', self.portEdit.text()) + if self.comboBox.currentIndex() == 0: + settings.setValue('engine', 'QMYSQL') + elif self.comboBox.currentIndex() == 1: + settings.setValue('engine', 'QSQLITE') + # Other types: QDB2, QIBASE, QOCI, QODBC, QPSQL, QMIMER + else: + print("Bad Database Type") + settings.sync() + return super().accept() diff --git a/ui/dbSetup.py b/ui/dbSetup.py new file mode 100644 index 0000000..9530fba --- /dev/null +++ b/ui/dbSetup.py @@ -0,0 +1,176 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'dbSetup.ui' +## +## Created by: Qt User Interface Compiler version 6.8.2 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient, + QCursor, QFont, QFontDatabase, QGradient, + QIcon, QImage, QKeySequence, QLinearGradient, + QPainter, QPalette, QPixmap, QRadialGradient, + QTransform) +from PySide6.QtWidgets import (QAbstractButton, QApplication, QComboBox, QDialog, + QDialogButtonBox, QFormLayout, QLabel, QLineEdit, + QSizePolicy, QStackedWidget, QVBoxLayout, QWidget) + +class Ui_setupDialog(object): + def setupUi(self, setupDialog): + if not setupDialog.objectName(): + setupDialog.setObjectName(u"setupDialog") + setupDialog.resize(400, 300) + self.actionBrowse = QAction(setupDialog) + self.actionBrowse.setObjectName(u"actionBrowse") + icon = QIcon(QIcon.fromTheme(u"folder-open")) + self.actionBrowse.setIcon(icon) + self.actionBrowse.setMenuRole(QAction.MenuRole.NoRole) + self.verticalLayout = QVBoxLayout(setupDialog) + self.verticalLayout.setObjectName(u"verticalLayout") + self.comboBox = QComboBox(setupDialog) + self.comboBox.addItem("") + self.comboBox.addItem("") + self.comboBox.setObjectName(u"comboBox") + + self.verticalLayout.addWidget(self.comboBox) + + self.stackedWidget = QStackedWidget(setupDialog) + self.stackedWidget.setObjectName(u"stackedWidget") + self.mariadb = QWidget() + self.mariadb.setObjectName(u"mariadb") + self.formLayout = QFormLayout(self.mariadb) + self.formLayout.setObjectName(u"formLayout") + self.label = QLabel(self.mariadb) + self.label.setObjectName(u"label") + + self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label) + + self.hostEdit = QLineEdit(self.mariadb) + self.hostEdit.setObjectName(u"hostEdit") + + self.formLayout.setWidget(0, QFormLayout.FieldRole, self.hostEdit) + + self.label_2 = QLabel(self.mariadb) + self.label_2.setObjectName(u"label_2") + + self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_2) + + self.portEdit = QLineEdit(self.mariadb) + self.portEdit.setObjectName(u"portEdit") + + self.formLayout.setWidget(1, QFormLayout.FieldRole, self.portEdit) + + self.label_3 = QLabel(self.mariadb) + self.label_3.setObjectName(u"label_3") + + self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_3) + + self.dbEdit = QLineEdit(self.mariadb) + self.dbEdit.setObjectName(u"dbEdit") + + self.formLayout.setWidget(2, QFormLayout.FieldRole, self.dbEdit) + + self.label_4 = QLabel(self.mariadb) + self.label_4.setObjectName(u"label_4") + + self.formLayout.setWidget(3, QFormLayout.LabelRole, self.label_4) + + self.userEdit = QLineEdit(self.mariadb) + self.userEdit.setObjectName(u"userEdit") + + self.formLayout.setWidget(3, QFormLayout.FieldRole, self.userEdit) + + self.label_5 = QLabel(self.mariadb) + self.label_5.setObjectName(u"label_5") + + self.formLayout.setWidget(4, QFormLayout.LabelRole, self.label_5) + + self.pwEdit = QLineEdit(self.mariadb) + self.pwEdit.setObjectName(u"pwEdit") + self.pwEdit.setEchoMode(QLineEdit.EchoMode.Password) + + self.formLayout.setWidget(4, QFormLayout.FieldRole, self.pwEdit) + + self.label_7 = QLabel(self.mariadb) + self.label_7.setObjectName(u"label_7") + + self.formLayout.setWidget(5, QFormLayout.LabelRole, self.label_7) + + self.pwConfirmEdit = QLineEdit(self.mariadb) + self.pwConfirmEdit.setObjectName(u"pwConfirmEdit") + self.pwConfirmEdit.setEchoMode(QLineEdit.EchoMode.Password) + + self.formLayout.setWidget(5, QFormLayout.FieldRole, self.pwConfirmEdit) + + self.stackedWidget.addWidget(self.mariadb) + self.sqlite = QWidget() + self.sqlite.setObjectName(u"sqlite") + self.formLayout_2 = QFormLayout(self.sqlite) + self.formLayout_2.setObjectName(u"formLayout_2") + self.label_6 = QLabel(self.sqlite) + self.label_6.setObjectName(u"label_6") + + self.formLayout_2.setWidget(0, QFormLayout.LabelRole, self.label_6) + + self.sqliteEdit = QLineEdit(self.sqlite) + self.sqliteEdit.setObjectName(u"sqliteEdit") + + self.formLayout_2.setWidget(0, QFormLayout.FieldRole, self.sqliteEdit) + + self.stackedWidget.addWidget(self.sqlite) + + self.verticalLayout.addWidget(self.stackedWidget) + + self.buttonBox = QDialogButtonBox(setupDialog) + self.buttonBox.setObjectName(u"buttonBox") + self.buttonBox.setOrientation(Qt.Orientation.Horizontal) + self.buttonBox.setStandardButtons(QDialogButtonBox.StandardButton.Cancel|QDialogButtonBox.StandardButton.Ok) + + self.verticalLayout.addWidget(self.buttonBox) + +#if QT_CONFIG(shortcut) + self.label.setBuddy(self.hostEdit) + self.label_2.setBuddy(self.portEdit) + self.label_3.setBuddy(self.dbEdit) + self.label_4.setBuddy(self.userEdit) + self.label_5.setBuddy(self.pwEdit) + self.label_7.setBuddy(self.pwConfirmEdit) +#endif // QT_CONFIG(shortcut) + + self.retranslateUi(setupDialog) + self.buttonBox.accepted.connect(setupDialog.accept) + self.buttonBox.rejected.connect(setupDialog.reject) + self.comboBox.currentIndexChanged.connect(self.stackedWidget.setCurrentIndex) + + self.stackedWidget.setCurrentIndex(0) + + + QMetaObject.connectSlotsByName(setupDialog) + # setupUi + + def retranslateUi(self, setupDialog): + setupDialog.setWindowTitle(QCoreApplication.translate("setupDialog", u"setupDialog", None)) + self.actionBrowse.setText("") +#if QT_CONFIG(tooltip) + self.actionBrowse.setToolTip(QCoreApplication.translate("setupDialog", u"Browse for database file", None)) +#endif // QT_CONFIG(tooltip) + self.comboBox.setItemText(0, QCoreApplication.translate("setupDialog", u"MariaDB/MySQL", None)) + self.comboBox.setItemText(1, QCoreApplication.translate("setupDialog", u"SQLite", None)) + + self.label.setText(QCoreApplication.translate("setupDialog", u"Host", None)) + self.label_2.setText(QCoreApplication.translate("setupDialog", u"Port", None)) + self.portEdit.setText(QCoreApplication.translate("setupDialog", u"3306", None)) + self.label_3.setText(QCoreApplication.translate("setupDialog", u"Database Name", None)) + self.dbEdit.setText(QCoreApplication.translate("setupDialog", u"scotus", None)) + self.label_4.setText(QCoreApplication.translate("setupDialog", u"User Name", None)) + self.userEdit.setText(QCoreApplication.translate("setupDialog", u"scotus", None)) + self.label_5.setText(QCoreApplication.translate("setupDialog", u"Password", None)) + self.label_7.setText(QCoreApplication.translate("setupDialog", u"Confirm", None)) + self.label_6.setText(QCoreApplication.translate("setupDialog", u"Datbase File", None)) + # retranslateUi + diff --git a/ui/dbSetup.ui b/ui/dbSetup.ui new file mode 100644 index 0000000..b9b99c5 --- /dev/null +++ b/ui/dbSetup.ui @@ -0,0 +1,231 @@ + + + setupDialog + + + + 0 + 0 + 400 + 300 + + + + setupDialog + + + + + + + MariaDB/MySQL + + + + + SQLite + + + + + + + + 0 + + + + + + + Host + + + hostEdit + + + + + + + + + + Port + + + portEdit + + + + + + + 3306 + + + + + + + Database Name + + + dbEdit + + + + + + + scotus + + + + + + + User Name + + + userEdit + + + + + + + scotus + + + + + + + Password + + + pwEdit + + + + + + + QLineEdit::EchoMode::Password + + + + + + + Confirm + + + pwConfirmEdit + + + + + + + QLineEdit::EchoMode::Password + + + + + + + + + + + Datbase File + + + + + + + + + + + + + + Qt::Orientation::Horizontal + + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + + + + + + + + + + + Browse for database file + + + QAction::MenuRole::NoRole + + + + + + + buttonBox + accepted() + setupDialog + accept() + + + 227 + 278 + + + 157 + 274 + + + + + buttonBox + rejected() + setupDialog + reject() + + + 295 + 284 + + + 286 + 274 + + + + + comboBox + currentIndexChanged(int) + stackedWidget + setCurrentIndex(int) + + + 199 + 22 + + + 199 + 149 + + + + +