From aedb8c46fcb3511eba438b5d2e7e07e6d21f88a0 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr> Date: Tue, 26 Mar 2024 10:39:38 +0100 Subject: [PATCH] REPLines: Add REP lines into model, view and minor change. --- src/Model/REPLine/REPLine.py | 150 +++++++++++++++++++++++++++++++ src/Model/REPLine/REPLineList.py | 56 ++++++++++++ src/Model/River.py | 9 ++ src/Model/Study.py | 2 +- src/Solver/Mage.py | 11 +++ src/View/CheckList/List.py | 2 +- src/View/CheckList/Table.py | 4 +- src/View/MainWindow.py | 16 ++++ src/View/REPLines/Edit/Window.py | 71 +++++++++++++++ src/View/REPLines/List.py | 71 +++++++++++++++ src/View/REPLines/Translate.py | 35 ++++++++ src/View/REPLines/Window.py | 104 +++++++++++++++++++++ src/View/Study/Window.py | 2 +- src/View/ui/MainWindow.ui | 12 +++ src/View/ui/REPLineDialog.ui | 110 +++++++++++++++++++++++ src/View/ui/REPLineList.ui | 85 ++++++++++++++++++ 16 files changed, 735 insertions(+), 5 deletions(-) create mode 100644 src/Model/REPLine/REPLine.py create mode 100644 src/Model/REPLine/REPLineList.py create mode 100644 src/View/REPLines/Edit/Window.py create mode 100644 src/View/REPLines/List.py create mode 100644 src/View/REPLines/Translate.py create mode 100644 src/View/REPLines/Window.py create mode 100644 src/View/ui/REPLineDialog.ui create mode 100644 src/View/ui/REPLineList.ui diff --git a/src/Model/REPLine/REPLine.py b/src/Model/REPLine/REPLine.py new file mode 100644 index 00000000..aea23d8c --- /dev/null +++ b/src/Model/REPLine/REPLine.py @@ -0,0 +1,150 @@ +# REPLine.py -- Pamhyr +# Copyright (C) 2024 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 -*- + +from functools import reduce + +from tools import trace, timer + +from Model.Tools.PamhyrDB import SQLSubModel +from Model.Except import NotImplementedMethodeError + + +class REPLine(SQLSubModel): + _sub_classes = [] + _id_cnt = 0 + + def __init__(self, id: int = -1, enabled=True, + name="", line="", solvers=set(), + status=None): + super(REPLine, self).__init__() + + if id == -1: + self.id = REPLine._id_cnt + else: + self.id = id + + self._status = status + + self._enabled = enabled + self._name = f"Line{self.id}" if name == "" else name + self._line = line + self._solvers = solvers + + REPLine._id_cnt = max(id, REPLine._id_cnt+1) + + @property + def enabled(self): + return self._enabled + + @enabled.setter + def enabled(self, enabled): + self._enabled = enabled + + def is_enabled(self): + return self._enabled + + @property + def name(self): + return self._name + + @name.setter + def name(self, name): + self._name = name + + @property + def line(self): + return self._line + + @line.setter + def line(self, line): + self._line = line + + @property + def solvers(self): + return self._solvers + + @solvers.setter + def solvers(self, solvers): + self._solvers = solvers + + @classmethod + def _db_create(cls, execute): + execute(""" + CREATE TABLE rep_lines( + id INTEGER NOT NULL PRIMARY KEY, + enabled BOOLEAN NOT NULL, + name TEXT NOT NULL, + line TEXT NOT NULL, + solvers TEXT NOT NULL + ) + """) + + return cls._create_submodel(execute) + + @classmethod + def _db_update(cls, execute, version): + major, minor, release = version.strip().split(".") + if major == minor == "0": + if int(release) < 9: + cls._db_create(execute) + + return True + + @classmethod + def _db_load(cls, execute, data=None): + new = [] + + table = execute( + "SELECT id, enabled, name, line, solvers " + + "FROM rep_lines" + ) + + for row in table: + it = iter(row) + + id = next(it) + enabled = (next(it) == 1) + name = next(it) + line = next(it) + solvers = set(next(it).split(";;")) + + f = cls( + id=id, enabled=enabled, name=name, line=line, + solvers=solvers, status=data['status'] + ) + + new.append(f) + + return new + + def _db_save(self, execute, data=None): + solvers = ";;".join(self._solvers) + + sql = ( + "INSERT INTO " + + "rep_lines(id, enabled, name, line, solvers) " + + "VALUES (" + + f"{self.id}, {self._enabled}, " + + f"'{self._db_format(self._name)}', " + + f"'{self._db_format(self._line)}', " + + f"'{self._db_format(solvers)}'" + + ")" + ) + execute(sql) + + return True diff --git a/src/Model/REPLine/REPLineList.py b/src/Model/REPLine/REPLineList.py new file mode 100644 index 00000000..bbed40dc --- /dev/null +++ b/src/Model/REPLine/REPLineList.py @@ -0,0 +1,56 @@ +# REPLineList.py -- Pamhyr +# Copyright (C) 2024 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 -*- + +from tools import trace, timer + +from Model.Except import NotImplementedMethodeError +from Model.Tools.PamhyrList import PamhyrModelList +from Model.REPLine.REPLine import REPLine + + +class REPLineList(PamhyrModelList): + _sub_classes = [REPLine] + + @classmethod + def _db_load(cls, execute, data=None): + new = cls(status=data["status"]) + + new._lst = REPLine._db_load(execute, data) + + return new + + def _db_save(self, execute, data=None): + ok = True + + # Delete previous data + execute("DELETE FROM rep_lines") + + for af in self._lst: + ok &= af._db_save(execute, data) + + return ok + + @property + def lines(self): + return self.lst + + def new(self, index): + n = REPLine(status=self._status) + self.insert(index, n) + self._status.modified() + return n diff --git a/src/Model/River.py b/src/Model/River.py index 41d4e0d8..a5525841 100644 --- a/src/Model/River.py +++ b/src/Model/River.py @@ -41,6 +41,7 @@ from Model.HydraulicStructures.HydraulicStructuresList import ( HydraulicStructureList, ) from Model.AdditionalFile.AddFileList import AddFileList +from Model.REPLine.REPLineList import REPLineList from Solver.Solvers import solver_type_list @@ -226,6 +227,7 @@ class River(Graph, SQLSubModel): ReservoirList, HydraulicStructureList, AddFileList, + REPLineList, ] def __init__(self, status=None): @@ -248,6 +250,7 @@ class River(Graph, SQLSubModel): status=self._status ) self._additional_files = AddFileList(status=self._status) + self._rep_lines = REPLineList(status=self._status) @classmethod def _db_create(cls, execute): @@ -320,6 +323,7 @@ class River(Graph, SQLSubModel): new._additional_files = AddFileList._db_load( execute, data ) + new._rep_lines = REPLineList._db_load(execute, data) return new @@ -335,6 +339,7 @@ class River(Graph, SQLSubModel): objs.append(self._reservoir) objs.append(self._hydraulic_structures) objs.append(self._additional_files) + objs.append(self._rep_lines) for solver in self._parameters: objs.append(self._parameters[solver]) @@ -438,6 +443,10 @@ Last export at: @date.""" def additional_files(self): return self._additional_files + @property + def rep_lines(self): + return self._rep_lines + @property def parameters(self): return self._parameters diff --git a/src/Model/Study.py b/src/Model/Study.py index 14bb5c91..4bb347b8 100644 --- a/src/Model/Study.py +++ b/src/Model/Study.py @@ -41,7 +41,7 @@ class Study(SQLModel): def __init__(self, filename=None, init_new=True): # Metadata - self._version = "0.0.8" + self._version = "0.0.9" self.creation_date = datetime.now() self.last_modification_date = datetime.now() self.last_save_date = datetime.now() diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py index 5594e68b..1a3f829b 100644 --- a/src/Solver/Mage.py +++ b/src/Solver/Mage.py @@ -128,6 +128,15 @@ class Mage(CommandLineSolver): name = self._study.name return f"{name}.TRA" + def _export_REP_additional_lines(self, study, rep_file): + lines = filter( + lambda line: line.is_enabled(), + study.river.rep_lines.lines + ) + + for line in lines: + rep_file.write(line.line) + @timer def _export_ST(self, study, repertory, qlog, name="0"): files = [] @@ -661,6 +670,8 @@ class Mage(CommandLineSolver): if EXT in ["GRA"]: f.write(f"{EXT} {file}\n") + self._export_REP_additional_lines(study, f) + @timer def export(self, study, repertory, qlog=None): self._study = study diff --git a/src/View/CheckList/List.py b/src/View/CheckList/List.py index 3afae091..ab83eaeb 100644 --- a/src/View/CheckList/List.py +++ b/src/View/CheckList/List.py @@ -50,7 +50,7 @@ class TabListModel(PamhyrListModel): if status is STATUS.OK: color = Qt.green elif status is STATUS.WARNING: - color = Qt.yellow + color = QColor("orange") elif status is STATUS.ERROR: color = Qt.red diff --git a/src/View/CheckList/Table.py b/src/View/CheckList/Table.py index 658c3b32..fc95b901 100644 --- a/src/View/CheckList/Table.py +++ b/src/View/CheckList/Table.py @@ -57,7 +57,7 @@ class TableModel(PamhyrTableModel): if self._data[row].is_ok(): color = Qt.green elif self._data[row].is_warning(): - color = Qt.yellow + color = QColor("orange") elif self._data[row].is_error(): color = Qt.red @@ -136,7 +136,7 @@ class TabTableModel(PamhyrTableModel): if status is STATUS.OK: color = Qt.green elif status is STATUS.WARNING: - color = Qt.yellow + color = QColor("orange") elif status is STATUS.ERROR: color = Qt.red diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index 836f6d7e..4c5cf62f 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -68,6 +68,7 @@ from View.Frictions.Window import FrictionsWindow from View.SedimentLayers.Window import SedimentLayersWindow from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow from View.AdditionalFiles.Window import AddFileListWindow +from View.REPLines.Window import REPLineListWindow from View.SolverParameters.Window import SolverParametersWindow from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow from View.CheckList.Window import CheckListWindow @@ -121,6 +122,7 @@ define_model_action = [ "action_menu_edit_hydraulic_structures", "action_menu_additional_file", "action_menu_results_last", "action_open_results_from_file", "action_menu_boundary_conditions_sediment", + "action_menu_rep_additional_lines", ] action = ( @@ -254,6 +256,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): "action_menu_edit_reach_sediment_layers": self.open_reach_sediment_layers, "action_menu_additional_file": self.open_additional_files, + "action_menu_rep_additional_lines": self.open_rep_lines, "action_menu_close": self.close_model, "action_menu_results_last": self.open_last_results, "action_open_results_from_file": self.open_results_from_file, @@ -1078,6 +1081,19 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): ) self.additonal_files.show() + def open_rep_lines(self): + if self._study is not None: + if self.sub_window_exists( + REPLineListWindow, + data=[self._study, None] + ): + return + + self.rep_lines = REPLineListWindow( + study=self._study, parent=self + ) + self.rep_lines.show() + def open_solver_parameters(self): if self.sub_window_exists( SolverParametersWindow, diff --git a/src/View/REPLines/Edit/Window.py b/src/View/REPLines/Edit/Window.py new file mode 100644 index 00000000..120a0a29 --- /dev/null +++ b/src/View/REPLines/Edit/Window.py @@ -0,0 +1,71 @@ +# Window.py -- Pamhyr +# Copyright (C) 2024 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 Modules import Modules +from View.Tools.PamhyrWindow import PamhyrDialog + +from PyQt5.QtWidgets import ( + QLabel, QPlainTextEdit, QPushButton, + QCheckBox, +) + +from View.REPLines.Translate import REPLineTranslate + +logger = logging.getLogger() + + +class EditREPLineWindow(PamhyrDialog): + _pamhyr_ui = "REPLineDialog" + _pamhyr_name = "Edit Mage REP lines" + + def __init__(self, study=None, config=None, rep_line=None, + trad=None, parent=None): + + name = trad[self._pamhyr_name] + " - " + study.name + super(EditREPLineWindow, self).__init__( + title=name, + study=study, + config=config, + options=[], + parent=parent + ) + + self._rep_line = rep_line + self._hash_data.append(self._rep_line) + + self.setup_values() + + def setup_values(self): + self.set_check_box("checkBox_enabled", self._rep_line.enabled) + self.set_line_edit_text("lineEdit_name", self._rep_line.name) + self.set_line_edit_text("lineEdit_line", self._rep_line.line) + + def accept(self): + is_enabled = self.get_check_box("checkBox_enabled") + name = self.get_line_edit_text("lineEdit_name") + line = self.get_line_edit_text("lineEdit_line") + + self._rep_line.enabled = is_enabled + self._rep_line.name = name + self._rep_line.line = line + self._rep_line.solvers = set() + + self._propagate_update(key=Modules.ADDITIONAL_FILES) + self.close() diff --git a/src/View/REPLines/List.py b/src/View/REPLines/List.py new file mode 100644 index 00000000..a591a4b1 --- /dev/null +++ b/src/View/REPLines/List.py @@ -0,0 +1,71 @@ +# List.py -- Pamhyr +# Copyright (C) 2024 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 functools import reduce +from tools import trace, timer + +from PyQt5.QtCore import ( + Qt, QVariant, +) + +from PyQt5.QtGui import ( + QColor, QBrush, +) + +from View.Tools.PamhyrList import PamhyrListModel + +logger = logging.getLogger() + + +class ListModel(PamhyrListModel): + def data(self, index, role): + row = index.row() + column = index.column() + + file = self._data.lines[row] + + if role == Qt.ForegroundRole: + color = Qt.gray + + if file.is_enabled(): + color = QColor("black") + else: + color = QColor("grey") + + return QBrush(color) + + if role == Qt.ItemDataRole.DisplayRole: + text = f"{file.name}: '{file.line}'" + + if not file.is_enabled(): + text += " (disabled)" + + return text + + return QVariant() + + def add(self, row): + self._data.new(row) + self.update() + + def delete(self, rows): + logger.info(f"add_files: delete {rows}") + self._data.delete_i(rows) + self.update() diff --git a/src/View/REPLines/Translate.py b/src/View/REPLines/Translate.py new file mode 100644 index 00000000..3849345e --- /dev/null +++ b/src/View/REPLines/Translate.py @@ -0,0 +1,35 @@ +# Translate.py -- Pamhyr +# Copyright (C) 2024 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 -*- + +from PyQt5.QtCore import QCoreApplication +from View.Translate import MainTranslate + +_translate = QCoreApplication.translate + + +class REPLineTranslate(MainTranslate): + def __init__(self): + super(REPLineTranslate, self).__init__() + + self._dict["Mage REP lines"] = _translate( + "REPLines", "Mage REP lines" + ) + + self._dict["Edit Mage REP lines"] = _translate( + "REPLines", "Edit Mage REP lines" + ) diff --git a/src/View/REPLines/Window.py b/src/View/REPLines/Window.py new file mode 100644 index 00000000..92cb015b --- /dev/null +++ b/src/View/REPLines/Window.py @@ -0,0 +1,104 @@ +# Window.py -- Pamhyr +# Copyright (C) 2024 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 -*- + +from tools import trace, timer + +from PyQt5.QtWidgets import ( + QAction, QListView, +) + +from View.Tools.PamhyrWindow import PamhyrWindow + +from View.REPLines.List import ListModel +from View.REPLines.Translate import REPLineTranslate +from View.REPLines.Edit.Window import EditREPLineWindow + + +class REPLineListWindow(PamhyrWindow): + _pamhyr_ui = "REPLineList" + _pamhyr_name = "Mage REP lines" + + def __init__(self, study=None, config=None, + parent=None): + trad = REPLineTranslate() + name = trad[self._pamhyr_name] + " - " + study.name + + super(REPLineListWindow, self).__init__( + title=name, + study=study, + config=config, + trad=trad, + options=[], + parent=parent + ) + + self.setup_list() + self.setup_connections() + + def setup_list(self): + lst = self.find(QListView, f"listView") + self._list = ListModel( + list_view=lst, + data=self._study.river.rep_lines, + ) + + def setup_connections(self): + self.find(QAction, "action_add").triggered.connect(self.add) + self.find(QAction, "action_delete").triggered.connect(self.delete) + self.find(QAction, "action_edit").triggered.connect(self.edit) + + def update(self): + self._list.update() + + def selected_rows(self): + lst = self.find(QListView, f"listView") + return list(map(lambda i: i.row(), lst.selectedIndexes())) + + def add(self): + rows = self.selected_rows() + if len(rows) > 0: + row = rows[0] + else: + row = 0 + + self._list.add(row) + + def delete(self): + rows = self.selected_rows() + self._list.delete(rows) + + def edit(self): + rows = self.selected_rows() + + for row in rows: + rep_line = self._study.river.rep_lines.lines[row] + + if self.sub_window_exists( + EditREPLineWindow, + data=[self._study, self._config, rep_line] + ): + continue + + win = EditREPLineWindow( + study=self._study, + config=self._config, + rep_line=rep_line, + trad=self._trad, + parent=self, + ) + win.show() diff --git a/src/View/Study/Window.py b/src/View/Study/Window.py index de7c759f..0a2cad3f 100644 --- a/src/View/Study/Window.py +++ b/src/View/Study/Window.py @@ -119,7 +119,7 @@ This is my new study description ## Copyright -(c) {get_user_name()} - {datetime.now().year} +© {get_user_name()} - {datetime.now().year} All right reserved. """ diff --git a/src/View/ui/MainWindow.ui b/src/View/ui/MainWindow.ui index 35e05ab6..4ea3eb60 100644 --- a/src/View/ui/MainWindow.ui +++ b/src/View/ui/MainWindow.ui @@ -208,7 +208,14 @@ <property name="title"> <string>&Advansed</string> </property> + <widget class="QMenu" name="menuMage"> + <property name="title"> + <string>Mage</string> + </property> + <addaction name="action_menu_rep_additional_lines"/> + </widget> <addaction name="action_menu_additional_file"/> + <addaction name="menuMage"/> </widget> <addaction name="menu_File"/> <addaction name="menu_network"/> @@ -1000,6 +1007,11 @@ <string>&Additional file</string> </property> </action> + <action name="action_menu_rep_additional_lines"> + <property name="text"> + <string>REP additional lines</string> + </property> + </action> </widget> <resources/> <connections> diff --git a/src/View/ui/REPLineDialog.ui b/src/View/ui/REPLineDialog.ui new file mode 100644 index 00000000..9d5722ae --- /dev/null +++ b/src/View/ui/REPLineDialog.ui @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Dialog</class> + <widget class="QDialog" name="Dialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>452</width> + <height>145</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="1" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QCheckBox" name="checkBox_enabled"> + <property name="text"> + <string>Enabled</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + </widget> + </item> + </layout> + </item> + <item row="2" column="0"> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Line</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="lineEdit_name"/> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Name</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="lineEdit_line"> + <property name="toolTip"> + <string>Comment lines start with '*' char (let see the mage documentation for more details)</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="3" column="0"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>Dialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>Dialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/View/ui/REPLineList.ui b/src/View/ui/REPLineList.ui new file mode 100644 index 00000000..f9722d37 --- /dev/null +++ b/src/View/ui/REPLineList.ui @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>896</width> + <height>504</height> + </rect> + </property> + <property name="windowTitle"> + <string>MainWindow</string> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QListView" name="listView"/> + </item> + </layout> + </widget> + <widget class="QToolBar" name="toolBar"> + <property name="windowTitle"> + <string>toolBar</string> + </property> + <attribute name="toolBarArea"> + <enum>TopToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak"> + <bool>false</bool> + </attribute> + <addaction name="action_add"/> + <addaction name="action_delete"/> + <addaction name="action_edit"/> + </widget> + <action name="action_add"> + <property name="icon"> + <iconset> + <normaloff>ressources/gtk-add.png</normaloff>ressources/gtk-add.png</iconset> + </property> + <property name="text"> + <string>Add</string> + </property> + <property name="toolTip"> + <string>Add new additional line</string> + </property> + <property name="shortcut"> + <string>Ctrl+N</string> + </property> + </action> + <action name="action_delete"> + <property name="icon"> + <iconset> + <normaloff>ressources/gtk-remove.png</normaloff>ressources/gtk-remove.png</iconset> + </property> + <property name="text"> + <string>Delete</string> + </property> + <property name="toolTip"> + <string>Delete additional line(s)</string> + </property> + <property name="shortcut"> + <string>Del</string> + </property> + </action> + <action name="action_edit"> + <property name="icon"> + <iconset> + <normaloff>ressources/edit.png</normaloff>ressources/edit.png</iconset> + </property> + <property name="text"> + <string>Edit</string> + </property> + <property name="toolTip"> + <string>Edit selected line(s)</string> + </property> + <property name="shortcut"> + <string>Ctrl+E</string> + </property> + </action> + </widget> + <resources/> + <connections/> +</ui> -- GitLab