Pamhyr2/src/View/Configure/Window.py

293 lines
9.4 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 logging
from copy import deepcopy
from config import Config
from View.ASubWindow import ASubWindow
from View.ListedSubWindow import ListedSubWindow
from View.Stricklers.Table import TableModel
from View.Stricklers.translate import *
from View.Stricklers.UndoCommand import *
from View.Configure.Solver.Window import ConfigureSolverWindow
from PyQt5.QtGui import (
QKeySequence,
)
from PyQt5.QtCore import (
Qt, QVariant, QAbstractTableModel,
)
from PyQt5.QtWidgets import (
QDialogButtonBox, QPushButton, QLineEdit,
QFileDialog, QTableView, QAbstractItemView,
QComboBox, QUndoStack, QShortcut, QHeaderView,
)
from Solver.Solvers import solver_long_name
logger = logging.getLogger()
class SolverTableModel(QAbstractTableModel):
def __init__(self, headers=[], rows=[]):
super(QAbstractTableModel, self).__init__()
self.rows = rows
self.headers = headers
def rowCount(self, parent):
return len(self.rows)
def columnCount(self, parent):
return len(self.headers)
def data(self, index, role):
if role != Qt.ItemDataRole.DisplayRole:
return QVariant()
ret = self.rows[index.row()][self.headers[index.column()]]
if self.headers[index.column()] == "type":
ret = solver_long_name[ret]
return ret
def headerData(self, section, orientation, role):
if (role == Qt.ItemDataRole.DisplayRole and
orientation == Qt.Orientation.Horizontal):
return self.headers[section].capitalize()
if (role == Qt.ItemDataRole.DisplayRole and
orientation == Qt.Orientation.Vertical):
return section + 1 # Start at 1
return QVariant()
def removeRow(self, index):
del self.rows[index.row()]
self.layoutChanged.emit()
def add_solver(self, solver):
self.rows.append(solver)
self.layoutChanged.emit()
def change_solver(self, solver, index):
self.rows[index.row()] = solver
self.layoutChanged.emit()
class ConfigureWindow(ASubWindow, ListedSubWindow):
def __init__(self, conf=None, title="Configure", parent=None):
super(ConfigureWindow, self).__init__(
name=title, ui="ConfigureDialog", parent=parent
)
self.ui.setWindowTitle(title)
if conf is None:
self.conf = Config()
else:
self.conf = conf
self.setup_sc()
# Solver
table = self.find(QTableView, "tableView_solver")
self.solver_table_model = SolverTableModel(
headers = ["name", "type", "description"],
rows = conf.solvers
)
table.setModel(self.solver_table_model)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
# Meshing_Tool
self.set_line_edit_text("lineEdit_meshing_tool", self.conf.meshing_tool)
# Const
self.set_line_edit_text("lineEdit_segment", str(self.conf.segment))
self.set_line_edit_text("lineEdit_max_listing", str(self.conf.max_listing))
# Backup
self.set_check_box("checkBox_backup", self.conf.backup_enable)
self.set_line_edit_text("lineEdit_backup_path", self.conf.backup_path)
self.set_time_edit("timeEdit_backup_frequence", self.conf.backup_frequence)
self.set_spin_box("spinBox_backup_max", self.conf.backup_max)
self.find(QTableView, "tableView_solver").resizeColumnsToContents()
self.connect()
# Stricklers
table = self.find(QTableView, f"tableView_stricklers")
self._stricklers = deepcopy(self.conf.stricklers)
self._stricklers_table = TableModel(
data = self._stricklers,
undo = self._undo_stack,
)
table.setModel(self._stricklers_table)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
# Editor
self.set_line_edit_text("lineEdit_editor_cmd", str(self.conf.editor))
# Language
languages = Config.languages()
for lang in languages:
self.combobox_add_item("comboBox_language", lang)
if self.conf.lang == languages[lang]:
self.set_combobox_text("comboBox_language", lang)
def setup_sc(self):
self._undo_stack = QUndoStack()
self.debug_sc = QShortcut(QKeySequence("Ctrl+G"), self)
self.undo_sc = QShortcut(QKeySequence.Undo, self)
self.redo_sc = QShortcut(QKeySequence.Redo, self)
self.copy_sc = QShortcut(QKeySequence.Copy, self)
self.paste_sc = QShortcut(QKeySequence.Paste, self)
def connect(self):
buttons = {
# Solvers
"pushButton_solver_add": self.add_solver,
"pushButton_solver_del": self.remove_solver,
"pushButton_solver_edit": self.edit_solver,
# Stricklers
"pushButton_stricklers_add": self.add_stricklers,
"pushButton_stricklers_del": self.del_stricklers,
"pushButton_stricklers_sort": self.sort_stricklers,
# Others
"pushButton_backup_path": lambda: self.file_dialog(
select_file = False,
callback = lambda f: self.set_line_edit_text(
"lineEdit_backup_path", f[0]
)
),
"pushButton_meshing_tool" : lambda: self.file_dialog(
select_file = True,
callback = lambda f: self.set_line_edit_text(
"lineEdit_meshing_tool", f[0]
)
),
}
for button in buttons:
self.find(QPushButton, button).clicked.connect(buttons[button])
self.debug_sc.activated.connect(self.set_debug)
def accept(self):
# Solvers
self.conf.solvers = self.solver_table_model.rows.copy()
# Meshing_Tool
self.conf.meshing_tool = self.get_line_edit_text("lineEdit_meshing_tool")
# Const
self.conf.segment = self.get_line_edit_text("lineEdit_segment")
self.conf.max_listing = self.get_line_edit_text("lineEdit_max_listing")
# Backup
self.conf.backup_enable = self.get_check_box("checkBox_backup")
self.conf.backup_path = self.get_line_edit_text("lineEdit_backup_path")
self.conf.backup_frequence = self.get_time_edit("timeEdit_backup_frequence")
self.conf.backup_max = self.get_spin_box("spinBox_backup_max")
# Stricklers
self.conf.stricklers = deepcopy(self._stricklers)
# Editor
self.conf.editor = self.get_line_edit_text("lineEdit_editor_cmd")
# Language
self.conf.lang = Config.languages()[self.get_combobox_text("comboBox_language")]
self.end()
def reject(self):
# Nothing todo
self.end()
def end(self):
self.conf.save()
self.close()
# Debug
def set_debug(self):
self.conf.debug = not self.conf.debug
logger.info(f"Debug mode set : {self.conf.debug}")
self.parent.setup_debug_mode()
# Solvers
def edit_solver(self):
indexes = self.find(QTableView, "tableView_solver").selectionModel().selectedRows()
for index in indexes:
self.edit_solver = ConfigureSolverWindow(
data=self.solver_table_model.rows[index.row()],
parent=self
)
if self.edit_solver.exec_():
self.solver_table_model.change_solver(self.edit_solver.data, index)
def add_solver(self):
dialog_solver = ConfigureSolverWindow(parent=self)
if dialog_solver.exec_():
self.solver_table_model.add_solver(dialog_solver.data)
def remove_solver(self):
indices = self.find(QTableView, "tableView_solver").selectionModel().selectedRows()
for index in sorted(indices):
self.solver_table_model.removeRow(index)
# Stricklers
def index_selected_rows_strikclers(self):
table = self.find(QTableView, f"tableView_stricklers")
return list(
set(
map(
lambda i: i.row(),
table.selectedIndexes()
)
)
)
def add_stricklers(self):
rows = self.index_selected_rows_strikclers()
if len(rows) == 0:
self._stricklers_table.add(0)
else:
self._stricklers_table.add(rows[0])
def del_stricklers(self):
rows = self.index_selected_rows_strikclers()
if len(rows) == 0:
return
self._stricklers_table.delete(rows)
def sort_stricklers(self):
self._stricklers_table.sort(False)