fmu-manipulation-toolbox 1.9rc0__py3-none-any.whl → 1.9rc2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fmu_manipulation_toolbox/__init__.py +0 -1
- fmu_manipulation_toolbox/__main__.py +1 -1
- fmu_manipulation_toolbox/__version__.py +1 -1
- fmu_manipulation_toolbox/assembly.py +8 -6
- fmu_manipulation_toolbox/checker.py +11 -8
- fmu_manipulation_toolbox/container.py +492 -206
- fmu_manipulation_toolbox/gui.py +45 -55
- fmu_manipulation_toolbox/gui_style.py +8 -0
- fmu_manipulation_toolbox/operations.py +184 -120
- fmu_manipulation_toolbox/resources/darwin64/container.dylib +0 -0
- fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
- fmu_manipulation_toolbox/resources/win32/client_sm.dll +0 -0
- fmu_manipulation_toolbox/resources/win32/server_sm.exe +0 -0
- fmu_manipulation_toolbox/resources/win64/client_sm.dll +0 -0
- fmu_manipulation_toolbox/resources/win64/container.dll +0 -0
- fmu_manipulation_toolbox/resources/win64/server_sm.exe +0 -0
- fmu_manipulation_toolbox/split.py +8 -0
- {fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/METADATA +1 -1
- {fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/RECORD +23 -22
- {fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/WHEEL +0 -0
- {fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/entry_points.txt +0 -0
- {fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/licenses/LICENSE.txt +0 -0
- {fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/top_level.txt +0 -0
fmu_manipulation_toolbox/gui.py
CHANGED
|
@@ -2,22 +2,24 @@ import os.path
|
|
|
2
2
|
import sys
|
|
3
3
|
import textwrap
|
|
4
4
|
|
|
5
|
-
from PySide6.QtCore import Qt,
|
|
5
|
+
from PySide6.QtCore import Qt, QUrl, QDir, Signal, QPoint, QModelIndex
|
|
6
6
|
from PySide6.QtWidgets import (QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QPushButton, QFileDialog,
|
|
7
7
|
QTextBrowser, QInputDialog, QMenu, QTreeView, QAbstractItemView, QTabWidget, QTableView,
|
|
8
8
|
QCheckBox)
|
|
9
9
|
from PySide6.QtGui import (QPixmap, QTextCursor, QStandardItem, QIcon, QDesktopServices, QAction,
|
|
10
10
|
QPainter, QColor, QImage, QStandardItemModel)
|
|
11
11
|
from functools import partial
|
|
12
|
-
from typing import Optional
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
|
|
14
|
+
from .gui_style import gui_style, log_color
|
|
15
15
|
from .operations import *
|
|
16
16
|
from .assembly import Assembly, AssemblyNode
|
|
17
17
|
from .checker import checker_list
|
|
18
18
|
from .help import Help
|
|
19
19
|
from .version import __version__ as version
|
|
20
20
|
|
|
21
|
+
logger = logging.getLogger("fmu_manipulation_toolbox")
|
|
22
|
+
|
|
21
23
|
|
|
22
24
|
class DropZoneWidget(QLabel):
|
|
23
25
|
WIDTH = 150
|
|
@@ -51,7 +53,7 @@ class DropZoneWidget(QLabel):
|
|
|
51
53
|
try:
|
|
52
54
|
file_path = event.mimeData().urls()[0].toLocalFile()
|
|
53
55
|
except IndexError:
|
|
54
|
-
|
|
56
|
+
logger.error("Please select a regular file.")
|
|
55
57
|
return
|
|
56
58
|
self.set_fmu(file_path)
|
|
57
59
|
event.accept()
|
|
@@ -98,54 +100,41 @@ class DropZoneWidget(QLabel):
|
|
|
98
100
|
self.fmu = FMU(filename)
|
|
99
101
|
self.set_image(os.path.join(self.fmu.tmp_directory, "model.png"))
|
|
100
102
|
except Exception as e:
|
|
101
|
-
|
|
103
|
+
logger.error(f"Cannot load this FMU: {e}")
|
|
102
104
|
self.set_image(None)
|
|
103
105
|
self.fmu = None
|
|
104
106
|
self.clicked.emit()
|
|
105
107
|
|
|
106
108
|
|
|
109
|
+
class LogHandler(logging.Handler):
|
|
110
|
+
LOG_COLOR = {
|
|
111
|
+
logging.DEBUG: QColor(log_color["DEBUG"]),
|
|
112
|
+
logging.INFO: QColor(log_color["INFO"]),
|
|
113
|
+
logging.WARNING: QColor(log_color["WARNING"]),
|
|
114
|
+
logging.ERROR: QColor(log_color["ERROR"]),
|
|
115
|
+
logging.CRITICAL: QColor(log_color["CRITICAL"]),
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
def __init__(self, text_browser, level):
|
|
119
|
+
super().__init__(level)
|
|
120
|
+
self.text_browser: QTextBrowser = text_browser
|
|
121
|
+
logger.addHandler(self)
|
|
122
|
+
logger.setLevel(level)
|
|
123
|
+
|
|
124
|
+
def emit(self, record) -> None:
|
|
125
|
+
self.text_browser.setTextColor(self.LOG_COLOR[record.levelno])
|
|
126
|
+
self.text_browser.insertPlainText(record.msg+"\n")
|
|
127
|
+
|
|
128
|
+
|
|
107
129
|
class LogWidget(QTextBrowser):
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
_stderr = None
|
|
111
|
-
messageWritten = Signal(str)
|
|
112
|
-
|
|
113
|
-
def __init__(self):
|
|
114
|
-
super().__init__()
|
|
115
|
-
|
|
116
|
-
def flush(self):
|
|
117
|
-
pass
|
|
118
|
-
|
|
119
|
-
@staticmethod
|
|
120
|
-
def fileno():
|
|
121
|
-
return -1
|
|
122
|
-
|
|
123
|
-
def write(self, msg):
|
|
124
|
-
if not self.signalsBlocked():
|
|
125
|
-
self.messageWritten.emit(msg)
|
|
126
|
-
|
|
127
|
-
@staticmethod
|
|
128
|
-
def stdout():
|
|
129
|
-
if not LogWidget.XStream._stdout:
|
|
130
|
-
LogWidget.XStream._stdout = LogWidget.XStream()
|
|
131
|
-
sys.stdout = LogWidget.XStream._stdout
|
|
132
|
-
return LogWidget.XStream._stdout
|
|
133
|
-
|
|
134
|
-
@staticmethod
|
|
135
|
-
def stderr():
|
|
136
|
-
if not LogWidget.XStream._stderr:
|
|
137
|
-
LogWidget.XStream._stderr = LogWidget.XStream()
|
|
138
|
-
sys.stderr = LogWidget.XStream._stderr
|
|
139
|
-
return LogWidget.XStream._stderr
|
|
130
|
+
def __init__(self, parent=None, level=logging.INFO):
|
|
131
|
+
super().__init__(parent)
|
|
140
132
|
|
|
141
|
-
def __init__(self):
|
|
142
|
-
super().__init__()
|
|
143
133
|
self.setMinimumWidth(900)
|
|
144
134
|
self.setMinimumHeight(500)
|
|
145
135
|
self.setSearchPaths([os.path.join(os.path.dirname(__file__), "resources")])
|
|
146
136
|
self.insertHtml('<center><img src="fmu_manipulation_toolbox.png"/></center><br/>')
|
|
147
|
-
|
|
148
|
-
LogWidget.XStream.stderr().messageWritten.connect(self.insertPlainText)
|
|
137
|
+
self.log_handler = LogHandler(self, logging.DEBUG)
|
|
149
138
|
|
|
150
139
|
def loadResource(self, _, name):
|
|
151
140
|
image_path = os.path.join(os.path.dirname(__file__), "resources", name.toString())
|
|
@@ -255,10 +244,10 @@ class AssemblyTreeWidget(QTreeView):
|
|
|
255
244
|
|
|
256
245
|
def removeRows(self, row, count, parent=QModelIndex()):
|
|
257
246
|
if not self.dnd_target_node:
|
|
258
|
-
|
|
247
|
+
logger.error("NO DROP NODE!?")
|
|
259
248
|
|
|
260
249
|
source_index = self.itemFromIndex(parent).child(row, 0).data(role=Qt.ItemDataRole.UserRole+1)
|
|
261
|
-
|
|
250
|
+
logger.debug(f"{source_index} ==> {self.dnd_target_node.name}")
|
|
262
251
|
|
|
263
252
|
self.dnd_target_node = None
|
|
264
253
|
return super().removeRows(row, count, parent)
|
|
@@ -289,7 +278,7 @@ class AssemblyTreeWidget(QTreeView):
|
|
|
289
278
|
|
|
290
279
|
def setTopIndex(self):
|
|
291
280
|
topIndex = self.model.index(0, 0, self.rootIndex())
|
|
292
|
-
|
|
281
|
+
logger.debug(topIndex.isValid(), topIndex.model())
|
|
293
282
|
if topIndex.isValid():
|
|
294
283
|
self.setCurrentIndex(topIndex)
|
|
295
284
|
if self.layoutCheck:
|
|
@@ -318,9 +307,9 @@ class AssemblyTreeWidget(QTreeView):
|
|
|
318
307
|
try:
|
|
319
308
|
file_path = event.mimeData().urls()[0].toLocalFile()
|
|
320
309
|
except IndexError:
|
|
321
|
-
|
|
310
|
+
logger.error("Please select a regular file.")
|
|
322
311
|
return
|
|
323
|
-
|
|
312
|
+
logger.debug(f"DROP: {file_path}")
|
|
324
313
|
event.accept()
|
|
325
314
|
else:
|
|
326
315
|
event.ignore()
|
|
@@ -518,7 +507,7 @@ class MainWindow(WindowWithLayout):
|
|
|
518
507
|
"FMU files (*.fmu)")
|
|
519
508
|
if ok and filename:
|
|
520
509
|
fmu.repack(filename)
|
|
521
|
-
|
|
510
|
+
logger.info(f"Modified version saved as {filename}.")
|
|
522
511
|
|
|
523
512
|
def save_log(self):
|
|
524
513
|
if self.dropped_fmu.fmu:
|
|
@@ -533,7 +522,7 @@ class MainWindow(WindowWithLayout):
|
|
|
533
522
|
with open(filename, "wt") as file:
|
|
534
523
|
file.write(str(self.log_widget.toPlainText()))
|
|
535
524
|
except Exception as e:
|
|
536
|
-
|
|
525
|
+
logger.error(f"{e}")
|
|
537
526
|
|
|
538
527
|
def add_operation(self, name, usage, severity, operation, x, y, prompt=None, prompt_file=None, arg=None,
|
|
539
528
|
func=None):
|
|
@@ -603,18 +592,18 @@ class MainWindow(WindowWithLayout):
|
|
|
603
592
|
if self.dropped_fmu.fmu:
|
|
604
593
|
self.log_widget.moveCursor(QTextCursor.MoveOperation.End)
|
|
605
594
|
fmu_filename = os.path.basename(self.dropped_fmu.fmu.fmu_filename)
|
|
606
|
-
|
|
595
|
+
logger.info('-' * 100)
|
|
607
596
|
self.log_widget.insertHtml(f"<strong>{fmu_filename}: {operation}</strong><br>")
|
|
608
597
|
|
|
609
598
|
apply_on = self.filter_list.get()
|
|
610
599
|
if apply_on:
|
|
611
600
|
self.log_widget.insertHtml(f"<i>Applied only for ports with causality = " +
|
|
612
601
|
", ".join(apply_on) + "</i><br>")
|
|
613
|
-
|
|
602
|
+
logger.info('-' * 100)
|
|
614
603
|
try:
|
|
615
604
|
self.dropped_fmu.fmu.apply_operation(operation, apply_on=apply_on)
|
|
616
605
|
except Exception as e:
|
|
617
|
-
|
|
606
|
+
logger.error(f"{e}")
|
|
618
607
|
|
|
619
608
|
scroll_bar = self.log_widget.verticalScrollBar()
|
|
620
609
|
scroll_bar.setValue(scroll_bar.maximum())
|
|
@@ -712,7 +701,7 @@ class ContainerWindow(WindowWithLayout):
|
|
|
712
701
|
self.last_directory = os.path.dirname(filename)
|
|
713
702
|
self.assembly_tree.load_container(filename)
|
|
714
703
|
except Exception as e:
|
|
715
|
-
|
|
704
|
+
logger.error(e)
|
|
716
705
|
|
|
717
706
|
|
|
718
707
|
class Application(QApplication):
|
|
@@ -724,8 +713,9 @@ Communicating with the FMU-developer and adapting the way the FMU is generated,
|
|
|
724
713
|
|
|
725
714
|
"""
|
|
726
715
|
def __init__(self, *args, **kwargs):
|
|
727
|
-
super().__init__(*args, **kwargs)
|
|
728
716
|
self.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.RoundPreferFloor)
|
|
717
|
+
super().__init__(*args, **kwargs)
|
|
718
|
+
|
|
729
719
|
|
|
730
720
|
QDir.addSearchPath('images', os.path.join(os.path.dirname(__file__), "resources"))
|
|
731
721
|
self.setStyleSheet(gui_style)
|
|
@@ -747,8 +737,8 @@ Communicating with the FMU-developer and adapting the way the FMU is generated,
|
|
|
747
737
|
def main():
|
|
748
738
|
application = Application(sys.argv)
|
|
749
739
|
|
|
750
|
-
|
|
751
|
-
|
|
740
|
+
logger.info(" " * 80 + f"Version {version}")
|
|
741
|
+
logger.info(application.__doc__)
|
|
752
742
|
|
|
753
743
|
sys.exit(application.exec())
|
|
754
744
|
|