200 lines
8.5 KiB
Python
200 lines
8.5 KiB
Python
from pathlib import Path
|
|
|
|
from PySide6.QtCore import QSettings, Qt, Signal
|
|
from PySide6.QtGui import QColor
|
|
from PySide6.QtWidgets import QColorDialog, QDialog, QFileDialog, QHeaderView, QTableWidgetItem
|
|
|
|
from bedit.core.libraries import bundled_library_path, default_library_paths
|
|
from bedit.gui.preferences import application_settings
|
|
from bedit.gui.generated.ui_settings_dialog import Ui_SettingsDialog
|
|
from bedit.gui.editors.openmodelica import HIGHLIGHT_STYLES
|
|
|
|
|
|
class SettingsDialog(QDialog):
|
|
"""Edit application preferences defined in the Designer form."""
|
|
|
|
settingsChanged = Signal()
|
|
|
|
def __init__(self, parent=None) -> None:
|
|
super().__init__(parent)
|
|
self.ui = Ui_SettingsDialog()
|
|
self.ui.setupUi(self)
|
|
self.ui.graphGridSpinBox.valueChanged.connect(
|
|
self.ui.graphSnapSpinBox.setMaximum
|
|
)
|
|
self.settings = application_settings()
|
|
self.ui.addLibraryFileButton.clicked.connect(self._add_library_file)
|
|
self.ui.addLibraryFolderButton.clicked.connect(self._add_library_folder)
|
|
self.ui.removeLibraryPathButton.clicked.connect(self._remove_library_path)
|
|
self.ui.libraryPathsList.itemSelectionChanged.connect(self._update_remove_button)
|
|
self.ui.syntaxStylesTable.cellDoubleClicked.connect(self._choose_syntax_color)
|
|
self._load_settings()
|
|
|
|
def _load_settings(self) -> None:
|
|
enabled = self.settings.value("autosave/enabled", None)
|
|
if enabled is None:
|
|
enabled = self.settings.value("General/autosaveEnabled", False)
|
|
interval = self.settings.value("autosave/intervalMinutes", None)
|
|
if interval is None:
|
|
interval = self.settings.value("General/autosaveInterval", 5)
|
|
self.ui.autosaveGroupBox.setChecked(
|
|
self._as_bool(enabled)
|
|
)
|
|
self.ui.autosaveIntervalSpinBox.setValue(int(interval))
|
|
self.ui.libraryPathsList.clear()
|
|
self.ui.libraryPathsList.addItems(self.library_paths(self.settings))
|
|
self.ui.graphGridSpinBox.setValue(self.graph_grid_size(self.settings))
|
|
self.ui.graphSnapSpinBox.setValue(self.graph_snap_size(self.settings))
|
|
self.ui.iconGridSpinBox.setValue(self.icon_grid_size(self.settings))
|
|
self._load_syntax_styles()
|
|
self._update_remove_button()
|
|
|
|
def _load_syntax_styles(self) -> None:
|
|
table = self.ui.syntaxStylesTable
|
|
table.setRowCount(len(HIGHLIGHT_STYLES))
|
|
table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
|
|
for row, (category, defaults) in enumerate(HIGHLIGHT_STYLES.items()):
|
|
label, default_color, default_bold, default_italic = defaults
|
|
name_item = QTableWidgetItem(label)
|
|
name_item.setData(Qt.ItemDataRole.UserRole, category)
|
|
name_item.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable)
|
|
table.setItem(row, 0, name_item)
|
|
color = str(self.settings.value(f"syntax/{category}/color", default_color))
|
|
color_item = QTableWidgetItem(color)
|
|
color_item.setBackground(QColor(color))
|
|
color_item.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable)
|
|
table.setItem(row, 1, color_item)
|
|
for column, key, default in (
|
|
(2, "bold", default_bold),
|
|
(3, "italic", default_italic),
|
|
):
|
|
item = QTableWidgetItem()
|
|
item.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsUserCheckable)
|
|
enabled = self._as_bool(
|
|
self.settings.value(f"syntax/{category}/{key}", default)
|
|
)
|
|
item.setCheckState(
|
|
Qt.CheckState.Checked if enabled else Qt.CheckState.Unchecked
|
|
)
|
|
table.setItem(row, column, item)
|
|
|
|
def _choose_syntax_color(self, row: int, column: int) -> None:
|
|
if column != 1:
|
|
return
|
|
item = self.ui.syntaxStylesTable.item(row, column)
|
|
color = QColorDialog.getColor(QColor(item.text()), self, "Highlight colour")
|
|
if color.isValid():
|
|
item.setText(color.name())
|
|
item.setBackground(color)
|
|
|
|
@staticmethod
|
|
def _as_bool(value) -> bool:
|
|
if isinstance(value, str):
|
|
return value.strip().lower() in {"1", "true", "yes", "on"}
|
|
return bool(value)
|
|
|
|
@staticmethod
|
|
def library_paths(settings: QSettings | None = None) -> list[str]:
|
|
settings = settings if settings is not None else application_settings()
|
|
value = settings.value("libraries/paths", default_library_paths())
|
|
if isinstance(value, str):
|
|
paths = [value]
|
|
else:
|
|
paths = [str(path) for path in value]
|
|
bundled = bundled_library_path()
|
|
migrated = [
|
|
str(bundled)
|
|
if not Path(path).exists()
|
|
and Path(path).parent == bundled.parent
|
|
and Path(path).suffix.lower() == ".json"
|
|
else path
|
|
for path in paths
|
|
]
|
|
if migrated != paths:
|
|
settings.setValue("libraries/paths", migrated)
|
|
settings.sync()
|
|
return migrated
|
|
|
|
@staticmethod
|
|
def graph_grid_size(settings: QSettings | None = None) -> int:
|
|
settings = settings if settings is not None else application_settings()
|
|
return settings.value("grid/graphSize", 64, type=int)
|
|
|
|
@staticmethod
|
|
def graph_snap_size(settings: QSettings | None = None) -> int:
|
|
settings = settings if settings is not None else application_settings()
|
|
return settings.value("grid/graphSnapSize", 8, type=int)
|
|
|
|
@staticmethod
|
|
def icon_grid_size(settings: QSettings | None = None) -> int:
|
|
settings = settings if settings is not None else application_settings()
|
|
return settings.value("grid/iconSize", 8, type=int)
|
|
|
|
def _add_library_file(self) -> None:
|
|
path, _ = QFileDialog.getOpenFileName(
|
|
self,
|
|
"Add library",
|
|
"",
|
|
"BEdit libraries (*.beb *.bedit.json *.json);;All files (*)",
|
|
)
|
|
if path:
|
|
self._append_unique_path(path)
|
|
|
|
def _add_library_folder(self) -> None:
|
|
path = QFileDialog.getExistingDirectory(self, "Add library folder")
|
|
if path:
|
|
self._append_unique_path(path)
|
|
|
|
def _append_unique_path(self, path: str) -> None:
|
|
normalized = str(Path(path).expanduser().resolve())
|
|
existing = {
|
|
self.ui.libraryPathsList.item(row).text()
|
|
for row in range(self.ui.libraryPathsList.count())
|
|
}
|
|
if normalized not in existing:
|
|
self.ui.libraryPathsList.addItem(normalized)
|
|
|
|
def _remove_library_path(self) -> None:
|
|
for item in self.ui.libraryPathsList.selectedItems():
|
|
self.ui.libraryPathsList.takeItem(self.ui.libraryPathsList.row(item))
|
|
|
|
def _update_remove_button(self) -> None:
|
|
self.ui.removeLibraryPathButton.setEnabled(bool(self.ui.libraryPathsList.selectedItems()))
|
|
|
|
def accept(self) -> None:
|
|
self.settings.setValue("autosave/enabled", self.ui.autosaveGroupBox.isChecked())
|
|
self.settings.setValue(
|
|
"autosave/intervalMinutes", self.ui.autosaveIntervalSpinBox.value()
|
|
)
|
|
self.settings.remove("General/autosaveEnabled")
|
|
self.settings.remove("General/autosaveInterval")
|
|
paths = [
|
|
self.ui.libraryPathsList.item(row).text()
|
|
for row in range(self.ui.libraryPathsList.count())
|
|
]
|
|
self.settings.setValue("libraries/paths", paths)
|
|
self.settings.setValue("grid/graphSize", self.ui.graphGridSpinBox.value())
|
|
self.settings.setValue("grid/graphSnapSize", self.ui.graphSnapSpinBox.value())
|
|
self.settings.setValue("grid/iconSize", self.ui.iconGridSpinBox.value())
|
|
for row in range(self.ui.syntaxStylesTable.rowCount()):
|
|
category = self.ui.syntaxStylesTable.item(row, 0).data(
|
|
Qt.ItemDataRole.UserRole
|
|
)
|
|
self.settings.setValue(
|
|
f"syntax/{category}/color",
|
|
self.ui.syntaxStylesTable.item(row, 1).text(),
|
|
)
|
|
self.settings.setValue(
|
|
f"syntax/{category}/bold",
|
|
self.ui.syntaxStylesTable.item(row, 2).checkState()
|
|
== Qt.CheckState.Checked,
|
|
)
|
|
self.settings.setValue(
|
|
f"syntax/{category}/italic",
|
|
self.ui.syntaxStylesTable.item(row, 3).checkState()
|
|
== Qt.CheckState.Checked,
|
|
)
|
|
self.settings.sync()
|
|
self.settingsChanged.emit()
|
|
super().accept()
|