Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 941cd27

Browse files
committedJan 28, 2025·
Converted lifecycle list view to a table.
1 parent 2226ff4 commit 941cd27

File tree

3 files changed

+210
-131
lines changed

3 files changed

+210
-131
lines changed
 

‎arho_feature_template/core/plan_manager.py

+1-14
Original file line numberDiff line numberDiff line change
@@ -463,24 +463,11 @@ def save_plan(plan: Plan) -> QgsFeature:
463463
regulation_group_feature = save_regulation_group(regulation_group, plan_id)
464464
save_regulation_group_association(regulation_group_feature["id"], PlanLayer.name, plan_id)
465465

466-
# loop lifecycles and save
466+
# Save lifecycles
467467
for lifecycle in plan.lifecycles:
468468
lifecycle.plan_id = feature["id"]
469469
save_lifecycle(lifecycle)
470470

471-
# Save plan lifecycles
472-
# if hasattr(plan, "lifecycle"):
473-
# print("Has attribute lifecycle!")
474-
# if plan.lifecycle:
475-
# print("Plan has a lifecycle!")
476-
# for lifecycle in plan.lifecycle:
477-
# print(f"Lifecycle found: {lifecycle}!")
478-
# save_lifecycle(lifecycle)
479-
# else:
480-
# print("Plan doesnt have any lifecycles!")
481-
# else:
482-
# print("No attribute lifecycle!")
483-
484471
return feature
485472

486473

‎arho_feature_template/gui/dialogs/plan_attribute_form.py

+139-46
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,26 @@
44
from typing import TYPE_CHECKING
55

66
from qgis.PyQt import uic
7-
from qgis.PyQt.QtCore import Qt
7+
from qgis.PyQt.QtCore import QDate, Qt
88
from qgis.PyQt.QtGui import QStandardItem, QStandardItemModel
99
from qgis.PyQt.QtWidgets import (
1010
QComboBox,
1111
QDateEdit,
1212
QDialog,
1313
QDialogButtonBox,
1414
QLineEdit,
15-
QListView,
1615
QPushButton,
1716
QSizePolicy,
1817
QSpacerItem,
18+
QStyledItemDelegate,
19+
QTableWidget,
1920
QTextEdit,
2021
QTreeWidgetItem,
22+
QWidget,
2123
)
2224

2325
from arho_feature_template.core.models import LifeCycle, Plan, RegulationGroup, RegulationGroupLibrary
26+
from arho_feature_template.gui.components.code_combobox import CodeComboBox
2427
from arho_feature_template.gui.components.plan_regulation_group_widget import RegulationGroupWidget
2528
from arho_feature_template.gui.components.tree_with_search_widget import TreeWithSearchWidget
2629
from arho_feature_template.project.layers.code_layers import (
@@ -32,19 +35,63 @@
3235
if TYPE_CHECKING:
3336
from qgis.PyQt.QtWidgets import QComboBox, QLineEdit, QTextEdit, QVBoxLayout, QWidget
3437

35-
from arho_feature_template.gui.components.code_combobox import CodeComboBox, HierarchicalCodeComboBox
38+
from arho_feature_template.gui.components.code_combobox import HierarchicalCodeComboBox
3639

3740
ui_path = resources.files(__package__) / "plan_attribute_form.ui"
3841
FormClass, _ = uic.loadUiType(ui_path)
3942

4043

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+
4188
class PlanAttributeForm(QDialog, FormClass): # type: ignore
4289
permanent_identifier_line_edit: QLineEdit
4390
name_line_edit: QLineEdit
4491
organisation_combo_box: CodeComboBox
4592
description_text_edit: QTextEdit
4693
plan_type_combo_box: HierarchicalCodeComboBox
47-
# lifecycle_status_combo_box: CodeComboBox
94+
lifecycle_status_combo_box: CodeComboBox
4895
record_number_line_edit: QLineEdit
4996
producers_plan_identifier_line_edit: QLineEdit
5097
matter_management_identifier_line_edit: QLineEdit
@@ -53,11 +100,9 @@ class PlanAttributeForm(QDialog, FormClass): # type: ignore
53100
plan_regulation_group_libraries_combobox: QComboBox
54101
regulation_groups_tree_layout: QVBoxLayout
55102

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
61106

62107
button_box: QDialogButtonBox
63108

@@ -105,9 +150,13 @@ def __init__(self, plan: Plan, regulation_group_libraries: list[RegulationGroupL
105150
for regulation_group in plan.general_regulations:
106151
self.add_plan_regulation_group(regulation_group)
107152

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)
111160

112161
self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
113162
self.button_box.accepted.connect(self._on_ok_clicked)
@@ -116,12 +165,30 @@ def __init__(self, plan: Plan, regulation_group_libraries: list[RegulationGroupL
116165

117166
def _check_required_fields(self) -> None:
118167
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+
119186
if (
120187
self.name_line_edit.text() != ""
121188
and self.plan_type_combo_box.value() is not None
122189
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
125192
):
126193
ok_button.setEnabled(True)
127194
else:
@@ -168,45 +235,72 @@ def init_plan_regulation_group_library(self, library: RegulationGroupLibrary):
168235

169236
# ---
170237

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)
176245

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)
180250

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+
)
185286

186-
# Optionally, check required fields again
187287
self._check_required_fields()
188288

189289
def into_lifecycle_model(self) -> list[LifeCycle]:
190290
lifecycles = []
191291

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))
210304

211305
return lifecycles
212306

@@ -229,5 +323,4 @@ def into_model(self) -> Plan:
229323

230324
def _on_ok_clicked(self):
231325
self.model = self.into_model()
232-
# self.lifecycle_model = self.into_lifecycle_model()
233326
self.accept()

‎arho_feature_template/gui/dialogs/plan_attribute_form.ui

+70-71
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@
6161
<rect>
6262
<x>0</x>
6363
<y>0</y>
64-
<width>218</width>
65-
<height>306</height>
64+
<width>829</width>
65+
<height>569</height>
6666
</rect>
6767
</property>
6868
<layout class="QVBoxLayout" name="verticalLayout_4">
@@ -128,16 +128,6 @@
128128
</property>
129129
</widget>
130130
</item>
131-
<item row="3" column="0">
132-
<widget class="QLabel" name="label_5">
133-
<property name="text">
134-
<string>Organisaatio*:</string>
135-
</property>
136-
</widget>
137-
</item>
138-
<item row="3" column="1">
139-
<widget class="CodeComboBox" name="organisation_combo_box"/>
140-
</item>
141131
<item row="4" column="0">
142132
<widget class="QLabel" name="tyyppiLabel">
143133
<property name="text">
@@ -155,6 +145,33 @@
155145
</property>
156146
</widget>
157147
</item>
148+
<item row="5" column="0">
149+
<widget class="QLabel" name="elinkaarenTilaLabel">
150+
<property name="text">
151+
<string>Elinkaaren tila*:</string>
152+
</property>
153+
<property name="buddy">
154+
<cstring>lifecycle_status_combo_box</cstring>
155+
</property>
156+
</widget>
157+
</item>
158+
<item row="5" column="1">
159+
<widget class="CodeComboBox" name="lifecycle_status_combo_box">
160+
<property name="toolTip">
161+
<string>Kaavan elinkaaren tila</string>
162+
</property>
163+
</widget>
164+
</item>
165+
<item row="3" column="0">
166+
<widget class="QLabel" name="label_5">
167+
<property name="text">
168+
<string>Organisaatio*:</string>
169+
</property>
170+
</widget>
171+
</item>
172+
<item row="3" column="1">
173+
<widget class="CodeComboBox" name="organisation_combo_box"/>
174+
</item>
158175
</layout>
159176
</item>
160177
<item>
@@ -258,8 +275,8 @@
258275
<rect>
259276
<x>0</x>
260277
<y>0</y>
261-
<width>601</width>
262-
<height>493</height>
278+
<width>659</width>
279+
<height>515</height>
263280
</rect>
264281
</property>
265282
<layout class="QVBoxLayout" name="verticalLayout_6"/>
@@ -273,91 +290,72 @@
273290
</item>
274291
</layout>
275292
</widget>
276-
<widget class="QWidget" name="lifecycle_status_tab">
293+
<widget class="QWidget" name="lifecycles_tab">
277294
<attribute name="title">
278295
<string>Elinkaaret</string>
279296
</attribute>
280297
<widget class="QGroupBox" name="groupBox_2">
281298
<property name="geometry">
282299
<rect>
283-
<x>10</x>
300+
<x>0</x>
284301
<y>10</y>
285-
<width>831</width>
286-
<height>571</height>
302+
<width>801</width>
303+
<height>561</height>
287304
</rect>
288305
</property>
289306
<property name="title">
290-
<string>Elinkaarien tilat</string>
307+
<string>Elinkaaret</string>
291308
</property>
292309
<widget class="QWidget" name="verticalLayoutWidget">
293310
<property name="geometry">
294311
<rect>
295-
<x>10</x>
312+
<x>30</x>
296313
<y>30</y>
297-
<width>301</width>
298-
<height>531</height>
314+
<width>631</width>
315+
<height>461</height>
299316
</rect>
300317
</property>
301-
<layout class="QVBoxLayout" name="verticalLayout_8">
318+
<layout class="QVBoxLayout" name="verticalLayout_5">
302319
<item>
303-
<layout class="QFormLayout" name="formLayout_3">
304-
<item row="0" column="0">
305-
<widget class="QLabel" name="label_9">
306-
<property name="text">
307-
<string>Elinkaaren tila:</string>
308-
</property>
309-
</widget>
310-
</item>
311-
<item row="0" column="1">
312-
<widget class="CodeComboBox" name="lifecycle_status_combo_box">
313-
<property name="toolTip">
314-
<string>Kaavan elinkaaren tila</string>
315-
</property>
316-
</widget>
317-
</item>
318-
<item row="1" column="0">
319-
<widget class="QLabel" name="label_10">
320-
<property name="text">
321-
<string>Alkupäivämäärä:</string>
322-
</property>
323-
</widget>
324-
</item>
325-
<item row="1" column="1">
326-
<widget class="QDateEdit" name="lifecycle_start_date"/>
327-
</item>
328-
<item row="2" column="0">
329-
<widget class="QLabel" name="label_11">
330-
<property name="text">
331-
<string>Loppupäivämäärä:</string>
332-
</property>
333-
</widget>
334-
</item>
335-
<item row="2" column="1">
336-
<widget class="QDateEdit" name="lifecycle_end_date"/>
337-
</item>
338-
<item row="3" column="0">
339-
<widget class="QPushButton" name="add_lifecycle_button">
340-
<property name="text">
341-
<string>Tallenna elinkaari</string>
342-
</property>
343-
</widget>
344-
</item>
345-
</layout>
320+
<widget class="QTableWidget" name="lifecycle_table"/>
346321
</item>
347322
</layout>
348323
</widget>
349324
<widget class="QWidget" name="verticalLayoutWidget_2">
350325
<property name="geometry">
351326
<rect>
352-
<x>330</x>
327+
<x>689</x>
353328
<y>30</y>
354-
<width>491</width>
355-
<height>531</height>
329+
<width>81</width>
330+
<height>461</height>
356331
</rect>
357332
</property>
358-
<layout class="QVBoxLayout" name="verticalLayout_9">
333+
<layout class="QVBoxLayout" name="verticalLayout_8">
359334
<item>
360-
<widget class="QListView" name="lifecycle_list"/>
335+
<widget class="QPushButton" name="delete_lifecycle_button">
336+
<property name="sizePolicy">
337+
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
338+
<horstretch>0</horstretch>
339+
<verstretch>0</verstretch>
340+
</sizepolicy>
341+
</property>
342+
<property name="text">
343+
<string>Poista</string>
344+
</property>
345+
</widget>
346+
</item>
347+
<item>
348+
<widget class="QPushButton" name="add_lifecycle_button">
349+
<property name="sizePolicy">
350+
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
351+
<horstretch>0</horstretch>
352+
<verstretch>0</verstretch>
353+
</sizepolicy>
354+
</property>
355+
<property name="text">
356+
<string>Lisää</string>
357+
</property>
358+
</widget>
361359
</item>
362360
</layout>
363361
</widget>
@@ -401,6 +399,7 @@
401399
<tabstop>name_line_edit</tabstop>
402400
<tabstop>description_text_edit</tabstop>
403401
<tabstop>plan_type_combo_box</tabstop>
402+
<tabstop>lifecycle_status_combo_box</tabstop>
404403
<tabstop>mGroupBox</tabstop>
405404
<tabstop>record_number_line_edit</tabstop>
406405
<tabstop>producers_plan_identifier_line_edit</tabstop>

0 commit comments

Comments
 (0)
Please sign in to comment.