fmu-manipulation-toolbox 1.8.1__py3-none-any.whl → 1.8.2__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.
Files changed (24) hide show
  1. fmu_manipulation_toolbox/__version__.py +1 -1
  2. fmu_manipulation_toolbox/assembly.py +127 -41
  3. fmu_manipulation_toolbox/cli.py +14 -5
  4. fmu_manipulation_toolbox/fmu_container.py +62 -18
  5. fmu_manipulation_toolbox/fmu_operations.py +2 -3
  6. fmu_manipulation_toolbox/gui.py +330 -79
  7. fmu_manipulation_toolbox/gui_style.py +129 -0
  8. fmu_manipulation_toolbox/resources/container.png +0 -0
  9. fmu_manipulation_toolbox/resources/drop_fmu.png +0 -0
  10. fmu_manipulation_toolbox/resources/fmu.png +0 -0
  11. fmu_manipulation_toolbox/resources/fmu_manipulation_toolbox.png +0 -0
  12. fmu_manipulation_toolbox/resources/icon_fmu.png +0 -0
  13. fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
  14. fmu_manipulation_toolbox/resources/win32/client_sm.dll +0 -0
  15. fmu_manipulation_toolbox/resources/win32/server_sm.exe +0 -0
  16. fmu_manipulation_toolbox/resources/win64/client_sm.dll +0 -0
  17. fmu_manipulation_toolbox/resources/win64/container.dll +0 -0
  18. fmu_manipulation_toolbox/resources/win64/server_sm.exe +0 -0
  19. {fmu_manipulation_toolbox-1.8.1.dist-info → fmu_manipulation_toolbox-1.8.2.dist-info}/METADATA +8 -3
  20. {fmu_manipulation_toolbox-1.8.1.dist-info → fmu_manipulation_toolbox-1.8.2.dist-info}/RECORD +24 -21
  21. {fmu_manipulation_toolbox-1.8.1.dist-info → fmu_manipulation_toolbox-1.8.2.dist-info}/WHEEL +1 -1
  22. {fmu_manipulation_toolbox-1.8.1.dist-info → fmu_manipulation_toolbox-1.8.2.dist-info}/LICENSE.txt +0 -0
  23. {fmu_manipulation_toolbox-1.8.1.dist-info → fmu_manipulation_toolbox-1.8.2.dist-info}/entry_points.txt +0 -0
  24. {fmu_manipulation_toolbox-1.8.1.dist-info → fmu_manipulation_toolbox-1.8.2.dist-info}/top_level.txt +0 -0
@@ -1,17 +1,22 @@
1
1
  import os.path
2
2
  import sys
3
- from .version import __version__ as version
4
- from PyQt6.QtCore import Qt, QObject, QUrl, pyqtSignal, QDir, QSize, QPoint
5
- from PyQt6.QtWidgets import (QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QPushButton, QFileDialog,
6
- QTextBrowser, QInputDialog, QMenu)
7
- from PyQt6.QtGui import (QPixmap, QImage, QFont, QTextCursor, QIcon, QDesktopServices, QAction, QPainter, QColor)
8
3
  import textwrap
4
+
5
+ from PySide6.QtCore import Qt, QObject, QUrl, QDir, Signal, QPoint, QModelIndex
6
+ from PySide6.QtWidgets import (QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QPushButton, QFileDialog,
7
+ QTextBrowser, QInputDialog, QMenu, QTreeView, QAbstractItemView, QTabWidget, QTableView,
8
+ QCheckBox)
9
+ from PySide6.QtGui import (QPixmap, QTextCursor, QStandardItem, QIcon, QDesktopServices, QAction,
10
+ QPainter, QColor, QImage, QStandardItemModel)
9
11
  from functools import partial
10
12
  from typing import Optional
11
13
 
14
+ from .gui_style import *
12
15
  from .fmu_operations import *
16
+ from .assembly import Assembly, AssemblyNode
13
17
  from .checker import checker_list
14
18
  from .help import Help
19
+ from .version import __version__ as version
15
20
 
16
21
 
17
22
  class DropZoneWidget(QLabel):
@@ -19,29 +24,29 @@ class DropZoneWidget(QLabel):
19
24
  HEIGHT = 150
20
25
  fmu = None
21
26
  last_directory = None
22
- clicked = pyqtSignal()
27
+ clicked = Signal()
23
28
 
24
- def __init__(self):
25
- super().__init__()
29
+ def __init__(self, parent=None):
30
+ super().__init__(parent)
26
31
  self.setAcceptDrops(True)
27
32
  self.set_image(None)
28
33
  self.setProperty("class", "dropped_fmu")
29
34
  self.setFixedSize(self.WIDTH, self.HEIGHT)
30
35
 
31
36
  def dragEnterEvent(self, event):
32
- if event.mimeData().hasImage:
37
+ if event.mimeData().hasUrls():
33
38
  event.accept()
34
39
  else:
35
40
  event.ignore()
36
41
 
37
42
  def dragMoveEvent(self, event):
38
- if event.mimeData().hasImage:
43
+ if event.mimeData().hasUrls():
39
44
  event.accept()
40
45
  else:
41
46
  event.ignore()
42
47
 
43
48
  def dropEvent(self, event):
44
- if event.mimeData().hasImage:
49
+ if event.mimeData().hasUrls():
45
50
  event.setDropAction(Qt.DropAction.CopyAction)
46
51
  try:
47
52
  file_path = event.mimeData().urls()[0].toLocalFile()
@@ -60,7 +65,7 @@ class DropZoneWidget(QLabel):
60
65
  default_directory = os.path.expanduser('~')
61
66
 
62
67
  fmu_filename, _ = QFileDialog.getOpenFileName(parent=self, caption='Select FMU to Manipulate',
63
- directory=default_directory, filter="FMU files (*.fmu)")
68
+ dir=default_directory, filter="FMU files (*.fmu)")
64
69
  if fmu_filename:
65
70
  self.set_fmu(fmu_filename)
66
71
 
@@ -71,7 +76,7 @@ class DropZoneWidget(QLabel):
71
76
  filename = os.path.join(os.path.dirname(__file__), "resources", "fmu.png")
72
77
 
73
78
  base_image = QImage(filename).scaled(self.WIDTH, self.HEIGHT, Qt.AspectRatioMode.IgnoreAspectRatio,
74
- Qt.TransformationMode.SmoothTransformation)
79
+ Qt.TransformationMode.SmoothTransformation)
75
80
  mask_filename = os.path.join(os.path.dirname(__file__), "resources", "mask.png")
76
81
  mask_image = QImage(mask_filename).scaled(self.WIDTH, self.HEIGHT, Qt.AspectRatioMode.IgnoreAspectRatio,
77
82
  Qt.TransformationMode.SmoothTransformation)
@@ -87,8 +92,7 @@ class DropZoneWidget(QLabel):
87
92
 
88
93
  self.setPixmap(pixmap)
89
94
 
90
-
91
- def set_fmu(self, filename):
95
+ def set_fmu(self, filename: str):
92
96
  try:
93
97
  self.last_directory = os.path.dirname(filename)
94
98
  self.fmu = FMU(filename)
@@ -104,7 +108,10 @@ class LogWidget(QTextBrowser):
104
108
  class XStream(QObject):
105
109
  _stdout = None
106
110
  _stderr = None
107
- messageWritten = pyqtSignal(str)
111
+ messageWritten = Signal(str)
112
+
113
+ def __init__(self):
114
+ super().__init__()
108
115
 
109
116
  def flush(self):
110
117
  pass
@@ -133,17 +140,10 @@ class LogWidget(QTextBrowser):
133
140
 
134
141
  def __init__(self):
135
142
  super().__init__()
136
- if os.name == 'nt':
137
- font = QFont('Consolas')
138
- font.setPointSize(10)
139
- else:
140
- font = QFont('Courier New')
141
- font.setPointSize(12)
142
- self.setFont(font)
143
- self.setMinimumWidth(800)
144
- self.setMinimumHeight(480)
145
-
146
- self.insertHtml('<center><img src="fmu_manipulation_toolbox.png"/></center><br>')
143
+ self.setMinimumWidth(900)
144
+ self.setMinimumHeight(500)
145
+ self.setSearchPaths([os.path.join(os.path.dirname(__file__), "resources")])
146
+ self.insertHtml('<center><img src="fmu_manipulation_toolbox.png"/></center><br/>')
147
147
  LogWidget.XStream.stdout().messageWritten.connect(self.insertPlainText)
148
148
  LogWidget.XStream.stderr().messageWritten.connect(self.insertPlainText)
149
149
 
@@ -175,14 +175,14 @@ class FilterWidget(QPushButton):
175
175
  self.nb_items = len(items)
176
176
  self.update_filter_text()
177
177
  if items:
178
- menu = QMenu()
178
+ self.menu = QMenu()
179
179
  for item in items:
180
180
  action = QAction(item, self)
181
181
  action.setCheckable(True)
182
182
  action.setChecked(True)
183
183
  action.triggered.connect(partial(self.toggle_item, action))
184
- menu.addAction(action)
185
- self.setMenu(menu)
184
+ self.menu.addAction(action)
185
+ self.setMenu(self.menu)
186
186
 
187
187
  def toggle_item(self, action: QAction):
188
188
  if not action.isChecked() and len(self.items_selected) == 1:
@@ -208,30 +208,201 @@ class FilterWidget(QPushButton):
208
208
  return sorted(self.items_selected)
209
209
 
210
210
 
211
- class FMUManipulationToolboxlMainWindow(QWidget):
212
- def __init__(self, *args, **kwargs):
213
- super().__init__(*args, **kwargs)
211
+ class AssemblyTreeWidget(QTreeView):
212
+ class AssemblyTreeModel(QStandardItemModel):
213
+
214
+ def __init__(self, assembly: Assembly, parent=None):
215
+ super().__init__(parent)
216
+
217
+ self.lastDroppedItems = []
218
+ self.pendingRemoveRowsAfterDrop = False
219
+ self.setHorizontalHeaderLabels(['col1'])
220
+ self.dnd_target_node: Optional[AssemblyNode] = None
221
+
222
+ self.icon_container = QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'container.png'))
223
+ self.icon_fmu = QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'icon_fmu.png'))
224
+
225
+ if assembly:
226
+ self.add_node(assembly.root, self)
227
+
228
+ def add_node(self, node: AssemblyNode, parent_item):
229
+ # Add Container
230
+ item = QStandardItem(self.icon_container, node.name)
231
+ parent_item.appendRow(item)
232
+ item.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsDragEnabled |
233
+ Qt.ItemFlag.ItemIsDropEnabled)
234
+ item.setData(node, role=Qt.ItemDataRole.UserRole + 1)
235
+ item.setData("container", role=Qt.ItemDataRole.UserRole + 2)
236
+
237
+ # Add FMU's
238
+ children_name = node.children.keys()
239
+ for fmu_name in node.fmu_names_list:
240
+ if fmu_name not in children_name:
241
+ fmu_node = QStandardItem(self.icon_fmu, fmu_name)
242
+ fmu_node.setData(node, role=Qt.ItemDataRole.UserRole + 1)
243
+ fmu_node.setData("fmu", role=Qt.ItemDataRole.UserRole + 2)
244
+ fmu_node.setFlags(Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable |
245
+ Qt.ItemFlag.ItemIsDragEnabled)
246
+ item.appendRow(fmu_node)
247
+
248
+ # Add Sub-Containers
249
+ for child in node.children.values():
250
+ self.add_node(child, item)
251
+
252
+ def insertRows(self, row, count, parent=QModelIndex()):
253
+ self.dnd_target_node = parent.data(role=Qt.ItemDataRole.UserRole + 1)
254
+ return super().insertRows(row, count, parent=parent)
255
+
256
+ def removeRows(self, row, count, parent=QModelIndex()):
257
+ if not self.dnd_target_node:
258
+ print("NO DROP NODE!?")
259
+
260
+ source_index = self.itemFromIndex(parent).child(row, 0).data(role=Qt.ItemDataRole.UserRole+1)
261
+ print(f"{source_index} ==> {self.dnd_target_node.name}")
262
+
263
+ self.dnd_target_node = None
264
+ return super().removeRows(row, count, parent)
265
+
266
+ def dropMimeData(self, data, action, row, column, parent: QModelIndex):
267
+ if parent.column() < 0: # Avoid to drop item as a sibling of the root.
268
+ return False
269
+ return super().dropMimeData(data, action, row, column, parent)
270
+
271
+ def __init__(self, parent=None):
272
+ super().__init__(parent)
273
+
274
+ self.model = self.AssemblyTreeModel(None)
275
+ self.setModel(self.model)
276
+
277
+ self.expandAll()
278
+ self.setDropIndicatorShown(True)
279
+ self.setDragDropOverwriteMode(False)
280
+ self.setAcceptDrops(True)
281
+ self.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
282
+ self.setRootIsDecorated(True)
283
+ self.setHeaderHidden(True)
284
+
285
+ def load_container(self, filename):
286
+ assembly = Assembly(filename)
287
+ self.model = self.AssemblyTreeModel(assembly)
288
+ self.setModel(self.model)
289
+
290
+ def setTopIndex(self):
291
+ topIndex = self.model.index(0, 0, self.rootIndex())
292
+ print(topIndex.isValid(), topIndex.model())
293
+ if topIndex.isValid():
294
+ self.setCurrentIndex(topIndex)
295
+ if self.layoutCheck:
296
+ self.model.layoutChanged.disconnect(self.setTopIndex)
297
+ else:
298
+ if not self.layoutCheck:
299
+ self.model.layoutChanged.connect(self.setTopIndex)
300
+ self.layoutCheck = True
301
+
302
+
303
+ def dragEnterEvent2(self, event):
304
+ if event.mimeData().hasImage:
305
+ event.accept()
306
+ else:
307
+ event.ignore()
308
+
309
+ def dragMoveEvent2(self, event):
310
+ if event.mimeData().hasImage:
311
+ event.accept()
312
+ else:
313
+ event.ignore()
314
+
315
+ def dropEvent2(self, event):
316
+ if event.mimeData().hasImage:
317
+ event.setDropAction(Qt.DropAction.CopyAction)
318
+ try:
319
+ file_path = event.mimeData().urls()[0].toLocalFile()
320
+ except IndexError:
321
+ print("Please select a regular file.")
322
+ return
323
+ print(f"DROP: {file_path}")
324
+ event.accept()
325
+ else:
326
+ event.ignore()
327
+
328
+
329
+ class AssemblPropertiesWidget(QWidget):
330
+ def __init__(self, parent=None):
331
+ super().__init__(parent)
332
+
333
+ self.layout = QGridLayout()
334
+ self.layout.setVerticalSpacing(4)
335
+ self.layout.setHorizontalSpacing(4)
336
+ self.layout.setContentsMargins(10, 10, 10, 10)
337
+ self.setLayout(self.layout)
214
338
 
215
- self.setWindowTitle('FMU Manipulation Toolbox')
339
+ mt_check = QCheckBox("Multi-Threaded", self)
340
+ self.layout.addWidget(mt_check, 1, 0)
341
+
342
+ profiling_check = QCheckBox("Profiling", self)
343
+ self.layout.addWidget(profiling_check, 1, 1)
344
+
345
+ auto_inputs_check = QCheckBox("Auto Inputs", self)
346
+ self.layout.addWidget(auto_inputs_check, 0, 0)
347
+
348
+ auto_outputs_check = QCheckBox("Auto Outputs", self)
349
+ self.layout.addWidget(auto_outputs_check, 0, 1)
350
+
351
+ auto_links_check = QCheckBox("Auto Links", self)
352
+ self.layout.addWidget(auto_links_check, 0, 2)
353
+
354
+
355
+ class AssemblyTabWidget(QTabWidget):
356
+ def __init__(self, parent=None):
357
+ super().__init__(parent)
358
+
359
+ table = AssemblPropertiesWidget(parent=self)
360
+ self.addTab(table, "Properties")
361
+ table = QTableView()
362
+ self.addTab(table, "Links")
363
+ table = QTableView()
364
+ self.addTab(table, "Inputs")
365
+ table = QTableView()
366
+ self.addTab(table, "Outputs")
367
+ table = QTableView()
368
+ self.addTab(table, "Start values")
369
+
370
+ self.tabBar().setDocumentMode(True)
371
+ self.tabBar().setExpanding(True)
372
+
373
+
374
+ class WindowWithLayout(QWidget):
375
+ def __init__(self, title: str):
376
+ super().__init__(None) # Do not set parent to have a separated window
377
+ self.setWindowTitle(title)
216
378
 
217
- # set the grid layout
218
379
  self.layout = QGridLayout()
219
380
  self.layout.setVerticalSpacing(4)
220
381
  self.layout.setHorizontalSpacing(4)
221
382
  self.layout.setContentsMargins(10, 10, 10, 10)
222
383
  self.setLayout(self.layout)
223
384
 
385
+
386
+ class MainWindow(WindowWithLayout):
387
+ def __init__(self):
388
+ super().__init__('FMU Manipulation Toolbox')
389
+
224
390
  self.dropped_fmu = DropZoneWidget()
225
391
  self.dropped_fmu.clicked.connect(self.update_fmu)
392
+
226
393
  self.layout.addWidget(self.dropped_fmu, 0, 0, 4, 1)
227
394
 
228
- font = QFont('Verdana')
229
- font.setPointSize(14)
230
- font.setBold(True)
231
395
  self.fmu_title = QLabel()
232
- self.fmu_title.setFont(font)
396
+ self.fmu_title.setProperty("class", "title")
233
397
  self.layout.addWidget(self.fmu_title, 0, 1, 1, 4)
234
398
 
399
+ self.container_window = None
400
+ #TODO: Container Window
401
+ #container_button = QPushButton("Make a container")
402
+ #container_button.setProperty("class", "quit")
403
+ #container_button.clicked.connect(self.launch_container)
404
+ #self.layout.addWidget(container_button, 4, 1, 1, 1)
405
+
235
406
  help_widget = HelpWidget()
236
407
  self.layout.addWidget(help_widget, 0, 5, 1, 1)
237
408
 
@@ -267,8 +438,8 @@ class FMUManipulationToolboxlMainWindow(QWidget):
267
438
  self.add_operation(operation[0], operation[1], operation[2], operation[3], line, col, **operation[4])
268
439
 
269
440
  line += 1
270
- self.apply_filter_label = QLabel("Apply modification only on: ")
271
- self.layout.addWidget(self.apply_filter_label, line, 1, 1, 2, alignment=Qt.AlignmentFlag.AlignRight)
441
+ self.apply_filter_label = QLabel("Apply only on: ")
442
+ self.layout.addWidget(self.apply_filter_label, line, 2, 1, 1, alignment=Qt.AlignmentFlag.AlignRight)
272
443
  self.set_tooltip(self.apply_filter_label, 'gui-apply-only')
273
444
 
274
445
  causality = ["parameter", "calculatedParameter", "input", "output", "local", "independent"]
@@ -308,6 +479,19 @@ class FMUManipulationToolboxlMainWindow(QWidget):
308
479
  # show the window
309
480
  self.show()
310
481
 
482
+ def closeEvent(self, event):
483
+ if self.container_window:
484
+ self.container_window.close()
485
+ self.container_window = None
486
+ event.accept()
487
+
488
+ def launch_container(self):
489
+ if not self.container_window:
490
+ self.container_window = ContainerWindow(self)
491
+
492
+ def closing_container(self):
493
+ self.container_window = None
494
+
311
495
  def set_tooltip(self, widget, usage):
312
496
  widget.setToolTip("\n".join(textwrap.wrap(self.help.usage(usage))))
313
497
 
@@ -385,7 +569,7 @@ class FMUManipulationToolboxlMainWindow(QWidget):
385
569
  self.layout.addWidget(button, x, y)
386
570
 
387
571
  def prompt_string(self, message):
388
- text, ok = QInputDialog().getText(self, "Enter value", f"{message}:", QLineEdit.Normal, "")
572
+ text, ok = QInputDialog().getText(self, "Enter value", f"{message}:", QLineEdit.EchoMode.Normal, "")
389
573
 
390
574
  if ok and text:
391
575
  return text
@@ -436,6 +620,101 @@ class FMUManipulationToolboxlMainWindow(QWidget):
436
620
  scroll_bar.setValue(scroll_bar.maximum())
437
621
 
438
622
 
623
+ class ContainerWindow(WindowWithLayout):
624
+ def __init__(self, parent: MainWindow):
625
+ super().__init__('FMU Manipulation Toolbox - Container')
626
+ self.main_window = parent
627
+ self.last_directory = None
628
+
629
+ # ROW 0
630
+ load_button = QPushButton("Load Description")
631
+ load_button.clicked.connect(self.load_container)
632
+ load_button.setProperty("class", "quit")
633
+ self.layout.addWidget(load_button, 0, 0)
634
+
635
+ self.container_label = QLabel()
636
+ self.container_label.setProperty("class", "title")
637
+ self.container_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
638
+ self.layout.addWidget(self.container_label, 0, 1, 1, 2)
639
+
640
+ # ROW 1
641
+ add_fmu_button = QPushButton("Add FMU")
642
+ add_fmu_button.setProperty("class", "modify")
643
+ add_fmu_button.setDisabled(True)
644
+ self.layout.addWidget(add_fmu_button, 1, 1)
645
+
646
+ add_sub_button = QPushButton("Add SubContainer")
647
+ add_sub_button.setProperty("class", "modify")
648
+ add_sub_button.setDisabled(True)
649
+ self.layout.addWidget(add_sub_button, 1, 2)
650
+
651
+ self.assembly_tree = AssemblyTreeWidget(parent=self)
652
+ self.assembly_tree.setMinimumHeight(600)
653
+ self.assembly_tree.setMinimumWidth(200)
654
+ self.layout.addWidget(self.assembly_tree, 1, 0, 3, 1)
655
+
656
+ # ROW 2
657
+ del_fmu_button = QPushButton("Remove FMU")
658
+ del_fmu_button.setProperty("class", "removal")
659
+ del_fmu_button.setDisabled(True)
660
+ self.layout.addWidget(del_fmu_button, 2, 1)
661
+
662
+ del_sub_button = QPushButton("Remove SubContainer")
663
+ del_sub_button.setProperty("class", "removal")
664
+ del_sub_button.setDisabled(True)
665
+ self.layout.addWidget(del_sub_button, 2, 2)
666
+
667
+ # ROW 3
668
+ self.assembly_tab = AssemblyTabWidget(parent=self)
669
+ self.assembly_tab.setMinimumWidth(600)
670
+ self.layout.addWidget(self.assembly_tab, 3, 1, 1, 2)
671
+
672
+ # ROW 4
673
+ close_button = QPushButton("Close")
674
+ close_button.setProperty("class", "quit")
675
+ close_button.clicked.connect(self.close)
676
+ self.layout.addWidget(close_button, 4, 0)
677
+
678
+ save_button = QPushButton("Save Container")
679
+ save_button.setProperty("class", "save")
680
+ self.layout.addWidget(save_button, 4, 2)
681
+
682
+ self.assembly_tree.selectionModel().currentChanged.connect(self.item_selected)
683
+ topIndex = self.assembly_tree.model.index(0, 0, self.assembly_tree.rootIndex())
684
+ self.assembly_tree.setCurrentIndex(topIndex)
685
+
686
+ self.show()
687
+
688
+ def closeEvent(self, event):
689
+ if self.main_window:
690
+ self.main_window.closing_container()
691
+ event.accept()
692
+
693
+ def item_selected(self, current: QModelIndex, previous: QModelIndex):
694
+ if current.isValid():
695
+ node = current.data(role=Qt.ItemDataRole.UserRole + 1)
696
+ node_type = current.data(role=Qt.ItemDataRole.UserRole + 2)
697
+ self.container_label.setText(f"{node.name} ({node_type})")
698
+ else:
699
+ self.container_label.setText("")
700
+
701
+ def load_container(self):
702
+ if self.last_directory:
703
+ default_directory = self.last_directory
704
+ else:
705
+ default_directory = os.path.expanduser('~')
706
+
707
+ filename, _ = QFileDialog.getOpenFileName(parent=self, caption='Select FMU to Manipulate',
708
+ dir=default_directory,
709
+ filter="JSON files (*.json);;SSP files (*.ssp)")
710
+ if filename:
711
+ try:
712
+ self.last_directory = os.path.dirname(filename)
713
+ self.assembly_tree.load_container(filename)
714
+ except Exception as e:
715
+ print(e)
716
+
717
+
439
718
  class Application(QApplication):
440
719
  """
441
720
  Analyse and modify your FMUs.
@@ -446,55 +725,23 @@ Communicating with the FMU-developer and adapting the way the FMU is generated,
446
725
  """
447
726
  def __init__(self, *args, **kwargs):
448
727
  super().__init__(*args, **kwargs)
728
+ self.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.RoundPreferFloor)
449
729
 
450
730
  QDir.addSearchPath('images', os.path.join(os.path.dirname(__file__), "resources"))
451
- font = QFont("Verdana")
452
- font.setPointSize(10)
453
- self.setFont(font)
454
- css_dark = """
455
- QWidget {background: #4b4e51; color: #b5bab9}
456
- QPushButton { min-height: 30px; padding: 1px 1px 0.2em 0.2em; border: 1px solid #282830; border-radius: 5px;}
457
- QComboBox { min-height: 30px; padding: 1px 1px 0.2em 0.2em; border: 1px solid #282830; border-radius: 5px;}
458
- QPushButton:pressed { border: 2px solid #282830; }
459
- QPushButton.info {background-color: #4e6749; color: #dddddd;}
460
- QPushButton.info:hover {background-color: #5f7850; color: #dddddd;}
461
- QPushButton.info:hover {background-color: #5f7850; color: #dddddd;}
462
- QPushButton.modify {background-color: #98763f; color: #dddddd;}
463
- QPushButton.modify:hover {background-color: #a9874f; color: #dddddd;}
464
- QPushButton.removal {background-color: #692e2e; color: #dddddd;}
465
- QPushButton.removal:hover{background-color: #7a3f3f; color: #dddddd;}
466
- QPushButton.save {background-color: #564967; color: #dddddd;}
467
- QPushButton.save:hover {background-color: #675a78; color: #dddddd;}
468
- QPushButton.quit {background-color: #4571a4; color: #dddddd;}
469
- QPushButton.quit:hover {background-color: #5682b5; color: #dddddd;}
470
- QToolTip {color: black}
471
- QLabel.dropped_fmu {background-color: #b5bab9}
472
- QLabel.dropped_fmu:hover {background-color: #c6cbca}
473
- QTextBrowser {background-color: #282830; color: #b5bab9;}
474
- QMenu {font-size: 18px;}
475
- QMenu::item {padding: 2px 250px 2px 20px; border: 1px solid transparent;}
476
- QMenu::item::indicator {width: 32px; height: 32px; }
477
- QMenu::indicator:checked {image: url(images:checkbox-checked.png);}
478
- QMenu::indicator:checked:hover {image: url(images:checkbox-checked-hover.png);}
479
- QMenu::indicator:checked:disabled {image: url(images:checkbox-checked-disabled.png);}
480
- QMenu::indicator:unchecked {IconWidth: 50px; image: url(images:checkbox-unchecked.png); }
481
- QMenu::indicator:unchecked:hover {width: 35px; image: url(images:checkbox-unchecked-hover.png); }
482
- QMenu::indicator:unchecked:disabled {width: 35px; image: url(images:checkbox-unchecked-disabled.png); }
483
- """
484
-
485
- self.setStyleSheet(css_dark)
731
+ self.setStyleSheet(gui_style_dark)
486
732
 
487
733
  if os.name == 'nt':
734
+ import ctypes
488
735
  self.setWindowIcon(QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'icon-round.png')))
489
736
 
490
737
  # https://stackoverflow.com/questions/1551605/how-to-set-applications-taskbar-icon-in-windows-7/1552105#1552105
491
- import ctypes
738
+
492
739
  application_id = 'FMU_Manipulation_Toolbox' # arbitrary string
493
740
  ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(application_id)
494
741
  else:
495
742
  self.setWindowIcon(QIcon(os.path.join(os.path.dirname(__file__), 'resources', 'icon.png')))
496
743
 
497
- self.window = FMUManipulationToolboxlMainWindow()
744
+ self.window = MainWindow()
498
745
 
499
746
 
500
747
  def main():
@@ -504,3 +751,7 @@ def main():
504
751
  print(application.__doc__)
505
752
 
506
753
  sys.exit(application.exec())
754
+
755
+
756
+ if __name__ == "__main__":
757
+ main()
@@ -0,0 +1,129 @@
1
+ # if os.name == 'nt':
2
+ # font = QFont('Consolas')
3
+ # font.setPointSize(11)
4
+ # else:
5
+ # font = QFont('Courier New')
6
+ # font.setPointSize(12)
7
+ # self.setFont(font)
8
+
9
+
10
+ gui_style_dark = """
11
+ QWidget {
12
+ font: 10pt "Verdana";
13
+ background: #4b4e51;
14
+ color: #b5bab9;
15
+ }
16
+ QPushButton, QComboBox {
17
+ min-height: 30px;
18
+ padding: 1px 1px 0.2em 0.2em;
19
+ border: 1px solid #282830;
20
+ border-radius: 5px;
21
+ color: #dddddd;
22
+ }
23
+ QPushButton:pressed {
24
+ border: 2px solid #282830;
25
+ }
26
+ QPushButton.info {
27
+ background-color: #4e6749;
28
+ }
29
+ QPushButton.info:hover {
30
+ background-color: #5f7850;
31
+ }
32
+ QPushButton.modify {
33
+ background-color: #98763f;
34
+ }
35
+ QPushButton.modify:hover {
36
+ background-color: #a9874f;
37
+ }
38
+ QPushButton.removal {
39
+ background-color: #692e2e;
40
+ }
41
+ QPushButton.removal:hover {
42
+ background-color: #7a3f3f;
43
+ }
44
+ QPushButton.save {
45
+ background-color: #564967;
46
+ }
47
+ QPushButton.save:hover {
48
+ background-color: #675a78;
49
+ }
50
+ QPushButton.quit {
51
+ background-color: #4571a4;
52
+ }
53
+ QPushButton.quit:hover {
54
+ background-color: #5682b5;
55
+ }
56
+ QPushButton::disabled {
57
+ background-color: gray;
58
+ }
59
+ QToolTip {
60
+ color: black
61
+ }
62
+ QLabel.dropped_fmu {
63
+ background-color: #b5bab9
64
+ }
65
+ QLabel.title {
66
+ font: 14pt bold "Verdana";
67
+ }
68
+ QLabel.dropped_fmu:hover {
69
+ background-color: #c6cbca
70
+ }
71
+ QTextBrowser, QTreeView {
72
+ font: 11pt "Consolas";
73
+ background-color: #282830;
74
+ color: #b5bab9;
75
+ }
76
+ QMenu::item {
77
+ padding: 2px 250px 2px 20px;
78
+ border: 1px solid transparent;
79
+ }
80
+ QMenu::item::indicator, QCheckBox::item::indicator {
81
+ width: 32px;
82
+ height: 32px;
83
+ }
84
+ QMenu::indicator:checked, QCheckBox::indicator:checked {
85
+ image: url(images:checkbox-checked.png);
86
+ }
87
+ QMenu::indicator:checked:hover, QCheckBox::indicator:checked:hover {
88
+ image: url(images:checkbox-checked-hover.png);
89
+ }
90
+ QMenu::indicator:checked:disabled, QCheckBox::indicator:checked:disabled {
91
+ image: url(images:checkbox-checked-disabled.png);
92
+ }
93
+ QMenu::indicator:unchecked, QCheckBox::indicator:unchecked {
94
+ image: url(images:checkbox-unchecked.png);
95
+ }
96
+ QMenu::indicator:unchecked:hover, QCheckBox::indicator:unchecked:hover {
97
+ image: url(images:checkbox-unchecked-hover.png);
98
+ }
99
+ QMenu::indicator:unchecked:disabled, QCheckBox::indicator:unchecked:disabled {
100
+ image: url(images:checkbox-unchecked-disabled.png);
101
+ }
102
+ QCheckBox::item {
103
+ padding: 2px 250px 2px 20px;
104
+ border: 1px solid transparent;
105
+ }
106
+ QTabBar::tab {
107
+ min-height: 30px;
108
+ padding: 1px 1px 0.2em 0.2em;
109
+ color: #dddddd;
110
+ margin: 2px;
111
+ margin-bottom: 0px;
112
+ border: 1px solid #282830;
113
+ border-top-left-radius: 5px;
114
+ border-top-right-radius: 5px;
115
+ }
116
+ QTabBar::tab:selected, QTabBar::tab:hover {
117
+ background-color: #5f7850;
118
+ margin-bottom:-1px;
119
+ }
120
+ QTabBar {
121
+ border-bottom: 1px solid #282830;
122
+ }
123
+ QTabBar::tab:top:last, QTabBar::tab:bottom:last {
124
+ margin-right: 0;
125
+ }
126
+ QTabBar::tab:top:first, QTabBar::tab:bottom:first {
127
+ margin-left: 0;
128
+ }
129
+ """
Binary file