src/bedit/
├── __main__.py
├── core/ # Pure Python, no PySide
│ ├── model.py
│ ├── port_types.py
│ ├── serializer.py
│ └── libraries.py
└── gui/ # All Qt-dependent code
├── app.py
├── main_window.py
├── preferences.py
├── controllers/
├── dialogs/
├── graphics/
├── models/
└── generated/ # Designer/resource output only
Notable improvements:
Domain models, serialization, port types, and library parsing are now Qt-free.
Qt signals and undo infrastructure are explicitly isolated under gui/controllers.
Library parsing is separated from the Qt repository and tree models.
All generated Python is contained in gui/generated.
Designer build tasks now write to the generated directory.
The application entry point and package metadata use the new paths.
README now documents the structure and dependency rules.
Removed the old mixed document, library, and workspace packages.
139 lines
5.9 KiB
Python
139 lines
5.9 KiB
Python
from pathlib import Path
|
|
|
|
from PySide6.QtCore import QSettings, Signal
|
|
from PySide6.QtWidgets import QDialog, QFileDialog, QFormLayout, QGroupBox, QSpinBox
|
|
|
|
from bedit.core.libraries import default_library_paths
|
|
from bedit.gui.preferences import application_settings
|
|
from bedit.gui.generated.ui_settings_dialog import Ui_SettingsDialog
|
|
|
|
|
|
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.grid_group = QGroupBox("Editor grids", self.ui.generalTab)
|
|
grid_form = QFormLayout(self.grid_group)
|
|
self.graph_grid_spin = QSpinBox()
|
|
self.graph_grid_spin.setRange(8, 512)
|
|
self.graph_grid_spin.setSuffix(" units")
|
|
self.graph_snap_spin = QSpinBox()
|
|
self.graph_snap_spin.setRange(1, 128)
|
|
self.graph_snap_spin.setSuffix(" units")
|
|
self.graph_grid_spin.valueChanged.connect(self.graph_snap_spin.setMaximum)
|
|
self.icon_grid_spin = QSpinBox()
|
|
self.icon_grid_spin.setRange(1, 64)
|
|
self.icon_grid_spin.setSuffix(" units")
|
|
grid_form.addRow("Workspace grid size:", self.graph_grid_spin)
|
|
grid_form.addRow("Workspace snapping size:", self.graph_snap_spin)
|
|
grid_form.addRow("Icon grid size:", self.icon_grid_spin)
|
|
self.ui.generalLayout.insertWidget(1, self.grid_group)
|
|
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._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.graph_grid_spin.setValue(self.graph_grid_size(self.settings))
|
|
self.graph_snap_spin.setValue(self.graph_snap_size(self.settings))
|
|
self.icon_grid_spin.setValue(self.icon_grid_size(self.settings))
|
|
self._update_remove_button()
|
|
|
|
@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):
|
|
return [value]
|
|
return [str(path) for path in value]
|
|
|
|
@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 (*.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.graph_grid_spin.value())
|
|
self.settings.setValue("grid/graphSnapSize", self.graph_snap_spin.value())
|
|
self.settings.setValue("grid/iconSize", self.icon_grid_spin.value())
|
|
self.settings.sync()
|
|
self.settingsChanged.emit()
|
|
super().accept()
|