Skip to content

Commit 6d0e295

Browse files
committed
improve LoadPlanDialog
- UI adjustments: enable dialog resizing to smaller, disable table cell editing, set table columns to resize to content (and ID column to stretch), reorder columns, change QLineEdit to QgsFilterLineEdit, change UI labeling and spacing - automatically load the plans of the first found connection - show active plan as selected if present in the selected connection - refactor code
1 parent a2cca41 commit 6d0e295

File tree

3 files changed

+160
-126
lines changed

3 files changed

+160
-126
lines changed

arho_feature_template/core/plan_manager.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -279,16 +279,16 @@ def set_active_plan(self, plan_id: str | None):
279279

280280
def load_land_use_plan(self):
281281
"""Load an existing land use plan using a dialog selection."""
282-
connections = get_existing_database_connection_names()
282+
connection_names = get_existing_database_connection_names()
283283

284-
if not connections:
284+
if not connection_names:
285285
QMessageBox.critical(None, "Error", "No database connections found.")
286286
return
287287

288288
if not handle_unsaved_changes():
289289
return
290290

291-
dialog = LoadPlanDialog(None, connections)
291+
dialog = LoadPlanDialog(None, connection_names)
292292

293293
if dialog.exec_() == QDialog.Accepted:
294294
selected_plan_id = dialog.get_selected_plan_id()
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,37 @@
1+
from __future__ import annotations
2+
13
from importlib import resources
4+
from typing import Sequence
25

36
from qgis.core import QgsProviderRegistry
47
from qgis.PyQt import uic
58
from qgis.PyQt.QtCore import QRegularExpression, QSortFilterProxyModel, Qt
69
from qgis.PyQt.QtGui import QStandardItem, QStandardItemModel
7-
from qgis.PyQt.QtWidgets import QComboBox, QDialog, QDialogButtonBox, QLineEdit, QMessageBox, QPushButton, QTableView
10+
from qgis.PyQt.QtWidgets import (
11+
QComboBox,
12+
QDialog,
13+
QDialogButtonBox,
14+
QHeaderView,
15+
QLineEdit,
16+
QMessageBox,
17+
QPushButton,
18+
QTableView,
19+
)
820

921
from arho_feature_template.core.exceptions import UnexpectedNoneError
22+
from arho_feature_template.utils.misc_utils import get_active_plan_id
1023

1124
ui_path = resources.files(__package__) / "load_plan_dialog.ui"
1225

1326
LoadPlanDialogBase, _ = uic.loadUiType(ui_path)
1427

1528

1629
class PlanFilterProxyModel(QSortFilterProxyModel):
30+
def __init__(self, model: QStandardItemModel):
31+
super().__init__()
32+
self.setSourceModel(model)
33+
self.setFilterCaseSensitivity(Qt.CaseInsensitive)
34+
1735
def filterAcceptsRow(self, source_row, source_parent): # noqa: N802
1836
model = self.sourceModel()
1937
if not model:
@@ -33,57 +51,97 @@ def filterAcceptsRow(self, source_row, source_parent): # noqa: N802
3351

3452

3553
class LoadPlanDialog(QDialog, LoadPlanDialogBase): # type: ignore
36-
connectionComboBox: QComboBox # noqa: N815
37-
push_button_load: QPushButton
38-
planTableView: QTableView # noqa: N815
39-
searchLineEdit: QLineEdit # noqa: N815
40-
buttonBox: QDialogButtonBox # noqa: N815
54+
connections_selection: QComboBox
55+
load_btn: QPushButton
56+
plan_table_view: QTableView
57+
search_line_edit: QLineEdit
58+
button_box: QDialogButtonBox
4159

42-
def __init__(self, parent, connections):
60+
ID_COLUMN = 4
61+
62+
def __init__(self, parent, connection_names: list[str]):
4363
super().__init__(parent)
4464
self.setupUi(self)
4565

4666
self._selected_plan_id = None
4767

48-
self.buttonBox.rejected.connect(self.reject)
49-
self.buttonBox.accepted.connect(self.accept)
50-
self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
68+
self.button_box.rejected.connect(self.reject)
69+
self.button_box.accepted.connect(self.accept)
70+
self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
5171

52-
self.push_button_load.clicked.connect(self.load_plans)
53-
self.searchLineEdit.textChanged.connect(self.filter_plans)
72+
self.load_btn.clicked.connect(self.load_plans)
73+
self.search_line_edit.textChanged.connect(self.filter_plans)
5474

55-
self.connectionComboBox.addItems(connections)
75+
self.connections_selection.addItems(connection_names)
5676

57-
self.planTableView.setSelectionMode(QTableView.SingleSelection)
58-
self.planTableView.setSelectionBehavior(QTableView.SelectRows)
77+
self.plan_table_view: QTableView
78+
self.plan_table_view.setSelectionMode(QTableView.SingleSelection)
79+
self.plan_table_view.setSelectionBehavior(QTableView.SelectRows)
5980

6081
self.model = QStandardItemModel()
6182
self.model.setColumnCount(5)
6283
self.model.setHorizontalHeaderLabels(
6384
[
64-
"ID",
65-
"Tuottajan kaavatunnus",
6685
"Nimi",
67-
"Kaavan elinkaaren tila",
86+
"Tuottajan kaavatunnus",
6887
"Kaavalaji",
88+
"Kaavan elinkaaren tila",
89+
"ID",
6990
]
7091
)
7192

72-
self.filterProxyModel = PlanFilterProxyModel()
73-
self.filterProxyModel.setSourceModel(self.model)
74-
self.filterProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
93+
self.filterProxyModel = PlanFilterProxyModel(self.model)
7594

76-
self.planTableView.setModel(self.filterProxyModel)
77-
self.planTableView.selectionModel().selectionChanged.connect(self.on_selection_changed)
95+
self.plan_table_view.setModel(self.filterProxyModel)
96+
self.plan_table_view.selectionModel().selectionChanged.connect(self.on_selection_changed)
97+
# self.plan_table_view.setSortingEnabled(True)
7898

79-
def load_plans(self):
99+
header = self.plan_table_view.horizontalHeader()
100+
for i in range(4):
101+
header.setSectionResizeMode(i, QHeaderView.ResizeToContents)
102+
header.setSectionResizeMode(4, QHeaderView.Stretch)
103+
104+
# Show plans for the first connections by default
105+
# NOTE: Could be changed to the previously used connection if/when plugin can remember it
106+
if len(connection_names) > 0:
107+
self.load_plans()
108+
109+
def clear_table(self):
80110
self.model.removeRows(0, self.model.rowCount())
81111

82-
selected_connection = self.connectionComboBox.currentText()
112+
def load_plans(self):
113+
self.clear_table()
114+
115+
selected_connection = self.connections_selection.currentText()
83116
if not selected_connection:
84-
self.planTableView.setModel(QStandardItemModel())
85117
return
86118

119+
active_plan_id = get_active_plan_id()
120+
row_to_select = None
121+
plans = self.get_plans_from_db(selected_connection)
122+
for i, plan in enumerate(plans):
123+
id_, producers_plan_identifier, name, lifecycle_status, plan_type = plan
124+
self.model.appendRow(
125+
[
126+
QStandardItem(name or ""),
127+
QStandardItem(producers_plan_identifier or ""),
128+
QStandardItem(plan_type or ""),
129+
QStandardItem(lifecycle_status or ""),
130+
QStandardItem(id_ or ""),
131+
]
132+
)
133+
if active_plan_id == id_:
134+
row_to_select = i
135+
136+
if row_to_select is not None:
137+
self.plan_table_view.selectRow(row_to_select)
138+
139+
def get_plans_from_db(self, selected_connection: str) -> Sequence[str]:
140+
"""
141+
Loads plans from the selected DB connection.
142+
143+
Returns plan information in the format [ID, producers_plan_identifier, name, lifecycle_status, plan_type].
144+
"""
87145
provider_registry = QgsProviderRegistry.instance()
88146
if provider_registry is None:
89147
raise UnexpectedNoneError
@@ -111,35 +169,36 @@ def load_plans(self):
111169
ON
112170
p.plan_type_id = pt.id;
113171
""")
114-
for plan in plans:
115-
self.model.appendRow([QStandardItem(column or "") for column in plan])
116-
117172
except Exception as e: # noqa: BLE001
118173
QMessageBox.critical(self, "Error", f"Failed to load plans: {e}")
119-
self.model.removeRows(0, self.model.rowCount())
174+
self.clear_table()
175+
return plans
120176

121177
def filter_plans(self):
122-
search_text = self.searchLineEdit.text()
178+
search_text = self.search_line_edit.text()
123179
if search_text:
124180
search_regex = QRegularExpression(search_text)
125181
self.filterProxyModel.setFilterRegularExpression(search_regex)
126182
else:
127183
self.filterProxyModel.setFilterRegularExpression("")
128184

129185
def on_selection_changed(self):
130-
# Enable the OK button only if a row is selected
131-
selection = self.planTableView.selectionModel().selectedRows()
132-
ok_button = self.buttonBox.button(QDialogButtonBox.Ok)
186+
"""
187+
Check active selection in `plan_table_view`.
188+
189+
Enable the OK button only if a row is selected.
190+
"""
191+
selection = self.plan_table_view.selectionModel().selectedRows()
133192
if selection:
134193
selected_row = selection[0].row()
135-
self._selected_plan_id = self.planTableView.model().index(selected_row, 0).data()
136-
ok_button.setEnabled(True)
194+
self._selected_plan_id = self.plan_table_view.model().index(selected_row, self.ID_COLUMN).data()
195+
self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
137196
else:
138197
self._selected_plan_id = None
139-
ok_button.setEnabled(False)
198+
self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
140199

141200
def get_selected_connection(self):
142-
return self.connectionComboBox.currentText()
201+
return self.connections_selection.currentText()
143202

144203
def get_selected_plan_id(self):
145204
return self._selected_plan_id

0 commit comments

Comments
 (0)