8
8
from RATapi .utils .enums import Procedures
9
9
10
10
from rascal2 .config import path_for
11
- from rascal2 .widgets .delegates import ValidatedInputDelegate , ValueSpinBoxDelegate
11
+ from rascal2 .widgets .delegates import ParametersDelegate , ValidatedInputDelegate , ValueSpinBoxDelegate
12
12
13
13
14
14
class ClassListModel (QtCore .QAbstractTableModel ):
@@ -28,12 +28,21 @@ class ClassListModel(QtCore.QAbstractTableModel):
28
28
def __init__ (self , classlist : RATapi .ClassList , parent : QtWidgets .QWidget ):
29
29
super ().__init__ (parent )
30
30
self .parent = parent
31
+
32
+ self .classlist : RATapi .ClassList
33
+ self .item_type : type
34
+ self .headers : list [str ]
35
+
36
+ self .setup_classlist (classlist )
37
+ self .edit_mode = False
38
+
39
+ def setup_classlist (self , classlist : RATapi .ClassList ):
40
+ """Setup the ClassList, type and headers for the model."""
31
41
self .classlist = classlist
32
42
self .item_type = classlist ._class_handle
33
43
if not issubclass (self .item_type , pydantic .BaseModel ):
34
44
raise NotImplementedError ("ClassListModel only works for classlists of Pydantic models!" )
35
45
self .headers = list (self .item_type .model_fields )
36
- self .edit_mode = False
37
46
38
47
def rowCount (self , parent = None ) -> int :
39
48
return len (self .classlist )
@@ -80,7 +89,12 @@ def headerData(self, section, orientation, role=QtCore.Qt.ItemDataRole.DisplayRo
80
89
and role == QtCore .Qt .ItemDataRole .DisplayRole
81
90
and section != 0
82
91
):
83
- return self .headers [section - 1 ].replace ("_" , " " ).title ()
92
+ header = self .headers [section - 1 ]
93
+ if "SLD" in header :
94
+ header = header .replace ("_" , " " )
95
+ else :
96
+ header = header .replace ("_" , " " ).title ()
97
+ return header
84
98
return None
85
99
86
100
def append_item (self ):
@@ -296,3 +310,104 @@ def edit(self):
296
310
for i in range (0 , self .model .rowCount ()):
297
311
if i in self .model .protected_indices :
298
312
self .table .setIndexWidget (self .model .index (i , 0 ), None )
313
+
314
+
315
+ class LayersModel (ClassListModel ):
316
+ """Classlist model for Layers."""
317
+
318
+ def __init__ (self , classlist : RATapi .ClassList , parent : QtWidgets .QWidget ):
319
+ super ().__init__ (classlist , parent )
320
+ self .absorption = classlist ._class_handle == RATapi .models .AbsorptionLayer
321
+ self .SLD_imags = {}
322
+
323
+ def flags (self , index ):
324
+ flags = super ().flags (index )
325
+ if self .edit_mode :
326
+ flags |= QtCore .Qt .ItemFlag .ItemIsEditable
327
+ return flags
328
+
329
+ def append_item (self ):
330
+ kwargs = {"thickness" : "" , "SLD" : "" , "roughness" : "" }
331
+ if self .absorption :
332
+ kwargs ["SLD_imaginary" ] = ""
333
+ self .classlist .append (self .item_type (** kwargs ))
334
+ self .endResetModel ()
335
+
336
+ def set_absorption (self , absorption : bool ):
337
+ """Set whether the project is using absorption or not.
338
+
339
+ Parameters
340
+ ----------
341
+ absorption : bool
342
+ Whether the project is using absorption.
343
+
344
+ """
345
+ if self .absorption != absorption :
346
+ self .beginResetModel ()
347
+ self .absorption = absorption
348
+ if absorption :
349
+ classlist = RATapi .ClassList (
350
+ [
351
+ RATapi .models .AbsorptionLayer (
352
+ ** dict (layer ),
353
+ SLD_imaginary = self .SLD_imags .get (layer .name , "" ),
354
+ )
355
+ for layer in self .classlist
356
+ ]
357
+ )
358
+ # set handle manually for if classlist is empty
359
+ classlist ._class_handle = RATapi .models .AbsorptionLayer
360
+ else :
361
+ # we save the SLD_imaginary values so that they aren't lost if the
362
+ # user accidentally toggles absorption off and on!
363
+ self .SLD_imags = {layer .name : layer .SLD_imaginary for layer in self .classlist }
364
+ classlist = RATapi .ClassList (
365
+ [
366
+ RATapi .models .Layer (
367
+ name = layer .name ,
368
+ thickness = layer .thickness ,
369
+ SLD = layer .SLD_real ,
370
+ roughness = layer .roughness ,
371
+ hydration = layer .hydration ,
372
+ hydrate_with = layer .hydrate_with ,
373
+ )
374
+ for layer in self .classlist
375
+ ]
376
+ )
377
+ classlist ._class_handle = RATapi .models .Layer
378
+ self .setup_classlist (classlist )
379
+ self .parent .parent .parent .update_draft_project ({"layers" : classlist })
380
+ self .endResetModel ()
381
+
382
+
383
+ class LayerFieldWidget (ProjectFieldWidget ):
384
+ """Project field widget for Layer objects."""
385
+
386
+ classlist_model = LayersModel
387
+
388
+ def __init__ (self , field , parent ):
389
+ super ().__init__ (field , parent )
390
+ self .project_widget = parent .parent
391
+
392
+ def set_item_delegates (self ):
393
+ for i in range (1 , self .model .columnCount ()):
394
+ if i in [1 , self .model .columnCount () - 1 ]:
395
+ header = self .model .headers [i - 1 ]
396
+ self .table .setItemDelegateForColumn (
397
+ i , ValidatedInputDelegate (self .model .item_type .model_fields [header ], self .table )
398
+ )
399
+ else :
400
+ self .table .setItemDelegateForColumn (i , ParametersDelegate (self .project_widget , self .table ))
401
+
402
+ def set_absorption (self , absorption : bool ):
403
+ """Set whether the classlist uses AbsorptionLayers.
404
+
405
+ Parameters
406
+ ----------
407
+ absorption : bool
408
+ Whether the classlist should use AbsorptionLayers.
409
+
410
+ """
411
+ self .model .set_absorption (absorption )
412
+ if self .model .edit_mode :
413
+ self .edit ()
0 commit comments