class DockTitleBar(QWidget, object): def __init__(self, dock_widget, renamable=False): super(DockTitleBar, self).__init__(dock_widget) self._renamable = renamable main_layout = QHBoxLayout() main_layout.setContentsMargins(0, 0, 0, 1) self.setLayout(main_layout) self._buttons_box = QGroupBox('') self._buttons_box.setObjectName('Docked') self._buttons_layout = QHBoxLayout() self._buttons_layout.setSpacing(1) self._buttons_layout.setMargin(2) self._buttons_box.setLayout(self._buttons_layout) main_layout.addWidget(self._buttons_box) self._title_label = QLabel(self) self._title_label.setStyleSheet('background: transparent') self._title_edit = QLineEdit(self) self._title_edit.setVisible(False) self._button_size = QSize(14, 14) self._dock_btn = QToolButton(self) self._dock_btn.setIcon(resources.icon('restore_window', theme='color')) self._dock_btn.setMaximumSize(self._button_size) self._dock_btn.setAutoRaise(True) self._close_btn = QToolButton(self) self._close_btn.setIcon(resources.icon('close_window', theme='color')) self._close_btn.setMaximumSize(self._button_size) self._close_btn.setAutoRaise(True) self._buttons_layout.addSpacing(2) self._buttons_layout.addWidget(self._title_label) self._buttons_layout.addWidget(self._title_edit) self._buttons_layout.addStretch() self._buttons_layout.addSpacing(5) self._buttons_layout.addWidget(self._dock_btn) self._buttons_layout.addWidget(self._close_btn) self._buttons_box.mouseDoubleClickEvent = self.mouseDoubleClickEvent self._buttons_box.mousePressEvent = self.mousePressEvent self._buttons_box.mouseMoveEvent = self.mouseMoveEvent self._buttons_box.mouseReleaseEvent = self.mouseReleaseEvent dock_widget.featuresChanged.connect(self._on_dock_features_changed) self._title_edit.editingFinished.connect(self._on_finish_edit) self._dock_btn.clicked.connect(self._on_dock_btn_clicked) self._close_btn.clicked.connect(self._on_close_btn_clicked) self._on_dock_features_changed(dock_widget.features()) self.set_title(dock_widget.windowTitle()) dock_widget.installEventFilter(self) dock_widget.topLevelChanged.connect(self._on_change_floating_style) @property def renamable(self): return self._renamable @renamable.setter def renamable(self, flag): self._renamable = flag def eventFilter(self, obj, event): if event.type() == QEvent.WindowTitleChange: self.set_title(obj.windowTitle()) return super(DockTitleBar, self).eventFilter(obj, event) def mouseMoveEvent(self, event): event.ignore() def mousePressEvent(self, event): event.ignore() def mouseReleaseEvent(self, event): event.ignore() def mouseDoubleClickEvent(self, event): if event.pos().x() <= self._title_label.width() and self._renamable: self._start_edit() else: super(DockTitleBar, self).mouseDoubleClickEvent(event) def update(self, *args, **kwargs): self._on_change_floating_style(self.parent().isFloating()) super(DockTitleBar, self).update(*args, **kwargs) def set_title(self, title): self._title_label.setText(title) self._title_edit.setText(title) def add_button(self, button): button.setAutoRaise(True) button.setMaximumSize(self._button_size) self._buttons_layout.insertWidget(5, button) def _start_edit(self): self._title_label.hide() self._title_edit.show() self._title_edit.setFocus() def _finish_edit(self): self._title_edit.hide() self._title_label.show() self.parent().setWindowTitle(self._title_edit.text()) def _on_dock_features_changed(self, features): if not features & QDockWidget.DockWidgetVerticalTitleBar: self._close_btn.setVisible(features & QDockWidget.DockWidgetClosable) self._dock_btn.setVisible(features & QDockWidget.DockWidgetFloatable) else: raise ValueError('Vertical title bar is not supported!') def _on_finish_edit(self): self._finish_edit() def _on_dock_btn_clicked(self): self.parent().setFloating(not self.parent().isFloating()) def _on_close_btn_clicked(self): self.parent().toggleViewAction().setChecked(False) self.parent().close() def _on_change_floating_style(self, state): pass
class IndexedStringsWidget(QWidget): """ Holds the list of indexed string attributes """ def __init__(self, data, parent=None): QWidget.__init__(self, parent) self.data = data vbox = QVBoxLayout() self.setLayout(vbox) title = QLabel('Indexed Strings') vbox.addWidget(title) self.frame = QFrame() vbox.addWidget(self.frame) self.vbox = QVBoxLayout() self.frame.setLayout(self.vbox) self.frame.setFrameShape(QFrame.Panel) self.frame.setFrameShadow(QFrame.Sunken) self.table = QTableWidget() self.table.horizontalHeader().hide() self.vbox.addWidget(self.table) self.table.hide() self.noStringsLabel = QLabel('<i>No indexed strings</i>') self.vbox.addWidget(self.noStringsLabel) self.widgets = [] self.populate() self.data.attributeAdded.connect(self.attributeAddedSlot) self.data.dataReset.connect(self.dataResetSlot) self.data.dirtied.connect(self.dataDirtiedSlot) def dataDirtiedSlot(self, dirty): """ SLOT when the particle data is dirtied or cleaned.""" if not dirty: for widget in self.widgets: widget.drawBorder(False) def dataResetSlot(self): """ SLOT when particle data is reconstructed """ self.populate() def attributeAddedSlot(self, name): #pylint:disable=W0613 """ SLOT when an attribute is added to the particle set """ attr = self.data.attributeInfo(name) if attr.type == partio.INDEXEDSTR: self.populate() def populate(self): """ Populates the table of indexed strings """ self.widgets = [] # If no widgets, just drop that in attrs = [] for anum in range(self.data.numAttributes()): attr = self.data.attributeInfo(anum) if attr.type == partio.INDEXEDSTR: attrs.append(attr) if not attrs: self.table.hide() self.noStringsLabel.show() return self.table.show() self.noStringsLabel.hide() self.table.setColumnCount(1) self.table.setRowCount(len(attrs)) for row, attr in enumerate(attrs): item = QTableWidgetItem(attr.name) self.table.setVerticalHeaderItem(row, item) strings = self.data.indexedStrs(attr) table = QTableWidget() table.setColumnCount(1) table.setRowCount(len(strings)) table.horizontalHeader().hide() table.setVerticalHeaderLabels( [str(i) for i in range(len(strings))]) for i, string in enumerate(strings): widget = QLabel(string) table.setCellWidget(i, 0, widget) self.widgets.append(widget) self.table.setCellWidget(row, 0, table) self.table.horizontalHeader().setStretchLastSection(False) self.table.setTabKeyNavigation(True) self.table.horizontalHeader().setSectionsMovable(False) self.table.horizontalHeader().resizeSections( QHeaderView.ResizeToContents) self.table.verticalHeader().resizeSections( QHeaderView.ResizeToContents)
class IndexedStringsWidget(QWidget): """ Holds the list of indexed string attributes """ def __init__(self, data, parent=None): QWidget.__init__(self, parent) self.data = data vbox = QVBoxLayout() self.setLayout(vbox) title = QLabel('Indexed Strings') vbox.addWidget(title) self.frame = QFrame() vbox.addWidget(self.frame) self.vbox = QVBoxLayout() self.frame.setLayout(self.vbox) self.frame.setFrameShape(QFrame.Panel) self.frame.setFrameShadow(QFrame.Sunken) self.table = QTableWidget() self.table.horizontalHeader().hide() self.vbox.addWidget(self.table) self.table.hide() self.noStringsLabel = QLabel('<i>No indexed strings</i>') self.vbox.addWidget(self.noStringsLabel) self.widgets = [] self.populate() self.data.attributeAdded.connect(self.attributeAddedSlot) self.data.dataReset.connect(self.dataResetSlot) self.data.dirtied.connect(self.dataDirtiedSlot) def dataDirtiedSlot(self, dirty): """ SLOT when the particle data is dirtied or cleaned.""" if not dirty: for widget in self.widgets: widget.drawBorder(False) def dataResetSlot(self): """ SLOT when particle data is reconstructed """ self.populate() def attributeAddedSlot(self, name): #pylint:disable=W0613 """ SLOT when an attribute is added to the particle set """ attr = self.data.attributeInfo(name) if attr.type == partio.INDEXEDSTR: self.populate() def populate(self): """ Populates the table of indexed strings """ self.widgets = [] # If no widgets, just drop that in attrs = [] for anum in range(self.data.numAttributes()): attr = self.data.attributeInfo(anum) if attr.type == partio.INDEXEDSTR: attrs.append(attr) if not attrs: self.table.hide() self.noStringsLabel.show() return self.table.show() self.noStringsLabel.hide() self.table.setColumnCount(1) self.table.setRowCount(len(attrs)) for row, attr in enumerate(attrs): item = QTableWidgetItem(attr.name) self.table.setVerticalHeaderItem(row, item) strings = self.data.indexedStrs(attr) table = QTableWidget() table.setColumnCount(1) table.setRowCount(len(strings)) table.horizontalHeader().hide() table.setVerticalHeaderLabels([str(i) for i in range(len(strings))]) for i, string in enumerate(strings): widget = QLabel(string) table.setCellWidget(i, 0, widget) self.widgets.append(widget) self.table.setCellWidget(row, 0, table) self.table.horizontalHeader().setStretchLastSection(False) self.table.setTabKeyNavigation(True) self.table.horizontalHeader().setSectionsMovable(False) self.table.horizontalHeader().resizeSections(QHeaderView.ResizeToContents) self.table.verticalHeader().resizeSections(QHeaderView.ResizeToContents)
class FixedAttributesWidget(QWidget): """ A widget for viewing/editing fixed attributes (non-varying) """ def __init__(self, data, parent=None): QWidget.__init__(self, parent) self.data = data vbox = QVBoxLayout() self.setLayout(vbox) title = QLabel('Fixed Attributes') vbox.addWidget(title) self.frame = QFrame() vbox.addWidget(self.frame) self.vbox = QVBoxLayout() self.frame.setLayout(self.vbox) self.frame.setFrameShape(QFrame.Panel) self.frame.setFrameShadow(QFrame.Sunken) self.table = QTableWidget() self.table.horizontalHeader().hide() self.vbox.addWidget(self.table) self.table.hide() self.noAttrLabel = QLabel('<i>No fixed attributes</i>') self.vbox.addWidget(self.noAttrLabel) self.widgets = [] self.populate() self.data.fixedAttributeAdded.connect(self.fixedAttributeAddedSlot) self.data.dataReset.connect(self.dataResetSlot) self.data.dirtied.connect(self.dataDirtiedSlot) def dataDirtiedSlot(self, dirty): """ SLOT when the particle data is dirtied or cleaned.""" if not dirty: for widget in self.widgets: widget.drawBorder(False) def dataResetSlot(self): """ SLOT when particle data is reconstructed """ self.populate() def fixedAttributeAddedSlot(self, name): #pylint:disable=W0613 """ SLOT when a fixed attribute is added to the particle set """ self.populate() def populate(self): """ Populates the table of fixed attributes """ self.widgets = [] # If no widgets, just drop that in numAttrs = self.data.numFixedAttributes() if not numAttrs: self.table.hide() self.noAttrLabel.show() return self.table.show() self.noAttrLabel.hide() self.table.setColumnCount(1) self.table.setRowCount(numAttrs) self.attrs = getAttrs(self.data.numFixedAttributes, self.data.fixedAttributeInfo, True) for row, (_, attr) in enumerate(self.attrs): item = QTableWidgetItem(attr.name) tooltip = '<p><tt> Name: {}<br> Type: {}<br>Count: {}</tt></p>'.\ format(attr.name, partio.TypeName(attr.type), attr.count) item.setToolTip(tooltip) self.table.setVerticalHeaderItem(row, item) value = self.data.getFixed(attr) widget = getWidget(value, self.data, attr) self.table.setCellWidget(row, 0, widget) self.widgets.append(widget) self.table.horizontalHeader().setStretchLastSection(False) self.table.setTabKeyNavigation(True) self.table.horizontalHeader().setSectionsMovable(False) self.table.horizontalHeader().resizeSections( QHeaderView.ResizeToContents) self.table.verticalHeader().resizeSections( QHeaderView.ResizeToContents)
class FixedAttributesWidget(QWidget): """ A widget for viewing/editing fixed attributes (non-varying) """ def __init__(self, data, parent=None): QWidget.__init__(self, parent) self.data = data vbox = QVBoxLayout() self.setLayout(vbox) title = QLabel('Fixed Attributes') vbox.addWidget(title) self.frame = QFrame() vbox.addWidget(self.frame) self.vbox = QVBoxLayout() self.frame.setLayout(self.vbox) self.frame.setFrameShape(QFrame.Panel) self.frame.setFrameShadow(QFrame.Sunken) self.table = QTableWidget() self.table.horizontalHeader().hide() self.vbox.addWidget(self.table) self.table.hide() self.noAttrLabel = QLabel('<i>No fixed attributes</i>') self.vbox.addWidget(self.noAttrLabel) self.widgets = [] self.populate() self.data.fixedAttributeAdded.connect(self.fixedAttributeAddedSlot) self.data.dataReset.connect(self.dataResetSlot) self.data.dirtied.connect(self.dataDirtiedSlot) def dataDirtiedSlot(self, dirty): """ SLOT when the particle data is dirtied or cleaned.""" if not dirty: for widget in self.widgets: widget.drawBorder(False) def dataResetSlot(self): """ SLOT when particle data is reconstructed """ self.populate() def fixedAttributeAddedSlot(self, name): #pylint:disable=W0613 """ SLOT when a fixed attribute is added to the particle set """ self.populate() def populate(self): """ Populates the table of fixed attributes """ self.widgets = [] # If no widgets, just drop that in numAttrs = self.data.numFixedAttributes() if not numAttrs: self.table.hide() self.noAttrLabel.show() return self.table.show() self.noAttrLabel.hide() self.table.setColumnCount(1) self.table.setRowCount(numAttrs) self.attrs = getAttrs(self.data.numFixedAttributes, self.data.fixedAttributeInfo, True) for row, (_, attr) in enumerate(self.attrs): item = QTableWidgetItem(attr.name) tooltip = '<p><tt> Name: {}<br> Type: {}<br>Count: {}</tt></p>'.\ format(attr.name, partio.TypeName(attr.type), attr.count) item.setToolTip(tooltip) self.table.setVerticalHeaderItem(row, item) value = self.data.getFixed(attr) widget = getWidget(value, self.data, attr) self.table.setCellWidget(row, 0, widget) self.widgets.append(widget) self.table.horizontalHeader().setStretchLastSection(False) self.table.setTabKeyNavigation(True) self.table.horizontalHeader().setSectionsMovable(False) self.table.horizontalHeader().resizeSections(QHeaderView.ResizeToContents) self.table.verticalHeader().resizeSections(QHeaderView.ResizeToContents)