order-processing/QT/Input_Dialog.py

164 lines
6.8 KiB
Python

import collections
from PySide6 import QtCore, QtWidgets
from QT.Main_Window import Attr_Dict
class Input_Dialog (QtWidgets.QDialog) :
def __init__ (self, title, ** spec) :
super ().__init__ (spec.pop ("parent", None))
self.setWindowTitle (title)
self.layout = L = QtWidgets.QFormLayout (self)
self.widgets = {}
self.min_width = spec.pop ("_MIN_WIDTH", 200)
self.field_spec = spec
self.dependencies = collections.defaultdict (list)
for name, fspec in spec.items () :
type = fspec.get ("type")
default = fspec.get ("default")
if type is None and default is not None :
type = default.__class__.__name__
getattr (self, "_add_%s" % type, self._add_str) \
(L, name, fspec, default, type)
for attr, format in fspec.get ("auto", {}).items () :
self.dependencies [attr].append ((name, format))
layout = QtWidgets.QHBoxLayout ()
ok = QtWidgets.QPushButton ("OK")
ok.clicked.connect (self.store_values)
cancel = QtWidgets.QPushButton ("Cancel")
cancel.clicked.connect (self.reject)
layout.addStretch (10)
layout.addWidget (ok)
layout.addWidget (cancel)
ok.setDefault (True)
L.addRow (layout)
self.setMinimumWidth (self.min_width)
self.result = Attr_Dict ()
# end def __init__
def get_values (self) :
data = Attr_Dict ()
errors = {}
for name, (getter, _) in self.widgets.items () :
data [name] = value = getter ()
fspec = self.field_spec [name]
if not value and fspec.get ("required", False) :
errors [name] = "Required"
return data, errors
# end def store_values
def store_values (self) :
self.result, errors = self.get_values ()
if not errors :
self.accept ()
# end def store_values
def _auto_update (self, changed) :
if changed in self.dependencies :
values, _ = self.get_values ()
for attr, format in self.dependencies [changed] :
if not values.get (attr) :
self.widgets [attr] [1] (format % values)
# end def _auto_update
def _add_str (self, L, name, fspec, default, type) :
widget = QtWidgets.QLineEdit ()
widget.setText (default or "")
self.widgets [name] = widget.text, widget.setText
L.addRow (fspec.get ("title", name.capitalize ()), widget)
widget.editingFinished.connect \
(lambda : self._auto_update (name))
# end def _add_str
def _add_int (self, L, name, fspec, default, type) :
widget = QtWidgets.QSpinBox ()
widget.setRange (-65536, 0x7FFFFFFF)
widget.setValue (default or 0)
self.widgets [name] = widget.value, widget.setValue
L.addRow (fspec.get ("title", name.capitalize ()), widget)
widget.editingFinished.connect \
(lambda : self._auto_update (name))
# end def _add_int
def _add_file_dialog (self, cb, L, name, fspec, default) :
layout = QtWidgets.QHBoxLayout ()
current = QtWidgets.QLineEdit ()
current.setText (default or "")
current.setEnabled (False)
change = QtWidgets.QPushButton ("...")
change.setFixedWidth (24)
change.clicked.connect (lambda : cb (fspec, current))
layout.addWidget (current)
layout.addWidget (change)
layout.setStretch (0, 10)
self.widgets [name] = current.text, current.setText
L.addRow (fspec.get ("title", name.capitalize ()), layout)
self.min_width = max (self.min_width, 600)
# end def _add_file_dialog
def _add_open_filename (self, L, name, fspec, default, type) :
self._add_file_dialog \
(self._choose_file_dialog, L, name, fspec, default)
# end def _add_open_filename
def _choose_file_dialog (self, fspec, current) :
filter = fspec.get ("filter", ())
filter = ";;".join ("%s (%s)" % (t, e) for (t, e) in filter)
file_name = QtWidgets.QFileDialog.getOpenFileName \
( filter = filter
) [0]
if file_name :
current.setText (file_name)
# end def _choose_file_dialog
def _add_save_filename (self, L, name, fspec, default, type) :
self._add_file_dialog \
(self._save_file_dialog, L, name, fspec, default)
# end def _add_open_filename
def _save_file_dialog (self, fspec, current) :
filter = fspec.get ("filter", ())
filter = ";;".join ("%s (%s)" % (t, e) for (t, e) in filter)
file_name = QtWidgets.QFileDialog.getSaveFileName \
( filter = filter
) [0]
if file_name :
current.setText (file_name)
# end def _save_file_dialog
def _add_drop_down (self, L, name, fspec, default, type) :
widget = QtWidgets.QComboBox ()
for idx, e in enumerate \
(sorted (fspec ["choices"], key = lambda e : e ["label"])) :
widget.addItem (e ["label"], e ["value"])
if "tooltip" in e :
widget.setItemData \
(idx, e ["tooltip"], QtCore.Qt.ToolTipRole)
self.widgets [name] = widget.currentText, widget.setCurrentText
L.addRow (fspec.get ("title", name.capitalize ()), widget)
widget.currentTextChanged.connect \
(lambda : self._auto_update (name))
# end def _add_drop_down
def run (self) :
if self.exec () == 1 :
return self.result
# end def run
# end class Input_Dialog
if __name__ == "__main__" :
app = QtWidgets.QApplication ([])
r = Input_Dialog \
( "Test"
, name = {"default": "", "title" : "Layer Name", "required": True}
, file_name = {"default": "", "title" : "Filename"
, "type" : "save_filename"
, "filter": ( ( "Layer Files", "*.layer")
, ( "Json Files", "*.json")
, ( "All Files", "*.*")
)
, "auto" : {"name" : "%(name)s/%(name)s.layer"}
}
).run ()
if r is not None :
print (r)