diff --git a/src/minder3d/lib/sovImageTablePanelWidget.py b/src/minder3d/lib/sovImageTablePanelWidget.py index 51bb68d..a55627d 100644 --- a/src/minder3d/lib/sovImageTablePanelWidget.py +++ b/src/minder3d/lib/sovImageTablePanelWidget.py @@ -15,6 +15,7 @@ class ImageTablePanelWidget(QWidget, Ui_ImageTablePanelWidget): + @time_and_log def __init__(self, gui, state, parent=None): """Initialize the GUI and state for the application. diff --git a/src/minder3d/lib/sovInfoTablePanelWidget.py b/src/minder3d/lib/sovInfoTablePanelWidget.py index f848598..7ba9a95 100644 --- a/src/minder3d/lib/sovInfoTablePanelWidget.py +++ b/src/minder3d/lib/sovInfoTablePanelWidget.py @@ -5,6 +5,7 @@ class InfoTablePanelWidget(QWidget, Ui_InfoTablePanelWidget): + @time_and_log def __init__(self, gui, state, parent=None): """Initialize the GUI and state for the parent widget. @@ -13,7 +14,6 @@ def __init__(self, gui, state, parent=None): state: The state object. parent: The parent widget (default is None). """ - super().__init__(parent) self.setupUi(self) diff --git a/src/minder3d/lib/sovObjectPanelWidget.py b/src/minder3d/lib/sovObjectPanelWidget.py new file mode 100644 index 0000000..f278517 --- /dev/null +++ b/src/minder3d/lib/sovObjectPanelWidget.py @@ -0,0 +1,339 @@ +""" +""" + +import numpy as np +from PySide6.QtWidgets import QInputDialog, QWidget + +from .sovColorMapUtils import get_nearest_color_index_and_name +from .sovUtils import get_children_as_list, time_and_log +from .ui_sovObjectPanelWidget import Ui_ObjectPanelWidget + + +class ObjectPanelWidget(QWidget, Ui_ObjectPanelWidget): + @time_and_log + def __init__(self, gui, state, parent=None): + """Initialize the GUI and state for the application. + + Args: + gui: The graphical user interface object. + state: The state object for the application. + parent: The parent widget (default is None). + """ + super().__init__(parent) + self.setupUi(self) + + self.gui = gui + self.state = state + + self.update_gui = True + + for color_name, _ in self.state.colormap.items(): + self.objectColorComboBox.addItem(color_name) + + self.objectHighlightSelectedObjectsCheckBox.stateChanged.connect( + self.update_highlight_selected + ) + + self.objectUnselectAllButton.pressed.connect(self.unselect_all_objects) + + self.objectRenameButton.pressed.connect(self.rename_selected_object) + + self.objectDeleteButton.pressed.connect(self.delete_selected_objects) + self.objectPropertiesToAllButton.pressed.connect( + self.propogate_properties_to_all + ) + self.objectPropertiesToChildrenButton.pressed.connect( + self.propogate_properties_to_children + ) + self.objectPropertiesToSimilarButton.pressed.connect( + self.propogate_properties_to_similar + ) + + self.objectNameComboBox.currentIndexChanged.connect( + self.select_object_by_name_combobox + ) + + self.objectColorByComboBox.currentIndexChanged.connect( + self.modify_selected_objects + ) + + self.objectColorComboBox.currentIndexChanged.connect( + self.modify_selected_objects + ) + + self.objectOpacitySlider.valueChanged.connect( + self.modify_selected_objects + ) + + @time_and_log + def update_scene(self): + self.update_gui = False + + self.objectNameComboBox.clear() + self.objectNameComboBox.addItem('None') + for so in self.state.scene_list: + self.objectNameComboBox.addItem( + str(so.GetProperty().GetTagStringValue('Name')) + ) + + self.update_gui = True + + @time_and_log + def update_highlight_selected(self, value): + """Update the highlight selected state and redraw the selected objects. + + Args: + value (bool): The new value for the highlight selected state. + """ + self.state.highlight_selected = value + for selected_id in self.state.selected_ids: + self.log(f'update_highlight_selected: Id={selected_id}') + so = self.state.scene_list[ + self.state.scene_list_ids.index(selected_id) + ] + self.gui.redraw_object(so) + + @time_and_log + def unselect_all_objects(self): + """Unselect all objects in the scene. + + This function unselects all objects in the scene by removing them + from selected_ids and selected_point_ids. + """ + for selected_idx, selected_so_id in enumerate(self.state.selected_ids): + if selected_so_id != -1: + scene_idx = self.state.scene_list_ids.index(selected_so_id) + self.state.selected_ids[selected_idx] = -1 + selected_so = self.state.scene_list[scene_idx] + self.redraw_object(selected_so) + self.state.selected_ids = [] + self.state.selected_point_ids = [] + + self.update_gui = False + + self.objectNameComboBox.setCurrentIndex(0) + + self.update_gui = True + + @time_and_log + def select_object_by_name_combobox(self, idx): + if self.update_gui is False: + return + + so = None + so_id = -2 + if idx > 0: + idx -= 1 + so = self.state.scene_list[idx] + so_id = so.GetId() + # Unselect currently selected objects + for selected_idx, selected_so_id in enumerate(self.state.selected_ids): + if selected_so_id != -1 and selected_so_id != so_id: + scene_idx = self.state.scene_list_ids.index(selected_so_id) + selected_so = self.state.scene_list[scene_idx] + self.state.selected_ids[selected_idx] = -1 + self.gui.redraw_object(selected_so) + if so_id != -2: + self.state.selected_ids = [so_id] + self.state.selected_point_ids = [0] + self.gui.redraw_object(so) + + @time_and_log + def redraw_object(self, so): + """Redraws the specified object in the scene. + + This method updates the visual representation of the specified object in the 2D and 3D views if the corresponding + update flags are set to True. It also updates the object's properties in the GUI. + + Args: + self: The object instance. + so: The object to be redrawn. + update_2D (bool): Flag indicating whether to update the 2D view (default is True). + update_3D (bool): Flag indicating whether to update the 3D view (default is True). + """ + so_id = so.GetId() + if so_id not in self.state.scene_list_ids: + self.log('ERROR: so_id not in scene_list_ids', 'error') + return + scene_idx = self.state.scene_list_ids.index(so_id) + + self.update_gui = False + + self.objectNameComboBox.setCurrentIndex(scene_idx + 1) + + c = so.GetProperty().GetColor() + color = [c.GetRed(), c.GetGreen(), c.GetBlue(), c.GetAlpha()] + color[0:3] = np.array(color)[0:3] * self.state.colormap_scale_factor + color[3] = color[3] * 100.0 + self.objectOpacitySlider.setValue(color[3]) + _, color_name = get_nearest_color_index_and_name( + color[0:3], self.state.colormap + ) + self.objectColorComboBox.setCurrentText(color_name) + + self.objectColorByComboBox.clear() + self.objectColorByComboBox.addItem('Solid Color') + actor = self.state.scene_list_properties[scene_idx].get('Actor') + if actor is not None: + pdata = actor.GetMapper().GetInput() + for i in range(pdata.GetPointData().GetNumberOfArrays()): + pname = pdata.GetPointData().GetArrayName(i) + self.objectColorByComboBox.addItem(pname) + + self.objectColorByComboBox.setCurrentText( + self.state.scene_list_properties[scene_idx]['ColorBy'] + ) + + self.update_gui = True + + @time_and_log + def modify_selected_objects(self, _): + """Modify the selected objects in the scene with new color and properties. + + This function modifies the color and properties of the selected objects in the scene based on the current state + of the application. It updates the color, opacity, and color-by property of the selected objects. + + Args: + self: The instance of the class. + """ + if self.update_gui is False: + return + + for so_id in self.state.selected_ids: + scene_idx = self.state.scene_list_ids.index(so_id) + so = self.state.scene_list[scene_idx] + color = np.empty(4) + color[0:3] = self.state.colormap[ + self.objectColorComboBox.currentText() + ] + color[0:3] /= self.state.colormap_scale_factor + color[3] = self.objectOpacitySlider.value() / 100.0 + so.GetProperty().SetColor(color) + self.state.scene_list_properties[scene_idx][ + 'ColorBy' + ] = self.objectColorByComboBox.currentText() + + self.gui.redraw_object(so) + + @time_and_log + def rename_selected_object(self): + """Propagate properties to similar objects in the scene. + + This function updates the properties of all objects in the scene based + on the current settings. + + Args: + self: The current instance of the class. + """ + if len(self.state.selected_ids) == 0: + return + so_id = self.state.selected_ids[-1] + so_name = ( + self.state.scene_list[so_id].GetProperty().GetTagStringValue('Name') + ) + dlg = QInputDialog(self) + dlg.setInputMode(QInputDialog.TextInput) + dlg.setLabelText('New name:') + dlg.resize(500, 100) + dlg.setTextValue(so_name) + valid = dlg.exec_() + so_name = dlg.textValue() + if not valid: + return False + self.state.scene_list[so_id].SetName(so_name) + + @time_and_log + def delete_selected_objects(self): + """Delete the selected objects from the scene. + + This function deletes the selected objects from the scene by removing them from the scene list and updating the GUI accordingly. + """ + for so_id in self.state.selected_ids: + print('deleting so_id:', so_id) + scene_idx = self.state.scene_list_ids.index(so_id) + so = self.state.scene_list[scene_idx] + so_parent = so.GetParent() + so_parent.RemoveChild(so) + self.state.scene_list.pop(scene_idx) + self.state.scene_list_properties.pop(scene_idx) + self.state.selected_ids = [] + self.state.selected_point_ids = [] + + self.update_gui = False + + self.objectNameComboBox.clear() + self.objectNameComboBox.addItem('None') + for so in self.state.scene_list: + self.objectNameComboBox.addItem(f'{so.GetTypeName()} {so.GetId()}') + + self.update_gui = True + + self.update_scene() + + @time_and_log + def propogate_properties_to_all(self): + """Propagate properties to all objects in the scene. + + This function updates the properties of all objects in the scene based on the current settings. + + Args: + self: The current instance of the class. + """ + color_by = self.objectColorByComboBox.currentText() + color = np.empty(4) + color[0:3] = self.state.colormap[self.objectColorComboBox.currentText()] + color[0:3] /= self.state.colormap_scale_factor + color[3] = self.objectOpacitySlider.value() / 100.0 + for idx in range(len(self.state.scene_list)): + self.state.scene_list_properties[idx]['ColorBy'] = color_by + self.state.scene_list[idx].GetProperty().SetColor(color) + self.redraw_object(self.state.scene_list[idx]) + + @time_and_log + def propogate_properties_to_similar(self): + """Propagate properties to similar objects in the scene. + + This function updates the properties of all objects in the scene based + on the current settings. + + Args: + self: The current instance of the class. + """ + if len(self.state.selected_ids) == 0: + return + so_id = int(self.state.selected_ids[-1]) + so_type = self.state.scene_list[so_id].GetTypeName() + color_by = self.objectColorByComboBox.currentText() + color = np.empty(4) + color[0:3] = self.state.colormap[self.objectColorComboBox.currentText()] + color[0:3] /= self.state.colormap_scale_factor + color[3] = self.objectOpacitySlider.value() / 100.0 + for idx in range(len(self.state.scene_list)): + if self.state.scene_list[idx].GetTypeName() == so_type: + self.state.scene_list_properties[idx]['ColorBy'] = color_by + self.state.scene_list[idx].GetProperty().SetColor(color) + self.redraw_object(self.state.scene_list[idx]) + + @time_and_log + def propogate_properties_to_children(self): + """Propagate properties to the children objects. + + This function propagates the selected properties to the children + objects in the scene. + """ + for so_id in self.state.selected_ids: + scene_idx = self.state.scene_list_ids.index(so_id) + so = self.state.scene_list[scene_idx] + color_by = self.objectColorByComboBox.currentText() + color = np.empty(4) + color[0:3] = self.state.colormap[ + self.objectColorComboBox.currentText() + ] + color[0:3] /= self.state.colormap_scale_factor + color[3] = self.objectOpacitySlider.value() / 100.0 + children = get_children_as_list(so) + for child_so in children: + idx = self.state.scene_list.index(child_so) + self.state.scene_list_properties[idx]['ColorBy'] = color_by + self.state.scene_list[idx].GetProperty().SetColor(color) + self.redraw_object(child_so) diff --git a/src/minder3d/lib/sovObjectPanelWidget.ui b/src/minder3d/lib/sovObjectPanelWidget.ui new file mode 100644 index 0000000..c2c2643 --- /dev/null +++ b/src/minder3d/lib/sovObjectPanelWidget.ui @@ -0,0 +1,214 @@ + + + ObjectPanelWidget + + + + 0 + 0 + 290 + 222 + + + + + 0 + 0 + + + + + 290 + 222 + + + + Form + + + + + 0 + 0 + 285 + 221 + + + + + 0 + 0 + + + + + + + + 7 + + + + Unselect All + + + + + + + + 5 + + + + 100 + + + 50 + + + Qt::Horizontal + + + + + + + Visualization: + + + + + + + + 7 + + + + Children + + + + + + + + + + + + + + + + + + + + + + + + + + + Solid Color: + + + + + + + Object: + + + + + + + Highlight Selected + + + true + + + + + + + + 7 + + + + Rename + + + + + + + Opacity: + + + + + + + + + + + + + + + + + + 7 + + + + Similar + + + + + + + + 7 + + + + All + + + + + + + + 7 + + + + Delete + + + + + + + Propogate vizualization properties to: + + + + + + + + + diff --git a/src/minder3d/lib/sovView3DPanelWidget.py b/src/minder3d/lib/sovView3DPanelWidget.py index 348f6d8..7158127 100644 --- a/src/minder3d/lib/sovView3DPanelWidget.py +++ b/src/minder3d/lib/sovView3DPanelWidget.py @@ -9,6 +9,7 @@ class View3DPanelWidget(QWidget, Ui_View3DPanelWidget): + @time_and_log def __init__(self, gui, state, parent=None): super().__init__(parent) self.setupUi(self) diff --git a/src/minder3d/lib/sovWelcomePanelWidget.py b/src/minder3d/lib/sovWelcomePanelWidget.py index aa21a67..bc94009 100644 --- a/src/minder3d/lib/sovWelcomePanelWidget.py +++ b/src/minder3d/lib/sovWelcomePanelWidget.py @@ -1,10 +1,12 @@ from PySide6.QtGui import QColor, QPalette from PySide6.QtWidgets import QWidget +from .sovUtils import time_and_log from .ui_sovWelcomePanelWidget import Ui_WelcomePanelWidget class WelcomePanelWidget(QWidget, Ui_WelcomePanelWidget): + @time_and_log def __init__(self, gui, state, parent=None): """Initialize the GUI and state for the application. diff --git a/src/minder3d/lib/ui_sovObjectPanelWidget.py b/src/minder3d/lib/ui_sovObjectPanelWidget.py new file mode 100644 index 0000000..d5cba32 --- /dev/null +++ b/src/minder3d/lib/ui_sovObjectPanelWidget.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'sovObjectPanelWidgetFfXnUi.ui' +## +## Created by: Qt User Interface Compiler version 6.5.0 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QGridLayout, + QLabel, QPushButton, QSizePolicy, QSlider, + QWidget) + +class Ui_ObjectPanelWidget(object): + def setupUi(self, ObjectPanelWidget): + if not ObjectPanelWidget.objectName(): + ObjectPanelWidget.setObjectName(u"ObjectPanelWidget") + ObjectPanelWidget.resize(290, 222) + sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(ObjectPanelWidget.sizePolicy().hasHeightForWidth()) + ObjectPanelWidget.setSizePolicy(sizePolicy) + ObjectPanelWidget.setMinimumSize(QSize(290, 222)) + self.gridLayoutWidget = QWidget(ObjectPanelWidget) + self.gridLayoutWidget.setObjectName(u"gridLayoutWidget") + self.gridLayoutWidget.setGeometry(QRect(0, 0, 285, 221)) + sizePolicy1 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) + sizePolicy1.setHorizontalStretch(0) + sizePolicy1.setVerticalStretch(0) + sizePolicy1.setHeightForWidth(self.gridLayoutWidget.sizePolicy().hasHeightForWidth()) + self.gridLayoutWidget.setSizePolicy(sizePolicy1) + self.gridLayout = QGridLayout(self.gridLayoutWidget) + self.gridLayout.setObjectName(u"gridLayout") + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.objectUnselectAllButton = QPushButton(self.gridLayoutWidget) + self.objectUnselectAllButton.setObjectName(u"objectUnselectAllButton") + font = QFont() + font.setPointSize(7) + self.objectUnselectAllButton.setFont(font) + + self.gridLayout.addWidget(self.objectUnselectAllButton, 0, 2, 1, 1) + + self.objectOpacitySlider = QSlider(self.gridLayoutWidget) + self.objectOpacitySlider.setObjectName(u"objectOpacitySlider") + font1 = QFont() + font1.setPointSize(5) + self.objectOpacitySlider.setFont(font1) + self.objectOpacitySlider.setMaximum(100) + self.objectOpacitySlider.setValue(50) + self.objectOpacitySlider.setOrientation(Qt.Horizontal) + + self.gridLayout.addWidget(self.objectOpacitySlider, 3, 1, 1, 2) + + self.objectColorByLabel = QLabel(self.gridLayoutWidget) + self.objectColorByLabel.setObjectName(u"objectColorByLabel") + + self.gridLayout.addWidget(self.objectColorByLabel, 4, 0, 1, 1) + + self.objectPropertiesToChildrenButton = QPushButton(self.gridLayoutWidget) + self.objectPropertiesToChildrenButton.setObjectName(u"objectPropertiesToChildrenButton") + self.objectPropertiesToChildrenButton.setFont(font) + + self.gridLayout.addWidget(self.objectPropertiesToChildrenButton, 7, 0, 1, 1) + + self.objectNameComboBox = QComboBox(self.gridLayoutWidget) + self.objectNameComboBox.setObjectName(u"objectNameComboBox") + + self.gridLayout.addWidget(self.objectNameComboBox, 1, 1, 1, 2) + + self.objectColorByComboBox = QComboBox(self.gridLayoutWidget) + self.objectColorByComboBox.setObjectName(u"objectColorByComboBox") + + self.gridLayout.addWidget(self.objectColorByComboBox, 4, 1, 1, 2) + + self.objectColorLabel = QLabel(self.gridLayoutWidget) + self.objectColorLabel.setObjectName(u"objectColorLabel") + + self.gridLayout.addWidget(self.objectColorLabel, 5, 1, 1, 1) + + self.objectNameLabel = QLabel(self.gridLayoutWidget) + self.objectNameLabel.setObjectName(u"objectNameLabel") + + self.gridLayout.addWidget(self.objectNameLabel, 1, 0, 1, 1) + + self.objectHighlightSelectedObjectsCheckBox = QCheckBox(self.gridLayoutWidget) + self.objectHighlightSelectedObjectsCheckBox.setObjectName(u"objectHighlightSelectedObjectsCheckBox") + self.objectHighlightSelectedObjectsCheckBox.setChecked(True) + + self.gridLayout.addWidget(self.objectHighlightSelectedObjectsCheckBox, 0, 0, 1, 2) + + self.objectRenameButton = QPushButton(self.gridLayoutWidget) + self.objectRenameButton.setObjectName(u"objectRenameButton") + self.objectRenameButton.setFont(font) + + self.gridLayout.addWidget(self.objectRenameButton, 2, 1, 1, 1) + + self.objectOpacityLabel = QLabel(self.gridLayoutWidget) + self.objectOpacityLabel.setObjectName(u"objectOpacityLabel") + + self.gridLayout.addWidget(self.objectOpacityLabel, 3, 0, 1, 1) + + self.objectColorComboBox = QComboBox(self.gridLayoutWidget) + self.objectColorComboBox.setObjectName(u"objectColorComboBox") + + self.gridLayout.addWidget(self.objectColorComboBox, 5, 2, 1, 1) + + self.objectPropertiesToSimilarButton = QPushButton(self.gridLayoutWidget) + self.objectPropertiesToSimilarButton.setObjectName(u"objectPropertiesToSimilarButton") + self.objectPropertiesToSimilarButton.setFont(font) + + self.gridLayout.addWidget(self.objectPropertiesToSimilarButton, 7, 1, 1, 1) + + self.objectPropertiesToAllButton = QPushButton(self.gridLayoutWidget) + self.objectPropertiesToAllButton.setObjectName(u"objectPropertiesToAllButton") + self.objectPropertiesToAllButton.setFont(font) + + self.gridLayout.addWidget(self.objectPropertiesToAllButton, 7, 2, 1, 1) + + self.objectDeleteButton = QPushButton(self.gridLayoutWidget) + self.objectDeleteButton.setObjectName(u"objectDeleteButton") + self.objectDeleteButton.setFont(font) + + self.gridLayout.addWidget(self.objectDeleteButton, 2, 2, 1, 1) + + self.objectApplyToLabel = QLabel(self.gridLayoutWidget) + self.objectApplyToLabel.setObjectName(u"objectApplyToLabel") + + self.gridLayout.addWidget(self.objectApplyToLabel, 6, 0, 1, 3) + + + self.retranslateUi(ObjectPanelWidget) + + QMetaObject.connectSlotsByName(ObjectPanelWidget) + # setupUi + + def retranslateUi(self, ObjectPanelWidget): + ObjectPanelWidget.setWindowTitle(QCoreApplication.translate("ObjectPanelWidget", u"Form", None)) + self.objectUnselectAllButton.setText(QCoreApplication.translate("ObjectPanelWidget", u"Unselect All", None)) + self.objectColorByLabel.setText(QCoreApplication.translate("ObjectPanelWidget", u"Visualization:", None)) + self.objectPropertiesToChildrenButton.setText(QCoreApplication.translate("ObjectPanelWidget", u"Children", None)) +#if QT_CONFIG(accessibility) + self.objectNameComboBox.setAccessibleName("") +#endif // QT_CONFIG(accessibility) + self.objectNameComboBox.setCurrentText("") +#if QT_CONFIG(accessibility) + self.objectColorByComboBox.setAccessibleName("") +#endif // QT_CONFIG(accessibility) + self.objectColorByComboBox.setCurrentText("") + self.objectColorLabel.setText(QCoreApplication.translate("ObjectPanelWidget", u"Solid Color:", None)) + self.objectNameLabel.setText(QCoreApplication.translate("ObjectPanelWidget", u"Object:", None)) + self.objectHighlightSelectedObjectsCheckBox.setText(QCoreApplication.translate("ObjectPanelWidget", u"Highlight Selected", None)) + self.objectRenameButton.setText(QCoreApplication.translate("ObjectPanelWidget", u"Rename", None)) + self.objectOpacityLabel.setText(QCoreApplication.translate("ObjectPanelWidget", u"Opacity:", None)) +#if QT_CONFIG(accessibility) + self.objectColorComboBox.setAccessibleName("") +#endif // QT_CONFIG(accessibility) + self.objectColorComboBox.setCurrentText("") + self.objectPropertiesToSimilarButton.setText(QCoreApplication.translate("ObjectPanelWidget", u"Similar", None)) + self.objectPropertiesToAllButton.setText(QCoreApplication.translate("ObjectPanelWidget", u"All", None)) + self.objectDeleteButton.setText(QCoreApplication.translate("ObjectPanelWidget", u"Delete", None)) + self.objectApplyToLabel.setText(QCoreApplication.translate("ObjectPanelWidget", u"Propogate vizualization properties to:", None)) + # retranslateUi + diff --git a/src/minder3d/minder3DWindow.py b/src/minder3d/minder3DWindow.py index 97a5c22..dad2429 100644 --- a/src/minder3d/minder3DWindow.py +++ b/src/minder3d/minder3DWindow.py @@ -4,12 +4,18 @@ import numpy as np import vtk from PySide6.QtCore import QCoreApplication -from PySide6.QtWidgets import QFileDialog, QInputDialog, QMainWindow, QTabBar +from PySide6.QtWidgets import ( + QFileDialog, + QInputDialog, + QMainWindow, + QSizePolicy, + QTabBar, +) -from .lib.sovColorMapUtils import get_nearest_color_index_and_name from .lib.sovImageTablePanelWidget import ImageTablePanelWidget from .lib.sovInfoTablePanelWidget import InfoTablePanelWidget from .lib.sovNewTaskPanelWidget import NewTaskPanelWidget +from .lib.sovObjectPanelWidget import ObjectPanelWidget from .lib.sovUtils import ( LogWindow, get_children_as_list, @@ -50,21 +56,11 @@ def __init__(self, parent=None): self.saveVTKModelsMenuItem.triggered.connect(self.save_vtk_models) self.saveSceneMenuItem.triggered.connect(self.save_scene) - for color_name, _ in self.state.colormap.items(): - self.objectColorComboBox.addItem(color_name) - - self.connect_object_gui() + self.bottomPanelLayout.minimumSize().setHeight(230) + self.bottomPanelLayout.maximumSize().setHeight(230) - self.objectHighlightSelectedObjectsCheckBox.stateChanged.connect( - self.update_highlight_selected - ) - self.objectDeleteButton.pressed.connect(self.delete_selected_objects) - self.objectPropertiesToAllButton.pressed.connect( - self.propogate_properties_to_all - ) - self.objectPropertiesToChildrenButton.pressed.connect( - self.propogate_properties_to_children - ) + self.bottomRightPanelLayout.minimumSize().setWidth(830) + self.bottomRightPanelLayout.maximumSize().setWidth(830) # View 2D Widget self.view2DPanel = View2DPanelWidget(self, self.state) @@ -74,6 +70,14 @@ def __init__(self, parent=None): self.view3DPanel = View3DPanelWidget(self, self.state) self.view3DLayout.addWidget(self.view3DPanel) + # Object Widget + self.objectPanel = ObjectPanelWidget(self, self.state) + self.objectLayout.addWidget(self.objectPanel) + + # Info Table + self.infoTablePanel = InfoTablePanelWidget(self, self.state) + self.infoTableLayout.addWidget(self.infoTablePanel) + # Welcome Tab self.welcomePanel = WelcomePanelWidget(self, self.state) self.welcomeTabLayout.addWidget(self.welcomePanel) @@ -87,20 +91,23 @@ def __init__(self, parent=None): self.newTaskTabLayout.addWidget(self.newTaskPanel) self.tabWidget.tabCloseRequested.connect(self.tab_close_event) + self.tabWidget.setFixedHeight(200) + self.tabWidget.setFixedWidth(700) - # Remove Close buttons from welcome, visualization, and pre-process and task tabs + # Remove Close buttons from welcome, visualization, and pre-process + # and task tabs tabBar = self.tabWidget.tabBar() for i in range(0, 3): tabBar.tabButton(i, QTabBar.RightSide).deleteLater() tabBar.setTabButton(i, QTabBar.RightSide, None) - # Info Table - self.infoTablePanel = InfoTablePanelWidget(self, self.state) - self.infoTableLayout.addWidget(self.infoTablePanel) - # Image Table self.imageTablePanel = ImageTablePanelWidget(self, self.state) self.imageTableLayout.addWidget(self.imageTablePanel) + self.imageTablePanel.setMinimumWidth(300) + self.imageTablePanel.setSizePolicy( + QSizePolicy.Minimum, QSizePolicy.Fixed + ) self.statusText.setText('Ready') @@ -117,49 +124,13 @@ def tab_close_event(self, index): self.tabWidget.removeTab(index) tab.close() - @time_and_log - def connect_object_gui(self): - self.objectNameComboBox.currentIndexChanged.connect( - self.select_object_by_name_combobox - ) - - self.objectColorByComboBox.currentIndexChanged.connect( - self.modify_selected_objects - ) - - self.objectColorComboBox.currentIndexChanged.connect( - self.modify_selected_objects - ) - - self.objectOpacitySlider.valueChanged.connect( - self.modify_selected_objects - ) - - @time_and_log - def disconnect_object_gui(self): - self.objectNameComboBox.currentIndexChanged.disconnect( - self.select_object_by_name_combobox - ) - - self.objectColorByComboBox.currentIndexChanged.disconnect( - self.modify_selected_objects - ) - - self.objectColorComboBox.currentIndexChanged.disconnect( - self.modify_selected_objects - ) - - self.objectOpacitySlider.valueChanged.disconnect( - self.modify_selected_objects - ) - def closeEvent(self, QCloseEvent): super().closeEvent(QCloseEvent) self.view2DPanel.close() self.view3DPanel.close() def log(self, message, level='info'): - """Set the status text and color based on the log level, and update the log window. + """Set the status text, and color based on the log level Args: message (str): The message to be displayed in the status text. @@ -242,10 +213,12 @@ def load_scene(self, filename=None): def save_image(self, filename=None): """Save the current image to a file. - If no filename is provided, a file dialog will be opened to select the save location. + If no filename is provided, a file dialog will be opened to select the + save location. Args: - filename (str?): The name of the file to save the image to. If not provided, a file dialog will be opened. + filename (str): The name of the file to save the image to. If not + provided, a file dialog will be opened. """ if not filename: @@ -268,11 +241,13 @@ def save_image(self, filename=None): def save_overlay(self, filename=None): """Save the overlay of the current image to a file. - If no filename is provided, it prompts the user to select a file location. - If a filename is provided, it saves the overlay of the current image to that file location. + If no filename is provided, it prompts the user to select a file + location. If a filename is provided, it saves the overlay of the + current image to that file location. Args: - filename (str?): The name of the file to save the overlay to. If not provided, a file dialog will be shown. + filename (str): The name of the file to save the overlay to. + If not provided, a file dialog will be shown. """ if not filename: @@ -295,11 +270,12 @@ def save_overlay(self, filename=None): def save_vtk_models(self, filename=None): """Save VTK models to a VRML file. - If no filename is provided, a file dialog is opened to prompt the user for a filename. - The VTK models are exported to the specified VRML file. + If no filename is provided, a file dialog is opened to prompt the user + for a filename. The VTK models are exported to the specified VRML file. Args: - filename (str?): The name of the file to save the VTK models to. If not provided, a file dialog will be opened. + filename (str): The name of the file to save the VTK models to. + If not provided, a file dialog will be opened. """ if not filename: @@ -321,8 +297,8 @@ def save_vtk_models(self, filename=None): def save_scene(self, filename=None): """Save the current scene to a file. - If no filename is provided, a file dialog will be shown to select the file. - If a filename is provided, the scene will be saved to that file. + If no filename is provided, a file dialog will be shown to select the + file. If a filename is provided, the scene will be saved to that file. Args: filename (str?): The name of the file to save the scene to. @@ -344,15 +320,17 @@ def save_scene(self, filename=None): @time_and_log def create_new_image(self, img, filename=None, tag=None): - """Create a new image and update the state with the new image information. + """Create a new image and update the state with the new image info Args: img: The new image to be added. - filename (str?): The filename for the new image. If not provided, a default filename will be generated. + filename (str?): The filename for the new image. If not provided, + a default filename will be generated. tag (str?): A tag to be appended to the filename. Returns: - bool: True if the new image is successfully created and added to the state, False otherwise. + bool: True if the new image is successfully created and added to + the state, False otherwise. """ if filename is None: @@ -408,13 +386,18 @@ def create_new_image(self, img, filename=None, tag=None): @time_and_log def replace_image(self, img, update_overlay=True): - """Replace the current image with a new image and update the overlay if specified. + """Replace the current image with a new image and update the overlay. - This function replaces the current image with the provided image and updates the corresponding image array, minimum and maximum values. If `update_overlay` is True, it also updates the overlay to match the new image. Additionally, it appends view2D_flip based on the file extension of the image. + This function replaces the current image with the provided image and + updates the corresponding image array, minimum and maximum values. + If `update_overlay` is True, it also updates the overlay to match the + new image. Additionally, it appends view2D_flip based on the file + extension of the image. Args: img: The new image to be set as the current image. - update_overlay (bool?): Flag to indicate whether to update the overlay. Defaults to True. + update_overlay (bool?): Flag to indicate whether to update the + overlay. Defaults to True. Raises: @@ -458,9 +441,11 @@ def update_overlay(self): def update_scene(self): """Update the scene with the latest changes. - This method updates the scene by updating the scene list, scene list ids, and scene list properties. - It also clears the object name combo box and adds items to it based on the scene list. - Additionally, it updates the 2D and 3D views if the corresponding auto-update flags are set. + This method updates the scene by updating the scene list, scene list + ids, and scene list properties. It also clears the object name combo + box and adds items to it based on the scene list. Additionally, it + updates the 2D and 3D views if the corresponding auto-update flags are + set. Args: self: The object instance. @@ -470,209 +455,48 @@ def update_scene(self): self.state.scene_list_ids = [] self.state.scene_list_properties = [] - self.disconnect_object_gui() - self.objectNameComboBox.clear() - self.objectNameComboBox.addItem('None') + self.update_gui = False + for so in self.state.scene_list: self.state.scene_list_ids.append(so.GetId()) self.state.scene_list_properties.append( dict(ColorBy='Solid Color', Actor=None) ) - self.objectNameComboBox.addItem(f'{so.GetTypeName()} {so.GetId()}') + if so.GetProperty().GetTagStringValue('Name') == '': + so.GetProperty().SetTagStringValue( + 'Name', f'{so.GetTypeName()} {so.GetId()}' + ) + if self.state.view2D_overlay_auto_update: self.view2DPanel.update_scene() if self.state.view3D_scene_auto_update: self.view3DPanel.update_scene() self.imageTablePanel.update_scene() - self.connect_object_gui() - - @time_and_log - def update_highlight_selected(self, value): - """Update the highlight selected state and redraw the selected objects. - - Args: - value (bool): The new value for the highlight selected state. - """ - - self.state.highlight_selected = value - for selected_id in self.state.selected_ids: - self.log(f'update_highlight_selected: Id={selected_id}') - so = self.state.scene_list[ - self.state.scene_list_ids.index(selected_id) - ] - self.redraw_object(so) - - @time_and_log - def select_object_by_name_combobox(self, idx): - so = None - so_id = -2 - if idx > 0: - idx -= 1 - so = self.state.scene_list[idx] - so_id = so.GetId() - # Unselect currently selected objects - for selected_idx, selected_so_id in enumerate(self.state.selected_ids): - if selected_so_id != -1 and selected_so_id != so_id: - scene_idx = self.state.scene_list_ids.index(selected_so_id) - selected_so = self.state.scene_list[scene_idx] - self.state.selected_ids[selected_idx] = -1 - self.redraw_object(selected_so) - if so_id != -2: - self.state.selected_ids = [so_id] - self.state.selected_point_ids = [0] - self.redraw_object(so) + self.objectPanel.update_scene() @time_and_log - def redraw_object(self, so, update_2D=True, update_3D=True): + def redraw_object( + self, so, update_2D=True, update_3D=True, update_object=True + ): """Redraws the specified object in the scene. - This method updates the visual representation of the specified object in the 2D and 3D views if the corresponding - update flags are set to True. It also updates the object's properties in the GUI. + This method updates the visual representation of the specified object + in the 2D and 3D views if the corresponding update flags are set to + True. It also updates the object's properties in the GUI. Args: self: The object instance. so: The object to be redrawn. - update_2D (bool): Flag indicating whether to update the 2D view (default is True). - update_3D (bool): Flag indicating whether to update the 3D view (default is True). + update_2D (bool): Flag indicating whether to update the 2D view + (default is True). + update_3D (bool): Flag indicating whether to update the 3D view + (default is True). """ - - so_id = so.GetId() - if so_id not in self.state.scene_list_ids: - self.log('ERROR: so_id not in scene_list_ids', 'error') - return - scene_idx = self.state.scene_list_ids.index(so_id) - - self.disconnect_object_gui() - - self.objectNameComboBox.setCurrentIndex(scene_idx + 1) - - c = so.GetProperty().GetColor() - color = [c.GetRed(), c.GetGreen(), c.GetBlue(), c.GetAlpha()] - color[0:3] = np.array(color)[0:3] * self.state.colormap_scale_factor - color[3] = color[3] * 100.0 - self.objectOpacitySlider.setValue(color[3]) - _, color_name = get_nearest_color_index_and_name( - color[0:3], self.state.colormap - ) - self.objectColorComboBox.setCurrentText(color_name) - if update_2D and self.state.view2D_overlay_auto_update: self.view2DPanel.redraw_object(so) if update_3D and self.state.view3D_scene_auto_update: self.view3DPanel.redraw_object(so) - - # Must call after view3DPanel.redraw_object() so that actors defined. - self.objectColorByComboBox.clear() - self.objectColorByComboBox.addItem('Solid Color') - actor = self.state.scene_list_properties[scene_idx].get('Actor') - if actor is not None: - pdata = actor.GetMapper().GetInput() - for i in range(pdata.GetPointData().GetNumberOfArrays()): - pname = pdata.GetPointData().GetArrayName(i) - self.objectColorByComboBox.addItem(pname) - - self.objectColorByComboBox.setCurrentText( - self.state.scene_list_properties[scene_idx]['ColorBy'] - ) - - self.connect_object_gui() - - @time_and_log - def modify_selected_objects(self, _): - """Modify the selected objects in the scene with new color and properties. - - This function modifies the color and properties of the selected objects in the scene based on the current state - of the application. It updates the color, opacity, and color-by property of the selected objects. - - Args: - self: The instance of the class. - """ - - for so_id in self.state.selected_ids: - scene_idx = self.state.scene_list_ids.index(so_id) - so = self.state.scene_list[scene_idx] - color = np.empty(4) - color[0:3] = self.state.colormap[ - self.objectColorComboBox.currentText() - ] - color[0:3] /= self.state.colormap_scale_factor - color[3] = self.objectOpacitySlider.value() / 100.0 - so.GetProperty().SetColor(color) - self.state.scene_list_properties[scene_idx][ - 'ColorBy' - ] = self.objectColorByComboBox.currentText() - - if self.state.view2D_overlay_auto_update: - self.view2DPanel.redraw_object(so) - if self.state.view3D_scene_auto_update: - self.view3DPanel.redraw_object(so) - - @time_and_log - def delete_selected_objects(self): - """Delete the selected objects from the scene. - - This function deletes the selected objects from the scene by removing them from the scene list and updating the GUI accordingly. - """ - - for so_id in self.state.selected_ids: - print('deleting so_id:', so_id) - scene_idx = self.state.scene_list_ids.index(so_id) - so = self.state.scene_list[scene_idx] - so_parent = so.GetParent() - so_parent.RemoveChild(so) - self.state.scene_list.pop(scene_idx) - self.state.scene_list_properties.pop(scene_idx) - self.state.selected_ids = [] - self.state.selected_point_ids = [] - - self.disconnect_object_gui() - self.objectNameComboBox.clear() - self.objectNameComboBox.addItem('None') - for so in self.state.scene_list: - self.objectNameComboBox.addItem(f'{so.GetTypeName()} {so.GetId()}') - self.connect_object_gui() - self.update_scene() - - @time_and_log - def propogate_properties_to_all(self): - """Propagate properties to all objects in the scene. - - This function updates the properties of all objects in the scene based on the current settings. - - Args: - self: The current instance of the class. - """ - - color_by = self.objectColorByComboBox.currentText() - color = np.empty(4) - color[0:3] = self.state.colormap[self.objectColorComboBox.currentText()] - color[0:3] /= self.state.colormap_scale_factor - color[3] = self.objectOpacitySlider.value() / 100.0 - for idx in range(len(self.state.scene_list)): - self.state.scene_list_properties[idx]['ColorBy'] = color_by - self.state.scene_list[idx].GetProperty().SetColor(color) - self.redraw_object(self.state.scene_list[idx]) - - @time_and_log - def propogate_properties_to_children(self): - """Propagate properties to the children objects. - - This function propagates the selected properties to the children objects in the scene. - """ - - for so_id in self.state.selected_ids: - scene_idx = self.state.scene_list_ids.index(so_id) - so = self.state.scene_list[scene_idx] - color_by = self.objectColorByComboBox.currentText() - color = np.empty(4) - color[0:3] = self.state.colormap[ - self.objectColorComboBox.currentText() - ] - color[0:3] /= self.state.colormap_scale_factor - color[3] = self.objectOpacitySlider.value() / 100.0 - children = get_children_as_list(so) - for child_so in children: - idx = self.state.scene_list.index(child_so) - self.state.scene_list_properties[idx]['ColorBy'] = color_by - self.state.scene_list[idx].GetProperty().SetColor(color) - self.redraw_object(child_so) + if update_object: + # Must call after view3DPanel.redraw_object() so that actors are + # defined and color-by options are known. + self.objectPanel.redraw_object(so) diff --git a/src/minder3d/minder3DWindow.ui b/src/minder3d/minder3DWindow.ui index ef2c905..291564a 100644 --- a/src/minder3d/minder3DWindow.ui +++ b/src/minder3d/minder3DWindow.ui @@ -6,8 +6,8 @@ 0 0 - 1043 - 691 + 1024 + 675 @@ -34,7 +34,7 @@ - + QLayout::SetDefaultConstraint @@ -105,190 +105,7 @@ - - - - 0 - 0 - - - - - 211 - 181 - - - - true - - - - - - - 7 - - - - Delete - - - - - - - - - - - - - - - - - - 5 - - - - 100 - - - 50 - - - Qt::Horizontal - - - - - - - Solid Color: - - - - - - - Opacity: - - - - - - - Visualization: - - - - - - - Object: - - - - - - - Propogate vizualization properties to: - - - - - - - - - - - - - - - - - - 7 - - - - All - - - - - - - - 7 - - - - Rename - - - - - - - - - - - - - - - - - - 7 - - - - Children - - - - - - - - 7 - - - - Similar - - - - - - - Highlight Selected - - - true - - - - - - - - 7 - - - - Unselect All - - - - - + @@ -298,23 +115,40 @@ - + - + + + + + Qt::Horizontal + + + + 300 + 0 + + + + + - + + + QLayout::SetDefaultConstraint + - + 0 0 - 700 + 830 194 @@ -412,9 +246,12 @@ Qt::Horizontal + + QSizePolicy::Fixed + - 40 + 250 0 @@ -453,7 +290,7 @@ 0 0 - 1043 + 1024 22 diff --git a/src/minder3d/ui_minder3DWindow.py b/src/minder3d/ui_minder3DWindow.py index b2da284..ef891e1 100644 --- a/src/minder3d/ui_minder3DWindow.py +++ b/src/minder3d/ui_minder3DWindow.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ################################################################################ -## Form generated from reading UI file 'minder3DWindowPfcNFq.ui' +## Form generated from reading UI file 'minder3DWindowtMVPMu.ui' ## ## Created by: Qt User Interface Compiler version 6.5.0 ## @@ -16,34 +16,33 @@ QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) -from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QGridLayout, - QGroupBox, QHBoxLayout, QLabel, QLayout, - QLineEdit, QMainWindow, QMenu, QMenuBar, - QProgressBar, QPushButton, QSizePolicy, QSlider, +from PySide6.QtWidgets import (QApplication, QGridLayout, QHBoxLayout, QLabel, + QLayout, QLineEdit, QMainWindow, QMenu, + QMenuBar, QProgressBar, QPushButton, QSizePolicy, QSpacerItem, QTabWidget, QVBoxLayout, QWidget) class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): - MainWindow.setObjectName(u'MainWindow') - MainWindow.resize(1043, 691) + MainWindow.setObjectName(u"MainWindow") + MainWindow.resize(1024, 675) MainWindow.setMinimumSize(QSize(1024, 0)) self.loadImageMenuItem = QAction(MainWindow) - self.loadImageMenuItem.setObjectName(u'loadImageMenuItem') + self.loadImageMenuItem.setObjectName(u"loadImageMenuItem") self.saveImageMenuItem = QAction(MainWindow) - self.saveImageMenuItem.setObjectName(u'saveImageMenuItem') + self.saveImageMenuItem.setObjectName(u"saveImageMenuItem") self.saveOverlayMenuItem = QAction(MainWindow) - self.saveOverlayMenuItem.setObjectName(u'saveOverlayMenuItem') + self.saveOverlayMenuItem.setObjectName(u"saveOverlayMenuItem") self.saveVTKModelsMenuItem = QAction(MainWindow) - self.saveVTKModelsMenuItem.setObjectName(u'saveVTKModelsMenuItem') + self.saveVTKModelsMenuItem.setObjectName(u"saveVTKModelsMenuItem") self.loadSceneMenuItem = QAction(MainWindow) - self.loadSceneMenuItem.setObjectName(u'loadSceneMenuItem') + self.loadSceneMenuItem.setObjectName(u"loadSceneMenuItem") self.saveSceneMenuItem = QAction(MainWindow) - self.saveSceneMenuItem.setObjectName(u'saveSceneMenuItem') + self.saveSceneMenuItem.setObjectName(u"saveSceneMenuItem") self.savePreProcessedOverlayMenuItem = QAction(MainWindow) - self.savePreProcessedOverlayMenuItem.setObjectName(u'savePreProcessedOverlayMenuItem') + self.savePreProcessedOverlayMenuItem.setObjectName(u"savePreProcessedOverlayMenuItem") self.centralwidget = QWidget(MainWindow) - self.centralwidget.setObjectName(u'centralwidget') + self.centralwidget.setObjectName(u"centralwidget") sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) @@ -51,14 +50,14 @@ def setupUi(self, MainWindow): self.centralwidget.setSizePolicy(sizePolicy) self.centralwidget.setMinimumSize(QSize(1024, 0)) self.gridLayout_3 = QGridLayout(self.centralwidget) - self.gridLayout_3.setObjectName(u'gridLayout_3') - self.verticalLayout = QVBoxLayout() - self.verticalLayout.setObjectName(u'verticalLayout') - self.verticalLayout.setSizeConstraint(QLayout.SetDefaultConstraint) + self.gridLayout_3.setObjectName(u"gridLayout_3") + self.appLayout = QVBoxLayout() + self.appLayout.setObjectName(u"appLayout") + self.appLayout.setSizeConstraint(QLayout.SetDefaultConstraint) self.topPanelLayout = QHBoxLayout() - self.topPanelLayout.setObjectName(u'topPanelLayout') + self.topPanelLayout.setObjectName(u"topPanelLayout") self.view2DLayout = QVBoxLayout() - self.view2DLayout.setObjectName(u'view2DLayout') + self.view2DLayout.setObjectName(u"view2DLayout") self.view2DSpacer = QSpacerItem(391, 0, QSizePolicy.Fixed, QSizePolicy.Minimum) self.view2DLayout.addItem(self.view2DSpacer) @@ -71,7 +70,7 @@ def setupUi(self, MainWindow): self.topPanelLayout.addItem(self.topPanelSpacer) self.view3DLayout = QVBoxLayout() - self.view3DLayout.setObjectName(u'view3DLayout') + self.view3DLayout.setObjectName(u"view3DLayout") self.view3DSpacer = QSpacerItem(361, 0, QSizePolicy.Fixed, QSizePolicy.Minimum) self.view3DLayout.addItem(self.view3DSpacer) @@ -80,118 +79,14 @@ def setupUi(self, MainWindow): self.topPanelLayout.addLayout(self.view3DLayout) self.rightPanelLayout = QVBoxLayout() - self.rightPanelLayout.setObjectName(u'rightPanelLayout') - self.objectGroupBox = QGroupBox(self.centralwidget) - self.objectGroupBox.setObjectName(u'objectGroupBox') - sizePolicy1 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) - sizePolicy1.setHorizontalStretch(0) - sizePolicy1.setVerticalStretch(0) - sizePolicy1.setHeightForWidth(self.objectGroupBox.sizePolicy().hasHeightForWidth()) - self.objectGroupBox.setSizePolicy(sizePolicy1) - self.objectGroupBox.setMinimumSize(QSize(211, 181)) - self.objectGroupBox.setAutoFillBackground(True) - self.gridLayout_2 = QGridLayout(self.objectGroupBox) - self.gridLayout_2.setObjectName(u'gridLayout_2') - self.objectDeleteButton = QPushButton(self.objectGroupBox) - self.objectDeleteButton.setObjectName(u'objectDeleteButton') - font = QFont() - font.setPointSize(7) - self.objectDeleteButton.setFont(font) - - self.gridLayout_2.addWidget(self.objectDeleteButton, 4, 3, 1, 1) - - self.objectNameComboBox = QComboBox(self.objectGroupBox) - self.objectNameComboBox.setObjectName(u'objectNameComboBox') - - self.gridLayout_2.addWidget(self.objectNameComboBox, 2, 1, 1, 3) - - self.objectOpacitySlider = QSlider(self.objectGroupBox) - self.objectOpacitySlider.setObjectName(u'objectOpacitySlider') - font1 = QFont() - font1.setPointSize(5) - self.objectOpacitySlider.setFont(font1) - self.objectOpacitySlider.setMaximum(100) - self.objectOpacitySlider.setValue(50) - self.objectOpacitySlider.setOrientation(Qt.Horizontal) - - self.gridLayout_2.addWidget(self.objectOpacitySlider, 5, 1, 1, 3) - - self.objectColorLabel = QLabel(self.objectGroupBox) - self.objectColorLabel.setObjectName(u'objectColorLabel') - - self.gridLayout_2.addWidget(self.objectColorLabel, 7, 1, 1, 1) - - self.objectOpacityLabel = QLabel(self.objectGroupBox) - self.objectOpacityLabel.setObjectName(u'objectOpacityLabel') - - self.gridLayout_2.addWidget(self.objectOpacityLabel, 5, 0, 1, 1) - - self.objectColorByLabel = QLabel(self.objectGroupBox) - self.objectColorByLabel.setObjectName(u'objectColorByLabel') - - self.gridLayout_2.addWidget(self.objectColorByLabel, 6, 0, 1, 1) - - self.objectNameLabel = QLabel(self.objectGroupBox) - self.objectNameLabel.setObjectName(u'objectNameLabel') - - self.gridLayout_2.addWidget(self.objectNameLabel, 2, 0, 1, 1) - - self.objectApplyToLabel = QLabel(self.objectGroupBox) - self.objectApplyToLabel.setObjectName(u'objectApplyToLabel') - - self.gridLayout_2.addWidget(self.objectApplyToLabel, 9, 0, 1, 4) - - self.objectColorComboBox = QComboBox(self.objectGroupBox) - self.objectColorComboBox.setObjectName(u'objectColorComboBox') - - self.gridLayout_2.addWidget(self.objectColorComboBox, 7, 2, 1, 2) - - self.objectPropertiesToAllButton = QPushButton(self.objectGroupBox) - self.objectPropertiesToAllButton.setObjectName(u'objectPropertiesToAllButton') - self.objectPropertiesToAllButton.setFont(font) - - self.gridLayout_2.addWidget(self.objectPropertiesToAllButton, 11, 2, 1, 2) - - self.objectRenameButton = QPushButton(self.objectGroupBox) - self.objectRenameButton.setObjectName(u'objectRenameButton') - self.objectRenameButton.setFont(font) + self.rightPanelLayout.setObjectName(u"rightPanelLayout") + self.objectLayout = QVBoxLayout() + self.objectLayout.setObjectName(u"objectLayout") - self.gridLayout_2.addWidget(self.objectRenameButton, 4, 1, 1, 1) - - self.objectColorByComboBox = QComboBox(self.objectGroupBox) - self.objectColorByComboBox.setObjectName(u'objectColorByComboBox') - - self.gridLayout_2.addWidget(self.objectColorByComboBox, 6, 1, 1, 3) - - self.objectPropertiesToChildrenButton = QPushButton(self.objectGroupBox) - self.objectPropertiesToChildrenButton.setObjectName(u'objectPropertiesToChildrenButton') - self.objectPropertiesToChildrenButton.setFont(font) - - self.gridLayout_2.addWidget(self.objectPropertiesToChildrenButton, 11, 0, 1, 1) - - self.objectPropertiesToSimilarButton = QPushButton(self.objectGroupBox) - self.objectPropertiesToSimilarButton.setObjectName(u'objectPropertiesToSimilarButton') - self.objectPropertiesToSimilarButton.setFont(font) - - self.gridLayout_2.addWidget(self.objectPropertiesToSimilarButton, 11, 1, 1, 1) - - self.objectHighlightSelectedObjectsCheckBox = QCheckBox(self.objectGroupBox) - self.objectHighlightSelectedObjectsCheckBox.setObjectName(u'objectHighlightSelectedObjectsCheckBox') - self.objectHighlightSelectedObjectsCheckBox.setChecked(True) - - self.gridLayout_2.addWidget(self.objectHighlightSelectedObjectsCheckBox, 0, 0, 1, 3) - - self.pushButton = QPushButton(self.objectGroupBox) - self.pushButton.setObjectName(u'pushButton') - self.pushButton.setFont(font) - - self.gridLayout_2.addWidget(self.pushButton, 0, 3, 1, 1) - - - self.rightPanelLayout.addWidget(self.objectGroupBox) + self.rightPanelLayout.addLayout(self.objectLayout) self.infoTableLayout = QVBoxLayout() - self.infoTableLayout.setObjectName(u'infoTableLayout') + self.infoTableLayout.setObjectName(u"infoTableLayout") self.rightPanelLayout.addLayout(self.infoTableLayout) @@ -199,103 +94,113 @@ def setupUi(self, MainWindow): self.topPanelLayout.addLayout(self.rightPanelLayout) - self.verticalLayout.addLayout(self.topPanelLayout) + self.appLayout.addLayout(self.topPanelLayout) - self.middlePanelLayout = QHBoxLayout() - self.middlePanelLayout.setObjectName(u'middlePanelLayout') + self.bottomPanelLayout = QHBoxLayout() + self.bottomPanelLayout.setObjectName(u"bottomPanelLayout") self.imageTableLayout = QVBoxLayout() - self.imageTableLayout.setObjectName(u'imageTableLayout') + self.imageTableLayout.setObjectName(u"imageTableLayout") + self.horizontalSpacer_2 = QSpacerItem(300, 0, QSizePolicy.Expanding, QSizePolicy.Minimum) - self.middlePanelLayout.addLayout(self.imageTableLayout) + self.imageTableLayout.addItem(self.horizontalSpacer_2) - self.verticalLayout_3 = QVBoxLayout() - self.verticalLayout_3.setObjectName(u'verticalLayout_3') + + self.bottomPanelLayout.addLayout(self.imageTableLayout) + + self.bottomRightPanelLayout = QVBoxLayout() + self.bottomRightPanelLayout.setObjectName(u"bottomRightPanelLayout") + self.bottomRightPanelLayout.setSizeConstraint(QLayout.SetDefaultConstraint) self.tabWidget = QTabWidget(self.centralwidget) - self.tabWidget.setObjectName(u'tabWidget') - sizePolicy2 = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) - sizePolicy2.setHorizontalStretch(0) - sizePolicy2.setVerticalStretch(0) - sizePolicy2.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth()) - self.tabWidget.setSizePolicy(sizePolicy2) - self.tabWidget.setMinimumSize(QSize(700, 194)) + self.tabWidget.setObjectName(u"tabWidget") + sizePolicy1 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding) + sizePolicy1.setHorizontalStretch(0) + sizePolicy1.setVerticalStretch(0) + sizePolicy1.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth()) + self.tabWidget.setSizePolicy(sizePolicy1) + self.tabWidget.setMinimumSize(QSize(830, 194)) self.tabWidget.setTabsClosable(True) self.welcomeTab = QWidget() - self.welcomeTab.setObjectName(u'welcomeTab') + self.welcomeTab.setObjectName(u"welcomeTab") self.welcomeTabLayout = QHBoxLayout(self.welcomeTab) - self.welcomeTabLayout.setObjectName(u'welcomeTabLayout') - self.tabWidget.addTab(self.welcomeTab, '') + self.welcomeTabLayout.setObjectName(u"welcomeTabLayout") + self.tabWidget.addTab(self.welcomeTab, "") self.visualizationTab = QWidget() - self.visualizationTab.setObjectName(u'visualizationTab') + self.visualizationTab.setObjectName(u"visualizationTab") self.visualizationTabLayout = QHBoxLayout(self.visualizationTab) - self.visualizationTabLayout.setObjectName(u'visualizationTabLayout') - self.tabWidget.addTab(self.visualizationTab, '') + self.visualizationTabLayout.setObjectName(u"visualizationTabLayout") + self.tabWidget.addTab(self.visualizationTab, "") self.newTaskTab = QWidget() - self.newTaskTab.setObjectName(u'newTaskTab') + self.newTaskTab.setObjectName(u"newTaskTab") self.newTaskTabLayout = QHBoxLayout(self.newTaskTab) - self.newTaskTabLayout.setObjectName(u'newTaskTabLayout') - self.tabWidget.addTab(self.newTaskTab, '') + self.newTaskTabLayout.setObjectName(u"newTaskTabLayout") + self.tabWidget.addTab(self.newTaskTab, "") - self.verticalLayout_3.addWidget(self.tabWidget) + self.bottomRightPanelLayout.addWidget(self.tabWidget) self.horizontalLayout_2 = QHBoxLayout() - self.horizontalLayout_2.setObjectName(u'horizontalLayout_2') + self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.statusLabel = QLabel(self.centralwidget) - self.statusLabel.setObjectName(u'statusLabel') - sizePolicy1.setHeightForWidth(self.statusLabel.sizePolicy().hasHeightForWidth()) - self.statusLabel.setSizePolicy(sizePolicy1) + self.statusLabel.setObjectName(u"statusLabel") + sizePolicy2 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + sizePolicy2.setHorizontalStretch(0) + sizePolicy2.setVerticalStretch(0) + sizePolicy2.setHeightForWidth(self.statusLabel.sizePolicy().hasHeightForWidth()) + self.statusLabel.setSizePolicy(sizePolicy2) + font = QFont() + font.setPointSize(7) self.statusLabel.setFont(font) self.horizontalLayout_2.addWidget(self.statusLabel) self.statusText = QLineEdit(self.centralwidget) - self.statusText.setObjectName(u'statusText') - sizePolicy1.setHeightForWidth(self.statusText.sizePolicy().hasHeightForWidth()) - self.statusText.setSizePolicy(sizePolicy1) + self.statusText.setObjectName(u"statusText") + sizePolicy2.setHeightForWidth(self.statusText.sizePolicy().hasHeightForWidth()) + self.statusText.setSizePolicy(sizePolicy2) self.statusText.setMinimumSize(QSize(150, 0)) self.statusText.setFont(font) self.horizontalLayout_2.addWidget(self.statusText) self.statusProgressBar = QProgressBar(self.centralwidget) - self.statusProgressBar.setObjectName(u'statusProgressBar') - sizePolicy1.setHeightForWidth(self.statusProgressBar.sizePolicy().hasHeightForWidth()) - self.statusProgressBar.setSizePolicy(sizePolicy1) + self.statusProgressBar.setObjectName(u"statusProgressBar") + sizePolicy2.setHeightForWidth(self.statusProgressBar.sizePolicy().hasHeightForWidth()) + self.statusProgressBar.setSizePolicy(sizePolicy2) self.statusProgressBar.setMinimumSize(QSize(150, 12)) self.statusProgressBar.setValue(0) self.statusProgressBar.setTextVisible(False) self.horizontalLayout_2.addWidget(self.statusProgressBar) - self.horizontalSpacer = QSpacerItem(40, 0, QSizePolicy.Expanding, QSizePolicy.Minimum) + self.horizontalSpacer = QSpacerItem(250, 0, QSizePolicy.Fixed, QSizePolicy.Minimum) self.horizontalLayout_2.addItem(self.horizontalSpacer) self.statusViewLogButton = QPushButton(self.centralwidget) - self.statusViewLogButton.setObjectName(u'statusViewLogButton') - sizePolicy1.setHeightForWidth(self.statusViewLogButton.sizePolicy().hasHeightForWidth()) - self.statusViewLogButton.setSizePolicy(sizePolicy1) + self.statusViewLogButton.setObjectName(u"statusViewLogButton") + sizePolicy2.setHeightForWidth(self.statusViewLogButton.sizePolicy().hasHeightForWidth()) + self.statusViewLogButton.setSizePolicy(sizePolicy2) self.statusViewLogButton.setFont(font) self.horizontalLayout_2.addWidget(self.statusViewLogButton) - self.verticalLayout_3.addLayout(self.horizontalLayout_2) + self.bottomRightPanelLayout.addLayout(self.horizontalLayout_2) - self.middlePanelLayout.addLayout(self.verticalLayout_3) + self.bottomPanelLayout.addLayout(self.bottomRightPanelLayout) - self.verticalLayout.addLayout(self.middlePanelLayout) + self.appLayout.addLayout(self.bottomPanelLayout) - self.gridLayout_3.addLayout(self.verticalLayout, 0, 0, 1, 1) + self.gridLayout_3.addLayout(self.appLayout, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(MainWindow) - self.menubar.setObjectName(u'menubar') - self.menubar.setGeometry(QRect(0, 0, 1043, 22)) + self.menubar.setObjectName(u"menubar") + self.menubar.setGeometry(QRect(0, 0, 1024, 22)) self.fileMenu = QMenu(self.menubar) - self.fileMenu.setObjectName(u'fileMenu') + self.fileMenu.setObjectName(u"fileMenu") MainWindow.setMenuBar(self.menubar) self.menubar.addAction(self.fileMenu.menuAction()) @@ -316,42 +221,19 @@ def setupUi(self, MainWindow): # setupUi def retranslateUi(self, MainWindow): - MainWindow.setWindowTitle(QCoreApplication.translate('MainWindow', u'Minder3D', None)) - self.loadImageMenuItem.setText(QCoreApplication.translate('MainWindow', u'Load Image', None)) - self.saveImageMenuItem.setText(QCoreApplication.translate('MainWindow', u'Save Image', None)) - self.saveOverlayMenuItem.setText(QCoreApplication.translate('MainWindow', u'Save Overlay', None)) - self.saveVTKModelsMenuItem.setText(QCoreApplication.translate('MainWindow', u'Save VTK Models', None)) - self.loadSceneMenuItem.setText(QCoreApplication.translate('MainWindow', u'Load Spatial Objects', None)) - self.saveSceneMenuItem.setText(QCoreApplication.translate('MainWindow', u'Save Spatial Objects', None)) - self.savePreProcessedOverlayMenuItem.setText(QCoreApplication.translate('MainWindow', u'Save Pre-Processed Overlay', None)) - self.objectDeleteButton.setText(QCoreApplication.translate('MainWindow', u'Delete', None)) -#if QT_CONFIG(accessibility) - self.objectNameComboBox.setAccessibleName('') -#endif // QT_CONFIG(accessibility) - self.objectNameComboBox.setCurrentText('') - self.objectColorLabel.setText(QCoreApplication.translate('MainWindow', u'Solid Color:', None)) - self.objectOpacityLabel.setText(QCoreApplication.translate('MainWindow', u'Opacity:', None)) - self.objectColorByLabel.setText(QCoreApplication.translate('MainWindow', u'Visualization:', None)) - self.objectNameLabel.setText(QCoreApplication.translate('MainWindow', u'Object:', None)) - self.objectApplyToLabel.setText(QCoreApplication.translate('MainWindow', u'Propogate vizualization properties to:', None)) -#if QT_CONFIG(accessibility) - self.objectColorComboBox.setAccessibleName('') -#endif // QT_CONFIG(accessibility) - self.objectColorComboBox.setCurrentText('') - self.objectPropertiesToAllButton.setText(QCoreApplication.translate('MainWindow', u'All', None)) - self.objectRenameButton.setText(QCoreApplication.translate('MainWindow', u'Rename', None)) -#if QT_CONFIG(accessibility) - self.objectColorByComboBox.setAccessibleName('') -#endif // QT_CONFIG(accessibility) - self.objectColorByComboBox.setCurrentText('') - self.objectPropertiesToChildrenButton.setText(QCoreApplication.translate('MainWindow', u'Children', None)) - self.objectPropertiesToSimilarButton.setText(QCoreApplication.translate('MainWindow', u'Similar', None)) - self.objectHighlightSelectedObjectsCheckBox.setText(QCoreApplication.translate('MainWindow', u'Highlight Selected', None)) - self.pushButton.setText(QCoreApplication.translate('MainWindow', u'Unselect All', None)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.welcomeTab), QCoreApplication.translate('MainWindow', u'Welcome: Load and Save', None)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.visualizationTab), QCoreApplication.translate('MainWindow', u'Visualization', None)) - self.tabWidget.setTabText(self.tabWidget.indexOf(self.newTaskTab), QCoreApplication.translate('MainWindow', u'New Task', None)) - self.statusLabel.setText(QCoreApplication.translate('MainWindow', u'Status:', None)) - self.statusViewLogButton.setText(QCoreApplication.translate('MainWindow', u'View Log', None)) - self.fileMenu.setTitle(QCoreApplication.translate('MainWindow', u'File', None)) + MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"Minder3D", None)) + self.loadImageMenuItem.setText(QCoreApplication.translate("MainWindow", u"Load Image", None)) + self.saveImageMenuItem.setText(QCoreApplication.translate("MainWindow", u"Save Image", None)) + self.saveOverlayMenuItem.setText(QCoreApplication.translate("MainWindow", u"Save Overlay", None)) + self.saveVTKModelsMenuItem.setText(QCoreApplication.translate("MainWindow", u"Save VTK Models", None)) + self.loadSceneMenuItem.setText(QCoreApplication.translate("MainWindow", u"Load Spatial Objects", None)) + self.saveSceneMenuItem.setText(QCoreApplication.translate("MainWindow", u"Save Spatial Objects", None)) + self.savePreProcessedOverlayMenuItem.setText(QCoreApplication.translate("MainWindow", u"Save Pre-Processed Overlay", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.welcomeTab), QCoreApplication.translate("MainWindow", u"Welcome: Load and Save", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.visualizationTab), QCoreApplication.translate("MainWindow", u"Visualization", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.newTaskTab), QCoreApplication.translate("MainWindow", u"New Task", None)) + self.statusLabel.setText(QCoreApplication.translate("MainWindow", u"Status:", None)) + self.statusViewLogButton.setText(QCoreApplication.translate("MainWindow", u"View Log", None)) + self.fileMenu.setTitle(QCoreApplication.translate("MainWindow", u"File", None)) # retranslateUi +