-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New UI for plugin management, stored/retrieved plugin states and new …
…PluginWrapper for UI
- Loading branch information
Showing
11 changed files
with
893 additions
and
246 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ htmlcov | |
/data | ||
.ruff* | ||
/local_test_data | ||
test_export/ | ||
|
||
# IDE | ||
*.code-workspace | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import os | ||
from sqlite3 import connect | ||
|
||
DB_DIR = "data" | ||
DB_NAME = "plugins.db" | ||
TABLE_NAME = "plugins" | ||
|
||
|
||
def create_new_db_if_not_exist(): | ||
path = os.path.join(os.getcwd(), DB_DIR, DB_NAME) | ||
connection = connect(path) | ||
cur = connection.cursor() | ||
cur.execute(f"CREATE TABLE IF NOT EXISTS {TABLE_NAME}(plugin_name TEXT PRIMARY KEY, enabled BOOL)") | ||
|
||
|
||
def add__update_plugin_configuration(plugin_name: str, enabled: bool): | ||
path = os.path.join(os.getcwd(), DB_DIR, DB_NAME) | ||
connection = connect(path) | ||
cur = connection.cursor() | ||
|
||
query = "SELECT * from plugins WHERE plugin_name = ?" | ||
params = (plugin_name,) | ||
|
||
cur.execute(query, params) | ||
result = cur.fetchall() | ||
|
||
if result: | ||
query = "UPDATE plugins SET enabled = ? WHERE plugin_name = ? " | ||
params = (enabled, plugin_name) | ||
cur.execute(query, params) | ||
|
||
else: | ||
query = "INSERT INTO plugins (plugin_name, enabled) VALUES(?,?)" | ||
params = (plugin_name, enabled) | ||
cur.execute(query, params) | ||
|
||
connection.commit() | ||
|
||
|
||
def get_plugin_configuration(plugin_name: str): | ||
path = os.path.join(os.getcwd(), DB_DIR, DB_NAME) | ||
connection = connect(path) | ||
cur = connection.cursor() | ||
|
||
query = "SELECT * from plugins WHERE plugin_name = ?" | ||
params = [plugin_name] | ||
|
||
cur.execute(query, params) | ||
result = cur.fetchone() | ||
|
||
return result if result else None | ||
|
||
|
||
if __name__ == "__main__": | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
import logging | ||
import sys | ||
from pathlib import Path | ||
|
||
from PySide6.QtCore import QMetaMethod, Qt, Signal, Slot | ||
from PySide6.QtGui import QIcon | ||
from PySide6.QtWidgets import ( | ||
QApplication, | ||
QFileDialog, | ||
QListWidgetItem, | ||
QMainWindow, | ||
QMessageBox, | ||
) | ||
from qt_material import apply_stylesheet | ||
|
||
from joystick_diagrams import app_init | ||
from joystick_diagrams.app_state import AppState | ||
from joystick_diagrams.exceptions import JoystickDiagramsException | ||
from joystick_diagrams.plugins.plugin_interface import PluginInterface | ||
from joystick_diagrams.ui.mock_main.qt_designer import plugin_settings_ui | ||
from joystick_diagrams.ui.plugin_wrapper import PluginWrapper | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
RECONFIGURE_TEXT = "Reconfigure" | ||
|
||
|
||
class PluginSettings(QMainWindow, plugin_settings_ui.Ui_Form): # Refactor pylint: disable=too-many-instance-attributes | ||
pluginModified = Signal(object) | ||
pluginPathConfigured = Signal(object) | ||
|
||
def __init__(self, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
self.setupUi(self) | ||
self.plugin = None | ||
|
||
# Attributes | ||
|
||
# Connections | ||
self.pluginEnabled.stateChanged.connect(self.handle_enabled_change) | ||
self.configureLink.clicked.connect(self.open_file_dialog) | ||
|
||
# Setup | ||
|
||
# Style Overrides | ||
self.configureLink.setStyleSheet("color: white !important;") | ||
|
||
def setup(self): | ||
"""Initialise the widget configuration""" | ||
|
||
# Setup labels | ||
self.pluginEnabled.setChecked(self.plugin.enabled) | ||
self.plugin_name_label.setText(self.plugin.plugin_name) | ||
self.plugin_version_label.setText(self.plugin.plugin_version) | ||
|
||
# Setup file selection | ||
self.configureLink.setText(self.get_plugin_path_type().dialog_title) | ||
self.configureLink.setDescription("") | ||
|
||
if self.plugin.plugin.path: | ||
self.set_plugin_path(self.plugin.plugin.path) | ||
|
||
# TODO if file already set from storage... | ||
|
||
def handle_enabled_change(self, data): | ||
self.plugin.enabled = data if data == 0 else 1 | ||
print(f"Plugin enabled state is now {self.plugin.enabled}") | ||
self.pluginModified.emit(self.plugin) | ||
|
||
def get_plugin_file_extensions(self): | ||
return [] | ||
|
||
def get_plugin_path_type(self) -> PluginInterface.FilePath | PluginInterface.FolderPath: | ||
return self.plugin.plugin.path_type | ||
|
||
def set_plugin_path(self, path: Path): | ||
if not isinstance(path, Path): | ||
return | ||
|
||
try: | ||
load = self.plugin.plugin.set_path(path) | ||
|
||
if not load: | ||
raise JoystickDiagramsException("Error loading plugin") | ||
if load: | ||
self.configureLink.setText(RECONFIGURE_TEXT) | ||
self.configureLink.setDescription(path.__str__()) | ||
self.pluginPathConfigured.emit(self.plugin) | ||
except JoystickDiagramsException: | ||
QMessageBox.warning( | ||
self, | ||
"Plugin failure", | ||
"Something went very wrong.", | ||
buttons=QMessageBox.Discard, | ||
defaultButton=QMessageBox.Discard, | ||
) | ||
|
||
def open_file_dialog(self) -> None: | ||
plugin_path = self.get_plugin_path_type() | ||
|
||
match type(plugin_path): | ||
case PluginInterface.FilePath: | ||
exts = " ".join(f"*{ext}" for ext in plugin_path.supported_extensions) | ||
|
||
_file = QFileDialog.getOpenFileName( | ||
self, | ||
caption=plugin_path.dialog_title, | ||
dir=plugin_path.default_path, | ||
filter=(f"All Files ({exts})"), | ||
) | ||
|
||
if _file[0]: | ||
self.set_plugin_path(Path(_file[0])) | ||
case PluginInterface.FolderPath: | ||
_folder = QFileDialog.getExistingDirectory(self, plugin_path.dialog_title, plugin_path.default_path) | ||
if _folder: | ||
self.set_plugin_path(Path(_folder)) | ||
case _: | ||
_logger.error("Unexpected plugin path type given.") | ||
|
||
# def load_plugin_settings(self, data): | ||
|
||
|
||
# self.pluginVersionInfo.setText(f"Version {data.version}") | ||
# self.pluginName.setText(f"{data.name} Settings") | ||
|
||
# # Path Setup | ||
# self.pluginPath.setText(data.path) | ||
|
||
# # Prevents duplicate signals from being connected | ||
# if self.pluginPathButton.isSignalConnected(QMetaMethod.fromSignal(self.pluginPathButton.clicked)): | ||
# self.pluginPathButton.clicked.disconnect() | ||
|
||
# # Clean up | ||
# # Additional validation to be added to PluginInterface/Plugin loading | ||
# if isinstance(data.path_type, PluginInterface.FilePath): | ||
# self.pluginPathButton.clicked.connect(lambda: self.file_dialog(data.path_type)) | ||
|
||
# if isinstance(data.path_type, PluginInterface.FolderPath): | ||
# self.pluginPathButton.clicked.connect(lambda: self.folder_dialog(data.path_type)) | ||
|
||
|
||
if __name__ == "__main__": | ||
app = QApplication(sys.argv) | ||
init = app_init.init() | ||
window = PluginSettings() | ||
window.show() | ||
apply_stylesheet(app, theme="dark_blue.xml", invert_secondary=False) | ||
app.exec() |
116 changes: 116 additions & 0 deletions
116
joystick_diagrams/ui/mock_main/qt_designer/plugin_settings_ui.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
################################################################################ | ||
## Form generated from reading UI file 'plugin_settings_ui.ui' | ||
## | ||
## Created by: Qt User Interface Compiler version 6.6.1 | ||
## | ||
## 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 (QBrush, QColor, QConicalGradient, QCursor, | ||
QFont, QFontDatabase, QGradient, QIcon, | ||
QImage, QKeySequence, QLinearGradient, QPainter, | ||
QPalette, QPixmap, QRadialGradient, QTransform) | ||
from PySide6.QtWidgets import (QApplication, QCheckBox, QCommandLinkButton, QFrame, | ||
QHBoxLayout, QLabel, QSizePolicy, QSpacerItem, | ||
QVBoxLayout, QWidget) | ||
|
||
class Ui_Form(object): | ||
def setupUi(self, Form): | ||
if not Form.objectName(): | ||
Form.setObjectName(u"Form") | ||
Form.resize(750, 596) | ||
Form.setMaximumSize(QSize(750, 600)) | ||
self.verticalLayoutWidget = QWidget(Form) | ||
self.verticalLayoutWidget.setObjectName(u"verticalLayoutWidget") | ||
self.verticalLayoutWidget.setGeometry(QRect(9, 9, 731, 87)) | ||
self.verticalLayout_3 = QVBoxLayout(self.verticalLayoutWidget) | ||
self.verticalLayout_3.setObjectName(u"verticalLayout_3") | ||
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) | ||
self.horizontalLayout = QHBoxLayout() | ||
self.horizontalLayout.setObjectName(u"horizontalLayout") | ||
self.plugin_name_label = QLabel(self.verticalLayoutWidget) | ||
self.plugin_name_label.setObjectName(u"plugin_name_label") | ||
font = QFont() | ||
font.setPointSize(12) | ||
self.plugin_name_label.setFont(font) | ||
|
||
self.horizontalLayout.addWidget(self.plugin_name_label) | ||
|
||
self.plugin_version_label = QLabel(self.verticalLayoutWidget) | ||
self.plugin_version_label.setObjectName(u"plugin_version_label") | ||
|
||
self.horizontalLayout.addWidget(self.plugin_version_label) | ||
|
||
|
||
self.verticalLayout_3.addLayout(self.horizontalLayout) | ||
|
||
self.horizontalLayout_2 = QHBoxLayout() | ||
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") | ||
self.pluginEnabled = QCheckBox(self.verticalLayoutWidget) | ||
self.pluginEnabled.setObjectName(u"pluginEnabled") | ||
sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) | ||
sizePolicy.setHorizontalStretch(0) | ||
sizePolicy.setVerticalStretch(0) | ||
sizePolicy.setHeightForWidth(self.pluginEnabled.sizePolicy().hasHeightForWidth()) | ||
self.pluginEnabled.setSizePolicy(sizePolicy) | ||
font1 = QFont() | ||
font1.setPointSize(14) | ||
self.pluginEnabled.setFont(font1) | ||
|
||
self.horizontalLayout_2.addWidget(self.pluginEnabled) | ||
|
||
self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Preferred, QSizePolicy.Minimum) | ||
|
||
self.horizontalLayout_2.addItem(self.horizontalSpacer) | ||
|
||
self.configureLink = QCommandLinkButton(self.verticalLayoutWidget) | ||
self.configureLink.setObjectName(u"configureLink") | ||
sizePolicy1 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) | ||
sizePolicy1.setHorizontalStretch(0) | ||
sizePolicy1.setVerticalStretch(0) | ||
sizePolicy1.setHeightForWidth(self.configureLink.sizePolicy().hasHeightForWidth()) | ||
self.configureLink.setSizePolicy(sizePolicy1) | ||
self.configureLink.setStyleSheet(u"color: rgb(255, 255, 255);\n" | ||
"selection-color: rgb(255, 255, 255);") | ||
|
||
self.horizontalLayout_2.addWidget(self.configureLink) | ||
|
||
|
||
self.verticalLayout_3.addLayout(self.horizontalLayout_2) | ||
|
||
self.frame = QFrame(Form) | ||
self.frame.setObjectName(u"frame") | ||
self.frame.setGeometry(QRect(9, 102, 116, 33)) | ||
self.frame.setAutoFillBackground(False) | ||
self.frame.setFrameShape(QFrame.Box) | ||
self.frame.setFrameShadow(QFrame.Plain) | ||
self.frame.setLineWidth(0) | ||
self.frame.setMidLineWidth(1) | ||
self.verticalLayout_2 = QVBoxLayout(self.frame) | ||
self.verticalLayout_2.setObjectName(u"verticalLayout_2") | ||
self.label_3 = QLabel(self.frame) | ||
self.label_3.setObjectName(u"label_3") | ||
|
||
self.verticalLayout_2.addWidget(self.label_3) | ||
|
||
|
||
self.retranslateUi(Form) | ||
|
||
QMetaObject.connectSlotsByName(Form) | ||
# setupUi | ||
|
||
def retranslateUi(self, Form): | ||
Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None)) | ||
self.plugin_name_label.setText(QCoreApplication.translate("Form", u"Plugin_Name", None)) | ||
self.plugin_version_label.setText(QCoreApplication.translate("Form", u"TextLabel", None)) | ||
self.pluginEnabled.setText(QCoreApplication.translate("Form", u"Enable Plugin", None)) | ||
self.configureLink.setText(QCoreApplication.translate("Form", u"Configure plugin", None)) | ||
self.configureLink.setDescription(QCoreApplication.translate("Form", u"Select your file/folder", None)) | ||
self.label_3.setText(QCoreApplication.translate("Form", u"No options available", None)) | ||
# retranslateUi | ||
|
Oops, something went wrong.