def setupUi(self): header = QLabel(f"{type(self._obj).__name__}") font = header.font() font.setBold(True) header.setFont(font) self.mainLayout = QVBoxLayout() self.mainLayout.addWidget(header) if isinstance(self._obj, (list, dict)): label = f"The {type(self._obj).__name__} has {len(self._obj)} element" if len(self._obj) != 1: label += "s" self.mainLayout.addWidget(QLabel(label + ".")) self.mainLayout.addStretch() elif self._obj is None: self.mainLayout.addWidget(QLabel("Not implemented yet.")) self.mainLayout.addStretch() else: self.mainLayout.addWidget(self._view) self.setLayout(self.mainLayout) # === table settings === # self._view.resizeColumnsToContents() self._view.verticalHeader().setVisible(False) self._view.setFocusPolicy(Qt.NoFocus) self._view.setSelectionMode(QAbstractItemView.SingleSelection) self._view.setEditTriggers(QAbstractItemView.AllEditTriggers) self._view.horizontalHeader().setStretchLastSection(True) self._view.horizontalHeader().setSectionsClickable(False) # self._view.setMinimumWidth(650) self.setMinimumWidth(600)
def _create_switch(self, box, layout, col, labels): if labels is None: return None l = QLabel(labels[0], box) l.setMinimumHeight(20) l.setAlignment(Qt.AlignCenter | Qt.AlignBottom) font = l.font() font.setPointSize(7) font.setBold(True) l.setFont(font) layout.addWidget(l, 3, col, Qt.AlignBottom | Qt.AlignCenter) r1 = QRadioButton(box) r1.setStyleSheet( 'QRadioButton::indicator{subcontrol-position:center;}') layout.addWidget(r1, 4, col, Qt.AlignCenter) r2 = QRadioButton(box) r2.setStyleSheet( 'QRadioButton::indicator{subcontrol-position:center;}') layout.addWidget(r2, 5, col, Qt.AlignCenter) l = QLabel(labels[1], box) l.setAlignment(Qt.AlignCenter) l.setFont(font) layout.addWidget(l, 6, col, Qt.AlignTop | Qt.AlignCenter) g = QButtonGroup(box) g.addButton(r1) g.addButton(r2) r1.setChecked(True) return r2
def _add_switches(self, switch_frame, switch_layout, switches, switch_dict, switch_fn, row): col = 0 for v, l in switches.items(): check = QCheckBox(switch_frame) check.setFixedSize(20, 20) check.setStyleSheet( 'QCheckBox::indicator{subcontrol-position:center;}') check.stateChanged.connect(switch_fn) switch_dict[v] = check switch_layout.addWidget(check, row, col) switch_layout.setAlignment(check, Qt.AlignCenter) label = QLabel(l, switch_frame) font = label.font() font.setPointSize(7) font.setBold(True) label.setFont(font) switch_layout.addWidget(label, row + 1, col) switch_layout.setAlignment(label, Qt.AlignCenter) col += 1 if col >= 6: col = 0 row += 2 return row
def _create_stop_cond(self, label_text, name, layout, col): # Create an indicator to show stop status ind = Indicator(self, QColor(255, 0, 0)) ind.setFixedSize(25, 20) layout.addWidget(ind, 0, col) layout.setAlignment(ind, Qt.AlignCenter) self._stop_inds[name] = ind # Add a switch to control the stop control state check = QCheckBox(self) check.setFixedSize(20, 20) check.setStyleSheet( 'QCheckBox::indicator{subcontrol-position:center;}') layout.addWidget(check, 1, col) layout.setAlignment(check, Qt.AlignCenter) check.stateChanged.connect(self._set_stop_conds) self._stop_switches[name] = check # Create a label for the inhibit switch label = QLabel(label_text, self) label.setAlignment(Qt.AlignCenter) font = label.font() font.setPointSize(7) font.setBold(True) label.setFont(font) label_height = 2 if '\n' in label_text else 1 layout.addWidget(label, 2, col, label_height, 1) layout.setAlignment(label, Qt.AlignCenter | Qt.AlignTop)
def __init__(self, app_context): super(AboutDialog, self).__init__() ok_btn = QDialogButtonBox.Ok self.button_box = QDialogButtonBox(ok_btn) self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.reject) layout = QVBoxLayout() title = QLabel("Melbourne") font = title.font() font.setPointSize(20) font.setBold(True) title.setFont(font) logo = QLabel() logo.setPixmap(QPixmap(app_context.get_resource("logo_128.png"))) layout.addWidget(title) layout.addWidget(logo) layout.addWidget(QLabel("Version 5.0.1")) layout.addWidget(QLabel("Copyright © Aditya Duri")) for i in range(0, layout.count()): layout.itemAt(i).setAlignment(Qt.AlignHCenter) layout.addWidget(self.button_box) self.setLayout(layout)
def __init__(self, *args, **kwargs): super(AboutDialog, self).__init__(*args, **kwargs) QBtn = QDialogButtonBox.Ok # No cancel self.buttonBox = QDialogButtonBox(QBtn) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) layout = QVBoxLayout() title = QLabel("MooseAche") font = title.font() font.setPointSize(20) title.setFont(font) layout.addWidget(title) logo = QLabel() logo.setPixmap(QPixmap(os.path.join('images', 'ma-icon-128.png'))) layout.addWidget(logo) layout.addWidget(QLabel("Version 23.35.211.233232")) layout.addWidget(QLabel("Copyright 2015 MooseAche Inc.")) for i in range(0, layout.count()): layout.itemAt(i).setAlignment(Qt.AlignHCenter) layout.addWidget(self.buttonBox) self.setLayout(layout)
def __init__(self): super().__init__() QBtn = QDialogButtonBox.Ok # No cancel self.buttonBox = QDialogButtonBox(QBtn) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) layout = QVBoxLayout() title = QLabel("Mozzarella Ashbadger") font = title.font() font.setPointSize(20) title.setFont(font) layout.addWidget(title) logo = QLabel() logo.setPixmap(QPixmap(os.path.join("icons", "ma-icon-128.png"))) layout.addWidget(logo) layout.addWidget(QLabel("Version 23.35.211.233232")) layout.addWidget(QLabel("Copyright 2015 Mozzarella Inc.")) for i in range(0, layout.count()): layout.itemAt(i).setAlignment(Qt.AlignHCenter) layout.addWidget(self.buttonBox) self.setLayout(layout)
def _setup_ui(self): self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised) layout = QGridLayout(self) self.setLayout(layout) layout.setMargin(1) layout.setHorizontalSpacing(10) layout.setVerticalSpacing(1) self._create_header('MONITOR', layout, 0) self._mon_temp = self._create_meas('TEMP', layout, 1, 0, True) self._vccint = self._create_meas('VCCINT', layout, 2, 0, False) self._vccaux = self._create_meas('VCCAUX', layout, 3, 0, False) self._p3v3io = self._create_meas('+3V3IO', layout, 4, 0, False) self._create_header('AGC', layout, 2) self._agc_temp = self._create_meas('TEMP', layout, 1, 2, True) self._bplssw = self._create_meas('BPLSSW', layout, 2, 2, False) self._p4sw = self._create_meas('+4SW', layout, 3, 2, False) label = QLabel('MEASUREMENTS', self) font = label.font() font.setPointSize(12) font.setBold(True) label.setFont(font) label.setAlignment(Qt.AlignCenter) layout.addWidget(label, 4, 2, 1, 2, Qt.AlignRight)
def _create_meas(self, name, layout, row, col, temp): label = QLabel(name, self) font = label.font() font.setPointSize(8) font.setBold(True) label.setFont(font) layout.addWidget(label, row, col) layout.setAlignment(label, Qt.AlignRight) meas_value = QLineEdit(self) meas_value.setReadOnly(True) meas_value.setMaximumSize(65, 32) font = QFont('Monospace') font.setStyleHint(QFont.TypeWriter) font.setPointSize(10) meas_value.setFont(font) meas_value.setAlignment(Qt.AlignCenter) if temp: meas_value.setText('0.00 C') else: meas_value.setText('0.00 V') layout.addWidget(meas_value, row, col + 1) layout.setAlignment(meas_value, Qt.AlignLeft) return meas_value
def _create_inh_control(self, name, parent, layout, col): # Create a label for the inhibit switch label = QLabel(name, parent) label.setAlignment(Qt.AlignCenter) font = label.font() font.setPointSize(7) font.setBold(True) label.setFont(font) layout.addWidget(label, 0, col) # Add an indicator to show inhibit state ind = Indicator(parent, QColor(255, 120, 0)) ind.setFixedSize(20, 20) layout.addWidget(ind, 1, col) layout.setAlignment(ind, Qt.AlignCenter) # Add a switch to control the inhibit state check = QCheckBox(parent) check.setFixedSize(20, 20) check.setStyleSheet( 'QCheckBox::indicator{subcontrol-position:center;}') layout.addWidget(check, 2, col) layout.setAlignment(check, Qt.AlignCenter) layout.setColumnMinimumWidth(col, 25) self._inh_switches.append(check) self._inh_inds.append(ind)
def makeDisplay(self): layout = QGridLayout(self) wordLabel = QLabel(self) self.wordLabel = wordLabel font = wordLabel.font() font.setPointSize(32) font.setBold(True) wordLabel.setFont(font) layout.addWidget(wordLabel, 0, 0, 1, 6) layout.setMargin(10) group = QButtonGroup(self) self.group = group self.buttons = [] for i in range(4): scoreButton = QPushButton(self, text=str(i)) scoreButton.setCheckable(True) if i == 0: scoreButton.setChecked(True) scoreButton.setMaximumWidth(40) group.addButton(scoreButton, i) layout.addWidget(scoreButton, 1, i) self.buttons.append(scoreButton) self.modelSimilarity = QLabel(self, text='') layout.addWidget(self.modelSimilarity, 2, 0) self.setLayout(layout)
def _create_header(self, name, layout, col): label = QLabel(name, self) font = label.font() font.setPointSize(10) font.setBold(True) label.setFont(font) layout.addWidget(label, 0, col, 1, 2) layout.setAlignment(label, Qt.AlignCenter)
def _create_label(self, text, parent): label = QLabel(text, parent) label.setAlignment(Qt.AlignCenter) font = label.font() font.setPointSize(7) font.setBold(True) label.setFont(font) label.setMinimumWidth(30) return label
def _setup_ui(self): self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised) layout = QHBoxLayout(self) self.setLayout(layout) # Create a group box for the inhibit switches nh_group = QGroupBox('INH', self) nh_group.setAlignment(Qt.AlignCenter) layout.addWidget(nh_group) layout.setAlignment(nh_group, Qt.AlignTop) layout.setMargin(1) layout.setSpacing(1) # Set up a grid layout to hold the labels, switches, and indicators nh_layout = QGridLayout(nh_group) nh_group.setLayout(nh_layout) nh_layout.setMargin(1) nh_layout.setSpacing(1) # Construct the inhibit indicators and switches col = 0 for switch, msg in INH_SWITCHES.items(): self._create_inh_control(switch, nh_group, nh_layout, col) ind = self._inh_inds[-1] self._inh_switches[-1].stateChanged.connect( lambda on, ind=ind, msg=msg: self._set_inh(ind, msg, on)) col += 1 sl_group = QWidget(self) layout.addWidget(sl_group) sl_layout = QVBoxLayout(sl_group) sl_group.setLayout(sl_layout) sl_layout.setMargin(1) sl_layout.setSpacing(1) sl_layout.addSpacing(4) stat_group = QWidget(sl_group) sl_layout.addWidget(stat_group) stat_layout = QGridLayout(stat_group) stat_layout.setMargin(3) stat_layout.setSpacing(3) col = 0 for name, label in STATUS_INDS.items(): self._status_inds[name] = self._create_status_light( label, stat_group, stat_layout, col) col += 1 label = QLabel('CONTROL', sl_group) font = label.font() font.setPointSize(12) font.setBold(True) label.setFont(font) label.setAlignment(Qt.AlignCenter) sl_layout.addWidget(label)
def test_text(pixmap_differ: PixmapDiffer): actual: QPainter expected: QPainter with pixmap_differ.create_painters(300, 240, 'scaled_label_text') as ( actual, expected): ex_widget = QWidget() ex_layout = QVBoxLayout(ex_widget) ex_label1 = QLabel('Lorem ipsum') ex_label2 = QLabel('Lorem ipsum') ex_font = ex_label1.font() if ex_font.family() == 'Sans Serif': # Fonts are different on Travis CI. big_font_size = 30 small_font_size = 25 else: big_font_size = 35 small_font_size = 28 ex_font.setPointSize(big_font_size) ex_label1.setFont(ex_font) ex_font.setPointSize(small_font_size) ex_label2.setFont(ex_font) ex_size_policy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) ex_label1.setSizePolicy(ex_size_policy) ex_label1.setAlignment(Qt.AlignBottom) ex_label2.setAlignment(Qt.AlignTop) ex_label2.setSizePolicy(ex_size_policy) ex_layout.addWidget(ex_label1) ex_layout.addWidget(ex_label2) ex_layout.setStretch(0, 4) ex_layout.setStretch(1, 1) ex_widget.resize(300, 240) expected.drawPixmap(0, 0, ex_widget.grab()) widget = QWidget() layout = QVBoxLayout(widget) label1 = ScaledLabel('Lorem ipsum') label2 = ScaledLabel('Lorem ipsum') size_policy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) label1.setSizePolicy(size_policy) label2.setSizePolicy(size_policy) label1.setScaledContents(True) label2.setScaledContents(True) label1.setAlignment(Qt.AlignBottom) label2.setAlignment(Qt.AlignTop) layout.addWidget(label1) layout.addWidget(label2) layout.setStretch(0, 4) layout.setStretch(1, 1) widget.resize(300, 240) actual.drawPixmap(0, 0, widget.grab())
def _setup_ui(self, color): # Set up our basic layout layout = QHBoxLayout(self) self.setLayout(layout) layout.setSpacing(3) layout.setMargin(1) # Construct register groups for EB, FEXT, FB, and S eb_frame, self._eb_box = self._create_reg(self._eb_inds, 'EBANK', 3, color) fext_frame, self._fext_box = self._create_reg(self._fext_inds, 'FEXT', 3, color) fb_frame, self._fb_box = self._create_reg(self._fb_inds, 'FBANK', 5, color) s_frame, self._s_box = self._create_reg(self._s_inds, '', 12, color) layout.addWidget(eb_frame) layout.addWidget(fext_frame) layout.addWidget(fb_frame) layout.addWidget(s_frame) # Create a grouping widget for the S label and decoded octal value box label_value = QWidget(self) label_value.setMinimumWidth(100) lv_layout = QHBoxLayout(label_value) lv_layout.setSpacing(3) lv_layout.setMargin(1) lv_layout.setContentsMargins(0, 32, 0, 0) label_value.setLayout(lv_layout) layout.addWidget(label_value) # Create a value box for displaying the overall decoded address self._addr_value = QLineEdit(label_value) self._addr_value.setReadOnly(True) self._addr_value.setMaximumSize(65, 32) self._addr_value.setText('0000') font = QFont('Monospace') font.setStyleHint(QFont.TypeWriter) font.setPointSize(10) self._addr_value.setFont(font) self._addr_value.setAlignment(Qt.AlignCenter) lv_layout.addWidget(self._addr_value) # Create a label to show 'S' label = QLabel('S', label_value) font = label.font() font.setPointSize(14) font.setBold(True) label.setFont(font) lv_layout.addWidget(label) # Add some spacing to account for lack of parity indicators layout.addSpacing(36)
def _setup_ui(self): self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised) # Set up our basic layout layout = QGridLayout(self) self.setLayout(layout) layout.setSpacing(1) layout.setMargin(1) for bank in range(0o10): sw = self._create_bank_switch('E%o' % bank, layout, 0, bank, 1) sw.stateChanged.connect(self._update_ems_banks) self._bank_switches.append(sw) for col in range(0o10, 0o22): s = QSpacerItem(20, 20) layout.addItem(s, 1, col) label = QLabel('EMS', self) font = label.font() font.setPointSize(12) font.setBold(True) label.setFont(font) label.setAlignment(Qt.AlignCenter) layout.addWidget(label, 5, 16, 2, 2, Qt.AlignCenter) b = self._create_button('ALL', layout, 5, 1, 3) b.pressed.connect(lambda: self._set_all(True)) b = self._create_button('NONE', layout, 5, 3, 2) b.pressed.connect(lambda: self._set_all(False)) self._ems_sel = QRadioButton('EMS', self) self._ems_sel.setLayoutDirection(Qt.RightToLeft) layout.addWidget(self._ems_sel, 5, 6, 2, 3) layout.setAlignment(self._ems_sel, Qt.AlignRight) self._agc_sel = QRadioButton('AGC', self) self._agc_sel.setChecked(True) layout.addWidget(self._agc_sel, 5, 8, 2, 3) layout.setAlignment(self._agc_sel, Qt.AlignCenter) font.setPointSize(7) self._ems_sel.setFont(font) self._agc_sel.setFont(font) b = self._create_button('PAD', layout, 5, 11, 2) b.pressed.connect(self._load_pad) b = self._create_button('LOAD', layout, 5, 12, 3) b.pressed.connect(self._load_core) b = self._create_button('DUMP', layout, 5, 14, 2) b.pressed.connect(self._dump_core)
def __init__(self, title, parent=None): super().__init__(parent) widget = QWidget() layout = QHBoxLayout(widget) layout.setContentsMargins(self.H_MARGIN, self.V_MARGIN, self.H_MARGIN, self.V_MARGIN) layout.setSpacing(self.V_MARGIN) label = QLabel(title, widget) fm = QFontMetrics(label.font()) label.setFixedWidth(fm.horizontalAdvance(title)) self._add_line(widget, layout) layout.addWidget(label) self._add_line(widget, layout) self.setDefaultWidget(widget)
def _setup_ui(self): self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised) # Set up our basic layout layout = QGridLayout(self) self.setLayout(layout) layout.setSpacing(1) layout.setMargin(1) for bank in range(0o44): col = bank % 18 row = int(bank / 18) * 2 sw = self._create_bank_switch('%o' % bank, layout, row, col, 1) sw.stateChanged.connect( lambda state, bank=bank: self._update_crs_bank(bank)) self._bank_switches.append(sw) self._aux_switch = self._create_bank_switch('44-77', layout, 5, 0, 2) label = QLabel('CRS', self) font = label.font() font.setPointSize(12) font.setBold(True) label.setFont(font) label.setAlignment(Qt.AlignCenter) layout.addWidget(label, 5, 16, 2, 2, Qt.AlignCenter) b = self._create_button('ALL', layout, 5, 1, 3) b.pressed.connect(lambda: self._set_all(True)) b = self._create_button('NONE', layout, 5, 3, 2) b.pressed.connect(lambda: self._set_all(False)) self._crs_sel = QRadioButton('CRS', self) self._crs_sel.setLayoutDirection(Qt.RightToLeft) layout.addWidget(self._crs_sel, 5, 6, 2, 3) layout.setAlignment(self._crs_sel, Qt.AlignRight) self._agc_sel = QRadioButton('AGC', self) self._agc_sel.setChecked(True) layout.addWidget(self._agc_sel, 5, 8, 2, 3) layout.setAlignment(self._agc_sel, Qt.AlignCenter) font.setPointSize(7) self._crs_sel.setFont(font) self._agc_sel.setFont(font) b = self._create_button('LOAD', layout, 5, 12, 3) b.pressed.connect(self._load_rope) b = self._create_button('DUMP', layout, 5, 14, 2) b.pressed.connect(self._dump_rope)
def _create_switch_group(self, layout, group_name, button3, switch1, switch2, switch3): group_box = QGroupBox(group_name, self) layout.addWidget(group_box) group_layout = QGridLayout(group_box) group_box.setLayout(group_layout) group_layout.setMargin(0) group_layout.setSpacing(0) l = QLabel('S', group_box) l.setAlignment(Qt.AlignCenter) font = l.font() font.setPointSize(7) font.setBold(True) l.setFont(font) l.setMinimumWidth(30) group_layout.addWidget(l, 0, 0, Qt.AlignBottom) l = QLabel('PRESET', group_box) l.setAlignment(Qt.AlignCenter) l.setFont(font) l.setMinimumWidth(30) group_layout.addWidget(l, 0, 1, Qt.AlignBottom) l = QLabel(button3, group_box) l.setAlignment(Qt.AlignCenter) l.setFont(font) l.setMinimumWidth(30) group_layout.addWidget(l, 0, 2, Qt.AlignBottom) b1 = QPushButton(group_box) b1.setFixedSize(20, 20) group_layout.addWidget(b1, 1, 0, Qt.AlignCenter) b2 = QPushButton(group_box) b2.setFixedSize(20, 20) group_layout.addWidget(b2, 1, 1, Qt.AlignCenter) b3 = QPushButton(group_box) b3.setFixedSize(20, 20) group_layout.addWidget(b3, 1, 2, Qt.AlignCenter) s1 = self._create_switch(group_box, group_layout, 0, switch1) s2 = self._create_switch(group_box, group_layout, 1, switch2) s3 = self._create_switch(group_box, group_layout, 2, switch3) return b1, b2, b3, s1, s2, s3
def _create_status_light(self, name, parent, layout, col): label = QLabel(name, parent) label.setAlignment(Qt.AlignCenter) font = label.font() font.setPointSize(7) font.setBold(True) label.setFont(font) layout.addWidget(label, 1, col) # Add an indicator to show inhibit state ind = Indicator(parent, QColor(255, 0, 0)) ind.setFixedSize(20, 20) layout.addWidget(ind, 2, col) layout.setAlignment(ind, Qt.AlignCenter) return ind
def _create_button(self, name, layout, row, col, width): label = QLabel(name, self) label.setAlignment(Qt.AlignCenter) font = label.font() font.setPointSize(7) font.setBold(True) label.setFont(font) label.setMinimumWidth(30) layout.addWidget(label, row, col, 1, width) layout.setAlignment(label, Qt.AlignCenter) b = QPushButton(self) b.setFixedSize(20, 20) layout.addWidget(b, row + 1, col, 1, width) layout.setAlignment(b, Qt.AlignCenter) return b
def __init__(self, title, parent=None): super().__init__(parent) widget = QWidget() layout = QHBoxLayout(widget) layout.setContentsMargins(self.H_MARGIN, self.V_MARGIN, self.H_MARGIN, self.V_MARGIN) layout.setSpacing(self.V_MARGIN) label = QLabel(title, widget) fm = QFontMetrics(label.font()) label.setFixedWidth(fm.horizontalAdvance(title)) lines = QFrame(widget), QFrame(widget) for line in lines: line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) layout.addWidget(line) layout.insertWidget(1, label) self.setDefaultWidget(widget)
def __init__(self): super().__init__() self.setWindowTitle("커피퐁당") self.setFixedSize(300, 100) label = QLabel("Cafe Fondant") font = label.font() font.setPointSize(20) font.setFamily("Century Gothic") font.setItalic(True) font.setUnderline(True) label.setFont(font) label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.setCentralWidget(label)
def _create_bank_switch(self, name, layout, row, col, width): label = QLabel(name, self) label.setAlignment(Qt.AlignBottom | (Qt.AlignLeft if width == 2 else Qt.AlignCenter)) font = label.font() font.setPointSize(7) font.setBold(True) label.setFont(font) layout.addWidget(label, row, col, 1, width) check = QCheckBox(self) check.setFixedSize(20, 20) check.setStyleSheet( 'QCheckBox::indicator{subcontrol-position:center;}') layout.addWidget(check, row + 1, col, 1, 1) layout.setAlignment(check, Qt.AlignCenter) return check
def __init__(self): super().__init__() self.setWindowTitle("My App") widget = QLabel("Hello") # In order to modify the font, we retrieve it, # change it, and set it back font = widget.font() font.setPointSize(30) widget.setFont(font) widget.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) widget.setPixmap(QPixmap('assets/example.jpg')) widget.setScaledContents(True) widget.setFixedSize(QSize(200, 100)) checkbox = QCheckBox("A checkbox") checkbox.setCheckState(Qt.Checked) checkbox.setTristate(True) checkbox.stateChanged.connect(self.show_state) # self.setCentralWidget(checkbox) self.setCentralWidget(widget)
def _setup_ui(self): self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised) layout = QGridLayout(self) self.setLayout(layout) layout.setMargin(1) layout.setSpacing(1) # Construct the stop indicators and switches col = 0 for l, n in STOP_CONDS.items(): self._create_stop_cond(l, n, layout, col) col += 1 label = QLabel('COMP STOP', self) font = label.font() font.setPointSize(12) font.setBold(True) label.setFont(font) label.setAlignment(Qt.AlignCenter) layout.addWidget(label, 3, 0, 1, 4, Qt.AlignRight) self._s1 = QRadioButton('S1', self) self._s1.setLayoutDirection(Qt.RightToLeft) layout.addWidget(self._s1, 3, 5, 1, 2) layout.setAlignment(self._s1, Qt.AlignRight) self._s1.setChecked(True) self._s1.toggled.connect(self._set_stop_conds) self._s2 = QRadioButton('S2', self) layout.addWidget(self._s2, 3, 6, 1, 2) layout.setAlignment(self._s2, Qt.AlignRight) font.setPointSize(7) self._s1.setFont(font) self._s2.setFont(font)
def _setup_ui(self): layout = QVBoxLayout(self) self.setLayout(layout) layout.setMargin(1) layout.setSpacing(1) layout.addSpacing(50) l = QLabel('BANK S', self) l.setMinimumHeight(20) l.setAlignment(Qt.AlignCenter | Qt.AlignBottom) font = l.font() font.setPointSize(7) font.setBold(True) l.setFont(font) layout.addWidget(l, Qt.AlignCenter) bank_s = QRadioButton(self) bank_s.setStyleSheet( 'QRadioButton::indicator{subcontrol-position:center;}') layout.addWidget(bank_s, Qt.AlignTop | Qt.AlignCenter) s_only = QRadioButton(self) s_only.setStyleSheet( 'QRadioButton::indicator{subcontrol-position:center;}') s_only.toggled.connect( lambda s: self._usbif.send(um.WriteControlBankS(s))) layout.addWidget(s_only, Qt.AlignTop | Qt.AlignCenter) l = QLabel('S ONLY', self) l.setAlignment(Qt.AlignCenter | Qt.AlignTop) l.setFont(font) layout.addWidget(l, Qt.AlignTop | Qt.AlignCenter) bank_s.setChecked(True)
class ConfirmCheckMakeThisTrackDefaultWithUnCheckOption(QDialog): def __init__(self, track_type, parent=None): super().__init__(parent) self.track_type = track_type self.yesButton = QPushButton("OK") self.noButton = QPushButton("Cancel") self.thirdButton = QPushButton("Uncheck this one") self.setWindowTitle("Confirm Check") self.setWindowIcon(GlobalFiles.QuestionIcon) self.message = QLabel( "<nobr>Are you sure?<br>This will <b>uncheck</b> set default and set forced options " "from " + self.track_type + " tab") self.messageIcon = QLabel() self.buttons_layout = QHBoxLayout() self.buttons_layout.addWidget(self.thirdButton) self.buttons_layout.addWidget(self.yesButton) self.buttons_layout.addWidget(self.noButton) self.main_layout = QGridLayout() self.main_layout.addWidget(self.messageIcon, 0, 0, 2, 1) self.main_layout.addWidget(QLabel(), 0, 1, 1, 1) # add space self.main_layout.addWidget(self.message, 0, 2, 2, 3) self.main_layout.addLayout(self.buttons_layout, 2, 4, 1, 1) self.main_layout.setContentsMargins(20, 20, 20, 20) self.setLayout(self.main_layout) self.result = "No" self.setup_ui() self.signal_connect() def setup_ui(self): self.disable_question_mark_window() self.set_message_icon_info() # self.increase_message_font_size(1) self.set_default_buttons() def signal_connect(self): self.yesButton.clicked.connect(self.click_yes) self.noButton.clicked.connect(self.click_no) self.thirdButton.clicked.connect(self.click_third_button) def click_yes(self): self.result = "Yes" self.close() def click_no(self): self.result = "No" self.close() def click_third_button(self): self.result = "Third" self.close() def disable_question_mark_window(self): self.setWindowFlag(QtCore.Qt.WindowContextHelpButtonHint, on=False) def increase_message_font_size(self, value): message_font = self.message.font() message_font.setPointSize(self.message.fontInfo().pointSize() + value) self.message.setFont(message_font) def set_message_icon_info(self): self.messageIcon.setPixmap(QtGui.QPixmap(GlobalFiles.InfoBigIconPath)) def set_default_buttons(self): self.yesButton.setDefault(False) self.noButton.setDefault(True) def showEvent(self, a0: QtGui.QShowEvent) -> None: super().showEvent(a0) self.setFixedSize(self.size()) def execute(self): self.exec_()
def _generate_sector(self, sector, band=None, gen_cloud=False): logging.debug( "Generation process launched for %s, generating cloud: %r", sector, gen_cloud) logging.info(f"Generating image for {sector['name']}") if self._data is None: logging.error( "No data loaded for sector! Should never have gotten here!") return self._proj_str = f'+proj=laea +lat_0={sector["centerLat"]} +lon_0={sector["centerLng"]} +x_0=0 +y_0=0 +ellps=WGS84 +units=m +no_defs' self._laea_transformer = pyproj.Transformer.from_proj( LAT_LON_PROJ, self._proj_str) lat_from, lat_to = (sector['latFrom'], sector['latTo']) lon_from, lon_to = (sector['longFrom'], sector['longTo']) # Make sure our longitude is in the "REAL" range if lon_from < -180: filt_lon_from = lon_from + 360 elif lon_from > 180: filt_lon_from = lon_from - 360 else: filt_lon_from = lon_from if lon_to > 180: filt_lon_to = lon_to - 360 elif lon_to < -180: filt_lon_to = lon_to + 360 else: filt_lon_to = lon_to # Just look at *this* sector # Start with a rough latitude/longitude filter # (with 1/2 degree latitude, 1 dgree longitude border) with numpy.errstate(invalid='ignore'): # Filter on density again so that any bins that wound up without data are removed. filter_items = [ ~numpy.isnan(self._data['SO2_column_number_density']) ] filter_items.append(self._data['latitude'] >= (lat_from - .5)) filter_items.append(self._data['latitude'] <= (lat_to + .5)) logging.debug("Generating latitude filters") lat_filter = numpy.logical_and.reduce(filter_items) # Figure out longitude filter if filt_lon_to > filt_lon_from: filt_lon_from = [filt_lon_from, 180] filt_lon_to = [-180, filt_lon_to] else: filt_lon_from = [filt_lon_from] filt_lon_to = [filt_lon_to] lon_filters = [] for start, stop in zip(filt_lon_from, filt_lon_to): lon_filters.append( numpy.logical_and(self._data['longitude'] <= (start + 1), self._data['longitude'] >= (stop - 1))) logging.debug("Generating longitude filters") if len(lon_filters) > 1: lon_filter = numpy.logical_or(*lon_filters) else: lon_filter = lon_filters[0] logging.debug("Combining filters") post_filter = numpy.logical_and(lat_filter, lon_filter) # short-circuit filtering if no records would be retained if not post_filter.any(): logging.info("No in-range data found for %s, %s", band or "cloud", sector['sector']) return sector_data = self._apply_filter(post_filter) logging.debug("Rough filters applied") if not sector_data['latitude'].any(): # No data for this set of parameters. Try the next logging.info("No data found for %s, %s", band or "cloud", sector['sector']) return # Figure out the bounds in laea projection pixel_bounds = numpy.stack( (sector_data['latitude_bounds'], sector_data['longitude_bounds']), axis=-1) x_lat_lon = pixel_bounds[:, :, 1].reshape(pixel_bounds[:, :, 1].size) y_lat_lon = pixel_bounds[:, :, 0].reshape(pixel_bounds[:, :, 0].size) x_laea, y_laea = self._laea_transformer.transform( y_lat_lon, x_lat_lon, ) x_laea = x_laea.reshape(int(x_laea.size / 4), 4) y_laea = y_laea.reshape(int(y_laea.size / 4), 4) # Add these to sector data so they get filtered along with # everything else sector_data['x_laea'] = (['time', 'corners'], x_laea) sector_data['y_laea'] = (['time', 'corners'], y_laea) # seperate the max/min x and y limits of each pixel so we can tell which # actually have area within the image x_max = numpy.nanmax(x_laea, axis=1) x_min = numpy.nanmin(x_laea, axis=1) y_max = numpy.nanmax(y_laea, axis=1) y_min = numpy.nanmin(y_laea, axis=1) meter_width = sector['pixelSize'] * 1000 * sector[ 'imageWidth'] # km-->meters meter_height = sector['pixelSize'] * 1000 * sector['imageHeight'] center_x, center_y = ( 0, 0 ) # Always centered at 0, because that's how we defined our projection # Yes, this could be simplified, since our center is 0, but this keeps # flexability should that change, and explicitly spells out exactly what # we are doing here. x_range = [center_x - (meter_width / 2), center_x + (meter_width / 2)] y_range = [ center_y - (meter_height / 2), center_y + (meter_height / 2) ] # Second filter - now that we have translated the cordinate system, # trim down to *only* the area to be displayed. filters = [ x_max > x_range[0], # Right edge of pixel inside left edge of image x_min < x_range[1], # Left edge of pixel inside right edge of image y_max > y_range[0], # well, you get the idea y_min < y_range[1] ] final_filter = numpy.logical_and.reduce(filters) # Short-circuit filtering in border cases if not final_filter.any(): logging.info("No in-range data found for %s, %s", band, sector['sector']) return # Only filter if we are actually getting rid of something if not final_filter.all(): sector_data = self._apply_filter(final_filter, sector_data) if not sector_data['latitude'].any(): # No data for this set of parameters. Try the next logging.debug("No data found for %s, %s", band, sector['sector']) return logging.debug("Data filtered for sector succesfully") # Center point of pixels data_x, data_y = self._laea_transformer.transform( sector_data['latitude'], sector_data['longitude']) laea_pixel_bounds = numpy.stack( [sector_data['x_laea'], sector_data['y_laea']], axis=2) areas = PolyArea(sector_data['x_laea'], sector_data['y_laea']) mass = areas * sector_data['SO2_column_number_density'] # in moles mass *= 64 # in grams total_mass = numpy.nansum(mass) * 1e-9 # Kilo Tonnes self._du_val = sector_data[ 'SO2_column_number_density'] * 2241.15 # Conversion Factor from manual self._normalized_du = self._du_val * (1 / 20) self._normalized_du[self._normalized_du > 1] = 1 self._normalized_du[self._normalized_du < 0] = 0 _percentile_levels = (90, 95, 97, 99, 100) _percentiles = numpy.nanpercentile(self._du_val, _percentile_levels) _percentiles[_percentiles < 0] = 0 _percentiles[_percentiles > 20] = 20 _percentColors = self._du_color_map.map(_percentiles * (1 / 20), mode='qcolor') # When rounded to 5 digits, the color results are identical. # Doing the rounding significanly reduces the number of unique values, # therby enabling significant speed up by using a lookup table rather # than having to check each value individually. self._normalized_du = numpy.round(self._normalized_du, 5) # show_volc_names = sector.get('showAllLabels', True) # hide_all_names = sector.get('hideAllLabels', False) # Generate path objects for each pixel for graphing purposes. # To get the shape of each pixel, shift each one to 0,0 lower left bounding box shifted_coords = laea_pixel_bounds - numpy.min(laea_pixel_bounds, axis=1)[:, None, :] # We have to do min twice to get the single min value for each group of corner points # If we only did it once, X and Y would be scaled seperately, distorting the shape. scale_factors = numpy.max(numpy.max(shifted_coords, axis=1), axis=1) # Scale each pixel to fit within -0.5 - +0.5 with warnings.catch_warnings(): warnings.simplefilter("ignore") scaled_coords = (shifted_coords * (1 / scale_factors[:, None, None])) - .5 # "Center" the scaled coordinates so the paths correctly represent the points scaled_coords -= (((numpy.max(scaled_coords, axis=1) - numpy.min(scaled_coords, axis=1)) - 1) / 2)[:, None, :] pixel_paths = [_generate_path(x) for x in scaled_coords] # Have to keep disp_widget, otherwise python deletes things too soon. (plot_item, scale_widget, disp_widget, date_label) = _initalize_image_widgets(self._file_date, band, self._data_type) # Add the total mass to the date label if sector['sector'] == '1kmHIKI': date_label.setText(date_label.text() + f" {total_mass:.2f}kt") date_label.adjustSize() # Make color blocks to display the percentiles if not gen_cloud: _percentContainer = QWidget() _percentContainer.setObjectName("Percent Container") _percentContainer.setAutoFillBackground(False) _percentContainer.setStyleSheet('background-color:transparent') main_layout = QVBoxLayout(_percentContainer) main_layout.setObjectName("Main Layout") main_layout.setContentsMargins(0, 0, 0, 0) title = QLabel(_percentContainer) title.setText("Percentiles:") title.setAlignment(Qt.AlignLeft) title_font = title.font() title_font.setPointSize(8) title.setFont(title_font) main_layout.addWidget(title) percentLayout = QHBoxLayout() percentLayout.setObjectName("Percent Bar Layout") percentLayout.setContentsMargins(0, 0, 0, 0) percentLayout.setSpacing(0) main_layout.addLayout(percentLayout) for idx, color in enumerate(_percentColors): val = _percentiles[idx] widg = QWidget() lay = QVBoxLayout() lay.setObjectName(f"Val {idx} layout") lay.setContentsMargins(0, 0, 0, 0) widg.setLayout(lay) label = QLabel() label.setText( f"{_percentile_levels[idx]}<sup>th</sup><br>{str(round(val, 2))} DU" ) labelFont = label.font() labelFont.setPointSize(8) label.setFont(labelFont) label.setAlignment(Qt.AlignCenter) lay.addWidget(label) ss = f'background-color:{color.name()};border:1px solid black;' if idx != 0: ss += "border-left:None;" widg.setStyleSheet(ss) percentLayout.addWidget(widg) _percentContainer.setGeometry(0, 0, 300, 18) _percentContainer.setLayout(main_layout) vbox = plot_item.getViewBox() vbox.disableAutoRange() vbox.setRange(xRange=x_range, yRange=y_range, padding=0) ############################################################### # Plot Generation Code ############################################################### def plot_dataset(dataset, color_map, scale_labels): # Only generate the brush once for each unique value lookup_table = { x: pg.mkBrush(color_map.map(x)) for x in numpy.unique(dataset) } brushes = [lookup_table[x] for x in dataset.data] scale_widget.setGradient(color_map.getGradient()) scale_widget.setLabels(scale_labels) # Generate Plot plot = plot_item.plot(data_x, data_y, pen=None, symbolPen=None, symbolBrush=brushes, pxMode=False, symbolSize=scale_factors, symbol=pixel_paths) plot_item.getViewWidget().parent().grab() volcview_img = plot_item.getViewWidget().parent().grab() self._view_extents = vbox.viewRange() file_bytes = QByteArray() file_buffer = QBuffer(file_bytes) file_buffer.open(QIODevice.WriteOnly) volcview_img.save(file_buffer, "PNG") file_buffer.close() file_stream = BytesIO(file_bytes) pil_img = Image.open(file_stream) # find coverage percent(ish) width, height = pil_img.size total_count = width * height # Should be 800,000, unless we changed the size of the images. # dump into a numpy array to count grey pixels as_array = numpy.array(pil_img) # the grey value we use is 238, so if all elements of axis 2 are 238, # then the pixel is grey. is_grey = numpy.all(as_array == 238, axis=2) # number that is False is non-grey, or covered, pixels # Not quite true due to scale bar, borders, etc. unique, counts = numpy.unique(is_grey, return_counts=True) non_grey = dict(zip(unique, counts))[False] covered_percent = non_grey / total_count # Don't send the image to volcview unless it has at least 15% coverage. # Allow 2% for the scale bar and other features. threshold = .17 if sector['pixelSize'] == 5: threshold = .06 if covered_percent > threshold: self._add_coastlines(pil_img) raw_data = QByteArray() buffer = QBuffer(raw_data) if not gen_cloud and not self._data_type in ('VIIRS'): # "Save" the percentile bar to a bytes buffer, in PNG format buffer.open(QIODevice.WriteOnly) _percentContainer.grab().save(buffer, "PNG") buffer.close() # Use a bytes IO object to "read" the image into a PIL object img_stream = BytesIO(raw_data) with Image.open(img_stream) as img: pil_img.paste(img, (5, 5), mask=img) # Add the scale bar and timestamp. scale_top = pil_img.height buffer.open(QIODevice.WriteOnly) scale_widget.grab() # why? WHYYYYYYYY???? scale_widget.grab().save(buffer, "PNG") buffer.close() img_stream = BytesIO(raw_data) with Image.open(img_stream) as img: scale_top = pil_img.height - img.height - 10 pil_img.paste(img, (25, scale_top), mask=img) # Add the timestamp buffer.open(QIODevice.WriteOnly) date_label.grab().save(buffer, "PNG") buffer.close() img_stream = BytesIO(raw_data) with Image.open(img_stream) as img: pil_img.paste(img, (pil_img.width - img.width - 51, scale_top - img.height - 5), mask=img) # Save an archive image logging.debug("Saving archive image for %s", band) filename = f"{self._file_date.strftime('%Y_%m_%d_%H%M%S')}-{band}-{self._data_type}.png" save_file = os.path.join(config.FILE_BASE, 'VolcView', sector['name'], filename) os.makedirs(os.path.dirname(save_file), exist_ok=True) pil_img.save(save_file, format='PNG') file_stream = BytesIO() # "Save" the image to memory in PNG format pil_img.save(file_stream, format='PNG') file_stream.seek(0) # Go back to the begining for reading out logging.debug("Uploading image for %s", band) if not DEBUG: self._volcview_upload(file_stream, sector, band) else: logging.debug("******Pretending to send to volc view") print("TEST UPLOAD", sector['name'], filename, "***200***") logging.debug("Image upload complete") if DEBUG: # This is just Debugging code to save the generated # image to disk for local analysis. # Feel free to change file paths to something more # appropriate if desired. print(f"^^^^SAVING IMAGE FOR FILE TO DISK^^^") dest_dir = f"/tmp/VolcViewImages/{sector['sector']}" os.makedirs(dest_dir, exist_ok=True) dest_file = f"{self._data_type}-{band}-{self._file_date.strftime('%Y_%m_%d_%H%M%S')}.png" dest_path = os.path.join(dest_dir, dest_file) file_stream.seek(0) with open(dest_path, 'wb') as f: f.write(file_stream.read()) ################### else: logging.info("Not enough coverage to bother with") plot_item.removeItem(plot) ############################################################### if gen_cloud: band = 'cloud' logging.debug("Plotting CLOUD dataset") plot_dataset(sector_data['cloud_fraction'], self._cloud_color_map, self._cloud_scale_labels) logging.debug("CLOUD dataset plotted. function ends.") elif self._data_type == 'VIIRS': labels = {0: "0", 0.5: "SO2 Index", 1: "100"} plot_dataset(self._normalized_du, self._du_color_map, labels) else: plot_dataset(self._normalized_du, self._du_color_map, self._du_scale_labels)