Skip to content

Commit b415127

Browse files
Mtk112nmaarnio
authored andcommitted
Improved lifecycle UI
1 parent 7a82825 commit b415127

File tree

5 files changed

+152
-155
lines changed

5 files changed

+152
-155
lines changed

arho_feature_template/core/models.py

+2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ def from_config_file(
8585
for group_name in feature_data.get("regulation_groups", [])
8686
if (group := cls.find_matching_group_config(group_name, regulation_group_libraries))
8787
],
88+
lifecycles=[],
8889
plan_id=None,
8990
id_=None,
9091
)
@@ -367,6 +368,7 @@ class PlanFeature:
367368
name: str | None = None
368369
description: str | None = None
369370
regulation_groups: list[RegulationGroup] = field(default_factory=list)
371+
lifecycles: list[LifeCycle] = field(default_factory=list)
370372
plan_id: int | None = None
371373
id_: int | None = None
372374

arho_feature_template/core/plan_manager.py

-3
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,6 @@ def edit_plan(self):
229229
active_plan_id = QgsExpressionContextUtils.projectScope(QgsProject.instance()).variable("active_plan_id")
230230
feature = PlanLayer.get_feature_by_id(active_plan_id, no_geometries=False)
231231
if feature is None:
232-
iface.messageBar().pushWarning("", "No active/open plan found!")
233232
return
234233
plan_model = PlanLayer.model_from_feature(feature)
235234

@@ -302,7 +301,6 @@ def edit_plan_feature(self, feature: QgsFeature, layer_name: str):
302301
layer_class = FEATURE_LAYER_NAME_TO_CLASS_MAP[layer_name]
303302
plan_feature = layer_class.model_from_feature(feature)
304303

305-
# Geom editing handled with basic QGIS vertex editing?
306304
title = plan_feature.name if plan_feature.name else layer_name
307305
attribute_form = PlanFeatureForm(
308306
plan_feature, title, [*self.regulation_group_libraries, regulation_group_library_from_active_plan()]
@@ -725,7 +723,6 @@ def save_proposition(proposition: Proposition) -> QgsFeature:
725723
return feature
726724

727725

728-
729726
def save_lifecycle(lifecycle: LifeCycle) -> QgsFeature:
730727
"""Save a list of LifeCycle objects to the layer."""
731728
feature = LifeCycleLayer.feature_from_model(lifecycle)

arho_feature_template/gui/dialogs/plan_attribute_form.py

+117-84
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,22 @@
44
from typing import TYPE_CHECKING
55

66
from qgis.core import QgsApplication
7+
from qgis.gui import QgsDateTimeEdit
78
from qgis.PyQt import uic
8-
from qgis.PyQt.QtCore import QDate, Qt
9-
from qgis.PyQt.QtGui import QStandardItem, QStandardItemModel
9+
from qgis.PyQt.QtCore import Qt
10+
from qgis.PyQt.QtGui import QStandardItem
1011
from qgis.PyQt.QtWidgets import (
1112
QComboBox,
1213
QDateEdit,
1314
QDialog,
1415
QDialogButtonBox,
16+
QHeaderView,
1517
QLineEdit,
1618
QPushButton,
1719
QSizePolicy,
1820
QSpacerItem,
19-
QStyledItemDelegate,
2021
QTableWidget,
22+
QTableWidgetItem,
2123
QTextEdit,
2224
QTreeWidgetItem,
2325
QWidget,
@@ -48,50 +50,6 @@
4850
FormClass, _ = uic.loadUiType(ui_path)
4951

5052

51-
class LifecycleTableModel(QStandardItemModel):
52-
def __init__(self, status_options, parent=None):
53-
super().__init__(parent)
54-
self.status_options = status_options
55-
56-
def flags(self, index):
57-
if index.column() == 0: # "Elinkaaren tila" - editable combo box
58-
return Qt.ItemIsSelectable | Qt.ItemIsEnabled
59-
60-
if index.column() in (1, 2): # Dates
61-
return Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable
62-
return super().flags(index)
63-
64-
65-
class LifecycleDelegate(QStyledItemDelegate):
66-
def create_editor(self, parent, option, index):
67-
if index.column() == 0: # Status column
68-
lifecycle_combo_box = CodeComboBox(parent)
69-
lifecycle_combo_box.populate_from_code_layer(LifeCycleStatusLayer)
70-
return lifecycle_combo_box
71-
if index.column() in (1, 2): # Dates columns
72-
date_edit = QDateEdit(parent)
73-
date_edit.setDisplayFormat("yyyy-MM-dd")
74-
date_edit.setCalendarPopup(True)
75-
return date_edit
76-
return super().createEditor(parent, option, index)
77-
78-
def set_editor_data(self, editor, index):
79-
if isinstance(editor, CodeComboBox) and index.column() == 0:
80-
value = index.data(Qt.EditRole)
81-
if value is not None:
82-
editor.set_value(value)
83-
elif isinstance(editor, QDateEdit) and index.column() in (1, 2):
84-
value = index.data(Qt.EditRole)
85-
if value:
86-
editor.setDate(QDate.fromString(value, "yyyy-MM-dd"))
87-
88-
def set_model_data(self, editor, model, index):
89-
if isinstance(editor, CodeComboBox) and index.column() == 0:
90-
model.setData(index, editor.value(), Qt.EditRole)
91-
if isinstance(editor, QDateEdit) and index.column() in (1, 2):
92-
model.setData(index, editor.date().toString("yyyy-MM-dd"), Qt.EditRole)
93-
94-
9553
class PlanAttributeForm(QDialog, FormClass): # type: ignore
9654
permanent_identifier_line_edit: QLineEdit
9755
name_line_edit: QLineEdit
@@ -114,7 +72,7 @@ class PlanAttributeForm(QDialog, FormClass): # type: ignore
11472

11573
lifecycle_table: QTableWidget
11674
add_lifecycle: QPushButton
117-
delete_lifecycle: QPushButton
75+
# delete_lifecycle: QPushButton
11876

11977
button_box: QDialogButtonBox
12078

@@ -124,6 +82,7 @@ def __init__(self, plan: Plan, _regulation_group_libraries: list[RegulationGroup
12482
self.setupUi(self)
12583

12684
self.plan = plan
85+
self.lifecycle_models = plan.lifecycles
12786

12887
self.plan_type_combo_box.populate_from_code_layer(PlanTypeLayer)
12988
self.lifecycle_status_combo_box.populate_from_code_layer(LifeCycleStatusLayer)
@@ -173,12 +132,22 @@ def __init__(self, plan: Plan, _regulation_group_libraries: list[RegulationGroup
173132
self.add_document_btn.setIcon(QgsApplication.getThemeIcon("mActionAdd.svg"))
174133

175134
# Lifecycle table setup
176-
self.lifecycle_table.setColumnCount(3) # Three columns: Status, Start Date, End Date
177-
self.lifecycle_table.setHorizontalHeaderLabels(["Elinkaaren tila", "Alkupvm", "Loppupvm"])
178-
self.lifecycle_table.setRowCount(0) # No rows initially
135+
self.lifecycle_table.setColumnCount(4)
136+
self.lifecycle_table.setHorizontalHeaderLabels(["Elinkaaren tila", "Alkupvm", "Loppupvm", "id"])
137+
# self.lifecycle_table.setColumnHidden(3, True)
138+
self.lifecycle_table.setRowCount(0)
139+
140+
header = self.lifecycle_table.horizontalHeader()
141+
header.setSectionResizeMode(0, QHeaderView.Stretch)
142+
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
143+
header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
144+
145+
self.populate_lifecycle_table()
146+
# for lifecycle in plan.lifecycles:
147+
# self.add_lifecycle_row(lifecycle)
179148

180149
self.add_lifecycle_button.clicked.connect(self.add_lifecycle_row)
181-
self.delete_lifecycle_button.clicked.connect(self.delete_lifecycle_row)
150+
# self.delete_lifecycle_button.clicked.connect(self.delete_lifecycle_row)
182151

183152
self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
184153
self.button_box.accepted.connect(self._on_ok_clicked)
@@ -188,7 +157,6 @@ def __init__(self, plan: Plan, _regulation_group_libraries: list[RegulationGroup
188157
def _check_required_fields(self) -> None:
189158
ok_button = self.button_box.button(QDialogButtonBox.Ok)
190159

191-
# Check if all required fields are filled and lifecycle table has at least one valid row
192160
has_valid_lifecycle_row = False
193161
for row in range(self.lifecycle_table.rowCount()):
194162
status_item = self.lifecycle_table.cellWidget(row, 0)
@@ -198,7 +166,7 @@ def _check_required_fields(self) -> None:
198166
if (
199167
status_item
200168
and status_item.value() is not None
201-
and start_date_item
169+
# and start_date_item
202170
and start_date_item.date()
203171
and (end_date_item and end_date_item.date() or True)
204172
):
@@ -279,56 +247,107 @@ def delete_document(self, document_widget: DocumentWidget):
279247

280248
# ---
281249

250+
def populate_lifecycle_table(self):
251+
# kutsu add_lifecycle_row
252+
self.lifecycle_table.setRowCount(len(self.lifecycle_models))
253+
254+
for row, lifecycle in enumerate(self.lifecycle_models):
255+
# Populate the status combobox
256+
status_combobox = CodeComboBox(self)
257+
status_combobox.populate_from_code_layer(LifeCycleStatusLayer)
258+
status_combobox.set_value(lifecycle.status_id)
259+
self.lifecycle_table.setCellWidget(row, 0, status_combobox)
260+
261+
# Populate the start date edit field
262+
start_date_edit = QDateEdit(self)
263+
start_date_edit.setDisplayFormat("yyyy-MM-dd")
264+
start_date_edit.setCalendarPopup(True)
265+
start_date_edit.setDate(lifecycle.starting_at.date())
266+
self.lifecycle_table.setCellWidget(row, 1, start_date_edit)
267+
268+
# Populate the end date edit field
269+
end_date_edit = QDateEdit(self)
270+
end_date_edit.setDisplayFormat("yyyy-MM-dd")
271+
end_date_edit.setCalendarPopup(True)
272+
if lifecycle.ending_at:
273+
end_date_edit.setDate(lifecycle.ending_at.date())
274+
self.lifecycle_table.setCellWidget(row, 2, end_date_edit)
275+
276+
# Populate the ID column
277+
id_item = QTableWidgetItem(str(lifecycle.id_) if lifecycle.id_ else "")
278+
id_item.setData(Qt.UserRole, lifecycle.id_)
279+
self.lifecycle_table.setItem(row, 3, id_item)
280+
282281
def add_lifecycle_row(self):
283282
row_position = self.lifecycle_table.rowCount()
284283
self.lifecycle_table.insertRow(row_position)
285284

286-
status = CodeComboBox(self)
285+
status = CodeComboBox()
287286
status.populate_from_code_layer(LifeCycleStatusLayer)
288287
self.lifecycle_table.setCellWidget(row_position, 0, status)
289288

290-
start_date_edit = QDateEdit(self)
289+
start_date_edit = QgsDateTimeEdit()
291290
start_date_edit.setDisplayFormat("yyyy-MM-dd")
292291
start_date_edit.setCalendarPopup(True)
293292
self.lifecycle_table.setCellWidget(row_position, 1, start_date_edit)
294293

295-
end_date_edit = QDateEdit(self)
294+
end_date_edit = QgsDateTimeEdit()
296295
end_date_edit.setDisplayFormat("yyyy-MM-dd")
297296
end_date_edit.setCalendarPopup(True)
297+
end_date_edit.clear()
298298
self.lifecycle_table.setCellWidget(row_position, 2, end_date_edit)
299299

300-
self.lifecycle_table.resizeRowsToContents()
301-
self.lifecycle_table.resizeColumnsToContents()
302-
303-
def delete_lifecycle_row(self):
304-
selected_rows = self.lifecycle_table.selectionModel().selectedRows()
300+
""" def add_lifecycle_row(self, lifecycle: LifeCycle | None):
301+
# Add a new row at the end of the table
302+
row_position = self.lifecycle_table.rowCount()
303+
self.lifecycle_table.insertRow(row_position)
305304
306-
if selected_rows:
307-
row_position = selected_rows[0].row()
308-
self.lifecycle_table.removeRow(row_position)
309-
self._check_required_fields()
305+
# Status combobox
306+
status_combobox = CodeComboBox()
307+
status_combobox.populate_from_code_layer(LifeCycleStatusLayer)
308+
self.lifecycle_table.setCellWidget(row_position, 0, status_combobox)
310309
311-
def save_lifecycle(self):
312-
for row in range(self.lifecycle_table.rowCount()):
313-
status = self.lifecycle_table.cellWidget(row, 0)
314-
start_date_item = self.lifecycle_table.cellWidget(row, 1)
315-
end_date_item = self.lifecycle_table.cellWidget(row, 2)
310+
# Start date field
311+
start_date_edit = QgsDateTimeEdit()
312+
start_date_edit.setDisplayFormat("yyyy-MM-dd")
313+
start_date_edit.setCalendarPopup(True)
314+
self.lifecycle_table.setCellWidget(row_position, 1, start_date_edit)
316315
317-
if status and start_date_item:
318-
status = status.value() if status.value() is not None else ""
319-
start_date = start_date_item.date().toString("yyyy-MM-dd") if start_date_item.date() else ""
320-
end_date = end_date_item.date().toString("yyyy-MM-dd") if end_date_item.date() else None
316+
# End date field
317+
end_date_edit = QgsDateTimeEdit()
318+
end_date_edit.setDisplayFormat("yyyy-MM-dd")
319+
end_date_edit.setCalendarPopup(True)
320+
self.lifecycle_table.setCellWidget(row_position, 2, end_date_edit)
321321
322-
lifecycle_model_item = QStandardItem(status)
323-
lifecycle_model_item.setData(status.value(), Qt.UserRole + 1)
324-
start_date_model_item = QStandardItem(start_date)
325-
end_date_model_item = QStandardItem(end_date if end_date else "")
322+
# ID field
323+
id_item = QTableWidgetItem()
324+
# If lifecycle exists and has an ID, set it
325+
if lifecycle and lifecycle.id_:
326+
id_item.setData(Qt.UserRole, lifecycle.id_)
327+
id_item.setText(str(lifecycle.id_))
328+
self.lifecycle_table.setItem(row_position, 3, id_item)
329+
330+
# If lifecycle is provided, populate the fields
331+
if lifecycle:
332+
# For existing lifecycle, populate its data
333+
status_combobox.set_value(lifecycle.status_id)
334+
if lifecycle.starting_at:
335+
start_date_edit.setDate(lifecycle.starting_at.date())
336+
if lifecycle.ending_at:
337+
end_date_edit.setDate(lifecycle.ending_at.date())
338+
else:
339+
# For a new lifecycle, leave the fields empty
340+
status_combobox.set_value(None) # Do not set a default value
341+
start_date_edit.clear() # No date set initially
342+
end_date_edit.clear() # No date set initially """
326343

327-
self.lifecycle_table.model().appendRow(
328-
[lifecycle_model_item, start_date_model_item, end_date_model_item]
329-
)
344+
# def delete_lifecycle_row(self):
345+
# selected_rows = self.lifecycle_table.selectionModel().selectedRows()
330346

331-
self._check_required_fields()
347+
# if selected_rows:
348+
# row_position = selected_rows[0].row()
349+
# self.lifecycle_table.removeRow(row_position)
350+
# self._check_required_fields()
332351

333352
def into_lifecycle_model(self) -> list[LifeCycle]:
334353
lifecycles = []
@@ -338,13 +357,27 @@ def into_lifecycle_model(self) -> list[LifeCycle]:
338357
status_item = self.lifecycle_table.cellWidget(row, 0)
339358
start_date_item = self.lifecycle_table.cellWidget(row, 1)
340359
end_date_item = self.lifecycle_table.cellWidget(row, 2)
360+
id_item = self.lifecycle_table.item(row, 3)
341361

362+
# Check if status_item and start_date_item exist, then create the LifeCycle
342363
if status_item and start_date_item:
343364
status_id = status_item.value()
344365
start_date = start_date_item.date().toString("yyyy-MM-dd") if start_date_item.date() else ""
345366
end_date = end_date_item.date().toString("yyyy-MM-dd") if end_date_item.date() else None
346367

347-
lifecycles.append(LifeCycle(status_id=status_id, starting_at=start_date, ending_at=end_date))
368+
lifecycle_id = None
369+
if id_item and id_item.text().strip(): # Check if the ID in the 4th column is not empty
370+
lifecycle_id = id_item.data(Qt.UserRole)
371+
372+
# Create the LifeCycle model and add it to the list
373+
lifecycles.append(
374+
LifeCycle(
375+
status_id=status_id,
376+
starting_at=start_date,
377+
ending_at=end_date,
378+
id_=lifecycle_id, # Set the ID only if not None
379+
)
380+
)
348381

349382
return lifecycles
350383

0 commit comments

Comments
 (0)