def sizeHint(self): """Overrides :meth:`QtWidgets.QWidget.sizeHint`.""" if self._shape == Shapes.Triangle: return QtCore.QSize(self._triangle_factor*self._height_hint, self._height_hint) elif self._shape == Shapes.Rounded: return QtCore.QSize(self._rounded_factor*self._height_hint, self._height_hint) return QtCore.QSize(self._height_hint, self._height_hint)
def __init__(self): app = application() self.tab_widget = QtWidgets.QTabWidget() self.main_window = QtWidgets.QMainWindow() self.main_window.setWindowTitle('Standard Icons') self.main_window.setCentralWidget(self.tab_widget) self.main_window.closeEvent = self.close_event # add a progress bar to the status bar self.progress_bar = QtWidgets.QProgressBar( self.main_window.statusBar()) self.progress_bar.setAlignment(QtCore.Qt.AlignCenter) self.main_window.statusBar().addPermanentWidget(self.progress_bar) self.main_window.showMaximized() self.num_icons = 0 self.file_index = 0 self.zoom_widget = QtWidgets.QDialog() self.zoom_widget.setSizeGripEnabled(True) self.zoom_widget.resize(QtCore.QSize(256, 256)) self.zoom_widget.setWindowFlags(QtCore.Qt.WindowCloseButtonHint) vbox = QtWidgets.QVBoxLayout() self.zoom_label = QtWidgets.QLabel() self.zoom_label.setScaledContents(True) vbox.addWidget(self.zoom_label) self.zoom_widget.setLayout(vbox) qt_icons = [sp for sp in dir(QtWidgets.QStyle) if sp.startswith('SP_')] self.windows_files = [ 'accessibilitycpl', 'compstui', 'ddores', 'dmdskres', 'explorer', 'gameux', 'ieframe', 'imageres', 'mmcndmgr', 'mmres', 'moricons', 'netcenter', 'netshell', 'networkexplorer', 'pifmgr', 'pnidui', 'sensorscpl', 'setupapi', 'shell32', 'wmploc', 'wpdshext' ] self.num_files = 1 + len(self.windows_files) self.progress_bar.setRange(0, self.num_files) self.add_qt_tab('Qt Icons', qt_icons) if has_clr: self.windows_index = 0 self.timer = QtCore.QTimer() self.timer.timeout.connect(self.add_windows_tab) self.timer.start(0) else: self.update_message('Loaded {} icons.'.format(self.num_icons)) self.progress_bar.hide() app.exec()
def test_icon_size(): int_val = QtWidgets.QStyle.SP_DriveNetIcon icon = convert.to_qicon(int_val) sizes = icon.availableSizes() if sys.platform == 'win32': assert len(sizes) > 1 # # specify the size to the get_icon function # b = Button(icon=convert.to_qicon(int_val)) assert b.text() == '' assert b.toolButtonStyle() == Qt.ToolButtonIconOnly assert b.iconSize() == sizes[0] b = Button(icon=convert.to_qicon(int_val, size=789)) assert b.iconSize() == QtCore.QSize(789, 789) b = Button(icon=convert.to_qicon(int_val, size=3.0)) # specifying a scale factor will use the largest available size assert b.iconSize() == QtCore.QSize(3 * sizes[-1].width(), 3 * sizes[-1].height()) b = Button(icon=convert.to_qicon(int_val, size=QtCore.QSize(50, 50))) assert b.iconSize() == QtCore.QSize(50, 50) for size in [(256, ), (256, 256, 256)]: with pytest.raises(ValueError, match='(width, height)'): Button(icon=convert.to_qicon(int_val, size=size)) # # use the icon_size kwarg # b = Button(icon=convert.to_qicon(int_val), icon_size=1234) assert b.iconSize() == QtCore.QSize(1234, 1234) b = Button(icon=convert.to_qicon(int_val), icon_size=3.0) # specifying a scale factor will use the largest available size assert b.iconSize() == QtCore.QSize(3 * sizes[-1].width(), 3 * sizes[-1].height()) b = Button(icon=convert.to_qicon(int_val), icon_size=(312, 312)) assert b.iconSize() == QtCore.QSize(312, 312) b = Button(icon=convert.to_qicon(int_val), icon_size=QtCore.QSize(500, 500)) assert b.iconSize() == QtCore.QSize(500, 500) for size in [(256, ), (256, 256, 256)]: with pytest.raises(ValueError, match='(width, height)'): Button(icon=convert.to_qicon(int_val), icon_size=size)
def test_icon(): path = os.path.dirname(__file__) + '/gamma.png' gamma_size = QtCore.QSize(191, 291) int_val = QtWidgets.QStyle.SP_DriveNetIcon icon = convert.to_qicon(int_val) sizes = icon.availableSizes() if sys.platform == 'win32': assert len(sizes) > 1 b = Button(icon=int_val) assert b.text() == '' assert not b.icon().isNull() assert b.iconSize() == sizes[0] assert b.toolButtonStyle() == Qt.ToolButtonIconOnly b = Button(icon=path) assert b.text() == '' assert not b.icon().isNull() assert b.iconSize() == gamma_size assert b.toolButtonStyle() == Qt.ToolButtonIconOnly b = Button(icon=convert.icon_to_base64(convert.to_qicon(path))) assert b.text() == '' assert not b.icon().isNull() assert b.iconSize() == gamma_size assert b.toolButtonStyle() == Qt.ToolButtonIconOnly
class _Execute(QtCore.QThread): sig_error = QtCore.pyqtSignal(str) sig_update_row_color = QtCore.pyqtSignal(str, int) sig_highlight_row = QtCore.pyqtSignal(int) sig_update_reply = QtCore.pyqtSignal(int, str) sig_show_execute_icon = QtCore.pyqtSignal() def __init__(self, parent): QtCore.QThread.__init__(self) self.parent = parent self._error = False def run(self): if self._error: return for index, action, delay, message in self.parent._command_list: if self._error or self.parent._abort_execution: self.sig_show_execute_icon.emit() break self.sig_highlight_row.emit(index) try: if action == 'read': if delay > 0: time.sleep(delay) reply = self.parent._conn.read() elif action == 'write': num_bytes = self.parent._conn.write(message) reply = '<sent {} bytes>'.format(num_bytes) elif action == 'query': reply = self.parent._conn.query(message, delay) elif action == 'delay': time.sleep(delay) reply = '' else: assert False, 'Method "{}" not implemented'.format(action) self.sig_update_reply.emit(index, reply.strip()) except Exception: self._error = True self.sig_error.emit('Row {}: {}({})\n\n{}'.format( index + 1, action, message, traceback.format_exc())) break finally: self.sig_update_row_color.emit(action, index)
def paintEvent(self, event): """Overrides :meth:`QtWidgets.QWidget.paintEvent`.""" option = QtWidgets.QStyleOption() option.initFrom(self) h = option.rect.height() w = option.rect.width() if self._shape == Shapes.Triangle or self._shape == Shapes.Rounded: aspect = self._triangle_factor if self._shape == Shapes.Triangle else self._rounded_factor ah = w / aspect aw = w if ah > h: ah = h aw = h * aspect x = abs(aw - w) / 2.0 y = abs(ah - h) / 2.0 bounds = QtCore.QRectF(x, y, aw, ah) else: size = min(w, h) x = abs(size - w) / 2.0 y = abs(size - h) / 2.0 bounds = QtCore.QRectF(x, y, size, size) painter = QtGui.QPainter(self) painter.setRenderHint(QtGui.QPainter.Antialiasing, True) if self.isEnabled(): color = self._on_color if self._is_on else self._off_color else: color = QtGui.QColor('#BDBDBD') lighter = QtGui.QColor(color).lighter(150) # 150 -> 50% brighter color_str = 'rgb(%d,%d,%d)' % (color.red(), color.green(), color.blue()) lighter_str = 'rgb(%d,%d,%d)' % (lighter.red(), lighter.green(), lighter.blue()) svg = (SVG_MAP[self._shape] % (color_str, lighter_str)).encode('utf8') self._renderer.load(QtCore.QByteArray(svg)) self._renderer.render(painter, bounds)
def test_to_qicon(): assert isinstance(convert.to_qicon(QtGui.QIcon()), QtGui.QIcon) assert isinstance(convert.to_qicon(QtGui.QPixmap()), QtGui.QIcon) assert isinstance(convert.to_qicon(QtGui.QImage()), QtGui.QIcon) assert isinstance(convert.to_qicon(QtWidgets.QStyle.SP_TitleBarMenuButton), QtGui.QIcon) assert isinstance(convert.to_qicon(14), QtGui.QIcon) base64 = 'iVBORw0KGgoAAAANSUhEUgAAACgAAABCCAYAAAAlkZRRAAAACXBIWXMAAAsTAAALEwEAmpwYAAABpElEQVR' \ 'oge2ZT07CQBSHf29kLXKOsnApBEx7DAl3sT2BZzAx6C1ahYBLFzRxyQ1Q12SeiwoSQonjzMiLmW9Fh+nMlz' \ 'ft/HkFhEOuGnofRLz+3RyVztpVrhryhXjBhu8OlsN2DADQ/NYalS+m93sXVJpzACBGASAxvt+1kGuCoC3On' \ 'kGXc9824iMYBG0JgrZ4X0lMWe+KtKKkdTcvQgT3sRy2Y6URr6+bo3laV/cogpUcX28VpbV1vdtY4iyCYcsv' \ 'lSBoi7j94G474iMoXjDMg7YEQVvEC4rPDxq/xctBdH7CuAGA0/vSOBlkivk0o+iMNcfuVWq6+6uOfot4wdo' \ 'h/riKcqbqYOMrMfQTxEdQvKC4/eAu4iMYBG0RL9gAthd6yg4lco6B+AiKFzSfB1erBVQj8+CyF2PB1sPrAg' \ 'fyea4RP8TiBb+GmDIA0ArF5h/CLUCPx5AKuISAsJJYIV4w8O8hAOj2O9VbTJRNn6YpAHT6nZxQnYun49nmQ' \ 'NTrXcSaKN8t37RRU85AMRvPEgDoXnZT8Pe3un31FXMymTzL/xwrXlA8n2MHdwPYAbB5AAAAAElFTkSuQmCC' assert isinstance(convert.to_qicon(QtCore.QByteArray(base64.encode())), QtGui.QIcon) assert isinstance(convert.to_qicon(bytearray(base64.encode())), QtGui.QIcon) default_size = convert.to_qicon( QtWidgets.QStyle.SP_TitleBarMenuButton).availableSizes()[-1] assert isinstance(default_size, QtCore.QSize) with pytest.raises(TypeError): convert.to_qicon(None) with pytest.raises(OSError): convert.to_qicon(99999) # not a valid QStyle.StandardPixmap enum value with pytest.raises(OSError): convert.to_qicon('this is not an icon') assert isinstance( convert.to_qicon(os.path.join(os.path.dirname(__file__), 'gamma.png')), QtGui.QIcon) # insert this directory into sys.path and check again sys.path.insert(0, os.path.dirname(__file__)) assert isinstance(convert.to_qicon('gamma.png'), QtGui.QIcon) icon_1 = convert.to_qicon('gamma.png').availableSizes()[0] icon_2 = convert.to_qicon('gamma.png', size=0.5).availableSizes()[0] assert int(icon_1.width() * 0.5) == icon_2.width() assert int(icon_1.height() * 0.5) == icon_2.height()
def test_drag_enter_paths(): mime = QtCore.QMimeData() event = QtGui.QDragEnterEvent(QtCore.QPoint(0, 0), Qt.CopyAction, mime, Qt.LeftButton, Qt.NoModifier) paths = utils.drag_drop_paths(event) assert len(paths) == 0 url1 = QtCore.QUrl('/path/to/image.jpeg') url1.setScheme('file') url2 = QtCore.QUrl( '') # does not pass the isValid() and scheme() == 'file' checks url3 = QtCore.QUrl('/path/to/image.jpeg') url3.setScheme('ftp') # does not pass the scheme() == 'file' check url4 = QtCore.QUrl('/path/to/image.png') url4.setScheme('file') url5 = QtCore.QUrl('/path/to/image2.jpg') url5.setScheme('file') mime.setUrls([url1, url2, url3, url4, url5]) event = QtGui.QDragEnterEvent(QtCore.QPoint(0, 0), Qt.CopyAction, mime, Qt.LeftButton, Qt.NoModifier) paths = utils.drag_drop_paths(event) assert len(paths) == 3 assert '/path/to/image.jpeg' in paths assert '/path/to/image.png' in paths assert '/path/to/image2.jpg' in paths paths = utils.drag_drop_paths(event, pattern='*.jp*g') assert len(paths) == 2 assert '/path/to/image.jpeg' in paths assert '/path/to/image2.jpg' in paths paths = utils.drag_drop_paths(event, pattern='*.png') assert len(paths) == 1 assert '/path/to/image.png' in paths
def __init__(self, parent=None): super(BlinkingLEDs, self).__init__(parent) self.setWindowTitle('Blinking LEDs') # The shape can be an enum value or member name (case in-sensitive) # The color can be anything that msl.qt.utils.to_qcolor() accepts params = [ { 'shape': LED.Circle, 'on_color': Qt.darkGreen, 'clickable': True }, { 'shape': 'rouNDed', 'on_color': (78, 82, 107) }, { 'shape': 2, 'on_color': 'cyan', 'clickable': True }, { 'shape': 'Triangle', 'on_color': '#6b3064' }, ] self.leds = [] layout = QtWidgets.QHBoxLayout() for kwargs in params: led = LED(**kwargs) led.toggled.connect(self.led_state_changed) led.clicked.connect(self.led_was_clicked) layout.addWidget(led) self.leds.append(led) self.setLayout(layout) self._timer = QtCore.QTimer() self._timer.timeout.connect(self.toggle_random_led) self._timer.start(200)
def select_zoom(self, event): """Called when the user wants to zoom in.""" event.accept() if self.canvas.image is None: return if event.button() & (QtCore.Qt.LeftButton | QtCore.Qt.MidButton): if event.isFinish(): self.view_box.rbScaleBox.hide() # get the coordinates of the highlighted region rect = QtCore.QRectF(pg.Point(event.buttonDownPos(event.button())), pg.Point(event.pos())) rect = self.view_box.childGroup.mapRectFromParent(rect).normalized() # get the size of the image on the canvas # DO NOT use self.canvas.width(), self.canvas.height() height, width = self.original_image.shape[:2] if self.zoom_history: width = int(self.zoom_history[-1][2] * width) height = int(self.zoom_history[-1][3] * height) angle = self.rotate_slider.value() values = rotate_zoom(angle, rect, width, height) if values is None: return # zoom outside of the image x, y, w, h, width, height = values # convert to the coordinates of the original (un-zoomed) image if self.zoom_history: orig_height, orig_width = self.original_image.shape[:2] x2, y2, w2, h2 = self.zoom_history[-1] x = x * width / orig_width + x2 y = y * height / orig_height + y2 w *= w2 h *= h2 self.append_zoom(x, y, w, h) else: self.view_box.updateScaleBox(event.buttonDownPos(), event.pos())
def test_icon_to_base64(): # reading from a standard Qt icon does not raise any errors assert isinstance( convert.icon_to_base64(QtWidgets.QStyle.SP_TitleBarMenuButton), QtCore.QByteArray) # reading from a file does not raise any errors icon = convert.to_qicon('gamma.png') assert isinstance(convert.icon_to_base64(icon), QtCore.QByteArray) assert convert.icon_to_base64(icon).startsWith(b'iVBORw0KGgoAAAA') assert convert.icon_to_base64(icon, fmt='PNG').startsWith(b'iVBORw0KGgoAAAA') assert convert.icon_to_base64(icon, fmt='BMP').startsWith(b'Qk32jgIAAAAAADY') assert convert.icon_to_base64(icon, fmt='JPG').startsWith(b'/9j/4AAQSkZJRgA') assert convert.icon_to_base64(icon, fmt='JPEG').startsWith(b'/9j/4AAQSkZJRgA') # GIF is not supported with pytest.raises(ValueError): convert.icon_to_base64(icon, fmt='GIF') # the size of 'gamma.png' size = QtCore.QSize(191, 291) # convert back to a QIcon and check each pixel original = icon.pixmap(size).toImage() converted = convert.to_qicon( convert.icon_to_base64(icon)).pixmap(size).toImage() for x in range(0, size.width()): for y in range(0, size.height()): rgb_original = original.pixel(x, y) rgb_converted = converted.pixel(x, y) assert QtGui.QColor(rgb_original).getRgb() == QtGui.QColor( rgb_converted).getRgb()
class _Settings(QtWidgets.QDialog): sig_update_jog_tooltip = QtCore.pyqtSignal() def __init__(self, parent): """Display a QDialog to edit the settings""" super(_Settings, self).__init__(flags=QtCore.Qt.WindowCloseButtonHint) self.conn = parent._connection info = self.conn.get_hardware_info() self.setWindowTitle( info.modelNumber.decode('utf-8') + ' || ' + info.notes.decode('utf-8')) # move info max_vel, max_acc = self.conn.get_motor_velocity_limits() vel, acc = self.conn.get_vel_params() vel = self.conn.get_real_value_from_device_unit(vel, UnitType.VELOCITY) acc = self.conn.get_real_value_from_device_unit( acc, UnitType.ACCELERATION) backlash = self.conn.get_real_value_from_device_unit( self.conn.get_backlash(), UnitType.DISTANCE) # move widgets self.acc_spinbox = QtWidgets.QDoubleSpinBox() self.acc_spinbox.setMinimum(0) self.acc_spinbox.setMaximum(max_acc) self.acc_spinbox.setValue(acc) self.acc_spinbox.setToolTip( '<html><b>Range:</b><br>0 - {} mm/s<sup>2</sup></html>'.format( max_acc)) self.vel_spinbox = QtWidgets.QDoubleSpinBox() self.vel_spinbox.setMinimum(0) self.vel_spinbox.setMaximum(max_vel) self.vel_spinbox.setValue(vel) self.vel_spinbox.setToolTip( '<html><b>Range:</b><br>0 - {} mm/s</html>'.format(max_vel)) self.backlash_spinbox = QtWidgets.QDoubleSpinBox() self.backlash_spinbox.setMinimum(0) self.backlash_spinbox.setMaximum(5) self.backlash_spinbox.setValue(backlash) self.backlash_spinbox.setToolTip( '<html><b>Range:</b><br>0 - 5 mm</html>') move_group = QtWidgets.QGroupBox('Move Parameters') move_grid = QtWidgets.QGridLayout() move_grid.addWidget(QtWidgets.QLabel('Backlash'), 0, 0, alignment=QtCore.Qt.AlignRight) move_grid.addWidget(self.backlash_spinbox, 0, 1) move_grid.addWidget(QtWidgets.QLabel('mm'), 0, 2, alignment=QtCore.Qt.AlignLeft) move_grid.addWidget(QtWidgets.QLabel('Maximum Velocity'), 1, 0, alignment=QtCore.Qt.AlignRight) move_grid.addWidget(self.vel_spinbox, 1, 1) move_grid.addWidget(QtWidgets.QLabel('mm/s'), 1, 2, alignment=QtCore.Qt.AlignLeft) move_grid.addWidget(QtWidgets.QLabel('Acceleration'), 2, 0, alignment=QtCore.Qt.AlignRight) move_grid.addWidget(self.acc_spinbox, 2, 1) move_grid.addWidget(QtWidgets.QLabel('mm/s<sup>2</sup>'), 2, 2, alignment=QtCore.Qt.AlignLeft) move_group.setLayout(move_grid) # jog info jog_size = self.conn.get_real_value_from_device_unit( self.conn.get_jog_step_size(), UnitType.DISTANCE) vel, acc = self.conn.get_jog_vel_params() jog_vel = self.conn.get_real_value_from_device_unit( vel, UnitType.VELOCITY) jog_acc = self.conn.get_real_value_from_device_unit( acc, UnitType.ACCELERATION) # jog widgets min_jog, max_jog = 0.002, parent._max_pos_mm / 2.0 self.jog_size_spinbox = QtWidgets.QDoubleSpinBox() self.jog_size_spinbox.setMinimum(min_jog) self.jog_size_spinbox.setMaximum(max_jog) self.jog_size_spinbox.setDecimals(3) self.jog_size_spinbox.setValue(jog_size) self.jog_size_spinbox.setToolTip( '<html><b>Range:</b><br>{} - {} mm</html>'.format( min_jog, max_jog)) self.jog_acc_spinbox = QtWidgets.QDoubleSpinBox() self.jog_acc_spinbox.setMinimum(0) self.jog_acc_spinbox.setMaximum(max_acc) self.jog_acc_spinbox.setValue(jog_acc) self.jog_acc_spinbox.setToolTip( '<html><b>Range:</b><br>0 - {} mm/s<sup>2</sup></html>'.format( max_acc)) self.jog_vel_spinbox = QtWidgets.QDoubleSpinBox() self.jog_vel_spinbox.setMinimum(0) self.jog_vel_spinbox.setMaximum(max_vel) self.jog_vel_spinbox.setValue(jog_vel) self.jog_vel_spinbox.setToolTip( '<html><b>Range:</b><br>0 - {} mm/s</html>'.format(max_vel)) jog_group = QtWidgets.QGroupBox('Jog Parameters') jog_grid = QtWidgets.QGridLayout() jog_grid.addWidget(QtWidgets.QLabel('Step Size'), 0, 0, alignment=QtCore.Qt.AlignRight) jog_grid.addWidget(self.jog_size_spinbox, 0, 1) jog_grid.addWidget(QtWidgets.QLabel('mm'), 0, 2, alignment=QtCore.Qt.AlignLeft) jog_grid.addWidget(QtWidgets.QLabel('Maximum Velocity'), 1, 0, alignment=QtCore.Qt.AlignRight) jog_grid.addWidget(self.jog_vel_spinbox, 1, 1) jog_grid.addWidget(QtWidgets.QLabel('mm/s'), 1, 2, alignment=QtCore.Qt.AlignLeft) jog_grid.addWidget(QtWidgets.QLabel('Acceleration'), 2, 0, alignment=QtCore.Qt.AlignRight) jog_grid.addWidget(self.jog_acc_spinbox, 2, 1) jog_grid.addWidget(QtWidgets.QLabel('mm/s<sup>2</sup>'), 2, 2, alignment=QtCore.Qt.AlignLeft) jog_group.setLayout(jog_grid) hbox = QtWidgets.QHBoxLayout() hbox.addWidget(move_group) hbox.addWidget(jog_group) update_button = QtWidgets.QPushButton('Update') update_button.setToolTip('Update the device settings') update_button.clicked.connect(self.update_settings) cancel_button = QtWidgets.QPushButton('Cancel') cancel_button.setToolTip('Update the device settings') cancel_button.clicked.connect(self.close) info_button = QtWidgets.QPushButton() info_button.setIcon(get_icon('imageres|109')) info_button.clicked.connect( lambda: show_hardware_info(parent._connection)) info_button.setToolTip('Display the hardware information') button_layout = QtWidgets.QGridLayout() button_layout.addWidget(cancel_button, 0, 0) button_layout.addItem( QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding), 0, 1) button_layout.addWidget(update_button, 0, 2) button_layout.addWidget(info_button, 0, 3) vbox = QtWidgets.QVBoxLayout() vbox.addLayout(hbox) vbox.addLayout(button_layout) self.setLayout(vbox) def update_settings(self): vel = self.conn.get_device_unit_from_real_value( self.vel_spinbox.value(), UnitType.VELOCITY) acc = self.conn.get_device_unit_from_real_value( self.acc_spinbox.value(), UnitType.ACCELERATION) self.conn.set_vel_params(vel, acc) backlash = self.conn.get_device_unit_from_real_value( self.backlash_spinbox.value(), UnitType.DISTANCE) self.conn.set_backlash(backlash) jog_vel = self.conn.get_device_unit_from_real_value( self.jog_vel_spinbox.value(), UnitType.VELOCITY) jog_acc = self.conn.get_device_unit_from_real_value( self.jog_acc_spinbox.value(), UnitType.ACCELERATION) self.conn.set_jog_vel_params(jog_vel, jog_acc) jog_size = self.conn.get_device_unit_from_real_value( self.jog_size_spinbox.value(), UnitType.DISTANCE) self.conn.set_jog_step_size(jog_size) self.sig_update_jog_tooltip.emit() self.close()
class _Signaler(QtCore.QObject): """Used for sending a signal of the current position.""" signal = QtCore.pyqtSignal()
class _Tree(QtWidgets.QTreeWidget): sig_selected = QtCore.pyqtSignal(str) def __init__(self, equipment_table, connection_table): """A Tree view of the options to use as filters for the devices.""" super(_Tree, self).__init__() # configure the super class self.setColumnCount(1) self.header().close() self.header().setStretchLastSection(False) self.header().setSectionResizeMode( QtWidgets.QHeaderView.ResizeToContents) self.itemDoubleClicked.connect(self._item_clicked) self.equipment_table = equipment_table self.connection_table = connection_table self.skip_names = ('Alias', 'Asset Number', 'Description', 'Latest Report Number', 'Model', 'Serial') self.rename_map = {'Date Calibrated': 'Year Calibrated'} self.create_top_level() def create_top_level(self): top_level_names = [] for name in self.equipment_table.header: if name in self.skip_names: continue if name in self.rename_map: name = self.rename_map[name] top_level_names.append(name) top_level_names.extend(['Backend', 'Interface']) # for ConnectionRecord's for item in sorted(top_level_names): QtWidgets.QTreeWidgetItem(self, [item]) def populate_tree(self): self.clear() self.create_top_level() for index in range(self.topLevelItemCount()): item = self.topLevelItem(index) name = item.text(0) if name == 'Manufacturer': values = {} for record in self.equipment_table.records_all: if record.manufacturer and record.manufacturer not in values: values[record.manufacturer] = [record.model] else: if record.model and record.model not in values[ record.manufacturer]: values[record.manufacturer].append(record.model) item.setText(0, name + ' ({})'.format(len(values))) for manufacturer in sorted(values): model_item = QtWidgets.QTreeWidgetItem( item, [manufacturer]) for model in sorted(values[manufacturer]): QtWidgets.QTreeWidgetItem(model_item, [model]) elif name == 'Year Calibrated': years = [] for record in self.equipment_table.records_all: year = record.date_calibrated.year if year > 1 and year not in years: years.append(year) item.setText(0, name + ' ({})'.format(len(years))) for year in sorted(years)[::-1]: QtWidgets.QTreeWidgetItem(item, [str(year)]) elif name == 'Connection': bools = {'True': 0, 'False': 0} for record in self.equipment_table.records_all: bools[str(record.connection is not None)] += 1 item.setText(0, name + ' (2)') for key in sorted(bools): QtWidgets.QTreeWidgetItem(item, [key]) elif name == 'Calibration Cycle': cycles = [] for record in self.equipment_table.records_all: if record.calibration_cycle == 0: continue if int(record.calibration_cycle ) == record.calibration_cycle: cycle = int(record.calibration_cycle) else: cycle = record.calibration_cycle if cycle not in cycles: cycles.append(cycle) item.setText(0, name + ' ({})'.format(len(cycles))) for c in sorted(cycles): QtWidgets.QTreeWidgetItem(item, [str(c)]) else: if name == 'Backend' or name == 'Interface': values = self._get_distinct_connection_records(name) else: values = self._get_distinct_equipment_records(name) item.setText(0, name + ' ({})'.format(len(values))) for value in sorted(values): QtWidgets.QTreeWidgetItem(item, [value]) def _get_distinct_equipment_records(self, name): out = [] attrib = name.lower().replace(' ', '_') for record in self.equipment_table.records_all: value = u'{}'.format(getattr(record, attrib)) if value and value not in out: out.append(value) return out def _get_distinct_connection_records(self, name): out = [] attrib = name.lower().replace(' ', '_') for record in self.connection_table.records_all: value = getattr(record, attrib).name if value and value not in out: out.append(value) return out def _item_clicked(self, item, column): num_parents = 0 parent = item.parent() while parent is not None: parent = parent.parent() num_parents += 1 if num_parents == 0: # then a top-level item was clicked return if num_parents == 1: attrib_name = item.parent().text(column).split( ' (')[column].lower().replace(' ', '_') text = u'{}={}'.format(attrib_name, item.text(column)) else: attrib_name = item.parent().parent().text(column).split( ' (')[column].lower().replace(' ', '_') text = u'{}={}, model={}'.format(attrib_name, item.parent().text(column), item.text(column)) self.sig_selected.emit(text)
def test_rescale_icon(): # the actual size of 'gamma.png' size = QtCore.QSize(191, 291) icon = convert.to_qicon('gamma.png') sizes = icon.availableSizes() assert len(sizes) == 1 assert sizes[0].width() == size.width() assert sizes[0].height() == size.height() new_size = convert.rescale_icon(icon, 2.6).size() assert new_size.width() == int(size.width() * 2.6) assert new_size.height() == int(size.height() * 2.6) new_size = convert.rescale_icon(icon, 150).size() assert new_size.width() == int( (150. / float(size.height())) * size.width()) assert new_size.height() == 150 new_size = convert.rescale_icon( icon, 300, aspect_mode=Qt.KeepAspectRatioByExpanding).size() assert new_size.width() == 300 assert new_size.height() == int( (300. / float(size.width())) * size.height()) size2 = (150, 200) new_size = convert.rescale_icon(icon, size2, aspect_mode=Qt.IgnoreAspectRatio).size() assert new_size.width() == size2[0] assert new_size.height() == size2[1] new_size = convert.rescale_icon(icon, size2).size() assert new_size.width() == int(size2[1] * size.width() / float(size.height())) assert new_size.height() == size2[1] # passing different objects does not raise an error if sys.platform == 'win32' and has_pythonnet(): assert isinstance(convert.rescale_icon('explorer|0', 1.0), QtGui.QPixmap) assert isinstance( convert.rescale_icon(QtWidgets.QStyle.SP_TitleBarMenuButton, 1.0), QtGui.QPixmap) assert isinstance(convert.rescale_icon(25, 1.0), QtGui.QPixmap) assert isinstance(convert.rescale_icon(icon.pixmap(size), 1.0), QtGui.QPixmap) assert isinstance(convert.rescale_icon(icon.pixmap(size).toImage(), 1.0), QtGui.QPixmap) if sys.platform == 'win32' and has_pythonnet(): with pytest.raises(TypeError, match=r'Unsupported "size"'): convert.rescale_icon('explorer|0', None) # if a list/tuple then must contain 2 elements for item in [(), [], (256, ), [ 256, ], (256, 256, 256), [256, 256, 256]]: with pytest.raises( ValueError, match=r'The size must be in the form \(width, height\)'): convert.rescale_icon(icon, item)