diff --git a/src/model/network/Graph.py b/src/model/network/Graph.py index e90d2b756899ef11aa57a6d3492c1b15df901747..ba49af66a16ee8729fd9bd92c65da7011861a457 100644 --- a/src/model/network/Graph.py +++ b/src/model/network/Graph.py @@ -22,6 +22,11 @@ class Node(object): return ret + def __setitem__(self, name, value): + if name == "name": + self.name = value + elif name == "id": + self.id = value class Edge(object): def __init__(self, id:str, name:str, node1:Node = None, node2:Node = None): @@ -54,6 +59,18 @@ class Edge(object): return ret + def __setitem__(self, name, value): + if name == "name": + self.name = value + elif name == "id": + self.id = value + elif name == "node1": + self.node1 = value + elif name == "node2": + self.node2 = value + elif name == "enable": + self.enable = value + def enable(self): self.enable = True @@ -77,6 +94,9 @@ class Graph(object): def nodes(self): return self._nodes.copy() + def nodes_names(self): + return list(map(lambda n: n.name, self._nodes)) + def edges(self): return self._edges.copy() @@ -100,6 +120,9 @@ class Graph(object): False ) + def node(self, node_name:str): + return list(filter(lambda n: n.name == node_name, self._nodes))[0] + def add_node(self): node = Node(self._nodes_ids, f"Node {self._nodes_ids}") self._nodes.append(node) diff --git a/src/view/NetworkWindow.py b/src/view/NetworkWindow.py index 50a05cc2337eb3931c3014cb6e91e8d44e45322c..89feb34b3631b0691be85f03193802c392a99ba8 100644 --- a/src/view/NetworkWindow.py +++ b/src/view/NetworkWindow.py @@ -4,26 +4,74 @@ from view.ASubWindow import ASubWindow from model.network.Graph import (Node, Edge, Graph) from PyQt5.QtCore import ( - Qt, QVariant, QAbstractTableModel, + Qt, QRect, QVariant, QAbstractTableModel, pyqtSlot, pyqtSignal, ) from PyQt5.QtWidgets import ( - QTableView, + QTableView, QItemDelegate, QComboBox, QLineEdit, ) +class LineEditDelegate(QItemDelegate): + on_focus_out = pyqtSignal(object) + + def __init__(self, *args, **kwargs): + super(LineEditDelegate, self).__init__(*args, **kwargs) + self.line_edit = None + + def createEditor(self, parent, option, index): + self.line_edit = QLineEdit(parent=parent) + self.line_edit.destroyed.connect(lambda: self._line_edit_left(index=index)) + return self.line_edit + + def _line_edit_left(self, index): + self.on_focus_out.emit(index) + return + +class ComboBoxDelegate(QItemDelegate): + def __init__(self, graph=None, parent=None): + super(ComboBoxDelegate, self).__init__(parent) + self.graph = graph + + def createEditor(self, parent, option, index): + self.editor = QComboBox(parent) + self.editor.addItems(self.graph.nodes_names()) + return self.editor + + def setEditorData(self, editor, index): + value = index.data(Qt.DisplayRole) + self.editor.currentTextChanged.connect(self.currentItemChanged) + + def setModelData(self, editor, model, index): + text = str(editor.currentText()) + model.setData(index, text) + editor.close() + editor.deleteLater() + + def updateEditorGeometry(self, editor, option, index): + r = QRect(option.rect) + if self.editor.windowFlags() & Qt.Popup and editor.parent() is not None: + r.setTopLeft(self.editor.parent().mapToGlobal(r.topLeft())) + editor.setGeometry(r) + + @pyqtSlot() + def currentItemChanged(self): + self.commitData.emit(self.sender()) + class TableModel(QAbstractTableModel): - def __init__(self, headers=[], rows=[]): + def __init__(self, headers=[], rows=[], graph=None): super(QAbstractTableModel, self).__init__() self.rows = rows self.headers = headers + self.graph = graph + + def flags(self, index): + return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable def rowCount(self, parent): - # How many rows are there? return len(self.rows) def columnCount(self, parent): - # How many columns? return len(self.headers) def data(self, index, role): @@ -41,6 +89,29 @@ class TableModel(QAbstractTableModel): return QVariant() + @pyqtSlot() + def setData(self, index, value, role=Qt.EditRole): + if index.isValid(): + if role == Qt.EditRole: + if (self.headers[index.column()] == "node1" or + self.headers[index.column()] == "node2"): + node = self.graph.node(value) + self.rows[index.row()][self.headers[index.column()]] = node + else: + self.rows[index.row()][self.headers[index.column()]] = value + + self.dataChanged.emit(index, index, [Qt.DisplayRole]) + self.layoutChanged.emit() + return True + + self.dataChanged.emit(index, index) + else: + return False + + def update(self): + print("update") + self.layoutChanged.emit() + class NetworkWindow(ASubWindow): def __init__(self, title="Network", parent=None): @@ -49,21 +120,46 @@ class NetworkWindow(ASubWindow): self.graph = Graph() - n1 = self.graph.add_node() - n2 = self.graph.add_node() - n3 = self.graph.add_node() + n1 = self.graph.add_node() # TODO: Delete me + n2 = self.graph.add_node() # TODO: Delete me + n3 = self.graph.add_node() # TODO: Delete me - self.nodes_table_model = TableModel( + for i in range(0,100): + self.graph.add_node() # TODO: Delete me + + # Nodes table + + self.nodes_model = TableModel( headers = ["name", "id"], - rows = self.graph.nodes() + rows = self.graph.nodes(), + graph = self.graph, ) - self.find(QTableView, "tableView_nodes").setModel(self.nodes_table_model) + self.delegate_line = LineEditDelegate(parent=self) + table = self.find(QTableView, "tableView_nodes") + table.setModel(self.nodes_model) + table.setItemDelegate(self.delegate_line) + #table.resizeColumnsToContents() - self.graph.add_edge(n1, n2) - self.graph.add_edge(n2, n3) + self.graph.add_edge(n1, n2) # TODO: Delete me + self.graph.add_edge(n2, n3) # TODO: Delete me - self.reachs_table_model = TableModel( + # Edges table + + self.reachs_model = TableModel( headers = ["name", "node1", "node2"], - rows = self.graph.edges() + rows = self.graph.edges(), + graph=self.graph, + ) + self.delegate_combobox = ComboBoxDelegate( + graph=self.graph, + parent=self, ) - self.find(QTableView, "tableView_reachs").setModel(self.reachs_table_model) + table = self.find(QTableView, "tableView_reachs") + table.setModel(self.reachs_model) + table.setItemDelegateForColumn(1, self.delegate_combobox) + table.setItemDelegateForColumn(2, self.delegate_combobox) + #table.resizeColumnsToContents() + + # Connection the two table + self.nodes_model.dataChanged.connect(self.reachs_model.update) + self.reachs_model.dataChanged.connect(self.nodes_model.update)