Pamhyr2, Scenario: Add Read only mode.

scenarios
Pierre-Antoine Rouby 2024-09-03 15:22:02 +02:00
parent 8f0535dc5c
commit 8afa3d1e30
9 changed files with 103 additions and 17 deletions

View File

@ -18,12 +18,20 @@
import logging import logging
from enum import Enum, auto
logger = logging.getLogger() logger = logging.getLogger()
class Status(Enum):
EDIT = auto()
READ_ONLY = auto()
class StudyStatus(object): class StudyStatus(object):
def __init__(self, scenario=None): def __init__(self, scenario=None):
super(StudyStatus, self).__init__() super(StudyStatus, self).__init__()
self._status = Status.EDIT
self._scenario = scenario self._scenario = scenario
self._saved = True self._saved = True
@ -34,6 +42,18 @@ class StudyStatus(object):
return self._scenario.id return self._scenario.id
def is_editable(self):
return self._status == Status.EDIT
def set_as_editable(self):
self._status = Status.EDIT
def is_read_only(self):
return self._status == Status.READ_ONLY
def set_as_read_only(self):
self._status = Status.READ_ONLY
@property @property
def scenario(self): def scenario(self):
return self._scenario return self._scenario

View File

@ -22,6 +22,7 @@ import logging
from datetime import datetime from datetime import datetime
from tools import timer, timestamp from tools import timer, timestamp
from functools import reduce
from Model.Tools.PamhyrDB import SQLModel from Model.Tools.PamhyrDB import SQLModel
from Model.Scenarios import Scenarios from Model.Scenarios import Scenarios
@ -94,6 +95,12 @@ class Study(SQLModel):
def river(self): def river(self):
return self._river return self._river
def is_editable(self):
return self.status.is_editable()
def is_read_only(self):
return self.status.is_read_only()
@property @property
def is_saved(self): def is_saved(self):
return self.status.is_saved() return self.status.is_saved()
@ -354,6 +361,13 @@ class Study(SQLModel):
scenario = new.scenarios[int(scenario_id[0])] scenario = new.scenarios[int(scenario_id[0])]
new.status.scenario = scenario new.status.scenario = scenario
if reduce(
lambda a, s: a or (s.parent is scenario),
new.scenarios.lst,
False
):
new.status.set_as_read_only()
data["scenario"] = scenario data["scenario"] = scenario
data["loaded_pid"] = set() data["loaded_pid"] = set()
@ -444,6 +458,7 @@ class Study(SQLModel):
if switch: if switch:
self.status.scenario = new self.status.scenario = new
self.status.set_as_editable()
return new return new
def reload_from_scenario(self, scenario): def reload_from_scenario(self, scenario):
@ -464,3 +479,12 @@ class Study(SQLModel):
sql_exec, sql_exec,
data=data data=data
) )
if reduce(
lambda a, s: a or (s.parent is scenario),
self.scenarios.lst,
False
):
self.status.set_as_read_only()
else:
self.status.set_as_editable()

View File

@ -883,6 +883,9 @@ class GraphWidget(QGraphicsView):
super(GraphWidget, self).mousePressEvent(event) super(GraphWidget, self).mousePressEvent(event)
return return
if self.graph._status.is_read_only():
return
# Move item and select edge item # Move item and select edge item
if self._state == "move": if self._state == "move":
self._selected_new_edge_src_node = None self._selected_new_edge_src_node = None
@ -932,7 +935,7 @@ class GraphWidget(QGraphicsView):
def mouseReleaseEvent(self, event): def mouseReleaseEvent(self, event):
self.clicked = False self.clicked = False
if self._only_display: if self._only_display or self.graph._status.is_read_only():
return return
if self._state == "move": if self._state == "move":
@ -951,6 +954,9 @@ class GraphWidget(QGraphicsView):
super(GraphWidget, self).mouseReleaseEvent(event) super(GraphWidget, self).mouseReleaseEvent(event)
def mouseMoveEvent(self, event): def mouseMoveEvent(self, event):
if self.graph._status.is_read_only():
return
pos = self.mapToScene(event.pos()) pos = self.mapToScene(event.pos())
# Selecte item on the fly # Selecte item on the fly
@ -1002,7 +1008,7 @@ class GraphWidget(QGraphicsView):
# Contextual menu # Contextual menu
def contextMenuEvent(self, event): def contextMenuEvent(self, event):
if self._only_display: if self._only_display or self.graph._status.is_read_only():
return return
pos = self.mapToScene(event.pos()) pos = self.mapToScene(event.pos())

View File

@ -85,11 +85,18 @@ class NetworkWindow(PamhyrWindow):
def setup_table(self): def setup_table(self):
# Nodes table # Nodes table
if self._study.is_read_only:
node_editable_headers = []
edge_editable_headers = []
else:
node_editable_headers = ["name"]
edge_editable_headers = ["name", "node1", "node2"]
table = self.find(QTableView, "tableView_nodes") table = self.find(QTableView, "tableView_nodes")
self._nodes_model = NodeTableModel( self._nodes_model = NodeTableModel(
table_view=table, table_view=table,
table_headers=self._table_headers_node, table_headers=self._table_headers_node,
editable_headers=["name"], editable_headers=node_editable_headers,
data=self._graph, data=self._graph,
undo=self._undo_stack, undo=self._undo_stack,
) )
@ -108,7 +115,7 @@ class NetworkWindow(PamhyrWindow):
self._reachs_model = EdgeTableModel( self._reachs_model = EdgeTableModel(
table_view=table, table_view=table,
table_headers=self._table_headers_edge, table_headers=self._table_headers_edge,
editable_headers=["name", "node1", "node2"], editable_headers=edge_editable_headers,
delegates={ delegates={
"node1": self.delegate_combobox, "node1": self.delegate_combobox,
"node2": self.delegate_combobox, "node2": self.delegate_combobox,
@ -132,13 +139,15 @@ class NetworkWindow(PamhyrWindow):
def setup_connections(self): def setup_connections(self):
self._nodes_model.dataChanged.connect(self.update) self._nodes_model.dataChanged.connect(self.update)
self._nodes_model.dataChanged.connect(self._graph_widget.rename_nodes)
self._reachs_model.dataChanged.connect( self._reachs_model.dataChanged.connect(
self._graph_widget.display_update) self._graph_widget.display_update)
self._reachs_model.dataChanged.connect(self.update) self._reachs_model.dataChanged.connect(self.update)
self._graph_widget.changeEdge.connect(self.update) self._graph_widget.changeEdge.connect(self.update)
self._graph_widget.changeNode.connect(self.update) self._graph_widget.changeNode.connect(self.update)
if self._study.is_editable:
self._nodes_model.dataChanged.connect(self._graph_widget.rename_nodes)
self.find(QAction, "action_toolBar_add").setCheckable(True) self.find(QAction, "action_toolBar_add").setCheckable(True)
self.find(QAction, "action_toolBar_add").triggered.connect( self.find(QAction, "action_toolBar_add").triggered.connect(
self.clicked_add self.clicked_add

View File

@ -61,7 +61,7 @@ class ScenarioItem(QGraphicsTextItem):
if self.graph.scenario_has_child(self.scenario): if self.graph.scenario_has_child(self.scenario):
tag = "" tag = ""
self.setPlainText(tag + self.scenario.name) self.setHtml(tag + self.scenario.name)
self.setDefaultTextColor(Qt.black) self.setDefaultTextColor(Qt.black)
self.setFlag(QGraphicsItem.ItemIsMovable) self.setFlag(QGraphicsItem.ItemIsMovable)
@ -412,7 +412,9 @@ class GraphWidget(QGraphicsView):
self._study.save() self._study.save()
self._study.reload_from_scenario(item.scenario) self._study.reload_from_scenario(item.scenario)
self._close_other_window()
self.exec_with_waiting_window(fn, "select_scenario") self.exec_with_waiting_window(fn, "select_scenario")
self.changeScenario.emit(self.sender()) self.changeScenario.emit(self.sender())
def new_scenario(self, pos): def new_scenario(self, pos):
@ -421,5 +423,14 @@ class GraphWidget(QGraphicsView):
scenario = self._study.new_scenario_from_current() scenario = self._study.new_scenario_from_current()
scenario.set_pos(pos.x(), pos.y()) scenario.set_pos(pos.x(), pos.y())
self._close_other_window()
self.exec_with_waiting_window(fn, "new_scenario") self.exec_with_waiting_window(fn, "new_scenario")
self.changeScenario.emit(self.sender()) self.changeScenario.emit(self.sender())
def _close_other_window(self):
self.parent\
.parent\
._close_sub_window(
exceptions=["Scenarios", "Debug REPL"]
)

View File

@ -124,5 +124,6 @@ class ScenariosWindow(PamhyrWindow):
def update(self): def update(self):
self._scenarios_model.update() self._scenarios_model.update()
self._graph_widget.display_update() self._graph_widget.display_update()
self._set_title()
self._propagate_update(key=Modules.SCENARIOS) self._propagate_update(key=Modules.SCENARIOS)

View File

@ -39,7 +39,7 @@ class ScenariosTranslate(MainTranslate):
) )
self._sub_dict["table_headers_scenarios"] = { self._sub_dict["table_headers_scenarios"] = {
"id": self._dict['id'], # "id": self._dict['id'],
"name": self._dict['name'], "name": self._dict['name'],
"description": self._dict['description'], "description": self._dict['description'],
"parent": _translate("Scenarios", "Parent"), "parent": _translate("Scenarios", "Parent"),

View File

@ -117,6 +117,9 @@ class ListedSubWindow(object):
except Exception: except Exception:
return return
def _close_sub_window(self): def _close_sub_window(self, exceptions=[]):
for _, win in self._sub_win_list: for name, win in self._sub_win_list:
if name in exceptions:
continue
win.close() win.close()

View File

@ -183,6 +183,18 @@ class PamhyrWindow(ASubMainWindow, ListedSubWindow, PamhyrWindowTools):
self._set_title() self._set_title()
self._set_icon() self._set_icon()
def _set_title(self):
title = self._title
if self._study.is_read_only():
title = "" + title
scenario = self._study.status.scenario
if scenario is not None and scenario.name != "default":
title += f" | {scenario.name}"
self.ui.setWindowTitle(title)
def closeEvent(self, event): def closeEvent(self, event):
self._close_sub_window() self._close_sub_window()
self._propagate_update(Modules.WINDOW_LIST) self._propagate_update(Modules.WINDOW_LIST)