Window.py 8.08 KiB
# -*- coding: utf-8 -*-

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,
)


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()

        return self.rows[index.row()][self.headers[index.column()]]

    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.copy()
        )
        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)

        # 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.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])

    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)

        # 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()

    # 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)