mirror of https://gitlab.com/pamhyr/pamhyr2
257 lines
7.3 KiB
Python
257 lines
7.3 KiB
Python
# Window.py -- Pamhyr
|
|
# Copyright (C) 2023 INRAE
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import copy
|
|
import sys
|
|
import csv
|
|
from time import time
|
|
|
|
from tools import trace, timer
|
|
|
|
from PyQt5.QtGui import (
|
|
QKeySequence,
|
|
)
|
|
from PyQt5.QtCore import (
|
|
QModelIndex, Qt, QEvent, QCoreApplication
|
|
)
|
|
from PyQt5.QtWidgets import (
|
|
QApplication, QMainWindow, QFileDialog, QCheckBox,
|
|
QUndoStack, QShortcut, QTableView, QAbstractItemView,
|
|
QHeaderView, QVBoxLayout, QAction,
|
|
)
|
|
|
|
from Model.Geometry.Reach import Reach
|
|
from Model.Geometry.ProfileXYZ import ProfileXYZ
|
|
|
|
from View.Tools.PamhyrWindow import PamhyrWindow
|
|
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
|
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
|
|
|
from View.Geometry.Profile.Plot import Plot
|
|
from View.Geometry.Profile.Table import GeometryProfileTableModel
|
|
from View.Geometry.Profile.Translate import GeometryProfileTranslate
|
|
|
|
_translate = QCoreApplication.translate
|
|
|
|
|
|
class ProfileWindow(PamhyrWindow):
|
|
_pamhyr_ui = "GeometryCrossSection"
|
|
_pamhyr_name = "Geometry cross-section"
|
|
|
|
def __init__(self, profile=None, study=None, config=None, parent=None):
|
|
self._profile = profile
|
|
|
|
trad = GeometryProfileTranslate()
|
|
name = (
|
|
trad[self._pamhyr_name] +
|
|
f" - {self._profile.name} {self._profile.kp}"
|
|
)
|
|
|
|
super(ProfileWindow, self).__init__(
|
|
title=name,
|
|
study=study,
|
|
config=config,
|
|
trad=trad,
|
|
parent=parent
|
|
)
|
|
|
|
self._hash_data.append(profile)
|
|
|
|
self.setup_table()
|
|
self.setup_plot()
|
|
self.setup_connections()
|
|
|
|
def setup_table(self):
|
|
table_headers = self._trad.get_dict("table_headers")
|
|
|
|
table = self.find(QTableView, "tableView")
|
|
self._tablemodel = GeometryProfileTableModel(
|
|
table_view=table,
|
|
table_headers=table_headers,
|
|
editable_headers=["name", "x", "y", "z"],
|
|
data=self._profile,
|
|
undo=self._undo_stack
|
|
)
|
|
table.setModel(self._tablemodel)
|
|
table.setSelectionBehavior(QAbstractItemView.SelectRows)
|
|
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
|
table.setAlternatingRowColors(True)
|
|
|
|
def setup_plot(self):
|
|
self._tablemodel.blockSignals(True)
|
|
|
|
self._canvas = MplCanvas(width=3, height=4, dpi=100)
|
|
self._canvas.setObjectName("canvas")
|
|
self._toolbar = PamhyrPlotToolbar(
|
|
self._canvas, self,
|
|
items=["home", "zoom", "save", "iso", "back/forward", "move"]
|
|
)
|
|
self._plot_layout = self.find(QVBoxLayout, "verticalLayout")
|
|
self._plot_layout.addWidget(self._toolbar)
|
|
self._plot_layout.addWidget(self._canvas)
|
|
|
|
self._plot = Plot(
|
|
canvas=self._canvas,
|
|
data=self._profile,
|
|
toolbar=self._toolbar,
|
|
table=self.find(QTableView, "tableView")
|
|
)
|
|
self._plot.draw()
|
|
|
|
self._tablemodel.blockSignals(False)
|
|
|
|
def setup_connections(self):
|
|
actions = {
|
|
"action_sort_asc": self.sort_X_ascending,
|
|
"action_sort_des": self.sort_X_descending,
|
|
"action_up": self.move_up,
|
|
"action_down": self.move_down,
|
|
"action_add": self.add,
|
|
"action_delete": self.delete,
|
|
}
|
|
|
|
for action in actions:
|
|
self.find(QAction, action)\
|
|
.triggered.connect(actions[action])
|
|
|
|
self._tablemodel.dataChanged.connect(self.update_plot)
|
|
|
|
def update_plot(self):
|
|
self._tablemodel.blockSignals(True)
|
|
|
|
# TODO: Do not rebuild all graph
|
|
self._plot.update()
|
|
|
|
self._tablemodel.blockSignals(False)
|
|
|
|
def index_selected_row(self):
|
|
table = self.find(QTableView, "tableView")
|
|
rows = table.selectionModel()\
|
|
.selectedRows()
|
|
if len(rows) == 0:
|
|
return 0
|
|
|
|
return rows[0].row()
|
|
|
|
def add(self):
|
|
table = self.find(QTableView, "tableView")
|
|
if len(table.selectedIndexes()) == 0:
|
|
self._tablemodel.insert_row(self._tablemodel.rowCount())
|
|
else:
|
|
row = self.index_selected_row()
|
|
self._tablemodel.insert_row(row + 1)
|
|
self.update_plot()
|
|
|
|
def delete(self):
|
|
table = self.find(QTableView, "tableView")
|
|
rows = sorted(
|
|
list(
|
|
set(
|
|
[index.row() for index in table.selectedIndexes()]
|
|
)
|
|
)
|
|
)
|
|
|
|
if len(rows) > 0:
|
|
self._tablemodel.remove_rows(rows)
|
|
self.update_plot()
|
|
|
|
def sort_X_ascending(self):
|
|
self._tablemodel.sort('x', order=Qt.AscendingOrder)
|
|
self.update_plot()
|
|
|
|
def sort_X_descending(self):
|
|
self._tablemodel.sort('x', order=Qt.DescendingOrder)
|
|
self.update_plot()
|
|
|
|
def sort_Y_ascending(self):
|
|
self._tablemodel.sort('y', order=Qt.AscendingOrder)
|
|
self.update_plot()
|
|
|
|
def sort_Y_descending(self):
|
|
self._tablemodel.sort('y', order=Qt.DescendingOrder)
|
|
self.update_plot()
|
|
|
|
def move_down(self):
|
|
rows = list(
|
|
set(
|
|
[index.row() for index in
|
|
self.find(QTableView, "tableView").selectedIndexes()]
|
|
)
|
|
)
|
|
|
|
for row in rows:
|
|
if row < self._tablemodel.rowCount() - 1:
|
|
self._tablemodel.move_down(row)
|
|
|
|
self.update_plot()
|
|
|
|
def move_up(self):
|
|
rows = list(
|
|
set(
|
|
[index.row() for index in
|
|
self.find(QTableView, "tableView").selectedIndexes()]
|
|
)
|
|
)
|
|
|
|
for row in rows:
|
|
if 0 < row:
|
|
self._tablemodel.move_up(row)
|
|
|
|
self.update_plot()
|
|
|
|
def _copy(self):
|
|
table = self.find(QTableView, "tableView")
|
|
rows = table.selectionModel().selectedRows()
|
|
|
|
data = []
|
|
data.append(["x", "y", "z", "name"])
|
|
|
|
for row in rows:
|
|
point = self._profile.point(row.row())
|
|
data.append(
|
|
[
|
|
point.x, point.y, point.z, point.name
|
|
]
|
|
)
|
|
|
|
self.copyTableIntoClipboard(data)
|
|
|
|
def _paste(self):
|
|
header, data = self.parseClipboardTable()
|
|
|
|
if len(data) == 0:
|
|
return
|
|
|
|
if len(header) != 0:
|
|
header.append("profile")
|
|
# for row in data:
|
|
# row.append(self._profile)
|
|
|
|
row = self.index_selected_row()
|
|
self._tablemodel.paste(row, header, data)
|
|
self.update_plot()
|
|
|
|
def _undo(self):
|
|
self._tablemodel.undo()
|
|
self.update_plot()
|
|
|
|
def _redo(self):
|
|
self._tablemodel.redo()
|
|
self.update_plot()
|