QT added
parent
fee801a822
commit
0e5286c333
|
|
@ -0,0 +1,164 @@
|
|||
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)
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
from PySide6 import QtWidgets, QtCore, QtGui
|
||||
import os
|
||||
|
||||
class Attr_Dict (dict) :
|
||||
|
||||
def __getattr__ (self, key) :
|
||||
return self [key]
|
||||
# end def __getattr__
|
||||
|
||||
# end class Attr_Dict
|
||||
|
||||
class Main_Window (QtWidgets.QMainWindow) :
|
||||
|
||||
DEFAULT_SETTINGS_FILE = "settings.ini"
|
||||
|
||||
APP_NAME = "Main Window"
|
||||
VERSION = "0"
|
||||
APP_ORGANISATION = ("Org-Name", "Org-Domain")
|
||||
|
||||
def __init__ (self, app, settings) :
|
||||
super ().__init__ ()
|
||||
self.settings = settings
|
||||
self.setWindowTitle ("%s %s" % (self.APP_NAME, self.VERSION))
|
||||
self._setupActions (app)
|
||||
self._setupGui ()
|
||||
if not self.restore_settings (settings) :
|
||||
self.show ()
|
||||
# end def __init__
|
||||
|
||||
def _setupActions (self, app) :
|
||||
self.actions = Attr_Dict ()
|
||||
self._add_action ("exit", "Exit", self.close, icon = ":/icons/exit.png")
|
||||
# end def _setupActions
|
||||
|
||||
def _add_action (self, name, label, callback, icon = None, ** options) :
|
||||
A = QtGui.QAction (label, self, ** options)
|
||||
if icon :
|
||||
A.setIcon (QtGui.QIcon (icon))
|
||||
self.actions [name] = A
|
||||
A.triggered.connect (callback)
|
||||
# end def _add_action
|
||||
|
||||
def _setupGui (self) :
|
||||
pass
|
||||
# end def _setupGui
|
||||
|
||||
def closeEvent (self, * args) :
|
||||
self.save_settings ()
|
||||
super ().closeEvent (* args)
|
||||
# end def closeEvent
|
||||
|
||||
@classmethod
|
||||
def _open_settings (cls, settings_file = None) :
|
||||
if not settings_file :
|
||||
settings_file = os.path.join (cls.APP_DIR, cls.DEFAULT_SETTINGS_FILE)
|
||||
QtCore.QCoreApplication.setOrganizationName (cls.APP_ORGANISATION [0])
|
||||
QtCore.QCoreApplication.setOrganizationDomain (cls.APP_ORGANISATION [1])
|
||||
QtCore.QCoreApplication.setApplicationName (cls.APP_NAME)
|
||||
return QtCore.QSettings (settings_file, QtCore.QSettings.IniFormat)
|
||||
# end def _open_settings
|
||||
|
||||
@classmethod
|
||||
def load_settings (cls, cmd) :
|
||||
settings = cls._open_settings (cmd.settings_file)
|
||||
ps = cls._load_app_settings (settings)
|
||||
settings.beginGroup ("TempSettings")
|
||||
settings.setValue ("settingsFile", cmd.settings_file)
|
||||
for n, v in ps.items () :
|
||||
if getattr (cmd, n, None) != None :
|
||||
v = getattr (cmd, n)
|
||||
settings.setValue (n, v)
|
||||
settings.endGroup ()
|
||||
return settings
|
||||
# end def load_settings
|
||||
|
||||
def restore_settings (self, settings) :
|
||||
self.settings = settings
|
||||
QtCore.QTimer.singleShot (1, self._restore_settings)
|
||||
# end def restore_settings
|
||||
|
||||
def _restore_settings (self) :
|
||||
settings = self.settings
|
||||
settings.beginGroup ("MainWindow")
|
||||
self.restoreGeometry (settings.value ("geometry" ))
|
||||
self.restoreState (settings.value ("windowState"))
|
||||
settings.endGroup ()
|
||||
# end def _restore_settings
|
||||
|
||||
def save_settings (self) :
|
||||
settings = self.settings
|
||||
settings.beginGroup ("MainWindow")
|
||||
settings.setValue ("geometry", self.saveGeometry ())
|
||||
settings.setValue ("windowState", self.saveState ())
|
||||
settings.endGroup ()
|
||||
# end def save_settings
|
||||
|
||||
@classmethod
|
||||
def run (cls, settings) :
|
||||
QtWidgets.QApplication.setStyle ("macintosh")
|
||||
app = QtWidgets.QApplication ([])
|
||||
if cls.pre_main_window_action (settings) :
|
||||
self = cls (app, settings)
|
||||
if self.isVisible () :
|
||||
app.exec_ ()
|
||||
# end def run
|
||||
|
||||
@classmethod
|
||||
def pre_main_window_action (cls, settings) :
|
||||
return True
|
||||
# end def pre_main_window_action
|
||||
|
||||
# end class Main_Window
|
||||
|
||||
### __END__ Main_Window
|
||||
|
|
@ -0,0 +1,448 @@
|
|||
# Simplified tree model (based on a QtAbstractItemModel)
|
||||
|
||||
from PySide2 import QtCore, QtWidgets
|
||||
from Accessor import Getter
|
||||
import contextlib
|
||||
|
||||
Qt = QtCore.Qt
|
||||
|
||||
class Column :
|
||||
"""Column definition"""
|
||||
|
||||
Flag_Map = dict \
|
||||
( no_flag = (Qt.NoItemFlags, False)
|
||||
, selectable = (Qt.ItemIsSelectable, True)
|
||||
, enabled = (Qt.ItemIsEnabled, True)
|
||||
, editable = (Qt.ItemIsEditable, False)
|
||||
, drag = (Qt.ItemIsDragEnabled, False)
|
||||
, drop = (Qt.ItemIsDropEnabled, False)
|
||||
, checkable = (Qt.ItemIsUserCheckable, False)
|
||||
, tristate = (Qt.ItemIsTristate, False)
|
||||
)
|
||||
|
||||
Clone_Attributes = ("name", "attr", "getter", "_flags", "model")
|
||||
|
||||
def __init__ ( self, name, attr = None, getter = None, model = None
|
||||
, ** flags
|
||||
) :
|
||||
self.name = name
|
||||
self.attr = attr or name.lower ()
|
||||
self.getter = getter or getattr (Getter, self.attr)
|
||||
self.model = model
|
||||
self._flags = flags
|
||||
# end def __init__
|
||||
|
||||
def background (self, row) :
|
||||
return None
|
||||
# end def background
|
||||
|
||||
def __call__ (self, row) :
|
||||
return self.getter (row)
|
||||
# end def __call__
|
||||
|
||||
def clone (self, ** overrides) :
|
||||
d = dict \
|
||||
( (a, overrides.get (a, getattr (self, a)))
|
||||
for a in self.Clone_Attributes
|
||||
)
|
||||
d.update (d.pop ("_flags", {}))
|
||||
return self.__class__ (** d)
|
||||
# end def clone
|
||||
|
||||
def checkstate (self, row) :
|
||||
return None
|
||||
# end def checkstate
|
||||
|
||||
def decoration (self, row) :
|
||||
return None
|
||||
# end def decoration
|
||||
|
||||
def flags (self, row) :
|
||||
result = 0
|
||||
for attr, (flag, default) in self.Flag_Map.items () :
|
||||
v = self._flags.get (attr, default)
|
||||
if callable (v) :
|
||||
v = v (row)
|
||||
if v :
|
||||
result |= flag
|
||||
return result
|
||||
# end def flags
|
||||
|
||||
def font (self, row) :
|
||||
return None
|
||||
# end def font
|
||||
|
||||
def foreground (self, row) :
|
||||
return None
|
||||
# end def foreground
|
||||
|
||||
def text_aligment (self, row) :
|
||||
return None
|
||||
# end def text_aligment
|
||||
|
||||
# end class Column
|
||||
|
||||
class _Root_Item_ :
|
||||
"""Simple models which can be used as hidden root element of no real root
|
||||
element exists in the model
|
||||
"""
|
||||
parent = None
|
||||
|
||||
def __init__ (self, * children) :
|
||||
self.children = []
|
||||
for c in children :
|
||||
self.append (c)
|
||||
# end def __init__
|
||||
|
||||
def append (self, child) :
|
||||
self.children.append (child)
|
||||
child.parent = self
|
||||
# end def append
|
||||
|
||||
def index (self, child) :
|
||||
return self.children.index (child)
|
||||
# end def index
|
||||
|
||||
def __delitem__ (self, key) :
|
||||
del self.children [key]
|
||||
# end def __delitem__
|
||||
|
||||
def __getitem__ (self, key) :
|
||||
return self.children [key]
|
||||
# end def __getitem__
|
||||
|
||||
def __len__ (self) :
|
||||
return len (self.children)
|
||||
# end def __len__
|
||||
|
||||
def __setitem__ (self, key, value) :
|
||||
self.children [key] = value
|
||||
if not isinstance (value, (list, tuple)) :
|
||||
value = (value, )
|
||||
for v in value :
|
||||
v.parent = self
|
||||
# end def __setitem__
|
||||
|
||||
def __str__ (self) :
|
||||
return "<Root-Item>"
|
||||
# end def __str__
|
||||
|
||||
# end class _Root_Item_
|
||||
|
||||
class Model_Adapter (QtCore.QAbstractItemModel) :
|
||||
"""The underlying QT class handling the interface to the wrapper class
|
||||
"""
|
||||
|
||||
### QT Interface
|
||||
def columnCount (self, parent) :
|
||||
return len (self.Columns)
|
||||
# end def columnCount
|
||||
|
||||
def data (self, index, role) :
|
||||
#print ("data", role)
|
||||
if not index.isValid () :
|
||||
return None
|
||||
column = index.column ()
|
||||
item = index.internalPointer ()
|
||||
col_desc = self.Columns [column]
|
||||
if role == Qt.DisplayRole or role == Qt.EditRole :
|
||||
return col_desc (item)
|
||||
elif role == Qt.CheckStateRole :
|
||||
return col_desc.checkstate (item)
|
||||
elif role == Qt.BackgroundRole :
|
||||
return col_desc.background (item)
|
||||
elif role == Qt.ForegroundRole :
|
||||
return col_desc.foreground (item)
|
||||
elif role == Qt.FontRole :
|
||||
return col_desc.font (item)
|
||||
elif role == Qt.DecorationRole :
|
||||
return col_desc.decoration (item)
|
||||
elif role == Qt.TextAlignmentRole :
|
||||
return col_desc.text_aligment (item)
|
||||
return None
|
||||
# end def data
|
||||
|
||||
def flags (self, index) :
|
||||
if index.isValid () :
|
||||
data = index.internalPointer ()
|
||||
col = index.column ()
|
||||
return self.Columns [col].flags (data)
|
||||
return super ().flags (index)
|
||||
# end def flags
|
||||
|
||||
def index (self, row, column, parent_index, parent = None) :
|
||||
#debug = "ID: %d <%-7s>" % \
|
||||
# (row, self.item_path (parent_index, ", ") or "R")
|
||||
if parent is None :
|
||||
if not parent_index.isValid () :
|
||||
parent = self.root_item
|
||||
else :
|
||||
parent = parent_index.internalPointer ()
|
||||
try :
|
||||
child = parent [row]
|
||||
#print ("%s, P<%s>, C<%s>" %(1, parent, child))
|
||||
return self.createIndex (row, column, child)
|
||||
except IndexError as exc:
|
||||
#print (debug, exc)
|
||||
return self.invalid_index
|
||||
# end def index
|
||||
|
||||
def index_for_item (self, item, column = 0) :
|
||||
if item.parent :
|
||||
row = item.parent.index (item)
|
||||
return self.createIndex (row, column, item)
|
||||
return self.invalid_index
|
||||
# end def index_for_item
|
||||
|
||||
def item_from_index (self, index) :
|
||||
if index.isValid () :
|
||||
return index.internalPointer ()
|
||||
# end def item_from_index
|
||||
|
||||
@property
|
||||
def invalid_index (self) :
|
||||
return QtCore.QModelIndex ()
|
||||
# end def invalid_index
|
||||
|
||||
def parent (self, index) :
|
||||
if not index.isValid () :
|
||||
return self.invalid_index
|
||||
item = index.internalPointer ()
|
||||
parent = item.parent
|
||||
if parent is self.root_item :
|
||||
return self.invalid_index
|
||||
if parent.parent :
|
||||
row = parent.parent.index (parent)
|
||||
else :
|
||||
row = 0
|
||||
return self.createIndex (row, 0, parent)
|
||||
# end def parent
|
||||
|
||||
def rowCount (self, parent_index) :
|
||||
if not parent_index.isValid () :
|
||||
parent = self.root_item
|
||||
else:
|
||||
parent = parent_index.internalPointer ()
|
||||
#path = self.item_path (parent_index, ", ") or "R"
|
||||
#print ("RC: %-7s [%d]" % (path, len (parent)))
|
||||
return len (parent)
|
||||
# end def rowCount
|
||||
|
||||
def setData (self, index, value, role) :
|
||||
if index.isValid () :
|
||||
if self.set_data (index, value, role) :
|
||||
self.dataChanged.emit (index, index)
|
||||
return True
|
||||
return False
|
||||
# end def setData
|
||||
|
||||
### QT Optional
|
||||
def headerData (self, section, orientation, role) :
|
||||
if ( (orientation == Qt.Horizontal)
|
||||
and (role == Qt.DisplayRole)
|
||||
) :
|
||||
return self.Columns [section].name
|
||||
return None
|
||||
# end def headerData
|
||||
|
||||
def hasChildren (self, index) :
|
||||
result = True
|
||||
if index.isValid () :
|
||||
result = bool (len (index.internalPointer ()))
|
||||
#path = self.item_path (parent_index, ", ") or "R"
|
||||
#print ("HC: %-7s [%s]" % (path, result))
|
||||
return result
|
||||
# end def hasChildren
|
||||
|
||||
### mime data handling
|
||||
def supportedDropActions (self) :
|
||||
default = super ().supportedDropActions ()
|
||||
return getattr (self, "supported_drop_actions", default)
|
||||
# end def supportedDropActions
|
||||
|
||||
def mimeTypes (self) :
|
||||
model_fct = getattr (self, "mime_types", None)
|
||||
result = super ().mimeTypes ()
|
||||
if model_fct is not None :
|
||||
result = model_fct (result)
|
||||
return result
|
||||
# end def mimeTypes
|
||||
|
||||
def mimeData (self, indexes) :
|
||||
model_fct = getattr (self, "mime_data", None)
|
||||
if model_fct :
|
||||
items = [i.internalPointer () for i in indexes]
|
||||
result = QtCore.QMimeData ()
|
||||
model_fct (result, items, indexes)
|
||||
return result
|
||||
return super ().mimeData (indexes)
|
||||
# end def mimeData
|
||||
|
||||
def dropMimeData (self, mime_data, action, row, column, parent) :
|
||||
model_fct = getattr (self, "drop_mime_data", None)
|
||||
if model_fct is None :
|
||||
return super ().dropMimeData \
|
||||
(mime_data, action, row, column, parent)
|
||||
return model_fct \
|
||||
(mime_data, action, row, column, parent)
|
||||
# end def dropMimeData
|
||||
|
||||
### Python Interface
|
||||
Columns = ()
|
||||
Supported_Drop_Actions = ()
|
||||
mimeTypes = ()
|
||||
|
||||
def __init__ (self, * items, ** kw) :
|
||||
super ().__init__ ()
|
||||
self.Columns = [c.clone (model = self) for c in self.Columns]
|
||||
root_item = kw.pop ("root", None)
|
||||
if root_item is None :
|
||||
root_item = _Root_Item_ (* items)
|
||||
self.root_item = root_item
|
||||
# end def __init__
|
||||
|
||||
def append (self, item, parent = None) :
|
||||
if parent is None :
|
||||
parent = self.root_item
|
||||
start = len (parent)
|
||||
index = self.index_for_item (parent)
|
||||
self.beginInsertRows (index, start, start)
|
||||
parent.append (item)
|
||||
self.endInsertRows ()
|
||||
# end def append
|
||||
|
||||
def dump (self, root_index = None, indend = "") :
|
||||
if root_index is None :
|
||||
root_index = self.invalid_index
|
||||
result = []
|
||||
for i in range (self.rowCount (root_index)) :
|
||||
index = self.index (i, 0, root_index)
|
||||
item = self.item_from_index (index)
|
||||
result.append ("%s%s" % (indend, item))
|
||||
result.extend (self.dump (index, indend + "."))
|
||||
if not indend :
|
||||
print ("---- Dump by index functions")
|
||||
print ("\n".join (result))
|
||||
print ("---- Dump end")
|
||||
return result
|
||||
# end def dump
|
||||
|
||||
def _walk (self, path, root, root_index = None) :
|
||||
for n in range (len (root)) :
|
||||
c = root [n]
|
||||
p = path + (n, )
|
||||
if root_index is not None :
|
||||
index = self.index (n, 0, root_index)
|
||||
yield p, c, index
|
||||
yield from self._walk (p, c, index)
|
||||
else :
|
||||
yield p, c
|
||||
yield from self._walk (p, c)
|
||||
# end def _walk
|
||||
|
||||
def walk (self, with_index = False) :
|
||||
index = None
|
||||
if with_index :
|
||||
index = self.invalid_index
|
||||
return self._walk ((), self.root_item, index)
|
||||
# end def walk
|
||||
|
||||
def item_path (self, index, joiner = None) :
|
||||
result = []
|
||||
if index.isValid () :
|
||||
result.extend (self.item_path (self.parent (index)))
|
||||
result.append (index.row ())
|
||||
if joiner :
|
||||
result = joiner.join (result)
|
||||
return result
|
||||
# end def item_path
|
||||
|
||||
def qindex (self, item, col = 0) :
|
||||
if item is self.root_item :
|
||||
row = 0
|
||||
else :
|
||||
row = item.parent.index (item)
|
||||
return self.createIndex (row, col, item.parent)
|
||||
# end def qindex
|
||||
|
||||
def insert_row (self, item, parent_index = None, start = -1) :
|
||||
count = 1
|
||||
parent_index = parent_index or self.invalid_index
|
||||
if start == -1 :
|
||||
start = self.rowCount (parent_index)
|
||||
if parent_index.isValid () :
|
||||
parent = parent_index.internalPointer ()
|
||||
else :
|
||||
parent = self.root_item
|
||||
self.beginInsertRows (parent_index, start, start + count - 1)
|
||||
parent [start:start] = [item]
|
||||
self.endInsertRows ()
|
||||
return self.index (start, 0, parent_index)
|
||||
# end def insert_row
|
||||
|
||||
def item_from_index (self, index) :
|
||||
if index.isValid () :
|
||||
return index.internalPointer ()
|
||||
# end def item_from_index
|
||||
|
||||
def remove (self, index = None, item = None) :
|
||||
if index is None :
|
||||
parent = item.parent
|
||||
row = parent.index (item)
|
||||
parent_index = self.qindex (parent)
|
||||
else :
|
||||
row = index.row ()
|
||||
parent_index = index.parent ()
|
||||
if parent_index.isValid () :
|
||||
parent = parent_index.internalPointer ()
|
||||
else :
|
||||
parent = self.root_item
|
||||
item = parent [row]
|
||||
self.beginRemoveRows (parent_index, row, row + 1)
|
||||
del parent [row]
|
||||
if hasattr (item, "delete") :
|
||||
item.delete ()
|
||||
self.endRemoveRows ()
|
||||
# end def remove
|
||||
|
||||
@contextlib.contextmanager
|
||||
def replace_model (self) :
|
||||
self.beginResetModel ()
|
||||
yield
|
||||
self.endResetModel ()
|
||||
# end def replace_model
|
||||
|
||||
def set_data (self, index, value, role) :
|
||||
return False
|
||||
# end def set_data
|
||||
|
||||
# end class Model_Adapter
|
||||
|
||||
class Tree_View (QtWidgets.QTreeView) :
|
||||
|
||||
def expanded_nodes (self) :
|
||||
expanded_path = []
|
||||
model = self.model ()
|
||||
if model :
|
||||
for p, _, index in model.walk (True) :
|
||||
if self.isExpanded (index) :
|
||||
expanded_path.append (p)
|
||||
return expanded_path
|
||||
# end def expanded_nodes
|
||||
|
||||
def restore_expanded_nodes (self, expanded) :
|
||||
model = self.model ()
|
||||
if model :
|
||||
indixes = {}
|
||||
iv_index = model.invalid_index
|
||||
for path in expanded :
|
||||
parent_index = indixes.get (path [:-1], iv_index)
|
||||
index = model.index (path [-1], 0, parent_index)
|
||||
indixes [path] = index
|
||||
item = model.item_from_index (index)
|
||||
if item and len (item) :
|
||||
self.setExpanded (index, True)
|
||||
# end def restore_expanded_nodes
|
||||
|
||||
# end class Tree_View
|
||||
### __END__ QT.Model_Adapter
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
from PySide2 import QtWidgets, QtGui
|
||||
|
||||
|
||||
def Push_Button (text, clicked = None, icon = None) :
|
||||
button = QtWidgets.QPushButton (text)
|
||||
if clicked :
|
||||
button.clicked.connect (clicked)
|
||||
if icon :
|
||||
button.setIcon (QtGui.QIcon (icon))
|
||||
return button
|
||||
# end def Push_Button
|
||||
|
||||
#class Push_Button (QtWidgets.QPushButton) :
|
||||
#
|
||||
# def __init__ ( self, text
|
||||
# , callback = None
|
||||
# , icon = None
|
||||
# ) :
|
||||
# super ().__init__ (text)
|
||||
# if callback :
|
||||
# self.clicked.connect (callback)
|
||||
# if icon :
|
||||
# self.setIcon (QtGui.QIcon (icon))
|
||||
# # end def
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[TempSettings]
|
||||
settingsFile=@Invalid()
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
### package for commone QT classes
|
||||
from PySide6 import QtWidgets, QtCore, QtGui, QtCore
|
||||
QT = QtCore.Qt
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue