def testWidgetIterator(self): treeWidget = QTreeWidget() treeWidget.setColumnCount(1) items = [] for i in range(10): items.append(QTreeWidgetItem(None, ['item: %d' % i])) treeWidget.insertTopLevelItems(0, items) index = 0 for it in QTreeWidgetItemIterator(treeWidget): self.assertEqual(it.value().text(0), 'item: %d' % index) index += 1
def testCase(self): treeWidget = QTreeWidget() treeWidget.setColumnCount(1) items = [] for i in range(10): items.append(QTreeWidgetItem(None, ["item: %i" % i])) treeWidget.insertTopLevelItems(0, items); _iter = QTreeWidgetItemIterator(treeWidget) index = 0 while(_iter.value()): item = _iter.value() self.assertTrue(item is items[index]) index += 1 _iter += 1
def testCase(self): treeWidget = QTreeWidget() treeWidget.setColumnCount(1) items = [] for i in range(10): items.append(QTreeWidgetItem(None, ["item: %i" % i])) treeWidget.insertTopLevelItems(0, items); _iter = QTreeWidgetItemIterator(treeWidget) index = 0 while(_iter.value()): item = _iter.value() self.assert_(item is items[index]) index += 1 _iter += 1
def reset_model(self, index): """Setup model according to current relationship_class selected in combobox. """ self.class_name, self.object_class_name_list = self.relationship_class_keys[ index] object_class_name_list = self.object_class_name_list.split(",") self.model.set_horizontal_header_labels(object_class_name_list) self.existing_items_model.set_horizontal_header_labels( object_class_name_list) self.new_items_model.set_horizontal_header_labels( object_class_name_list) self.relationship_ids.clear() for db_map in self.db_maps: relationship_classes = self.db_map_rel_cls_lookup[db_map] rel_cls = relationship_classes.get( (self.class_name, self.object_class_name_list), None) if rel_cls is None: continue for relationship in self.db_mngr.get_items_by_field( db_map, "relationship", "class_id", rel_cls["id"]): key = tuple(relationship["object_name_list"].split(",")) self.relationship_ids[key] = relationship["id"] existing_items = list(self.relationship_ids) self.existing_items_model.reset_model(existing_items) self.model.refresh() self.model.modelReset.emit() for wg in self.splitter_widgets(): wg.deleteLater() for name in object_class_name_list: tree_widget = QTreeWidget(self) tree_widget.setSelectionMode(QAbstractItemView.ExtendedSelection) tree_widget.setColumnCount(1) tree_widget.setIndentation(0) header_item = QTreeWidgetItem([name]) header_item.setTextAlignment(0, Qt.AlignHCenter) tree_widget.setHeaderItem(header_item) objects = self.db_mngr.get_items_by_field(self.db_map, "object", "class_name", name) items = [QTreeWidgetItem([obj["name"]]) for obj in objects] tree_widget.addTopLevelItems(items) tree_widget.resizeColumnToContents(0) self.splitter.addWidget(tree_widget) sizes = [wg.columnWidth(0) for wg in self.splitter_widgets()] self.splitter.setSizes(sizes) for widget in self.hidable_widgets: widget.show()
def testSetItemWidget(self): treeWidget = QTreeWidget() treeWidget.setColumnCount(2) item = QTreeWidgetItem(['text of column 0', '']) treeWidget.insertTopLevelItem(0, item) # Adding QPushButton inside the method treeWidget.setItemWidget(item, 1, QPushButton('Push button on column 1')) # Getting the widget back w = treeWidget.itemWidget(treeWidget.itemAt(0, 1), 1) self.assertIsInstance(w, QPushButton) p = QPushButton('New independent button') # Adding QPushButton object from variable treeWidget.setItemWidget(item, 0, p) w = treeWidget.itemWidget(treeWidget.itemAt(0, 0), 0) self.assertIsInstance(w, QPushButton)
class ObjectTreeDialog(QDialog): def __init__(self, parent=None, root_object=None): super(ObjectTreeDialog, self).__init__(parent) self.setWindowTitle("Object Tree") layout = QtWidgets.QVBoxLayout() # Tree widget for displaying our object hierarchy self.tree_widget = QTreeWidget() self.tree_widget_columns = [ "TYPE", "OBJECT NAME", "TEXT", "ICONTEXT", "TITLE", "WINDOW_TITLE", "CLASSES", "POINTER_ADDRESS", "GEOMETRY" ] self.tree_widget.setColumnCount(len(self.tree_widget_columns)) self.tree_widget.setHeaderLabels(self.tree_widget_columns) # Only show our type and object name columns. The others we only use to store data so that # we can use the built-in QTreeWidget.findItems to query. for column_name in self.tree_widget_columns: if column_name == "TYPE" or column_name == "OBJECT NAME": continue column_index = self.tree_widget_columns.index(column_name) self.tree_widget.setColumnHidden(column_index, True) header = self.tree_widget.header() header.setSectionResizeMode(0, QHeaderView.ResizeToContents) header.setSectionResizeMode(1, QHeaderView.ResizeToContents) # Populate our object tree widget # If a root object wasn't specified, then use the Editor main window if not root_object: params = azlmbr.qt.QtForPythonRequestBus( azlmbr.bus.Broadcast, "GetQtBootstrapParameters") editor_id = QtWidgets.QWidget.find(params.mainWindowId) editor_main_window = wrapInstance(int(getCppPointer(editor_id)[0]), QtWidgets.QMainWindow) root_object = editor_main_window self.build_tree(root_object, self.tree_widget) # Listen for when the tree widget selection changes so we can update # selected item properties self.tree_widget.itemSelectionChanged.connect( self.on_tree_widget_selection_changed) # Split our tree widget with a properties view for showing more information about # a selected item. We also use a stacked layout for the properties view so that # when nothing has been selected yet, we can show a message informing the user # that something needs to be selected. splitter = QSplitter() splitter.addWidget(self.tree_widget) self.widget_properties = QWidget(self) self.stacked_layout = QtWidgets.QStackedLayout() self.widget_info = QWidget() form_layout = QtWidgets.QFormLayout() self.name_value = QLineEdit("") self.name_value.setReadOnly(True) self.type_value = QLabel("") self.geometry_value = QLabel("") self.text_value = QLabel("") self.icon_text_value = QLabel("") self.title_value = QLabel("") self.window_title_value = QLabel("") self.classes_value = QLabel("") form_layout.addRow("Name:", self.name_value) form_layout.addRow("Type:", self.type_value) form_layout.addRow("Geometry:", self.geometry_value) form_layout.addRow("Text:", self.text_value) form_layout.addRow("Icon Text:", self.icon_text_value) form_layout.addRow("Title:", self.title_value) form_layout.addRow("Window Title:", self.window_title_value) form_layout.addRow("Classes:", self.classes_value) self.widget_info.setLayout(form_layout) self.widget_properties.setLayout(self.stacked_layout) self.stacked_layout.addWidget( QLabel("Select an object to view its properties")) self.stacked_layout.addWidget(self.widget_info) splitter.addWidget(self.widget_properties) # Give our splitter stretch factor of 1 so it will expand to take more room over # the footer layout.addWidget(splitter, 1) # Create our popup widget for showing information when hovering over widgets self.hovered_widget = None self.inspect_mode = False self.inspect_popup = InspectPopup() self.inspect_popup.resize(100, 50) self.inspect_popup.hide() # Add a footer with a button to switch to widget inspect mode self.footer = QWidget() footer_layout = QtWidgets.QHBoxLayout() self.inspect_button = QPushButton("Pick widget to inspect") self.inspect_button.clicked.connect(self.on_inspect_clicked) footer_layout.addStretch(1) footer_layout.addWidget(self.inspect_button) self.footer.setLayout(footer_layout) layout.addWidget(self.footer) self.setLayout(layout) # Delete ourselves when the dialog is closed, so that we don't stay living in the background # since we install an event filter on the application self.setAttribute(Qt.WA_DeleteOnClose, True) # Listen to events at the application level so we can know when the mouse is moving app = QtWidgets.QApplication.instance() app.installEventFilter(self) def eventFilter(self, obj, event): # Look for mouse movement events so we can see what widget the mouse is hovered over event_type = event.type() if event_type == QEvent.MouseMove: global_pos = event.globalPos() # Make our popup follow the mouse, but we need to offset it by 1, 1 otherwise # the QApplication.widgetAt will always return our popup instead of the Editor # widget since it is on top self.inspect_popup.move(global_pos + QtCore.QPoint(1, 1)) # Find out which widget is under our current mouse position hovered_widget = QtWidgets.QApplication.widgetAt(global_pos) if self.hovered_widget: # Bail out, this is the same widget we are already hovered on if self.hovered_widget is hovered_widget: return False # Update our hovered widget and label self.hovered_widget = hovered_widget self.update_hovered_widget_popup() elif event_type == QEvent.KeyRelease: if event.key() == Qt.Key_Escape: # Cancel the inspect mode if the Escape key is pressed # We don't need to actually hide the inspect popup here because # it will be hidden already by the Escape action self.inspect_mode = False elif event_type == QEvent.MouseButtonPress or event_type == QEvent.MouseButtonRelease: # Trigger inspecting the currently hovered widget when the left mouse button is clicked # Don't continue processing this event if self.inspect_mode and event.button() == Qt.LeftButton: # Only trigger the inspect on the click release, but we want to also eat the press # event so that the widget we clicked on isn't stuck in a weird state (e.g. thinks its being dragged) # Also hide the inspect popup since it won't be hidden automatically by the mouse click since we are # consuming the event if event_type == event_type == QEvent.MouseButtonRelease: self.inspect_popup.hide() self.inspect_widget() return True # Pass every event through return False def build_tree(self, obj, parent_tree): if len(obj.children()) == 0: return for child in obj.children(): object_type = type(child).__name__ object_name = child.objectName() text = icon_text = title = window_title = geometry_str = classes = "(N/A)" if isinstance(child, QtGui.QWindow): title = child.title() if isinstance(child, QAction): text = child.text() icon_text = child.iconText() if isinstance(child, QWidget): window_title = child.windowTitle() if not (child.property("class") == ""): classes = child.property("class") if isinstance(child, QAbstractButton): text = child.text() # Keep track of the pointer address for this object so we can search for it later pointer_address = str(int(getCppPointer(child)[0])) # Some objects might not have a geometry (e.g. actions, generic qobjects) if hasattr(child, 'geometry'): geometry_rect = child.geometry() geometry_str = "x: {x}, y: {y}, width: {width}, height: {height}".format( x=geometry_rect.x(), y=geometry_rect.y(), width=geometry_rect.width(), height=geometry_rect.height()) child_tree = QTreeWidgetItem([ object_type, object_name, text, icon_text, title, window_title, classes, pointer_address, geometry_str ]) if isinstance(parent_tree, QTreeWidget): parent_tree.addTopLevelItem(child_tree) else: parent_tree.addChild(child_tree) self.build_tree(child, child_tree) def update_hovered_widget_popup(self): if self.inspect_mode and self.hovered_widget: if not self.inspect_popup.isVisible(): self.inspect_popup.show() self.inspect_popup.update_widget(self.hovered_widget) else: self.inspect_popup.hide() def on_inspect_clicked(self): self.inspect_mode = True self.update_hovered_widget_popup() def on_tree_widget_selection_changed(self): selected_items = self.tree_widget.selectedItems() # If nothing is selected, then switch the stacked layout back to 0 # to show the message if not selected_items: self.stacked_layout.setCurrentIndex(0) return # Update the selected widget properties and switch to the 1 index in # the stacked layout so that all the rows will be visible item = selected_items[0] self.name_value.setText( item.text(self.tree_widget_columns.index("OBJECT NAME"))) self.type_value.setText( item.text(self.tree_widget_columns.index("TYPE"))) self.geometry_value.setText( item.text(self.tree_widget_columns.index("GEOMETRY"))) self.text_value.setText( item.text(self.tree_widget_columns.index("TEXT"))) self.icon_text_value.setText( item.text(self.tree_widget_columns.index("ICONTEXT"))) self.title_value.setText( item.text(self.tree_widget_columns.index("TITLE"))) self.window_title_value.setText( item.text(self.tree_widget_columns.index("WINDOW_TITLE"))) self.classes_value.setText( item.text(self.tree_widget_columns.index("CLASSES"))) self.stacked_layout.setCurrentIndex(1) def inspect_widget(self): self.inspect_mode = False # Find the tree widget item that matches our hovered widget, and then set it as the current item # so that the tree widget will scroll to it, expand it, and select it widget_pointer_address = str(int( getCppPointer(self.hovered_widget)[0])) pointer_address_column = self.tree_widget_columns.index( "POINTER_ADDRESS") items = self.tree_widget.findItems( widget_pointer_address, Qt.MatchFixedString | Qt.MatchRecursive, pointer_address_column) if items: item = items[0] self.tree_widget.clearSelection() self.tree_widget.setCurrentItem(item) else: print("Unable to find widget")
class AddOrManageObjectGroupDialog(QDialog): def __init__(self, parent, object_class_item, db_mngr, *db_maps): """ Args: parent (SpineDBEditor): data store widget object_class_item (ObjectClassItem) db_mngr (SpineDBManager) *db_maps: database mappings """ super().__init__(parent) self.object_class_item = object_class_item self.db_mngr = db_mngr self.db_maps = db_maps self.db_map = db_maps[0] self.db_maps_by_codename = { db_map.codename: db_map for db_map in db_maps } self.db_combo_box = QComboBox(self) self.header_widget = QWidget(self) self.group_name_line_edit = QLineEdit(self) header_layout = QHBoxLayout(self.header_widget) header_layout.addWidget(QLabel(f"Group name: ")) header_layout.addWidget(self.group_name_line_edit) header_layout.addSpacing(32) header_layout.addWidget(QLabel("Database")) header_layout.addWidget(self.db_combo_box) self.non_members_tree = QTreeWidget(self) self.non_members_tree.setHeaderLabel("Non members") self.non_members_tree.setSelectionMode(QTreeWidget.ExtendedSelection) self.non_members_tree.setColumnCount(1) self.non_members_tree.setIndentation(0) self.members_tree = QTreeWidget(self) self.members_tree.setHeaderLabel("Members") self.members_tree.setSelectionMode(QTreeWidget.ExtendedSelection) self.members_tree.setColumnCount(1) self.members_tree.setIndentation(0) self.add_button = QToolButton() self.add_button.setToolTip("<p>Add selected non-members.</p>") self.add_button.setIcon(QIcon(":/icons/menu_icons/cube_plus.svg")) self.add_button.setIconSize(QSize(24, 24)) self.add_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.add_button.setText(">>") self.remove_button = QToolButton() self.remove_button.setToolTip("<p>Remove selected members.</p>") self.remove_button.setIcon(QIcon(":/icons/menu_icons/cube_minus.svg")) self.remove_button.setIconSize(QSize(24, 24)) self.remove_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.remove_button.setText("<<") self.vertical_button_widget = QWidget() vertical_button_layout = QVBoxLayout(self.vertical_button_widget) vertical_button_layout.addStretch() vertical_button_layout.addWidget(self.add_button) vertical_button_layout.addWidget(self.remove_button) vertical_button_layout.addStretch() self.button_box = QDialogButtonBox(self) self.button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) layout = QGridLayout(self) layout.addWidget(self.header_widget, 0, 0, 1, 3, Qt.AlignHCenter) layout.addWidget(self.non_members_tree, 1, 0) layout.addWidget(self.vertical_button_widget, 1, 1) layout.addWidget(self.members_tree, 1, 2) layout.addWidget(self.button_box, 2, 0, 1, 3) self.setAttribute(Qt.WA_DeleteOnClose) self.db_combo_box.addItems(list(self.db_maps_by_codename)) self.db_map_object_ids = { db_map: { x["name"]: x["id"] for x in self.db_mngr.get_items_by_field( self.db_map, "object", "class_id", self.object_class_item.db_map_id(db_map)) } for db_map in db_maps } self.reset_list_widgets(db_maps[0].codename) self.connect_signals() def connect_signals(self): """Connect signals to slots.""" self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.reject) self.db_combo_box.currentTextChanged.connect(self.reset_list_widgets) self.add_button.clicked.connect(self.add_members) self.remove_button.clicked.connect(self.remove_members) def reset_list_widgets(self, database): self.db_map = self.db_maps_by_codename[database] object_ids = self.db_map_object_ids[self.db_map] members = [] non_members = [] for obj_name, obj_id in object_ids.items(): if obj_id in self.initial_member_ids(): members.append(obj_name) elif obj_id != self.initial_entity_id(): non_members.append(obj_name) member_items = [QTreeWidgetItem([obj_name]) for obj_name in members] non_member_items = [ QTreeWidgetItem([obj_name]) for obj_name in non_members ] self.members_tree.addTopLevelItems(member_items) self.non_members_tree.addTopLevelItems(non_member_items) def initial_member_ids(self): raise NotImplementedError() def initial_entity_id(self): raise NotImplementedError() @Slot(bool) def add_members(self, checked=False): indexes = sorted([ self.non_members_tree.indexOfTopLevelItem(x) for x in self.non_members_tree.selectedItems() ], reverse=True) items = [ self.non_members_tree.takeTopLevelItem(ind) for ind in indexes ] self.members_tree.addTopLevelItems(items) @Slot(bool) def remove_members(self, checked=False): indexes = sorted([ self.members_tree.indexOfTopLevelItem(x) for x in self.members_tree.selectedItems() ], reverse=True) items = [self.members_tree.takeTopLevelItem(ind) for ind in indexes] self.non_members_tree.addTopLevelItems(items) def _check_validity(self): if not self.members_tree.topLevelItemCount(): self.parent().msg_error.emit( "Please select at least one member object.") return False return True
class TallyDock(PlotterDock): def __init__(self, model, font_metric, parent=None): super().__init__(model, font_metric, parent) self.setAllowedAreas(QtCore.Qt.RightDockWidgetArea) # Dock maps for tally information self.tally_map = {} self.filter_map = {} self.score_map = {} self.nuclide_map = {} # Tally selector self.tallySelectorLayout = QFormLayout() self.tallySelector = QComboBox(self) self.tallySelector.currentTextChanged[str].connect( self.main_window.editSelectedTally) self.tallySelectorLayout.addRow(self.tallySelector) self.tallySelectorLayout.setLabelAlignment(QtCore.Qt.AlignLeft) self.tallySelectorLayout.setFieldGrowthPolicy( QFormLayout.AllNonFixedFieldsGrow) # Add selector to its own box self.tallyGroupBox = QGroupBox('Selected Tally') self.tallyGroupBox.setLayout(self.tallySelectorLayout) # Create submit button self.applyButton = QPushButton("Apply Changes") self.applyButton.setMinimumHeight(self.font_metric.height() * 1.6) self.applyButton.clicked.connect(self.main_window.applyChanges) # Color options section self.tallyColorForm = ColorForm(self.model, self.main_window, 'tally') self.scoresGroupBox = Expander(title="Scores:") self.scoresListWidget = QListWidget() self.nuclidesListWidget = QListWidget() # Main layout self.dockLayout = QVBoxLayout() self.dockLayout.addWidget(QLabel("Tallies")) self.dockLayout.addWidget(HorizontalLine()) self.dockLayout.addWidget(self.tallyGroupBox) self.dockLayout.addStretch() self.dockLayout.addWidget(HorizontalLine()) self.dockLayout.addWidget(self.tallyColorForm) self.dockLayout.addWidget(HorizontalLine()) self.dockLayout.addWidget(self.applyButton) # Create widget for dock and apply main layout self.scroll = QScrollArea() self.scroll.setWidgetResizable(True) self.widget = QWidget() self.widget.setLayout(self.dockLayout) self.scroll.setWidget(self.widget) self.setWidget(self.scroll) def _createFilterTree(self, spatial_filters): av = self.model.activeView tally = self.model.statepoint.tallies[av.selectedTally] filters = tally.filters # create a tree for the filters self.treeLayout = QVBoxLayout() self.filterTree = QTreeWidget() self.treeLayout.addWidget(self.filterTree) self.treeExpander = Expander("Filters:", layout=self.treeLayout) self.treeExpander.expand() # start with filters expanded header = QTreeWidgetItem(["Filters"]) self.filterTree.setHeaderItem(header) self.filterTree.setItemHidden(header, True) self.filterTree.setColumnCount(1) self.filterTree.itemChanged.connect(self.updateFilters) self.filter_map = {} self.bin_map = {} for tally_filter in filters: filter_label = str(type(tally_filter)).split(".")[-1][:-2] filter_item = QTreeWidgetItem(self.filterTree, (filter_label,)) self.filter_map[tally_filter] = filter_item # make checkable if not spatial_filters: filter_item.setFlags(QtCore.Qt.ItemIsUserCheckable) filter_item.setToolTip(0, "Only tallies with spatial filters are viewable.") else: filter_item.setFlags(filter_item.flags() | QtCore.Qt.ItemIsTristate | QtCore.Qt.ItemIsUserCheckable) filter_item.setCheckState(0, QtCore.Qt.Unchecked) # all mesh bins are selected by default and not shown in the dock if isinstance(tally_filter, openmc.MeshFilter): filter_item.setCheckState(0, QtCore.Qt.Checked) filter_item.setFlags(QtCore.Qt.ItemIsUserCheckable) filter_item.setToolTip(0, "All Mesh bins are selected automatically") continue def _bin_sort_val(bin): if isinstance(bin, Iterable) and all([isinstance(val, float) for val in bin]): return np.sum(bin) else: return bin for bin in sorted(tally_filter.bins, key=_bin_sort_val): item = QTreeWidgetItem(filter_item, [str(bin),]) if not spatial_filters: item.setFlags(QtCore.Qt.ItemIsUserCheckable) item.setToolTip(0, "Only tallies with spatial filters are viewable.") else: item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable) item.setCheckState(0, QtCore.Qt.Unchecked) bin = bin if not isinstance(bin, Iterable) else tuple(bin) self.bin_map[tally_filter, bin] = item # start with all filters selected if spatial filters are present if spatial_filters: filter_item.setCheckState(0, QtCore.Qt.Checked) def selectFromModel(self): cv = self.model.currentView self.selectedTally(cv.selectedTally) def selectTally(self, tally_label=None): # using active view to populate tally options live av = self.model.activeView # reset form layout for i in reversed(range(self.tallySelectorLayout.count())): self.tallySelectorLayout.itemAt(i).widget().setParent(None) # always re-add the tally selector to the layout self.tallySelectorLayout.addRow(self.tallySelector) self.tallySelectorLayout.addRow(HorizontalLine()) if tally_label is None or tally_label == "None" or tally_label == "": av.selectedTally = None self.score_map = None self.nuclide_map = None self.filter_map = None av.tallyValue = "Mean" else: # get the tally tally = self.model.statepoint.tallies[av.selectedTally] # populate filters filter_types = {type(f) for f in tally.filters} spatial_filters = bool(filter_types.intersection(_SPATIAL_FILTERS)) if not spatial_filters: self.filter_description = QLabel("(No Spatial Filters)") self.tallySelectorLayout.addRow(self.filter_description) self._createFilterTree(spatial_filters) self.tallySelectorLayout.addRow(self.treeExpander) self.tallySelectorLayout.addRow(HorizontalLine()) # value selection self.tallySelectorLayout.addRow(QLabel("Value:")) self.valueBox = QComboBox(self) self.values = tuple(_TALLY_VALUES.keys()) for value in self.values: self.valueBox.addItem(value) self.tallySelectorLayout.addRow(self.valueBox) self.valueBox.currentTextChanged[str].connect( self.main_window.editTallyValue) self.updateTallyValue() if not spatial_filters: self.valueBox.setEnabled(False) self.valueBox.setToolTip("Only tallies with spatial filters are viewable.") # scores self.score_map = {} self.scoresListWidget.itemClicked.connect( self.main_window.updateScores) self.score_map.clear() self.scoresListWidget.clear() sorted_scores = sorted(tally.scores) # always put total first if present if 'total' in sorted_scores: idx = sorted_scores.index('total') sorted_scores.insert(0, sorted_scores.pop(idx)) for score in sorted_scores: ql = QListWidgetItem() ql.setText(score.capitalize()) ql.setCheckState(QtCore.Qt.Unchecked) if not spatial_filters: ql.setFlags(QtCore.Qt.ItemIsUserCheckable) else: ql.setFlags(ql.flags() | QtCore.Qt.ItemIsUserCheckable) ql.setFlags(ql.flags() & ~QtCore.Qt.ItemIsSelectable) self.score_map[score] = ql self.scoresListWidget.addItem(ql) # select the first score item by default for item in self.score_map.values(): item.setCheckState(QtCore.Qt.Checked) break self.updateScores() self.scoresGroupBoxLayout = QVBoxLayout() self.scoresGroupBoxLayout.addWidget(self.scoresListWidget) self.scoresGroupBox = Expander("Scores:", layout=self.scoresGroupBoxLayout) self.tallySelectorLayout.addRow(self.scoresGroupBox) # nuclides self.nuclide_map = {} self.nuclidesListWidget.itemClicked.connect(self.main_window.updateNuclides) self.nuclide_map.clear() self.nuclidesListWidget.clear() sorted_nuclides = sorted(tally.nuclides) # always put total at the top if 'total' in sorted_nuclides: idx = sorted_nuclides.index('total') sorted_nuclides.insert(0, sorted_nuclides.pop(idx)) for nuclide in sorted_nuclides: ql = QListWidgetItem() ql.setText(nuclide.capitalize()) ql.setCheckState(QtCore.Qt.Unchecked) if not spatial_filters: ql.setFlags(QtCore.Qt.ItemIsUserCheckable) else: ql.setFlags(ql.flags() | QtCore.Qt.ItemIsUserCheckable) ql.setFlags(ql.flags() & ~QtCore.Qt.ItemIsSelectable) self.nuclide_map[nuclide] = ql self.nuclidesListWidget.addItem(ql) # select the first nuclide item by default for item in self.nuclide_map.values(): item.setCheckState(QtCore.Qt.Checked) break self.updateNuclides() self.nuclidesGroupBoxLayout = QVBoxLayout() self.nuclidesGroupBoxLayout.addWidget(self.nuclidesListWidget) self.nuclidesGroupBox = Expander("Nuclides:", layout=self.nuclidesGroupBoxLayout) self.tallySelectorLayout.addRow(self.nuclidesGroupBox) def updateMinMax(self): self.tallyColorForm.updateMinMax() def updateTallyValue(self): cv = self.model.currentView idx = self.valueBox.findText(cv.tallyValue) self.valueBox.setCurrentIndex(idx) def updateSelectedTally(self): cv = self.model.currentView idx = 0 if cv.selectedTally: idx = self.tallySelector.findData(cv.selectedTally) self.tallySelector.setCurrentIndex(idx) def updateFilters(self): applied_filters = defaultdict(tuple) for f, f_item in self.filter_map.items(): if type(f) == openmc.MeshFilter: continue filter_checked = f_item.checkState(0) if filter_checked != QtCore.Qt.Unchecked: selected_bins = [] for idx, b in enumerate(f.bins): b = b if not isinstance(b, Iterable) else tuple(b) bin_checked = self.bin_map[(f, b)].checkState(0) if bin_checked == QtCore.Qt.Checked: selected_bins.append(idx) applied_filters[f] = tuple(selected_bins) self.model.appliedFilters = applied_filters def updateScores(self): applied_scores = [] for score, score_box in self.score_map.items(): if score_box.checkState() == QtCore.Qt.CheckState.Checked: applied_scores.append(score) self.model.appliedScores = tuple(applied_scores) if not applied_scores: # if no scores are selected, enable all scores again for score, score_box in self.score_map.items(): sunits = _SCORE_UNITS.get(score, _REACTION_UNITS) empty_item = QListWidgetItem() score_box.setFlags(empty_item.flags() | QtCore.Qt.ItemIsUserCheckable) score_box.setFlags(empty_item.flags() & ~QtCore.Qt.ItemIsSelectable) elif 'total' in applied_scores: self.model.appliedScores = ('total',) # if total is selected, disable all other scores for score, score_box in self.score_map.items(): if score != 'total': score_box.setFlags(QtCore.Qt.ItemIsUserCheckable) score_box.setToolTip("De-select 'total' to enable other scores") else: # get units of applied scores selected_units = _SCORE_UNITS.get(applied_scores[0], _REACTION_UNITS) # disable scores with incompatible units for score, score_box in self.score_map.items(): sunits = _SCORE_UNITS.get(score, _REACTION_UNITS) if sunits != selected_units: score_box.setFlags(QtCore.Qt.ItemIsUserCheckable) score_box.setToolTip("Score is incompatible with currently selected scores") else: score_box.setFlags(score_box.flags() | QtCore.Qt.ItemIsUserCheckable) score_box.setFlags(score_box.flags() & ~QtCore.Qt.ItemIsSelectable) def updateNuclides(self): applied_nuclides = [] for nuclide, nuclide_box in self.nuclide_map.items(): if nuclide_box.checkState() == QtCore.Qt.CheckState.Checked: applied_nuclides.append(nuclide) self.model.appliedNuclides = tuple(applied_nuclides) if 'total' in applied_nuclides: self.model.appliedNuclides = ['total',] for nuclide, nuclide_box in self.nuclide_map.items(): if nuclide != 'total': nuclide_box.setFlags(QtCore.Qt.ItemIsUserCheckable) nuclide_box.setToolTip("De-select 'total' to enable other nuclides") elif not applied_nuclides: # if no nuclides are selected, enable all nuclides again for nuclide, nuclide_box in self.nuclide_map.items(): empty_item = QListWidgetItem() nuclide_box.setFlags(empty_item.flags() | QtCore.Qt.ItemIsUserCheckable) nuclide_box.setFlags(empty_item.flags() & ~QtCore.Qt.ItemIsSelectable) def update(self): # update the color form self.tallyColorForm.update() if self.model.statepoint: self.tallySelector.clear() self.tallySelector.setEnabled(True) self.tallySelector.addItem("None") for idx, tally in enumerate(self.model.statepoint.tallies.values()): if tally.name == "": self.tallySelector.addItem('Tally {}'.format(tally.id), userData=tally.id) else: self.tallySelector.addItem('Tally {} "{}"'.format(tally.id, tally.name), userData=tally.id) self.tally_map[idx] = tally self.updateSelectedTally() self.updateMinMax() else: self.tallySelector.clear() self.tallySelector.setDisabled(True)
class MemTree(QWidget): def __init__(self, qmp, parent): super().__init__() self.qmp = qmp self.qmp.memoryMap.connect(self.update_tree) self.parent = parent self.tree_sem = QSemaphore(1) self.sending_sem = QSemaphore( 1) # used to prevent sending too many requests at once self.init_ui() self.get_map() def init_ui(self): self.vbox = QVBoxLayout() self.refresh = QPushButton('Refresh') self.refresh.clicked.connect(lambda: self.get_map()) self.vbox.addWidget(self.refresh) self.tree = QTreeWidget() self.tree.itemDoubleClicked.connect(self.open_region) self.tree.setColumnCount(3) self.tree.header().setSectionResizeMode(QHeaderView.ResizeToContents) self.tree.header().setStretchLastSection(False) self.tree.setHeaderLabels( ['Memory Region', 'Start Address', 'End Address']) self.vbox.addWidget(self.tree) self.setLayout(self.vbox) self.setGeometry(100, 100, 500, 300) self.setWindowTitle("Memory Tree") self.show() def get_map(self): self.tree.clear() self.qmp.command('mtree') # finds item with name 'name' in self.tree # self.tree_sem must be acquired before use def find(self, name, node): if node.text(0) == name: return node else: for i in range(node.childCount()): result = self.find(name, node.child(i)) if result: return result return None def update_tree(self, value): if value != None: self.tree_sem.acquire() current_addr_space = '' for region in value: parent_node = self.tree parent = region['parent'] if parent != '': root = self.tree.invisibleRootItem() for i in range(root.childCount()): if root.child(i).text(0) == current_addr_space: root = root.child(i) break parent_node = self.find(parent, root) else: current_addr_space = region['name'] node = QTreeWidgetItem(parent_node) node.setText(0, region['name']) start = region['start'] end = region['end'] if start < 0: start = start + (1 << constants['bits']) if end < 0: end = end + (1 << constants['bits']) node.setText(1, f'{start:016x}') node.setText(2, f'{end:016x}') node.setFont(0, QFont('Courier New')) node.setFont(1, QFont('Courier New')) node.setFont(2, QFont('Courier New')) self.tree_sem.release() def open_region(self, node, col): self.parent.open_new_window( MemDumpWindow(self.qmp, base=int(node.text(1), 16), max=int(node.text(2), 16)))
class DiscoverUi(QWidget): def __init__(self): super().__init__() self.discover = Discover() self.devices = self.discover.devices self.listWidget = None self.treeWidget = None self.initUI() self.mac_addr = None def initDevices(self): for device in self.devices: newItem = QListWidgetItem() newItem.setText(device.name + " (" + device.address + ")") self.listWidget.addItem(newItem) def initUI(self): self.listWidget = QListWidget() self.initDevices() self.treeWidget = QTreeWidget() self.treeWidget.itemPressed.connect(self.onItemPressed) self.treeWidget.setColumnCount(4) self.treeWidget.setColumnWidth(0, 250) self.treeWidget.setColumnWidth(1, 300) self.treeWidget.setColumnWidth(2, 300) self.treeWidget.setColumnWidth(3, 150) self.treeWidget.setHeaderLabels(["Service", "Service UUID", "Characteristic UUID", "Characteristic Property"]) btn = QPushButton("Read Services") btn.clicked.connect(self.onPushButton) groupDevices = QGroupBox("Devices") groupDevices.setMaximumWidth(300) vbox = QVBoxLayout() vbox.addWidget(self.listWidget) vbox.addWidget(btn) groupDevices.setLayout(vbox) self.btnR = QPushButton("Read") self.btnR.clicked.connect(self.onReadButton) self.btnW = QPushButton("Write") self.btnW.clicked.connect(self.onWriteButton) self.lneI = QLineEdit() self.chkN = QCheckBox("Notify") self.chkN.toggled.connect(self.onNotifyCheck) hbox = QHBoxLayout() hbox.addWidget(self.btnR) hbox.addWidget(self.btnW) hbox.addWidget(self.lneI) hbox.addWidget(self.chkN) groupProperty = QGroupBox("Property") #groupProperty.setLayout(vbox) groupProperty.setLayout(hbox) groupServices = QGroupBox("Services") vbox = QVBoxLayout() vbox.addWidget(self.treeWidget) vbox.addWidget(groupProperty) groupServices.setLayout(vbox) hbox = QHBoxLayout() hbox.addWidget(groupDevices) hbox.addWidget(groupServices) self.setLayout(hbox) self.setGeometry(300, 300, 800, 600) self.setWindowTitle('BLE Discover') self.show() def onPushButton(self): try: self.mac_addr = self.devices[self.listWidget.currentRow()].address self.discover.getServices(self.mac_addr) except: print("Could not get GATT services.") else: svcs = self.discover.svcs for serviceKey, serviceValue in svcs.services.items(): item = QTreeWidgetItem(None, [serviceValue.description, serviceValue.uuid]) for characteristic in serviceValue.characteristics: for property in characteristic.properties: child = QTreeWidgetItem(["", "", characteristic.uuid, property]) item.addChild(child) self.treeWidget.addTopLevelItem(item) def onReadButton(self): byteArray = self.discover.readGattChar(self.mac_addr, self.chosenUuid) text = ''.join('{:02x}'.format(x) for x in byteArray) self.lneI.setText(text) def onWriteButton(self): text = self.lneI.text() print("onWriteButton") self.discover.writeGattChar(self.mac_addr, self.chosenUuid, bytes.fromhex(text)) def notifyCallback(self, sender, data): text = ''.join('{:02x}'.format(x) for x in data) self.lneI.textChanged.emit(text) def onNotifyCheck(self, checked): if checked: print("onNotifyCheck") self.discover.startNotify(self.mac_addr, self.chosenUuid, self.notifyCallback) else: print("onNotifyCheck else") def onItemPressed(self, item, column): if item.child(0) is None: print(item) print(item.text(2)) print(item.text(3)) self.chosenUuid = item.text(2) property = item.text(3) if property == "read": self.btnR.setEnabled(True) self.btnW.setEnabled(False) self.lneI.setEnabled(False) self.chkN.setEnabled(False) elif property == "write": self.btnR.setEnabled(True) self.btnW.setEnabled(True) self.lneI.setEnabled(True) self.chkN.setEnabled(False) elif property == "notify": self.btnR.setEnabled(False) self.btnW.setEnabled(False) self.lneI.setEnabled(False) self.chkN.setEnabled(True)