4
4
from typing import TYPE_CHECKING
5
5
6
6
from qgis .PyQt import uic
7
- from qgis .PyQt .QtCore import Qt
7
+ from qgis .PyQt .QtCore import QDate , Qt
8
8
from qgis .PyQt .QtGui import QStandardItem , QStandardItemModel
9
9
from qgis .PyQt .QtWidgets import (
10
10
QComboBox ,
11
11
QDateEdit ,
12
12
QDialog ,
13
13
QDialogButtonBox ,
14
14
QLineEdit ,
15
- QListView ,
16
15
QPushButton ,
17
16
QSizePolicy ,
18
17
QSpacerItem ,
18
+ QStyledItemDelegate ,
19
+ QTableWidget ,
19
20
QTextEdit ,
20
21
QTreeWidgetItem ,
22
+ QWidget ,
21
23
)
22
24
23
25
from arho_feature_template .core .models import LifeCycle , Plan , RegulationGroup , RegulationGroupLibrary
26
+ from arho_feature_template .gui .components .code_combobox import CodeComboBox
24
27
from arho_feature_template .gui .components .plan_regulation_group_widget import RegulationGroupWidget
25
28
from arho_feature_template .gui .components .tree_with_search_widget import TreeWithSearchWidget
26
29
from arho_feature_template .project .layers .code_layers import (
32
35
if TYPE_CHECKING :
33
36
from qgis .PyQt .QtWidgets import QComboBox , QLineEdit , QTextEdit , QVBoxLayout , QWidget
34
37
35
- from arho_feature_template .gui .components .code_combobox import CodeComboBox , HierarchicalCodeComboBox
38
+ from arho_feature_template .gui .components .code_combobox import HierarchicalCodeComboBox
36
39
37
40
ui_path = resources .files (__package__ ) / "plan_attribute_form.ui"
38
41
FormClass , _ = uic .loadUiType (ui_path )
39
42
40
43
44
+ class LifecycleTableModel (QStandardItemModel ):
45
+ def __init__ (self , status_options , parent = None ):
46
+ super ().__init__ (parent )
47
+ self .status_options = status_options
48
+
49
+ def flags (self , index ):
50
+ if index .column () == 0 : # "Elinkaaren tila" - editable combo box
51
+ return Qt .ItemIsSelectable | Qt .ItemIsEnabled
52
+
53
+ if index .column () in (1 , 2 ): # Dates
54
+ return Qt .ItemIsSelectable | Qt .ItemIsEnabled | Qt .ItemIsEditable
55
+ return super ().flags (index )
56
+
57
+
58
+ class LifecycleDelegate (QStyledItemDelegate ):
59
+ def create_editor (self , parent , option , index ):
60
+ if index .column () == 0 : # Status column
61
+ lifecycle_combo_box = CodeComboBox (parent )
62
+ lifecycle_combo_box .populate_from_code_layer (LifeCycleStatusLayer )
63
+ return lifecycle_combo_box
64
+ if index .column () in (1 , 2 ): # Dates columns
65
+ date_edit = QDateEdit (parent )
66
+ date_edit .setDisplayFormat ("yyyy-MM-dd" )
67
+ date_edit .setCalendarPopup (True )
68
+ return date_edit
69
+ return super ().createEditor (parent , option , index )
70
+
71
+ def set_editor_data (self , editor , index ):
72
+ if isinstance (editor , CodeComboBox ) and index .column () == 0 :
73
+ value = index .data (Qt .EditRole )
74
+ if value is not None :
75
+ editor .set_value (value )
76
+ elif isinstance (editor , QDateEdit ) and index .column () in (1 , 2 ):
77
+ value = index .data (Qt .EditRole )
78
+ if value :
79
+ editor .setDate (QDate .fromString (value , "yyyy-MM-dd" ))
80
+
81
+ def set_model_data (self , editor , model , index ):
82
+ if isinstance (editor , CodeComboBox ) and index .column () == 0 :
83
+ model .setData (index , editor .value (), Qt .EditRole )
84
+ if isinstance (editor , QDateEdit ) and index .column () in (1 , 2 ):
85
+ model .setData (index , editor .date ().toString ("yyyy-MM-dd" ), Qt .EditRole )
86
+
87
+
41
88
class PlanAttributeForm (QDialog , FormClass ): # type: ignore
42
89
permanent_identifier_line_edit : QLineEdit
43
90
name_line_edit : QLineEdit
44
91
organisation_combo_box : CodeComboBox
45
92
description_text_edit : QTextEdit
46
93
plan_type_combo_box : HierarchicalCodeComboBox
47
- # lifecycle_status_combo_box: CodeComboBox
94
+ lifecycle_status_combo_box : CodeComboBox
48
95
record_number_line_edit : QLineEdit
49
96
producers_plan_identifier_line_edit : QLineEdit
50
97
matter_management_identifier_line_edit : QLineEdit
@@ -53,11 +100,9 @@ class PlanAttributeForm(QDialog, FormClass): # type: ignore
53
100
plan_regulation_group_libraries_combobox : QComboBox
54
101
regulation_groups_tree_layout : QVBoxLayout
55
102
56
- lifecycle_status_combo_box : CodeComboBox
57
- lifecycle_start_date : QDateEdit
58
- lifecycle_end_date : QDateEdit
59
- add_lifecycle_button : QPushButton
60
- lifecycle_list : QListView
103
+ lifecycle_table : QTableWidget
104
+ add_lifecycle : QPushButton
105
+ delete_lifecycle : QPushButton
61
106
62
107
button_box : QDialogButtonBox
63
108
@@ -105,9 +150,13 @@ def __init__(self, plan: Plan, regulation_group_libraries: list[RegulationGroupL
105
150
for regulation_group in plan .general_regulations :
106
151
self .add_plan_regulation_group (regulation_group )
107
152
108
- self .lifecycle_model = QStandardItemModel ()
109
- self .lifecycle_list .setModel (self .lifecycle_model )
110
- self .add_lifecycle_button .clicked .connect (self .save_lifecycle )
153
+ # Lifecycle table setup
154
+ self .lifecycle_table .setColumnCount (3 ) # Three columns: Status, Start Date, End Date
155
+ self .lifecycle_table .setHorizontalHeaderLabels (["Elinkaaren tila" , "Alkupvm" , "Loppupvm" ])
156
+ self .lifecycle_table .setRowCount (0 ) # No rows initially
157
+
158
+ self .add_lifecycle_button .clicked .connect (self .add_lifecycle_row )
159
+ self .delete_lifecycle_button .clicked .connect (self .delete_lifecycle_row )
111
160
112
161
self .button_box .button (QDialogButtonBox .Ok ).setEnabled (False )
113
162
self .button_box .accepted .connect (self ._on_ok_clicked )
@@ -116,12 +165,30 @@ def __init__(self, plan: Plan, regulation_group_libraries: list[RegulationGroupL
116
165
117
166
def _check_required_fields (self ) -> None :
118
167
ok_button = self .button_box .button (QDialogButtonBox .Ok )
168
+
169
+ # Check if all required fields are filled and lifecycle table has at least one valid row
170
+ has_valid_lifecycle_row = False
171
+ for row in range (self .lifecycle_table .rowCount ()):
172
+ status_item = self .lifecycle_table .cellWidget (row , 0 )
173
+ start_date_item = self .lifecycle_table .cellWidget (row , 1 )
174
+ end_date_item = self .lifecycle_table .cellWidget (row , 2 )
175
+
176
+ if (
177
+ status_item
178
+ and status_item .value () is not None
179
+ and start_date_item
180
+ and start_date_item .date ()
181
+ and (end_date_item and end_date_item .date () or True )
182
+ ):
183
+ has_valid_lifecycle_row = True
184
+ break
185
+
119
186
if (
120
187
self .name_line_edit .text () != ""
121
188
and self .plan_type_combo_box .value () is not None
122
189
and self .organisation_combo_box .value () is not None
123
- # and self.lifecycle_status_combo_box.value() is not None
124
- and self . lifecycle_model . rowCount () > 0
190
+ and self .lifecycle_status_combo_box .value () is not None
191
+ and has_valid_lifecycle_row # Ensure there's at least one valid lifecycle row
125
192
):
126
193
ok_button .setEnabled (True )
127
194
else :
@@ -168,45 +235,72 @@ def init_plan_regulation_group_library(self, library: RegulationGroupLibrary):
168
235
169
236
# ---
170
237
171
- def save_lifecycle (self ):
172
- # Get values from the widgets
173
- status = self .lifecycle_status_combo_box .currentText () # Get the selected text from the combo box
174
- start_date = self .lifecycle_start_date .date ().toString ("yyyy-MM-dd" ) # Format the QDate as a string
175
- end_date = self .lifecycle_end_date .date ().toString ("yyyy-MM-dd" ) if self .lifecycle_end_date .date () else None
238
+ def add_lifecycle_row (self ):
239
+ row_position = self .lifecycle_table .rowCount ()
240
+ self .lifecycle_table .insertRow (row_position )
241
+
242
+ status = CodeComboBox (self )
243
+ status .populate_from_code_layer (LifeCycleStatusLayer )
244
+ self .lifecycle_table .setCellWidget (row_position , 0 , status )
176
245
177
- # Format the lifecycle entry
178
- date_range = f"{ start_date } - { end_date } " if end_date else start_date
179
- lifecycle_entry = f"{ status } | { date_range } "
246
+ start_date_edit = QDateEdit (self )
247
+ start_date_edit .setDisplayFormat ("yyyy-MM-dd" )
248
+ start_date_edit .setCalendarPopup (True )
249
+ self .lifecycle_table .setCellWidget (row_position , 1 , start_date_edit )
180
250
181
- # Add to the model
182
- item = QStandardItem (lifecycle_entry )
183
- item .setData (self .lifecycle_status_combo_box .value (), Qt .UserRole + 1 )
184
- self .lifecycle_model .appendRow (item )
251
+ end_date_edit = QDateEdit (self )
252
+ end_date_edit .setDisplayFormat ("yyyy-MM-dd" )
253
+ end_date_edit .setCalendarPopup (True )
254
+ self .lifecycle_table .setCellWidget (row_position , 2 , end_date_edit )
255
+
256
+ self .lifecycle_table .resizeRowsToContents ()
257
+ self .lifecycle_table .resizeColumnsToContents ()
258
+
259
+ def delete_lifecycle_row (self ):
260
+ selected_rows = self .lifecycle_table .selectionModel ().selectedRows ()
261
+
262
+ if selected_rows :
263
+ row_position = selected_rows [0 ].row ()
264
+ self .lifecycle_table .removeRow (row_position )
265
+ self ._check_required_fields ()
266
+
267
+ def save_lifecycle (self ):
268
+ for row in range (self .lifecycle_table .rowCount ()):
269
+ status = self .lifecycle_table .cellWidget (row , 0 )
270
+ start_date_item = self .lifecycle_table .cellWidget (row , 1 )
271
+ end_date_item = self .lifecycle_table .cellWidget (row , 2 )
272
+
273
+ if status and start_date_item :
274
+ status = status .value () if status .value () is not None else ""
275
+ start_date = start_date_item .date ().toString ("yyyy-MM-dd" ) if start_date_item .date () else ""
276
+ end_date = end_date_item .date ().toString ("yyyy-MM-dd" ) if end_date_item .date () else None
277
+
278
+ lifecycle_model_item = QStandardItem (status )
279
+ lifecycle_model_item .setData (status .value (), Qt .UserRole + 1 )
280
+ start_date_model_item = QStandardItem (start_date )
281
+ end_date_model_item = QStandardItem (end_date if end_date else "" )
282
+
283
+ self .lifecycle_table .model ().appendRow (
284
+ [lifecycle_model_item , start_date_model_item , end_date_model_item ]
285
+ )
185
286
186
- # Optionally, check required fields again
187
287
self ._check_required_fields ()
188
288
189
289
def into_lifecycle_model (self ) -> list [LifeCycle ]:
190
290
lifecycles = []
191
291
192
- for row in range (self .lifecycle_model .rowCount ()):
193
- item = self .lifecycle_model .item (row )
194
- if item :
195
- lifecycle_entry = item .text ()
196
- parts = lifecycle_entry .split (" | " )
197
- date_range = parts [1 ]
198
- date_parts = date_range .split (" - " )
199
- start_date = date_parts [0 ]
200
- end_date = date_parts [1 ] if len (date_parts ) > 1 else None # End date is optional
201
-
202
- # Add the lifecycle to the list
203
- lifecycles .append (
204
- LifeCycle (
205
- status_id = item .data (Qt .UserRole + 1 ),
206
- starting_at = start_date ,
207
- ending_at = end_date ,
208
- )
209
- )
292
+ # Iterate through the rows in lifecycle_table
293
+ for row in range (self .lifecycle_table .rowCount ()):
294
+ status_item = self .lifecycle_table .cellWidget (row , 0 )
295
+ start_date_item = self .lifecycle_table .cellWidget (row , 1 )
296
+ end_date_item = self .lifecycle_table .cellWidget (row , 2 )
297
+
298
+ if status_item and start_date_item :
299
+ status_id = status_item .value ()
300
+ start_date = start_date_item .date ().toString ("yyyy-MM-dd" ) if start_date_item .date () else ""
301
+ end_date = end_date_item .date ().toString ("yyyy-MM-dd" ) if end_date_item .date () else None
302
+
303
+ lifecycles .append (LifeCycle (status_id = status_id , starting_at = start_date , ending_at = end_date ))
210
304
211
305
return lifecycles
212
306
@@ -229,5 +323,4 @@ def into_model(self) -> Plan:
229
323
230
324
def _on_ok_clicked (self ):
231
325
self .model = self .into_model ()
232
- # self.lifecycle_model = self.into_lifecycle_model()
233
326
self .accept ()
0 commit comments