Pamhyr2/src/View/Geometry/GeometryWindow.py

471 lines
16 KiB
Python

# -*- coding: utf-8 -*-
import os
import pathlib
import sys
import csv
import time
from tools import timer
from PyQt5 import QtWidgets
from PyQt5.QtGui import (
QKeySequence,
)
from PyQt5.QtCore import (
QModelIndex, Qt, QSettings, pyqtSlot,
QItemSelectionModel, QCoreApplication, QSize
)
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QFileDialog, QCheckBox,
QUndoStack, QShortcut,
)
from View.Geometry.PlotXY import PlotXY
from View.Geometry.PlotKPC import PlotKPC
from View.Geometry.PlotAC import PlotAC
from View.Geometry.mainwindow_ui_reach import Ui_MainWindow
from View.Geometry import qtableview_reach
from View.Geometry import window_profileXYZ
from View.ASubWindow import WindowToolKit
_translate = QCoreApplication.translate
class GeometryWindow(QMainWindow, WindowToolKit):
def __init__(self, model=None, parent=None):
self.parent = parent
super(GeometryWindow, self).__init__(parent=parent)
self._model = model
self._reach = model.river.current_reach().reach
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.tableView = self.ui.tableView
self.tableView_header = self.ui.tableView_header
self._tablemodel = None
self.setup_window()
self.setup_undo()
self.setup_model()
self.setup_plots()
self.setup_connections()
self.changed_slider_value()
def setup_window(self):
self.setWindowTitle(f"{self.ui.mainwindow_title} - {self._reach.name}")
def setup_undo(self):
self._undo_stack = QUndoStack()
self.undo_sc = QShortcut(QKeySequence.Undo, self)
self.redo_sc = QShortcut(QKeySequence.Redo, self)
def setup_model(self):
self._tablemodel = qtableview_reach.PandasModelEditable(
headers = self.ui.tableView_header,
reach = self._reach,
undo = self._undo_stack
)
self.tableView.setModel(self._tablemodel)
self.tableView.setItemDelegate(qtableview_reach.Delegate())
def setup_plots(self):
if self._reach.number_profiles != 0:
self.plot_xy()
self.plot_kpc()
self.plot_ac()
def setup_connections(self):
self.ui.btn_open.clicked.connect(self.open_file_dialog)
self.ui.btn_sort_asc.clicked.connect(self.sort_ascending)
self.ui.btn_sort_desc.clicked.connect(self.sort_descending)
self.ui.btn_move_up.clicked.connect(self.move_row_up)
self.ui.btn_move_down.clicked.connect(self.move_row_down)
self.ui.btn_end_editing.clicked.connect(self.handleSave)
self.ui.btn_add.clicked.connect(self.insert_row)
self.ui.btn_delete.clicked.connect(self.delete_row)
self.ui.btn_edit.clicked.connect(self.edit_profile)
self.ui.verticalSlider.valueChanged.connect(self.changed_slider_value)
# self.tableView.selectionModel().selectionChanged.connect(self.changed_slider_value_2)
self.ui.btn_slider_up.clicked.connect(self.decrement_value_slider)
self.ui.btn_slider_down.clicked.connect(self.increment_value_slider)
self.ui.btn_move_up.clicked.connect(self.changed_profile_slot)
self.undo_sc.activated.connect(self.undo)
self.redo_sc.activated.connect(self.redo)
# Profile selection when line change in table
self.tableView.selectionModel()\
.selectionChanged\
.connect(self.select_current_profile)
# Update plot when profile data change
# self._tablemodel.dataChanged.connect(self.update_plot_xy)
# self._tablemodel.dataChanged.connect(self.update_plot_kpc)
# self.tableView.selectionModel()\
# .selectionChanged\
# .connect(self.update_plot_xy)
# self.tableView.selectionModel()\
# .selectionChanged\
# .connect(self.update_plot_kpc)
def open_file_dialog(self):
options = QFileDialog.Options()
DEFAULT_DIRECTORY = os.getenv("HOME")
settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', )
current_dir = settings.value('current_directory', DEFAULT_DIRECTORY, type=str)
options |= QFileDialog.DontUseNativeDialog
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self,
_translate("MainWindow_reach", "Ouvrir un fichier"),
current_dir,
_translate("MainWindow_reach", "Fichiers .ST (*.ST)") +
";; " +
_translate("MainWindow_reach", "Fichiers textes (*.txt)") +
";; " +
_translate("MainWindow_reach", "Tous les fichiers (*)"),
options=options
)
current_dir = os.path.split(filename)[0] or DEFAULT_DIRECTORY
if filename != "":
size = os.stat(filename).st_size
self._reach.import_geometry(filename)
self._tablemodel.layoutChanged.emit()
self.update_profile_windows()
self.plot_xy()
self.plot_kpc()
self.plot_ac()
def messagebox_profile_editing(self):
msg_box = QtWidgets.QMessageBox()
msg_box.setIcon(QtWidgets.QMessageBox.Information)
msg_box.setWindowTitle(_translate("MainWindow_reach",
"Édition des profils sélectionnés"))
msg_box.setText(_translate("MainWindow_reach",
"Vous avez sélectionné plus de 5 profils."
" \nSeuls les 5 premiers seront édités."))
msg_box.setStandardButtons(QtWidgets.QMessageBox.Ok)
return_value = msg_box.exec()
if return_value == QtWidgets.QMessageBox.Ok:
print('OK clicked')
def edit_profile(self):
list_selected_row = list(
set([index.row() for index in self.tableView.selectedIndexes()])
)
self.tableView.model().blockSignals(True)
if len(list_selected_row) > 5:
self.messagebox_profile_editing()
for selected_row in list_selected_row[:5]:
selected_row = int(selected_row)
profile_identifier = self._reach.get_profile_selected_identifier(selected_row)
kp = self._reach.profile(selected_row).kp
profile_name = self._reach.get_profile_name(selected_row)
if len(self.list_second_window) == 0:
self.second_window = window_profileXYZ.View(
selected_row + 1,
self._reach.get_profile_via_identifier(profile_identifier),
kp=kp, profile_name="", parent=self
)
self.second_window.window_title(
kp=kp,
profile_name=profile_name,
profile_selected_num=selected_row
)
self.second_window.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
self.list_second_window.append(self.second_window)
self.second_window.show()
self.list_row.append(profile_identifier)
else:
if profile_identifier in self.list_row:
self.list_second_window[self.list_row.index(profile_identifier)]\
.window_title(
kp=kp, profile_name=profile_name,
profile_selected_num=selected_row
)
self.list_second_window[
self.list_row.index(profile_identifier)
].setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
self.list_second_window[
self.list_row.index(profile_identifier)
].show()
else:
second_window1 = window_profileXYZ.View(
selected_row + 1,
self._reach.get_profile_via_identifier(profile_identifier),
kp=kp, profile_name="", parent=self
)
second_window1.window_title(
kp=kp, profile_name=profile_name,
profile_selected_num=selected_row
)
second_window1.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
second_window1.show()
self.list_row.append(profile_identifier)
self.list_second_window.append(second_window1)
widgetList = QApplication.topLevelWidgets()
numWindows = len(widgetList)
self.tableView.model().blockSignals(False)
def wind_profile_changed(self):
self.second_window\
.datachanged_signal[bool]\
.connect(self.changed_profile_slot)
pyqtSlot(bool)
def changed_profile_slot(self, status):
self.update_view1 = status
def update_profile_windows(self):
self.list_second_window = []
self.list_row = []
def plot_xy(self):
self.tableView.model().blockSignals(True)
self._plot_xy = PlotXY(
canvas = self.ui.canvas_1,
data = self._reach,
toolbar = self.ui.toolbar_1
)
self._plot_xy.draw()
self.tableView.model().blockSignals(False)
def update_plot_xy(self):
self.tableView.model().blockSignals(True)
self._plot_xy.update()
self.tableView.model().blockSignals(False)
def plot_kpc(self):
self.tableView.model().blockSignals(True)
self._plot_kpc = PlotKPC(
canvas = self.ui.canvas_2,
data = self._reach,
toolbar = self.ui.toolbar_2
)
self._plot_kpc.draw()
self.tableView.model().blockSignals(False)
def update_plot_kpc(self):
self.tableView.model().blockSignals(True)
self._plot_kpc.update()
self.tableView.model().blockSignals(False)
def plot_ac(self):
self.tableView.model().blockSignals(True)
self._plot_ac = PlotAC(
canvas = self.ui.canvas_3,
data = self._reach,
toolbar = self.ui.toolbar_3,
plot_xy = self._plot_xy
)
self._plot_ac.draw()
self.tableView.model().blockSignals(False)
def update_plot_ac(self, ind: int):
self.tableView.model().blockSignals(True)
self._plot_ac.update(ind=ind)
self.tableView.model().blockSignals(False)
def get_station(self, ind: int):
return self._reach.profile(ind).get_station()
def get_elevation(self, ind: int):
return self._reach.profile(ind).z()
def select_plot_xy(self, ind: int):
self.tableView.model().blockSignals(True)
self._plot_xy.update(ind=ind)
self.tableView.model().blockSignals(False)
def select_plot_kpc(self, ind: int):
self.tableView.model().blockSignals(True)
self._plot_kpc.update(ind=ind)
self.tableView.model().blockSignals(False)
def select_plot_ac(self, ind: int):
self.tableView.model().blockSignals(True)
self._plot_ac.update(ind=ind)
self.tableView.model().blockSignals(False)
def select_row_profile_slider(self, ind: int = 0):
if self.tableView is not None:
selectionModel = self.tableView.selectionModel()
index = self.tableView.model().index(ind, 0)
selectionModel.select(
index,
QItemSelectionModel.Rows |
QItemSelectionModel.ClearAndSelect |
QItemSelectionModel.Select
)
self.tableView.scrollTo(index)
def select_current_profile(self):
self.tableView.model().blockSignals(True)
if len(self.tableView.selectedIndexes()) > 0:
row = self.index_selected_row()
self.ui.verticalSlider.setValue(row)
self.select_plot_xy(row)
self.select_plot_kpc(row)
self.select_plot_ac(row)
self.tableView.model().blockSignals(False)
def changed_slider_value(self):
self.tableView.model().blockSignals(True)
if self._tablemodel.rowCount() != 0:
self.ui.verticalSlider.setMaximum(self._tablemodel.rowCount() - 1)
slider_value = self.ui.verticalSlider.value()
kp = self._reach.profile(slider_value).kp
self.ui.vertical_slider_label.setText(
_translate("MainWindow_reach", "Kp : ") +
f"{kp}" + "\n" +
_translate("MainWindow_reach",
"Profil N° : ") +
f"{slider_value + 1}"
)
self.select_plot_xy(slider_value)
self.select_plot_kpc(slider_value)
self.select_row_profile_slider(slider_value)
self.tableView.model().blockSignals(False)
def increment_value_slider(self):
if 0 <= self.ui.verticalSlider.value() < self._tablemodel.rowCount() - 1:
self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() + 1)
def decrement_value_slider(self):
if 0 < self.ui.verticalSlider.value() < self._tablemodel.rowCount():
self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() - 1)
def insert_row(self):
if len(self.tableView.selectedIndexes()) == 0:
self._tablemodel.insert_row(self._tablemodel.rowCount())
else:
row = self.index_selected_row()
self._tablemodel.insert_row(row + 1)
def delete_row(self):
rows = list(set(
[index.row() for index in self.tableView.selectedIndexes()]
))
if len(rows) > 0:
self._tablemodel.remove_row(rows[0])
self.update_plot_xy()
self.select_current_profile()
self.plot_kpc()
self.changed_slider_value()
def index_selected_row(self):
return self.tableView\
.selectionModel()\
.selectedRows()[0]\
.row()
def sort_ascending(self):
self._tablemodel.sort_profiles(True)
self.select_current_profile()
self.changed_slider_value()
def sort_descending(self):
self._tablemodel.sort_profiles(False)
self.select_current_profile()
self.changed_slider_value()
def move_row_down(self):
row = self.index_selected_row()
self._tablemodel.move_row_down(row)
self.select_current_profile()
def move_row_up(self):
row = self.index_selected_row()
self._tablemodel.move_row_up(row)
self.select_current_profile()
def undo(self):
self._tablemodel.undo()
self.select_current_profile()
self.update_plot_xy()
self.update_plot_kpc()
def redo(self):
self._tablemodel.redo()
self.select_current_profile()
self.update_plot_xy()
self.update_plot_kpc()
def handleSave(self):
options = QFileDialog.Options()
DEFAULT_DIRECTORY = '/home/'
settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', )
current_dir = settings.value('current_directory', DEFAULT_DIRECTORY, type=str)
options |= QFileDialog.DontUseNativeDialog
filename, filters = QFileDialog.getSaveFileName(
self,
filter=_translate("MainWindow_reach",
"Files .ST(*.ST or *.st)")
+ ";; " +
_translate("MainWindow_reach", "All files "
"(*)"),
options=options
)
current_dir = os.path.split(filename)[0] or DEFAULT_DIRECTORY
if filename != '':
self._tablemodel.export_reach(filename)
def handleOpen(self):
filename, filterName = QFileDialog.getOpenFileName(self)
if filename != '':
with open(filename, 'r') as f:
reader = csv.reader(f, delimiter='\t')
header = next(reader)
buf = []
for row in reader:
row[0] = QCheckBox("-")
buf.append(row)
self._tablemodel = None
self._tablemodel = qtableview_reach.PandasModelEditable(buf)
self.tableView.setModel(self._tablemodel)
filename = ''