mirror of https://gitlab.com/pamhyr/pamhyr2
Pamhyr2, Scenario: Add Read only mode.
parent
8f0535dc5c
commit
8afa3d1e30
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
|
|
@ -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,22 +139,24 @@ 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)
|
||||||
|
|
||||||
self.find(QAction, "action_toolBar_add").setCheckable(True)
|
if self._study.is_editable:
|
||||||
self.find(QAction, "action_toolBar_add").triggered.connect(
|
self._nodes_model.dataChanged.connect(self._graph_widget.rename_nodes)
|
||||||
self.clicked_add
|
|
||||||
)
|
|
||||||
|
|
||||||
self.find(QAction, "action_toolBar_del").setCheckable(True)
|
self.find(QAction, "action_toolBar_add").setCheckable(True)
|
||||||
self.find(QAction, "action_toolBar_del").triggered.connect(
|
self.find(QAction, "action_toolBar_add").triggered.connect(
|
||||||
self.clicked_del
|
self.clicked_add
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.find(QAction, "action_toolBar_del").setCheckable(True)
|
||||||
|
self.find(QAction, "action_toolBar_del").triggered.connect(
|
||||||
|
self.clicked_del
|
||||||
|
)
|
||||||
|
|
||||||
def clicked_add(self):
|
def clicked_add(self):
|
||||||
if self.get_action_checkable("action_toolBar_add"):
|
if self.get_action_checkable("action_toolBar_add"):
|
||||||
|
|
|
||||||
|
|
@ -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"]
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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"),
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue