diff --git a/src/Model/AdditionalFile/AddFile.py b/src/Model/AdditionalFile/AddFile.py
new file mode 100644
index 00000000..64099205
--- /dev/null
+++ b/src/Model/AdditionalFile/AddFile.py
@@ -0,0 +1,148 @@
+# AddFile.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 .
+
+# -*- coding: utf-8 -*-
+
+from functools import reduce
+
+from tools import trace, timer
+
+from Model.Tools.PamhyrDB import SQLSubModel
+from Model.Except import NotImplementedMethodeError
+
+
+class AddFile(SQLSubModel):
+ _sub_classes = []
+ _id_cnt = 0
+
+ def __init__(self, id: int = -1, enabled=True,
+ name="", path="", text="",
+ status=None):
+ super(AddFile, self).__init__()
+
+ if id == -1:
+ self.id = AddFile._id_cnt
+ else:
+ self.id = id
+
+ self._status = status
+
+ self._enabled = enabled
+ self._name = f"File {self.id}" if name == "" else name
+ self._path = path
+ self._text = text
+
+ AddFile._id_cnt = max(id, AddFile._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 path(self):
+ return self._path
+
+ @path.setter
+ def path(self, path):
+ self._path = path
+
+ @property
+ def text(self):
+ return self._text
+
+ @text.setter
+ def text(self, text):
+ self._text = text
+
+ @classmethod
+ def _db_create(cls, execute):
+ execute("""
+ CREATE TABLE additional_files(
+ id INTEGER NOT NULL PRIMARY KEY,
+ enabled BOOLEAN NOT NULL,
+ name TEXT NOT NULL,
+ path TEXT NOT NULL,
+ text 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) < 8:
+ cls._db_create(execute)
+
+ return True
+
+ @classmethod
+ def _db_load(cls, execute, data=None):
+ new = []
+
+ table = execute(
+ "SELECT id, enabled, name, path, text " +
+ "FROM additional_files"
+ )
+
+ for row in table:
+ it = iter(row)
+
+ id = next(it)
+ enabled = (next(it) == 1)
+ name = next(it)
+ path = next(it)
+ text = next(it)
+
+ f = cls(
+ id=id, enabled=enabled, name=name, path=path, text=text,
+ status=data['status']
+ )
+
+ new.append(f)
+
+ return new
+
+ def _db_save(self, execute, data=None):
+ sql = (
+ "INSERT INTO " +
+ "additional_files(id, enabled, name, path, text) " +
+ "VALUES (" +
+ f"{self.id}, {self._enabled}, " +
+ f"'{self._db_format(self._name)}', " +
+ f"'{self._db_format(self._path)}', " +
+ f"'{self._db_format(self._text)}'" +
+ ")"
+ )
+ execute(sql)
+
+ return True
diff --git a/src/Model/AdditionalFile/AddFileList.py b/src/Model/AdditionalFile/AddFileList.py
new file mode 100644
index 00000000..8d28e211
--- /dev/null
+++ b/src/Model/AdditionalFile/AddFileList.py
@@ -0,0 +1,56 @@
+# AddFileList.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 .
+
+# -*- coding: utf-8 -*-
+
+from tools import trace, timer
+
+from Model.Except import NotImplementedMethodeError
+from Model.Tools.PamhyrList import PamhyrModelList
+from Model.AdditionalFile.AddFile import AddFile
+
+
+class AddFileList(PamhyrModelList):
+ _sub_classes = [AddFile]
+
+ @classmethod
+ def _db_load(cls, execute, data=None):
+ new = cls(status=data["status"])
+
+ new._lst = AddFile._db_load(execute, data)
+
+ return new
+
+ def _db_save(self, execute, data=None):
+ ok = True
+
+ # Delete previous data
+ execute("DELETE FROM additional_files")
+
+ for af in self._lst:
+ ok &= af._db_save(execute, data)
+
+ return ok
+
+ @property
+ def files(self):
+ return self.lst
+
+ def new(self, index):
+ n = AddFile(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 80da45f4..41d4e0d8 100644
--- a/src/Model/River.py
+++ b/src/Model/River.py
@@ -40,6 +40,7 @@ from Model.Reservoir.ReservoirList import ReservoirList
from Model.HydraulicStructures.HydraulicStructuresList import (
HydraulicStructureList,
)
+from Model.AdditionalFile.AddFileList import AddFileList
from Solver.Solvers import solver_type_list
@@ -224,6 +225,7 @@ class River(Graph, SQLSubModel):
SedimentLayerList,
ReservoirList,
HydraulicStructureList,
+ AddFileList,
]
def __init__(self, status=None):
@@ -245,6 +247,7 @@ class River(Graph, SQLSubModel):
self._hydraulic_structures = HydraulicStructureList(
status=self._status
)
+ self._additional_files = AddFileList(status=self._status)
@classmethod
def _db_create(cls, execute):
@@ -263,64 +266,59 @@ class River(Graph, SQLSubModel):
# Stricklers (Stricklers is load in first because it's needed
# for reachs)
new._stricklers = StricklersList._db_load(
- execute,
- data
+ execute, data
)
data["stricklers"] = new._stricklers
# Initial conditions
new._sediment_layers = SedimentLayerList._db_load(
- execute,
- data
+ execute, data
)
data["sediment_layers_list"] = new._sediment_layers
# Network
new._nodes = RiverNode._db_load(
- execute,
- data
+ execute, data
)
data["nodes"] = new.nodes()
new._edges = RiverReach._db_load(
- execute,
- data
+ execute, data
)
data["edges"] = new.edges()
# Boundary Condition
new._boundary_condition = BoundaryConditionList._db_load(
- execute,
- data
+ execute, data
)
# Lateral Contribution
new._lateral_contribution = LateralContributionList._db_load(
- execute,
- data
+ execute, data
)
# Initial conditions
new._initial_conditions = InitialConditionsDict._db_load(
- execute,
- data
+ execute, data
)
# Reservoir
new._reservoir = ReservoirList._db_load(
- execute,
- data
+ execute, data
)
# Hydraulic Structures
new._hydraulic_structures = HydraulicStructureList._db_load(
- execute,
- data
+ execute, data
)
# Parameters
new._parameters = SolverParametersList._db_load(
- execute,
- data
+ execute, data
+ )
+
+ # Additional Files
+ new._additional_files = AddFileList._db_load(
+ execute, data
)
return new
@@ -336,6 +334,7 @@ class River(Graph, SQLSubModel):
objs.append(self._stricklers)
objs.append(self._reservoir)
objs.append(self._hydraulic_structures)
+ objs.append(self._additional_files)
for solver in self._parameters:
objs.append(self._parameters[solver])
@@ -373,11 +372,27 @@ class River(Graph, SQLSubModel):
logger_exception(e)
def init_default(self):
+ self.init_default_network()
+ self.init_default_additional_files()
+
+ def init_default_network(self):
n1 = self.add_node(880.0, 950.0)
n2 = self.add_node(1120.0, 1020.0)
e = self.add_edge(n1, n2)
+ def init_default_additional_files(self):
+ add_file = self._additional_files.new(0)
+ add_file.name = "Pamhyr2 stamp file"
+ add_file.path = "Pamhyr2.txt"
+ add_file.text = """This repository has been generated by Pamhyr2 \
+version "@version" !
+
+All hand made file modification could be erased by the next solver
+execution...
+
+Last export at: @date."""
+
@property
def boundary_condition(self):
return self._boundary_condition
@@ -419,6 +434,10 @@ class River(Graph, SQLSubModel):
def hydraulic_structures(self):
return self._hydraulic_structures
+ @property
+ def additional_files(self):
+ return self._additional_files
+
@property
def parameters(self):
return self._parameters
diff --git a/src/Model/Study.py b/src/Model/Study.py
index 2b8a859c..d9167d19 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.7"
+ self._version = "0.0.8"
self.creation_date = datetime.now()
self.last_modification_date = datetime.now()
self.last_save_date = datetime.now()
diff --git a/src/Modules.py b/src/Modules.py
index 2c4d8f6b..90881369 100644
--- a/src/Modules.py
+++ b/src/Modules.py
@@ -40,6 +40,7 @@ class Modules(Flag):
HYDRAULIC_STRUCTURES = auto()
RESERVOIR = auto()
SEDIMENT_LAYER = auto()
+ ADDITIONAL_FILES = auto()
# Results
RESULTS = auto()
diff --git a/src/Solver/CommandLine.py b/src/Solver/CommandLine.py
index 6066e0c8..e93d4e98 100644
--- a/src/Solver/CommandLine.py
+++ b/src/Solver/CommandLine.py
@@ -19,7 +19,8 @@
import os
import logging
-from tools import timer, parse_command_line
+from datetime import datetime
+from tools import timer, parse_command_line, get_version
try:
# Installation allow Unix-like signal
@@ -124,6 +125,39 @@ class CommandLineSolver(AbstractSolver):
"""
raise NotImplementedMethodeError(self, self.log_file)
+ def export_additional_files(self, study, repertory, qlog, name="0"):
+ files = []
+
+ if qlog is not None:
+ qlog.put("Export additional files")
+
+ files = study.river.additional_files.files
+ for add_file in files:
+ self.export_additional_file(
+ add_file, repertory, files
+ )
+
+ def export_additional_file(self, add_file, repertory, files):
+ if add_file.path == "" or not add_file.is_enabled():
+ return files
+
+ path = os.path.join(repertory, add_file.path)
+ os.makedirs(
+ os.path.dirname(path),
+ exist_ok=True
+ )
+
+ with open(path, "w+") as f:
+ files.append(add_file.path)
+
+ txt = add_file.text
+ txt = txt.replace("@version", get_version())
+ txt = txt.replace("@date", datetime.now().isoformat(sep=" "))
+
+ f.write(txt)
+
+ return files
+
#######
# Run #
#######
diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py
index e4754ccb..51f7d656 100644
--- a/src/Solver/Mage.py
+++ b/src/Solver/Mage.py
@@ -671,6 +671,7 @@ class Mage(CommandLineSolver):
self._bin_file = f"{name}.BIN"
self._export_ST(study, repertory, qlog, name=name)
+ self.export_additional_files(study, repertory, qlog, name=name)
return True
@@ -886,6 +887,10 @@ class Mage8(Mage):
files = files + self._export_VAR(study, repertory, qlog, name=name)
files = files + self._export_CAS(study, repertory, qlog, name=name)
files = files + self._export_DEV(study, repertory, qlog, name=name)
+ files = files + self.export_additional_files(
+ study, repertory, qlog, name=name
+ )
+
self._export_REP(study, repertory, files, qlog, name=name)
return True
diff --git a/src/View/AdditionalFiles/Edit/Window.py b/src/View/AdditionalFiles/Edit/Window.py
new file mode 100644
index 00000000..6db27942
--- /dev/null
+++ b/src/View/AdditionalFiles/Edit/Window.py
@@ -0,0 +1,80 @@
+# 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 .
+
+# -*- coding: utf-8 -*-
+
+import logging
+
+from Modules import Modules
+from View.Tools.PamhyrWindow import PamhyrWindow
+
+from PyQt5.QtWidgets import (
+ QLabel, QPlainTextEdit, QPushButton,
+ QCheckBox,
+)
+
+from View.AdditionalFiles.Translate import AddFileTranslate
+
+logger = logging.getLogger()
+
+
+class EditAddFileWindow(PamhyrWindow):
+ _pamhyr_ui = "AdditionalFile"
+ _pamhyr_name = "Edit additional file"
+
+ def __init__(self, study=None, config=None, add_file=None,
+ trad=None, parent=None):
+
+ name = trad[self._pamhyr_name] + " - " + study.name
+ super(EditAddFileWindow, self).__init__(
+ title=name,
+ study=study,
+ config=config,
+ options=[],
+ parent=parent
+ )
+
+ self._add_file = add_file
+ self._hash_data.append(self._add_file)
+
+ self.setup_values()
+ self.setup_connection()
+
+ def setup_values(self):
+ self.set_check_box("checkBox", self._add_file.enabled)
+ self.set_line_edit_text("lineEdit_name", self._add_file.name)
+ self.set_line_edit_text("lineEdit_path", self._add_file.path)
+ self.set_plaintext_edit_text("plainTextEdit", self._add_file.text)
+
+ def setup_connection(self):
+ self.find(QPushButton, "pushButton_cancel")\
+ .clicked.connect(self.close)
+ self.find(QPushButton, "pushButton_ok")\
+ .clicked.connect(self.accept)
+
+ def accept(self):
+ is_enabled = self.get_check_box("checkBox")
+ name = self.get_line_edit_text("lineEdit_name")
+ path = self.get_line_edit_text("lineEdit_path")
+ text = self.get_plaintext_edit_text("plainTextEdit")
+
+ self._add_file.enabled = is_enabled
+ self._add_file.name = name
+ self._add_file.path = path
+ self._add_file.text = text
+
+ self._propagate_update(key=Modules.ADDITIONAL_FILES)
+ self.close()
diff --git a/src/View/AdditionalFiles/List.py b/src/View/AdditionalFiles/List.py
new file mode 100644
index 00000000..374ce54c
--- /dev/null
+++ b/src/View/AdditionalFiles/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 .
+
+# -*- 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.files[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.path}'"
+
+ 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/AdditionalFiles/Translate.py b/src/View/AdditionalFiles/Translate.py
new file mode 100644
index 00000000..3df7d339
--- /dev/null
+++ b/src/View/AdditionalFiles/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 .
+
+# -*- coding: utf-8 -*-
+
+from PyQt5.QtCore import QCoreApplication
+from View.Translate import MainTranslate
+
+_translate = QCoreApplication.translate
+
+
+class AddFileTranslate(MainTranslate):
+ def __init__(self):
+ super(AddFileTranslate, self).__init__()
+
+ self._dict["Additional files"] = _translate(
+ "AdditionalFiles", "Additional files"
+ )
+
+ self._dict["Edit additional file"] = _translate(
+ "AdditionalFiles", "Edit additional file"
+ )
diff --git a/src/View/AdditionalFiles/Window.py b/src/View/AdditionalFiles/Window.py
new file mode 100644
index 00000000..6cd84203
--- /dev/null
+++ b/src/View/AdditionalFiles/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 .
+
+# -*- coding: utf-8 -*-
+
+from tools import trace, timer
+
+from PyQt5.QtWidgets import (
+ QAction, QListView,
+)
+
+from View.Tools.PamhyrWindow import PamhyrWindow
+
+from View.AdditionalFiles.List import ListModel
+from View.AdditionalFiles.Translate import AddFileTranslate
+from View.AdditionalFiles.Edit.Window import EditAddFileWindow
+
+
+class AddFileListWindow(PamhyrWindow):
+ _pamhyr_ui = "AdditionalFileList"
+ _pamhyr_name = "Additional files"
+
+ def __init__(self, study=None, config=None,
+ parent=None):
+ trad = AddFileTranslate()
+ name = trad[self._pamhyr_name] + " - " + study.name
+
+ super(AddFileListWindow, 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.additional_files,
+ )
+
+ 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:
+ add_file = self._study.river.additional_files.files[row]
+
+ if self.sub_window_exists(
+ EditAddFileWindow,
+ data=[self._study, self._config, add_file]
+ ):
+ continue
+
+ win = EditAddFileWindow(
+ study=self._study,
+ config=self._config,
+ add_file=add_file,
+ trad=self._trad,
+ parent=self,
+ )
+ win.show()
diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py
index 496c894c..836f6d7e 100644
--- a/src/View/MainWindow.py
+++ b/src/View/MainWindow.py
@@ -67,6 +67,7 @@ from View.Stricklers.Window import StricklersWindow
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.SolverParameters.Window import SolverParametersWindow
from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow
from View.CheckList.Window import CheckListWindow
@@ -117,7 +118,7 @@ define_model_action = [
"action_menu_edit_friction", "action_menu_edit_lateral_contribution",
"action_menu_run_solver", "action_menu_sediment_layers",
"action_menu_edit_reach_sediment_layers", "action_menu_edit_reservoirs",
- "action_menu_edit_hydraulic_structures",
+ "action_menu_edit_hydraulic_structures", "action_menu_additional_file",
"action_menu_results_last", "action_open_results_from_file",
"action_menu_boundary_conditions_sediment",
]
@@ -252,6 +253,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
"action_menu_sediment_layers": self.open_sediment_layers,
"action_menu_edit_reach_sediment_layers":
self.open_reach_sediment_layers,
+ "action_menu_additional_file": self.open_additional_files,
"action_menu_close": self.close_model,
"action_menu_results_last": self.open_last_results,
"action_open_results_from_file": self.open_results_from_file,
@@ -1063,6 +1065,19 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
else:
self.msg_select_reach()
+ def open_additional_files(self):
+ if self._study is not None:
+ if self.sub_window_exists(
+ AddFileListWindow,
+ data=[self._study, None]
+ ):
+ return
+
+ self.additonal_files = AddFileListWindow(
+ study=self._study, parent=self
+ )
+ self.additonal_files.show()
+
def open_solver_parameters(self):
if self.sub_window_exists(
SolverParametersWindow,
diff --git a/src/View/ui/AdditionalFile.ui b/src/View/ui/AdditionalFile.ui
new file mode 100644
index 00000000..b4419c42
--- /dev/null
+++ b/src/View/ui/AdditionalFile.ui
@@ -0,0 +1,112 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 896
+ 504
+
+
+
+ MainWindow
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Cancel
+
+
+
+ -
+
+
+ Ok
+
+
+
+
+
+ -
+
+
+ File text
+
+
+
-
+
+
+
+
+
+ -
+
+
+ Information
+
+
+
-
+
+
+ Enabled
+
+
+ true
+
+
+
+ -
+
+
+ The relative file path on executable directory
+
+
+
+ -
+
+
+ -
+
+
+ Name
+
+
+
+ -
+
+
+ Path
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/View/ui/AdditionalFileList.ui b/src/View/ui/AdditionalFileList.ui
new file mode 100644
index 00000000..45da9fc6
--- /dev/null
+++ b/src/View/ui/AdditionalFileList.ui
@@ -0,0 +1,76 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 896
+ 504
+
+
+
+ MainWindow
+
+
+
+ -
+
+
+
+
+
+
+ toolBar
+
+
+ TopToolBarArea
+
+
+ false
+
+
+
+
+
+
+
+
+ ressources/gtk-add.pngressources/gtk-add.png
+
+
+ Add
+
+
+ Add a new file
+
+
+
+
+
+ ressources/gtk-remove.pngressources/gtk-remove.png
+
+
+ Delete
+
+
+ Delete selected file(s)
+
+
+
+
+
+ ressources/edit.pngressources/edit.png
+
+
+ Edit
+
+
+ Edit file
+
+
+
+
+
+
diff --git a/src/View/ui/MainWindow.ui b/src/View/ui/MainWindow.ui
index 3f6d6bdd..35e05ab6 100644
--- a/src/View/ui/MainWindow.ui
+++ b/src/View/ui/MainWindow.ui
@@ -204,11 +204,18 @@
&Windows
+
+
@@ -988,6 +995,11 @@
Boundary conditions and punctual contributions
+
+
+ &Additional file
+
+
diff --git a/src/tools.py b/src/tools.py
index 60e4ee9f..ae8da822 100644
--- a/src/tools.py
+++ b/src/tools.py
@@ -279,10 +279,20 @@ def get_user_name():
return "Me"
+def get_version():
+ with open(os.path.abspath(
+ os.path.join(
+ os.path.dirname(__file__),
+ "VERSION"
+ )
+ ), "r") as f:
+ return f.readline().strip()
+
#######################
# COMMAND LINE PARSER #
#######################
+
parser_special_char = ["\"", "\'"]