import qtawesome as qta
import json
from lys.Qt import QtCore, QtWidgets
from .widgets import FolderButton
[docs]
class DataStorageGUI(QtWidgets.QWidget):
"""
GUI widget for configuring data storage options.
Provide controls to select base folder, data folder, file name, numbering, and enable/disable saving.
Update the storage backend and show a saving-status indicator.
"""
def __init__(self, obj):
"""
Create the storage GUI and bind it to the storage object.
Args:
obj (DataStorage): The storage backend object (must provide ``base``, ``folder``, ``name``, ``getNumber()`` and the ``savingStateChanged`` signal).
"""
super().__init__()
self._obj = obj
self._settingPath = False
self._initLayout()
self._obj.base = self._base.text()
self._obj.folder = self._folder.text()
self._obj.name = self._name.text()
self._obj.savingStateChanged.connect(self._savingStateChanged)
self._obj.numberChanged.connect(self._pathChanged)
def _initLayout(self):
"""
Create and arrange the widgets for the storage configuration panel.
"""
# Widgets for data saving
browse = FolderButton(clicked=self._browse)
browse.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
self._base = QtWidgets.QLineEdit(objectName="DataStorage_base")
self._base.setText(".")
self._folder = QtWidgets.QLineEdit(objectName="DataStorage_folder")
self._name = QtWidgets.QLineEdit(objectName="DataStorage_name")
self._savedIndicator = QtWidgets.QLabel()
self._savedIndicator.setPixmap(qta.icon("ri.check-line", color="green").pixmap(24, 24))
self._savedIndicator.setAlignment(QtCore.Qt.AlignCenter)
self._savingState = QtWidgets.QLabel("[Status] Waiting")
self._numberedCheck = QtWidgets.QCheckBox("Numbered", checked=True, objectName="DataStorage_numbered")
self._enabledCheck = QtWidgets.QCheckBox("Enabled", checked=True, objectName="DataStorage_enabled")
self._number = QtWidgets.QSpinBox()
self._number.setEnabled(True)
# Connect signals
self._base.textChanged.connect(self._pathChanged)
self._folder.textChanged.connect(self._pathChanged)
self._name.textChanged.connect(self._pathChanged)
self._numberedCheck.toggled.connect(self._pathChanged)
self._enabledCheck.toggled.connect(self._pathChanged)
# Layout setup
pathLayout = QtWidgets.QGridLayout()
pathLayout.setAlignment(QtCore.Qt.AlignTop)
pathLayout.addWidget(browse, 1, 0)
pathLayout.addWidget(QtWidgets.QLabel("Base folder"), 0, 1)
pathLayout.addWidget(QtWidgets.QLabel("Data folder"), 0, 2)
pathLayout.addWidget(QtWidgets.QLabel("File name"), 0, 3)
pathLayout.addWidget(self._numberedCheck, 0, 4)
pathLayout.addWidget(self._base, 1, 1)
pathLayout.addWidget(self._folder, 1, 2)
pathLayout.addWidget(self._name, 1, 3)
pathLayout.addWidget(self._number, 1, 4)
pathLayout.addWidget(self._savedIndicator, 2, 0)
pathLayout.addWidget(self._savingState, 2, 1, 1, 3)
pathLayout.addWidget(self._enabledCheck, 2, 4)
mainLayout = QtWidgets.QVBoxLayout()
mainLayout.addLayout(pathLayout)
self.setLayout(mainLayout)
def _pathChanged(self):
"""
Handle changes to path-related widgets and propagate them to the storage object.
"""
if self._settingPath:
return
self._settingPath = True
# Update storage object properties from GUI fields
self._obj.base = self._base.text()
self._obj.folder = self._folder.text()
self._obj.name = self._name.text()
self._obj.numbered = self._numberedCheck.isChecked()
self._obj.enabled = self._enabledCheck.isChecked()
# Update number spinbox only if numbering is enabled
number = self._obj.getNumber()
self._number.setValue(number) if number is not None else self._number.clear()
# Save last path info
lastPath = {"base": self._base.text(), "folder": self._folder.text(), "name": self._name.text()}
with open(".lastPath.json", "w") as f:
json.dump(lastPath, f)
self._settingPath = False
def _browse(self):
"""
Open a dialog to choose the base folder and update the Base field.
"""
baseStr = QtWidgets.QFileDialog.getExistingDirectory(self, "Select base folder", self._base.text())
if baseStr:
self._base.setText(baseStr)
def _savingStateChanged(self, saving):
"""
Update the GUI to reflect the current saving state.
Args:
saving (bool): True when saving is in progress, False otherwise.
"""
if saving:
text = f"[Status] {len(self._obj._paths)} files reserved, {len(self._obj._threads)} files being saved."
self._savingState.setText(text)
else:
self._savingState.setText("[Status] Waiting")
icon = qta.icon("ri.loader-2-line", color="orange") if saving else qta.icon("ri.check-line", color="green")
self._savedIndicator.setPixmap(icon.pixmap(24, 24))