def setup_toolbar(self): color_widget = ColorWidget() color_widget.color_changed.connect(self.fourier.on_color_change) self.toolBar.addWidget(QLabel("Color:")) self.toolBar.addWidget(color_widget) self.toolBar.addWidget(QLabel("Shape:")) size_spin = QSpinBox(self.toolBar) size_spin.setValue(20) size_spin.valueChanged[int].connect(self.fourier.on_size_change) shape_combo = QComboBox(self.toolBar) shape_combo.activated[str].connect(self.fourier.on_shape_change) shape_combo.addItems(brush_shapes) self.toolBar.addWidget(shape_combo) self.toolBar.addWidget(size_spin) self.toolBar.addWidget(QLabel("Symmetry:")) x_sym = QCheckBox(self.toolBar) x_sym.toggled.connect(self.fourier.on_x_toggle) opp_sym = QCheckBox(self.toolBar) opp_sym.toggled.connect(self.fourier.on_opp_toggle) self.toolBar.addWidget(QLabel("X")) self.toolBar.addWidget(x_sym) y_sym = QCheckBox(self.toolBar) y_sym.toggled.connect(self.fourier.on_y_toggle) self.toolBar.addWidget(QLabel("Y")) self.toolBar.addWidget(y_sym) self.toolBar.addWidget(QLabel("Center")) self.toolBar.addWidget(opp_sym)
class SpinBoxPySlot(UsesQApplication, BasicPySlotCase): """Tests the connection of python slots to QSpinBox signals""" def setUp(self): super(SpinBoxPySlot, self).setUp() self.spin = QSpinBox() def tearDown(self): del self.spin super(SpinBoxPySlot, self).tearDown() def testSpinBoxValueChanged(self): """Connection of a python slot to QSpinBox.valueChanged(int)""" QObject.connect(self.spin, SIGNAL('valueChanged(int)'), self.cb) self.args = [3] self.spin.emit(SIGNAL('valueChanged(int)'), *self.args) self.assert_(self.called) def testSpinBoxValueChangedImplicit(self): """Indirect qt signal emission using QSpinBox.setValue(int)""" QObject.connect(self.spin, SIGNAL('valueChanged(int)'), self.cb) self.args = [42] self.spin.setValue(self.args[0]) self.assert_(self.called) def atestSpinBoxValueChangedFewArgs(self): """Emission of signals with fewer arguments than needed""" # XXX: PyQt4 crashes on the assertRaises QObject.connect(self.spin, SIGNAL('valueChanged(int)'), self.cb) self.args = (554,) self.assertRaises(TypeError, self.spin.emit, SIGNAL('valueChanged(int)'))
class SpinBoxPySlot(UsesQApplication, BasicPySlotCase): """Tests the connection of python slots to QSpinBox signals""" def setUp(self): super(SpinBoxPySlot, self).setUp() self.spin = QSpinBox() def tearDown(self): del self.spin super(SpinBoxPySlot, self).tearDown() def testSpinBoxValueChanged(self): """Connection of a python slot to QSpinBox.valueChanged(int)""" QObject.connect(self.spin, SIGNAL('valueChanged(int)'), self.cb) self.args = [3] self.spin.emit(SIGNAL('valueChanged(int)'), *self.args) self.assert_(self.called) def testSpinBoxValueChangedImplicit(self): """Indirect qt signal emission using QSpinBox.setValue(int)""" QObject.connect(self.spin, SIGNAL('valueChanged(int)'), self.cb) self.args = [42] self.spin.setValue(self.args[0]) self.assert_(self.called) def atestSpinBoxValueChangedFewArgs(self): """Emission of signals with fewer arguments than needed""" # XXX: PyQt4 crashes on the assertRaises QObject.connect(self.spin, SIGNAL('valueChanged(int)'), self.cb) self.args = (554,) self.assertRaises(TypeError, self.spin.emit, SIGNAL('valueChanged(int)'))
class Panel(QToolBar): def __init__(self, state, parent=None, *, editableFontSize=False): super().__init__(parent) self.appState = state self.state = FormatState(self.appState, self) self.fontSizeSpinBox = None if editableFontSize: self.fontSizeSpinBox = QSpinBox() self.fontSizeSpinBox.setAlignment(Qt.AlignRight) self.fontSizeSpinBox.setFocusPolicy(Qt.NoFocus) self.fontSizeSpinBox.setRange(MIN_FONT_SIZE, MAX_FONT_SIZE) self.fontSizeSpinBox.setSuffix(" pt") self.fontSizeSpinBox.setValue(self.appState.stdFontSize) self.fontSizeSpinBox.setToolTip("""<p><b>Font Size</b></p> <p>Set the font size in points.</p>""") self.formatActions = Actions.Format.Actions( self, self.fontSizeSpinBox) for action in self.formatActions.forToolbar(): if action is not None: self.addAction(action) else: self.addSeparator() if editableFontSize: self.addWidget(self.fontSizeSpinBox)
def setup_toolbar(self): color_widget = ColorWidget() color_widget.color_changed.connect(self.fourier.on_color_change) self.toolBar.addWidget(QLabel("Color:")) self.toolBar.addWidget(color_widget) self.toolBar.addWidget(QLabel("Shape:")) size_spin = QSpinBox(self.toolBar) size_spin.setValue(20) size_spin.valueChanged[int].connect(self.fourier.on_size_change) shape_combo = QComboBox(self.toolBar) shape_combo.activated[str].connect(self.fourier.on_shape_change) shape_combo.addItems(brush_shapes) self.toolBar.addWidget(shape_combo) self.toolBar.addWidget(size_spin) self.toolBar.addWidget(QLabel("Symmetry:")) x_sym = QCheckBox(self.toolBar) x_sym.toggled.connect(self.fourier.on_x_toggle) opp_sym = QCheckBox(self.toolBar) opp_sym.toggled.connect(self.fourier.on_opp_toggle) self.toolBar.addWidget(QLabel("X")) self.toolBar.addWidget(x_sym) y_sym = QCheckBox(self.toolBar) y_sym.toggled.connect(self.fourier.on_y_toggle) self.toolBar.addWidget(QLabel("Y")) self.toolBar.addWidget(y_sym) self.toolBar.addWidget(QLabel("Center")) self.toolBar.addWidget(opp_sym)
class SpinBoxPySignal(UsesQApplication): """Tests the connection of python signals to QSpinBox qt slots.""" def setUp(self): super(SpinBoxPySignal, self).setUp() self.obj = Dummy() self.spin = QSpinBox() self.spin.setValue(0) def tearDown(self): super(SpinBoxPySignal, self).tearDown() del self.obj del self.spin def testValueChanged(self): """Emission of a python signal to QSpinBox setValue(int)""" QObject.connect(self.obj, SIGNAL('dummy(int)'), self.spin, SLOT('setValue(int)')) self.assertEqual(self.spin.value(), 0) self.obj.emit(SIGNAL('dummy(int)'), 4) self.assertEqual(self.spin.value(), 4) def testValueChangedMultiple(self): """Multiple emissions of a python signal to QSpinBox setValue(int)""" QObject.connect(self.obj, SIGNAL('dummy(int)'), self.spin, SLOT('setValue(int)')) self.assertEqual(self.spin.value(), 0) self.obj.emit(SIGNAL('dummy(int)'), 4) self.assertEqual(self.spin.value(), 4) self.obj.emit(SIGNAL('dummy(int)'), 77) self.assertEqual(self.spin.value(), 77)
def createFontBoxesFor(parent, name, family, size, *, mono=False, tooltips=None, which="Font"): font = QFont(family, size) fontComboBox = QFontComboBox(parent) if not mono: fontFilter = QFontComboBox.ScalableFonts else: fontFilter = (QFontComboBox.ScalableFonts | QFontComboBox.MonospacedFonts) fontComboBox.setFontFilters(fontFilter) fontComboBox.setCurrentFont(font) fontSizeSpinBox = QSpinBox(parent) fontSizeSpinBox.setAlignment(Qt.AlignRight) fontSizeSpinBox.setRange(6, 36) fontSizeSpinBox.setSuffix(" pt") fontSizeSpinBox.setAlignment(Qt.AlignVCenter | Qt.AlignRight) fontSizeSpinBox.setValue(font.pointSize()) if tooltips is not None: tooltips.append((fontComboBox, """\ <p><b>{0} Font</b></p><p>The font family to use for the {0} Font.</p>""". format(which))) tooltips.append((fontSizeSpinBox, """\ <p><b>{0} Font Size</b></p><p>The font point size to use for the {0} Font.</p>""".format(which))) setattr(parent, "{}FontComboBox".format(name.lower()), fontComboBox) setattr(parent, "{}FontSizeSpinBox".format(name.lower()), fontSizeSpinBox)
class DoubleInt(QDialog): def __init__(self, cmd, parent=None, text_left='left', text_right='right', default1=0, default2=0): # cmd is a command which this dialog will call upon OKing. # The arguments are cmd(i1, i2), the two chosen ints. super(DoubleInt, self).__init__(parent) self.tr = text_right self.tl = text_left self.i1 = 0 self.i2 = 0 self.default1 = default1 self.default2 = default2 self.cmd = cmd self.initUI() def initUI(self): mainlay = QVBoxLayout() btns = QHBoxLayout() mainui = QGridLayout() mainlay.addLayout(mainui) mainlay.addLayout(btns) ok = QPushButton('OK') ok.clicked.connect(self.ok) cancel = QPushButton('Cancel') cancel.clicked.connect(self.close) btns.addStretch() btns.addWidget(ok) btns.addWidget(cancel) text1 = QLabel(self.tl) text2 = QLabel(self.tr) self.int1 = QSpinBox() self.int1.setMaximum(2048) self.int1.setMinimum(128) self.int1.setValue(self.default1) self.int2 = QSpinBox() self.int2.setMaximum(2048) self.int2.setMinimum(128) self.int2.setValue(self.default2) mainui.addWidget(text1, 0, 0) mainui.addWidget(text2, 0, 1) mainui.addWidget(self.int1, 1, 0) mainui.addWidget(self.int2, 1, 1) self.setLayout(mainlay) self.setGeometry(340, 340, 200, 100) self.setWindowTitle('MSH Suite - Double Integer') self.show() def ok(self): self.i1 = int(self.int1.text()) self.i2 = int(self.int2.text()) self.cmd(self.i1, self.i2) self.close()
def testSpinButton(self): #Connecting a lambda to a QPushButton.clicked() obj = QSpinBox() ctr = Control() arg = 444 func = lambda x: setattr(ctr, 'arg', 444) QObject.connect(obj, SIGNAL('valueChanged(int)'), func) obj.setValue(444) self.assertEqual(ctr.arg, arg) QObject.disconnect(obj, SIGNAL('valueChanged(int)'), func)
def testSpinButton(self): #Connecting a lambda to a QPushButton.clicked() obj = QSpinBox() ctr = Control() arg = 444 func = lambda x: setattr(ctr, 'arg', 444) QObject.connect(obj, SIGNAL('valueChanged(int)'), func) obj.setValue(444) self.assertEqual(ctr.arg, arg) QObject.disconnect(obj, SIGNAL('valueChanged(int)'), func)
class SliderWidget(QWidget): """ SliderWidget """ valueChanged = Signal(int) def __init__(self): super(SliderWidget, self).__init__() self.label = QLabel() self.slider = QSlider(Qt.Horizontal) self.spinbox = QSpinBox() self.slider.valueChanged.connect(self.changedValue) self.spinbox.valueChanged.connect(self.changedValue) layout = QGridLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setVerticalSpacing(0) layout.addWidget(self.label, 0, 0) layout.addWidget(self.slider, 0, 1) layout.addWidget(self.spinbox, 0, 2) self.setLayout(layout) def setName(self, name): """ Set the name for the slider """ self.label.setText(name) def setRange(self, range): """ Set the range for the value """ self.slider.setMinimum(range[0]) self.spinbox.setMinimum(range[0]) self.slider.setMaximum(range[1]) self.spinbox.setMaximum(range[1]) def setValue(self, value): """ Set the value for the slider and the spinbox """ self.slider.setValue(value) self.spinbox.setValue(value) def value(self): return self.slider.value() @Slot(int) def changedValue(self, value): self.setValue(value) self.valueChanged.emit(value)
def testSetValueIndirect(self): """Indirect signal emission: QSpinBox using valueChanged(int)/setValue(int)""" spinSend = QSpinBox() spinRec = QSpinBox() spinRec.setValue(5) QObject.connect(spinSend, SIGNAL('valueChanged(int)'), spinRec, SLOT('setValue(int)')) self.assertEqual(spinRec.value(), 5) spinSend.setValue(3) self.assertEqual(spinRec.value(), 3) self.assertEqual(spinSend.value(), 3)
def testSetValueIndirect(self): """Indirect signal emission: QSpinBox using valueChanged(int)/setValue(int)""" spinSend = QSpinBox() spinRec = QSpinBox() spinRec.setValue(5) QObject.connect(spinSend, SIGNAL('valueChanged(int)'), spinRec, SLOT('setValue(int)')) self.assertEqual(spinRec.value(), 5) spinSend.setValue(3) self.assertEqual(spinRec.value(), 3) self.assertEqual(spinSend.value(), 3)
class SliderWidget(QWidget): """ SliderWidget """ valueChanged = Signal(int) def __init__(self): super(SliderWidget, self).__init__() self.label = QLabel() self.slider = QSlider(Qt.Horizontal) self.spinbox = QSpinBox() self.slider.valueChanged.connect(self.changedValue) self.spinbox.valueChanged.connect(self.changedValue) layout = QGridLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setVerticalSpacing(0) layout.addWidget(self.label, 0, 0) layout.addWidget(self.slider, 0, 1) layout.addWidget(self.spinbox, 0, 2) self.setLayout(layout) def setName(self, name): """ Set the name for the slider """ self.label.setText(name) def setRange(self, range): """ Set the range for the value """ self.slider.setMinimum(range[0]) self.spinbox.setMinimum(range[0]) self.slider.setMaximum(range[1]) self.spinbox.setMaximum(range[1]) def setValue(self, value): """ Set the value for the slider and the spinbox """ self.slider.setValue(value) self.spinbox.setValue(value) def value(self): return self.slider.value() @Slot(int) def changedValue(self, value): self.setValue(value) self.valueChanged.emit(value)
def createBinaryOptions(self): """ Binary Analysis Options """ groupBox = QtGui.QGroupBox('Binary Analysis') # Elements cbs_unique_str = QCheckBox('Show unique strings', self) cbs_unique_com = QCheckBox('Show unique comments', self) cbs_unique_calls = QCheckBox('Show unique calls', self) cbs_entropy = QCheckBox('Calculate entropy', self) cutoff_label = QLabel('Connect BB cutoff') sb_cutoff = QSpinBox() sb_cutoff.setRange(1, 40) cutoff_func_label = QLabel('Connect functions cutoff') sbf_cutoff = QSpinBox() sbf_cutoff.setRange(1, 40) # Default states are read from the Config # class and reflected in the GUI cbs_unique_str.setCheckState( self.get_state(self.config.display_unique_strings)) cbs_unique_com.setCheckState( self.get_state(self.config.display_unique_comments)) cbs_unique_calls.setCheckState( self.get_state(self.config.display_unique_calls)) cbs_entropy.setCheckState(self.get_state( self.config.calculate_entropy)) sb_cutoff.setValue(self.config.connect_bb_cutoff) sbf_cutoff.setValue(self.config.connect_func_cutoff) # Connect elements and signals cbs_unique_str.stateChanged.connect(self.string_unique) cbs_unique_com.stateChanged.connect(self.comment_unique) cbs_unique_calls.stateChanged.connect(self.calls_unique) cbs_entropy.stateChanged.connect(self.string_entropy) sb_cutoff.valueChanged[int].connect(self.set_cutoff) sb_cutoff.valueChanged[int].connect(self.set_func_cutoff) vbox = QtGui.QVBoxLayout() vbox.addWidget(cbs_unique_str) vbox.addWidget(cbs_unique_com) vbox.addWidget(cbs_unique_calls) vbox.addWidget(cbs_entropy) vbox.addWidget(cutoff_label) vbox.addWidget(sb_cutoff) vbox.addWidget(cutoff_func_label) vbox.addWidget(sbf_cutoff) vbox.addStretch(1) groupBox.setLayout(vbox) return groupBox
class AddWindow(QDialog): def __init__(self, parent=None): super(AddWindow, self).__init__(parent) self.setGeometry(QtCore.QRect(110, 40, 171, 160)) def initUi(self): self.grid = QGridLayout() self.grid.addWidget(QLabel("Connection name"), 0, 0) self.grid.addWidget(QLabel("Username"), 2, 0) self.grid.addWidget(QLabel("Password"), 4, 0) self.grid.addWidget(QLabel("Hostname"), 6, 0) self.grid.addWidget(QLabel("Port"), 8, 0) self.connectionNameInput = QLineEdit(self) self.grid.addWidget(self.connectionNameInput, 1, 0) self.userNameInput = QLineEdit(self) self.grid.addWidget(self.userNameInput, 3, 0) self.passwordInput = QLineEdit(self) self.grid.addWidget(self.passwordInput, 5, 0) self.hostnameInput = QLineEdit(self) self.grid.addWidget(self.hostnameInput, 7, 0) self.portSpinBox = QSpinBox(self) self.portSpinBox.setMinimum(1) self.portSpinBox.setMaximum(65535) self.portSpinBox.setValue(22) self.grid.addWidget(self.portSpinBox, 9, 0) self.addButton = QPushButton("Accept") self.grid.addWidget(self.addButton, 10, 0) self.setLayout(self.grid) self.addButton.clicked.connect(self.clickedAddButton) self.show() @Slot() def clickedAddButton(self): dataRep = DataRepository() host = self.hostnameInput.text() port = self.portSpinBox.value() pwd = self.passwordInput.text() login = self.userNameInput.text() name = self.connectionNameInput.text() dataRep.addConnection({ 'host':host, 'port':port, 'pwd':pwd, 'login':login, 'name':name }) self.accept() self.close() def closeEvent(self, event): event.accept()
def createBinaryOptions(self): """ Binary Analysis Options """ groupBox = QtGui.QGroupBox('Binary Analysis') # Elements cbs_unique_str = QCheckBox('Show unique strings', self) cbs_unique_com = QCheckBox('Show unique comments', self) cbs_unique_calls = QCheckBox('Show unique calls', self) cbs_entropy = QCheckBox('Calculate entropy', self) cutoff_label = QLabel('Connect BB cutoff') sb_cutoff = QSpinBox() sb_cutoff.setRange(1, 40) cutoff_func_label = QLabel('Connect functions cutoff') sbf_cutoff = QSpinBox() sbf_cutoff.setRange(1, 40) # Default states are read from the Config # class and reflected in the GUI cbs_unique_str.setCheckState( self.get_state(self.config.display_unique_strings)) cbs_unique_com.setCheckState( self.get_state(self.config.display_unique_comments)) cbs_unique_calls.setCheckState( self.get_state(self.config.display_unique_calls)) cbs_entropy.setCheckState( self.get_state(self.config.calculate_entropy)) sb_cutoff.setValue(self.config.connect_bb_cutoff) sbf_cutoff.setValue(self.config.connect_func_cutoff) # Connect elements and signals cbs_unique_str.stateChanged.connect(self.string_unique) cbs_unique_com.stateChanged.connect(self.comment_unique) cbs_unique_calls.stateChanged.connect(self.calls_unique) cbs_entropy.stateChanged.connect(self.string_entropy) sb_cutoff.valueChanged[int].connect(self.set_cutoff) sb_cutoff.valueChanged[int].connect(self.set_func_cutoff) vbox = QtGui.QVBoxLayout() vbox.addWidget(cbs_unique_str) vbox.addWidget(cbs_unique_com) vbox.addWidget(cbs_unique_calls) vbox.addWidget(cbs_entropy) vbox.addWidget(cutoff_label) vbox.addWidget(sb_cutoff) vbox.addWidget(cutoff_func_label) vbox.addWidget(sbf_cutoff) vbox.addStretch(1) groupBox.setLayout(vbox) return groupBox
class DoFPCompound(QGroupBox): def __init__(self, parent=None): super(DoFPCompound, self).__init__(parent) self.setTitle("doFP") self.button_execute = QPushButton("Execute ...") self.spinbox_iterations = QSpinBox() self.spinbox_iterations.setMaximum(9999) self.spinbox_iterations.setValue(200) self.spinbox_iterations.setToolTip("No. iterations") layout = QHBoxLayout() layout.addWidget(self.spinbox_iterations) layout.addWidget(self.button_execute) self.setLayout(layout)
class DialogGetConfigNumber(QDialog): """ classdocs """ def __init__(self, current_tab_text=None, parent=None): """ Constructor """ super(DialogGetConfigNumber, self).__init__(parent) ok_button = QPushButton("&OK") cancel_button = QPushButton("Cancel") button_layout = QHBoxLayout() button_layout.addStretch() button_layout.addWidget(ok_button) button_layout.addWidget(cancel_button) layout = QGridLayout() current_row = 0 label_start = QLabel("config number :") self.hsb_start = QSpinBox() self.hsb_start.setMinimum(1) self.hsb_start.setMaximum(4) self.hsb_start.setValue(1) layout.addWidget(label_start, current_row, 0) layout.addWidget(self.hsb_start, current_row, 1, 1, 1) # current_row += 1 # label_finish = QLabel("ending address :") # self.hsb_finish = HexSpinBox() # self.hsb_finish.setMinimum(0x00) # self.hsb_finish.setMaximum(0x7F) # self.hsb_finish.setValue(0x7F) # layout.addWidget(label_finish, current_row, 0) # layout.addWidget(self.hsb_finish, current_row, 1, 1, 1) # # current_row += 1 # label_bank = QLabel("otp bank :") # self.spin_box_bank_sel = QSpinBox() # self.spin_box_bank_sel.setMinimum(0) # self.spin_box_bank_sel.setMaximum(1) # layout.addWidget(label_bank, current_row, 0) # layout.addWidget(self.spin_box_bank_sel, current_row, 1, 1, 1) current_row += 1 layout.addLayout(button_layout, current_row, 0, 1, 2) self.setLayout(layout) self.connect(ok_button, SIGNAL("clicked()"), self, SLOT("accept()")) self.connect(cancel_button, SIGNAL("clicked()"), self, SLOT("reject()")) self.setWindowTitle("set OTP write range / bank")
class CreateSamplesRow(): def __init__(self): self.plate = QLineEdit() self.parents = QSpinBox() self.samples = QSpinBox() self.loadedBy = QComboBox() self.parents.setMaximum(8) self.parents.setValue(2) self.samples.setMaximum(96) self.samples.setValue(94) self.loadedBy.addItems(['Column','Row']) def getPlate(self): return self.plate.text() def getParents(self): return self.parents.value() def getSamples(self): return self.samples.value() def getLoadedBy(self): return self.loadedBy.currentText()
def get_frame(self): # Info stuff. self.infos = {} infogrp = QGroupBox('Scene Info') grdlay = QGridLayout() grdlay.addWidget(QLabel('<b>Name</b>'), 0, 0) namebox = QLineEdit() self.infos['name'] = namebox namebox.setText(self.info.name) rangebox1 = QSpinBox() rangebox1.setMinimum(0) rangebox1.setMaximum(1000) self.infos['rangestart'] = rangebox1 rangebox1.setValue(self.info.frame_range[0]) rangebox2 = QSpinBox() rangebox2.setMinimum(0) rangebox2.setMaximum(1000) self.infos['rangeend'] = rangebox2 rangebox2.setValue(self.info.frame_range[1]) fpsbox = QDoubleSpinBox() self.infos['fps'] = fpsbox fpsbox.setValue(self.info.fps) bbox_btn = QPushButton('Bounding Box') bbox_btn.clicked.connect(self.edit_bbox) grdlay.addWidget(namebox, 0, 1) grdlay.addWidget(QLabel('<b>StartFrame</b>'), 1, 0) grdlay.addWidget(rangebox1, 1, 1) grdlay.addWidget(QLabel('<b>EndFrame</b>'), 1, 2) grdlay.addWidget(fpsbox, 0, 3) grdlay.addWidget(rangebox2, 1, 3) grdlay.addWidget(QLabel('<b>FPS</b>'), 0, 2) grdlay.addWidget(bbox_btn, 2, 0) grplay = QVBoxLayout() grplay.addLayout(grdlay) #grplay.addStretch() infogrp.setLayout(grplay) return infogrp
def testSetValue(self): """Direct signal emission: QSpinBox using valueChanged(int)/setValue(int)""" spinSend = QSpinBox() spinRec = QSpinBox() spinRec.setValue(5) spinSend.setValue(42) QObject.connect(spinSend, SIGNAL('valueChanged(int)'), spinRec, SLOT('setValue(int)')) self.assertEqual(spinRec.value(), 5) self.assertEqual(spinSend.value(), 42) spinSend.emit(SIGNAL('valueChanged(int)'), 3) self.assertEqual(spinRec.value(), 3) #Direct emission shouldn't change the value of the emitter self.assertEqual(spinSend.value(), 42) spinSend.emit(SIGNAL('valueChanged(int)'), 66) self.assertEqual(spinRec.value(), 66) self.assertEqual(spinSend.value(), 42)
def testSetValue(self): """Direct signal emission: QSpinBox using valueChanged(int)/setValue(int)""" spinSend = QSpinBox() spinRec = QSpinBox() spinRec.setValue(5) spinSend.setValue(42) QObject.connect(spinSend, SIGNAL('valueChanged(int)'), spinRec, SLOT('setValue(int)')) self.assertEqual(spinRec.value(), 5) self.assertEqual(spinSend.value(), 42) spinSend.emit(SIGNAL('valueChanged(int)'), 3) self.assertEqual(spinRec.value(), 3) #Direct emission shouldn't change the value of the emitter self.assertEqual(spinSend.value(), 42) spinSend.emit(SIGNAL('valueChanged(int)'), 66) self.assertEqual(spinRec.value(), 66) self.assertEqual(spinSend.value(), 42)
class NewMarkerDialog(QDialog): def __init__(self): super(NewMarkerDialog, self).__init__() self.setWindowTitle('Add new marker...') newMarkerLabel = QLabel('Marker:') self.newMarker = QLineEdit() includeLabel = QLabel('Include all samples:') self.includeAll = QCheckBox() controlsLabel = QLabel('Control wells:') self.controls = QSpinBox() self.controls.setRange(0,8) self.controls.setValue(2) layout = QGridLayout() layout.addWidget(newMarkerLabel,0,0) layout.addWidget(self.newMarker,0,1) layout.addWidget(includeLabel,1,0) layout.addWidget(self.includeAll,1,1) layout.addWidget(controlsLabel,2,0) layout.addWidget(self.controls,2,1) self.buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) layout.addWidget(self.buttons,100,0,1,2) self.setLayout(layout) def getMarker(self): return self.newMarker.text() def getIncludeAll(self): return self.includeAll.isChecked() def getControls(self): return self.controls.value() @staticmethod def run(parent = None): dialog = NewMarkerDialog() result = dialog.exec_() newMarker = dialog.getMarker() includeAll = dialog.getIncludeAll() controls = dialog.getControls() return (newMarker,includeAll,controls,result == QDialog.Accepted)
class ImageViewer(QWidget): def __init__(self, filename=None, name=None, parent=None): super(ImageViewer, self).__init__(parent) self.imageRaw = np.zeros((200, 200, 200)) self.imageRGB = np.zeros((200, 200, 200, 3)) self.viewRange = [[100, 100], [100, 100], [100, 100]] self.zoomFactors = [3.0, 3.0, 3.0] self.iMin = 0 self.iMax = 1000 self.ijk = [0, 0, 0] self.name = 'untitled' self.initHbRL() self.mouseCursorCross = False ## Upper buttons self.upperRow = QHBoxLayout() self.drawRightHb = QPushButton('RightHb', self) self.drawLeftHb = QPushButton('LeftHb', self) self.drawRightHb.setCheckable(True) self.drawLeftHb.setCheckable(True) self.upperRow.addWidget(self.drawRightHb) self.upperRow.addWidget(self.drawLeftHb) QtCore.QObject.connect(self.drawRightHb, QtCore.SIGNAL('clicked()'), self.clickRightHb) QtCore.QObject.connect(self.drawLeftHb, QtCore.SIGNAL('clicked()'), self.clickLeftHb) ## View Layout self.scenes = [ MyGraphicsScene(self, 0), MyGraphicsScene(self, 1), MyGraphicsScene(self, 2) ] self.views = [ QGraphicsView(self.scenes[0]), QGraphicsView(self.scenes[1]), QGraphicsView(self.scenes[2]) ] self.sceneItems = [None, None, None] #Scene 4 view4 = QGridLayout() labelX = QLabel('X: ') labelY = QLabel('Y: ') labelZ = QLabel('Z: ') self.spin = [QSpinBox(), QSpinBox(), QSpinBox()] labelMinIntensity = QLabel('Min: ') labelMaxIntensity = QLabel('Max: ') labelZoom = QLabel('Zoom: ') self.spinMin = QSpinBox() self.spinMax = QSpinBox() self.spinZoom = QSpinBox() self.spinMin.setMaximum(10000) self.spinMax.setMaximum(10000) self.spinMin.setValue(self.iMin) self.spinMax.setValue(self.iMax) self.spinZoom.setValue(self.zoomFactors[0]) self.spinMin.setKeyboardTracking(False) self.spinMin.valueChanged.connect(self.setIntensity) self.spinMax.setKeyboardTracking(False) self.spinMax.valueChanged.connect(self.setIntensityMax) self.spinZoom.valueChanged.connect(self.setZoomFactor) self.spinZoom.setKeyboardTracking(False) labelAreaR = QLabel('Right: ') labelAreaL = QLabel('Left: ') self.labelAreaValueR = QLabel() self.labelAreaValueL = QLabel() view4.addWidget(labelX, 0, 0, 2, 1) view4.addWidget(labelY, 1, 0, 2, 1) view4.addWidget(labelZ, 2, 0, 2, 1) view4.addWidget(labelMinIntensity, 4, 0, 2, 1) view4.addWidget(labelMaxIntensity, 5, 0, 2, 1) view4.addWidget(labelZoom, 6, 0, 2, 1) view4.addWidget(labelAreaR, 7, 0) view4.addWidget(labelAreaL, 7, 2) view4.addWidget(self.spin[0], 0, 2, 2, 1) view4.addWidget(self.spin[1], 1, 2, 2, 1) view4.addWidget(self.spin[2], 2, 2, 2, 1) view4.addWidget(self.spinMin, 4, 2, 2, 1) view4.addWidget(self.spinMax, 5, 2, 2, 1) view4.addWidget(self.spinZoom, 6, 2, 2, 1) view4.addWidget(self.labelAreaValueR, 7, 1) view4.addWidget(self.labelAreaValueL, 7, 3) self.viewLayout = QGridLayout() self.viewLayout.addWidget(self.views[0], 0, 0) self.viewLayout.addWidget(self.views[1], 0, 1) self.viewLayout.addWidget(self.views[2], 1, 0) self.viewLayout.addLayout(view4, 1, 1) ## Lower self.lowerRow = QHBoxLayout() calculateButtonDown = QPushButton('calculateVolume', self) saveButtonDown = QPushButton('SaveHb', self) loadButtonDown = QPushButton('loadHb', self) savepngButtonDown = QPushButton('Save PNG', self) self.lowerRow.addWidget(calculateButtonDown) self.lowerRow.addWidget(saveButtonDown) self.lowerRow.addWidget(loadButtonDown) self.lowerRow.addWidget(savepngButtonDown) QtCore.QObject.connect(calculateButtonDown, QtCore.SIGNAL('clicked()'), self.getHbAreas) QtCore.QObject.connect(saveButtonDown, QtCore.SIGNAL('clicked()'), self.saveHb) QtCore.QObject.connect(loadButtonDown, QtCore.SIGNAL('clicked()'), self.loadHb) QtCore.QObject.connect(savepngButtonDown, QtCore.SIGNAL('clicked()'), self.saveCoronalSlice) ## Layout self.mainLayout = QVBoxLayout() self.mainLayout.addLayout(self.upperRow) self.mainLayout.addLayout(self.viewLayout) self.mainLayout.addLayout(self.lowerRow) self.setLayout(self.mainLayout) self.setWindowTitle("Image Viewer") self.resize(600, 700) self.show() if filename: self.loadNifti1(filename, name=name) def loadNifti1(self, filename, name=None): self.loadImage = LoadImage() self.loadImage.readNifti1(filename) if name is None: name = filename[:] if name[-7:] == '.nii.gz': name = name[:-7] elif name[-4:] == '.nii': name = name[:-4] for ch in ['/', '.', '~']: pos = name.find(ch) while pos > -1: name = '%s_%s' % (name[:pos], name[pos + 1:]) pos = name.find(ch) self.name = name self.imageRaw = self.loadImage.data self.spinMin.setMaximum(int(self.imageRaw.max() * 1.2)) self.spinMax.setMaximum(int(self.imageRaw.max() * 1.2)) #self.iMin = int(max(0, self.imageRaw.min()*1.2)) self.iMin = 0 self.iMax = int(self.imageRaw.max() * 0.8) self.spinMin.setValue(self.iMin) self.spinMax.setValue(self.iMax) self.imageRGB = convertImageRGB( resetIntensity(self.imageRaw, iMin=self.iMin, iMax=self.iMax)) self.setIJK() self.drawBaseImage() self.setSceneIJK() self.showSpinValue() self.setMouseCursor(True) def showSpinValue(self): self.spin[0].setMaximum(self.imageRaw.shape[0]) self.spin[1].setMaximum(self.imageRaw.shape[1]) self.spin[2].setMaximum(self.imageRaw.shape[2]) self.spin[0].setKeyboardTracking(False) self.spin[1].setKeyboardTracking(False) self.spin[2].setKeyboardTracking(False) self.spin[0].setValue(self.ijk[0]) self.spin[1].setValue(self.ijk[1]) self.spin[2].setValue(self.ijk[2]) self.spin[0].valueChanged.connect(self.resetI) self.spin[1].valueChanged.connect(self.resetJ) self.spin[2].valueChanged.connect(self.resetK) def resetI(self, i): self.ijk[0] = i self.drawBaseImage([0]) def resetJ(self, j): self.ijk[1] = j self.drawBaseImage([1]) self.labelAreaValueR.clear() self.labelAreaValueL.clear() def resetK(self, k): self.ijk[2] = k self.drawBaseImage([2]) def initHbRL(self): self.hbRight = { 'name': 'HbRight', 'color': 'red', 'images': [], 'points': [] } self.hbLeft = { 'name': 'HbLeft', 'color': 'blue', 'images': [], 'points': [] } def clickRightHb(self): if self.drawLeftHb.isChecked(): self.drawLeftHb.setChecked(False) def clickLeftHb(self): if self.drawRightHb.isChecked(): self.drawRightHb.setChecked(False) def saveHb(self, filename=None): if filename is None: filename = '%s_lawson_hb.csv' % self.name writeHb(filename, self.hbRight, self.hbLeft) with open(filename, 'a') as fout: volumes = self.getHbAreas() fout.write('%s,%s\n' % (volumes[0], volumes[1])) png_filename = filename[:-4] def saveCoronalSlice(self, filename=None): viewIndex = 1 if filename is None: filename = '%s_lawson_hb' % self.name filename += str('%03d.png' % self.ijk[viewIndex]) self.scenes[viewIndex].savePng(filename, 'PNG') def loadHb(self, filename=None): if filename is None: filename = '%s_lawson_hb.csv' % self.name self.initHbRL() readHb(filename, self.hbRight, self.hbLeft) def setMouseCursor(self, cross=False): if cross != self.mouseCursorCross: self.mouseCursorCross = cross if cross: #self.setCursor(QCursor(QtCore.Qt.CrossCursor)) self.setCursor(QtCore.Qt.CrossCursor) else: #self.setCursor(QCursor(QtCore.Qt.ArrowCursor)) self.setCursor(QtCore.Qt.ArrowCursor) def getZoomFactors(self): return self.zoomFactors def magZoomFactors(self, ratio): self.setZoomFactors([value + ratio for value in self.zoomFactors]) self.spinZoom.setValue(self.zoomFactors[0]) def setZoomFactors(self, zoomFactors): sceneRects = self.saveScene() self.zoomFactors = zoomFactors self.drawBaseImage() self.restoreScene(sceneRects) def setZoomFactor(self, zoomFactor): self.setZoomFactors([zoomFactor, zoomFactor, zoomFactor]) def getIntensity(self): return self.iMin, self.iMax def setIntensityMax(self, iMax): self.setIntensity(iMax=iMax) def setIntensity(self, iMin=None, iMax=None): if iMin: self.iMin = iMin if iMax: self.iMax = iMax self.imageRGB = convertImageRGB( resetIntensity(self.imageRaw, iMin=self.iMin, iMax=self.iMax)) self.drawBaseImage() def mousePressEventLeft(self, viewIndex, x, y): if viewIndex == 1: if self.drawRightHb.isChecked(): hbDict = self.hbRight labelAreaValue = self.labelAreaValueR elif self.drawLeftHb.isChecked(): hbDict = self.hbLeft labelAreaValue = self.labelAreaValueL else: self.resetIJK(viewIndex, x, y) return if not hbDict.has_key(self.ijk[viewIndex]): hbDict[self.ijk[viewIndex]] = HbRegionDraw() if hbDict[self.ijk[viewIndex]].insert == 4: for item in hbDict['images']: # lines self.scenes[viewIndex].removeItem(item) hbDict['images'] = [] item = hbDict['points'].pop(0) # last point self.scenes[viewIndex].removeItem(item) i, j = self.point2fijk(viewIndex, x, y) if not hbDict[self.ijk[viewIndex]].push((i, j)): item = hbDict['points'].pop(0) # last point self.scenes[viewIndex].removeItem(item) #self.scenes[viewIndex].removeItem(self.scenes[viewIndex].items()[0]) x_round, y_round = self.ij2point(viewIndex, i, j) hbDict['points'].insert( 0, self.scenes[viewIndex].addEllipse( x_round - 1, y_round - 1, 2, 2, pen=QPen(QColor(hbDict['color'])))) if hbDict[self.ijk[viewIndex]].insert >= 4: area = hbDict[self.ijk[viewIndex]].calculate_area( hbDict['name']) print ' %s %s: %s' % (self.ijk[viewIndex], hbDict['name'], area) self.drawHb(hbDict) #labelAreaValue.setText('%s: %3.2f' % (self.ijk[viewIndex], area)) labelAreaValue.setText('%3.2f' % (area)) else: self.resetIJK(viewIndex, x, y) def mousePressEventRight(self, viewIndex, x, y): if viewIndex == 1: if self.drawRightHb.isChecked(): hbDict = self.hbRight elif self.drawLeftHb.isChecked(): hbDict = self.hbLeft else: return if not hbDict.has_key(self.ijk[viewIndex]): return if hbDict[self.ijk[viewIndex]].insert == 4: for item in hbDict['images']: # lines self.scenes[viewIndex].removeItem(item) hbDict['images'] = [] #for item in self.scenes[viewIndex].items()[:3]: # lines # self.scenes[viewIndex].removeItem(item) if hbDict[self.ijk[viewIndex]].pop(): item = hbDict['points'].pop(0) # last point self.scenes[viewIndex].removeItem(item) #self.scenes[viewIndex].removeItem(self.scenes[viewIndex].items()[0]) def moveIJK(self, viewIndex, dx): self.ijk[viewIndex] += dx self.spin[viewIndex].setValue(self.ijk[viewIndex]) self.drawBaseImage([viewIndex]) self.labelAreaValueR.clear() self.labelAreaValueL.clear() def point2fijk(self, viewIndex, x, y): indexTable = [[1, 2], [0, 2], [0, 1]] xIndex = indexTable[viewIndex][0] yIndex = indexTable[viewIndex][1] ijkX = float(x) / self.zoomFactors[viewIndex] ijkY = self.imageRGB.shape[yIndex] - 1 - float( y) / self.zoomFactors[viewIndex] ijkX = np.round(ijkX * 2) / 2 ijkY = np.round(ijkY * 2) / 2 return (ijkX, ijkY) def point2fijk_flt(self, viewIndex, x, y): indexTable = [[1, 2], [0, 2], [0, 1]] xIndex = indexTable[viewIndex][0] yIndex = indexTable[viewIndex][1] ijkX = float(x) / self.zoomFactors[viewIndex] ijkY = self.imageRGB.shape[yIndex] - 1 - float( y) / self.zoomFactors[viewIndex] return (ijkX, ijkY) def point2ijk(self, viewIndex, x, y): indexTable = [[1, 2], [0, 2], [0, 1]] xIndex = indexTable[viewIndex][0] yIndex = indexTable[viewIndex][1] ijkX = int(x / self.zoomFactors[viewIndex]) ijkY = self.imageRGB.shape[yIndex] - 1 - int( y / self.zoomFactors[viewIndex]) return (ijkX, ijkY) def ij2point(self, viewIndex, i, j): indexTable = [[1, 2], [0, 2], [0, 1]] xIndex = indexTable[viewIndex][0] yIndex = indexTable[viewIndex][1] pointX = i * self.zoomFactors[viewIndex] pointY = (self.imageRGB.shape[yIndex] - 1 - j) * self.zoomFactors[viewIndex] return (pointX, pointY) def resetIJK(self, viewIndex, x, y): indexTable = [[1, 2], [0, 2], [0, 1]] xIndex = indexTable[viewIndex][0] yIndex = indexTable[viewIndex][1] self.ijk[xIndex] = int(x / self.zoomFactors[viewIndex]) self.ijk[yIndex] = self.imageRGB.shape[yIndex] - 1 - int( y / self.zoomFactors[viewIndex]) self.spin[xIndex].setValue(self.ijk[xIndex]) self.spin[yIndex].setValue(self.ijk[yIndex]) self.drawBaseImage(indexTable[viewIndex]) self.labelAreaValueR.clear() self.labelAreaValueL.clear() def saveScene(self): sceneRects = [0, 0, 0] for i in range(3): size = self.views[i].size().toTuple() x, y, _, _ = self.scenes[i].sceneRect().getRect() x += (size[0] - 10) / 2.0 y += (size[1] - 10) / 2.0 x /= self.zoomFactors[i] y /= self.zoomFactors[i] sceneRects[i] = [x, y] return sceneRects def restoreScene(self, sceneRects): for i in range(3): size = self.views[i].size().toTuple() x = sceneRects[i][0] * self.zoomFactors[i] y = sceneRects[i][1] * self.zoomFactors[i] self.scenes[i].setSceneRect(x - (size[0] - 10) / 2, y - (size[0] - 10) / 2, size[0] - 10, size[1] - 10) def setSceneIJK(self, viewIndex=(0, 1, 2)): for i in viewIndex: size = self.views[i].size().toTuple() xyCenter = [ self.ijk[tmp] * self.zoomFactors[i] for tmp in range(3) if tmp is not i ] self.scenes[i].setSceneRect(xyCenter[0] - size[0] / 2.0, xyCenter[1] - size[1] / 2.0, size[0] - 10, size[1] - 10) def setIJK(self, ijk='center'): if ijk == 'center': self.ijk = [ self.imageRGB.shape[0] / 2, self.imageRGB.shape[1] / 2, self.imageRGB.shape[2] / 2 ] else: self.ijk = ijk self.spin[0].setValue(self.ijk[0]) self.spin[1].setValue(self.ijk[1]) self.spin[2].setValue(self.ijk[2]) def get2D(self, plane): if plane == 0: return np.rot90(self.imageRGB[self.ijk[0], :, :, :]) elif plane == 1: return np.rot90(self.imageRGB[:, self.ijk[1], :, :]) elif plane == 2: return np.rot90(self.imageRGB[:, :, self.ijk[2], :]) def drawBaseImage(self, viewIndex=(0, 1, 2), eraseOthers=True): for i in viewIndex: imageArray3d = self.get2D(i) height, width, bytesPerComponent = imageArray3d.shape imageArray = imageArray3d.flatten() bytesPerLine = bytesPerComponent * width image = QImage(imageArray, width, height, bytesPerLine, QImage.Format_RGB888) #image = image.scaled( int(width*self.zoomFactors[i]), int(height*self.zoomFactors[i]), Qt.KeepAspectRatio, Qt.SmoothTransformation) image = image.scaled(int(width * self.zoomFactors[i]), int(height * self.zoomFactors[i]), QtCore.Qt.KeepAspectRatio) if self.sceneItems[i] is not None: #self.scenes[i].removeItem(self.sceneItems[i]) self.sceneItems[i].setPixmap(QPixmap.fromImage(image)) if False: items = self.scenes[i].items() for item in items: self.scenes[i].removeItem(item) self.sceneItems[i] = self.scenes[i].addPixmap( QPixmap.fromImage(image)) for item in items[1:]: self.scenes[i].additem(item) del items else: self.sceneItems[i] = self.scenes[i].addPixmap( QPixmap.fromImage(image)) if eraseOthers: for item in self.scenes[i].items(): if item != self.sceneItems[i]: self.scenes[i].removeItem(item) # TODO: where to put this self.drawHbPts(self.hbRight) self.drawHb(self.hbRight) self.drawHbPts(self.hbLeft) self.drawHb(self.hbLeft) def drawHbPts(self, hbDict): viewIndex = 1 if not hbDict.has_key(self.ijk[viewIndex]): return pts = [ self.ij2point(viewIndex, i, j) for (i, j) in hbDict[self.ijk[viewIndex]].get_points() ] for i in range(hbDict[self.ijk[viewIndex]].insert): hbDict['points'].insert( 0, self.scenes[viewIndex].addEllipse( pts[i][0] - 1, pts[i][1] - 1, 2, 2, pen=QPen(QColor(hbDict['color'])))) def drawHb(self, hbDict): viewIndex = 1 if not hbDict.has_key(self.ijk[viewIndex]): return if hbDict[self.ijk[viewIndex]].insert < 4: return a, b, c, d = [ self.ij2point(viewIndex, i, j) for (i, j) in hbDict[self.ijk[viewIndex]].get_points() ] cp = hbDict[self.ijk[viewIndex]].cp cp = self.ij2point(viewIndex, cp[0], cp[1]) vA = (a[0] - cp[0], a[1] - cp[1]) vB = (b[0] - cp[0], b[1] - cp[1]) vD = (d[0] - cp[0], d[1] - cp[1]) arcAD = QPainterPath() arcDB = QPainterPath() if hbDict['name'] == 'HbRight': sign = 1 startAngle = 0 else: sign = -1 startAngle = 180 angleADlad = sign * angleBw2Vectors(vA, vD) angleAD = 180 / np.pi * angleADlad if vD[0] * vD[0] + vD[1] * vD[1] >= vA[0] * vA[0] + vA[1] * vA[1]: rotD = (np.sqrt(vD[0] * vD[0] + vD[1] * vD[1]), 0) coefA = rotD[0] rotA = rotateVector(vA, angleADlad) coefB = np.sqrt(coefA * coefA / (coefA * coefA - rotA[0] * rotA[0]) * rotA[1] * rotA[1]) eccentricAnomalyAD = -180 / np.pi * np.arctan( coefA / coefB * np.tan(angleADlad)) arcAD.moveTo(cp[0] + sign * coefA, cp[1]) arcAD.arcTo(cp[0] - coefA, cp[1] - coefB, 2 * coefA, 2 * coefB, startAngle, eccentricAnomalyAD) else: rotA = (np.sqrt(vA[0] * vA[0] + vA[1] * vA[1]), 0) coefA = rotA[0] angleDAlad = sign * angleBw2Vectors(vD, vA) angleDA = 180 / np.pi * angleDAlad rotD = vD coefB = np.sqrt(coefA * coefA / (coefA * coefA - rotD[0] * rotD[0]) * rotD[1] * rotD[1]) eccentricAnomalyDA = 180 / np.pi * np.arctan( coefA / coefB * np.tan(angleDAlad)) arcAD.moveTo(cp[0] + sign * coefA, cp[1]) arcAD.arcTo(cp[0] - coefA, cp[1] - coefB, 2 * coefA, 2 * coefB, startAngle, eccentricAnomalyDA) angleAD = 0.0 if vD[0] * vD[0] + vD[1] * vD[1] >= vB[0] * vB[0] + vB[1] * vB[1]: rotD = (np.sqrt(vD[0] * vD[0] + vD[1] * vD[1]), 0) coefA = rotD[0] angleBDlad = sign * angleBw2Vectors(vD, vB) angleBD = 180 / np.pi * angleBDlad rotB = rotateVector(vB, angleADlad) coefB = np.sqrt(coefA * coefA / (coefA * coefA - rotB[0] * rotB[0]) * rotB[1] * rotB[1]) eccentricAnomalyDB = 180 / np.pi * np.arctan( coefA / coefB * np.tan(angleBDlad)) arcDB.moveTo(cp[0] + sign * coefA, cp[1]) arcDB.arcTo(cp[0] - coefA, cp[1] - coefB, 2 * coefA, 2 * coefB, startAngle, eccentricAnomalyDB) angleAB = 180 / np.pi * sign * angleBw2Vectors(vA, vD) else: rotB = (np.sqrt(vB[0] * vB[0] + vB[1] * vB[1]), 0) coefA = rotB[0] angleABlad = sign * angleBw2Vectors(vA, vB) angleAB = 180 / np.pi * angleABlad angleDBlad = sign * angleBw2Vectors(vD, vB) angleDB = 180 / np.pi * angleDBlad rotD = rotateVector(vD, angleABlad) coefB = np.sqrt(coefA * coefA / (coefA * coefA - rotD[0] * rotD[0]) * rotD[1] * rotD[1]) eccentricAnomalyDB = -180 / np.pi * np.arctan( coefA / coefB * np.tan(angleDBlad)) arcDB.moveTo(cp[0] + sign * coefA, cp[1]) arcDB.arcTo(cp[0] - coefA, cp[1] - coefB, 2 * coefA, 2 * coefB, startAngle, eccentricAnomalyDB) imgAC = self.scenes[viewIndex].addLine(a[0], a[1], cp[0], cp[1], pen=QPen(QColor( hbDict['color']))) imgBC = self.scenes[viewIndex].addLine(b[0], b[1], c[0], c[1], pen=QPen(QColor( hbDict['color']))) imgAD = self.scenes[viewIndex].addPath(arcAD, pen=QPen(QColor( hbDict['color']))) imgAD.setTransform(QTransform().translate( cp[0], cp[1]).rotate(-angleAD).translate(-cp[0], -cp[1])) imgDB = self.scenes[viewIndex].addPath(arcDB, pen=QPen(QColor( hbDict['color']))) imgDB.setTransform(QTransform().translate( cp[0], cp[1]).rotate(-angleAB).translate(-cp[0], -cp[1])) hbDict['images'] = [imgAD, imgDB, imgBC, imgAC] def getHbAreas(self): volumes = [] for hbDict in [self.hbRight, self.hbLeft]: keys = hbDict.keys() if not keys: volumes.append(0.0) continue print 'Calculate %s Volume...' % hbDict['name'] unit = self.loadImage.zooms[0] * self.loadImage.zooms[ 1] * self.loadImage.zooms[2] volume = 0.0 keys.sort() for key in keys: if type(key) == type(''): continue area = hbDict[key].area print ' %s: %s (voxel)' % (key, area) volume += area volume *= unit print 'volume = %s (mm^3)' % volume volumes.append(volume) return volumes
def initUI(self): grp = QGroupBox('Material') grplay = QGridLayout() name = QLineEdit() name.setText(self.mat.name) self.controls['name'] = name tex0 = QLineEdit() tex0.setText(self.mat.tex0) self.controls['tex0'] = tex0 tex1 = QLineEdit() tex1.setText(self.mat.tex1) self.controls['tex1'] = tex1 tex2 = QLineEdit() tex2.setText(self.mat.tex2) self.controls['tex2'] = tex2 tex3 = QLineEdit() tex3.setText(self.mat.tex3) self.controls['tex3'] = tex3 flags = QGroupBox('Flags') fllay = QGridLayout() for ind, flag in enumerate(self.mat.flags): fllay.addWidget(QLabel(self.pretty_flags[flag[0]]), ind, 0) box = QCheckBox() fllay.addWidget(box, ind, 1) if flag[1]: box.toggle() self.controls[flag[0]] = box fllay.addWidget(QLabel('<b>RenderType</b>'), 8, 0) numbox = QComboBox() numbox.addItems(self.render_types) numbox.setCurrentIndex(self.mat.render_type) fllay.addWidget(numbox) self.controls['render_type'] = numbox fllay.addWidget(QLabel('<b>Data0</b>'), 9, 0) d0 = QSpinBox() d0.setValue(self.mat.data0) d0.setMinimum(0) d0.setMaximum(255) fllay.addWidget(d0) self.controls['data0'] = d0 fllay.addWidget(QLabel('<b>Data1</b>'), 10, 0) d1 = QSpinBox() d1.setValue(self.mat.data1) d1.setMinimum(0) d1.setMaximum(255) fllay.addWidget(d1) self.controls['data1'] = d1 flags.setLayout(fllay) colors = QGroupBox('Colors') collay = QGridLayout() self.add_color('<b>Diffuse</b>', self.mat.diff_color, collay, 3) self.add_color('<b>Specular</b>', self.mat.spec_color, collay, 4) self.add_color('<b>Ambient</b>', self.mat.ambt_color, collay, 5) colors.setLayout(collay) grplay.addWidget(QLabel('<b>Name</b>'), 0, 0) grplay.addWidget(name, 0, 1) grplay.addWidget(QLabel('<b>Texture0</b>'), 1, 0) grplay.addWidget(tex0, 1, 1) grplay.addWidget(QLabel('<b>Texture1</b>'), 1, 2) grplay.addWidget(tex1, 1, 3) grplay.addWidget(QLabel('<b>Texture2</b>'), 2, 0) grplay.addWidget(tex2, 2, 1) grplay.addWidget(QLabel('<b>Texture3</b>'), 2, 2) grplay.addWidget(tex3, 2, 3) grplay.addWidget(QLabel('<b>Gloss</b>'), 3, 0) gloss = QDoubleSpinBox() gloss.setValue(self.mat.gloss) grplay.addWidget(gloss, 3, 1) self.controls['gloss'] = gloss grplay.addWidget(colors, 4, 0, 1, 5) grplay.addWidget(flags, 5, 0, 1, 3) grp.setLayout(grplay) btns = QHBoxLayout() save = QPushButton('Save') save.clicked.connect(self.save) cancel = QPushButton('Cancel') cancel.clicked.connect(self.close) btns.addStretch() btns.addWidget(save) btns.addWidget(cancel) mainlay = QVBoxLayout() mainlay.addWidget(grp) mainlay.addLayout(btns) self.setLayout(mainlay) self.setGeometry(340, 340, 440, 200) self.setWindowTitle('MSH Suite - {0}'.format(self.mat.name)) self.show()
class CalculateSalaryWidget(QWidget): """A PySide widget which provides GUI for selecting employee and calculating salary for a month & year Tis contains boxes for month and year input. Enter the month and year of salary to be calculated here. This is initially automatically set to present month and year. Also contains a ``SearchBox`` for selecting name of employee who's salary needs to be calculated. Selecting the name automatically loads IDs of all employees with that name (in case multiple employees have exact same name) in a dropdown box (``QComboBox``). After selecting the required ID from there, the employee info is automatically loaded. The allowances and deductions are loaded in ``ValueBoxes`` and hence may be edited if required. After selecting everything, user needs to click 'calculate' button. This creates a ``Salary`` object from available info. The actual salary calculation takes place inside ``Salary`` class. This salary object is then passed to ``ShowPaySlipWidget`` which shows the final result and has option to confirm the calculation and print the payslip. Note: To automatically call functions on GUI interaction such as button click, PySide Signal and Slots are used. visit http://zetcode.com/gui/pysidetutorial/eventsandsignals/ for more on PySide Signal and Slots. See Also: - :py:mod:`SearchBox <CustomWidgets.searchBox.SearchBox>` widget from CustomWidgets - :py:mod:`ValueBox <CustomWidgets.valueBox.ValueBox>` widget from CustomWidgets - :py:mod:`Salary <CustomClasses.Salary.Salary>` class from CustomClasses - :py:mod:`ShowPaySlipWidget <ShowPaySlip.ShowPaySlipWidget>` """ def __init__(self, parent=None): QWidget.__init__(self, parent) self.__parent = parent self.title = "Calculate Salary" self.__desig = None self.__emp = None t = datetime.now() self.month = QComboBox() self.month.addItems([ "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" ]) self.month.setCurrentIndex(t.month - 1) self.year = QSpinBox() self.year.setRange(1900, 3000) self.year.setValue(t.year) self.name = SearchBox(self) self.name.setPlaceholderText("Enter Name") self.nameList = [] self.nameList = Database.getdb().getEmployeeNameList() self.name.setList(self.nameList) self.id = QComboBox() self.designation = QLineEdit() self.designation.setReadOnly(True) self.originalPay = QLineEdit() self.originalPay.setReadOnly(True) self.originalPayGrade = QLineEdit() self.originalPayGrade.setReadOnly(True) self.DOJ = QLineEdit() self.DOJ.setReadOnly(True) self.pan = QLineEdit() self.pan.setReadOnly(True) self.presentPay = QLineEdit() self.presentPay.setReadOnly(True) self.da_percent = ValueBox() self.hra_percent = ValueBox() self.ta_percent = ValueBox() self.it_percent = ValueBox() self.pt_percent = ValueBox() self.name.editTextChanged.connect(self.clearInfo) self.bttnCalculate = QPushButton("Calculate") self.bttnCalculate.clicked.connect(self.calculate) self.bttnCancel = QPushButton("Back") self.bttnCancel.clicked.connect(self.goBack) self.bttnCalculate.setObjectName("OkButton") self.bttnCancel.setObjectName("CancelButton") self.name.returnPressed.connect(self.setIDList) self.id.currentIndexChanged.connect( lambda: self.loadInfo(self.id.currentText())) self.setupUI() def calculate(self): """Automatically called on clicking calculate button""" if self.__emp is None: QMessageBox(QMessageBox.Information, "Error", "Please select an employee!", parent=self).exec_() else: if self.__parent is not None: self.__desig = Designation(self.__desig.designation, self.da_percent.text(), self.hra_percent.text(), self.ta_percent.text(), self.it_percent.text(), self.pt_percent.text()) salary = Salary(self.__emp, self.__desig, self.month.currentText(), self.year.text()) self.__parent.gotoPage("Result", salary) def clearInfo(self): """Clears the contents of all input/display boxes""" self.id.setCurrentIndex(-1) self.designation.clear() self.originalPay.clear() self.originalPayGrade.clear() self.DOJ.clear() self.pan.clear() self.da_percent.clear() self.hra_percent.clear() self.ta_percent.clear() self.it_percent.clear() self.pt_percent.clear() self.__desig = None self.__emp = None def loadInfo(self, id): """Loads info for given ID in the GUI boxes. This automatically called on selecting an ID from GUI Args: id (str): ID of employee who's info needs to be loaded """ print "id =", id, "...", len(id) if id != '': self.__emp = Database.getdb().getEmployeeInfo(id) self.designation.setText(self.__emp.designation) self.originalPay.setText(str(self.__emp.originalPay)) self.originalPayGrade.setText(str(self.__emp.originalPayGrade)) self.DOJ.setText(self.__emp.getStrDate()) self.pan.setText(self.__emp.pan) self.__desig = Database.getdb().getDesignationInfo( self.__emp.designation) self.da_percent.setText(str(self.__desig.da)) self.hra_percent.setText(str(self.__desig.hra)) self.ta_percent.setText(str(self.__desig.ta)) self.it_percent.setText(str(self.__desig.it)) self.pt_percent.setText(str(self.__desig.pt)) def setIDList(self, name): """Loads IDs of all employees with given name into the ID dropdown box This function is automatically called after selecting a name from the GUI Args: name (str): Name of employee """ self.id.clear() self.id.addItems(Database.getdb().getIdListForName(name)) def goBack(self): if self.__parent is not None: self.__parent.goBack() def setupUI(self): """Arranges GUI elements inside the widget properly""" paneLayout = QHBoxLayout() paneLayout.setContentsMargins(0, 0, 0, 0) leftPane = QFrame() leftPane.setObjectName("leftPane") leftPaneLayout = QVBoxLayout() leftPaneLayout.setContentsMargins(20, 20, 20, 10) heading = QLabel("Select Employee: ") heading.setObjectName("heading") leftPaneLayout.addWidget(heading) leftPaneLayout.addSpacing(10) datelayout = QHBoxLayout() datelayout.addWidget(QLabel("Salary for month of ")) datelayout.addWidget(self.month) datelayout.addWidget(self.year) datelayout.addStretch() leftPaneLayout.addLayout(datelayout) leftForm = QFormLayout() leftForm.setSpacing(10) leftForm.addRow(QLabel("Name"), self.name) leftForm.addRow(QLabel("ID No."), self.id) leftPaneLayout.addLayout(leftForm) leftPaneLayout.addStretch() leftPane.setLayout(leftPaneLayout) paneLayout.addWidget(leftPane) layout = QVBoxLayout() layout.setContentsMargins(20, 20, 20, 10) form = QFormLayout() form.setSpacing(10) form.addRow(QLabel("Designation"), self.designation) form.addRow(QLabel("Original Pay"), self.originalPay) form.addRow(QLabel("Original Pay Grade"), self.originalPayGrade) form.addRow(QLabel("Date of joining"), self.DOJ) form.addRow(QLabel("Pan No."), self.pan) infoGroup = QGroupBox("Basic Info") infoGroup.setLayout(form) layout.addWidget(infoGroup) leftForm = QFormLayout() leftForm.addRow(QLabel("Dearness Allowance"), self.da_percent) leftForm.addRow(QLabel("Housing Rent Allowance"), self.hra_percent) leftForm.addRow(QLabel("Transport Allowance"), self.ta_percent) leftGroup = QGroupBox("Allowances") leftGroup.setLayout(leftForm) rightForm = QFormLayout() rightForm.addRow(QLabel("Income Tax"), self.it_percent) rightForm.addRow(QLabel("Profession Tax"), self.pt_percent) rightGroup = QGroupBox("Deductions") rightGroup.setLayout(rightForm) table = QHBoxLayout() table.addWidget(leftGroup) table.addWidget(rightGroup) layout.addLayout(table) layout.addStretch() bttnLayout = QHBoxLayout() bttnLayout.addStretch() bttnLayout.addWidget(self.bttnCancel) bttnLayout.addWidget(self.bttnCalculate) layout.addLayout(bttnLayout) paneLayout.addLayout(layout) self.setLayout(paneLayout)
class MainWindow(QMainWindow): # Sets up the main window def resize_window(self): # Function for resizing the window self.resize(self.minimumSizeHint()) def __init__(self, parent=None): super(MainWindow, self).__init__(parent) # Set window Icon self.setWindowTitle(__appname__) iconImage = QImage(iconByteArray) iconPixmap = QPixmap(iconImage) self.setWindowIcon(QIcon(iconPixmap)) # Set up private key format widgets privateKeyFormatLayout = QHBoxLayout() privateKeyFormatLabel = QLabel('Select Key Format: ') self.privateKeyTypeCombobox = QComboBox() self.privateKeyTypeCombobox.addItems(privateKeyFormats) self.privateKeyLengthLabel = QLabel('0') privateKeyFormatLayout.addWidget(privateKeyFormatLabel) privateKeyFormatLayout.addWidget(self.privateKeyTypeCombobox) privateKeyFormatLayout.addWidget(self.privateKeyLengthLabel) # Set up private key text widgets privateKeyLayout = QVBoxLayout() privateKeyButtonsLayout = QHBoxLayout() generatePrivateKeyButton = QPushButton('Generate Key') generatePrivateKeyButton.clicked.connect(self.get_private_key) self.copyPrivateKeyButton = QPushButton('Copy Key') self.copyPrivateKeyButton.setDisabled(True) self.copyPrivateKeyButton.clicked.connect(self.copy_private_key) privateKeyButtonsLayout.addWidget(generatePrivateKeyButton) privateKeyButtonsLayout.addWidget(self.copyPrivateKeyButton) self.privateKeyEdit = GrowingTextEdit() self.privateKeyEdit.setFont(QFont('Courier')) self.privateKeyEdit.textChanged.connect( self.private_key_or_code_changed) privateKeyLayout.addLayout(privateKeyButtonsLayout) privateKeyLayout.addWidget(self.privateKeyEdit) # Set up cypher code widgets codeLayout = QHBoxLayout() codeLabel = QLabel('Select Cypher Code: ') self.codeSelect = QSpinBox() self.codeSelect.setValue(10) self.codeSelect.setMinimum(2) self.codeSelect.setDisabled(True) self.codeSelect.valueChanged.connect(self.private_key_or_code_changed) codeLayout.addWidget(codeLabel) codeLayout.addWidget(self.codeSelect) # Set up cypher text widgets cypherLayout = QVBoxLayout() cypherButtonsLayout = QHBoxLayout() cardButtonsLayout = QHBoxLayout() self.generateCypherButton = QPushButton('Generate Cypher') self.generateCypherButton.clicked.connect(self.get_cypher) self.generateCypherButton.setDisabled(True) self.copyCypherButton = QPushButton('Copy Cypher') self.copyCypherButton.setDisabled(True) self.copyCypherButton.clicked.connect(self.copy_cypher) cypherButtonsLayout.addWidget(self.generateCypherButton) cypherButtonsLayout.addWidget(self.copyCypherButton) self.cypherEdit = GrowingTextEdit() self.cypherEdit.setFont(QFont('Courier')) self.cypherEdit.setReadOnly(True) self.cypherEdit.setVisible(False) self.cypherEdit.textChanged.connect(self.resize_window) self.cypherPreviewLabel = QLabel('-CYPHER PREVIEW-') self.cypherPreviewLabel.setAlignment(Qt.AlignCenter) self.cypherPreviewLabel.setVisible(False) self.cypherPreview = GrowingTextEdit() self.cypherPreview.setFont(QFont('Courier')) self.cypherPreview.setAlignment(Qt.AlignHCenter) self.cypherPreview.setWordWrapMode(QTextOption.NoWrap) self.cypherPreview.setReadOnly(True) self.cypherPreview.setVisible(False) self.cypherCardsPrintButton = QPushButton('Print Cypher Cards') self.cypherCardsPrintButton.setVisible(False) self.cypherCardsPrintButton.clicked.connect(partial(self.cards, True)) self.cypherCardsCopyButton = QPushButton('Copy Cypher Cards') self.cypherCardsCopyButton.setVisible(False) self.cypherCardsCopyButton.clicked.connect(partial(self.cards, False)) cardButtonsLayout.addWidget(self.cypherCardsPrintButton) cardButtonsLayout.addWidget(self.cypherCardsCopyButton) cypherLayout.addLayout(cypherButtonsLayout) cypherLayout.addWidget(self.cypherEdit) cypherLayout.addWidget(self.cypherPreviewLabel) cypherLayout.addWidget(self.cypherPreview) cypherLayout.addLayout(cardButtonsLayout) # Set up donation widgets donationsLayout = QVBoxLayout() separater = QFrame() separater.setFrameShape(QFrame.HLine) self.donationButton = QPushButton('Donate') self.donationButton.setVisible(False) self.donationButton.clicked.connect(self.donate) self.copyEthAddressButton = QPushButton('ETH: Copy Address') self.copyEthAddressButton.clicked.connect( self.copy_eth_donation_address) self.copyEthAddressButton.setVisible(False) self.copyBtcAddressButton = QPushButton('BTC: Copy Address') self.copyBtcAddressButton.clicked.connect( self.copy_btc_donation_address) self.copyBtcAddressButton.setVisible(False) donationsLayout.addWidget(separater) donationsLayout.addWidget(self.donationButton) donationsLayout.addWidget(self.copyEthAddressButton) donationsLayout.addWidget(self.copyBtcAddressButton) # Add all widgets and sub-layouts to the master layout self.master_layout = QVBoxLayout() self.master_layout.addLayout(privateKeyFormatLayout) self.master_layout.addLayout(privateKeyLayout) self.master_layout.addLayout(codeLayout) self.master_layout.addLayout(cypherLayout) self.master_layout.addLayout(donationsLayout) self.master_widget = QWidget() self.master_widget.setLayout(self.master_layout) self.setCentralWidget(self.master_widget) # Start and connect the window resizing thread self.worker = Worker() self.worker.updateWindowSize.connect(self.resize_window) def copy_private_key( self): # Copies the private key text to the system clipboard clip.setText(self.privateKeyEdit.toPlainText()) self.copyPrivateKeyButton.setText('Key Copied') app.processEvents() sleep(2) self.copyPrivateKeyButton.setText('Copy Key') def copy_cypher(self): # Copies the cypher text to the system clipboard clip.setText(self.cypherEdit.toPlainText()) self.copyCypherButton.setText('Cypher Copied') app.processEvents() sleep(2) self.copyCypherButton.setText('Copy Cypher') def copy_eth_donation_address( self): # Copies the ETH donation address to the system clipboard clip.setText(ethDonationAddress) self.copyEthAddressButton.setText('ETH: Address Copied\nThanks!') app.processEvents() sleep(2) self.copyEthAddressButton.setText('ETH: Copy Address') def copy_btc_donation_address( self): # Copies the BTC donation address to the system clipboard clip.setText(btcDonationAddress) self.copyBtcAddressButton.setText('BTC: Address Copied\nThanks!') app.processEvents() sleep(2) self.copyBtcAddressButton.setText('BTC: Copy Address') def get_private_key( self ): # Generates a key of the desired format using two instances of the SystemRandom function privateKey = generate_private_key.start( self.privateKeyTypeCombobox.currentText()) self.privateKeyEdit.setText(privateKey) self.private_key_or_code_changed() self.copyPrivateKeyButton.setDisabled(False) def private_key_or_code_changed( self ): # Changes visibility and ability of some widgets based on user input self.privateKeyLengthLabel.setText( str(len(self.privateKeyEdit.toPlainText()))) self.copyCypherButton.setDisabled(True) self.cypherEdit.setText('') self.cypherPreview.setText('') self.cypherEdit.setVisible(False) self.cypherPreviewLabel.setVisible(False) self.cypherPreview.setVisible(False) if len(self.privateKeyEdit.toPlainText()) <= 2: self.copyPrivateKeyButton.setDisabled(True) self.generateCypherButton.setDisabled(True) self.codeSelect.setDisabled(True) else: self.codeSelect.setMaximum( len(self.privateKeyEdit.toPlainText()) - 1) self.copyPrivateKeyButton.setDisabled(False) self.generateCypherButton.setDisabled(False) self.codeSelect.setDisabled(False) self.cypherCardsPrintButton.setDisabled(True) self.cypherCardsPrintButton.setVisible(False) self.cypherCardsCopyButton.setDisabled(True) self.cypherCardsCopyButton.setVisible(False) self.worker.start() def get_cypher( self ): # Converts the raw key into a cypher based on the codeSelect value if not 1 >= len(self.privateKeyEdit.toPlainText()) >= int( self.privateKeyLengthLabel.text()): self.generateCypherButton.setDisabled(False) cypherRows, cypherSeed = create_cypher.start( self.privateKeyEdit.toPlainText(), self.codeSelect.value()) self.copyCypherButton.setDisabled(False) self.cypherEdit.setVisible(True) self.cypherEdit.setText(cypherSeed) self.cypherPreviewLabel.setVisible(True) self.cypherPreview.setVisible(True) previewText = '' for i in cypherRows: previewText += i + '\n' self.cypherPreview.setText(previewText) self.worker.start() self.cypherCardsPrintButton.setDisabled(False) self.cypherCardsPrintButton.setVisible(True) self.cypherCardsCopyButton.setDisabled(False) self.cypherCardsCopyButton.setVisible(True) self.donationButton.setVisible(True) else: self.generateCypherButton.setDisabled(True) def cards(self, print): # Creates and prints the output.txt file cardList = split_cypher_into_pairs.start(self.cypherEdit.toPlainText()) printString = format_cards.start(cardList) if print: self.cypherCardsPrintButton.setText('Printing') app.processEvents() cards_output.start(printString) self.cypherCardsPrintButton.setText('Print Cypher Cards') else: clip.setText(printString) self.cypherCardsCopyButton.setText('Cards Copied') app.processEvents() sleep(2) self.cypherCardsCopyButton.setText('Copy Cypher Cards') def donate(self): # Adjusts the visibility of the donation buttons if self.donationButton.text() == 'Donate': self.copyEthAddressButton.setVisible(True) self.copyBtcAddressButton.setVisible(True) self.donationButton.setText('Hide') elif self.donationButton.text() == 'Hide': self.copyEthAddressButton.setVisible(False) self.copyBtcAddressButton.setVisible(False) self.donationButton.setText('Donate') self.worker.start() def cleanup(self): # Clears the clipboard of any copied text clip.setText('')
# logo_style logo_style_label = QLabel("Logo style:") layout.addWidget(logo_style_label, 1, 2) logo_style_combo_box = QComboBox() logo_style_combo_box.addItem("Steady") logo_style_combo_box.addItem("Slow breath") logo_style_combo_box.addItem("Middle breath") logo_style_combo_box.addItem("Fast breath") layout.addWidget(logo_style_combo_box, 1, 3) # cpi1 cpi_one_label = QLabel("CPI1 (800):") layout.addWidget(cpi_one_label, 2, 0) cpi_one_spin_box = QSpinBox() cpi_one_spin_box.setRange(50, 6500) cpi_one_spin_box.setValue(800) cpi_one_spin_box.setSingleStep(50) layout.addWidget(cpi_one_spin_box, 2, 1) # cpi2 cpi_two_label = QLabel("CPI2 (1600):") layout.addWidget(cpi_two_label, 2, 2) cpi_two_spin_box = QSpinBox() cpi_two_spin_box.setRange(50, 6500) cpi_two_spin_box.setValue(1600) cpi_two_spin_box.setSingleStep(50) layout.addWidget(cpi_two_spin_box, 2, 3) # polling_rate polling_rate_label = QLabel("Polling rate (1000):") layout.addWidget(polling_rate_label, 3, 0)
class MainWindow(QWidget): def __init__(self, fixtures_folder, parent=None): QWidget.__init__(self, parent) self.current_fixture = None self.fixtures_folder = fixtures_folder self.setWindowTitle("Frangitron DMX program editor") self.text = QPlainTextEdit() font = QFont("Monospace") font.setStyleHint(QFont.TypeWriter) font.setPixelSize(16) self.text.setFont(font) self.text.setStyleSheet( "color: white; background-color: rgb(30, 30, 30)") self.combo_fixture = QComboBox() self.frame_programs = QWidget() self.checkboxes_programs = list() self.layout_programs = QGridLayout(self.frame_programs) self.spinner_offset = QSpinBox() self.spinner_offset.setMinimum(1) self.spinner_offset.setMaximum(512) self.spinner_offset.setValue(1) self.spinner_offset.valueChanged.connect(self.address_changed) self.doc = QPlainTextEdit() self.doc.setReadOnly(True) self.doc.setFont(font) self.status = QLabel() layout = QGridLayout(self) layout.addWidget(self.combo_fixture, 0, 1) layout.addWidget(self.spinner_offset, 0, 2) layout.addWidget(self.frame_programs, 1, 1) layout.addWidget(self.text, 0, 0, 3, 1) layout.addWidget(self.doc, 2, 1, 1, 2) layout.addWidget(self.status, 3, 0, 1, 3) layout.setColumnStretch(0, 60) layout.setColumnStretch(1, 40) self.resize(1280, 800) self.streamer = Streamer(self.fixtures_folder) self.combo_fixture.addItems(sorted(self.streamer.fixtures)) self.combo_fixture.currentIndexChanged.connect(self.fixture_changed) self.timer = QTimer() self.timer.timeout.connect(self.tick) self.timer.start(500.0 / FRAMERATE) self.should_reload = True self.fixture_changed() def selected_programs(self): return [ chk.text() for chk in self.checkboxes_programs if chk.isChecked() ] def update_programs(self): selected_programs = self.selected_programs() for checkbox_program in self.checkboxes_programs: self.layout_programs.removeWidget(checkbox_program) checkbox_program.deleteLater() self.checkboxes_programs = list() for i, program_name in enumerate( sorted(self.current_fixture.programs.keys())): column = i // 4 row = i % 4 new_checkbox = QCheckBox(program_name) new_checkbox.setChecked(program_name in selected_programs) self.layout_programs.addWidget(new_checkbox, row, column) self.checkboxes_programs.append(new_checkbox) def address_changed(self): self.current_fixture.address = self.spinner_offset.value() self.doc.setPlainText(self.current_fixture.doc()) self.update_programs() def fixture_changed(self): self.current_fixture = self.streamer.fixtures[ self.combo_fixture.currentText()] self.address_changed() self.streamer.reset_expressions() with open(self.current_fixture.programs_filepath, 'r') as f_programs: self.text.setPlainText(f_programs.read()) def tick(self): if self.should_reload: self.current_fixture.reload_programs() self.update_programs() self.streamer.reset_state() program = PROGRAM.replace('__fixture__', self.current_fixture.name) program = program.replace('__address__', str(self.current_fixture.address)) program = program.replace( '__programs__', ", ".join([ '"{}"'.format(prog) for prog in self.selected_programs() ])) self.streamer.load(programs_source=program) self.streamer.program_clicked("1") else: state = self.streamer.state if state: self.status.setStyleSheet( "background-color: green; color: white; padding: 5px") self.status.setText(state.context) else: self.status.setStyleSheet( "background-color: red; color: white; padding: 5px") self.status.setText("{} : {}".format(state.context, state.exception)) if self.current_fixture is None: return with open(self.current_fixture.programs_filepath, 'w') as f_programs: f_programs.write(self.text.toPlainText()) self.should_reload = not self.should_reload def closeEvent(self, event): self.timer.stop() self.streamer.load(programs_source="") self.streamer.program_clicked("1") sleep(2.0 / float(FRAMERATE)) self.streamer.stop() event.accept()
def init_UI(self): lay = QGridLayout() lay.addWidget(QLabel('<b>Position</b>'), 0, 0, 1, 4) posx = QDoubleSpinBox() posx.setValue(self.v.x) self.controls['posx'] = posx posy = QDoubleSpinBox() posy.setValue(self.v.y) self.controls['posy'] = posy posz = QDoubleSpinBox() posz.setValue(self.v.z) self.controls['posz'] = posz lay.addWidget(posx, 1, 0) lay.addWidget(posy, 1, 1) lay.addWidget(posz, 1, 2) lay.addWidget(QLabel('<b>Normal</b>'), 2, 0, 1, 4) norx = QDoubleSpinBox() norx.setValue(self.v.nx) self.controls['norx'] = norx nory = QDoubleSpinBox() nory.setValue(self.v.ny) self.controls['nory'] = nory norz = QDoubleSpinBox() norz.setValue(self.v.nz) self.controls['norz'] = norz lay.addWidget(norx, 3, 0) lay.addWidget(nory, 3, 1) lay.addWidget(norz, 3, 2) lay.addWidget(QLabel('<b>Texture Coordinates</b>'), 4, 0, 1, 4) u = QDoubleSpinBox() u.setValue(self.v.u) self.controls['u'] = u v = QDoubleSpinBox() v.setValue(self.v.v) self.controls['v'] = v lay.addWidget(u, 5, 0) lay.addWidget(v, 5, 1) lay.addWidget(QLabel('<b>Color</b>'), 6, 0, 1, 4) red = QSpinBox() red.setMinimum(0) red.setMaximum(255) red.setValue(self.v.color.red) self.controls['red'] = red green = QSpinBox() green.setMinimum(0) green.setMaximum(255) green.setValue(self.v.color.green) self.controls['green'] = green blue = QSpinBox() blue.setMinimum(0) blue.setMaximum(255) blue.setValue(self.v.color.blue) self.controls['blue'] = blue alpha = QSpinBox() alpha.setMinimum(0) alpha.setMaximum(255) alpha.setValue(self.v.color.alpha) self.controls['alpha'] = alpha lay.addWidget(red, 7, 0) lay.addWidget(green, 7, 1) lay.addWidget(blue, 7, 2) lay.addWidget(alpha, 7, 3) grp = QGroupBox('Vertex') grp.setLayout(lay) btns = QVBoxLayout() save = QPushButton('Save') save.clicked.connect(self.save) cancel = QPushButton('Cancel') cancel.clicked.connect(self.close) btns.addStretch() btns.addWidget(save) btns.addWidget(cancel) mainlay = QHBoxLayout() mainlay.addWidget(grp) mainlay.addLayout(btns) self.setLayout(mainlay) self.setGeometry(340, 340, 300, 250) self.setWindowTitle('MSH Suite - Vertex Editor') self.show()
class PushupForm(QDialog): ''' classdocs ''' pushupCreated = Signal(Pushup_Model) def __init__(self, athlete): ''' Constructor ''' QDialog.__init__(self) self.setWindowTitle("Pushup form") self.athlete = athlete self.pushupForm = QFormLayout() self.createGUI() def createGUI(self): self.series = QSpinBox() self.series.setMinimum(1) self.repetitions = QSpinBox() self.repetitions.setMaximum(512) self.avgHeartRateToggle = QCheckBox() self.avgHeartRateToggle.toggled.connect(self._toggleHeartRateSpinBox) self.avgHeartRate = QSpinBox() self.avgHeartRate.setMinimum(30) self.avgHeartRate.setMaximum(250) self.avgHeartRate.setValue(120) self.avgHeartRate.setDisabled(True) self.dateSelector_widget = QCalendarWidget() self.dateSelector_widget.setMaximumDate(QDate.currentDate()) self.addButton = QPushButton("Add pushup") self.addButton.setMaximumWidth(90) self.addButton.clicked.connect(self._createPushup) self.cancelButton = QPushButton("Cancel") self.cancelButton.setMaximumWidth(90) self.cancelButton.clicked.connect(self.reject) self.pushupForm.addRow("Series", self.series) self.pushupForm.addRow("Repetitions", self.repetitions) self.pushupForm.addRow("Store average heart rate ? ", self.avgHeartRateToggle) self.pushupForm.addRow("Average Heart Rate", self.avgHeartRate) self.pushupForm.addRow("Exercise Date", self.dateSelector_widget) btnsLayout = QVBoxLayout() btnsLayout.addWidget(self.addButton) btnsLayout.addWidget(self.cancelButton) btnsLayout.setAlignment(Qt.AlignRight) layoutWrapper = QVBoxLayout() layoutWrapper.addLayout(self.pushupForm) layoutWrapper.addLayout(btnsLayout) self.setLayout(layoutWrapper) def _createPushup(self): exerciseDate = self.dateSelector_widget.selectedDate() exerciseDate = self.qDate_to_date(exerciseDate) if self.avgHeartRateToggle.isChecked(): heartRate = self.avgHeartRate.value() else: heartRate = None pushup = Pushup_Model(self.athlete._name, exerciseDate, heartRate, self.series.value(), self.repetitions.value()) self.pushupCreated.emit(pushup) self.accept() def _toggleHeartRateSpinBox(self): if self.avgHeartRateToggle.isChecked(): self.avgHeartRate.setDisabled(False) else: self.avgHeartRate.setDisabled(True) def qDate_to_date(self, qDate): return date(qDate.year(), qDate.month(),qDate.day())
class Panel(QWidget): def __init__(self, state, config, parent): super().__init__(parent) self.state = state self.config = config self.form = parent self.createWidgets() self.layoutWidgets() self.createConnections() def createWidgets(self): settings = QSettings() creator = settings.value(Gopt.Key.Creator, self.state.user) self.creatorLineEdit = QLineEdit() self.creatorLineEdit.setText(creator) self.form.tooltips.append((self.creatorLineEdit, """\ <p><b>Creator</b></p> <p>The indexer's name.</p>""")) initials = "" if creator: initials = Lib.initials(creator) initials = settings.value(Gopt.Key.Initials, initials) self.initialsLineEdit = QLineEdit() self.initialsLineEdit.setMaximumWidth( self.initialsLineEdit.fontMetrics().width("W") * 4) self.initialsLineEdit.setText(initials) self.form.tooltips.append((self.initialsLineEdit, """\ <p><b>Initials</b></p> <p>The indexer's initials.</p>""")) self.languageGroupBox = QGroupBox("&Language") defaultLanguage = LanguageKind( settings.value(Gopt.Key.Language, Gopt.Default.Language)) thisLanguage = self.config.get(Gconf.Key.Language, defaultLanguage) self.defaultLanguageComboBox = QComboBox() self.form.tooltips.append((self.defaultLanguageComboBox, """\ <p><b>Language, Default</b></p> <p>The default setting for the <b>Language, For This Index</b> combobox for new indexes.</p>""")) self.thisLanguageComboBox = QComboBox() self.form.tooltips.append((self.thisLanguageComboBox, """\ <p><b>Language, For This Index</b></p> <p>The language to use for spellchecking and suggestions for this index.</p>""")) self.populateLanguageComboBox(self.defaultLanguageComboBox, defaultLanguage) self.populateLanguageComboBox(self.thisLanguageComboBox, thisLanguage) self.limitsGroupBox = QGroupBox("Publisher's Limits for this Index") self.highestPageSpinBox = QSpinBox() self.highestPageSpinBox.setAlignment(Qt.AlignRight) self.highestPageSpinBox.setRange(10, 26000) self.highestPageSpinBox.setValue( self.config.get(Gconf.Key.HighestPageNumber, Gconf.Default.HighestPageNumber)) self.form.tooltips.append((self.highestPageSpinBox, """\ <p><b>Highest Page Number</b></p> <p>Any entries which contain a page number greater than this one will be shown in the Filtered view if you use the “Too High Page Number” filter.</p>""")) self.largestPageRangeSpinBox = QSpinBox() self.largestPageRangeSpinBox.setAlignment(Qt.AlignRight) self.largestPageRangeSpinBox.setRange(2, 1000) self.largestPageRangeSpinBox.setValue( self.config.get(Gconf.Key.LargestPageRange, Gconf.Default.LargestPageRange)) self.form.tooltips.append((self.largestPageRangeSpinBox, """\ <p><b>Largest Page Range Span</b></p> <p>Any entries which contain a page range that spans more pages than this will be shown in the Filtered view if you use the “Too Large Page Range” filter.</p>""")) self.mostPagesSpinBox = QSpinBox() self.mostPagesSpinBox.setAlignment(Qt.AlignRight) self.mostPagesSpinBox.setRange(2, 100) self.mostPagesSpinBox.setValue( self.config.get(Gconf.Key.MostPages, Gconf.Default.MostPages)) self.form.tooltips.append((self.mostPagesSpinBox, """\ <p><b>Most Pages per Entry</b></p> <p>Any entries which contain more pages and page ranges this will be shown in the Filtered view if you use the “Too Many Pages” filter.</p>""")) def layoutWidgets(self): layout = QVBoxLayout() form = QFormLayout() form.addRow("C&reator", self.creatorLineEdit) form.addRow("&Initials", self.initialsLineEdit) layout.addLayout(form) form = QFormLayout() form.addRow("For This Index", self.thisLanguageComboBox) form.addRow("Default", self.defaultLanguageComboBox) self.languageGroupBox.setLayout(form) layout.addWidget(self.languageGroupBox) form = QFormLayout() form.addRow("&Highest Page Number", self.highestPageSpinBox) form.addRow("Largest &Page Range Span", self.largestPageRangeSpinBox) form.addRow("&Most Pages per Entry", self.mostPagesSpinBox) self.limitsGroupBox.setLayout(form) hbox = QHBoxLayout() hbox.addWidget(self.limitsGroupBox) hbox.addStretch() layout.addLayout(hbox) layout.addStretch() self.setLayout(layout) def createConnections(self): self.creatorLineEdit.textChanged.connect(self.updateInitials) self.defaultLanguageComboBox.currentIndexChanged.connect( self.setDefaultLanguage) self.thisLanguageComboBox.currentIndexChanged.connect( self.setThisLanguage) def updateInitials(self): text = self.creatorLineEdit.text() if text: initials = Lib.initials(text) if initials: self.initialsLineEdit.setText(initials) def populateLanguageComboBox(self, combobox, theLanguage): index = -1 for i, language in enumerate(LanguageKind): if language is theLanguage: index = i name = language.value combobox.addItem(QIcon(":/{}.svg".format(name.replace(" ", "_"))), name, language) combobox.setCurrentIndex(index) def setDefaultLanguage(self, index): language = self.defaultLanguageComboBox.itemData(index) settings = QSettings() settings.setValue(Gopt.Key.Language, language.value) def setThisLanguage(self, index): language = self.defaultLanguageComboBox.itemData(index) self.state.model.setConfig(Gconf.Key.Language, language) self.state.entryPanel.spellHighlighter.rehighlight() self.state.window.updateLanguageIndicator()
class DoFPParametersDialog(QDialog): AFTER_CONSTRUCTION_ALLFRAC = 1 AFTER_CONSTRUCTION_RANGESTRING = 2 AFTER_CONSTRUCTION_TOTOP = 3 def __init__(self, rangeConstructor=1.0, boardCombo=None, title="Enter first range arguments", parent=None): super(DoFPParametersDialog, self).__init__(parent) self._after_method = 2 self._board_combo = boardCombo label_constructor = QLabel("Constructor argument <b>(initFrac)</b>") self._spinbox_constructor = QSpinBox() self._spinbox_constructor.setMaximum(9999) self._spinbox_constructor.setValue(rangeConstructor) label_after_construction = QLabel("After construction method") self._radiogroup_methods = HorizontalRadioGroup(["setRangeString()", "setAllFracs()", "setToTop()"]) self._radiogroup_methods.radio_checked.connect(self._updateLayout) self._radiogroup_methods._radios[0].setChecked(True) # dunno why it's not checked by default label_method_args = QLabel("Method arguments") self._widget_method_args = SetRangeStringCompound() button_ok = QPushButton("Ok") button_ok.clicked.connect(self.accept) button_cancel = QPushButton("Cancel") button_cancel.clicked.connect(self.reject) layout = QGridLayout() row = 0; col = 0; layout.addWidget(label_constructor, row, col) col += 1 layout.addWidget(self._spinbox_constructor, row, col) row += 1; col = 0; layout.addWidget(label_after_construction, row, col) col += 1 layout.addWidget(self._radiogroup_methods) row += 1; col = 0; layout.addWidget(label_method_args, row, col) col += 1 self._update_pos = (row, col) layout.addWidget(self._widget_method_args, row, col) row += 1; col = 0 layout.addWidget(button_ok, row, col) col += 1 layout.addWidget(button_cancel, row, col) self.setLayout(layout) self.setWindowTitle(title) def _updateLayout(self, radioString): self._widget_method_args.setParent(None) self.layout().removeWidget(self._widget_method_args) if radioString == "setRangeString()": self._after_method = self.AFTER_CONSTRUCTION_RANGESTRING self._widget_method_args = SetRangeStringCompound() elif radioString == "setAllFracs()": self._after_method = self.AFTER_CONSTRUCTION_ALLFRAC self._widget_method_args = SetAllFracsSpinBox() elif radioString == "setToTop()": self._after_method = self.AFTER_CONSTRUCTION_TOTOP self._widget_method_args = SetToTopCompound(self._board_combo) self.layout().update() self.layout().addWidget(self._widget_method_args, self._update_pos[0], self._update_pos[1]) def getRange(self): # construct a range object and return it r = Range(self._spinbox_constructor.value()) if self._after_method == self.AFTER_CONSTRUCTION_ALLFRAC: r.setAllFracs(self._widget_method_args.value()) elif self._after_method == self.AFTER_CONSTRUCTION_RANGESTRING: r.setRangeString(self._widget_method_args.lineedit_string.text(), self._widget_method_args.spinbox_value.value()) elif self._after_method == self.AFTER_CONSTRUCTION_TOTOP: r.setToTop(self._widget_method_args.spinbox_fraction.value(), self._board_combo.boards()[self._widget_method_args.combobox_board.currentIndex()]) return r
class Form(QDialog): def __init__(self, state, parent=None): super().__init__(parent) Lib.prepareModalDialog(self) self.state = state self.setWindowTitle("Renumber Pages — {}".format( QApplication.applicationName())) self.createWidgets() self.layoutWidgets() self.createConnections() self.romanStartSpinBox.setFocus() self.updateUi() settings = QSettings() self.updateToolTips( bool( int( settings.value(Gopt.Key.ShowDialogToolTips, Gopt.Default.ShowDialogToolTips)))) def createWidgets(self): self.romanStartLabel = QLabel("&Roman from") self.romanStartSpinBox = Widgets.RomanSpinBox.SpinBox() self.tooltips.append((self.romanStartSpinBox, """\ <p><b>Roman from</b></p> <p>The first roman page number to change.</p>""")) self.romanStartLabel.setBuddy(self.romanStartSpinBox) self.romanEndLabel = QLabel("to") self.romanEndSpinBox = Widgets.RomanSpinBox.SpinBox() self.romanEndSpinBox.setValue(200) self.tooltips.append((self.romanEndSpinBox, """\ <p><b>Roman, to</b></p> <p>The last roman page number to change.</p>""")) self.romanChangeLabel = QLabel("change") self.romanChangeSpinBox = Widgets.ChangeSpinBox.SpinBox() self.romanChangeSpinBox.setRange(-100, 100) self.romanChangeSpinBox.setValue(0) self.romanChangeSpinBox.setMinimumWidth( self.romanChangeSpinBox.fontMetrics().width("W(no change)W")) self.tooltips.append((self.romanChangeSpinBox, """\ <p><b>Roman, change</b></p> <p>The amount to change the roman page numbers in the Roman from–to range.</p>""")) self.decimalStartLabel = QLabel("&Decimal from") self.decimalStartSpinBox = QSpinBox() self.decimalStartSpinBox.setAlignment(Qt.AlignRight) self.decimalStartLabel.setBuddy(self.decimalStartSpinBox) self.decimalStartSpinBox.setRange(1, 10000) self.tooltips.append((self.decimalStartSpinBox, """\ <p><b>Decimal from</b></p> <p>The first decimal page number to change.</p>""")) self.decimalEndLabel = QLabel("to") self.decimalEndSpinBox = QSpinBox() self.decimalEndSpinBox.setAlignment(Qt.AlignRight) self.decimalEndSpinBox.setRange(1, 10000) self.decimalEndSpinBox.setValue(2000) self.tooltips.append((self.decimalEndSpinBox, """\ <p><b>Decimal, to</b></p> <p>The last decimal page number to change.</p>""")) self.decimalChangeLabel = QLabel("change") self.decimalChangeSpinBox = Widgets.ChangeSpinBox.SpinBox() self.decimalChangeSpinBox.setRange(-100, 100) self.decimalChangeSpinBox.setValue(0) self.tooltips.append((self.decimalChangeSpinBox, """\ <p><b>Decimal, change</b></p> <p>The amount to change the decimal page numbers in the Decimal from–to range.</p>""")) self.buttonBox = QDialogButtonBox() self.renumberButton = QPushButton(QIcon(":/renumberpages.svg"), "Re&number") self.tooltips.append((self.renumberButton, """\ <p><b>Renumber</b></p> <p>Renumber roman and decimal page numbers within the given ranges by the specified amounts of change throughout the entire index.</p>""")) self.buttonBox.addButton(self.renumberButton, QDialogButtonBox.ActionRole) self.closeButton = QPushButton(QIcon(":/dialog-close.svg"), "&Cancel") self.tooltips.append((self.closeButton, """<p><b>Cancel</b></p> <p>Close the dialog without making any changes to the index.</p>""")) self.buttonBox.addButton(self.closeButton, QDialogButtonBox.RejectRole) self.helpButton = QPushButton(QIcon(":/help.svg"), "Help") self.tooltips.append( (self.helpButton, "Help on the Renumber Pages dialog")) self.buttonBox.addButton(self.helpButton, QDialogButtonBox.HelpRole) def layoutWidgets(self): grid = QGridLayout() grid.addWidget(self.romanStartLabel, 0, 0) grid.addWidget(self.romanStartSpinBox, 0, 1) grid.addWidget(self.romanEndLabel, 0, 2) grid.addWidget(self.romanEndSpinBox, 0, 3) grid.addWidget(self.romanChangeLabel, 0, 4) grid.addWidget(self.romanChangeSpinBox, 0, 5) grid.addWidget(self.decimalStartLabel, 1, 0) grid.addWidget(self.decimalStartSpinBox, 1, 1) grid.addWidget(self.decimalEndLabel, 1, 2) grid.addWidget(self.decimalEndSpinBox, 1, 3) grid.addWidget(self.decimalChangeLabel, 1, 4) grid.addWidget(self.decimalChangeSpinBox, 1, 5) hbox = QHBoxLayout() hbox.addLayout(grid) hbox.addStretch() layout = QVBoxLayout() layout.addLayout(hbox) layout.addStretch() layout.addWidget(self.buttonBox) self.setLayout(layout) def createConnections(self): self.buttonBox.rejected.connect(self.reject) self.renumberButton.clicked.connect(self.renumber) for spinbox in (self.romanStartSpinBox, self.romanEndSpinBox, self.romanChangeSpinBox, self.decimalStartSpinBox, self.decimalEndSpinBox, self.decimalChangeSpinBox): spinbox.valueChanged.connect(self.updateUi) self.helpButton.clicked.connect(self.help) def updateUi(self): self._synchronize(self.romanStartSpinBox, self.romanEndSpinBox) self._synchronize(self.decimalStartSpinBox, self.decimalEndSpinBox) changeRoman = ( (self.romanStartSpinBox.value() != self.romanEndSpinBox.value()) and self.romanChangeSpinBox.value() != 0) changeDecimal = ((self.decimalStartSpinBox.value() != self.decimalEndSpinBox.value()) and self.decimalChangeSpinBox.value() != 0) self.renumberButton.setEnabled(changeRoman or changeDecimal) self._setPrefix(self.romanChangeSpinBox) self._setPrefix(self.decimalChangeSpinBox) def _synchronize(self, startSpinBox, endSpinBox): value = startSpinBox.value() if endSpinBox.value() < value: endSpinBox.setValue(value) def _setPrefix(self, spinbox): spinbox.setPrefix("+" if spinbox.value() > 0 else "") def help(self): self.state.help("xix_ref_dlg_renumpages.html") def renumber(self): # No need to restore focus widget options = RenumberOptions(self.romanStartSpinBox.value(), self.romanEndSpinBox.value(), self.romanChangeSpinBox.value(), self.decimalStartSpinBox.value(), self.decimalEndSpinBox.value(), self.decimalChangeSpinBox.value()) with Lib.DisableUI(self): self.state.model.renumber(options, self.state.window.reportProgress) message = "Renumber pages" if self.state.model.canUndo: self.state.model.can_undo.emit(True, message) if self.state.model.canRedo: self.state.model.can_redo.emit(True, message) self.state.updateUi() say("Renumbered pages", SAY_TIMEOUT) self.accept()
class CalculateSalaryWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.__parent = parent self.setWindowTitle("Calculate Salary") t = datetime.now() self.month = QComboBox() self.month.addItems([ "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" ]) self.month.setCurrentIndex(t.month - 1) self.year = QSpinBox() self.year.setRange(1900, 3000) self.year.setValue(t.year) self.name = SearchBox(self) self.name.setPlaceholderText("Enter Name") self.name.returnPressed.connect(self.setIDList) self.nameList = [] self.nameList = DatabaseManager.db.getEmployeeNameList() self.name.setList(self.nameList) self.name.setCurrentIndex(-1) self.id = QComboBox() self.id.currentIndexChanged.connect( lambda: self.loadInfo(self.id.currentText())) self.designation = QLineEdit() self.designation.setReadOnly(True) self.originalPay = QLineEdit() self.originalPay.setReadOnly(True) self.originalPayGrade = QLineEdit() self.originalPayGrade.setReadOnly(True) self.DOJ = QLineEdit() self.DOJ.setReadOnly(True) self.pan = QLineEdit() self.pan.setReadOnly(True) self.presentPay = QLineEdit() self.presentPay.setReadOnly(True) self.da_percent = ValueBox() self.hra_percent = ValueBox() self.ta_percent = ValueBox() self.it_percent = ValueBox() self.pt_percent = ValueBox() self.name.editTextChanged.connect(self.clearInfo) self.bttnCalculate = QPushButton("Calculate") self.bttnCalculate.clicked.connect(self.calculate) self.bttnCancel = QPushButton("Back") self.bttnCancel.clicked.connect(self.goBack) self.bttnCalculate.setObjectName("OkButton") self.bttnCancel.setObjectName("CancelButton") self.setupUI() def calculate(self): if "" in (self.id.currentText(), self.name.text(), self.designation.text(), self.originalPay.text(), self.originalPayGrade.text(), self.DOJ.text(), self.pan.text(), self.da_percent.text(), self.hra_percent.text(), self.ta_percent.text(), self.it_percent.text(), self.pt_percent.text()): msg = QMessageBox(QMessageBox.Information, "Error", "Please enter all the information!", parent=self) msg.exec_() else: if self.__parent is not None: self.__parent.gotoPage( "Result", (self.id.currentText(), self.name.text(), self.designation.text(), self.originalPay.text(), self.originalPayGrade.text(), self.DOJ.text(), self.pan.text(), self.da_percent.text(), self.hra_percent.text(), self.ta_percent.text(), self.it_percent.text(), self.pt_percent.text(), self.month.currentText(), self.year.text())) def clearInfo(self): self.id.setCurrentIndex(-1) self.designation.clear() self.originalPay.clear() self.originalPayGrade.clear() self.DOJ.clear() self.pan.clear() self.da_percent.clear() self.hra_percent.clear() self.ta_percent.clear() self.it_percent.clear() self.pt_percent.clear() def loadInfo(self, id): print "id =", id, "...", len(id) if id != '': info = DatabaseManager.db.getEmployeeInfo(id) _, _, designation, originalPay, originalPayGrade, doj, pan = info self.designation.setText(str(designation)) self.originalPay.setText(str(originalPay)) self.originalPayGrade.setText(str(originalPayGrade)) self.DOJ.setText("%02d/%02d/%4d" % (doj.day, doj.month, doj.year)) self.pan.setText(str(pan)) _, da, hra, ta, it, pt = DatabaseManager.db.getDesignationInfo( designation) self.da_percent.setText(str(da)) self.hra_percent.setText(str(hra)) self.ta_percent.setText(str(ta)) self.it_percent.setText(str(it)) self.pt_percent.setText(str(pt)) def setIDList(self, name): self.id.clear() self.id.addItems(DatabaseManager.db.getIdListForName(name)) def goBack(self): if self.__parent is not None: self.__parent.goBack() def setupUI(self): layout = QVBoxLayout() layout.setContentsMargins(20, 20, 20, 10) datelayout = QHBoxLayout() datelayout.addWidget(QLabel("Salary for month of ")) datelayout.addWidget(self.month) datelayout.addWidget(self.year) datelayout.addStretch() layout.addLayout(datelayout) form = QFormLayout() form.setSpacing(10) form.addRow(QLabel("Name"), self.name) form.addRow(QLabel("ID No."), self.id) form.addRow(QLabel("Designation"), self.designation) form.addRow(QLabel("Original Pay"), self.originalPay) form.addRow(QLabel("Original Pay Grade"), self.originalPayGrade) form.addRow(QLabel("Date of joining"), self.DOJ) form.addRow(QLabel("Pan No."), self.pan) infoGroup = QGroupBox("Basic Info") infoGroup.setLayout(form) layout.addWidget(infoGroup) leftForm = QFormLayout() leftForm.addRow(QLabel("Dearness Allowance"), self.da_percent) leftForm.addRow(QLabel("Housing Rent Allowance"), self.hra_percent) leftForm.addRow(QLabel("Transport Allowance"), self.ta_percent) leftGroup = QGroupBox("Allowances") leftGroup.setLayout(leftForm) rightForm = QFormLayout() rightForm.addRow(QLabel("Income Tax"), self.it_percent) rightForm.addRow(QLabel("Profession Tax"), self.pt_percent) rightGroup = QGroupBox("Deductions") rightGroup.setLayout(rightForm) table = QHBoxLayout() table.addWidget(leftGroup) table.addWidget(rightGroup) layout.addLayout(table) layout.addStretch() bttnLayout = QHBoxLayout() bttnLayout.addStretch() bttnLayout.addWidget(self.bttnCancel) bttnLayout.addWidget(self.bttnCalculate) layout.addLayout(bttnLayout) self.setLayout(layout)
class PushupForm(QDialog): ''' classdocs ''' pushupCreated = Signal(Pushup_Model) def __init__(self, athlete): ''' Constructor ''' QDialog.__init__(self) self.setWindowTitle("Pushup form") self.athlete = athlete self.pushupForm = QFormLayout() self.createGUI() def createGUI(self): self.series = QSpinBox() self.series.setMinimum(1) self.repetitions = QSpinBox() self.repetitions.setMaximum(512) self.avgHeartRateToggle = QCheckBox() self.avgHeartRateToggle.toggled.connect(self._toggleHeartRateSpinBox) self.avgHeartRate = QSpinBox() self.avgHeartRate.setMinimum(30) self.avgHeartRate.setMaximum(250) self.avgHeartRate.setValue(120) self.avgHeartRate.setDisabled(True) self.dateSelector_widget = QCalendarWidget() self.dateSelector_widget.setMaximumDate(QDate.currentDate()) self.addButton = QPushButton("Add pushup") self.addButton.setMaximumWidth(90) self.addButton.clicked.connect(self._createPushup) self.cancelButton = QPushButton("Cancel") self.cancelButton.setMaximumWidth(90) self.cancelButton.clicked.connect(self.reject) self.pushupForm.addRow("Series", self.series) self.pushupForm.addRow("Repetitions", self.repetitions) self.pushupForm.addRow("Store average heart rate ? ", self.avgHeartRateToggle) self.pushupForm.addRow("Average Heart Rate", self.avgHeartRate) self.pushupForm.addRow("Exercise Date", self.dateSelector_widget) btnsLayout = QVBoxLayout() btnsLayout.addWidget(self.addButton) btnsLayout.addWidget(self.cancelButton) btnsLayout.setAlignment(Qt.AlignRight) layoutWrapper = QVBoxLayout() layoutWrapper.addLayout(self.pushupForm) layoutWrapper.addLayout(btnsLayout) self.setLayout(layoutWrapper) def _createPushup(self): exerciseDate = self.dateSelector_widget.selectedDate() exerciseDate = self.qDate_to_date(exerciseDate) if self.avgHeartRateToggle.isChecked(): heartRate = self.avgHeartRate.value() else: heartRate = None pushup = Pushup_Model(self.athlete._name, exerciseDate, heartRate, self.series.value(), self.repetitions.value()) self.pushupCreated.emit(pushup) self.accept() def _toggleHeartRateSpinBox(self): if self.avgHeartRateToggle.isChecked(): self.avgHeartRate.setDisabled(False) else: self.avgHeartRate.setDisabled(True) def qDate_to_date(self, qDate): return date(qDate.year(), qDate.month(), qDate.day())
class OptionsContainer(QWidget): def __init__(self,main_window): QWidget.__init__(self) self.main_window = main_window self.layout = QGridLayout() self.setLayout(self.layout) self.lr = numpy.zeros(2) self.fps = QSpinBox() self.fps.setValue(25) self.fps.setMinimum(1) self.fps.setMaximum(1000) self.layout.addWidget(QLabel("FPS:"),10,10) self.layout.addWidget(self.fps,10,11) self.capture_area_group = QButtonGroup() self.capture_area_fs = QRadioButton("Full Screen") self.connect(self.capture_area_fs, SIGNAL("clicked()"),self.capture_area_change) self.capture_area_fs.setChecked(True) self.capture_area_sa = QRadioButton("Selected Area") self.connect(self.capture_area_sa, SIGNAL("clicked()"),self.capture_area_change) self.capture_area_group.addButton(self.capture_area_fs) self.capture_area_group.addButton(self.capture_area_sa) self.capture_area_group.setExclusive(True) self.layout.addWidget(self.capture_area_fs,12,10) self.layout.addWidget(self.capture_area_sa,12,11) self.sa_group = QGroupBox() self.sa_grid = QGridLayout() self.sa_group.setLayout(self.sa_grid) self.sa_ul_bt = QPushButton("Select Upper Left") self.connect(self.sa_ul_bt, SIGNAL("clicked()"), self.select_ul) self.sa_lr_bt = QPushButton("Select Lower Right") self.connect(self.sa_lr_bt, SIGNAL("clicked()"), self.select_lr) self.sa_x = QSpinBox() self.sa_y = QSpinBox() self.sa_w = QSpinBox() self.sa_h = QSpinBox() for sb in [self.sa_h,self.sa_w,self.sa_x,self.sa_y]: sb.setMaximum(999999) sb.setMinimum(0) self.sa_grid.addWidget(self.sa_ul_bt,14,10,1,1) self.sa_grid.addWidget(self.sa_lr_bt,15,10,1,1) self.sa_grid.addWidget(QLabel("x"),14,11,1,1) self.sa_grid.addWidget(self.sa_x,14,12,1,1) self.sa_grid.addWidget(QLabel("y"),15,11,1,1) self.sa_grid.addWidget(self.sa_y,15,12,1,1) self.sa_grid.addWidget(QLabel("w"),16,11,1,1) self.sa_grid.addWidget(self.sa_w,16,12,1,1) self.sa_grid.addWidget(QLabel("h"),17,11,1,1) self.sa_grid.addWidget(self.sa_h,17,12,1,1) self.sa_show_bt = QPushButton("Show Area") self.sa_show_bt.setCheckable(True) self.connect(self.sa_show_bt, SIGNAL("clicked()"), self.show_selected_area) self.sa_grid.addWidget(self.sa_show_bt,18,10,1,10) self.sa_group.hide() self.layout.addWidget(self.sa_group,14,10,1,10) self.capture_delay = QSpinBox() self.capture_delay.setMinimum(0) self.capture_delay.setMaximum(10000) self.layout.addWidget(QLabel("Capture Delay"),18,10,1,1) self.layout.addWidget(self.capture_delay,18,11,1,1) self.capture_bt = QPushButton("Capture") self.stop_capture_bt = QPushButton("Stop") self.stop_capture_bt.hide() self.layout.addWidget(self.capture_bt,20,10,1,10) self.layout.addWidget(self.stop_capture_bt,30,10,1,10) self.ffmpeg_flags = QLineEdit() self.ffmpeg_flags.setText("-qscale 0 -vcodec mpeg4") self.layout.addWidget(QLabel("FFMPEG Flags:"),40,10) self.layout.addWidget(self.ffmpeg_flags,50,10,1,10) self.encode_bt = QPushButton("Encode Video") self.layout.addWidget(self.encode_bt,60,10,1,10) self.open_dir_bt = QPushButton("Open Directory") self.layout.addWidget(self.open_dir_bt,80,10,1,10) self.connect(self.open_dir_bt, SIGNAL("clicked()"),self.open_cwd) self.selected_area = SelectedArea() def show_selected_area(self): x = self.sa_x.value() y = self.sa_y.value() w = self.sa_w.value() h = self.sa_h.value() self.selected_area.setGeometry(x,y,w,h) self.selected_area.activateWindow() self.selected_area.raise_() if(self.sa_show_bt.isChecked()): self.selected_area.show() else:self.selected_area.hide() def select_ul(self): print "select_ul" self.clicked = False self.tw = TransWindow() self.tw.mouse_press = False self.tw.show() self.connect(self.tw, SIGNAL("mouse_press()"),self.set_ul) def select_lr(self): print "select_lr" self.clicked = False self.tw = TransWindow() self.tw.mouse_press = False self.tw.show() self.connect(self.tw, SIGNAL("mouse_press()"),self.set_lr) def set_ul(self): self.sa_x.setValue( self.tw.pos[0]) self.sa_y.setValue( self.tw.pos[1]) self.sa_w.setValue( self.lr[0] - self.sa_x.value()) self.sa_h.setValue( self.lr[1] - self.sa_y.value()) self.show_selected_area() def set_lr(self): self.lr = numpy.array([self.tw.pos[0],self.tw.pos[1]]) self.sa_w.setValue( self.tw.pos[0] - self.sa_x.value()) self.sa_h.setValue( self.tw.pos[1] - self.sa_y.value()) self.show_selected_area() def capture_area_change(self): print "capture_area_change" if(self.capture_area_fs.isChecked()): self.sa_group.hide() else: self.sa_group.show() self.adjustSize() self.main_window.adjustSize() def open_cwd(self): #will need to detect os and change accordingly os.system("open {}".format(os.getcwd()))
class UVViewer(QDialog): def __init__(self, model, w, h, parent=None): super(UVViewer, self).__init__(parent) self.w = w self.h = h self.mdl = model self.white_b = QBrush(Qt.white) self.black_b = QBrush(Qt.black) self.pen_width = 2 self.initUI() def initUI(self): mainlay = QVBoxLayout() scn = QGraphicsScene(0, 0, self.w, self.h) self.view = QGraphicsView() self.view.setScene(scn) self.view.setSceneRect(QRectF(0, 0, self.w, self.h)) self.view.setMaximumWidth(self.w) self.view.setMaximumHeight(self.h) mainlay.addWidget(self.view) btns = QHBoxLayout() btns.addStretch() self.pen_w = QSpinBox() self.pen_w.setValue(self.pen_width) redraw = QPushButton('Redraw') redraw.clicked.connect(self.draw_uvs) save = QPushButton('Save') save.clicked.connect(self.save) close = QPushButton('Close') close.clicked.connect(self.close) btns.addWidget(QLabel('Stroke Width')) btns.addWidget(self.pen_w) btns.addWidget(redraw) btns.addWidget(save) btns.addWidget(close) mainlay.addLayout(btns) self.draw_uvs() self.setLayout(mainlay) self.setGeometry(340, 340, 512, 560) self.setWindowTitle('MSH Suite UV Viewer') self.show() def draw_uvs(self): self.img = QPixmap(QSize(self.w, self.h)) pen = QPen() pen.setWidth(int(self.pen_w.text())) pen.setBrush(QBrush(Qt.white)) pen.setColor(QColor('white')) painter = QPainter() painter.begin(self.img) painter.setPen(pen) coords = self.get_coords() for face in coords: for n in xrange(len(face) - 1): print face[n][0], face[n][1], face[n + 1][0], face[n + 1][1] painter.drawLine(face[n][0], face[n][1], face[n + 1][0], face[n + 1][1]) painter.end() self.view.scene().addPixmap(self.img) def get_coords(self): coords = [] for seg in self.mdl.segments: if seg.classname == 'SegmentGeometry': print 'doing stuff' vcoll = seg.vertices for face in seg.faces: face_coords = [] for v in face.SIindices(): face_coords.append((vcoll[v].u * self.w, (1 - vcoll[v].v) * self.h)) face_coords.append((vcoll[face.vertices[0]].u * self.w, (1 - vcoll[face.vertices[0]].v) * self.h)) coords.append(face_coords) #print face_coords return coords def save(self): filename, _ = QFileDialog.getSaveFileName(self, 'Save UV Mesh', os.getcwd(), 'PNG Files (*.png)') if not filename: return self.img.save(filename, 'PNG') self.close()
class _PenepmaConfigurePanelWidget(_ConfigurePanelWidget): def _initUI(self): # Widgets self._brw_pendbase = DirBrowseWidget() self._brw_exe = FileBrowseWidget() if os.name == 'nt': self._brw_exe.setNameFilter('Application files (*.exe)') else: self._brw_exe.setNameFilter('Application files (*)') self._spn_dumpp = QSpinBox() self._spn_dumpp.setMinimum(30) self._spn_dumpp.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) # Layouts layout = _ConfigurePanelWidget._initUI(self) layout.addRow("Path to pendbase directory", self._brw_pendbase) layout.addRow('Path to PENEPMA executable', self._brw_exe) layout.addRow('Interval between dump (s)', self._spn_dumpp) # Signals self._brw_pendbase.pathChanged.connect(self._onPathChanged) self._brw_exe.pathChanged.connect(self._onPathChanged) return layout def _onPathChanged(self, path): if not path: return if not self._brw_pendbase.baseDir(): self._brw_pendbase.setBaseDir(path) if not self._brw_exe.baseDir(): self._brw_exe.setBaseDir(path) def hasAcceptableInput(self): if not self._brw_pendbase.path(): return False if not self._brw_exe.path(): return False if not os.access(self._brw_exe.path(), os.X_OK): return False return True def setSettings(self, settings): if 'penepma' in settings: path = getattr(settings.penepma, 'pendbase', None) try: self._brw_pendbase.setPath(path) except ValueError: pass path = getattr(settings.penepma, 'exe', None) try: self._brw_exe.setPath(path) except ValueError: pass try: dumpp = int(getattr(settings.penepma, 'dumpp', 30)) self._spn_dumpp.setValue(dumpp) except (TypeError, ValueError): pass def updateSettings(self, settings): section = _ConfigurePanelWidget.updateSettings(self, settings) section.pendbase = self._brw_pendbase.path() section.exe = self._brw_exe.path() section.dumpp = int(self._spn_dumpp.value()) return section
class Panel(QWidget): def __init__(self, state, config, parent): super().__init__(parent) self.state = state self.config = config self.form = parent self.createWidgets() self.layoutWidgets() self.createConnections() def createWidgets(self): self.formatPanel = Widgets.FormatPanel.Panel(self.state, self, editableFontSize=True) formatActions = self.formatPanel.formatActions self.titleLabel = QLabel("&Index Title") self.titleTextEdit = Widgets.LineEdit.HtmlLineEdit( self.state, formatActions=formatActions) self.titleLabel.setBuddy(self.titleTextEdit) self.titleTextEdit.setHtml(self.config.get(Gconf.Key.Title)) self.form.tooltips.append((self.titleTextEdit, """\ <p><b>Index Title</b></p> <p>The index's title. Leave blank if the title is to be added directly in the output file.</p>""")) self.noteLabel = QLabel("Index &Note") self.noteTextEdit = Widgets.LineEdit.MultilineHtmlEdit( self.state, maxLines=8, formatActions=formatActions) self.noteLabel.setBuddy(self.noteTextEdit) self.noteTextEdit.setLineWrapMode(QTextEdit.FixedColumnWidth) self.noteTextEdit.setLineWrapColumnOrWidth(60) self.noteTextEdit.setWordWrapMode(QTextOption.WordWrap) self.noteTextEdit.setHtml(self.config.get(Gconf.Key.Note)) self.form.tooltips.append((self.noteTextEdit, """\ <p><b>Index Note</b></p> <p>The index's note. Leave blank if no note is required or if the note is to be added directly in the output file.</p>""")) self.sectionsGroupBox = QGroupBox("Sections") self.blankBeforeLabel = QLabel("&Blank Lines Before") self.blankBeforeSpinBox = QSpinBox() self.blankBeforeSpinBox.setAlignment(Qt.AlignRight) self.blankBeforeLabel.setBuddy(self.blankBeforeSpinBox) self.blankBeforeSpinBox.setRange(0, 3) self.blankBeforeSpinBox.setValue( self.config.get(Gconf.Key.SectionPreLines)) self.form.tooltips.append((self.blankBeforeSpinBox, """\ <p><b>Blank Lines Before</b></p> <p>How many blank lines to output before a section. (A section is a distinct part of the index, e.g., the ‘A’s.)</p>""")) self.blankAfterLabel = QLabel("Blank &Lines After") self.blankAfterSpinBox = QSpinBox() self.blankAfterSpinBox.setAlignment(Qt.AlignRight) self.blankAfterLabel.setBuddy(self.blankAfterSpinBox) self.blankAfterSpinBox.setRange(0, 3) self.blankAfterSpinBox.setValue( self.config.get(Gconf.Key.SectionPostLines)) self.form.tooltips.append((self.blankAfterSpinBox, """\ <p><b>Blank Lines After</b></p> <p>How many blank lines to output before after section's title. (A section is a distinct part of the index, e.g., the ‘A’s.)</p>""")) self.sectionTitlesCheckBox = QCheckBox("&Output Titles") self.sectionTitlesCheckBox.setChecked( self.config.get(Gconf.Key.SectionTitles)) self.form.tooltips.append((self.sectionTitlesCheckBox, """\ <p><b>Output Titles</b></p> <p>If checked, section titles are output before each section, e.g., ‘A’, before the As, ‘B’, before the Bs, and so on.</p>""")) self.sectionSpecialTitleLabel = QLabel("Special Section &Title") self.sectionSpecialTitleTextEdit = Widgets.LineEdit.HtmlLineEdit( self.state, formatActions=formatActions) self.sectionSpecialTitleLabel.setBuddy( self.sectionSpecialTitleTextEdit) self.sectionSpecialTitleTextEdit.setHtml( self.config.get(Gconf.Key.SectionSpecialTitle)) self.form.tooltips.append((self.sectionSpecialTitleTextEdit, """\ <p><b>Special Section Title</b></p> <p>If there are entries which precede the ‘A’ section, then this section title will be used for them.</p> <p>Note that even if this title isn't used, its font name and size will be used for all the other section titles.</p>""")) size = self.font().pointSize() + (1 if WIN else 2) family = self.config.get(Gconf.Key.StdFont) size = self.config.get(Gconf.Key.StdFontSize, size) Lib.createFontBoxesFor(self, "Std", family, size, tooltips=self.form.tooltips, which="Std.") self.onStdFontChange(False) family = self.config.get(Gconf.Key.AltFont) size = self.config.get(Gconf.Key.AltFontSize, size) Lib.createFontBoxesFor(self, "Alt", family, size, tooltips=self.form.tooltips, which="Alt.") self.onAltFontChange(False) family = self.config.get(Gconf.Key.MonoFont) size = self.config.get(Gconf.Key.MonoFontSize, size) Lib.createFontBoxesFor(self, "Mono", family, size, mono=True, tooltips=self.form.tooltips, which="Mono.") self.onMonoFontChange(False) self.monoFontAsStrikeoutCheckbox = QCheckBox( "Output Mono. &Font as Strikeout") self.form.tooltips.append((self.monoFontAsStrikeoutCheckbox, """\ <p><b>Output Mono. Font as Strikeout</b></p> <p>If checked, any text in the index that is styled as mono. font family will be output using the std. font family—but with <s>strikeout</s>.</p>""")) self.monoFontAsStrikeoutCheckbox.setChecked( self.config.get(Gconf.Key.MonoFontAsStrikeout)) self.styleLabel = QLabel("St&yle") self.styleComboBox = QComboBox() self.styleLabel.setBuddy(self.styleComboBox) oldStyle = self.config.get(Gconf.Key.Style) index = -1 for i, style in enumerate(StyleKind): self.styleComboBox.addItem(style.text, style.value) if style is oldStyle: index = i self.styleComboBox.setCurrentIndex(index) self.form.tooltips.append((self.styleComboBox, """\ <p><b>Style</b></p> <p>The style of index to output.</p>""")) self.termPagesSepLabel = QLabel("T&erm-Pages Separator") self.termPagesSepTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit( self.state, 3, formatActions=formatActions) self.termPagesSepLabel.setBuddy(self.termPagesSepTextEdit) self.termPagesSepTextEdit.setHtml( self.config.get(Gconf.Key.TermPagesSeparator)) self.form.tooltips.append((self.termPagesSepTextEdit, """\ <p><b>Term-Pages Separator</b></p> <p>The separator text to use between the end of an entry's term and its pages.</p>{}""".format(BLANK_SPACE_HTML))) self.runInSepLabel = QLabel("&Run-in Separator") self.runInSepTextEdit = Widgets.LineEdit.SpacesHtmlLineEdit( self.state, 3, formatActions=formatActions) self.runInSepLabel.setBuddy(self.runInSepTextEdit) self.runInSepTextEdit.setHtml(self.config.get( Gconf.Key.RunInSeparator)) self.form.tooltips.append((self.runInSepTextEdit, """\ <p><b>Run-in Separator</b></p> <p>The separator text to use between run-in entries (for run-in style index output).</p>{}""".format(BLANK_SPACE_HTML))) self.formatPanel.state.editors = [ self.titleTextEdit, self.noteTextEdit, self.sectionSpecialTitleTextEdit, self.termPagesSepTextEdit, self.runInSepTextEdit ] def layoutWidgets(self): form = QFormLayout() hbox = QHBoxLayout() hbox.addStretch() hbox.addWidget(self.formatPanel) form.addRow(hbox) form.addRow(self.titleLabel, self.titleTextEdit) form.addRow(self.noteLabel, self.noteTextEdit) vbox = QVBoxLayout() hbox = QHBoxLayout() hbox.addWidget(self.blankBeforeLabel) hbox.addWidget(self.blankBeforeSpinBox) hbox.addWidget(self.blankAfterLabel) hbox.addWidget(self.blankAfterSpinBox) hbox.addStretch() vbox.addLayout(hbox) hbox = QHBoxLayout() hbox.addWidget(self.sectionTitlesCheckBox) hbox.addStretch() hbox.addWidget(self.sectionSpecialTitleLabel) hbox.addWidget(self.sectionSpecialTitleTextEdit) vbox.addLayout(hbox) self.sectionsGroupBox.setLayout(vbox) form.addRow(self.sectionsGroupBox) hbox = QHBoxLayout() hbox.addWidget(self.stdFontComboBox, 1) hbox.addWidget(self.stdFontSizeSpinBox) hbox.addStretch() label = QLabel("&Std. Font") label.setBuddy(self.stdFontComboBox) form.addRow(label, hbox) hbox = QHBoxLayout() hbox.addWidget(self.altFontComboBox, 1) hbox.addWidget(self.altFontSizeSpinBox) hbox.addStretch() label = QLabel("&Alt. Font") label.setBuddy(self.altFontComboBox) form.addRow(label, hbox) hbox = QHBoxLayout() hbox.addWidget(self.monoFontComboBox, 1) hbox.addWidget(self.monoFontSizeSpinBox) hbox.addStretch() label = QLabel("&Mono. Font") label.setBuddy(self.monoFontComboBox) form.addRow(label, hbox) grid = QGridLayout() grid.addWidget(self.monoFontAsStrikeoutCheckbox, 0, 0, 1, 2) grid.addWidget(self.termPagesSepLabel, 0, 2) grid.addWidget(self.termPagesSepTextEdit, 0, 3) grid.addWidget(self.styleLabel, 1, 0) grid.addWidget(self.styleComboBox, 1, 1) grid.addWidget(self.runInSepLabel, 1, 2) grid.addWidget(self.runInSepTextEdit, 1, 3) form.addRow(grid) self.setLayout(form) def createConnections(self): self.stdFontComboBox.currentFontChanged.connect(self.onStdFontChange) self.stdFontSizeSpinBox.valueChanged[int].connect(self.onStdFontChange) self.altFontComboBox.currentFontChanged.connect(self.onAltFontChange) self.altFontSizeSpinBox.valueChanged[int].connect(self.onAltFontChange) self.monoFontComboBox.currentFontChanged.connect(self.onMonoFontChange) self.monoFontSizeSpinBox.valueChanged[int].connect( self.onMonoFontChange) def onStdFontChange(self, propagate=True): font = QFont(self.stdFontComboBox.currentFont()) font.setPointSize(self.stdFontSizeSpinBox.value()) if propagate and bool(self.state.model): self.state.model.setConfig(Gconf.Key.StdFont, font.family()) self.state.model.setConfig(Gconf.Key.StdFontSize, font.pointSize()) def onAltFontChange(self, propagate=True): font = QFont(self.altFontComboBox.currentFont()) font.setPointSize(self.altFontSizeSpinBox.value()) if propagate and bool(self.state.model): self.state.model.setConfig(Gconf.Key.AltFont, font.family()) self.state.model.setConfig(Gconf.Key.AltFontSize, font.pointSize()) def onMonoFontChange(self, propagate=True): font = QFont(self.monoFontComboBox.currentFont()) font.setPointSize(self.monoFontSizeSpinBox.value()) if propagate and bool(self.state.model): self.state.model.setConfig(Gconf.Key.MonoFont, font.family()) self.state.model.setConfig(Gconf.Key.MonoFontSize, font.pointSize())
class Panel(QWidget): def __init__(self, state, config, parent): super().__init__(parent) self.state = state self.config = config self.form = parent self.createWidgets() self.layoutWidgets() self.createConnections() def createWidgets(self): settings = QSettings() self.sortRulesGroupBox = QGroupBox("Calculate &Sort As Rules") defaultSortAsRules = settings.value(Gconf.Key.SortAsRules, Gopt.Default.SortAsRules) self.thisSortAsRules = self.config.get(Gopt.Key.SortAsRules, defaultSortAsRules) self.defaultSortAsRulesBox = QComboBox() self.form.tooltips.append((self.defaultSortAsRulesBox, """\ <p><b>Calculate Sort As Rules, Default</b></p> <p>The default setting for the <b>Calculate Sort As Rules, For This Index</b> combobox for new indexes.</p>""")) self.thisSortAsRulesBox = QComboBox() self.form.tooltips.append((self.thisSortAsRulesBox, """\ <p><b>Calculate Sort As Rules, For This Index</b></p> <p>The rules to use for calculating each entry's sort as text for this index.</p> <p>If the rules are changed, when the dialog is closed, the new rules will be applied to every entry in the index.</p>""")) self.populateSortAsRulesBox(self.defaultSortAsRulesBox, defaultSortAsRules) self.populateSortAsRulesBox(self.thisSortAsRulesBox, self.thisSortAsRules) self.pageRangeRulesBox = QGroupBox("&Page Range Rules") defaultPageRangeRules = settings.value(Gconf.Key.PageRangeRules, Gopt.Default.PageRangeRules) self.thisPageRangeRules = self.config.get(Gopt.Key.PageRangeRules, defaultPageRangeRules) self.defaultPageRangeRulesBox = QComboBox() self.form.tooltips.append((self.defaultPageRangeRulesBox, """\ <p><b>Page Range Rules, Default</b></p> <p>The default setting for the <b>Page Range Rules, For This Index</b> combobox for new indexes.</p>""")) self.thisPageRangeRulesBox = QComboBox() self.form.tooltips.append((self.thisPageRangeRulesBox, """\ <p><b>Page Range Rules, For This Index</b></p> <p>The rules to use for handling page ranges, e.g., whether in full such as 120–124, or somehow compressed, e.g., 120–4, for this index.</p> <p>If the rules are changed, when the dialog is closed, the new rules will be applied to every entry in the index.</p>""")) self.populatePageRangeRulesBox(self.defaultPageRangeRulesBox, defaultPageRangeRules) self.populatePageRangeRulesBox(self.thisPageRangeRulesBox, self.thisPageRangeRules) self.padDigitsGroupBox = QGroupBox("Pad &Digits") defaultPadDigits = int( settings.value(Gconf.Key.PadDigits, Gopt.Default.PadDigits)) self.thisPadDigits = int( self.config.get(Gopt.Key.PadDigits, defaultPadDigits)) self.thisPadDigitsLabel = QLabel("For This Index") self.thisPadDigitsSpinBox = QSpinBox() self.thisPadDigitsSpinBox.setAlignment(Qt.AlignRight) self.thisPadDigitsSpinBox.setRange(0, 12) self.thisPadDigitsSpinBox.setValue(self.thisPadDigits) self.form.tooltips.append((self.thisPadDigitsSpinBox, """\ <p><b>Pad Digits, For This Index</b></p> <p>Sort as texts are compared textually, so if a term contains a number (or text which is converted to a number), the number must be padded by leading zeros to ensure correct ordering. This is the number of digits to pad for, for this index. For example, if set to 4, the numbers 1, 23, and 400 would be set to 0001, 0023, and 0400, in the sort as text.</p>""")) self.defaultPadDigitsLabel = QLabel("Default") self.defaultPadDigitsSpinBox = QSpinBox() self.defaultPadDigitsSpinBox.setAlignment(Qt.AlignRight) self.defaultPadDigitsSpinBox.setRange(0, 12) self.defaultPadDigitsSpinBox.setValue(defaultPadDigits) self.form.tooltips.append((self.defaultPadDigitsSpinBox, """\ <p><b>Pad Digits, Default</b></p> <p>The default setting for the <b>Pad Digits, For This Index</b> spinbox for new indexes.</p>""")) self.ignoreSubFirstsGroupBox = QGroupBox( "&Ignore Subentry Function Words") defaultIgnoreSubFirsts = bool( int( settings.value(Gconf.Key.IgnoreSubFirsts, Gopt.Default.IgnoreSubFirsts))) thisIgnoreSubFirsts = bool( int( self.config.get(Gopt.Key.IgnoreSubFirsts, defaultIgnoreSubFirsts))) self.thisIgnoreSubFirstsCheckBox = QCheckBox("For This Index") self.thisIgnoreSubFirstsCheckBox.setChecked(thisIgnoreSubFirsts) self.form.tooltips.append((self.thisIgnoreSubFirstsCheckBox, """\ <p><b>Ignore Subentry Function Words, For This Index</b></p> <p>This setting applies to this index.</p> <p>If checked, words listed in the <b>Index→Ignore Subentry Function Words</b> list are ignored for sorting purposes when the first word of a subentry, i.e., ignored when the first word of an entry's sort as text.</p> <p>This should normally be checked for Chicago Manual of Style Sort As Rules, and unchecked for NISO Rules.</p>""")) self.defaultIgnoreSubFirstsCheckBox = QCheckBox("Default") self.defaultIgnoreSubFirstsCheckBox.setChecked(defaultIgnoreSubFirsts) self.form.tooltips.append((self.defaultIgnoreSubFirstsCheckBox, """\ <p><b>Ignore Subentry Function Words, Default</b></p> <p>The default setting for the <b>Ignore Subentry Function Words, For This Index</b> checkbox for new indexes</p>""")) self.suggestSpelledGroupBox = QGroupBox( "&Suggest Spelled Out Numbers when Appropriate") defaultSuggestSpelled = bool( int( settings.value(Gconf.Key.SuggestSpelled, Gopt.Default.SuggestSpelled))) thisSuggestSpelled = bool( int(self.config.get(Gopt.Key.SuggestSpelled, defaultSuggestSpelled))) self.thisSuggestSpelledCheckBox = QCheckBox("For This Index") self.thisSuggestSpelledCheckBox.setChecked(thisSuggestSpelled) self.form.tooltips.append((self.thisSuggestSpelledCheckBox, """\ <p><b>Suggest Spelled Out Numbers when Appropriate, For This Index</b></p> <p>When checked (and providing the Sort As rules in force are not NISO rules), when adding or editing a term when the <b>Automatically Calculate Sort As</b> checkbox is checked, and when the term contains a number, the choice of sort as texts will include the number spelled out.</p>""")) self.defaultSuggestSpelledCheckBox = QCheckBox("Default") self.defaultSuggestSpelledCheckBox.setChecked(defaultSuggestSpelled) self.form.tooltips.append((self.defaultSuggestSpelledCheckBox, """\ <p><b>Suggest Spelled Out Numbers when Appropriate, Default</b></p> <p>The default setting for the <b>Suggest Spelled Out Numbers when Appropriate, For This Index</b> checkbox for new indexes.</p>""")) def layoutWidgets(self): layout = QVBoxLayout() form = QFormLayout() form.addRow("For This Index", self.thisSortAsRulesBox) form.addRow("Default", self.defaultSortAsRulesBox) self.sortRulesGroupBox.setLayout(form) layout.addWidget(self.sortRulesGroupBox) form = QFormLayout() form.addRow("For This Index", self.thisPageRangeRulesBox) form.addRow("Default", self.defaultPageRangeRulesBox) self.pageRangeRulesBox.setLayout(form) layout.addWidget(self.pageRangeRulesBox) hbox = QHBoxLayout() hbox.addWidget(self.thisPadDigitsLabel) hbox.addWidget(self.thisPadDigitsSpinBox) hbox.addStretch(1) hbox.addWidget(self.defaultPadDigitsLabel) hbox.addWidget(self.defaultPadDigitsSpinBox) hbox.addStretch(3) self.padDigitsGroupBox.setLayout(hbox) layout.addWidget(self.padDigitsGroupBox) hbox = QHBoxLayout() hbox.addWidget(self.thisIgnoreSubFirstsCheckBox) hbox.addWidget(self.defaultIgnoreSubFirstsCheckBox) hbox.addStretch() self.ignoreSubFirstsGroupBox.setLayout(hbox) layout.addWidget(self.ignoreSubFirstsGroupBox) hbox = QHBoxLayout() hbox.addWidget(self.thisSuggestSpelledCheckBox) hbox.addWidget(self.defaultSuggestSpelledCheckBox) hbox.addStretch() self.suggestSpelledGroupBox.setLayout(hbox) layout.addWidget(self.suggestSpelledGroupBox) layout.addStretch() self.setLayout(layout) def createConnections(self): self.defaultSortAsRulesBox.currentIndexChanged.connect( self.setDefaultSortAsRules) self.defaultPageRangeRulesBox.currentIndexChanged.connect( self.setDefaultPageRangeRules) self.defaultPadDigitsSpinBox.valueChanged.connect( self.setDefaultPadDigits) self.defaultIgnoreSubFirstsCheckBox.toggled.connect( self.setDefaultIgnoreSubFirsts) self.defaultSuggestSpelledCheckBox.toggled.connect( self.setDefaultSuggestSpelled) def populateSortAsRulesBox(self, combobox, rules): index = -1 for i, name in enumerate(SortAs.RulesForName): displayName = SortAs.RulesForName[name].name combobox.addItem(displayName, name) if name == rules: index = i combobox.setCurrentIndex(index) def setDefaultSortAsRules(self, index): index = self.defaultSortAsRulesBox.currentIndex() name = self.defaultSortAsRulesBox.itemData(index) settings = QSettings() settings.setValue(Gopt.Key.SortAsRules, name) def populatePageRangeRulesBox(self, combobox, rules): index = -1 for i, name in enumerate(Pages.RulesForName): displayName = Pages.RulesForName[name].name combobox.addItem(displayName, name) if name == rules: index = i combobox.setCurrentIndex(index) def setDefaultPageRangeRules(self, index): index = self.defaultPageRangeRulesBox.currentIndex() name = self.defaultPageRangeRulesBox.itemData(index) settings = QSettings() settings.setValue(Gopt.Key.PageRangeRules, name) def setDefaultPadDigits(self): value = self.defaultPadDigitsSpinBox.value() settings = QSettings() settings.setValue(Gopt.Key.PadDigits, value) def setDefaultIgnoreSubFirsts(self): value = int(self.defaultIgnoreSubFirstsCheckBox.isChecked()) settings = QSettings() settings.setValue(Gopt.Key.IgnoreSubFirsts, value) def setDefaultSuggestSpelled(self): value = int(self.defaultSuggestSpelledCheckBox.isChecked()) settings = QSettings() settings.setValue(Gopt.Key.SuggestSpelled, value)
class RunnerDialog(QDialog): options_added = Signal(Options) options_running = Signal(Options) options_simulated = Signal(Options) options_error = Signal(Options, Exception) results_saved = Signal(Results, str) results_error = Signal(Results, Exception) def __init__(self, parent=None): QDialog.__init__(self, parent) self.setWindowTitle('Runner') self.setMinimumWidth(750) # Runner self._runner = None self._running_timer = QTimer() self._running_timer.setInterval(500) # Widgets self._dlg_progress = QProgressDialog() self._dlg_progress.setRange(0, 100) self._dlg_progress.setModal(True) self._dlg_progress.hide() lbl_outputdir = QLabel("Output directory") self._txt_outputdir = DirBrowseWidget() max_workers = cpu_count() #@UndefinedVariable lbl_workers = QLabel('Number of workers') self._spn_workers = QSpinBox() self._spn_workers.setRange(1, max_workers) self._spn_workers.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) lbl_max_workers = QLabel('(max: %i)' % max_workers) self._chk_overwrite = QCheckBox("Overwrite existing results in output directory") self._chk_overwrite.setChecked(True) self._lbl_available = QLabel('Available') self._lst_available = QListView() self._lst_available.setModel(_AvailableOptionsListModel()) self._lst_available.setSelectionMode(QListView.SelectionMode.MultiSelection) tlb_available = QToolBar() spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) tlb_available.addWidget(spacer) act_open = tlb_available.addAction(getIcon("document-open"), "Open") act_open.setShortcut(QKeySequence.Open) tlb_available.addSeparator() act_remove = tlb_available.addAction(getIcon("list-remove"), "Remove") act_clear = tlb_available.addAction(getIcon("edit-clear"), "Clear") self._btn_addtoqueue = QPushButton(getIcon("go-next"), "") self._btn_addtoqueue.setToolTip("Add to queue") self._btn_addtoqueue.setEnabled(False) self._btn_addalltoqueue = QPushButton(getIcon("go-last"), "") self._btn_addalltoqueue.setToolTip("Add all to queue") self._btn_addalltoqueue.setEnabled(False) self._lbl_options = QLabel('Queued/Running/Completed') self._tbl_options = QTableView() self._tbl_options.setModel(_StateOptionsTableModel()) self._tbl_options.setItemDelegate(_StateOptionsItemDelegate()) self._tbl_options.setSelectionMode(QListView.SelectionMode.NoSelection) self._tbl_options.setColumnWidth(1, 60) self._tbl_options.setColumnWidth(2, 80) header = self._tbl_options.horizontalHeader() header.setResizeMode(0, QHeaderView.Interactive) header.setResizeMode(1, QHeaderView.Fixed) header.setResizeMode(2, QHeaderView.Fixed) header.setResizeMode(3, QHeaderView.Stretch) self._btn_start = QPushButton(getIcon("media-playback-start"), "Start") self._btn_cancel = QPushButton("Cancel") self._btn_cancel.setEnabled(False) self._btn_close = QPushButton("Close") self._btn_import = QPushButton("Import") self._btn_import.setEnabled(False) # Layouts layout = QVBoxLayout() sublayout = QGridLayout() sublayout.addWidget(lbl_outputdir, 0, 0) sublayout.addWidget(self._txt_outputdir, 0, 1) sublayout.addWidget(lbl_workers, 1, 0) subsublayout = QHBoxLayout() subsublayout.addWidget(self._spn_workers) subsublayout.addWidget(lbl_max_workers) sublayout.addLayout(subsublayout, 1, 1) layout.addLayout(sublayout) sublayout.addWidget(self._chk_overwrite, 2, 0, 1, 3) sublayout = QGridLayout() sublayout.setColumnStretch(0, 1) sublayout.setColumnStretch(2, 3) sublayout.addWidget(self._lbl_available, 0, 0) sublayout.addWidget(self._lst_available, 1, 0) sublayout.addWidget(tlb_available, 2, 0) subsublayout = QVBoxLayout() subsublayout.addStretch() subsublayout.addWidget(self._btn_addtoqueue) subsublayout.addWidget(self._btn_addalltoqueue) subsublayout.addStretch() sublayout.addLayout(subsublayout, 1, 1) sublayout.addWidget(self._lbl_options, 0, 2) sublayout.addWidget(self._tbl_options, 1, 2) layout.addLayout(sublayout) sublayout = QHBoxLayout() sublayout.addStretch() sublayout.addWidget(self._btn_import) sublayout.addWidget(self._btn_start) sublayout.addWidget(self._btn_cancel) sublayout.addWidget(self._btn_close) layout.addLayout(sublayout) self.setLayout(layout) # Signal self._running_timer.timeout.connect(self._onRunningTimer) act_open.triggered.connect(self._onOpen) act_remove.triggered.connect(self._onRemove) act_clear.triggered.connect(self._onClear) self._btn_addtoqueue.released.connect(self._onAddToQueue) self._btn_addalltoqueue.released.connect(self._onAddAllToQueue) self._btn_start.released.connect(self._onStart) self._btn_cancel.released.connect(self._onCancel) self._btn_close.released.connect(self._onClose) self._btn_import.released.connect(self._onImport) self.options_added.connect(self._onOptionsAdded) self.options_running.connect(self._onOptionsRunning) self.options_simulated.connect(self._onOptionsSimulated) self.options_error.connect(self._onOptionsError) self.results_error.connect(self._onResultsError) # Defaults settings = get_settings() section = settings.add_section('gui') if hasattr(section, 'outputdir'): self._txt_outputdir.setPath(section.outputdir) if hasattr(section, 'maxworkers'): self._spn_workers.setValue(int(section.maxworkers)) if hasattr(section, 'overwrite'): state = True if section.overwrite.lower() == 'true' else False self._chk_overwrite.setChecked(state) def _onDialogProgressProgress(self, progress, status): self._dlg_progress.setValue(progress * 100) self._dlg_progress.setLabelText(status) def _onDialogProgressCancel(self): self._dlg_progress.hide() if self._options_reader_thread is None: return self._options_reader_thread.cancel() self._options_reader_thread.quit() self._options_reader_thread.wait() def _onDialogProgressException(self, ex): self._dlg_progress.hide() self._options_reader_thread.quit() self._options_reader_thread.wait() messagebox.exception(self, ex) def _onRunningTimer(self): self._tbl_options.model().reset() def _onOpen(self): settings = get_settings() curdir = getattr(settings.gui, 'opendir', os.getcwd()) filepath, namefilter = \ QFileDialog.getOpenFileName(self, "Open", curdir, 'Options [*.xml] (*.xml)') if not filepath or not namefilter: return settings.gui.opendir = os.path.dirname(filepath) if not filepath.endswith('.xml'): filepath += '.xml' self._options_reader_thread = _OptionsReaderWrapperThread(filepath) self._dlg_progress.canceled.connect(self._onDialogProgressCancel) self._options_reader_thread.resultReady.connect(self._onOpened) self._options_reader_thread.progressUpdated.connect(self._onDialogProgressProgress) self._options_reader_thread.exceptionRaised.connect(self._onDialogProgressException) self._options_reader_thread.start() self._dlg_progress.reset() self._dlg_progress.show() def _onOpened(self, options): self._dlg_progress.hide() self._options_reader_thread.quit() self._options_reader_thread.wait() self._options_reader_thread = None try: self._lst_available.model().addOptions(options) except Exception as ex: messagebox.exception(self, ex) def _onRemove(self): selection = self._lst_available.selectionModel().selection().indexes() if len(selection) == 0: QMessageBox.warning(self, "Queue", "Select an options") return model = self._lst_available.model() for row in sorted(map(methodcaller('row'), selection), reverse=True): model.popOptions(row) def _onClear(self): self._lst_available.model().clearOptions() def _onAddToQueue(self): selection = self._lst_available.selectionModel().selection().indexes() if len(selection) == 0: QMessageBox.warning(self, "Queue", "Select an options") return model = self._lst_available.model() for row in sorted(map(methodcaller('row'), selection), reverse=True): options = model.options(row) try: self._runner.put(options) except Exception as ex: messagebox.exception(self, ex) return def _onAddAllToQueue(self): model = self._lst_available.model() for row in reversed(range(0, model.rowCount())): options = model.options(row) try: self._runner.put(options) except Exception as ex: messagebox.exception(self, ex) return def _onStart(self): outputdir = self._txt_outputdir.path() if not outputdir: QMessageBox.critical(self, 'Start', 'Missing output directory') return max_workers = self._spn_workers.value() overwrite = self._chk_overwrite.isChecked() self.start(outputdir, overwrite, max_workers) def _onCancel(self): self.cancel() def _onClose(self): if self._runner is not None: self._runner.close() self._running_timer.stop() self.close() def _onImport(self): list_options = self._lst_available.model().listOptions() if not list_options: return # Select options dialog = _OptionsSelector(list_options) if not dialog.exec_(): return options = dialog.options() # Start importer outputdir = self._runner.outputdir max_workers = self._runner.max_workers importer = LocalImporter(outputdir, max_workers) importer.start() importer.put(options) self._dlg_progress.show() try: while importer.is_alive(): if self._dlg_progress.wasCanceled(): importer.cancel() break self._dlg_progress.setValue(importer.progress * 100) finally: self._dlg_progress.hide() def _onOptionsAdded(self, options): logging.debug('runner: optionsAdded') self._tbl_options.model().addOptions(options) def _onOptionsRunning(self, options): logging.debug('runner: optionsRunning') self._tbl_options.model().resetOptions(options) def _onOptionsSimulated(self, options): logging.debug('runner: optionsSimulated') self._tbl_options.model().resetOptions(options) def _onOptionsError(self, options, ex): logging.debug('runner: optionsError') self._tbl_options.model().resetOptions(options) def _onResultsError(self, results, ex): logging.debug('runner: resultsError') self._tbl_options.model().reset() def closeEvent(self, event): if self.is_running(): message = 'Runner is running. Do you want to continue?' answer = QMessageBox.question(self, 'Runner', message, QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.No: event.ignore() return self.cancel() self._dlg_progress.close() settings = get_settings() section = settings.add_section('gui') path = self._txt_outputdir.path() if path: section.outputdir = path section.maxworkers = str(self._spn_workers.value()) section.overwrite = str(self._chk_overwrite.isChecked()) settings.write() event.accept() def addAvailableOptions(self, options): self._lst_available.model().addOptions(options) def removeAvailableOptions(self, options): self._lst_available.model().removeOptions(options) def clearAvailableOptions(self): self._lbl_available.model().clearOptions() def start(self, outputdir, overwrite, max_workers): self._runner = LocalRunner(outputdir=outputdir, overwrite=overwrite, max_workers=max_workers) self._tbl_options.setModel(_StateOptionsTableModel(self._runner)) self._spn_workers.setEnabled(False) self._txt_outputdir.setEnabled(False) self._chk_overwrite.setEnabled(False) self._btn_addtoqueue.setEnabled(True) self._btn_addalltoqueue.setEnabled(True) self._btn_start.setEnabled(False) self._btn_cancel.setEnabled(True) self._btn_close.setEnabled(False) self._btn_import.setEnabled(True) self._runner.options_added.connect(self.options_added.emit) self._runner.options_running.connect(self.options_running.emit) self._runner.options_simulated.connect(self.options_simulated.emit) self._runner.options_error.connect(self.options_error.emit) self._runner.results_saved.connect(self.results_saved.emit) self._runner.results_error.connect(self.results_error.emit) self._running_timer.start() self._runner.start() def cancel(self): if self._runner is None: return self._runner.cancel() self._running_timer.stop() self._runner.options_added.disconnect(self.options_added.emit) self._runner.options_running.disconnect(self.options_running.emit) self._runner.options_simulated.disconnect(self.options_simulated.emit) self._runner.options_error.disconnect(self.options_error.emit) self._runner.results_saved.disconnect(self.results_saved.emit) self._runner.results_error.disconnect(self.results_error.emit) self._runner = None self._spn_workers.setEnabled(True) self._txt_outputdir.setEnabled(True) self._chk_overwrite.setEnabled(True) self._btn_addtoqueue.setEnabled(False) self._btn_addalltoqueue.setEnabled(False) self._btn_start.setEnabled(True) self._btn_cancel.setEnabled(False) self._btn_close.setEnabled(True) self._btn_import.setEnabled(False) def is_running(self): return self._runner is not None and self._runner.is_alive()
class AnyIMU_window(QMainWindow): def __init__(self, parent=None): super(AnyIMU_window, self).__init__(parent) self.setWindowTitle('AnyIMU') self.resize(450, 700) os.system('cls') self.dcm = DCM() self.accDataCurr = None self.gyrDataCurr = None self.magDataCurr = None self.barDataCurr = None self.serialThread = None self.skipDataCount = 5 # The plot widget self.accPlotWidget = SensorDisplay(name='Accelerometer') self.gyrPlotWidget = SensorDisplay(name='Gyroscope') self.magPlotWidget = SensorDisplay(name='Magnetometer') self.barPlotWidget = SensorDisplay(name='Barometer') self.accPlotWidget.addPlot(fillLevelIn=0, brushIn=(200,0,0,100), penIn=(255,0,0), dataType='int', dataName='X') self.accPlotWidget.addPlot(fillLevelIn=0, brushIn=(0,200,0,100), penIn=(0,255,0), dataType='int', dataName='Y') self.accPlotWidget.addPlot(fillLevelIn=0, brushIn=(0,0,200,100), penIn=(0,0,255), dataType='int', dataName='Z') self.gyrPlotWidget.addPlot(fillLevelIn=0, brushIn=(200,0,0,100), penIn=(255,0,0), dataType='int', dataName='X') self.gyrPlotWidget.addPlot(fillLevelIn=0, brushIn=(0,200,0,100), penIn=(0,255,0), dataType='int', dataName='Y') self.gyrPlotWidget.addPlot(fillLevelIn=0, brushIn=(0,0,200,100), penIn=(0,0,255), dataType='int', dataName='Z') self.magPlotWidget.addPlot(fillLevelIn=0, brushIn=(200,0,0,100), penIn=(255,0,0), dataType='int', dataName='X') self.magPlotWidget.addPlot(fillLevelIn=0, brushIn=(0,200,0,100), penIn=(0,255,0), dataType='int', dataName='Y') self.magPlotWidget.addPlot(fillLevelIn=0, brushIn=(0,0,200,100), penIn=(0,0,255), dataType='int', dataName='Z') self.barPlotWidget.addPlot(fillLevelIn=0, brushIn=(200,0,0,100), penIn=(255,0,0), dataType='float', dataName='TEMP') self.barPlotWidget.addPlot(fillLevelIn=0, brushIn=(0,200,0,100), penIn=(0,255,0), dataType='float', dataName='PRS') self.barPlotWidget.addPlot(fillLevelIn=0, brushIn=(0,0,200,100), penIn=(0,0,255), dataType='float', dataName='ALT') # the main layout and widgets self.mainWidget = QWidget() self.setCentralWidget(self.mainWidget) self.mainLayout = QGridLayout() self.mainWidget.setLayout(self.mainLayout) connectionLayout = QHBoxLayout() # widgets serialLab = QLabel('Serial Port:') self.serialLine = QLineEdit('COM3') self.serialLine.setFixedWidth(100) baudRateLab = QLabel('Baud Rate:') self.baudRateCombo = QComboBox() for baud in [300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200]: self.baudRateCombo.addItem(str(baud)) default = self.baudRateCombo.findText('9600') self.baudRateCombo.setCurrentIndex(default) self.viewport = Viewport() # Debugging stuff---------------------------------- debugLayout = QHBoxLayout() # these are used to offset the the rotation self.xAdd = QSpinBox() self.yAdd = QSpinBox() self.zAdd = QSpinBox() for each in [self.xAdd, self.yAdd, self.zAdd]: each.setMinimum(-180) # min each.setMaximum(180) # max each.setSingleStep(90) # change this to a small value if need be # these are used for inverting the rotations self.xMult = QCheckBox() self.yMult = QCheckBox() self.zMult = QCheckBox() self.xAdd.setValue(0) self.yAdd.setValue(90) # in my case I need to offset by 90 in the Y axis self.zAdd.setValue(0) self.xMult.setChecked(False) self.yMult.setChecked(True) # in my case I need to invert the Y axis on the acc self.zMult.setChecked(False) for each in [self.xAdd, self.yAdd, self.zAdd, self.xMult, self.yMult, self.zMult]: debugLayout.addWidget(each) # Debugging stuff---------------------------------- self.serialBtn = QPushButton('Connect') # add widgets to layout connectionLayout.addWidget(serialLab) connectionLayout.addWidget(self.serialLine) connectionLayout.addWidget(baudRateLab) connectionLayout.addWidget(self.baudRateCombo) connectionLayout.addWidget(self.serialBtn) connectionLayout.addStretch() self.mainLayout.addLayout(connectionLayout, 0,0,1,2) self.mainLayout.addWidget(self.viewport, 1,0,1,2) self.mainLayout.addWidget(self.accPlotWidget, 2,0,1,1) self.mainLayout.addWidget(self.gyrPlotWidget, 2,1,1,1) self.mainLayout.addWidget(self.magPlotWidget, 3,0,1,1) self.mainLayout.addWidget(self.barPlotWidget, 3,1,1,1) self.mainLayout.addLayout(debugLayout, 4,0,1,2) self.serialBtn.clicked.connect(self.serialBtnCmd) self.serialBtnCmd() # --------------------------------------------------------------------------------------- def setupSerialThread(self): portVal = self.serialLine.text() baudRate = int(self.baudRateCombo.currentText()) self.serialThread = SerialThread() self.serialThread.serialConn(portVal, baudRate) self.serialThread.progress.connect(self.update, Qt.QueuedConnection) if not self.serialThread.isRunning(): self.serialThread.start() # --------------------------------------------------------------------------------------- def update(self, line): if self.skipDataCount: # skip the first couple lines of data, because there could be some junk self.skipDataCount-=1 return try: data = map(float, line.split(',')) dataChunks =[data[x:x+3] for x in xrange(0, len(data), 3)] except ValueError, e: print 'ERROR', e return self.accDataCurr = map(int, dataChunks[0]) self.gyrDataCurr = map(int, dataChunks[1]) self.magDataCurr = map(int, dataChunks[2]) self.barDataCurr = dataChunks[3] self.accPlotWidget.update(self.accDataCurr) self.gyrPlotWidget.update(self.gyrDataCurr) self.magPlotWidget.update(self.magDataCurr) self.barPlotWidget.update(self.barDataCurr) eulerAngles = self.dcm.update(self.accDataCurr, self.gyrDataCurr, self.magDataCurr) self.viewport.updateView(eulerAngles)
class optdlg(QDialog): def __init__(self, parent=None): super(optdlg, self).__init__(parent) self.setFixedSize(484, 399) appicom = QIcon(":/icons/njnlogo.png") self.setWindowIcon(appicom) self.setWindowTitle("Nigandu English to Tamil Dictionary | OPTIONS") self.buttonBox = QDialogButtonBox(self) self.buttonBox.setEnabled(True) self.buttonBox.setGeometry(QRect(350, 20, 121, 200)) self.buttonBox.setOrientation(Qt.Vertical) self.buttonBox.setStandardButtons(QDialogButtonBox.Apply|QDialogButtonBox.Cancel|QDialogButtonBox.Ok) self.buttonBox.setCenterButtons(True) self.restorebtn = QPushButton(self) self.restorebtn.setGeometry(QRect(354, 360, 121, 23)) self.restorebtn.setText("&RestoreDefults") self.fontbox = QGroupBox(self) self.fontbox.setGeometry(QRect(10, 10, 331, 141)) self.spinBox = QSpinBox(self.fontbox) self.spinBox.setGeometry(QRect(100, 20, 81, 21)) self.spinBox.setMinimum(10) self.spinBox.setMaximum(24) self.label = QLabel(self.fontbox) self.label.setGeometry(QRect(20, 20, 71, 21)) self.label.setText("Font Size:") self.fontbox.setTitle("Font") self.samplefontbox = QGroupBox(self) self.samplefontbox.setGeometry(QRect(20, 50, 291, 91)) self.samplefontbox.setTitle("Sample Text") self.sampletxt = QLabel(self.samplefontbox) self.sampletxt.setGeometry(QRect(20, 20, 251, 61)) self.sampletxt.setText("AaBbCcDdEeFfGgHhIiJjKkLlYyZz") self.clipbox = QGroupBox(self) self.clipbox.setGeometry(QRect(10, 160, 331, 61)) self.clipbox.setTitle("ClipBoard Options") self.checkclip = QCheckBox(self.clipbox) self.checkclip.setGeometry(QRect(20, 20, 301, 31)) self.checkclip.setText("Allow copy from clipboard on start-up") self.histbox = QGroupBox(self) self.histbox.setGeometry(QRect(10, 230, 331, 91)) self.histbox.setTitle("History") self.checkshowhistdock = QCheckBox(self.histbox) self.checkshowhistdock.setGeometry(QRect(20, 60, 301, 17)) self.checkshowhistdock.setText("Show History Dock on the right side") self.checkdelhist = QCheckBox(self.histbox) self.checkdelhist.setGeometry(QRect(20, 30, 301, 17)) self.checkdelhist.setText("Clear all the past history records") self.bkmbox = QGroupBox(self) self.bkmbox.setGeometry(QRect(10, 330, 331, 61)) self.bkmbox.setTitle("Book Marks") self.checkshowbkmdock = QCheckBox(self.bkmbox) self.checkshowbkmdock.setGeometry(QRect(20, 30, 301, 17)) self.checkshowbkmdock.setText("Show Book Marks Dock on the right side.") self.spinBox.valueChanged[int].connect(self.setsampletxt) self.restorebtn.clicked.connect(self.setdeafults) self.buttonBox.rejected.connect(self.close) def setdeafults(self): self.spinBox.setValue(13) self.checkshowhistdock.setChecked(True) self.checkshowbkmdock.setChecked(True) self.checkclip.setChecked(True) self.checkdelhist.setChecked(False) def setsampletxt(self, i): font = QFont() font.setPixelSize(i) self.sampletxt.setFont(font)
class SimulationWidget(QWidget): def __init__(self, *args, **kwargs): super(SimulationWidget, self).__init__(*args, **kwargs) self._setup_ui() def load_graph(self): """ Render the graph to disk and load it into the image viewer. """ render_graph(self.graph, name=OUT_NAME) self.image_widget.load(OUT_FILE) def generate(self): """ Generate a graph with the specified nodes and edges and render it. """ nodes = self.nodes_edit.value() edges = self.edges_edit.value() self.graph = UserGraph.random(nodes, edges) self.load_graph() def infect(self): """ Infect the graph with the specified parameters and render it. """ start = self.start_edit.value() target = self.target_edit.value() delta = self.delta_edit.value() if hasattr(self, 'graph') and self.graph is not None: # Clear all infected nodes for node in self.graph.users(): node.metadata['infected'] = False limited_infection(self.graph.get_user(start), self.graph, target, delta=delta) self.load_graph() def _setup_ui(self): layout = QVBoxLayout() top_layout = QHBoxLayout() top_layout.addWidget(QLabel('Nodes:')) self.nodes_edit = QSpinBox(self) self.nodes_edit.setValue(50) top_layout.addWidget(self.nodes_edit) top_layout.addWidget(QLabel('Edges:')) self.edges_edit = QSpinBox(self) self.edges_edit.setValue(50) top_layout.addWidget(self.edges_edit) generate_button = QPushButton('Generate') generate_button.clicked.connect(self.generate) top_layout.addWidget(generate_button) top_layout.addWidget(QLabel('Start node:')) self.start_edit = QSpinBox(self) self.start_edit.setValue(0) top_layout.addWidget(self.start_edit) top_layout.addWidget(QLabel('Target:')) self.target_edit = QSpinBox(self) self.target_edit.setValue(25) top_layout.addWidget(self.target_edit) top_layout.addWidget(QLabel('Delta:')) self.delta_edit = QSpinBox(self) self.delta_edit.setValue(0) top_layout.addWidget(self.delta_edit) infect_button = QPushButton('Infect') infect_button.clicked.connect(self.infect) top_layout.addWidget(infect_button) layout.addLayout(top_layout) self.image_widget = QSvgWidget(self) layout.addWidget(self.image_widget) self.setLayout(layout)
class EditorWindow(QMainWindow): """initialize editor""" def __init__(self, tixi, xmlFilename, cpacs_scheme=Config.path_cpacs_21_schema): super(EditorWindow, self).__init__() self.cur_file_path = "" self.cur_schema_path = "" self.setupEditor() self.setupButtonMenu() self.setupSearchBox() self.setupStatusbar() self.setupMenubar() self.setupNumbar() self.popUpWidget = None self.flag_layout = False self.hbox = QHBoxLayout() self.hbox.setSpacing(0) self.hbox.setContentsMargins(0,0,0,0) self.hbox.addWidget(self.number_bar) self.hbox.addWidget(self.editor) self.layout = QGridLayout() self.layout.addWidget(self.searchbox, 0, 0, 1, 4) self.layout.addWidget(self.button1, 0, 4, 1, 1) self.layout.addWidget(self.button2, 0, 5, 1, 1) self.layout.addLayout(self.hbox, 2, 0, 1, 8) self.layout.addWidget(self.fontsizeSpinBox, 0, 6, 1, 1) self.layout.addWidget(self.label1, 0, 7, 1, 1) self.window = QWidget() self.window.setLayout(self.layout) self.setWindowTitle('Simple XML editor') self.setCentralWidget(self.window) self.resize(800, 800) self.show() self.tixi = tixi self.loadFile(xmlFilename, cpacs_scheme) ''' loads cpacs file and validates it against the cpacs_schema @param xmlFilename: input file @param cpacs_scheme: validation scheme ''' def loadFile(self, xmlFilename=None, cpacs_scheme=Config.path_cpacs_21_schema): if xmlFilename and cpacs_scheme : try: self.tixi.open(xmlFilename) #self.tixi.openDocument(xmlFilename) #self.tixi.schemaValidateFromFile(cpacs_scheme) self.editor.setPlainText(self.tixi.exportDocumentAsString()) self.cur_file_path = xmlFilename self.cur_schema_path = cpacs_scheme except TixiException as e: self.statusBar().showMessage('CPACS ERROR: ' + e.error) ''' update the dictionary by the cpacs scheme @param path_dict: path to directory @param path_scheme: path to cpacs_scheme ''' def updatedictionary(self, path_dict=Config.path_code_completion_dict, path_scheme=Config.path_cpacs_21_schema): found = False olddict = open(path_dict) scheme_file = open(path_scheme, 'r') with open(path_dict, "a") as newdict : for line in scheme_file : word = re.search("(?<=\<xsd:complexType name=\").*(?=\"\>)", line) if word != None : for tmp in olddict : if tmp == word.group(0) +"\n" : found = True break if(not found) : newdict.write(word.group(0)+"\n") olddict.seek(0) found = False olddict.close() newdict.close() scheme_file.close() ''' validate xml file and write result to statusBar ''' def validate(self): try: etree.fromstring(str(self.editor.toPlainText())) self.statusBar().showMessage("Valid XML") except etree.XMLSyntaxError as e: if e.error_log.last_error is not None: msg = e.error_log.last_error.message line = e.error_log.last_error.line col = e.error_log.last_error.column self.statusBar().showMessage("Invalid XML: Line %s, Col %s: %s"%(line,col,msg)) except: self.statusBar().showMessage("Invalid XML: Unknown error") ''' close and cleanup tixi ''' def __del__(self): pass #self.tixi.close() #self.tixi.cleanup() ''' set and connect the search buttons ''' def setupButtonMenu(self): self.button1 = QPushButton("previous" ) self.button2 = QPushButton("next" ) self.label1 = QLabel("font") self.fontsizeSpinBox = QSpinBox() self.button1.hide() self.button2.hide() self.label1.hide() self.fontsizeSpinBox.hide() self.button1.clicked.connect(self.fire_search_backward) self.button2.clicked.connect(self.fire_search_foreward) self.fontsizeSpinBox.setRange(4, 30) self.fontsizeSpinBox.setSingleStep(1) self.fontsizeSpinBox.setSuffix('pt') self.fontsizeSpinBox.setValue(10) self.fontsizeSpinBox.valueChanged.connect(self.setfontsize) def setfontsize(self, value): self.font.setPointSize(value) self.editor.setFont(self.font) def setupEditor(self): self.font = QFont() self.font.setFamily('Courier') self.font.setFixedPitch(True) self.font.setPointSize(10) self.editor = EditorCodeCompletion(Config().path_code_completion_dict) self.editor.setFont(self.font) self.editor.setTabStopWidth(20) self.editor.setAcceptRichText(False) self.editor.setLineWrapMode(QTextEdit.NoWrap) self.editor.textChanged.connect(self.validate) self.highlighter = Highlighter(self.editor.document()) def setupNumbar(self): self.number_bar = NumberBar() self.number_bar.setTextEdit(self.getStates()) self.editor.cursorPositionChanged.connect(self.fireUpdateNumbar) self.connect(self.editor.verticalScrollBar(), SIGNAL("valueChanged(int)"), self.fireUpdateNumbar) #self.editor.verticalScrollBar.valueChanged.connect(self.fireUpdateNumbar) def setupStatusbar(self): self.lineNumber = -1 self.colNumber = -1 self.m_statusRight = QLabel("row: " + str(self.lineNumber) + ", col:" + str(self.colNumber), self) self.statusBar().addPermanentWidget(self.m_statusRight, 0) def setupSearchBox(self): self.searchbox = SearchField() self.searchbox.hide() def setupMenubar(self): commentAction = QAction('Comment', self) commentAction.setShortcut('Ctrl+K') commentAction.setStatusTip('Comment Block') commentAction.triggered.connect(self.fireComment) uncommentAction = QAction('Uncomment', self) uncommentAction.setShortcut('Ctrl+Shift+K') uncommentAction.setStatusTip('Comment Block') uncommentAction.triggered.connect(self.fireUnComment) searchAction = QAction('search', self) searchAction.setShortcut('Ctrl+F') searchAction.setStatusTip('search') searchAction.triggered.connect(self.fireSearchView) newAction = QAction('New', self) newAction.setShortcut('Ctrl+N') newAction.setStatusTip('creats empty cpacs-file') newAction.triggered.connect(self.fireNewAction) self.updateAction = QAction('Update', self) self.updateAction.setShortcut('Ctrl+U') self.updateAction.setStatusTip('Update CPACS') self.updateAction.triggered.connect(self.fireUpdate) revertAction = QAction('Revert', self) revertAction.setShortcut('Ctrl+R') revertAction.triggered.connect(self.fireRevert) clearAction = QAction('Clear', self) clearAction.setStatusTip('Clear Editor') clearAction.triggered.connect(self.editor.clear) numbarAction = QAction('Line Number', self) numbarAction.triggered.connect(self.fireSwitchLayout) self.xpathAction = QAction('Current XPath', self) self.xpathAction.triggered.connect(self.getCursorXPath) link_to_node_YesAction = QAction('yes', self) link_to_node_YesAction.triggered.connect(self.dummyFuction) link_to_node_NoAction = QAction('no', self) link_to_node_NoAction.triggered.connect(self.dummyFuction) toolXAction = QAction('Tool X',self) toolXAction.triggered.connect(self.fireToolX) menubar = self.menuBar() filemenu = menubar.addMenu("File") filemenu.addAction(newAction) filemenu.addAction(self.updateAction) filemenu.addAction(revertAction) sourcemenu = menubar.addMenu("Source") sourcemenu.addAction(commentAction) sourcemenu.addAction(uncommentAction) sourcemenu.addAction(searchAction) editormenu = menubar.addMenu("Editor") editormenu.addAction(clearAction) editormenu.addSeparator() editormenu.addAction(numbarAction) editormenu.addAction(self.xpathAction) editormenu_child1 = editormenu.addMenu('Link to node') editormenu_child1.addAction(link_to_node_YesAction) editormenu_child1.addAction(link_to_node_NoAction) toolmenu = menubar.addMenu("Tools") toolmenu.addAction(toolXAction) self.editor.setContextMenuPolicy(Qt.CustomContextMenu) self.editor.customContextMenuRequested.connect(self.showMenu) #self.editor.connect(self.editor, SIGNAL( "customContextMenuRequested(QPoint)" ), self.showMenu ) def showMenu( self, pos ): """ Show a context menu for the active layer in the legend """ menu = self.editor.createStandardContextMenu() menu.addAction(self.xpathAction) menu.exec_(QtCore.QPoint( self.mapToGlobal( pos ).x() + 5, self.mapToGlobal( pos ).y() )) def fireUpdateNumbar(self): self.updateLineNumber() self.number_bar.update() def dummyFuction(self): print ("not implemented yet") def getStates(self): self.stats = { "searchbox":self.searchbox, "editor":self.editor} return self.stats ''' find previous button ''' def fire_search_backward(self): self.editor.find(self.searchbox.text(), QTextDocument.FindBackward) self.searchbox.setFocus() ''' find next button ''' def fire_search_foreward(self): #print self.tixi.getNumberOfChilds('/cpacs/vehicles/aircraft/model[@uID="Aircraft1"]/wings/wing[@uID="Aircraft1_Wing1"]/transformation[@uID="Aircraft1_Wing1_Transf"]/scaling[@uID="Aircraft1_Wing1_Transf_Sca"]/z') searchList = list(filter(lambda a : a!='', self.searchbox.text().split('/'))) if len(searchList) == 1 : if self.editor.find(searchList[0]) : pass elif not self.editor.find(searchList[0], QTextDocument.FindBackward): QMessageBox.about(self, "error", "String %s not found" % (searchList[0])) else : self.editor.moveCursor(QTextCursor.Start) self.editor.find(searchList[0]) else : self.searchXPath(self.searchbox.text(), searchList) self.searchbox.setFocus() # test # /cpacs/vehicles/aircraft/model/wings/wing/sections/section def searchXPath(self, path, searchList): try: if self.tixi.xPathEvaluateNodeNumber(path) > 1 : QMessageBox.about(self, "error", "XPath %s not unique" % path) return self.editor.moveCursor(QTextCursor.Start) found = True # search index snd loop j = 0 # search backwards for uid for i in range(len(searchList)-1, -1, -1) : if '[' in searchList[i] : # get value in brackets : [x] --> x uid = re.search(r'\[(.*)\]', searchList[i]).group(1) uid = self.__transToSearchUid(searchList[:i+1], uid) found = self.editor.find(uid) j = i+1 break # search forward for all nodes after last uid while found and j < len(searchList) : found = self.editor.find('<'+searchList[j]) j += 1 if not found : QMessageBox.about(self, "error", "XPath %s not found" % path) except TixiException : QMessageBox.about(self, "error", "XPath %s not found" % path) def __transToSearchUid(self, path_list, uid): try: int(uid) path = "" for p in path_list : path = path + '/' + p return self.tixi.getTextAttribute(path , 'uID') except ValueError: return uid.replace('@', '') def getCursorXPath(self): start_pos = self.editor.textCursor().position() tag , tag_pos , isCursorInTag = self.getTagNameAtCursor() _,xpath_idx, xpath_uid = self.__findXPath_rec('/cpacs', '/cpacs' , tag, tag_pos) if not isCursorInTag: xpath_idx = self.__strRemoveReverseToChar(xpath_idx, '/') xpath_uid = self.__strRemoveReverseToChar(xpath_uid, '/') self.__setCursorToPostion(start_pos) self.__startXPathPopUp(xpath_idx, xpath_uid) def getTagNameAtCursor(self): ''' @return: name of tag , position of tag , cursor is btw open and closing tag ''' self.editor.find('<', QTextDocument.FindBackward) isClosingTag , fst_tag = self.__getTagName() pos = self.editor.textCursor().position() if isClosingTag : # find open tag of this closing tag self.editor.find('<'+fst_tag, QTextDocument.FindBackward) pos = self.editor.textCursor().position() return fst_tag , pos , False else: return fst_tag , pos , True def __getTagName(self): tc = self.editor.textCursor() tc.select(QTextCursor.WordUnderCursor) tx = tc.selectedText() isClosingTag = False if "</" in tx : # select next word tc.select(QTextCursor.WordUnderCursor) tx = tc.selectedText() isClosingTag = True return isClosingTag , "" if "<" in tx else tx def __findXPath_rec(self, xpath_idx, xpath_uid, search, pos): nodes = self.__getChildNodesIdxTuple(xpath_idx) for (node, idx) in nodes: if node != '#text' : new_xpath_idx, new_xpath_uid = self.__createNewXPath(xpath_idx, xpath_uid, node, idx) if search == node and self.isNodeAtSearchedTagPosition(new_xpath_uid, pos) : print ("gefunden" , new_xpath_idx) return True, new_xpath_idx , new_xpath_uid else: flag , res_idx, res_uid = self.__findXPath_rec(new_xpath_idx, new_xpath_uid, search, pos) if flag : return True, res_idx, res_uid return False , xpath_idx , xpath_uid def __getChildNodesIdxTuple(self, xpath): n = self.tixi.getNumberOfChilds(xpath) + 1 node_list = list(map(lambda i : self.tixi.getChildNodeName(xpath, i), range(1,n))) res = [] for j in range(len(node_list)) : cnt = 1 for k in range(j): if node_list[k] == node_list[j] : cnt = cnt + 1 res.append((node_list[j],cnt)) return res def __createNewXPath(self, xpath_idx, xpath_uid, node, idx): path_idx = xpath_idx + '/' + node path_uid = xpath_uid + '/' + node try : uID = self.tixi.getTextAttribute(path_idx + '[' + str(idx) + ']', 'uID') path_idx = path_idx + '[' + str(idx) + ']' path_uid = path_uid+'[@uID="' + uID + '"]' except TixiException: pass # e.error == 'ATTRIBUTE_NOT_FOUND return path_idx , path_uid def isNodeAtSearchedTagPosition(self, xpath, pos): ''' @param xpath: xpath with uids (doesn't work with indices) @param param: ''' self.editor.moveCursor(QTextCursor.Start) # split string at / and remove all empty strings l = list(filter(lambda x : x != '' , xpath.split('/'))) # search index snd loop j = 0 # search backwards for uid for i in range(len(l)-1, -1, -1) : if '[' in l[i] : # get value in brackets : [x] --> x uid = re.search(r'\[@(.*)\]', l[i]).group(1) self.editor.find(uid) j = i+1 break # search forward for all nodes after last uid while j < len(l) : self.editor.find('<'+l[j]) j += 1 return pos <= self.editor.textCursor().position() def __setCursorToPostion(self, pos): tc = self.editor.textCursor() tc.setPosition(pos) self.editor.setTextCursor(tc) def __startXPathPopUp(self, xpath_idx, xpath_uid): self.popUpWidget = XPathDialog(xpath_idx, xpath_uid) self.setEnabled(False) self.popUpWidget.closeAct.triggered.connect(self.__resetPopUpWidget) self.popUpWidget.show() def updateLineNumber(self): ''' sets the line and column number ''' self.lineNumber = self.editor.textCursor().blockNumber() + 1 self.colNumber = self.editor.textCursor().columnNumber() + 1 self.m_statusRight.setText("row: " + str(self.lineNumber) + ", col:" + str(self.colNumber)) def highlightCurrentLine(self) : ''' highlight line under cursor ''' extraSelections = [] selection = QTextEdit.ExtraSelection() lineColor = QColor(255, 250, 205) selection.format.setBackground(lineColor) selection.format.setProperty(QTextFormat.FullWidthSelection, True) selection.cursor = self.editor.textCursor() selection.cursor.clearSelection() extraSelections.append(selection) self.editor.setExtraSelections(extraSelections) self.editor.setFocus() #TODO: implemnt def fireUpdate(self): print ('dummy function - update the model') text_file = open(Config.path_cpacs_tmp_file, "w") text_file.write(self.editor.toPlainText()) text_file.close() #self.tixi.saveDocument(Config.path_cpacs_tmp_file) # '../cpacs_files/temp.xml' def fireRevert(self): ''' reloads cpacs file if not updated yet ''' if(self.cur_file_path and self.cur_schema_path) : self.loadFile(self.cur_file_path, self.cur_schema_path) else : QMessageBox.about(self, "error", "CPACS-File or Validation-Schema not available") def fireSwitchLayout(self): ''' function to show or hide line numbers ''' if(self.flag_layout) : self.number_bar.flag_show_numbers = True self.update() else : self.number_bar.flag_show_numbers = False self.update() self.flag_layout = not self.flag_layout def fireNewAction(self): ''' opens new file input form ''' self.setEnabled(False) self.popUpWidget = NewFileDialog() self.popUpWidget.buttonBox.accepted.connect(self.__createNewCpacsFile) self.popUpWidget.buttonBox.rejected.connect(self.__resetPopUpWidget) self.popUpWidget.closeAct.triggered.connect(self.__resetPopUpWidget) self.popUpWidget.show() def fireToolX(self): self.popUpWidget = ToolX("X-Tool", self.tixi) self.setEnabled(False) self.popUpWidget.buttonBox.accepted.connect(self.__resetPopUpWidget) self.popUpWidget.buttonBox.rejected.connect(self.__resetPopUpWidget) # closeAct for pressing X to close window self.popUpWidget.closeAct.triggered.connect(self.__resetPopUpWidget) self.popUpWidget.show() def __createNewCpacsFile(self): ''' closes all documents and creates new empty cpacs temporary file ''' idict = self.popUpWidget.fire_submitInput() self.tixi.closeAllDocuments() self.tixi.create('cpacs') self.tixi.addCpacsHeader(idict['name'], idict['creator'], idict['version'], idict['description'], idict['cpacsVersion']) self.tixi.saveDocument(Config.path_cpacs_tmp_file) self.loadFile(Config.path_cpacs_tmp_file) self.__resetPopUpWidget() def __resetPopUpWidget(self): self.popUpWidget.close() self.popUpWidget = None self.setEnabled(True) def fireComment(self): ''' inserts open respective closing tag before and after a selected text. ''' tc = self.editor.textCursor() tc.beginEditBlock() tc.setPosition(self.editor.textCursor().selectionStart()) tc.insertText("<!--") tc.setPosition(self.editor.textCursor().selectionEnd()) tc.insertText("-->") tc.endEditBlock() def fireUnComment(self): ''' removes open respective closing tag before and after a selected text. ''' tc = self.editor.textCursor() selectTxt = tc.selectedText() if selectTxt.find('<!--') != -1 : if selectTxt.rfind('-->') != -1 : selectTxt = selectTxt.replace('<!--', '', 1) selectTxt = self.__rreplace(selectTxt, '-->' , '', 1) tc.insertText(selectTxt) else: QMessageBox.about(self, "error", "no open tag (%s) in selection" % ('-->')) else: QMessageBox.about(self, "error", "no close tag (%s) in selection" % ('<!--')) def fireSearchView(self): ''' show and hide searchbox and buttons ''' if self.searchbox.isFocused() : self.searchbox.hide() self.button1.hide() self.button2.hide() self.label1.hide() self.fontsizeSpinBox.hide() else : self.searchbox.show() self.button1.show() self.button2.show() self.label1.show() self.fontsizeSpinBox.show() self.searchbox.setFocus() def keyPressEvent(self,event): ''' handle for searching strings by pressing enter key ''' if self.searchbox.isFocused() and event.key() == Qt.Key_Return : self.fire_search_foreward() # ====================================================================================================================== # utilities # ====================================================================================================================== def __strRemoveReverseToChar(self, s, c): return self.__rm_rec(s, c) def __rm_rec(self, s, c): if s == "" : return "" elif s[-1] == c : return s[:-1] else : return self.__rm_rec(s[:-1], c) def __rreplace(self, s, old, new, occurrence): ''' reverse string replace function @param s: source string @param old: char to be replaced @param new: new char @param occurrence: only the given count occurrences are replaced. ''' li = s.rsplit(old, occurrence) return new.join(li)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.debug = debug self.progset = QSettings("ADLMIDI-pyGUI", "ADLMIDI-pyGUI") self.about_window = None self.settings_window = None self.paused = False self.MaxRecentFiles = int(self.progset.value("file/MaxRecentFiles", 5)) self.recentList = self.progset.value("file/recent", []) if type(self.recentList) is unicode: self.recentList = [self.recentList] self.banks = [ " 0 = AIL (Star Control 3, Albion, Empire 2, Sensible Soccer, Settlers 2, many others)", "01 = Bisqwit (selection of 4op and 2op)", "02 = HMI (Descent, Asterix)", "03 = HMI (Descent:: Int)", "04 = HMI (Descent:: Ham)", "05 = HMI (Descent:: Rick)", "06 = HMI (Descent 2)", "07 = HMI (Normality)", "08 = HMI (Shattered Steel)", "09 = HMI (Theme Park)", "10 = HMI (3d Table Sports, Battle Arena Toshinden)", "11 = HMI (Aces of the Deep)", "12 = HMI (Earthsiege)", "13 = HMI (Anvil of Dawn)", "14 = DMX (Doom :: partially pseudo 4op)", "15 = DMX (Hexen, Heretic :: partially pseudo 4op)", "16 = DMX (MUS Play :: partially pseudo 4op)", "17 = AIL (Discworld, Grandest Fleet, Pocahontas, Slob Zone 3d, Ultima 4, Zorro)", "18 = AIL (Warcraft 2)", "19 = AIL (Syndicate)", "20 = AIL (Guilty, Orion Conspiracy, Terra Nova Strike Force Centauri :: 4op)", "21 = AIL (Magic Carpet 2)", "22 = AIL (Nemesis)", "23 = AIL (Jagged Alliance)", "24 = AIL (When Two Worlds War :: 4op, MISSING INSTRUMENTS)", "25 = AIL (Bards Tale Construction :: MISSING INSTRUMENTS)", "26 = AIL (Return to Zork)", "27 = AIL (Theme Hospital)", "28 = AIL (National Hockey League PA)", "29 = AIL (Inherit The Earth)", "30 = AIL (Inherit The Earth, file two)", "31 = AIL (Little Big Adventure :: 4op)", "32 = AIL (Wreckin Crew)", "33 = AIL (Death Gate)", "34 = AIL (FIFA International Soccer)", "35 = AIL (Starship Invasion)", "36 = AIL (Super Street Fighter 2 :: 4op)", "37 = AIL (Lords of the Realm :: MISSING INSTRUMENTS)", "38 = AIL (SimFarm, SimHealth :: 4op)", "39 = AIL (SimFarm, Settlers, Serf City)", "40 = AIL (Caesar 2 :: partially 4op, MISSING INSTRUMENTS)", "41 = AIL (Syndicate Wars)", "42 = AIL (Bubble Bobble Feat. Rainbow Islands, Z)", "43 = AIL (Warcraft)", "44 = AIL (Terra Nova Strike Force Centuri :: partially 4op)", "45 = AIL (System Shock :: partially 4op)", "46 = AIL (Advanced Civilization)", "47 = AIL (Battle Chess 4000 :: partially 4op, melodic only)", "48 = AIL (Ultimate Soccer Manager :: partially 4op)", "49 = AIL (Air Bucks, Blue And The Gray, America Invades, Terminator 2029)", "50 = AIL (Ultima Underworld 2)", "51 = AIL (Kasparov's Gambit)", "52 = AIL (High Seas Trader :: MISSING INSTRUMENTS)", "53 = AIL (Master of Magic, Master of Orion 2 :: 4op, std percussion)", "54 = AIL (Master of Magic, Master of Orion 2 :: 4op, orchestral percussion)", "55 = SB (Action Soccer)", "56 = SB (3d Cyberpuck :: melodic only)", "57 = SB (Simon the Sorcerer :: melodic only)", "58 = OP3 (The Fat Man 2op set)", "59 = OP3 (The Fat Man 4op set)", "60 = OP3 (JungleVision 2op set :: melodic only)", "61 = OP3 (Wallace 2op set, Nitemare 3D :: melodic only)", "62 = TMB (Duke Nukem 3D)", "63 = TMB (Shadow Warrior)", "64 = DMX (Raptor)" ] self.openicon = QIcon.fromTheme('document-open', QIcon('img/load.png')) self.saveicon = QIcon.fromTheme('document-save', QIcon('img/save.png')) self.playicon = QIcon.fromTheme('media-playback-start', QIcon('img/play.png')) self.pauseicon = QIcon.fromTheme('media-playback-pause', QIcon('img/pause.png')) self.stopicon = QIcon.fromTheme('media-playback-stop', QIcon('img/stop.png')) self.quiticon = QIcon.fromTheme('application-exit', QIcon('img/quit.png')) self.abouticon = QIcon.fromTheme('help-about', QIcon('img/about.png')) self.setticon = QIcon.fromTheme('preferences-desktop', QIcon('img/settings.png')) self.winsetup() def addWorker(self, worker): worker.message.connect(self.update) worker.finished.connect(self.workerFinished) self.threads.append(worker) def workerFinished(self): pass #barf('MSG', 'Thread completed the task!') def killWorkers(self): pass #for worker in self.threads: # worker.terminate() def winsetup(self): self.setWindowIcon(QIcon('img/note.png')) openFile = QAction(self.openicon, 'Open', self) openFile.setShortcut('Ctrl+O') openFile.triggered.connect(self.load) saveFile = QAction(self.saveicon, 'Save', self) saveFile.setShortcut('Ctrl+S') saveFile.triggered.connect(self.save) playFile = QAction(self.playicon, 'Play', self) playFile.setShortcut('Ctrl+P') playFile.triggered.connect(self.play) pausePlayb = QAction(self.pauseicon, 'Pause', self) pausePlayb.setShortcut('Ctrl+R') pausePlayb.triggered.connect(self.pause) stopPlay = QAction(self.stopicon, 'Stop', self) stopPlay.setShortcut('Ctrl+Z') stopPlay.triggered.connect(self.stop) exitAction = QAction(self.quiticon, 'Quit', self) exitAction.setShortcut('Ctrl+X') exitAction.triggered.connect(self.quit) aboutdlg = QAction(self.abouticon, 'About', self) aboutdlg.setShortcut('Ctrl+A') aboutdlg.triggered.connect(self.about) showSett = QAction(self.setticon, 'Settings', self) showSett.triggered.connect(self.settings) menubar = self.menuBar() fileMenu = menubar.addMenu('&File') configMenu = menubar.addMenu('&Options') configMenu.setStyleSheet("border: 1px solid black;") self.setLooped = QAction('Loop', configMenu, checkable=True) if self.progset.value("sound/Looped") == 'true': self.setLooped.setChecked(True) else: self.setLooped.setChecked(False) self.setLooped.setShortcut('Ctrl+L') self.setAutoplay = QAction('Autoplay', configMenu, checkable=True) if self.progset.value("sound/Autoplay") == 'true': self.setAutoplay.setChecked(True) else: self.setAutoplay.setChecked(False) self.setAutoplay.setShortcut('Ctrl+K') configMenu.addAction(self.setAutoplay) configMenu.addAction(self.setLooped) fileMenu.setStyleSheet("border: 1px solid black;") fileMenu.addAction(openFile) fileMenu.addAction(saveFile) fileMenu.addSeparator() self.recentMenu = fileMenu.addMenu('Recent') self.rfUpdate() fileMenu.addSeparator() fileMenu.addAction(showSett) fileMenu.addSeparator() fileMenu.addAction(exitAction) helpMenu = menubar.addMenu('&Help') helpMenu.setStyleSheet("border: 1px solid black;") helpMenu.addAction(aboutdlg) self.numCards = QSpinBox() numCards_text = QLabel(" OPL : ") self.numCards.setRange(1, 100) self.numCards.setValue(int(self.progset.value("sound/numCards", 3))) self.numCards.valueChanged.connect(self.updateMax4ops) self.fourOps = QSpinBox() fourOps_text = QLabel(" 4op Ch : ") self.fourOps.setRange(0, self.numCards.value()*6) self.fourOps.setValue(int(self.progset.value("sound/fourOps", self.numCards.value()*6))) self.twoOps = QSpinBox() twoOps_text = QLabel(" 2op Ch : ") self.twoOps.setValue((self.numCards.value()*12 - self.fourOps.value())) self.twoOps.setRange(self.twoOps.value(), self.twoOps.value()) toolbar = self.addToolBar('Media') toolbar.addAction(playFile) toolbar.addAction(pausePlayb) toolbar.addAction(stopPlay) toolbar.setMovable(False) toolbar.addSeparator() toolbar.addWidget(numCards_text) toolbar.addWidget(self.numCards) toolbar.addSeparator() toolbar.addWidget(fourOps_text) toolbar.addWidget(self.fourOps) #toolbar.addSeparator() #toolbar.addWidget(twoOps_text) #toolbar.addWidget(self.twoOps) self.statusBar() self.setFixedSize(380, 90) self.center() self.setWindowTitle('ADLMIDI pyGUI') self.show() if self.debug: barf("MSG", "Loaded Main Window", True, False) self.update("ready") self.threads = [] self.addWorker(AdlMidi(1)) self.addWorker(AdlMidiSave(2)) def rfUpdate(self): self.recentMenu.clear() def recentfile(f2l): return lambda: self.load2(f2l) self.recentFileActs = [] recentLength = len(self.recentList) for i in range(self.MaxRecentFiles): try: if i >= recentLength: break rev = (recentLength-1)-i filetoload = self.recentList[rev] filename = path.split(filetoload)[1] self.fileact = QAction(filename, self.recentMenu) self.fileact.triggered.connect(recentfile(filetoload)) self.recentFileActs.append(self.fileact) except Exception: pass for i in range(self.MaxRecentFiles): try: self.recentMenu.addAction(self.recentFileActs[i]) except Exception: pass def get_bank(self): try: selection = self.settings_window.combo.currentText() selection = str(selection[0])+str(selection[1]) return int(selection) except Exception: return 1 def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def about(self): if self.about_window is None: window = QMessageBox(self) self.about_window = window else: window = self.about_window window = self.about_window window.setWindowIcon(QIcon(self.abouticon)) window.setWindowTitle('About ADLMIDI pyGUI') credits = "<center><b>ADLMIDI pyGUI v%s (%s)</b><br>Developed by Tristy H. \"KittyTristy\"<br>[<a href=\"https://github.com/KittyTristy/ADLMIDI-pyGUI\">Website</a>] [<a href=\"mailto:[email protected]\">Email</a>] <br><br><br>" % (__version__, system()) title = "<b>ADLMIDI pyGUI</b> is a GUI wrapper<br>written in Python for use with..<br><br><b>ADLMIDI: MIDI Player<br>for Linux and Windows with OPL3 emulation</b><br>" cw = "(C) -- <a href=\"http://iki.fi/bisqwit/source/adlmidi.html\">http://iki.fi/bisqwit/source/adlmidi.html</a></center>" credits = credits + title + cw window.setText(credits) window.show() window.activateWindow() window.raise_() def settings(self): if self.settings_window is None: window = QDialog(self) self.settings_window = window else: window = self.settings_window window = self.settings_window window.setWindowTitle('Settings') window.notelabel = QLabel("Currently these settings are only guaranteed to work prior to loading the first MIDI!\nYou'll have to restart ADLMIDI pyGui to change them again if they stop working. \n\nSorry! This will be fixed soon!") window.notelabel.setWordWrap(True) window.notelabel.setStyleSheet("font-size: 8pt; border-style: dotted; border-width: 1px; padding: 12px;") window.banklabel = QLabel("<B>Choose Instrument Bank</B>") window.space = QLabel("") window.optlabel = QLabel("<B>Options</B>") window.combo = QComboBox() window.combo.addItems(self.banks) #window.combo.setMaximumWidth(350) window.combo.setMaxVisibleItems(12) window.combo.setStyleSheet("combobox-popup: 0;") window.combo.setCurrentIndex(int(self.progset.value("sound/bank", 1))) window.combo.currentIndexChanged.connect(self.saveSettings) window.perc = QCheckBox("Adlib Percussion Instrument Mode") #window.perc.stateChanged.connect(self.checkOpts) window.tremamp = QCheckBox("Tremolo Amplification Mode") #window.tremamp.stateChanged.connect(self.checkOpts) window.vibamp = QCheckBox("Vibrato Amplification Mode") #window.vibamp.stateChanged.connect(self.checkOpts) window.modscale = QCheckBox("Scaling of Modulator Volume") #window.modscale.stateChanged.connect(self.checkOpts) window.okButton = QPushButton('OK') window.okButton.clicked.connect(window.hide) vbox = QVBoxLayout() vbox.addWidget(window.space) vbox.addWidget(window.banklabel) vbox.addWidget(window.combo) vbox.addWidget(window.space) vbox.addWidget(window.optlabel) vbox.addWidget(window.perc) vbox.addWidget(window.tremamp) vbox.addWidget(window.vibamp) vbox.addWidget(window.modscale) vbox.addWidget(window.notelabel) hbox = QHBoxLayout() hbox.addStretch(1) hbox.addWidget(window.okButton) vbox.addLayout(hbox) window.setLayout(vbox) window.setFixedSize(530, 369) window.show() window.activateWindow() window.raise_() def updateMax4ops(self): self.fourOps.setMaximum(self.numCards.value()*6) self.fourOps.setValue(self.numCards.value()*6) barf("DBG", "Updating Maximum of 4ops Chs to %s" % (self.numCards.value()*6), True, False) #self.twoOps.setValue(self.numCards.value()*12 - self.fourOps.value()) #self.twoOps.setRange(self.twoOps.value(), self.twoOps.value()) def checkOpts(self): global arglist #barf("ACT", "Checking if Options have changed..", True, False) arglist = [] try: if QAbstractButton.isChecked(self.settings_window.perc) and not ('-p' in arglist): arglist.append('-p') elif not QAbstractButton.isChecked(self.settings_window.perc) and ('-p' in arglist): arglist.remove('-p') except Exception: pass try: if QAbstractButton.isChecked(self.settings_window.tremamp) and not ('-t' in arglist): arglist.append('-t') elif not QAbstractButton.isChecked(self.settings_window.tremamp) and ('-t' in arglist): arglist.remove('-t') except Exception: pass try: if QAbstractButton.isChecked(self.settings_window.vibamp) and not ('-v' in arglist): arglist.append('-v') elif not QAbstractButton.isChecked(self.settings_window.vibamp) and ('-v' in arglist): arglist.remove('-v') except Exception: pass try: if QAbstractButton.isChecked(self.settings_window.modscale) and not ('-s' in arglist): arglist.append('-s') elif not QAbstractButton.isChecked(self.settings_window.modscale) and ('-s' in arglist): arglist.remove('-s') except Exception: pass self.sel_bank = self.get_bank() def saveSettings(self): self.progset.setValue("sound/Autoplay", self.setAutoplay.isChecked()) self.progset.setValue("sound/Looped", self.setLooped.isChecked()) self.progset.setValue("sound/numCards", self.numCards.value()) self.progset.setValue("sound/fourOps", self.fourOps.value()) try: self.progset.setValue("sound/bank", self.settings_window.combo.currentIndex()) except Exception: pass if len(self.recentList) >= 1: self.progset.setValue("file/recent", self.recentList[-self.MaxRecentFiles:]) self.progset.setValue("file/MaxRecentFiles", self.MaxRecentFiles) #allkeys = self.progset.allKeys() #for key in allkeys: # barf('DBG', str(key) + " " + str(self.progset.value(key))) def closeEvent(self, event): self.stop() #self.pkill() self.saveSettings() barf("DBG", "Quitting", True, False) def quit(self): self.stop() #self.pkill() self.saveSettings() barf("DBG", "Quitting", True, False) exit(0) def pkill(self): try: p.kill() except Exception: pass ############################################################## ##### Statusbar Functions #################################### ############################################################## def clear(self): try: self.statusBar().removeWidget(self.playStatus) except Exception: pass @Slot(str) def update(self, status=''): self.clear() if status == "ready": text = " <B>Ready</b>" elif status == "play": text = " <B>Now Playing: </B>" + path.split(f.name)[1] elif status == "loop": text = " <B>Looping: </B>" + path.split(f.name)[1] elif status == "stop": text = " <B>Stopped: </B>" + path.split(f.name)[1] elif status == "pause": text = " <B>Paused: </B>" + path.split(f.name)[1] elif status == "loading": text = " <B>Loading.. </B>" elif status == "load": text = " <B>Loaded: </B>" + path.split(f.name)[1] elif status == "saving": text = " <B>Saving.. </B>" elif status == "saved": text = " <B>Saved as: </B>" + "saved/" + path.splitext(path.split(f.name)[1])[0] + ".wav" self.playStatus = QLabel(text) self.statusBar().addPermanentWidget(self.playStatus, 1) ############################################################## ####### Sound Functions ###################################### ############################################################## def play(self): global Paused, arglist if f != None and Paused == False: Paused = False self.stop() self.checkOpts() if not self.setLooped.isChecked(): arglist.append('-nl') arglist.append(str(self.progset.value("sound/bank", 1))) arglist.append(str(self.numCards.value())) arglist.append(str(self.fourOps.value())) for worker in self.threads: if worker.id == 1: worker.start() elif f != None and Paused == True: os.kill(p.pid, signal.SIGCONT) self.update("play") Paused = False def pause(self): global p, Paused if f != None: try: if Paused == False: os.kill(p.pid, signal.SIGSTOP) self.update("pause") Paused = True elif Paused == True: os.kill(p.pid, signal.SIGCONT) self.update("play") Paused = False except Exception: pass def stop(self): global Paused if f != None: Paused = False self.pkill() self.killWorkers() self.update("stop") ############################################################## ##### Load/Save Functions #################################### ############################################################## def load(self): global f lastdir = str(self.progset.value("file/lastdir", "")) fname, _ = QFileDialog.getOpenFileName(None, 'Open File', lastdir, "MIDI Audio File (*.mid *.MID)") if fname != "": f = file(fname, 'r') if not f.name in self.recentList: self.recentList.append(f.name) else: self.recentList.remove(f.name) self.recentList.append(f.name) self.progset.setValue("file/lastdir", path.split(f.name)[0]) self.rfUpdate() self.update("load") self.pkill() if self.debug: barf("SAV", "Loaded %s" % path.split(f.name)[1], True, False) if self.setAutoplay.isChecked(): self.play() else: self.update("load") def load2(self, r_file=None): global f f = file(r_file, 'r') self.recentList.remove(f.name) self.recentList.append(f.name) self.rfUpdate() self.update("load") self.pkill() if self.debug: barf("SAV", "Loaded %s" % path.split(f.name)[1], True, False) if self.setAutoplay.isChecked(): self.play() else: self.update("load") def save(self): if f != None: self.stop() for worker in self.threads: if worker.id == 2: worker.start()