class SpinBoxImageView(QHBoxLayout): valueChanged = pyqtSignal(int) def __init__(self, parentView, backgroundColor, foregroundColor, value, height, fontSize): QHBoxLayout.__init__(self) self.backgroundColor = backgroundColor self.foregroundColor = foregroundColor self.labelLayout = QVBoxLayout() self.upLabel = LabelButtons('spin-up', parentView, backgroundColor, foregroundColor, height/2, height/2) self.labelLayout.addWidget(self.upLabel) self.upLabel.clicked.connect(self.on_upLabel) self.downLabel = LabelButtons('spin-down', parentView, backgroundColor, foregroundColor, height/2, height/2) self.labelLayout.addWidget(self.downLabel) self.downLabel.clicked.connect(self.on_downLabel) self.addLayout(self.labelLayout) self.spinBox = QSpinBox() self.spinBox.valueChanged.connect(self.spinBoxValueChanged) self.addWidget(self.spinBox) self.spinBox.setToolTip("Spinbox") self.spinBox.setButtonSymbols(QAbstractSpinBox.NoButtons) self.spinBox.setAlignment(Qt.AlignRight) self.spinBox.setMaximum(value) self.spinBox.setMaximumHeight(height) self.spinBox.setSuffix("/" + str(value)) font = self.spinBox.font() font.setPixelSize(fontSize) self.spinBox.setFont(font) self.do_draw() def do_draw(self): r, g, b, a = self.foregroundColor.getRgb() rgb = "rgb({0},{1},{2})".format(r, g, b) sheet = TEMPLATE.format(rgb, self.backgroundColor.name()) self.spinBox.setStyleSheet(sheet) def spinBoxValueChanged(self, value): self.valueChanged.emit(value) def setValue(self, value): self.spinBox.setValue(value) def setNewValue(self, value): self.spinBox.setMaximum(value) self.spinBox.setSuffix("/" + str(value)) def on_upLabel(self): self.spinBox.setValue(self.spinBox.value() + 1) def on_downLabel(self): self.spinBox.setValue(self.spinBox.value() - 1)
class Prefs(preferences.Group): def __init__(self, page): super(Prefs, self).__init__(page) self._closeOutputs = QCheckBox(clicked=self.changed) self._pollingLabel = QLabel() self._pollingTime = QSpinBox() self._pollingTime.setRange(0, 1000) self._pollingTime.setSuffix(" ms") self._pollingTime.valueChanged.connect(self.changed) layout = QVBoxLayout() self.setLayout(layout) layout.addWidget(self._closeOutputs) app.translateUI(self) hbox = QHBoxLayout() layout.addLayout(hbox) hbox.addWidget(self._pollingLabel) hbox.addWidget(self._pollingTime) def translateUI(self): self.setTitle(_("Preferences")) self._closeOutputs.setText(_("Close unused MIDI output")) self._closeOutputs.setToolTip( _("Closes unused MIDI ports after one minute. " 'See "What\'s This" for more information.') ) self._closeOutputs.setWhatsThis( _( "<p>If checked, Frescobaldi will close MIDI output ports that are not " "used for one minute.</p>\n" "<p>This could free up system resources that a software MIDI synthesizer " "might be using, thus saving battery power.</p>\n" "<p>A side effect is that if you pause a MIDI file for a long time " "the instruments are reset to the default piano (instrument 0). " "In that case, playing the file from the beginning sets up the " "instruments again.</p>\n" ) ) self._pollingLabel.setText(_("Polling time for input:")) self._pollingTime.setToolTip(_("Polling time for MIDI input. " 'See "What\'s This" for more information.')) self._pollingTime.setWhatsThis( _( "Sets the time between the polling of the MIDI input port in milliseconds. " "Small values lead to faster recognition of incoming MIDI events, but stress " "the CPU. 10 ms should be a good value." ) ) def loadSettings(self): s = QSettings() self._closeOutputs.setChecked(s.value("midi/close_outputs", False, bool)) self._pollingTime.setValue(s.value("midi/polling_time", 10, int)) def saveSettings(self): s = QSettings() s.setValue("midi/close_outputs", self._closeOutputs.isChecked()) s.setValue("midi/polling_time", self._pollingTime.value())
class SpinBoxImageView(QHBoxLayout): valueChanged = pyqtSignal(int) def __init__(self, backgroundColor, foregroundColor, value, height, fontSize): QHBoxLayout.__init__(self) self.backgroundColor = backgroundColor self.foregroundColor = foregroundColor self.labelLayout = QVBoxLayout() self.upLabel = LabelButtons(backgroundColor, foregroundColor, height/2, height/2) self.labelLayout.addWidget(self.upLabel) self.upLabel.setSpinBoxUpIcon() self.upLabel.clicked.connect(self.on_upLabel) self.downLabel = LabelButtons(backgroundColor, foregroundColor, height/2, height/2) self.labelLayout.addWidget(self.downLabel) self.downLabel.setSpinBoxDownIcon() self.downLabel.clicked.connect(self.on_downLabel) self.addLayout(self.labelLayout) self.spinBox = QSpinBox() self.spinBox.valueChanged.connect(self.spinBoxValueChanged) self.addWidget(self.spinBox) self.spinBox.setToolTip("Spinbox") self.spinBox.setButtonSymbols(QAbstractSpinBox.NoButtons) self.spinBox.setAlignment(Qt.AlignRight) self.spinBox.setMaximum(value) self.spinBox.setMaximumHeight(height) self.spinBox.setSuffix("/" + str(value)) font = self.spinBox.font() font.setPixelSize(fontSize) self.spinBox.setFont(font) rgb = foregroundColor.getRgb() rgba_string = "rgba("+str(rgb[0])+","+str(rgb[1])+","+str(rgb[2])+","+str(0.6*100)+"%)" self.spinBox.setStyleSheet("QSpinBox { color: " + rgba_string + "; font: bold; background-color: " + str(backgroundColor.name()) + "; border:0;}") def changeOpacity(self, opacity): rgb = self.foregroundColor.getRgb() rgba_string = "rgba("+str(rgb[0])+","+str(rgb[1])+","+str(rgb[2])+","+str(opacity*100)+"%)" self.spinBox.setStyleSheet("QSpinBox { color: " + rgba_string + "; font: bold; background-color: " + str(self.backgroundColor.name()) + "; border:0;}") self.upLabel.changeOpacity(opacity) self.downLabel.changeOpacity(opacity) def spinBoxValueChanged(self, value): self.valueChanged.emit(value) def setValue(self, value): self.spinBox.setValue(value) def setNewValue(self, value): self.spinBox.setMaximum(value) self.spinBox.setSuffix("/" + str(value)) def on_upLabel(self): self.spinBox.setValue(self.spinBox.value() + 1) def on_downLabel(self): self.spinBox.setValue(self.spinBox.value() - 1)
class Prefs(preferences.Group): def __init__(self, page): super(Prefs, self).__init__(page) self._closeOutputs = QCheckBox(clicked=self.changed) self._pollingLabel = QLabel() self._pollingTime = QSpinBox() self._pollingTime.setRange(0, 1000) self._pollingTime.setSuffix(" ms") self._pollingTime.valueChanged.connect(self.changed) layout = QVBoxLayout() self.setLayout(layout) layout.addWidget(self._closeOutputs) app.translateUI(self) hbox = QHBoxLayout() layout.addLayout(hbox) hbox.addWidget(self._pollingLabel) hbox.addWidget(self._pollingTime) def translateUI(self): self.setTitle(_("Preferences")) self._closeOutputs.setText(_("Close unused MIDI output")) self._closeOutputs.setToolTip( _("Closes unused MIDI ports after one minute. " "See \"What's This\" for more information.")) self._closeOutputs.setWhatsThis( _("<p>If checked, Frescobaldi will close MIDI output ports that are not " "used for one minute.</p>\n" "<p>This could free up system resources that a software MIDI synthesizer " "might be using, thus saving battery power.</p>\n" "<p>A side effect is that if you pause a MIDI file for a long time " "the instruments are reset to the default piano (instrument 0). " "In that case, playing the file from the beginning sets up the " "instruments again.</p>\n")) self._pollingLabel.setText(_("Polling time for input:")) self._pollingTime.setToolTip( _("Polling time for MIDI input. " "See \"What's This\" for more information.")) self._pollingTime.setWhatsThis( _("Sets the time between the polling of the MIDI input port in milliseconds. " "Small values lead to faster recognition of incoming MIDI events, but stress " "the CPU. 10 ms should be a good value.")) def loadSettings(self): s = QSettings() self._closeOutputs.setChecked( s.value("midi/close_outputs", False, bool)) self._pollingTime.setValue(s.value("midi/polling_time", 10, int)) def saveSettings(self): s = QSettings() s.setValue("midi/close_outputs", self._closeOutputs.isChecked()) s.setValue("midi/polling_time", self._pollingTime.value())
class MusicView(preferences.Group): def __init__(self, page): super(MusicView, self).__init__(page) layout = QGridLayout() self.setLayout(layout) self.magnifierSizeLabel = QLabel() self.magnifierSizeSlider = QSlider(Qt.Horizontal, valueChanged=self.changed) self.magnifierSizeSlider.setSingleStep(50) self.magnifierSizeSlider.setRange(*popplerview.MagnifierSettings.sizeRange) self.magnifierSizeSpinBox = QSpinBox() self.magnifierSizeSpinBox.setRange(*popplerview.MagnifierSettings.sizeRange) self.magnifierSizeSpinBox.valueChanged.connect(self.magnifierSizeSlider.setValue) self.magnifierSizeSlider.valueChanged.connect(self.magnifierSizeSpinBox.setValue) layout.addWidget(self.magnifierSizeLabel, 0, 0) layout.addWidget(self.magnifierSizeSlider, 0, 1) layout.addWidget(self.magnifierSizeSpinBox, 0, 2) self.magnifierScaleLabel = QLabel() self.magnifierScaleSlider = QSlider(Qt.Horizontal, valueChanged=self.changed) self.magnifierScaleSlider.setSingleStep(50) self.magnifierScaleSlider.setRange(*popplerview.MagnifierSettings.scaleRange) self.magnifierScaleSpinBox = QSpinBox() self.magnifierScaleSpinBox.setRange(*popplerview.MagnifierSettings.scaleRange) self.magnifierScaleSpinBox.valueChanged.connect(self.magnifierScaleSlider.setValue) self.magnifierScaleSlider.valueChanged.connect(self.magnifierScaleSpinBox.setValue) layout.addWidget(self.magnifierScaleLabel, 1, 0) layout.addWidget(self.magnifierScaleSlider, 1, 1) layout.addWidget(self.magnifierScaleSpinBox, 1, 2) app.translateUI(self) def translateUI(self): self.setTitle(_("Music View")) self.magnifierSizeLabel.setText(_("Magnifier Size:")) self.magnifierSizeLabel.setToolTip(_( "Size of the magnifier glass (Ctrl+Click in the Music View).")) # L10N: as in "400 pixels", appended after number in spinbox, note the leading space self.magnifierSizeSpinBox.setSuffix(_(" pixels")) self.magnifierScaleLabel.setText(_("Magnifier Scale:")) self.magnifierScaleLabel.setToolTip(_( "Magnification of the magnifier.")) self.magnifierScaleSpinBox.setSuffix(_("percent unit sign", "%")) def loadSettings(self): s = popplerview.MagnifierSettings.load() self.magnifierSizeSlider.setValue(s.size) self.magnifierScaleSlider.setValue(s.scale) def saveSettings(self): s = popplerview.MagnifierSettings() s.size = self.magnifierSizeSlider.value() s.scale = self.magnifierScaleSlider.value() s.save()
class Updates(QWidget): def __init__(self, pref): QWidget.__init__(self) vbox = QVBoxLayout(self) vbox.addWidget(QLabel('Set the interval for updates:')) self.spin = QSpinBox() self.spin.setRange(1, 60) self.spin.setSuffix(' minutes') self.spin.setValue(pref.get('time', 10)) vbox.addWidget(self.spin)
class Form(QDialog): def __init__(self, parent=None): super(Form, self).__init__(parent) self.label_amount = QLabel('Amount') self.spin_amount = QDoubleSpinBox() self.spin_amount.setRange(0, 10000000000) self.spin_amount.setPrefix('Rp. ') self.spin_amount.setSingleStep(100000) self.label_rate = QLabel('Rate') self.spin_rate = QDoubleSpinBox() self.spin_rate.setSuffix(' %') self.spin_rate.setSingleStep(0.1) self.spin_rate.setRange(0, 100) self.label_year = QLabel('Years') self.spin_year = QSpinBox() self.spin_year.setSuffix(' year') self.spin_year.setSingleStep(1) self.spin_year.setRange(0, 1000) self.spin_year.setValue(1) self.label_total_ = QLabel('Total') self.label_total = QLabel('Rp. 0.00') grid = QGridLayout() grid.addWidget(self.label_amount, 0, 0) grid.addWidget(self.spin_amount, 0, 1) grid.addWidget(self.label_rate, 1, 0) grid.addWidget(self.spin_rate, 1, 1) grid.addWidget(self.label_year, 2, 0) grid.addWidget(self.spin_year, 2, 1) grid.addWidget(self.label_total_, 3, 0) grid.addWidget(self.label_total, 3, 1) self.setLayout(grid) self.connect(self.spin_amount, SIGNAL('valueChanged(double)'), self.update_ui) self.connect(self.spin_rate, SIGNAL('valueChanged(double)'), self.update_ui) self.connect(self.spin_year, SIGNAL('valueChanged(int)'), self.update_ui) self.setWindowTitle('Interest') def update_ui(self): amount = self.spin_amount.value() rate = self.spin_rate.value() year = self.spin_year.value() total = amount * (1 + rate / 100.0)**year self.label_total.setText('Rp. %.2f' % total)
def __init__(self, attr_name, attr_val, parent=None): super(Attribute, self).__init__(parent) # The label with the attribute's name label = QLabel(attr_name) # Now create the editing element, initialized with the attribute's # value. # First, if the value is an integer, use a spinbox if type(attr_val) is int: value = QSpinBox() value.setMaximum(1E9) value.setValue(attr_val) # Second, if the value is a float, use a doublespinbox, with some # customizations for certain attributes. elif type(attr_val) is float: # We want to display the sensitivities in useful units, which should # simulate scientific notation. The attribute value is the # sensitivity's index in the SENSVECTOR. if "Sens" in attr_name: value = QSpinBox() value.setMaximum(1E10) value.setMinimum(1) attr_val = SENSVECTOR[int(attr_val)] # Figure out which units to use for ex in [(1E-3, 'mV'), (1E-6, 'uV'), (1E-9, 'nV')]: if attr_val / ex[0] > 1 and attr_val / ex[0] < 1000: value.setValue(attr_val / ex[0]) value.setSuffix(' {units}'.format(units=ex[1])) # If the value is a float, but not a sensitivity, just use a normal # doublespinbox else: value = QDoubleSpinBox() value.setMaximum(1E9) value.setMinimum(-1E9) value.setValue(attr_val) # Third, if the value is a datetime, dispaly it in a datetimeedit # element. elif type(attr_val) is datetime: value = QDateTimeEdit() value.setDateTime(attr_val) # Finally, for everything else just display it in a lineedit element. else: value = QLineEdit() value.setText(str(attr_val)) layout = QHBoxLayout() layout.addWidget(label) layout.addWidget(value) self.setLayout(layout)
class Form(QDialog): def __init__(self, parent=None): super(Form, self).__init__(parent) self.label_amount = QLabel('Amount') self.spin_amount = QDoubleSpinBox() self.spin_amount.setRange(0, 10000000000) self.spin_amount.setPrefix('Rp. ') self.spin_amount.setSingleStep(100000) self.label_rate = QLabel('Rate') self.spin_rate = QDoubleSpinBox() self.spin_rate.setSuffix(' %') self.spin_rate.setSingleStep(0.1) self.spin_rate.setRange(0, 100) self.label_year = QLabel('Years') self.spin_year = QSpinBox() self.spin_year.setSuffix(' year') self.spin_year.setSingleStep(1) self.spin_year.setRange(0, 1000) self.spin_year.setValue(1) self.label_total_ = QLabel('Total') self.label_total = QLabel('Rp. 0.00') grid = QGridLayout() grid.addWidget(self.label_amount, 0, 0) grid.addWidget(self.spin_amount, 0, 1) grid.addWidget(self.label_rate, 1, 0) grid.addWidget(self.spin_rate, 1, 1) grid.addWidget(self.label_year, 2, 0) grid.addWidget(self.spin_year, 2, 1) grid.addWidget(self.label_total_, 3, 0) grid.addWidget(self.label_total, 3, 1) self.setLayout(grid) self.connect(self.spin_amount, SIGNAL('valueChanged(double)'), self.update_ui) self.connect(self.spin_rate, SIGNAL('valueChanged(double)'), self.update_ui) self.connect(self.spin_year, SIGNAL('valueChanged(int)'), self.update_ui) self.setWindowTitle('Interest') def update_ui(self): amount = self.spin_amount.value() rate = self.spin_rate.value() year = self.spin_year.value() total = amount * (1 + rate / 100.0) ** year self.label_total.setText('Rp. %.2f' % total)
class ProjectXively(QWidget): qtcb_update_illuminance = pyqtSignal(float) qtcb_update_air_pressure = pyqtSignal(float) qtcb_update_temperature = pyqtSignal(float) qtcb_update_humidity = pyqtSignal(float) qtcb_button_pressed = pyqtSignal(int) lcdwidget = None xively_host = "api.xively.com" xively_agent = "Tinkerforge Starter Kit Weather Station Demo" xively_channel = "Enter Feed ID here" xively_api_key = "Enter API Key here" xively_items = {} xively_headers = None xively_params = "" xively_update_rate = 5 # in minutes text_agent = None text_channel = None text_api_key = None number_update_rate = None save_button = None xively_timer = None error_message = None label_upload_active = None last_upload = None def __init__(self, parent, app): super(QWidget, self).__init__() self.lcdwidget = LCDWidget(self, app) self.lcdwidget.hide() self.text_agent = QLineEdit(self) self.text_agent.setText(self.xively_agent) self.text_channel = QLineEdit(self) self.text_channel.setText(self.xively_channel) self.text_api_key = QLineEdit(self) self.text_api_key.setText(self.xively_api_key) self.number_update_rate = QSpinBox(self) self.number_update_rate.setRange(1, 1440) self.number_update_rate.setSuffix(' min') self.number_update_rate.setValue(self.xively_update_rate) layout1 = QHBoxLayout() layout2 = QVBoxLayout() layout1.addStretch() layout1.addLayout(layout2) layout1.addStretch() layout2.addSpacerItem(QSpacerItem(LCDWidget.FIXED_WIDGTH, 0)) label = QLabel(self) label.setText( "Project: <b>Connect to Xively</b>. This project uploads the measured values to Xively. Please find documentation how to configure it and program sources in Python <a href=\"http://www.tinkerforge.com/en/doc/Kits/WeatherStation/WeatherStation.html#connect-to-xively\">here</a>.<br>" ) label.setTextFormat(Qt.RichText) label.setTextInteractionFlags(Qt.TextBrowserInteraction) label.setOpenExternalLinks(True) label.setWordWrap(True) label.setAlignment(Qt.AlignJustify) layout2.addSpacing(10) layout2.addWidget(label) layout2.addSpacing(10) layout3a = QHBoxLayout() label = QLabel("Agent Description:") label.setMinimumWidth(150) layout3a.addWidget(label) layout3a.addWidget(self.text_agent, 1) layout2.addLayout(layout3a) layout2.addSpacing(10) layout3b = QHBoxLayout() label = QLabel("Feed:") label.setMinimumWidth(150) layout3b.addWidget(label) layout3b.addWidget(self.text_channel, 1) layout2.addLayout(layout3b) layout2.addSpacing(10) layout3c = QHBoxLayout() label = QLabel("API Key:") label.setMinimumWidth(150) layout3c.addWidget(label) layout3c.addWidget(self.text_api_key, 1) layout2.addLayout(layout3c) layout2.addSpacing(10) layout3d = QHBoxLayout() label = QLabel("Update Rate:") label.setMinimumWidth(150) layout3d.addWidget(label) layout3d.addWidget(self.number_update_rate, 1) layout2.addLayout(layout3d) layout2.addSpacing(10) self.label_upload_active = QLabel("Not Active", self) self.label_upload_active.setMinimumWidth(150) font = QFont() font.setPixelSize(20) self.label_upload_active.setFont(font) self.set_active_label(False) self.save_button = QPushButton("Save/Activate") layout4 = QHBoxLayout() layout4.addWidget(self.label_upload_active) layout4.addWidget(self.save_button, 1) layout2.addLayout(layout4) layout2.addStretch() self.setLayout(layout1) self.qtcb_update_illuminance.connect(self.update_illuminance_data_slot) self.qtcb_update_air_pressure.connect( self.update_air_pressure_data_slot) self.qtcb_update_temperature.connect(self.update_temperature_data_slot) self.qtcb_update_humidity.connect(self.update_humidity_data_slot) self.qtcb_button_pressed.connect(self.button_pressed_slot) self.save_button.clicked.connect(self.save_configuration) self.lcdwidget.clear(self) self.error_message = QErrorMessage(self) def set_active_label(self, value): palette = self.label_upload_active.palette() if value: palette.setColor(self.foregroundRole(), Qt.darkGreen) self.label_upload_active.setText("Active") else: palette.setColor(self.foregroundRole(), Qt.red) self.label_upload_active.setText("Not Active") self.label_upload_active.setPalette(palette) def save_configuration(self): try: self.xively_agent = str(self.text_agent.text()).decode('ascii') self.xively_channel = str(self.text_channel.text()).decode('ascii') self.xively_api_key = str(self.text_api_key.text()).decode('ascii') except: self.error_message.showMessage( 'Agent, Feed and API Key can only contain ASCII characters') return self.xively_update_rate = self.number_update_rate.value() self.xively_headers = { "Content-Type": "application/x-www-form-urlencoded", "X-ApiKey": self.xively_api_key, "User-Agent": self.xively_agent, } self.xively_params = "/v2/feeds/" + self.xively_channel if self.xively_timer is None: self.xively_timer = QTimer(self) self.xively_timer.timeout.connect(self.update_xively) self.xively_timer.start(self.xively_update_rate * 60 * 1000) self.set_active_label(True) self.update_xively() def write_lcd(self): if self.last_upload == None: tmp = "Last: Never" else: tmp = "Last: " + self.last_upload self.lcdwidget.write_line(0, 0, "Xively Upload", self) self.lcdwidget.write_line(2, 0, tmp, self) def update_xively(self): if len(self.xively_items) == 0: return stream_items = [] for identifier, value in self.xively_items.items(): stream_items.append({ 'id': identifier, 'current_value': value[0], 'min_value': value[1], 'max_value': value[2] }) data = {'version': '1.0.0', 'datastreams': stream_items} self.xively_items = {} body = json.dumps(data) try: http = httplib.HTTPSConnection(self.xively_host) http.request('PUT', self.xively_params, body, self.xively_headers) response = http.getresponse() http.close() if response.status != 200: self.error_message.showMessage( 'Could not upload to xively -> Response:' + str(response.status) + ': ' + response.reason + '. Check your configuration.') self.xively_timer.stop() self.xively_timer = None self.set_active_label(False) return except Exception as e: self.error_message.showMessage('HTTP error: ' + str(e)) self.xively_timer.stop() self.xively_timer = None self.set_active_label(False) return # set upload time if upload was a success self.last_upload = time.strftime("%H:%M:%S") def put(self, identifier, value): self.write_lcd() try: _, min_value, max_value = self.xively_items[identifier] if value < min_value: min_value = value if value > max_value: max_value = value self.xively_items[identifier] = (value, min_value, max_value) except: self.xively_items[identifier] = (value, value, value) def update_illuminance_data_slot(self, illuminance): self.put('AmbientLight', illuminance) def update_illuminance(self, illuminance): self.qtcb_update_illuminance.emit(illuminance) def update_humidity_data_slot(self, humidity): self.put('Humidity', humidity) def update_humidity(self, humidity): self.qtcb_update_humidity.emit(humidity) def update_air_pressure_data_slot(self, air_pressure): self.put('AirPressure', air_pressure) def update_air_pressure(self, air_pressure): self.qtcb_update_air_pressure.emit(air_pressure) def update_temperature_data_slot(self, temperature): self.put('Temperature', temperature) def update_temperature(self, temperature): self.qtcb_update_temperature.emit(temperature) def button_pressed_slot(self, button): pass def button_pressed(self, button): self.qtcb_button_pressed.emit(button)
class MusicView(preferences.Group): def __init__(self, page): super(MusicView, self).__init__(page) layout = QGridLayout() self.setLayout(layout) self.newerFilesOnly = QCheckBox(toggled=self.changed) layout.addWidget(self.newerFilesOnly, 0, 0, 1, 3) self.magnifierSizeLabel = QLabel() self.magnifierSizeSlider = QSlider(Qt.Horizontal, valueChanged=self.changed) self.magnifierSizeSlider.setSingleStep(50) self.magnifierSizeSlider.setRange(*popplerview.MagnifierSettings.sizeRange) self.magnifierSizeSpinBox = QSpinBox() self.magnifierSizeSpinBox.setRange(*popplerview.MagnifierSettings.sizeRange) self.magnifierSizeSpinBox.valueChanged.connect(self.magnifierSizeSlider.setValue) self.magnifierSizeSlider.valueChanged.connect(self.magnifierSizeSpinBox.setValue) layout.addWidget(self.magnifierSizeLabel, 1, 0) layout.addWidget(self.magnifierSizeSlider, 1, 1) layout.addWidget(self.magnifierSizeSpinBox, 1, 2) self.magnifierScaleLabel = QLabel() self.magnifierScaleSlider = QSlider(Qt.Horizontal, valueChanged=self.changed) self.magnifierScaleSlider.setSingleStep(50) self.magnifierScaleSlider.setRange(*popplerview.MagnifierSettings.scaleRange) self.magnifierScaleSpinBox = QSpinBox() self.magnifierScaleSpinBox.setRange(*popplerview.MagnifierSettings.scaleRange) self.magnifierScaleSpinBox.valueChanged.connect(self.magnifierScaleSlider.setValue) self.magnifierScaleSlider.valueChanged.connect(self.magnifierScaleSpinBox.setValue) layout.addWidget(self.magnifierScaleLabel, 2, 0) layout.addWidget(self.magnifierScaleSlider, 2, 1) layout.addWidget(self.magnifierScaleSpinBox, 2, 2) self.enableKineticScrolling = QCheckBox(toggled=self.changed) layout.addWidget(self.enableKineticScrolling) self.showScrollbars = QCheckBox(toggled=self.changed) layout.addWidget(self.showScrollbars) app.translateUI(self) def translateUI(self): self.setTitle(_("Music View")) self.newerFilesOnly.setText(_("Only load updated PDF documents")) self.newerFilesOnly.setToolTip(_( "If checked, Frescobaldi will not open PDF documents that are not\n" "up-to-date (i.e. the source file has been modified later).")) self.magnifierSizeLabel.setText(_("Magnifier Size:")) self.magnifierSizeLabel.setToolTip(_( "Size of the magnifier glass (Ctrl+Click in the Music View).")) # L10N: as in "400 pixels", appended after number in spinbox, note the leading space self.magnifierSizeSpinBox.setSuffix(_(" pixels")) self.magnifierScaleLabel.setText(_("Magnifier Scale:")) self.magnifierScaleLabel.setToolTip(_( "Magnification of the magnifier.")) self.magnifierScaleSpinBox.setSuffix(_("percent unit sign", "%")) # L10N: "Kinetic Scrolling" is a checkbox label, as in "Enable Kinetic Scrolling" self.enableKineticScrolling.setText(_("Kinetic Scrolling")) self.showScrollbars.setText(_("Show Scrollbars")) def loadSettings(self): s = popplerview.MagnifierSettings.load() self.magnifierSizeSlider.setValue(s.size) self.magnifierScaleSlider.setValue(s.scale) s = QSettings() s.beginGroup("musicview") newerFilesOnly = s.value("newer_files_only", True, bool) self.newerFilesOnly.setChecked(newerFilesOnly) kineticScrollingActive = s.value("kinetic_scrolling", True, bool) self.enableKineticScrolling.setChecked(kineticScrollingActive) showScrollbars = s.value("show_scrollbars", True, bool) self.showScrollbars.setChecked(showScrollbars) def saveSettings(self): s = popplerview.MagnifierSettings() s.size = self.magnifierSizeSlider.value() s.scale = self.magnifierScaleSlider.value() s.save() s = QSettings() s.beginGroup("musicview") s.setValue("newer_files_only", self.newerFilesOnly.isChecked()) s.setValue("kinetic_scrolling", self.enableKineticScrolling.isChecked()) s.setValue("show_scrollbars", self.showScrollbars.isChecked())
class YPipeWidget(QWidget): def __init__(self, leftFlow = 0, rightFlow = 0, maxFlow = 100, parent = None): super(YPipeWidget, self).__init__(parent) self.leftSpinBox = QSpinBox(self) self.leftSpinBox.setRange(0, maxFlow) self.leftSpinBox.setValue(leftFlow) self.leftSpinBox.setSuffix(" l/s") self.leftSpinBox.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.connect(self.leftSpinBox, SIGNAL("valueChanged(int)"), self.valueChanged) self.rightSpinBox = QSpinBox(self) self.rightSpinBox.setRange(0, maxFlow) self.rightSpinBox.setValue(rightFlow) self.rightSpinBox.setSuffix(" l/s") self.rightSpinBox.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.connect(self.rightSpinBox, SIGNAL("valueChanged(int)"), self.valueChanged) self.label = QLabel(self) self.label.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.label.setAlignment(Qt.AlignCenter) fm = QFontMetricsF(self.font()) self.label.setMinimumWidth(fm.width(" 999 l/s ")) self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) self.setMinimumSize(self.minimumSizeHint()) self.valueChanged() def valueChanged(self): a = self.leftSpinBox.value() b = self.rightSpinBox.value() self.label.setText("{0}".format(a + b)) self.emit(SIGNAL("valueChanged"), a, b) self.update() def values(self): return self.leftSpinBox.value(), self.rightSpinBox.value() def minimumSizeHint(self): return QSize(self.leftSpinBox.width() * 3, self.leftSpinBox.height()) def resizeEvent(self, event = None): fm = QFontMetricsF(self.font()) x = (self.width() - self.label.width()) / 2 y = self.height() - (fm.height() * 1.5) self.label.move(x, y) y = self.height() / 60.0 x = (self.width() / 4.0) - self.leftSpinBox.width() self.leftSpinBox.move(x, y) x = self.width() - (self.width() / 4.0) self.rightSpinBox.move(x, y) def paintEvent(self, event = None): LogicalSize = 100.0 def logicalFromPhysical(length, side): return (length / side) * LogicalSize fm = QFontMetricsF(self.font()) ymargin = ((LogicalSize / 30.0) + logicalFromPhysical(self.leftSpinBox.height(), self.height())) ymax = (LogicalSize - logicalFromPhysical(fm.height() * 2, self.height())) width = LogicalSize / 4.0 cx, cy = LogicalSize / 2.0, LogicalSize / 3.0 ax, ay = cx - (2 * width), ymargin bx, by = cx - width, ay dx, dy = cx + width, ay ex, ey = cx + (2 * width), ymargin fx, fy = cx + (width / 2), cx + (LogicalSize / 24.0) gx, gy = fx, ymax hx, hy = cx - (width / 2), ymax ix, iy = hx, fy painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) side = min(self.width(), self.height()) painter.setViewport((self.width() - side) / 2, (self.height() - side) / 2, side, side) painter.setWindow(0, 0, LogicalSize, LogicalSize) painter.setPen(Qt.NoPen) gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100)) gradient.setColorAt(0, Qt.white) a = self.leftSpinBox.value() gradient.setColorAt(1, (Qt.red if a != 0 else Qt.white)) painter.setBrush(QBrush(gradient)) painter.drawPolygon(QPolygon([ax, ay, bx, by, cx, cy, ix, iy])) gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100)) gradient.setColorAt(0, Qt.white) b = self.rightSpinBox.value() gradient.setColorAt(1, (Qt.blue if b != 0 else Qt.white)) painter.setBrush(QBrush(gradient)) painter.drawPolygon(QPolygon([cx, cy, dx, dy, ex, ey, fx, fy])) if (a + b) == 0: color = QColor(Qt.white) else: ashare = (a / (a + b)) * 255.0 bshare = 255.0 - ashare color = QColor(ashare, 0, bshare) gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100)) gradient.setColorAt(0, Qt.white) gradient.setColorAt(1, color) painter.setBrush(QBrush(gradient)) painter.drawPolygon(QPolygon([cx, cy, fx, fy, gx, gy, hx, hy, ix, iy])) painter.setPen(Qt.black) painter.drawPolyline(QPolygon([ax, ay, ix, iy, hx, hy])) painter.drawPolyline(QPolygon([gx, gy, fx, fy, ex, ey])) painter.drawPolyline(QPolygon([bx, by, cx, cy, dx, dy]))
class EditorConfiguration(QWidget): def __init__(self, parent): super(EditorConfiguration, self).__init__() self._preferences = parent vbox = QVBoxLayout(self) #Indentation groupBoxFeatures = QGroupBox( translations.TR_PREFERENCES_EDITOR_CONFIG_FEATURES) formFeatures = QGridLayout(groupBoxFeatures) formFeatures.addWidget(QLabel( translations.TR_PREFERENCES_EDITOR_CONFIG_INDENTATION), 1, 0, Qt.AlignRight) self._spin = QSpinBox() self._spin.setAlignment(Qt.AlignRight) self._spin.setMinimum(1) self._spin.setValue(settings.INDENT) formFeatures.addWidget(self._spin, 1, 1, alignment=Qt.AlignTop) self._checkUseTabs = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_USE_TABS) self._checkUseTabs.setChecked(settings.USE_TABS) self.connect(self._checkUseTabs, SIGNAL("stateChanged(int)"), self._change_tab_spaces) formFeatures.addWidget(self._checkUseTabs, 1, 2, alignment=Qt.AlignTop) if settings.USE_TABS: self._spin.setSuffix( translations.TR_PREFERENCES_EDITOR_CONFIG_TAB_SIZE) else: self._spin.setSuffix( translations.TR_PREFERENCES_EDITOR_CONFIG_SPACES) #Margin Line formFeatures.addWidget(QLabel( translations.TR_PREFERENCES_EDITOR_CONFIG_MARGIN_LINE), 2, 0, Qt.AlignRight) self._spinMargin = QSpinBox() self._spinMargin.setMaximum(200) self._spinMargin.setValue(settings.MARGIN_LINE) formFeatures.addWidget(self._spinMargin, 2, 1, alignment=Qt.AlignTop) self._checkShowMargin = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_MARGIN_LINE) self._checkShowMargin.setChecked(settings.SHOW_MARGIN_LINE) formFeatures.addWidget(self._checkShowMargin, 2, 2, alignment=Qt.AlignTop) #End of line self._checkEndOfLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_END_OF_LINE) self._checkEndOfLine.setChecked(settings.USE_PLATFORM_END_OF_LINE) formFeatures.addWidget(self._checkEndOfLine, 3, 1, alignment=Qt.AlignTop) #Find Errors self._checkHighlightLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_ERROR_HIGHLIGHTING) self._checkHighlightLine.setChecked(settings.UNDERLINE_NOT_BACKGROUND) formFeatures.addWidget(self._checkHighlightLine, 4, 1, 1, 2, alignment=Qt.AlignTop) self._checkErrors = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_FIND_ERRORS) self._checkErrors.setChecked(settings.FIND_ERRORS) formFeatures.addWidget(self._checkErrors, 5, 1, 1, 2, alignment=Qt.AlignTop) self.connect(self._checkErrors, SIGNAL("stateChanged(int)"), self._disable_show_errors) self._showErrorsOnLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TOOLTIP_ERRORS) self._showErrorsOnLine.setChecked(settings.ERRORS_HIGHLIGHT_LINE) self.connect(self._showErrorsOnLine, SIGNAL("stateChanged(int)"), self._enable_errors_inline) formFeatures.addWidget(self._showErrorsOnLine, 6, 2, 1, 1, Qt.AlignTop) #Find Check Style self._checkStyle = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_PEP8) self._checkStyle.setChecked(settings.CHECK_STYLE) formFeatures.addWidget(self._checkStyle, 7, 1, 1, 2, alignment=Qt.AlignTop) self.connect(self._checkStyle, SIGNAL("stateChanged(int)"), self._disable_check_style) self._checkStyleOnLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TOOLTIP_PEP8) self._checkStyleOnLine.setChecked(settings.CHECK_HIGHLIGHT_LINE) self.connect(self._checkStyleOnLine, SIGNAL("stateChanged(int)"), self._enable_check_inline) formFeatures.addWidget(self._checkStyleOnLine, 8, 2, 1, 1, Qt.AlignTop) # Python3 Migration self._showMigrationTips = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_MIGRATION) self._showMigrationTips.setChecked(settings.SHOW_MIGRATION_TIPS) formFeatures.addWidget(self._showMigrationTips, 9, 1, 1, 2, Qt.AlignTop) #Center On Scroll self._checkCenterScroll = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_CENTER_SCROLL) self._checkCenterScroll.setChecked(settings.CENTER_ON_SCROLL) formFeatures.addWidget(self._checkCenterScroll, 10, 1, 1, 2, alignment=Qt.AlignTop) #Remove Trailing Spaces add Last empty line automatically self._checkTrailing = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_REMOVE_TRAILING) self._checkTrailing.setChecked(settings.REMOVE_TRAILING_SPACES) formFeatures.addWidget(self._checkTrailing, 11, 1, 1, 2, alignment=Qt.AlignTop) #Show Tabs and Spaces self._checkShowSpaces = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TABS_AND_SPACES) self._checkShowSpaces.setChecked(settings.SHOW_TABS_AND_SPACES) formFeatures.addWidget(self._checkShowSpaces, 12, 1, 1, 2, alignment=Qt.AlignTop) self._allowWordWrap = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_WORD_WRAP) self._allowWordWrap.setChecked(settings.ALLOW_WORD_WRAP) formFeatures.addWidget(self._allowWordWrap, 13, 1, 1, 2, alignment=Qt.AlignTop) self._checkForDocstrings = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_CHECK_FOR_DOCSTRINGS) self._checkForDocstrings.setChecked(settings.CHECK_FOR_DOCSTRINGS) formFeatures.addWidget(self._checkForDocstrings, 14, 1, 1, 2, alignment=Qt.AlignTop) vbox.addWidget(groupBoxFeatures) vbox.addItem(QSpacerItem(0, 10, QSizePolicy.Expanding, QSizePolicy.Expanding)) self.connect(self._preferences, SIGNAL("savePreferences()"), self.save) def _enable_check_inline(self, val): if val == Qt.Checked: self._checkStyle.setChecked(True) def _enable_errors_inline(self, val): if val == Qt.Checked: self._checkErrors.setChecked(True) def _disable_check_style(self, val): if val == Qt.Unchecked: self._checkStyleOnLine.setChecked(False) def _disable_show_errors(self, val): if val == Qt.Unchecked: self._showErrorsOnLine.setChecked(False) def _change_tab_spaces(self, val): if val == Qt.Unchecked: self._spin.setSuffix( translations.TR_PREFERENCES_EDITOR_CONFIG_SPACES) else: self._spin.setSuffix( translations.TR_PREFERENCES_EDITOR_CONFIG_TAB_SIZE) def save(self): qsettings = IDE.ninja_settings() qsettings.setValue('preferences/editor/indent', self._spin.value()) settings.INDENT = self._spin.value() endOfLine = self._checkEndOfLine.isChecked() qsettings.setValue('preferences/editor/platformEndOfLine', endOfLine) settings.USE_PLATFORM_END_OF_LINE = endOfLine margin_line = self._spinMargin.value() qsettings.setValue('preferences/editor/marginLine', margin_line) settings.MARGIN_LINE = margin_line settings.pep8mod_update_margin_line_length(margin_line) qsettings.setValue('preferences/editor/showMarginLine', self._checkShowMargin.isChecked()) settings.SHOW_MARGIN_LINE = self._checkShowMargin.isChecked() settings.UNDERLINE_NOT_BACKGROUND = \ self._checkHighlightLine.isChecked() qsettings.setValue('preferences/editor/errorsUnderlineBackground', settings.UNDERLINE_NOT_BACKGROUND) qsettings.setValue('preferences/editor/errors', self._checkErrors.isChecked()) settings.FIND_ERRORS = self._checkErrors.isChecked() qsettings.setValue('preferences/editor/errorsInLine', self._showErrorsOnLine.isChecked()) settings.ERRORS_HIGHLIGHT_LINE = self._showErrorsOnLine.isChecked() qsettings.setValue('preferences/editor/checkStyle', self._checkStyle.isChecked()) settings.CHECK_STYLE = self._checkStyle.isChecked() qsettings.setValue('preferences/editor/showMigrationTips', self._showMigrationTips.isChecked()) settings.SHOW_MIGRATION_TIPS = self._showMigrationTips.isChecked() qsettings.setValue('preferences/editor/checkStyleInline', self._checkStyleOnLine.isChecked()) settings.CHECK_HIGHLIGHT_LINE = self._checkStyleOnLine.isChecked() qsettings.setValue('preferences/editor/centerOnScroll', self._checkCenterScroll.isChecked()) settings.CENTER_ON_SCROLL = self._checkCenterScroll.isChecked() qsettings.setValue('preferences/editor/removeTrailingSpaces', self._checkTrailing.isChecked()) settings.REMOVE_TRAILING_SPACES = self._checkTrailing.isChecked() qsettings.setValue('preferences/editor/showTabsAndSpaces', self._checkShowSpaces.isChecked()) settings.SHOW_TABS_AND_SPACES = self._checkShowSpaces.isChecked() qsettings.setValue('preferences/editor/useTabs', self._checkUseTabs.isChecked()) settings.USE_TABS = self._checkUseTabs.isChecked() qsettings.setValue('preferences/editor/allowWordWrap', self._allowWordWrap.isChecked()) settings.ALLOW_WORD_WRAP = self._allowWordWrap.isChecked() qsettings.setValue('preferences/editor/checkForDocstrings', self._checkForDocstrings.isChecked()) settings.CHECK_FOR_DOCSTRINGS = self._checkForDocstrings.isChecked()
class CNSViewerWidget(QWidget): def __init__(self, path_to_df=None, df=None, *args, **kwargs): super().__init__(*args, **kwargs) #Apply QThreading to this step for larger cns files. if df is None: self.df = read_cns(path_to_df) else: self.df = df self.orig_df = self.df.copy() #Make copy. # self.df.reset_index(inplace=True) self.max_rows = 10 self.render_ui() self.map_events() self.refresh() self.jupyter_notebook_widget.pushVariables({ "df": self.df, "orig_df": self.orig_df, "viewer": self.df_widget, "refresh": self.refresh, "display": self.display }) def display(self, obj): try: html = obj._repr_html_() except: html = str(obj) self.df_widget.setHtml(html) def render_ui(self): """Builds the UI""" self.tab_widget = QTabWidget() #Filter Ops tab self.filter_ops_widget = CNSFilterOpsWidget(columns=self.df.columns) commands_widget = QWidget() self.command_label = QLabel("Command:") self.command_text_area = LNTextEdit() self.command_text_area.edit.setReadOnly(True) self.command_show_button = QPushButton("Apply") self.command_editable_checkbox = QCheckBox("Editable") self.command_editable_checkbox.setChecked(False) commands_widget_layout = QGridLayout() commands_widget_layout.addWidget(self.filter_ops_widget, 0, 0, 2, 2, Qt.AlignTop) commands_widget_layout.addWidget(self.command_label, 2, 0, 1, 1, Qt.AlignLeft | Qt.AlignTop) commands_widget_layout.addWidget(self.command_text_area, 3, 0, 2, 2, Qt.AlignTop) commands_widget_layout.addWidget(self.command_editable_checkbox, 5, 0, 1, 0, Qt.AlignLeft) commands_widget_layout.addWidget(self.command_show_button, 5, 1, 1, 1, Qt.AlignRight) commands_widget.setLayout(commands_widget_layout) # self.tab_widget.addTab(self.filter_ops_widget, "n00b Mode") #Commands Tab self.tab_widget.addTab(commands_widget, "Raw Commands") ipython_filter_widget = QWidget() self.jupyter_notebook_widget = QIPythonWidget() ipython_filter_widget_layout = QVBoxLayout() ipython_filter_widget_layout.addWidget(self.jupyter_notebook_widget) ipython_filter_widget.setLayout(ipython_filter_widget_layout) self.tab_widget.addTab(ipython_filter_widget, "Jupyter Mode") self.view_combobox = QComboBox() modes = ["Show First", "Show Last", "All", "Describe", "Filtered"] for mode in modes: self.view_combobox.addItem(mode) self.max_rows_spinbox = QSpinBox() #Map the change event to refresh the dataframe. self.max_rows_spinbox.setMinimum(0) self.max_rows_spinbox.setMaximum(self.df.shape[0]) self.max_rows_spinbox.setValue(self.max_rows) self.max_rows_spinbox.setSuffix(" rows") self.refresh_button = QPushButton("Refresh") self.df_widget = QTextEdit() self.df_widget.setReadOnly(True) self.save_button = QPushButton("Save File") df_layout = QGridLayout() df_layout.addWidget(self.view_combobox, 0, 0) df_layout.addWidget(self.max_rows_spinbox, 0, 1) df_layout.addWidget(self.refresh_button, 0, 2) df_layout.addWidget(self.df_widget, 1, 0, 4, 10) layout = QGridLayout() layout.addWidget(self.tab_widget, 0, 0, 3, 1, Qt.AlignLeft | Qt.AlignTop) layout.addLayout(df_layout, 0, 1, 7, 7) layout.addWidget(self.save_button, 3, 0, 1, 1, Qt.AlignLeft) self.setLayout(layout) def map_events(self): self.refresh_button.clicked.connect(self.refresh) self.view_combobox.currentIndexChanged.connect(self.toggle_max_rows) self.command_show_button.clicked.connect(self.exec_command) self.filter_ops_widget.add_signal.connect(self.add_filter_op) self.command_editable_checkbox.stateChanged.connect( self.toggle_command_area) def toggle_command_area(self): self.command_text_area.edit.setReadOnly(not ( self.command_editable_checkbox.isChecked())) def add_filter_op(self): command = self.filter_ops_widget.get_command_string() existing_commands = str( self.command_text_area.edit.toPlainText()).strip() if existing_commands != "": command = "\n{}".format(command) self.command_text_area.edit.appendPlainText(command) self.filter_ops_widget.reset() def exec_command(self): #Reset df to original. self.df = self.orig_df.copy() command = str(self.command_text_area.getText()) try: exec(command) except Exception as e: print("Failed to execute!") print(repr(e)) self.view_combobox.setCurrentIndex(4) self.refresh() def toggle_max_rows(self): mode = str(self.view_combobox.currentText()).lower() if mode in ["show first", "show last"]: self.max_rows_spinbox.setEnabled(True) else: self.max_rows_spinbox.setEnabled(False) def refresh(self): mode = str(self.view_combobox.currentText()).lower() if mode == "show first": self.max_rows = self.max_rows_spinbox.value() self.df_widget.setHtml(self.df.head(n=self.max_rows)._repr_html_()) elif mode == "show last": self.max_rows = self.max_rows_spinbox.value() self.df_widget.setHtml(self.df.tail(n=self.max_rows)._repr_html_()) elif mode == "describe": self.df_widget.setHtml(self.df.describe()._repr_html_()) elif mode == "filtered": self.df_widget.setHtml(self.df._repr_html_()) else: self.df_widget.setHtml(self.df._repr_html_())
class TabLaTeX(Panel_simple): titre = u"Tableaux LaTeX" # Donner un titre a chaque module def __init__(self, *args, **kw): Panel_simple.__init__(self, *args, **kw) self.sizer = QVBoxLayout() self.entree = LigneCommande(self, longueur = 500, action = self.generer_code) self.sizer.addWidget(self.entree) self.sizer_type = QHBoxLayout() self.type_tableau = QComboBox(self) self.type_tableau.addItems([u"Tableau de variations", u"Tableau de signes", u"Tableau de valeurs"]) self.type_tableau.setCurrentIndex(self._param_.mode) self.sizer_type.addWidget(QLabel(u"Type de tableau :", self)) self.sizer_type.addWidget(self.type_tableau) self.sizer_type.addSpacing(15) self.utiliser_cellspace = QCheckBox(u"Utiliser le paquetage cellspace.", self) self.utiliser_cellspace.setChecked(self._param_.utiliser_cellspace) self.utiliser_cellspace.setToolTip(u"Le paquetage cellspace évite que " "certains objets (comme les fractions) touchent les bordures du tableaux.") self.sizer_type.addSpacing(10) self.sizer_type.addWidget(self.utiliser_cellspace) self.derivee = QCheckBox(u"Dérivée.", self) self.derivee.setChecked(self._param_.derivee) self.derivee.setToolTip(u"Afficher une ligne indiquant le signe de la dérivée.") self.sizer_type.addSpacing(10) self.sizer_type.addWidget(self.derivee) self.limites = QCheckBox(u"Limites.", self) self.limites.setChecked(self._param_.limites) self.limites.setToolTip(u"Afficher les limites dans le tableau de variations.") self.sizer_type.addSpacing(10) self.sizer_type.addWidget(self.limites) self.decimales_tabvar = QSpinBox() self.decimales_tabvar.setRange(-1, 20) self.decimales_tabvar.setSuffix(u" décimales") self.decimales_tabvar.setSpecialValueText(u"Valeurs exactes") self.decimales_tabvar.setValue(self._param_.decimales_tabvar) ##self.decimales_tabvar.setAccelerated(True) aide = u"Nombre de décimales pour l'affichage des extrema, ou valeur exacte." self.decimales_tabvar.setToolTip(aide) self.sizer_type.addSpacing(10) self.sizer_type.addWidget(self.decimales_tabvar) self.decimales_tabval = QSpinBox() self.decimales_tabval.setRange(0, 20) self.decimales_tabval.setSuffix(u" décimales") self.decimales_tabval.setValue(self._param_.decimales_tabval) ##self.decimales_tabval.setAccelerated(True) aide = u"Nombre de décimales pour les valeurs du tableau." self.decimales_tabval.setToolTip(aide) self.sizer_type.addSpacing(10) self.sizer_type.addWidget(self.decimales_tabval) self.sizer_type.addSpacing(15) self.lbl_formatage = lbl = QLabel(u"Formatage des résultats :") self.sizer_type.addWidget(lbl) self.formatage_images = QLineEdit() ##self.formatage_images.setMinimumWidth(200) self.formatage_images.setText(self._param_.formatage_images) aide = u"Formatage à appliquer au résultat (VAL est la valeur du résultat)." lbl.setToolTip(aide) self.formatage_images.setToolTip(aide) self.sizer_type.addSpacing(10) self.sizer_type.addWidget(self.formatage_images) self.sizer_type.addStretch() self.sizer.addLayout(self.sizer_type) box = QGroupBox(u"Code LaTeX permettant de de générer le tableau", self) self.bsizer = QVBoxLayout() box.setLayout(self.bsizer) self.code_tableau = QTextEdit(self) self.code_tableau.setMinimumSize(700, 200) self.code_tableau.setReadOnly(True) self.bsizer.addWidget(self.code_tableau) self.copier_code = QPushButton(u"Copier dans le presse-papier", self) self.bsizer.addWidget(self.copier_code) txt = u"Pensez à rajouter dans l'entête de votre fichier LaTeX la ligne suivante :" self.bsizer.addWidget(QLabel(txt, self)) self.sizer_entete = QHBoxLayout() self.code_entete = QLineEdit(self) self.code_entete.setMinimumWidth(200) self.code_entete.setReadOnly(True) self.code_entete.setText(u"\\usepackage{tabvar}") self.sizer_entete.addWidget(self.code_entete) self.copier_entete = QPushButton(u"Copier cette ligne", self) self.sizer_entete.addWidget(self.copier_entete) self.bsizer.addLayout(self.sizer_entete) self.sizer.addWidget(box) self.cb = QCheckBox(u"Copier automatiquement le code LaTeX dans le presse-papier.", self) self.cb.setChecked(self._param_.copie_automatique) self.sizer.addWidget(self.cb) self.setLayout(self.sizer) self.adjustSize() self.type_tableau.currentIndexChanged.connect(self.EvtChoix) self.EvtChoix() def copier_code(): return self.vers_presse_papier(self.code_tableau.toPlainText()) self.copier_code.clicked.connect(copier_code) def copier_entete(): return self.vers_presse_papier(self.code_entete.text()) self.copier_entete.clicked.connect(copier_entete) def regler_mode_copie(): self._param_.copie_automatique = self.cb.isChecked() if self._param_.copie_automatique: copier_code() self.cb.stateChanged.connect(regler_mode_copie) def regler_cellspace(): self._param_.utiliser_cellspace = self.utiliser_cellspace.isChecked() if self._param_.utiliser_cellspace: self.code_entete.setText(u"\\usepackage{cellspace}") else: self.code_entete.setText(u"") self.valider() self.utiliser_cellspace.stateChanged.connect(regler_cellspace) def regler_parametres(event=None): self._param_.derivee = self.derivee.isChecked() self._param_.limites = self.limites.isChecked() self._param_.formatage_images = self.formatage_images.text() self.valider() def regler_decimales(event=None): try: self.focus_widget = app.focusWidget() self._param_.decimales_tabvar = self.decimales_tabvar.value() self._param_.decimales_tabval = self.decimales_tabval.value() self.valider() finally: self.focus_widget = self.entree self.derivee.stateChanged.connect(regler_parametres) self.limites.stateChanged.connect(regler_parametres) self.formatage_images.editingFinished.connect(regler_parametres) self.decimales_tabvar.valueChanged.connect(regler_decimales) self.decimales_tabval.valueChanged.connect(regler_decimales) self.focus_widget = self.entree def activer(self): Panel_simple.activer(self) # Actions à effectuer lorsque l'onglet devient actif self.entree.setFocus() def generer_code(self, commande, **kw): if not commande.strip(): return # Utilisé pour la sauvegarde automatique:x+3 self.modifie = True try: if self._param_.mode == 0: code_latex = tabvar(commande, derivee=self._param_.derivee, limites=self._param_.limites, decimales=self._param_.decimales_tabvar, approche=(self._param_.decimales_tabvar != -1)) elif self._param_.mode == 1: code_latex = tabsign(commande, cellspace=self._param_.utiliser_cellspace) elif self._param_.mode == 2: code_latex = tabval(commande, formatage_antecedents=self._param_.formatage_antecedents, formatage_images=self._param_.formatage_images, precision=10**-self._param_.decimales_tabval) else: warning("Type de tableau non reconnu.") self.code_tableau.setText(code_latex) if self._param_.copie_automatique: self.vers_presse_papier(texte = code_latex) self.focus_widget.setFocus() self.message(u"Le code LaTeX a bien été généré.") except BaseException, erreur: self.message(u"Impossible de générer le code LaTeX. " + message(erreur)) self.code_tableau.setText(u"<i><b>Erreur.</b> Impossible de générer le code LaTeX.</i>") self.entree.setFocus() if param.debug: raise
def initSettingTab(self): # ##Setting Tab### setting_tab = QWidget() setting_tab_layout = QVBoxLayout() self.tabWidget.addTab(setting_tab, "Settings") # Task Box task_box = QGroupBox() task_box.setTitle(QString("Task properties")) task_layout = QGridLayout() # Name name = QLabel("Name:") name_value = QLineEdit() name_value.setText(self.task.hittypename) name_value.setEnabled(False) clickable(name_value).connect(self.enable) task_layout.addWidget(name, 0, 1) task_layout.addWidget(name_value, 0, 2, 1, 3) # Description description = QLabel("Description:") description_value = QLineEdit() description_value.setText(self.task.description) description_value.setEnabled(False) clickable(description_value).connect(self.enable) task_layout.addWidget(description, 1, 1) task_layout.addWidget(description_value, 1, 2, 1, 3) # Keywords keywords = QLabel("Keywords:") keywords_value = QLineEdit() keywords_value.setText(','.join(self.task.keywords)) keywords_value.setEnabled(False) clickable(keywords_value).connect(self.enable) task_layout.addWidget(keywords, 2, 1) task_layout.addWidget(keywords_value, 2, 2, 1, 3) # Qualification qualification = QLabel("Qualification [%]:") qualification_value = QSpinBox() qualification_value.setSuffix('%') qualification_value.setValue(int(self.task.qualification)) qualification_value.setEnabled(False) clickable(qualification_value).connect(self.enable) task_layout.addWidget(qualification, 3, 1) task_layout.addWidget(qualification_value, 3, 4) # Assignments assignments = QLabel("Assignments:") assignments_value = QSpinBox() assignments_value.setSuffix('') assignments_value.setValue(int(self.task.assignments)) assignments_value.setEnabled(False) clickable(assignments_value).connect(self.enable) task_layout.addWidget(assignments, 4, 1) task_layout.addWidget(assignments_value, 4, 4) # Duration duration = QLabel("Duration [min]:") duration_value = QSpinBox() duration_value.setSuffix('min') duration_value.setValue(int(self.task.duration)) duration_value.setEnabled(False) clickable(duration_value).connect(self.enable) task_layout.addWidget(duration, 5, 1) task_layout.addWidget(duration_value, 5, 4) # Reward reward = QLabel("Reward [0.01$]:") reward_value = QDoubleSpinBox() reward_value.setRange(0.01, 0.5) reward_value.setSingleStep(0.01) reward_value.setSuffix('$') reward_value.setValue(self.task.reward) reward_value.setEnabled(False) clickable(reward_value).connect(self.enable) task_layout.addWidget(reward, 6, 1) task_layout.addWidget(reward_value, 6, 4) # Lifetime lifetime = QLabel("Lifetime [d]:") lifetime_value = QSpinBox() lifetime_value.setSuffix('d') lifetime_value.setValue(self.task.lifetime) lifetime_value.setEnabled(False) clickable(lifetime_value).connect(self.enable) task_layout.addWidget(lifetime, 7, 1) task_layout.addWidget(lifetime_value, 7, 4) # sandbox sandbox = QCheckBox("Sandbox") sandbox.setChecked(self.task.sandbox) task_layout.addWidget(sandbox, 8, 1) task_box.setLayout(task_layout) task_layout.setColumnMinimumWidth(1, 120) # Image Storage Box storage_box = QGroupBox() storage_box.setTitle(QString("Image Storage")) storage_layout = QGridLayout() # Host URL host_url = QLabel("Host-URL:") host_url_value = QLineEdit() host_url_value.setText(self.task.host_url) host_url_value.setEnabled(False) clickable(host_url_value).connect(self.enable) # Dropbox Path dropbox_path = QLabel("Dropbox-Path:") dropbox_path_value = QLineEdit() dropbox_path_value.setText(self.task.dropbox_path) dropbox_path_value.setEnabled(False) clickable(dropbox_path_value).connect(self.enable) # Dropbox or S3 usingS3 = QRadioButton("S3") usingS3.setChecked(self.task.usingS3) usingS3.setEnabled(False) usingDropbox = QRadioButton("Dropbox") usingDropbox.setChecked(self.task.usingDropbox) storage_layout.addWidget(host_url, 0, 1) storage_layout.addWidget(host_url_value, 0, 2, 1, 3) storage_layout.addWidget(dropbox_path, 1, 1) storage_layout.addWidget(dropbox_path_value, 1, 2, 1, 3) # Add Layouts save_button = QPushButton("Save Settings") setting_tab_layout.addWidget(task_box) setting_tab_layout.addWidget(storage_box) setting_tab.setLayout(setting_tab_layout) save_button.clicked.connect(self.SaveSettings) storage_layout.addWidget(usingS3, 2, 1) storage_layout.addWidget(usingDropbox, 3, 1) storage_layout.addWidget(save_button, 3, 4) # storage_layout.addStretch(1) storage_box.setLayout(storage_layout)
class MusicView(preferences.Group): def __init__(self, page): super(MusicView, self).__init__(page) layout = QGridLayout() self.setLayout(layout) self.newerFilesOnly = QCheckBox(toggled=self.changed) layout.addWidget(self.newerFilesOnly, 0, 0, 1, 3) self.magnifierSizeLabel = QLabel() self.magnifierSizeSlider = QSlider(Qt.Horizontal, valueChanged=self.changed) self.magnifierSizeSlider.setSingleStep(50) self.magnifierSizeSlider.setRange( *popplerview.MagnifierSettings.sizeRange) self.magnifierSizeSpinBox = QSpinBox() self.magnifierSizeSpinBox.setRange( *popplerview.MagnifierSettings.sizeRange) self.magnifierSizeSpinBox.valueChanged.connect( self.magnifierSizeSlider.setValue) self.magnifierSizeSlider.valueChanged.connect( self.magnifierSizeSpinBox.setValue) layout.addWidget(self.magnifierSizeLabel, 1, 0) layout.addWidget(self.magnifierSizeSlider, 1, 1) layout.addWidget(self.magnifierSizeSpinBox, 1, 2) self.magnifierScaleLabel = QLabel() self.magnifierScaleSlider = QSlider(Qt.Horizontal, valueChanged=self.changed) self.magnifierScaleSlider.setSingleStep(50) self.magnifierScaleSlider.setRange( *popplerview.MagnifierSettings.scaleRange) self.magnifierScaleSpinBox = QSpinBox() self.magnifierScaleSpinBox.setRange( *popplerview.MagnifierSettings.scaleRange) self.magnifierScaleSpinBox.valueChanged.connect( self.magnifierScaleSlider.setValue) self.magnifierScaleSlider.valueChanged.connect( self.magnifierScaleSpinBox.setValue) layout.addWidget(self.magnifierScaleLabel, 2, 0) layout.addWidget(self.magnifierScaleSlider, 2, 1) layout.addWidget(self.magnifierScaleSpinBox, 2, 2) self.enableKineticScrolling = QCheckBox(toggled=self.changed) layout.addWidget(self.enableKineticScrolling) self.showScrollbars = QCheckBox(toggled=self.changed) layout.addWidget(self.showScrollbars) app.translateUI(self) def translateUI(self): self.setTitle(_("Music View")) self.newerFilesOnly.setText(_("Only load updated PDF documents")) self.newerFilesOnly.setToolTip( _("If checked, Frescobaldi will not open PDF documents that are not\n" "up-to-date (i.e. the source file has been modified later).")) self.magnifierSizeLabel.setText(_("Magnifier Size:")) self.magnifierSizeLabel.setToolTip( _("Size of the magnifier glass (Ctrl+Click in the Music View).")) # L10N: as in "400 pixels", appended after number in spinbox, note the leading space self.magnifierSizeSpinBox.setSuffix(_(" pixels")) self.magnifierScaleLabel.setText(_("Magnifier Scale:")) self.magnifierScaleLabel.setToolTip( _("Magnification of the magnifier.")) self.magnifierScaleSpinBox.setSuffix(_("percent unit sign", "%")) # L10N: "Kinetic Scrolling" is a checkbox label, as in "Enable Kinetic Scrolling" self.enableKineticScrolling.setText(_("Kinetic Scrolling")) self.showScrollbars.setText(_("Show Scrollbars")) def loadSettings(self): s = popplerview.MagnifierSettings.load() self.magnifierSizeSlider.setValue(s.size) self.magnifierScaleSlider.setValue(s.scale) s = QSettings() s.beginGroup("musicview") newerFilesOnly = s.value("newer_files_only", True, bool) self.newerFilesOnly.setChecked(newerFilesOnly) kineticScrollingActive = s.value("kinetic_scrolling", True, bool) self.enableKineticScrolling.setChecked(kineticScrollingActive) showScrollbars = s.value("show_scrollbars", True, bool) self.showScrollbars.setChecked(showScrollbars) def saveSettings(self): s = popplerview.MagnifierSettings() s.size = self.magnifierSizeSlider.value() s.scale = self.magnifierScaleSlider.value() s.save() s = QSettings() s.beginGroup("musicview") s.setValue("newer_files_only", self.newerFilesOnly.isChecked()) s.setValue("kinetic_scrolling", self.enableKineticScrolling.isChecked()) s.setValue("show_scrollbars", self.showScrollbars.isChecked())
def initGui(): def setData(): buttonPath.setText(self.data["path"]) radioVisual.setChecked(self.data["isVisual"]) radioAnalytic.setChecked(not self.data["isVisual"]) chkBoxSquare.setChecked(self.data["isSquare"]) d1 = self.data["date1"] d2 = self.data["date2"] date1.setDate(d1) date2.setDate(d2) date1.setMaximumDate(d2.addDays(-1)) date2.setMinimumDate(d1.addDays(+1)) spinDay.setValue(d1.daysTo(d2)) def connect(): buttonOK.clicked.connect(self.onOK) buttonPath.clicked.connect(self.onPath) date1.dateChanged.connect(self.onDateChanged1) date2.dateChanged.connect(self.onDateChanged2) spinDay.valueChanged.connect(self.onValueChanged) windowTitle = "Setting download images Planet Labs" self.setWindowTitle(windowTitle) self.setWindowIcon(icon) grpImage = QGroupBox("Images", self) radioVisual = QRadioButton("Visual", grpImage) radioVisual.setObjectName("rbVisual") radioAnalytic = QRadioButton("Analytic", grpImage) chkBoxSquare = QCheckBox("Square thumbnail", grpImage) chkBoxSquare.setObjectName("cbBoxSquare") buttonPath = QPushButton(self.titleSelectDirectory, grpImage) buttonPath.setObjectName("pbPath") layoutRadioButtons = QHBoxLayout() for item in (radioVisual, radioAnalytic): layoutRadioButtons.addWidget(item) layoutImage = QVBoxLayout(grpImage) layoutImage.addLayout(layoutRadioButtons) layoutImage.addWidget(chkBoxSquare) layoutImage.addWidget(buttonPath) grpDateSearch = QGroupBox("Dates for search", self) date1 = QDateEdit(grpDateSearch) date1.setObjectName("deDate1") date2 = QDateEdit(grpDateSearch) date2.setObjectName("deDate2") for item in [date1, date2]: item.setCalendarPopup(True) format = item.displayFormat().replace("yy", "yyyy") item.setDisplayFormat(format) spinDay = QSpinBox(grpDateSearch) spinDay.setObjectName("sbDay") spinDay.setSingleStep(1) spinDay.setSuffix(" Days") spinDay.setRange(1, 1000 * 360) layoutDate = QHBoxLayout(grpDateSearch) layoutDate.addWidget(QLabel("From", grpDateSearch)) layoutDate.addWidget(date1) layoutDate.addWidget(QLabel("To", grpDateSearch)) layoutDate.addWidget(date2) layoutDate.addWidget(spinDay) buttonOK = QPushButton("OK", self) layout = QVBoxLayout(self) layout.addWidget(grpImage) layout.addWidget(grpDateSearch) layout.addWidget(buttonOK) self.resize(5 * len(windowTitle) + 200, 30) if not self.data is None: setData() else: radioVisual.setChecked(True) radioAnalytic.setChecked(False) chkBoxSquare.setChecked(False) d2 = QDate.currentDate() d1 = d2.addMonths(-1) date1.setDate(d1) date2.setDate(d2) date1.setMaximumDate(d2.addDays(-1)) date2.setMinimumDate(d1.addDays(+1)) spinDay.setValue(d1.daysTo(d2)) connect()
class ProjectXively(QWidget): qtcb_update_illuminance = pyqtSignal(float) qtcb_update_air_pressure = pyqtSignal(float) qtcb_update_temperature = pyqtSignal(float) qtcb_update_humidity = pyqtSignal(float) qtcb_button_pressed = pyqtSignal(int) lcdwidget = None xively_host = "api.xively.com" xively_agent = "Tinkerforge Starter Kit Weather Station Demo" xively_channel = "Enter Feed ID here" xively_api_key = "Enter API Key here" xively_items = {} xively_headers = None xively_params = "" xively_update_rate = 5 # in minutes text_agent = None text_channel = None text_api_key = None number_update_rate = None save_button = None xively_timer = None error_message = None label_upload_active = None last_upload = None def __init__(self, parent, app): super(QWidget, self).__init__() self.lcdwidget = LCDWidget(self, app) self.lcdwidget.hide() self.text_agent = QLineEdit(self) self.text_agent.setText(self.xively_agent) self.text_channel = QLineEdit(self) self.text_channel.setText(self.xively_channel) self.text_api_key = QLineEdit(self) self.text_api_key.setText(self.xively_api_key) self.number_update_rate = QSpinBox(self) self.number_update_rate.setRange(1, 1440) self.number_update_rate.setSuffix(' min') self.number_update_rate.setValue(self.xively_update_rate) layout1 = QHBoxLayout() layout2 = QVBoxLayout() layout1.addStretch() layout1.addLayout(layout2) layout1.addStretch() layout2.addSpacerItem(QSpacerItem(LCDWidget.FIXED_WIDGTH, 0)) label = QLabel(self) label.setText("Project: <b>Connect to Xively</b>. This project uploads the measured values to Xively. Please find documentation how to configure it and program sources in Python <a href=\"http://www.tinkerforge.com/en/doc/Kits/WeatherStation/WeatherStation.html#connect-to-xively\">here</a>.<br>") label.setTextFormat(Qt.RichText) label.setTextInteractionFlags(Qt.TextBrowserInteraction) label.setOpenExternalLinks(True) label.setWordWrap(True) label.setAlignment(Qt.AlignJustify) layout2.addSpacing(10) layout2.addWidget(label) layout2.addSpacing(10) layout3a = QHBoxLayout() label = QLabel("Agent Description:") label.setMinimumWidth(150) layout3a.addWidget(label) layout3a.addWidget(self.text_agent, 1) layout2.addLayout(layout3a) layout2.addSpacing(10) layout3b = QHBoxLayout() label = QLabel("Feed:") label.setMinimumWidth(150) layout3b.addWidget(label) layout3b.addWidget(self.text_channel, 1) layout2.addLayout(layout3b) layout2.addSpacing(10) layout3c = QHBoxLayout() label = QLabel("API Key:") label.setMinimumWidth(150) layout3c.addWidget(label) layout3c.addWidget(self.text_api_key, 1) layout2.addLayout(layout3c) layout2.addSpacing(10) layout3d = QHBoxLayout() label = QLabel("Update Rate:") label.setMinimumWidth(150) layout3d.addWidget(label) layout3d.addWidget(self.number_update_rate, 1) layout2.addLayout(layout3d) layout2.addSpacing(10) self.label_upload_active = QLabel("Not Active", self) self.label_upload_active.setMinimumWidth(150) font = QFont() font.setPixelSize(20) self.label_upload_active.setFont(font) self.set_active_label(False) self.save_button = QPushButton("Save/Activate") layout4 = QHBoxLayout() layout4.addWidget(self.label_upload_active) layout4.addWidget(self.save_button, 1) layout2.addLayout(layout4) layout2.addStretch() self.setLayout(layout1) self.qtcb_update_illuminance.connect(self.update_illuminance_data_slot) self.qtcb_update_air_pressure.connect(self.update_air_pressure_data_slot) self.qtcb_update_temperature.connect(self.update_temperature_data_slot) self.qtcb_update_humidity.connect(self.update_humidity_data_slot) self.qtcb_button_pressed.connect(self.button_pressed_slot) self.save_button.clicked.connect(self.save_configuration) self.lcdwidget.clear(self) self.error_message = QErrorMessage(self) def set_active_label(self, value): palette = self.label_upload_active.palette() if value: palette.setColor(self.foregroundRole(), Qt.darkGreen) self.label_upload_active.setText("Active") else: palette.setColor(self.foregroundRole(), Qt.red) self.label_upload_active.setText("Not Active") self.label_upload_active.setPalette(palette) def save_configuration(self): try: self.xively_agent = str(self.text_agent.text()).decode('ascii') self.xively_channel = str(self.text_channel.text()).decode('ascii') self.xively_api_key = str(self.text_api_key.text()).decode('ascii') except: self.error_message.showMessage('Agent, Feed and API Key can only contain ASCII characters') return self.xively_update_rate = self.number_update_rate.value() self.xively_headers = { "Content-Type" : "application/x-www-form-urlencoded", "X-ApiKey" : self.xively_api_key, "User-Agent" : self.xively_agent, } self.xively_params = "/v2/feeds/" + self.xively_channel if self.xively_timer is None: self.xively_timer = QTimer(self) self.xively_timer.timeout.connect(self.update_xively) self.xively_timer.start(self.xively_update_rate*60*1000) self.set_active_label(True) self.update_xively() def write_lcd(self): if self.last_upload == None: tmp = "Last: Never" else: tmp = "Last: " + self.last_upload self.lcdwidget.write_line(0, 0, "Xively Upload", self) self.lcdwidget.write_line(2, 0, tmp, self) def update_xively(self): if len(self.xively_items) == 0: return stream_items = [] for identifier, value in self.xively_items.items(): stream_items.append({'id': identifier, 'current_value': value[0], 'min_value': value[1], 'max_value': value[2]}) data = {'version': '1.0.0', 'datastreams': stream_items} self.xively_items = {} body = json.dumps(data) try: http = httplib.HTTPSConnection(self.xively_host) http.request('PUT', self.xively_params, body, self.xively_headers) response = http.getresponse() http.close() if response.status != 200: self.error_message.showMessage('Could not upload to xively -> Response:' + str(response.status) + ': ' + response.reason + '. Check your configuration.') self.xively_timer.stop() self.xively_timer = None self.set_active_label(False) return except Exception as e: self.error_message.showMessage('HTTP error: ' + str(e)) self.xively_timer.stop() self.xively_timer = None self.set_active_label(False) return # set upload time if upload was a success self.last_upload = time.strftime("%H:%M:%S") def put(self, identifier, value): self.write_lcd() try: _, min_value, max_value = self.xively_items[identifier] if value < min_value: min_value = value if value > max_value: max_value = value self.xively_items[identifier] = (value, min_value, max_value) except: self.xively_items[identifier] = (value, value, value) def update_illuminance_data_slot(self, illuminance): self.put('AmbientLight', illuminance/10.0) def update_illuminance(self, illuminance): self.qtcb_update_illuminance.emit(illuminance) def update_humidity_data_slot(self, humidity): self.put('Humidity', humidity/10.0) def update_humidity(self, humidity): self.qtcb_update_humidity.emit(humidity) def update_air_pressure_data_slot(self, air_pressure): self.put('AirPressure', air_pressure/1000.0) def update_air_pressure(self, air_pressure): self.qtcb_update_air_pressure.emit(air_pressure) def update_temperature_data_slot(self, temperature): self.put('Temperature', temperature/100.0) def update_temperature(self, temperature): self.qtcb_update_temperature.emit(temperature) def button_pressed_slot(self, button): pass def button_pressed(self, button): self.qtcb_button_pressed.emit(button)
class ProprietesAffichage(QWidget): def __init__(self, parent): QWidget.__init__(self, parent) self.parent = parent self.panel = self.parent.parent.panel self.canvas = self.panel.canvas self.islabel = self.parent.parent.islabel self.objets = parent.objets self.sizer = QVBoxLayout() self.changements = {} # ce dictionnaire contiendra tous les styles modifiés encadre = QHBoxLayout() if not self.islabel: proprietes = {'fixe': u'Objet fixe', 'visible': u'Objet visible', 'trace': u'Laisser une trace'} for propriete, titre in proprietes.items(): self.add_checkbox(encadre, propriete, titre) encadre.addStretch() encadre1 = QVBoxLayout() if not self.islabel: ligne = QHBoxLayout() if len(self.objets) == 1: self.etiquette = etiquette = QLineEdit() etiquette.setText(self.objets[0].legende) etiquette.setMinimumWidth(200) etiquette.editingFinished.connect(self.EvtEtiquette) ligne.addWidget(etiquette) if [objet for objet in self.objets if objet.etiquette is not None]: editer = QPushButton(u"Style") editer.clicked.connect(self.EvtLabelStyle) ligne.addWidget(editer) encadre1.addLayout(ligne) objets = [objet for objet in self.objets if objet.mode_affichage is not None] if objets: mode = objets[0].mode_affichage legende = QHBoxLayout() self.radios = OrderedDict(( (NOM, QRadioButton("Nom")), (TEXTE, QRadioButton(u"Texte")), (FORMULE, QRadioButton(u"Formule")), (RIEN, QRadioButton(u"Aucun")), )) if all(objet.mode_affichage == mode for objet in objets): self.radios[mode].setChecked(True) for mode, radio in self.radios.iteritems(): radio.toggled.connect(partial(self.EvtMode, mode)) legende.addWidget(radio) legende.addStretch() encadre1.addWidget(QLabel(u"Afficher : ")) encadre1.addLayout(legende) encadre2 = QVBoxLayout() objets = [objet for objet in self.objets if objet.style("style") is not None] # on ne peut regler les styles simultanement que pour des objets de meme categorie categorie = objets and objets[0].style("categorie") or None if objets and categorie and all(objet.style("categorie") == categorie for objet in objets): choix = QHBoxLayout() choix.addWidget(QLabel(u"Style de l'objet : ")) #categorie = objets[0].style("categorie") or "lignes" self.liste_styles = getattr(param, "styles_de_" + categorie, []) self.style = QComboBox() self.style.addItems(self.liste_styles) self.style.currentIndexChanged.connect(self.EvtStyle) style = objets[0].style("style") if style in self.liste_styles and all(objet.style("style") == style for objet in objets): self.style.setCurrentIndex(self.liste_styles.index(style)) # on sélectionne le style actuel choix.addWidget(self.style) choix.addStretch() encadre2.addLayout(choix) objets = [objet for objet in self.objets if objet.style("hachures") is not None] if objets: choix = QHBoxLayout() choix.addWidget(QLabel(u"Style des hâchures : ")) self.types_de_hachures = getattr(param, "types_de_hachures", []) self.hachures = QComboBox() self.hachures.addItems(self.types_de_hachures) self.hachures.currentIndexChanged.connect(self.EvtHachures) hachures = objets[0].style("hachures") if hachures in self.types_de_hachures and all(objet.style("hachures") == hachures for objet in objets): self.hachures.setCurrentIndex(self.types_de_hachures.index(hachures)) # on sélectionne les hachures actuelles choix.addWidget(self.hachures) choix.addStretch() encadre2.addLayout(choix) objets = [objet for objet in self.objets if objet.style("famille") is not None] categorie = objets and objets[0].style("categorie") or None if objets and categorie and all(objet.style("categorie") == categorie for objet in objets): choix = QHBoxLayout() choix.addWidget(QLabel("Police : ")) #categorie = self.objet.style("categorie") or "lignes" self.liste_familles = getattr(param, "familles_de_" + categorie, []) self.famille = QComboBox() self.famille.addItems(self.liste_familles) self.famille.currentIndexChanged.connect(self.EvtFamille) famille = objets[0].style("famille") if famille in self.liste_familles and all(objet.style("famille") == famille for objet in objets): self.famille.setCurrentIndex(self.liste_familles.index(famille)) # on sélectionne la famille actuelle choix.addWidget(self.famille) choix.addStretch() encadre2.addLayout(choix) objets = [objet for objet in self.objets if objet.style("couleur") is not None] if objets: couleur = objets[0].style("couleur") choix = QHBoxLayout() choix.addWidget(QLabel(u"Couleur de l'objet : ")) if all(objet.style("couleur") == couleur for objet in objets): # conversion du format matplotlib au format Qt r, g, b = colorConverter.to_rgb(couleur) couleur = QColor(int(255*r), int(255*g), int(255*b)) else: couleur = None b = ColorSelecter(self, color=couleur) b.colorSelected.connect(self.OnSelectColour) choix.addWidget(b) choix.addStretch() encadre2.addLayout(choix) objets = [objet for objet in self.objets if objet.style("epaisseur") is not None] if objets: epaiss = objets[0].style("epaisseur") epaisseur = QHBoxLayout() epaisseur.addWidget(QLabel(u"Epaisseur (en 10e de pixels) : ")) self.epaisseur = QSpinBox() self.epaisseur.setMinimumWidth(30) self.epaisseur.setRange(1, 10000) if all(objet.style("epaisseur") == epaiss for objet in objets): self.epaisseur.setValue(10*epaiss) else: self.epaisseur.setSpecialValueText(' ') print(u'FIXME: cas non géré.') self.epaisseur.valueChanged.connect(self.EvtEpaisseur) epaisseur.addWidget(self.epaisseur) epaisseur.addStretch() encadre2.addLayout(epaisseur) objets = [objet for objet in self.objets if objet.style("taille") is not None] if objets: tail = objets[0].style("taille") taille = QHBoxLayout() taille.addWidget(QLabel(u"Taille (en 10e de pixels) : ")) self.taille = QSpinBox() self.taille.setMinimumWidth(30) self.taille.setRange(1,10000) if all(objet.style("taille") == tail for objet in objets): self.taille.setValue(10*tail) else: self.taille.setSpecialValueText(' ') print(u'FIXME: cas non géré.') self.taille.valueChanged.connect(self.EvtTaille) taille.addWidget(self.taille) taille.addStretch() encadre2.addLayout(taille) objets = [objet for objet in self.objets if objet.style("position") is not None] if objets: pos = objets[0].style("position") position = QHBoxLayout() position.addWidget(QLabel(u"Position de la flêche : ")) self.position = QSpinBox() self.position.setMinimumWidth(30) self.position.setRange(0, 100) if all(objet.style("position") == pos for objet in objets): self.position.setValue(100*pos) else: self.position.setSpecialValueText(' ') print(u'FIXME: cas non géré.') self.position.valueChanged.connect(self.EvtPosition) position.addWidget(self.position) position.addStretch() encadre2.addLayout(position) objets = [objet for objet in self.objets if objet.style("angle") is not None] if objets: ang = objets[0].style("angle") angle = QHBoxLayout() angle.addWidget(QLabel(u"Angle (en degré) : ")) self.angle = QSpinBox() self.angle.setMinimumWidth(30) self.angle.setRange(-180, 180) self.angle.setSpecialValueText('auto') self.angle.setSuffix(u'°'); self.angle.setWrapping(True) if all(objet.style("angle") == ang for objet in objets): self.angle.setValue(ang if ang != 'auto' else -180) else: self.angle.setSpecialValueText(' ') print(u'FIXME: cas non géré.') self.angle.valueChanged.connect(self.EvtAngle) angle.addWidget(self.angle) angle.addStretch() encadre2.addLayout(angle) self.add_checkbox(encadre, 'double_fleche', u"Flêche double") objets = [objet for objet in self.objets if objet.style("codage") is not None] # on ne peut regler les codages simultanement que pour des objets de meme categorie categorie = objets and objets[0].style("categorie") or None if objets and categorie and all(objet.style("categorie") == categorie for objet in objets): choix = QHBoxLayout() choix.addWidget(QLabel("Codage : ")) #categorie = objets[0].style("categorie") or "lignes" self.liste_codages = getattr(param, "codage_des_" + categorie, []) self.codage = QComboBox() self.codage.addItems(self.liste_codages) self.codage.currentIndexChanged.connect(self.EvtCodage) codage = objets[0].style("codage") if codage in self.liste_codages and all(objet.style("codage") == codage for objet in objets): self.codage.setCurrentIndex(self.liste_codages.index(codage)) # on sélectionne le codage actuel choix.addWidget(self.codage) encadre2.addLayout(choix) boutons = QHBoxLayout() ok = QPushButton('OK') ok.clicked.connect(self.EvtOk) boutons.addWidget(ok) appliquer = QPushButton(u"Appliquer") appliquer.clicked.connect(self.EvtAppliquer) boutons.addWidget(appliquer) if not self.islabel: supprimer = QPushButton(u"Supprimer") supprimer.clicked.connect(self.EvtSupprimer) boutons.addWidget(supprimer) annuler = QPushButton(u"Annuler") annuler.clicked.connect(self.EvtAnnuler) boutons.addWidget(annuler) if encadre.count(): # ne pas afficher une rubrique vide ! encadre_box = QGroupBox(u"Mode d'affichage") encadre_box.setLayout(encadre) self.sizer.addWidget(encadre_box) if encadre1.count(): encadre1_box = QGroupBox(u"Etiquette") encadre1_box.setLayout(encadre1) self.sizer.addWidget(encadre1_box) if encadre2.count(): encadre2_box = QGroupBox(u"Styles") encadre2_box.setLayout(encadre2) self.sizer.addWidget(encadre2_box) self.sizer.addLayout(boutons) self.setLayout(self.sizer) ##self.parent.parent.dim1 = self.sizer.CalcMin().Get() def add_checkbox(self, layout, propriete, titre): objets = [objet for objet in self.objets if objet.style(propriete) is not None] if objets: cb = QCheckBox(titre) cb.setTristate(True) layout.addWidget(cb) verifies = [objet.style(propriete) is True for objet in objets] if not any(verifies): etat = Qt.Unchecked elif all(verifies): etat = Qt.Checked else: etat = Qt.PartiallyChecked cb.setCheckState(etat) cb.stateChanged.connect(partial(self.checked, propriete=propriete)) cb.stateChanged.connect(partial(cb.setTristate, False)) def EvtMode(self, valeur): self.changements["mode"] = valeur def checked(self, state, propriete): # Bug avec Qt 4.8.1 - En cochant la case la première fois, on obtient # Qt.PartiallyChecked, et non Qt.Checked. Si ensuite, on décoche et on # recoche, on obtient bien Qt.Checked. self.changements[propriete] = (state != Qt.Unchecked) def EvtEtiquette(self): self.changements["label"] = self.etiquette.text() def OnSelectColour(self, color): # conversion du format Qt au format matplotlib r, g, b, a = color.getRgb() self.changements["couleur"] = (r/255, g/255, b/255, a/255) def EvtStyle(self, index): self.changements["style"] = self.liste_styles[index] def EvtHachures(self, index): self.changements["hachures"] = self.types_de_hachures[index] def EvtCodage(self, index): self.changements["codage"] = self.liste_codages[index] def EvtFamille(self, index): self.changements["famille"] = self.liste_familles[index] def EvtOk(self): self.EvtAppliquer() self.EvtAnnuler() def EvtAppliquer(self): with self.canvas.geler_affichage(actualiser=True, sablier=True): try: for objet in self.objets: changements = self.changements.copy() mode = changements.pop('mode', None) label = changements.pop('label', None) for key in changements.copy(): if objet.style(key) is None: # le style n'a pas de sens pour l'objet changements.pop(key) if mode is not None or label is not None: self.canvas.executer(u"%s.label(%s, %s)" %(objet.nom, repr(label), mode)) if mode is None: mode = objet.etiquette.style("mode") self.changements["mode"] = mode self.radios[mode].setChecked(True) if self.islabel: self.canvas.executer(u"%s.etiquette.style(**%s)" %(objet.parent.nom, changements)) else: self.canvas.executer(u"%s.style(**%s)" %(objet.nom, changements)) except: print_error() def EvtSupprimer(self): with self.canvas.geler_affichage(actualiser=True, sablier=True): for objet in self.objets: self.canvas.executer(u"del %s" %objet.nom) self.EvtAnnuler() def EvtAnnuler(self): # Ce qui suit corrige un genre de bug bizarre de wx: # quand une fenêtre de sélection de couleur a été affichée, # la fenêtre principale passe au second plan à la fermeture de la fenêtre de propriétés ?!? # (ce qui est très désagréable dès qu'un dossier est ouvert dans l'explorateur, par exemple !) # -> à supprimer avec Qt ? self.parent.parent.fenetre_principale.raise_() self.parent.parent.close() # fermeture de la frame def EvtLabelStyle(self): win = Proprietes(self.parent, [objet.etiquette for objet in self.objets if objet.etiquette is not None], True) win.show() def EvtEpaisseur(self): self.changements["epaisseur"] = self.epaisseur.value()/10 def EvtTaille(self): self.changements["taille"] = self.taille.value()/10 def EvtAngle(self): angle = self.angle.value() self.changements["angle"] = (angle if angle != -180 else 'auto') def EvtPosition(self): self.changements["position"] = self.position.value()/100
def add_device_to_tree(self, device): # check if device is already added if len(device['uid']) > 0: for row in range(self.model_devices.rowCount()): existing_name = self.model_devices.item(row, 0).text() exisitng_uid = self.tree_devices.indexWidget( self.model_devices.item(row, 1).index()).text() if device['name'] == existing_name and device[ 'uid'] == exisitng_uid: EventLogger.info( 'Ignoring duplicate device "{0}" with UID "{1}"'. format(device['name'], device['uid'])) return # add device name_item = QStandardItem(device['name']) uid_item = QStandardItem('') self.model_devices.appendRow([name_item, uid_item]) edit_uid = QLineEdit() edit_uid.setPlaceholderText('Enter UID') edit_uid.setValidator( QRegExpValidator(QRegExp( '^[{0}]{{1,6}}$'.format(BASE58)))) # FIXME: use stricter logic edit_uid.setText(device['uid']) self.tree_devices.setIndexWidget(uid_item.index(), edit_uid) value_specs = device_specs[device['name']]['values'] parent_item = QStandardItem('Values') name_item.appendRow([parent_item, QStandardItem('')]) self.tree_devices.expand(parent_item.index()) # add values for value_spec in value_specs: value_name_item = QStandardItem(value_spec['name']) value_interval_item = QStandardItem('') parent_item.appendRow([value_name_item, value_interval_item]) spinbox_interval = QSpinBox() spinbox_interval.setRange(0, (1 << 31) - 1) spinbox_interval.setSingleStep(1) spinbox_interval.setValue( device['values'][value_spec['name']]['interval']) spinbox_interval.setSuffix(' seconds') self.tree_devices.setIndexWidget(value_interval_item.index(), spinbox_interval) if value_spec['subvalues'] != None: for subvalue_name in value_spec['subvalues']: subvalue_name_item = QStandardItem(subvalue_name) subvalue_check_item = QStandardItem('') value_name_item.appendRow( [subvalue_name_item, subvalue_check_item]) check_subvalue = QCheckBox() check_subvalue.setChecked(device['values'][ value_spec['name']]['subvalues'][subvalue_name]) self.tree_devices.setIndexWidget( subvalue_check_item.index(), check_subvalue) self.tree_devices.expand(name_item.index()) # add options option_specs = device_specs[device['name']]['options'] if option_specs != None: parent_item = QStandardItem('Options') name_item.appendRow([parent_item, QStandardItem('')]) for option_spec in option_specs: option_name_item = QStandardItem(option_spec['name']) option_widget_item = QStandardItem('') parent_item.appendRow([option_name_item, option_widget_item]) if option_spec['type'] == 'choice': widget_option_value = QComboBox() for option_value_spec in option_spec['values']: widget_option_value.addItem( option_value_spec[0].decode('utf-8'), option_value_spec[1]) widget_option_value.setCurrentIndex( widget_option_value.findText(device['options'][ option_spec['name']]['value'].decode('utf-8'))) elif option_spec['type'] == 'int': widget_option_value = QSpinBox() widget_option_value.setRange(option_spec['minimum'], option_spec['maximum']) widget_option_value.setSuffix(option_spec['suffix']) widget_option_value.setValue( device['options'][option_spec['name']]['value']) elif option_spec['type'] == 'bool': widget_option_value = QCheckBox() widget_option_value.setChecked( device['options'][option_spec['name']]['value']) self.tree_devices.setIndexWidget(option_widget_item.index(), widget_option_value)
def add_device_to_tree(self, device): # check if device is already added if len(device['uid']) > 0: for row in range(self.model_devices.rowCount()): existing_name = self.model_devices.item(row, 0).text() exisitng_uid = self.tree_devices.indexWidget(self.model_devices.item(row, 1).index()).text() if device['name'] == existing_name and device['uid'] == exisitng_uid: EventLogger.info('Ignoring duplicate device "{0}" with UID "{1}"' .format(device['name'], device['uid'])) return # add device name_item = QStandardItem(device['name']) uid_item = QStandardItem('') self.model_devices.appendRow([name_item, uid_item]) edit_uid = QLineEdit() edit_uid.setPlaceholderText('Enter UID') edit_uid.setValidator(QRegExpValidator(QRegExp('^[{0}]{{1,6}}$'.format(BASE58)))) # FIXME: use stricter logic edit_uid.setText(device['uid']) self.tree_devices.setIndexWidget(uid_item.index(), edit_uid) value_specs = device_specs[device['name']]['values'] parent_item = QStandardItem('Values') name_item.appendRow([parent_item, QStandardItem('')]) self.tree_devices.expand(parent_item.index()) # add values for value_spec in value_specs: value_name_item = QStandardItem(value_spec['name']) value_interval_item = QStandardItem('') parent_item.appendRow([value_name_item, value_interval_item]) spinbox_interval = QSpinBox() spinbox_interval.setRange(0, (1 << 31) - 1) spinbox_interval.setSingleStep(1) spinbox_interval.setValue(device['values'][value_spec['name']]['interval']) spinbox_interval.setSuffix(' seconds') self.tree_devices.setIndexWidget(value_interval_item.index(), spinbox_interval) if value_spec['subvalues'] != None: for subvalue_name in value_spec['subvalues']: subvalue_name_item = QStandardItem(subvalue_name) subvalue_check_item = QStandardItem('') value_name_item.appendRow([subvalue_name_item, subvalue_check_item]) check_subvalue = QCheckBox() check_subvalue.setChecked(device['values'][value_spec['name']]['subvalues'][subvalue_name]) self.tree_devices.setIndexWidget(subvalue_check_item.index(), check_subvalue) self.tree_devices.expand(name_item.index()) # add options option_specs = device_specs[device['name']]['options'] if option_specs != None: parent_item = QStandardItem('Options') name_item.appendRow([parent_item, QStandardItem('')]) for option_spec in option_specs: option_name_item = QStandardItem(option_spec['name']) option_widget_item = QStandardItem('') parent_item.appendRow([option_name_item, option_widget_item]) if option_spec['type'] == 'choice': widget_option_value = QComboBox() for option_value_spec in option_spec['values']: widget_option_value.addItem(option_value_spec[0].decode('utf-8'), option_value_spec[1]) widget_option_value.setCurrentIndex(widget_option_value.findText(device['options'][option_spec['name']]['value'].decode('utf-8'))) elif option_spec['type'] == 'int': widget_option_value = QSpinBox() widget_option_value.setRange(option_spec['minimum'], option_spec['maximum']) widget_option_value.setSuffix(option_spec['suffix']) widget_option_value.setValue(device['options'][option_spec['name']]['value']) elif option_spec['type'] == 'bool': widget_option_value = QCheckBox() widget_option_value.setChecked(device['options'][option_spec['name']]['value']) self.tree_devices.setIndexWidget(option_widget_item.index(), widget_option_value)
class Window(QMainWindow): def __init__(self, parent=None): super(Window, self).__init__(parent) self.image = QImage() self.dirty = False self.filename = None self.mirroredvertically = False self.mirroredhorizontally = False self.printer = None self.create_widgets() self.create_actions() self.load_settings() self.setWindowTitle("Image Changer") self.updateFileMenu() QTimer.singleShot(0, self.loadInitialFile) def create_widgets(self): self.imageLabel = QLabel() self.imageLabel.setMinimumSize(200, 200) self.imageLabel.setAlignment(Qt.AlignCenter) self.imageLabel.setContextMenuPolicy(Qt.ActionsContextMenu) self.setCentralWidget(self.imageLabel) logDockWidget = QDockWidget("Log", self) logDockWidget.setObjectName("LogDockWidget") logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea| Qt.RightDockWidgetArea) self.listWidget = QListWidget() logDockWidget.setWidget(self.listWidget) self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget) self.sizeLabel = QLabel() self.sizeLabel.setFrameStyle(QFrame.StyledPanel|QFrame.Sunken) status = self.statusBar() status.setSizeGripEnabled(False) status.addPermanentWidget(self.sizeLabel) status.showMessage("Ready", 5000) def create_actions(self): fileNewAction = self.createAction("&New...", self.fileNew, QKeySequence.New, "filenew", "Create an image file") fileOpenAction = self.createAction("&Open...", self.fileOpen, QKeySequence.Open, "fileopen", "Open an existing image file") fileSaveAction = self.createAction("&Save", self.fileSave, QKeySequence.Save, "filesave", "Save the image") fileSaveAsAction = self.createAction("Save &As...", self.fileSaveAs, icon="filesaveas", tip="Save the image using a new name") filePrintAction = self.createAction("&Print", self.filePrint, QKeySequence.Print, "fileprint", "Print the image") fileQuitAction = self.createAction("&Quit", self.close, "Ctrl+Q", "filequit", "Close the application") editInvertAction = self.createAction("&Invert", None, "Ctrl+I", "editinvert", "Invert the image's colors", True) editInvertAction.toggled.connect(self.editInvert) editSwapRedAndBlueAction = self.createAction("Sw&ap Red and Blue", None, "Ctrl+A", "editswap", "Swap the image's red and blue color components", True) editSwapRedAndBlueAction.toggled.connect(self.editSwapRedAndBlue) editZoomAction = self.createAction("&Zoom...", self.editZoom, "Alt+Z", "editzoom", "Zoom the image") editResizeAction = self.createAction("&Resize...", self.editResize, "Ctrl+R", "editresize", "Resize the image") mirrorGroup = QActionGroup(self) editUnMirrorAction = self.createAction("&Unmirror", None, "Ctrl+U", "editunmirror", "Unmirror the image", True) editUnMirrorAction.toggled.connect(self.editUnMirror) mirrorGroup.addAction(editUnMirrorAction) editMirrorHorizontalAction = self.createAction( "Mirror &Horizontally", None, "Ctrl+H", "editmirrorhoriz", "Horizontally mirror the image", True) editMirrorHorizontalAction.toggled.connect( self.editMirrorHorizontal) mirrorGroup.addAction(editMirrorHorizontalAction) editMirrorVerticalAction = self.createAction( "Mirror &Vertically", None, "Ctrl+V", "editmirrorvert", "Vertically mirror the image", True) editMirrorVerticalAction.toggled.connect(self.editMirrorVertical) mirrorGroup.addAction(editMirrorVerticalAction) editUnMirrorAction.setChecked(True) helpAboutAction = self.createAction("&About Image Changer", self.helpAbout) helpHelpAction = self.createAction("&Help", self.helpHelp, QKeySequence.HelpContents) self.fileMenu = self.menuBar().addMenu("&File") self.fileMenuActions = (fileNewAction, fileOpenAction, fileSaveAction, fileSaveAsAction, None, filePrintAction, fileQuitAction) self.fileMenu.aboutToShow.connect(self.updateFileMenu) editMenu = self.menuBar().addMenu("&Edit") self.addActions(editMenu, (editInvertAction, editSwapRedAndBlueAction, editZoomAction, editResizeAction)) mirrorMenu = editMenu.addMenu(QIcon(":/editmirror.png"), "&Mirror") self.addActions(mirrorMenu, (editUnMirrorAction, editMirrorHorizontalAction, editMirrorVerticalAction)) helpMenu = self.menuBar().addMenu("&Help") self.addActions(helpMenu, (helpAboutAction, helpHelpAction)) fileToolbar = self.addToolBar("File") fileToolbar.setObjectName("FileToolBar") self.addActions(fileToolbar, (fileNewAction, fileOpenAction, fileSaveAsAction)) editToolbar = self.addToolBar("Edit") editToolbar.setObjectName("EditToolBar") self.addActions(editToolbar, (editInvertAction, editSwapRedAndBlueAction, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction)) self.zoomSpinBox = QSpinBox() self.zoomSpinBox.setRange(1, 400) self.zoomSpinBox.setSuffix(" %") self.zoomSpinBox.setValue(100) self.zoomSpinBox.setToolTip("Zoom the image") self.zoomSpinBox.setStatusTip(self.zoomSpinBox.toolTip()) self.zoomSpinBox.setFocusPolicy(Qt.NoFocus) self.zoomSpinBox.valueChanged.connect(self.showImage) editToolbar.addWidget(self.zoomSpinBox) self.addActions(self.imageLabel, (editInvertAction, editSwapRedAndBlueAction, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction)) self.resetableActions = ((editInvertAction, False), (editSwapRedAndBlueAction, False), (editUnMirrorAction, True)) def load_settings(self): settings = QSettings() self.recentFiles = settings.value("RecentFiles").toStringList() self.restoreGeometry( settings.value("MainWindow/Geometry").toByteArray()) self.restoreState(settings.value("MainWindow/State").toByteArray()) def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/{0}.png".format(icon))) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.triggered.connect(slot) if checkable: action.setCheckable(True) return action def addActions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def closeEvent(self, event): if self.okToContinue(): settings = QSettings() filename = (QVariant(QString(self.filename)) if self.filename is not None else QVariant()) settings.setValue("LastFile", filename) recentFiles = (QVariant(self.recentFiles) if self.recentFiles else QVariant()) settings.setValue("RecentFiles", recentFiles) settings.setValue("MainWindow/Geometry", QVariant( self.saveGeometry())) settings.setValue("MainWindow/State", QVariant( self.saveState())) else: event.ignore() def okToContinue(self): if self.dirty: reply = QMessageBox.question(self, "Image Changer - Unsaved Changes", "Save unsaved changes?", QMessageBox.Yes|QMessageBox.No|QMessageBox.Cancel) if reply == QMessageBox.Cancel: return False elif reply == QMessageBox.Yes: return self.fileSave() return True def loadInitialFile(self): settings = QSettings() fname = unicode(settings.value("LastFile").toString()) if fname and QFile.exists(fname): self.loadFile(fname) def updateStatus(self, message): self.statusBar().showMessage(message, 5000) self.listWidget.addItem(message) if self.filename is not None: self.setWindowTitle("Image Changer - {0}[*]".format( os.path.basename(self.filename))) elif not self.image.isNull(): self.setWindowTitle("Image Changer - Unnamed[*]") else: self.setWindowTitle("Image Changer[*]") self.setWindowModified(self.dirty) def updateFileMenu(self): self.fileMenu.clear() self.addActions(self.fileMenu, self.fileMenuActions[:-1]) current = (QString(self.filename) if self.filename is not None else None) recentFiles = [] for fname in self.recentFiles: if fname != current and QFile.exists(fname): recentFiles.append(fname) if recentFiles: self.fileMenu.addSeparator() for i, fname in enumerate(recentFiles): action = QAction(QIcon(":/icon.png"), "&{0} {1}".format(i + 1, QFileInfo( fname).fileName()), self) action.setData(QVariant(fname)) action.triggered.connect(self.loadFile) self.fileMenu.addAction(action) self.fileMenu.addSeparator() self.fileMenu.addAction(self.fileMenuActions[-1]) def fileNew(self): if not self.okToContinue(): return dialog = newimagedlg.NewImageDlg(self) if dialog.exec_(): self.addRecentFile(self.filename) self.image = QImage() for action, check in self.resetableActions: action.setChecked(check) self.image = dialog.image() self.filename = None self.dirty = True self.showImage() self.sizeLabel.setText("{0} x {1}".format(self.image.width(), self.image.height())) self.updateStatus("Created new image") def fileOpen(self): if not self.okToContinue(): return dir = (os.path.dirname(self.filename) if self.filename is not None else ".") formats = (["*.{0}".format(unicode(format).lower()) for format in QImageReader.supportedImageFormats()]) fname = unicode(QFileDialog.getOpenFileName(self, "Image Changer - Choose Image", dir, "Image files ({0})".format(" ".join(formats)))) if fname: self.loadFile(fname) def loadFile(self, fname=None): if fname is None: action = self.sender() if isinstance(action, QAction): fname = unicode(action.data().toString()) if not self.okToContinue(): return else: return if fname: self.filename = None image = QImage(fname) if image.isNull(): message = "Failed to read {0}".format(fname) else: self.addRecentFile(fname) self.image = QImage() for action, check in self.resetableActions: action.setChecked(check) self.image = image self.filename = fname self.showImage() self.dirty = False self.sizeLabel.setText("{0} x {1}".format( image.width(), image.height())) message = "Loaded {0}".format(os.path.basename(fname)) self.updateStatus(message) def addRecentFile(self, fname): if fname is None: return if not self.recentFiles.contains(fname): self.recentFiles.prepend(QString(fname)) while self.recentFiles.count() > 9: self.recentFiles.takeLast() def fileSave(self): if self.image.isNull(): return True if self.filename is None: return self.fileSaveAs() else: if self.image.save(self.filename, None): self.updateStatus("Saved as {0}".format(self.filename)) self.dirty = False return True else: self.updateStatus("Failed to save {0}".format( self.filename)) return False def fileSaveAs(self): if self.image.isNull(): return True fname = self.filename if self.filename is not None else "." formats = (["*.{0}".format(unicode(format).lower()) for format in QImageWriter.supportedImageFormats()]) fname = unicode(QFileDialog.getSaveFileName(self, "Image Changer - Save Image", fname, "Image files ({0})".format(" ".join(formats)))) if fname: if "." not in fname: fname += ".png" self.addRecentFile(fname) self.filename = fname return self.fileSave() return False def filePrint(self): if self.image.isNull(): return if self.printer is None: self.printer = QPrinter(QPrinter.HighResolution) self.printer.setPageSize(QPrinter.Letter) form = QPrintDialog(self.printer, self) if form.exec_(): painter = QPainter(self.printer) rect = painter.viewport() size = self.image.size() size.scale(rect.size(), Qt.KeepAspectRatio) painter.setViewport(rect.x(), rect.y(), size.width(), size.height()) painter.drawImage(0, 0, self.image) def editInvert(self, on): if self.image.isNull(): return self.image.invertPixels() self.showImage() self.dirty = True self.updateStatus("Inverted" if on else "Uninverted") def editSwapRedAndBlue(self, on): if self.image.isNull(): return self.image = self.image.rgbSwapped() self.showImage() self.dirty = True self.updateStatus(("Swapped Red and Blue" if on else "Unswapped Red and Blue")) def editUnMirror(self, on): if self.image.isNull(): return if self.mirroredhorizontally: self.editMirrorHorizontal(False) if self.mirroredvertically: self.editMirrorVertical(False) def editMirrorHorizontal(self, on): if self.image.isNull(): return self.image = self.image.mirrored(True, False) self.showImage() self.mirroredhorizontally = not self.mirroredhorizontally self.dirty = True self.updateStatus(("Mirrored Horizontally" if on else "Unmirrored Horizontally")) def editMirrorVertical(self, on): if self.image.isNull(): return self.image = self.image.mirrored(False, True) self.showImage() self.mirroredvertically = not self.mirroredvertically self.dirty = True self.updateStatus(("Mirrored Vertically" if on else "Unmirrored Vertically")) def editZoom(self): if self.image.isNull(): return percent, ok = QInputDialog.getInteger(self, "Image Changer - Zoom", "Percent:", self.zoomSpinBox.value(), 1, 400) if ok: self.zoomSpinBox.setValue(percent) def editResize(self): if self.image.isNull(): return form = resizedlg.ResizeDlg(self.image.width(), self.image.height(), self) if form.exec_(): width, height = form.result() if (width == self.image.width() and height == self.image.height()): self.statusBar().showMessage("Resized to the same size", 5000) else: self.image = self.image.scaled(width, height) self.showImage() self.dirty = True size = "{0} x {1}".format(self.image.width(), self.image.height()) self.sizeLabel.setText(size) self.updateStatus("Resized to {0}".format(size)) def showImage(self, percent=None): if self.image.isNull(): return if percent is None: percent = self.zoomSpinBox.value() factor = percent / 100.0 width = self.image.width() * factor height = self.image.height() * factor image = self.image.scaled(width, height, Qt.KeepAspectRatio) self.imageLabel.setPixmap(QPixmap.fromImage(image)) def helpAbout(self): QMessageBox.about(self, "About Image Changer", """<b>Image Changer</b> v {0} <p>Copyright © 2008 Qtrac Ltd. All rights reserved. <p>This application can be used to perform simple image manipulations. <p>Python {1} - Qt {2} - PyQt {3} on {4}""".format( __version__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system())) def helpHelp(self): form = helpform.HelpForm("index.html", self) form.show()
class ScreenShot(QWidget): def __init__(self): super(ScreenShot, self).__init__() self.initUI() def initUI(self): self.originalPixmap = QPixmap() self.screenshotLabel = QLabel("screenshotlabel", self) self.screenshotLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.screenshotLabel.setAlignment(Qt.AlignCenter) self.screenGeometry = QApplication.desktop().screenGeometry( ) # Qrect() print self.screenGeometry, self.screenGeometry.width() self.screenshotLabel.setMinimumSize(self.screenGeometry.width() / 8, self.screenGeometry.height() / 8) mainlayout = QVBoxLayout(self) mainlayout.addWidget(self.screenshotLabel) self.optionsGroupBox = QGroupBox(u"选项", self) self.hideThisWindowCheckBox = QCheckBox(u"隐藏这个窗口", self.optionsGroupBox) self.optionsGroupBoxLayout = QGridLayout(self.optionsGroupBox) mainlayout.addWidget(self.optionsGroupBox) self.delaySpinBox = QSpinBox(self.optionsGroupBox) self.delaySpinBox.setSuffix(u"s") self.delaySpinBox.setMaximum(60) self.optionsGroupBoxLayout.addWidget(QLabel(u"截屏延时:", self), 0, 0) self.optionsGroupBoxLayout.addWidget(self.delaySpinBox, 0, 1) self.optionsGroupBoxLayout.addWidget(self.hideThisWindowCheckBox, 1, 0) buttonLayout = QHBoxLayout() self.newScreenshotButton = QPushButton(u"新截图", self) self.newScreenshotButton.clicked.connect(self.__newScreenshot) buttonLayout.addWidget(self.newScreenshotButton) saveScreenshotButton = QPushButton(u"保存截图", self) buttonLayout.addWidget(saveScreenshotButton) quitScreenshotButton = QPushButton(u"退出截图", self) quitScreenshotButton.setShortcut("Ctrl+Q") buttonLayout.addWidget(saveScreenshotButton) buttonLayout.addStretch() mainlayout.addLayout(buttonLayout) quitScreenshotButton.clicked.connect(self.close) saveScreenshotButton.clicked.connect(self.__saveScreenshot) self.delaySpinBox.valueChanged.connect(self.__updateCheckBox) self.delaySpinBox.setValue(5) self.setWindowTitle(u"截图") self.resize(300, 200) def resizeEvent(self, QResizeEvent): scaledSize = self.originalPixmap.size() scaledSize.scale(self.screenshotLabel.size(), Qt.KeepAspectRatio) if (not self.screenshotLabel.pixmap()) or ( scaledSize != self.screenshotLabel.pixmap().size()): self.__updateScreenshotLabel() def __newScreenshot(self): if self.hideThisWindowCheckBox.isChecked(): self.hide() self.newScreenshotButton.setDisabled(True) QTimer.singleShot(self.delaySpinBox.value() * 1000, self.__shootScreen) def __saveScreenshot(self): format = "png" initialPath = QDesktopServices.storageLocation( QDesktopServices.PicturesLocation) # initialPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); if initialPath.isEmpty(): initialPath = QDir.currentPath() initialPath += "/untitled." + format fileDialog = QtGui.QFileDialog(self, u"存储为", initialPath) fileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave) fileDialog.setFileMode(QtGui.QFileDialog.AnyFile) fileDialog.setDirectory(initialPath) mimeTypes = QStringList() for bf in QImageWriter.supportedImageFormats(): mimeTypes.append(QLatin1String(bf)) # fileDialog.setMin setMimeTypeFilters(mimeTypes) # fileDialog.selectMimeTypeFilter("image/" + format); fileDialog.setDefaultSuffix(format) if fileDialog.accept(): return fileName = fileDialog.selectedFiles().first() if not self.originalPixmap.save(fileName): QtGui.QMessageBox.Warning( self, u"保存错误", u"图像无法存储到 \"%s\"." % str(QDir.toNativeSeparators(fileName))) def __shootScreen(self): if self.delaySpinBox.value() != 0: QApplication.beep() self.originalPixmap = QPixmap.grabWindow( QApplication.desktop().winId()) self.__updateScreenshotLabel() self.newScreenshotButton.setDisabled(False) if self.hideThisWindowCheckBox.isChecked(): self.show() def __updateCheckBox(self): print "sssss" if self.delaySpinBox.value() == 0: self.hideThisWindowCheckBox.setDisabled(True) self.hideThisWindowCheckBox.setChecked(False) else: self.hideThisWindowCheckBox.setDisabled(False) def __updateScreenshotLabel(self): self.screenshotLabel.setPixmap( self.originalPixmap.scaled(self.screenshotLabel.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
class NewSensorgroupPage1(QWizardPage): """WizardPage to select constructor values""" def __init__(self, parent, project): QWizardPage.__init__(self, parent) self.setTitle(QCoreApplication.translate('DataStorageBrowser', 'Select data import properties')) self.project = project self.mainLayout = QGridLayout() self.setLayout(self.mainLayout) tsLabel = QLabel(self) tsLabel.setText(QCoreApplication.translate('DataStorageBrowser', 'Time step')) self.mainLayout.addWidget(tsLabel, 0, 0) self.tsInput = QSpinBox(self) self.tsInput.setSuffix(' s') self.tsInput.setSpecialValueText('---') self.tsInput.setMinimum(0) self.tsInput.setMaximum(86400) self.tsInput.setValue(0) self.registerField('timestep', self.tsInput, 'value') self.mainLayout.addWidget(self.tsInput, 0, 1) tzLabel = QLabel(self) tzLabel.setText(QCoreApplication.translate('DataStorageBrowser', 'Time zone')) self.mainLayout.addWidget(tzLabel, 1, 0) self.tzInput = QSpinBox(self) self.tzInput.setMinimum(0) self.tzInput.setMaximum(23) self.tzInput.setSuffix(' h') self.tzInput.setValue(0) self.registerField('timezone', self.tzInput, 'value') self.mainLayout.addWidget(self.tzInput, 1, 1) tfLabel = QLabel(self) tfLabel.setText(QCoreApplication.translate('DataStorageBrowser', 'Time format')) self.mainLayout.addWidget(tfLabel, 2, 0) self.tfInput = QLineEdit(self) self.tfInput.setText('') self.registerField('timeformat', self.tfInput, 'text') self.mainLayout.addWidget(self.tfInput, 2, 1) self.delimLabel = QLabel(self) self.delimLabel.setText(QCoreApplication.translate('DataStorageBrowser', 'CSV separator')) self.mainLayout.addWidget(self.delimLabel, 3, 0) self.delimInput = QLineEdit(self) self.delimInput.setMaxLength(1) self.delimInput.setText(';') self.registerField('delim', self.delimInput, 'text') self.mainLayout.addWidget(self.delimInput, 3, 1) self.tcolLabel = QLabel(self) self.tcolLabel.setText(QCoreApplication.translate('DataStorageBrowser', 'CSV time column')) self.mainLayout.addWidget(self.tcolLabel, 4, 0) self.tcolInput = QSpinBox(self) self.tcolInput.setMinimum(1) self.tcolInput.setMaximum(500) self.tcolInput.setValue(2) self.registerField('timecol', self.tcolInput, 'value') self.mainLayout.addWidget(self.tcolInput, 4, 1) self.extraLabel = QLabel(self) self.extraLabel.setText(QCoreApplication.translate('DataStorageBrowser', 'CSV extra headers')) self.mainLayout.addWidget(self.extraLabel, 5, 0) self.extraInput = QLineEdit(self) self.extraInput.setMaxLength(200) self.extraInput.setText('Device;Unit;SensorType') self.registerField('extra_headers', self.extraInput, 'text') self.mainLayout.addWidget(self.extraInput, 5, 1) def initializePage(self): t = str(self.field('type').toString()) if t == 'CSV': self.tfInput.setText('%d.%m.%Y %H:%M') for w in (self.delimLabel, self.delimInput, self.tcolLabel, self.tcolInput, self.extraLabel, self.extraInput): w.show() elif t == 'Remus': self.tfInput.setText('%d.%m.%y %H:%M:%S') for w in (self.delimLabel, self.delimInput, self.tcolLabel, self.tcolInput, self.extraLabel, self.extraInput): w.hide() else: raise SimuVis4.Errors.NotImplementedError def validatePage(self): return True
class CodePastingDialog(QDialog): def __init__(self, parent=None, code=''): super(CodePastingDialog, self).__init__(parent) self.setWindowTitle(self.tr("Enviar a Pastebin")) self.setMinimumSize(700, 500) self._parent = parent container = QVBoxLayout(self) # Thread self.thread = code_pasting.Thread() self.connect(self.thread, SIGNAL("finished()"), self._paste_result) # Campos fields_box = QGridLayout() fields_box.addWidget(QLabel(self.tr("Expirar después de:")), 0, 0) self._spin_expire = QSpinBox() self._spin_expire.setSuffix(self.tr(" Días")) self._spin_expire.setMinimum(1) fields_box.addWidget(self._spin_expire, 0, 1) fields_box.addWidget(QLabel(self.tr("Acceso:")), 1, 0) self._combo_access = QComboBox() self._combo_access.addItems([self.tr("Público"), self.tr("Privado")]) fields_box.addWidget(self._combo_access, 1, 1) fields_box.addWidget(QLabel(self.tr("Nombre:")), 2, 0) self._line_filename = QLineEdit() place_holder_text = parent.get_active_editor().filename self._line_filename.setPlaceholderText(place_holder_text) fields_box.addWidget(self._line_filename, 2, 1) fields_box.addWidget(QLabel(self.tr("Descripción:")), 3, 0) # Editor self._code_editor = QPlainTextEdit() self._set_editor_style(self._code_editor) self._code_editor.setPlainText(code) hbox = QHBoxLayout() hbox.addItem(QSpacerItem(0, 1, QSizePolicy.Expanding)) btn_paste = QPushButton(self.tr("Enviar")) hbox.addWidget(btn_paste) btn_cancel = QPushButton(self.tr("Cancelar")) hbox.addWidget(btn_cancel) container.addLayout(fields_box) container.addWidget(self._code_editor) container.addLayout(hbox) # Loading widget self.loading_widget = loading_widget.LoadingWidget(self) self.loading_widget.hide() # Conexiones self.connect(btn_cancel, SIGNAL("clicked()"), self.close) self.connect(btn_paste, SIGNAL("clicked()"), self._emit_data) def _emit_data(self): code = self._code_editor.toPlainText() expire = str(self._spin_expire.value()) + 'D' paste_name = self._line_filename.text() if not paste_name: paste_name = self._parent.get_active_editor().filename self.loading_widget.show() self.thread.paste(code, paste_name, expire) def _paste_result(self): self.loading_widget.hide() result = self.thread.result if result is None: QMessageBox.critical(self, self.tr("Error!"), self.tr("No hay código")) return QMessageBox.information(self, self.tr("URL"), str(result)) self.close() def _set_editor_style(self, editor): style = 'QPlainTextEdit {color: #E2E2E5; background-color: #0E0F12; }' editor.setStyleSheet(style) def resizeEvent(self, event): super(CodePastingDialog, self).resizeEvent(event) self.loading_widget.resize(event.size())
class EditorConfiguration(QWidget): def __init__(self, parent): super(EditorConfiguration, self).__init__() self._preferences = parent vbox = QVBoxLayout(self) #Indentation groupBoxFeatures = QGroupBox( translations.TR_PREFERENCES_EDITOR_CONFIG_FEATURES) formFeatures = QGridLayout(groupBoxFeatures) formFeatures.addWidget( QLabel(translations.TR_PREFERENCES_EDITOR_CONFIG_INDENTATION), 1, 0, Qt.AlignRight) self._spin = QSpinBox() self._spin.setAlignment(Qt.AlignRight) self._spin.setMinimum(1) self._spin.setValue(settings.INDENT) formFeatures.addWidget(self._spin, 1, 1, alignment=Qt.AlignTop) self._checkUseTabs = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_USE_TABS) self._checkUseTabs.setChecked(settings.USE_TABS) self.connect(self._checkUseTabs, SIGNAL("stateChanged(int)"), self._change_tab_spaces) formFeatures.addWidget(self._checkUseTabs, 1, 2, alignment=Qt.AlignTop) if settings.USE_TABS: self._spin.setSuffix( translations.TR_PREFERENCES_EDITOR_CONFIG_TAB_SIZE) else: self._spin.setSuffix( translations.TR_PREFERENCES_EDITOR_CONFIG_SPACES) #Margin Line formFeatures.addWidget( QLabel(translations.TR_PREFERENCES_EDITOR_CONFIG_MARGIN_LINE), 2, 0, Qt.AlignRight) self._spinMargin = QSpinBox() self._spinMargin.setMaximum(200) self._spinMargin.setValue(settings.MARGIN_LINE) formFeatures.addWidget(self._spinMargin, 2, 1, alignment=Qt.AlignTop) self._checkShowMargin = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_MARGIN_LINE) self._checkShowMargin.setChecked(settings.SHOW_MARGIN_LINE) formFeatures.addWidget(self._checkShowMargin, 2, 2, alignment=Qt.AlignTop) #End of line self._checkEndOfLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_END_OF_LINE) self._checkEndOfLine.setChecked(settings.USE_PLATFORM_END_OF_LINE) formFeatures.addWidget(self._checkEndOfLine, 3, 1, alignment=Qt.AlignTop) #Find Errors self._checkHighlightLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_ERROR_HIGHLIGHTING) self._checkHighlightLine.setChecked(settings.UNDERLINE_NOT_BACKGROUND) formFeatures.addWidget(self._checkHighlightLine, 4, 1, 1, 2, alignment=Qt.AlignTop) self._checkErrors = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_FIND_ERRORS) self._checkErrors.setChecked(settings.FIND_ERRORS) formFeatures.addWidget(self._checkErrors, 5, 1, 1, 2, alignment=Qt.AlignTop) self.connect(self._checkErrors, SIGNAL("stateChanged(int)"), self._disable_show_errors) self._showErrorsOnLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TOOLTIP_ERRORS) self._showErrorsOnLine.setChecked(settings.ERRORS_HIGHLIGHT_LINE) self.connect(self._showErrorsOnLine, SIGNAL("stateChanged(int)"), self._enable_errors_inline) formFeatures.addWidget(self._showErrorsOnLine, 6, 2, 1, 1, Qt.AlignTop) #Find Check Style self._checkStyle = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_PEP8) self._checkStyle.setChecked(settings.CHECK_STYLE) formFeatures.addWidget(self._checkStyle, 7, 1, 1, 2, alignment=Qt.AlignTop) self.connect(self._checkStyle, SIGNAL("stateChanged(int)"), self._disable_check_style) self._checkStyleOnLine = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TOOLTIP_PEP8) self._checkStyleOnLine.setChecked(settings.CHECK_HIGHLIGHT_LINE) self.connect(self._checkStyleOnLine, SIGNAL("stateChanged(int)"), self._enable_check_inline) formFeatures.addWidget(self._checkStyleOnLine, 8, 2, 1, 1, Qt.AlignTop) # Python3 Migration self._showMigrationTips = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_MIGRATION) self._showMigrationTips.setChecked(settings.SHOW_MIGRATION_TIPS) formFeatures.addWidget(self._showMigrationTips, 9, 1, 1, 2, Qt.AlignTop) #Center On Scroll self._checkCenterScroll = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_CENTER_SCROLL) self._checkCenterScroll.setChecked(settings.CENTER_ON_SCROLL) formFeatures.addWidget(self._checkCenterScroll, 10, 1, 1, 2, alignment=Qt.AlignTop) #Remove Trailing Spaces add Last empty line automatically self._checkTrailing = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_REMOVE_TRAILING) self._checkTrailing.setChecked(settings.REMOVE_TRAILING_SPACES) formFeatures.addWidget(self._checkTrailing, 11, 1, 1, 2, alignment=Qt.AlignTop) #Show Tabs and Spaces self._checkShowSpaces = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TABS_AND_SPACES) self._checkShowSpaces.setChecked(settings.SHOW_TABS_AND_SPACES) formFeatures.addWidget(self._checkShowSpaces, 12, 1, 1, 2, alignment=Qt.AlignTop) self._allowWordWrap = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_WORD_WRAP) self._allowWordWrap.setChecked(settings.ALLOW_WORD_WRAP) formFeatures.addWidget(self._allowWordWrap, 13, 1, 1, 2, alignment=Qt.AlignTop) self._checkForDocstrings = QCheckBox( translations.TR_PREFERENCES_EDITOR_CONFIG_CHECK_FOR_DOCSTRINGS) self._checkForDocstrings.setChecked(settings.CHECK_FOR_DOCSTRINGS) formFeatures.addWidget(self._checkForDocstrings, 14, 1, 1, 2, alignment=Qt.AlignTop) vbox.addWidget(groupBoxFeatures) vbox.addItem( QSpacerItem(0, 10, QSizePolicy.Expanding, QSizePolicy.Expanding)) self.connect(self._preferences, SIGNAL("savePreferences()"), self.save) def _enable_check_inline(self, val): if val == Qt.Checked: self._checkStyle.setChecked(True) def _enable_errors_inline(self, val): if val == Qt.Checked: self._checkErrors.setChecked(True) def _disable_check_style(self, val): if val == Qt.Unchecked: self._checkStyleOnLine.setChecked(False) def _disable_show_errors(self, val): if val == Qt.Unchecked: self._showErrorsOnLine.setChecked(False) def _change_tab_spaces(self, val): if val == Qt.Unchecked: self._spin.setSuffix( translations.TR_PREFERENCES_EDITOR_CONFIG_SPACES) else: self._spin.setSuffix( translations.TR_PREFERENCES_EDITOR_CONFIG_TAB_SIZE) def save(self): qsettings = IDE.ninja_settings() qsettings.setValue('preferences/editor/indent', self._spin.value()) settings.INDENT = self._spin.value() endOfLine = self._checkEndOfLine.isChecked() qsettings.setValue('preferences/editor/platformEndOfLine', endOfLine) settings.USE_PLATFORM_END_OF_LINE = endOfLine margin_line = self._spinMargin.value() qsettings.setValue('preferences/editor/marginLine', margin_line) settings.MARGIN_LINE = margin_line settings.pep8mod_update_margin_line_length(margin_line) qsettings.setValue('preferences/editor/showMarginLine', self._checkShowMargin.isChecked()) settings.SHOW_MARGIN_LINE = self._checkShowMargin.isChecked() settings.UNDERLINE_NOT_BACKGROUND = \ self._checkHighlightLine.isChecked() qsettings.setValue('preferences/editor/errorsUnderlineBackground', settings.UNDERLINE_NOT_BACKGROUND) qsettings.setValue('preferences/editor/errors', self._checkErrors.isChecked()) settings.FIND_ERRORS = self._checkErrors.isChecked() qsettings.setValue('preferences/editor/errorsInLine', self._showErrorsOnLine.isChecked()) settings.ERRORS_HIGHLIGHT_LINE = self._showErrorsOnLine.isChecked() qsettings.setValue('preferences/editor/checkStyle', self._checkStyle.isChecked()) settings.CHECK_STYLE = self._checkStyle.isChecked() qsettings.setValue('preferences/editor/showMigrationTips', self._showMigrationTips.isChecked()) settings.SHOW_MIGRATION_TIPS = self._showMigrationTips.isChecked() qsettings.setValue('preferences/editor/checkStyleInline', self._checkStyleOnLine.isChecked()) settings.CHECK_HIGHLIGHT_LINE = self._checkStyleOnLine.isChecked() qsettings.setValue('preferences/editor/centerOnScroll', self._checkCenterScroll.isChecked()) settings.CENTER_ON_SCROLL = self._checkCenterScroll.isChecked() qsettings.setValue('preferences/editor/removeTrailingSpaces', self._checkTrailing.isChecked()) settings.REMOVE_TRAILING_SPACES = self._checkTrailing.isChecked() qsettings.setValue('preferences/editor/showTabsAndSpaces', self._checkShowSpaces.isChecked()) settings.SHOW_TABS_AND_SPACES = self._checkShowSpaces.isChecked() qsettings.setValue('preferences/editor/useTabs', self._checkUseTabs.isChecked()) settings.USE_TABS = self._checkUseTabs.isChecked() qsettings.setValue('preferences/editor/allowWordWrap', self._allowWordWrap.isChecked()) settings.ALLOW_WORD_WRAP = self._allowWordWrap.isChecked() qsettings.setValue('preferences/editor/checkForDocstrings', self._checkForDocstrings.isChecked()) settings.CHECK_FOR_DOCSTRINGS = self._checkForDocstrings.isChecked()
class MusicView(preferences.Group): def __init__(self, page): super(MusicView, self).__init__(page) layout = QGridLayout() self.setLayout(layout) self.magnifierSizeLabel = QLabel() self.magnifierSizeSlider = QSlider(Qt.Horizontal, valueChanged=self.changed) self.magnifierSizeSlider.setSingleStep(50) self.magnifierSizeSlider.setRange(*popplerview.MagnifierSettings.sizeRange) self.magnifierSizeSpinBox = QSpinBox() self.magnifierSizeSpinBox.setRange(*popplerview.MagnifierSettings.sizeRange) self.magnifierSizeSpinBox.valueChanged.connect(self.magnifierSizeSlider.setValue) self.magnifierSizeSlider.valueChanged.connect(self.magnifierSizeSpinBox.setValue) layout.addWidget(self.magnifierSizeLabel, 0, 0) layout.addWidget(self.magnifierSizeSlider, 0, 1) layout.addWidget(self.magnifierSizeSpinBox, 0, 2) self.magnifierScaleLabel = QLabel() self.magnifierScaleSlider = QSlider(Qt.Horizontal, valueChanged=self.changed) self.magnifierScaleSlider.setSingleStep(50) self.magnifierScaleSlider.setRange(*popplerview.MagnifierSettings.scaleRange) self.magnifierScaleSpinBox = QSpinBox() self.magnifierScaleSpinBox.setRange(*popplerview.MagnifierSettings.scaleRange) self.magnifierScaleSpinBox.valueChanged.connect(self.magnifierScaleSlider.setValue) self.magnifierScaleSlider.valueChanged.connect(self.magnifierScaleSpinBox.setValue) layout.addWidget(self.magnifierScaleLabel, 1, 0) layout.addWidget(self.magnifierScaleSlider, 1, 1) layout.addWidget(self.magnifierScaleSpinBox, 1, 2) self.enableKineticScrolling = QCheckBox(toggled=self.changed) layout.addWidget(self.enableKineticScrolling) self.showScrollbars = QCheckBox(toggled=self.changed) layout.addWidget(self.showScrollbars) app.translateUI(self) def translateUI(self): self.setTitle(_("Music View")) self.magnifierSizeLabel.setText(_("Magnifier Size:")) self.magnifierSizeLabel.setToolTip(_( "Size of the magnifier glass (Ctrl+Click in the Music View).")) # L10N: as in "400 pixels", appended after number in spinbox, note the leading space self.magnifierSizeSpinBox.setSuffix(_(" pixels")) self.magnifierScaleLabel.setText(_("Magnifier Scale:")) self.magnifierScaleLabel.setToolTip(_( "Magnification of the magnifier.")) self.magnifierScaleSpinBox.setSuffix(_("percent unit sign", "%")) # L10N: "Kinetic Scrolling" is a checkbox label, as in "Enable Kinetic Scrolling" self.enableKineticScrolling.setText(_("Kinetic Scrolling")) self.showScrollbars.setText(_("Show Scrollbars")) def loadSettings(self): s = popplerview.MagnifierSettings.load() self.magnifierSizeSlider.setValue(s.size) self.magnifierScaleSlider.setValue(s.scale) ks = QSettings() kineticScrollingActive = ks.value("musicview/kinetic_scrolling", True) not in (False, "false") self.enableKineticScrolling.setChecked(kineticScrollingActive) showScrollbars = ks.value("musicview/show_scrollbars", True) not in (False, "false") self.showScrollbars.setChecked(showScrollbars) def saveSettings(self): s = popplerview.MagnifierSettings() s.size = self.magnifierSizeSlider.value() s.scale = self.magnifierScaleSlider.value() s.save() ks = QSettings() ks.setValue("musicview/kinetic_scrolling", self.enableKineticScrolling.isChecked()) ks.setValue("musicview/show_scrollbars", self.showScrollbars.isChecked())
class EditorGeneral(QWidget): """EditorGeneral widget class.""" def __init__(self, parent): super(EditorGeneral, self).__init__() self._preferences, vbox = parent, QVBoxLayout(self) self.original_style = copy.copy(resources.CUSTOM_SCHEME) self.current_scheme, self._modified_editors = 'default', [] self._font = settings.FONT groupBoxMini = QGroupBox( translations.TR_PREFERENCES_EDITOR_GENERAL_MINIMAP) groupBoxTypo = QGroupBox( translations.TR_PREFERENCES_EDITOR_GENERAL_TYPOGRAPHY) groupBoxScheme = QGroupBox( translations.TR_PREFERENCES_EDITOR_GENERAL_SCHEME) #Minimap formMini = QGridLayout(groupBoxMini) formMini.setContentsMargins(5, 15, 5, 5) self._checkShowMinimap = QCheckBox( translations.TR_PREFERENCES_EDITOR_GENERAL_ENABLE_MINIMAP) self._spinMaxOpacity = QSpinBox() self._spinMaxOpacity.setRange(0, 100) self._spinMaxOpacity.setSuffix("% Max.") self._spinMinOpacity = QSpinBox() self._spinMinOpacity.setRange(0, 100) self._spinMinOpacity.setSuffix("% Min.") self._spinSize = QSpinBox() self._spinSize.setMaximum(100) self._spinSize.setMinimum(0) self._spinSize.setSuffix( translations.TR_PREFERENCES_EDITOR_GENERAL_AREA_MINIMAP) formMini.addWidget(self._checkShowMinimap, 0, 1) formMini.addWidget(QLabel( translations.TR_PREFERENCES_EDITOR_GENERAL_SIZE_MINIMAP), 1, 0, Qt.AlignRight) formMini.addWidget(self._spinSize, 1, 1) formMini.addWidget(QLabel( translations.TR_PREFERENCES_EDITOR_GENERAL_OPACITY), 2, 0, Qt.AlignRight) formMini.addWidget(self._spinMinOpacity, 2, 1) formMini.addWidget(self._spinMaxOpacity, 2, 2) #Typo gridTypo = QGridLayout(groupBoxTypo) gridTypo.setContentsMargins(5, 15, 5, 5) self._btnEditorFont = QPushButton('') gridTypo.addWidget(QLabel( translations.TR_PREFERENCES_EDITOR_GENERAL_EDITOR_FONT), 0, 0, Qt.AlignRight) gridTypo.addWidget(self._btnEditorFont, 0, 1) #Scheme vboxScheme = QVBoxLayout(groupBoxScheme) vboxScheme.setContentsMargins(5, 15, 5, 5) self._listScheme = QListWidget() vboxScheme.addWidget(self._listScheme) hbox = QHBoxLayout() btnDownload = QPushButton( translations.TR_PREFERENCES_EDITOR_DOWNLOAD_SCHEME) btnDownload.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.connect(btnDownload, SIGNAL("clicked()"), self._open_schemes_manager) hbox.addWidget(btnDownload) btnAdd = QPushButton(QIcon(":img/add"), translations.TR_EDITOR_CREATE_SCHEME) btnAdd.setIconSize(QSize(16, 16)) btnAdd.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.connect(btnAdd, SIGNAL("clicked()"), self._open_schemes_designer) btnRemove = QPushButton(QIcon(":img/delete"), translations.TR_EDITOR_REMOVE_SCHEME) btnRemove.setIconSize(QSize(16, 16)) btnRemove.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.connect(btnRemove, SIGNAL("clicked()"), self._remove_scheme) hbox.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox.addWidget(btnAdd) hbox.addWidget(btnRemove) vboxScheme.addLayout(hbox) vbox.addWidget(groupBoxMini) vbox.addWidget(groupBoxTypo) vbox.addWidget(groupBoxScheme) #Settings qsettings = IDE.ninja_settings() qsettings.beginGroup('preferences') qsettings.beginGroup('editor') self._checkShowMinimap.setChecked(settings.SHOW_MINIMAP) if settings.IS_MAC_OS: self._spinMinOpacity.setValue(100) self._spinMaxOpacity.setValue(100) self._spinMinOpacity.setDisabled(True) self._spinMaxOpacity.setDisabled(True) else: self._spinMinOpacity.setValue(settings.MINIMAP_MIN_OPACITY * 100) self._spinMaxOpacity.setValue(settings.MINIMAP_MAX_OPACITY * 100) self._spinSize.setValue(settings.SIZE_PROPORTION * 100) btnText = ', '.join(self._font.toString().split(',')[0:2]) self._btnEditorFont.setText(btnText) self._listScheme.clear() self._listScheme.addItem('default') self._schemes = json_manager.load_editor_skins() for item in self._schemes: self._listScheme.addItem(item) items = self._listScheme.findItems( qsettings.value('scheme', defaultValue='', type='QString'), Qt.MatchExactly) if items: self._listScheme.setCurrentItem(items[0]) else: self._listScheme.setCurrentRow(0) qsettings.endGroup() qsettings.endGroup() #Signals self.connect(self._btnEditorFont, SIGNAL("clicked()"), self._load_editor_font) self.connect(self._listScheme, SIGNAL("itemSelectionChanged()"), self._preview_style) self.connect(self._preferences, SIGNAL("savePreferences()"), self.save) def _open_schemes_manager(self): ninjaide = IDE.get_service("ide") ninjaide.show_schemes() # refresh schemes def _open_schemes_designer(self): name = self._listScheme.currentItem().text() scheme = self._schemes.get(name, resources.COLOR_SCHEME) designer = preferences_editor_scheme_designer.EditorSchemeDesigner( scheme, self) designer.exec_() if designer.saved: scheme_name = designer.line_name.text() scheme = designer.original_style self._schemes[scheme_name] = scheme result = self._listScheme.findItems(scheme_name, Qt.MatchExactly) if not result: self._listScheme.addItem(scheme_name) def _remove_scheme(self): name = self._listScheme.currentItem().text() fileName = ('{0}.color'.format( file_manager.create_path(resources.EDITOR_SKINS, name))) file_manager.delete_file(fileName) item = self._listScheme.takeItem(self._listScheme.currentRow()) del item def hideEvent(self, event): super(EditorGeneral, self).hideEvent(event) resources.CUSTOM_SCHEME = self.original_style for editorWidget in self._modified_editors: try: editorWidget.restyle(editorWidget.lang) except RuntimeError: print('the editor has been removed') def _preview_style(self): scheme = self._listScheme.currentItem().text() if scheme == self.current_scheme: return main_container = IDE.get_service('main_container') if not main_container: return editorWidget = main_container.get_current_editor() if editorWidget is not None: resources.CUSTOM_SCHEME = self._schemes.get( scheme, resources.COLOR_SCHEME) editorWidget.restyle(editorWidget.lang) self._modified_editors.append(editorWidget) self.current_scheme = scheme def _load_editor_font(self): try: font, ok = QFontDialog.getFont(self._font, self) if ok: self._font = font btnText = ', '.join(self._font.toString().split(',')[0:2]) self._btnEditorFont.setText(btnText) except: QMessageBox.warning( self, translations.TR_PREFERENCES_EDITOR_GENERAL_FONT_MESSAGE_TITLE, translations.TR_PREFERENCES_EDITOR_GENERAL_FONT_MESSAGE_BODY) def save(self): qsettings = IDE.ninja_settings() settings.FONT = self._font qsettings.setValue('preferences/editor/font', settings.FONT) settings.SHOW_MINIMAP = self._checkShowMinimap.isChecked() settings.MINIMAP_MAX_OPACITY = self._spinMaxOpacity.value() / 100.0 settings.MINIMAP_MIN_OPACITY = self._spinMinOpacity.value() / 100.0 settings.SIZE_PROPORTION = self._spinSize.value() / 100.0 qsettings.setValue('preferences/editor/minimapMaxOpacity', settings.MINIMAP_MAX_OPACITY) qsettings.setValue('preferences/editor/minimapMinOpacity', settings.MINIMAP_MIN_OPACITY) qsettings.setValue('preferences/editor/minimapSizeProportion', settings.SIZE_PROPORTION) qsettings.setValue('preferences/editor/minimapShow', settings.SHOW_MINIMAP) scheme = self._listScheme.currentItem().text() resources.CUSTOM_SCHEME = self._schemes.get(scheme, resources.COLOR_SCHEME) qsettings.setValue('preferences/editor/scheme', scheme)
class Indenting(preferences.Group): def __init__(self, page): super(Indenting, self).__init__(page) layout = QGridLayout(spacing=1) self.setLayout(layout) self.tabwidthBox = QSpinBox(minimum=1, maximum=99) self.tabwidthLabel = l = QLabel() l.setBuddy(self.tabwidthBox) self.nspacesBox = QSpinBox(minimum=0, maximum=99) self.nspacesLabel = l = QLabel() l.setBuddy(self.nspacesBox) self.dspacesBox = QSpinBox(minimum=0, maximum=99) self.dspacesLabel = l = QLabel() l.setBuddy(self.dspacesBox) layout.addWidget(self.tabwidthLabel, 0, 0) layout.addWidget(self.tabwidthBox, 0, 1) layout.addWidget(self.nspacesLabel, 1, 0) layout.addWidget(self.nspacesBox, 1, 1) layout.addWidget(self.dspacesLabel, 2, 0) layout.addWidget(self.dspacesBox, 2, 1) self.tabwidthBox.valueChanged.connect(page.changed) self.nspacesBox.valueChanged.connect(page.changed) self.dspacesBox.valueChanged.connect(page.changed) self.translateUI() def translateUI(self): self.setTitle(_("Indenting Preferences")) self.tabwidthLabel.setText(_("Visible Tab Width:")) self.tabwidthBox.setToolTip(_( "The visible width of a Tab character in the editor.")) self.nspacesLabel.setText(_("Indent text with:")) self.nspacesBox.setToolTip(_( "How many spaces to use for indenting one level.\n" "Move to zero to use a Tab character for indenting.")) self.nspacesBox.setSpecialValueText(_("Tab")) self.dspacesLabel.setText(_("Tab outside indent inserts:")) self.dspacesBox.setToolTip(_( "How many spaces to insert when Tab is pressed outside the indent, " "elsewhere in the document.\n" "Move to zero to insert a literal Tab character in this case.")) self.nspacesBox.setSpecialValueText(_("Tab")) self.dspacesBox.setSpecialValueText(_("Tab")) # L10N: abbreviation for "n spaces" in spinbox, n >= 1, no plural forms prefix, suffix = _("{num} spaces").split("{num}") self.nspacesBox.setPrefix(prefix) self.nspacesBox.setSuffix(suffix) self.dspacesBox.setPrefix(prefix) self.dspacesBox.setSuffix(suffix) def loadSettings(self): s = QSettings() s.beginGroup("indent") self.tabwidthBox.setValue(s.value("tab_width", 8, int)) self.nspacesBox.setValue(s.value("indent_spaces", 2, int)) self.dspacesBox.setValue(s.value("document_spaces", 8, int)) def saveSettings(self): s = QSettings() s.beginGroup("indent") s.setValue("tab_width", self.tabwidthBox.value()) s.setValue("indent_spaces", self.nspacesBox.value()) s.setValue("document_spaces", self.dspacesBox.value())
class YPipeWidget(QWidget): def __init__(self, leftFlow=0, rightFlow=0, maxFlow=100, parent=None): super(YPipeWidget, self).__init__(parent) self.leftSpinBox = QSpinBox(self) self.leftSpinBox.setRange(0, maxFlow) self.leftSpinBox.setValue(leftFlow) self.leftSpinBox.setSuffix(" l/s") self.leftSpinBox.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.connect(self.leftSpinBox, SIGNAL("valueChanged(int)"), self.valueChanged) self.rightSpinBox = QSpinBox(self) self.rightSpinBox.setRange(0, maxFlow) self.rightSpinBox.setValue(rightFlow) self.rightSpinBox.setSuffix(" l/s") self.rightSpinBox.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.connect(self.rightSpinBox, SIGNAL("valueChanged(int)"), self.valueChanged) self.label = QLabel(self) self.label.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.label.setAlignment(Qt.AlignCenter) fm = QFontMetricsF(self.font()) self.label.setMinimumWidth(fm.width(" 999 l/s ")) self.setSizePolicy( QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) self.setMinimumSize(self.minimumSizeHint()) self.valueChanged() def valueChanged(self): a = self.leftSpinBox.value() b = self.rightSpinBox.value() self.label.setText("{0} l/s".format(a + b)) self.emit(SIGNAL("valueChanged"), a, b) self.update() def values(self): return self.leftSpinBox.value(), self.rightSpinBox.value() def minimumSizeHint(self): return QSize(self.leftSpinBox.width() * 3, self.leftSpinBox.height() * 5) def resizeEvent(self, event=None): fm = QFontMetricsF(self.font()) x = (self.width() - self.label.width()) / 2 y = self.height() - (fm.height() * 1.5) self.label.move(x, y) y = self.height() / 60.0 x = (self.width() / 4.0) - self.leftSpinBox.width() self.leftSpinBox.move(x, y) x = self.width() - (self.width() / 4.0) self.rightSpinBox.move(x, y) def paintEvent(self, event=None): LogicalSize = 100.0 def logicalFromPhysical(length, side): return (length / side) * LogicalSize fm = QFontMetricsF(self.font()) ymargin = ( (LogicalSize / 30.0) + logicalFromPhysical(self.leftSpinBox.height(), self.height())) ymax = (LogicalSize - logicalFromPhysical(fm.height() * 2, self.height())) width = LogicalSize / 4.0 cx, cy = LogicalSize / 2.0, LogicalSize / 3.0 ax, ay = cx - (2 * width), ymargin bx, by = cx - width, ay dx, dy = cx + width, ay ex, ey = cx + (2 * width), ymargin fx, fy = cx + (width / 2), cx + (LogicalSize / 24.0) gx, gy = fx, ymax hx, hy = cx - (width / 2), ymax ix, iy = hx, fy painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) side = min(self.width(), self.height()) painter.setViewport((self.width() - side) / 2, (self.height() - side) / 2, side, side) painter.setWindow(0, 0, LogicalSize, LogicalSize) painter.setPen(Qt.NoPen) gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100)) gradient.setColorAt(0, Qt.white) a = self.leftSpinBox.value() gradient.setColorAt(1, (Qt.red if a != 0 else Qt.white)) painter.setBrush(QBrush(gradient)) painter.drawPolygon(QPolygon([ax, ay, bx, by, cx, cy, ix, iy])) gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100)) gradient.setColorAt(0, Qt.white) b = self.rightSpinBox.value() gradient.setColorAt(1, (Qt.blue if b != 0 else Qt.white)) painter.setBrush(QBrush(gradient)) painter.drawPolygon(QPolygon([cx, cy, dx, dy, ex, ey, fx, fy])) if (a + b) == 0: color = QColor(Qt.white) else: ashare = (a / (a + b)) * 255.0 bshare = 255.0 - ashare color = QColor(ashare, 0, bshare) gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100)) gradient.setColorAt(0, Qt.white) gradient.setColorAt(1, color) painter.setBrush(QBrush(gradient)) painter.drawPolygon(QPolygon([cx, cy, fx, fy, gx, gy, hx, hy, ix, iy])) painter.setPen(Qt.black) painter.drawPolyline(QPolygon([ax, ay, ix, iy, hx, hy])) painter.drawPolyline(QPolygon([gx, gy, fx, fy, ex, ey])) painter.drawPolyline(QPolygon([bx, by, cx, cy, dx, dy]))
class Window(QMainWindow): def __init__(self, parent=None): super(Window, self).__init__(parent) self.image = QImage() self.dirty = False self.filename = None self.dbFilename = None self.mirroredvertically = False self.mirroredhorizontally = False self.printer = None self.exampleForm= None self.matlPopup= None self.matlPropsHere= None self.create_widgets() self.create_actions() self.load_settings() self.setWindowTitle("Thermapythia") self.updateFileMenu() self.openStackupDB() QTimer.singleShot(0, self.loadInitialFile) def create_widgets(self): self.imageLabel = QLabel() self.imageLabel.setMinimumSize(200, 200) self.imageLabel.setAlignment(Qt.AlignCenter) self.imageLabel.setContextMenuPolicy(Qt.ActionsContextMenu) self.setCentralWidget(self.imageLabel) logDockWidget = QDockWidget("Log", self) logDockWidget.setObjectName("LogDockWidget") logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea| Qt.RightDockWidgetArea) self.listWidget = QListWidget() logDockWidget.setWidget(self.listWidget) self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget) self.sizeLabel = QLabel() self.sizeLabel.setFrameStyle(QFrame.StyledPanel|QFrame.Sunken) status = self.statusBar() status.setSizeGripEnabled(False) status.addPermanentWidget(self.sizeLabel) status.showMessage("Ready", 5000) def create_actions(self): fileNewAction = self.createAction("&New...", self.fileNew, QKeySequence.New, "filenew", "Create an image file") fileOpenAction = self.createAction("&Open...", self.fileOpen, QKeySequence.Open, "fileopen", "Open an existing image file") fileSaveAction = self.createAction("&Save", self.fileSave, QKeySequence.Save, "filesave", "Save the image") fileSaveAsAction = self.createAction("Save &As...", self.fileSaveAs, icon="filesaveas", tip="Save the image using a new name") filePrintAction = self.createAction("&Print", self.filePrint, QKeySequence.Print, "fileprint", "Print the image") fileQuitAction = self.createAction("&Quit", self.close, "Ctrl+Q", "filequit", "Close the application") # createAction(String, slot, shortcut, icon, tip, checkable matlEditAction = self.createAction("&Materials", self.matlEdit, None, "matls", "Edit materials") layerEditAction= self.createAction("&Layers", self.layerEdit, None, "layers", "Edit layers") viaEditAction= self.createAction("&Vias", self.viaEdit, None, "vias", "Edit vias") zzzEditAction= self.createAction("&Zzz", self.zzzEdit, None, "zzz", "Edit zzz") editInvertAction = self.createAction("&Invert", None, "Ctrl+I", "editinvert", "Invert the image's colors", True) editInvertAction.toggled.connect(self.editInvert) editSwapRedAndBlueAction = self.createAction("Sw&ap Red and Blue", None, "Ctrl+A", "editswap", "Swap the image's red and blue color components", True) editSwapRedAndBlueAction.toggled.connect(self.editSwapRedAndBlue) editZoomAction = self.createAction("&Zoom...", self.editZoom, "Alt+Z", "editzoom", "Zoom the image") mirrorGroup = QActionGroup(self) editUnMirrorAction = self.createAction("&Unmirror", None, "Ctrl+U", "editunmirror", "Unmirror the image", True) editUnMirrorAction.toggled.connect(self.editUnMirror) mirrorGroup.addAction(editUnMirrorAction) editMirrorHorizontalAction = self.createAction( "Mirror &Horizontally", None, "Ctrl+H", "editmirrorhoriz", "Horizontally mirror the image", True) editMirrorHorizontalAction.toggled.connect( self.editMirrorHorizontal) mirrorGroup.addAction(editMirrorHorizontalAction) editMirrorVerticalAction = self.createAction("Mirror &Vertically", None, "Ctrl+V", "editmirrorvert", "Vertically mirror the image", True) editMirrorVerticalAction.toggled.connect(self.editMirrorVertical) mirrorGroup.addAction(editMirrorVerticalAction) editUnMirrorAction.setChecked(True) helpAboutAction = self.createAction("&About Thermapythia", self.helpAbout) helpHelpAction = self.createAction("&Help", self.helpHelp, QKeySequence.HelpContents) self.fileMenu = self.menuBar().addMenu("&File") self.fileMenuActions = (fileNewAction, fileOpenAction, fileSaveAction, fileSaveAsAction, None, filePrintAction, fileQuitAction) self.fileMenu.aboutToShow.connect(self.updateFileMenu) stackupMenu = self.menuBar().addMenu("&Stackup") self.addActions(stackupMenu, (matlEditAction, layerEditAction, viaEditAction)) editMenu = self.menuBar().addMenu("&Edit") self.addActions(editMenu, (editInvertAction, editSwapRedAndBlueAction, editZoomAction)) mirrorMenu = editMenu.addMenu(QIcon(":/editmirror.png"), "&Mirror") self.addActions(mirrorMenu, (editUnMirrorAction, editMirrorHorizontalAction, editMirrorVerticalAction)) helpMenu = self.menuBar().addMenu("&Help") self.addActions(helpMenu, (helpAboutAction, helpHelpAction)) fileToolbar = self.addToolBar("File") fileToolbar.setObjectName("FileToolBar") self.addActions(fileToolbar, (fileNewAction, fileOpenAction, fileSaveAsAction)) stackupToolbar = self.addToolBar("Stackup") stackupToolbar.setObjectName("StackupToolBar") self.addActions(stackupToolbar, (matlEditAction, layerEditAction, viaEditAction)) editToolbar = self.addToolBar("Edit") editToolbar.setObjectName("EditToolBar") self.addActions(editToolbar, (editInvertAction, editSwapRedAndBlueAction, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction)) self.zoomSpinBox = QSpinBox() self.zoomSpinBox.setRange(1, 400) self.zoomSpinBox.setSuffix(" %") self.zoomSpinBox.setValue(100) self.zoomSpinBox.setToolTip("Zoom the image") self.zoomSpinBox.setStatusTip(self.zoomSpinBox.toolTip()) self.zoomSpinBox.setFocusPolicy(Qt.NoFocus) self.zoomSpinBox.valueChanged.connect(self.showImage) editToolbar.addWidget(self.zoomSpinBox) self.addActions(self.imageLabel, (editInvertAction, editSwapRedAndBlueAction, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction)) self.resetableActions = ((editInvertAction, False), (editSwapRedAndBlueAction, False), (editUnMirrorAction, True)) def load_settings(self): settings = QSettings() self.recentFiles = settings.value("RecentFiles").toStringList() self.restoreGeometry( settings.value("MainWindow/Geometry").toByteArray()) self.restoreState(settings.value("MainWindow/State").toByteArray()) def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/{0}.png".format(icon))) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.triggered.connect(slot) if checkable: action.setCheckable(True) return action def addActions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def closeEvent(self, event): if self.okToContinue(): settings = QSettings() filename = (QVariant(QString(self.filename)) if self.filename is not None else QVariant()) settings.setValue("LastFile", filename) recentFiles = (QVariant(self.recentFiles) if self.recentFiles else QVariant()) settings.setValue("RecentFiles", recentFiles) settings.setValue("MainWindow/Geometry", QVariant( self.saveGeometry())) settings.setValue("MainWindow/State", QVariant( self.saveState())) else: event.ignore() def okToContinue(self): if self.dirty: reply = QMessageBox.question(self, "Thermapythia - Unsaved Changes", "Save unsaved changes?", QMessageBox.Yes|QMessageBox.No|QMessageBox.Cancel) if reply == QMessageBox.Cancel: return False elif reply == QMessageBox.Yes: return self.fileSave() return True def loadInitialFile(self): settings = QSettings() fname = unicode(settings.value("LastFile").toString()) if fname and QFile.exists(fname): self.loadFile(fname) def updateStatus(self, message): self.statusBar().showMessage(message, 5000) self.listWidget.addItem(message) if self.filename is not None: self.setWindowTitle("Thermapythia - {0}[*]".format( os.path.basename(self.filename))) elif not self.image.isNull(): self.setWindowTitle("Thermapythia - Unnamed[*]") else: self.setWindowTitle("Thermapythia[*]") self.setWindowModified(self.dirty) def updateFileMenu(self): self.fileMenu.clear() self.addActions(self.fileMenu, self.fileMenuActions[:-1]) current = (QString(self.filename) if self.filename is not None else None) recentFiles = [] for fname in self.recentFiles: if fname != current and QFile.exists(fname): recentFiles.append(fname) if recentFiles: self.fileMenu.addSeparator() for i, fname in enumerate(recentFiles): action = QAction(QIcon(":/icon.png"), "&{0} {1}".format(i + 1, QFileInfo( fname).fileName()), self) action.setData(QVariant(fname)) action.triggered.connect(self.loadFile) self.fileMenu.addAction(action) self.fileMenu.addSeparator() self.fileMenu.addAction(self.fileMenuActions[-1]) def fileNew(self): if not self.okToContinue(): return dialog = newimagedlg.NewImageDlg(self) if dialog.exec_(): self.addRecentFile(self.filename) self.image = QImage() for action, check in self.resetableActions: action.setChecked(check) self.image = dialog.image() self.filename = None self.dirty = True self.showImage() self.sizeLabel.setText("{0} x {1}".format(self.image.width(), self.image.height())) self.updateStatus("Created new image") def fileOpen(self): if not self.okToContinue(): return dir = (os.path.dirname(self.filename) if self.filename is not None else ".") formats = (["*.{0}".format(unicode(format).lower()) for format in QImageReader.supportedImageFormats()]) fname = unicode(QFileDialog.getOpenFileName(self, "Thermapythia - Choose Image", dir, "Image files ({0})".format(" ".join(formats)))) if fname: self.loadFile(fname) def loadFile(self, fname=None): if fname is None: action = self.sender() if isinstance(action, QAction): fname = unicode(action.data().toString()) if not self.okToContinue(): return else: return if fname: self.filename = None image = QImage(fname) if image.isNull(): message = "Failed to read {0}".format(fname) else: self.addRecentFile(fname) self.image = QImage() for action, check in self.resetableActions: action.setChecked(check) self.image = image self.filename = fname self.showImage() self.dirty = False self.sizeLabel.setText("{0} x {1}".format( image.width(), image.height())) message = "Loaded {0}".format(os.path.basename(fname)) self.updateStatus(message) def addRecentFile(self, fname): if fname is None: return if not self.recentFiles.contains(fname): self.recentFiles.prepend(QString(fname)) while self.recentFiles.count() > 9: self.recentFiles.takeLast() def fileSave(self): if self.image.isNull(): return True if self.filename is None: return self.fileSaveAs() else: if self.image.save(self.filename, None): self.updateStatus("Saved as {0}".format(self.filename)) self.dirty = False return True else: self.updateStatus("Failed to save {0}".format( self.filename)) return False def fileSaveAs(self): if self.image.isNull(): return True fname = self.filename if self.filename is not None else "." formats = (["*.{0}".format(unicode(format).lower()) for format in QImageWriter.supportedImageFormats()]) fname = unicode(QFileDialog.getSaveFileName(self, "Thermapythia - Save Image", fname, "Image files ({0})".format(" ".join(formats)))) if fname: if "." not in fname: fname += ".png" self.addRecentFile(fname) self.filename = fname return self.fileSave() return False def filePrint(self): if self.image.isNull(): return if self.printer is None: self.printer = QPrinter(QPrinter.HighResolution) self.printer.setPageSize(QPrinter.Letter) form = QPrintDialog(self.printer, self) if form.exec_(): painter = QPainter(self.printer) rect = painter.viewport() size = self.image.size() size.scale(rect.size(), Qt.KeepAspectRatio) painter.setViewport(rect.x(), rect.y(), size.width(), size.height()) painter.drawImage(0, 0, self.image) # def openStackupDB(self): if self.dbFilename != None: return self.dbFilename = os.path.join(os.path.dirname(__file__), "stackup.db") create = not QFile.exists(self.dbFilename) db = QSqlDatabase.addDatabase("QSQLITE") db.setDatabaseName(self.dbFilename) if not db.open(): QMessageBox.warning(None, "Can't open stackup database", QString("Database Error: %1").arg(db.lastError().text())) sys.exit(1) if create == False: self.updateStatus("Found stackup database file: " + str(self.dbFilename)) self.createDatabaseTables() with open('test2.js', "r") as jsonHandle: jsonContents= jsonHandle.read() config= yaml.load(jsonContents) matlCount= self.countDatabaseTableRows("matl") if matlCount == 0: self.updateStatus("material editor call goes here.") # # TODO: Put the guess-what-I'm thinking Qt table editor thing here. # # self.loadDefaultMatls() matls = Matls.Matls(config['matl_config']) self.loadDefaultData('matl', matls) viaCount= self.countDatabaseTableRows("via") if viaCount == 0: vias = Vias.Vias(config['via_config']) self.loadDefaultData('via', vias) layerCount= self.countDatabaseTableRows("layer") if layerCount == 0: layers = Layers.Layers(config['layer_config']) self.loadDefaultData('layer', layers) # initialize zzz new content here, perhaps def createDatabaseTables(self): query = QSqlQuery() self.updateStatus("Creating database tables") # "id" INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, statusMatl = query.exec_("""CREATE TABLE IF NOT EXISTS "matl" ( "name" TEXT, "type" TEXT, "density" real, "color" TEXT, "specific_heat" real, "conductivity" real, "conductivityXX" real, "conductivityYY" real, "conductivityZZ" real, "reflection_coeff" real, "emissivity" real, "max_height" real, "thickness" real );""") if statusMatl == False: self.updateStatus("Could not create material property database table 'matl'") self.updateStatus("Database error message: " + query.lastError().text()) statusPhylayer = query.exec_("""CREATE TABLE IF NOT EXISTS "layer" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, "name" TEXT, "matl" TEXT, "type" TEXT, "thickness" real, "displaces" TEXT, "coverage" real, "z_bottom" real, "z_top" real, "adheres_to" TEXT);""") if statusPhylayer == False: self.updateStatus("Could not create material property database table 'layer'") self.updateStatus("Database error message: " + query.lastError().text()) statusVia = query.exec_("""CREATE TABLE IF NOT EXISTS "via" ( "id" INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, "name" TEXT, "matl" TEXT, "to" TEXT, "from" TEXT);""") if statusVia == False: self.updateStatus("Could not create material property database table 'via'") self.updateStatus("Database error message: " + query.lastError().text()) def countDatabaseTableRows(self, tablename): query = QSqlQuery() self.updateStatus("Loading database tables") query.prepare("select count(*) from " + tablename + ";") status = query.exec_() if status == False: self.updateStatus("Could not count entries in table '" + tablename + "'") self.updateStatus("Database error message: " + query.lastError().text()) query.first() count, ok = query.value(0).toInt() # self.updateStatus("There are " + str(count) + " rows in the " + tablename + " table") return count def loadDefaultData(self, table, data): query = QSqlQuery() insertList= "', '".join(data.tableCols) insertList= "'" + insertList + "'" colCount= len(data.tableCols) quest= "" for i in range(0, colCount): quest = quest + "?," quest= quest[:-1] sql= "INSERT INTO " + table + "(" + insertList + ") VALUES (" + quest + ");" # self.updateStatus(sql) status= query.prepare(sql) if status == False: self.updateStatus("Could not prepare material property database table " + table) self.updateStatus("Database error message: " + query.lastError().text()) for row in data.propDict: for prop in data.tableCols: propval= data.propDict[row][prop] if data.tableColSQLTypes[prop] == 'TEXT': query.addBindValue(QVariant(QString(propval))) # self.updateStatus("Setting TEXT property " + prop + " to value " + str(propval) + " in row " + str(row)) elif data.tableColSQLTypes[prop] == 'real': if (propval == '-'): propreal= -999.9 else: propreal= float(propval) query.addBindValue(QVariant(propreal)) # self.updateStatus("Setting real property " + prop + " to value " + str(propreal) + " in row " + str(row)) status= query.exec_() if status == False: self.updateStatus("Could not load property database table " + table + " with " + str(row)) self.updateStatus("Database error message: " + query.lastError().text()) def matlEdit(self): self.dirty= True self.updateStatus("Call edit material code here") # This ends up in a little child window self.matlPopup= QLabel("<font color=green size=72><b> Material Editor </b></font>") # self.matlPopup.setWindowFlags(Qt.SplashScreen) self.matlPopup.setWindowTitle("Material edit popup") self.matlPropsHere= QLabel("<font color=red size=24><b> Data goes here </b></font>") # self.matlPopup.setWindowFlags(Qt.SplashScreen) if 1 == 0: dataLayout= QVBoxLayout() dataLayout.addWidget(self.matlPopup) dataLayout.addWidget(self.matlPropsHere) self.setLayout(dataLayout) self.matlPopup.show() self.matlPropsHere.show() # self.exampleForm= MatlForm() # First need a layout manager, and add the widget to that. # Then attach the layout manager to a window. # addWidget(self.exampleForm) # self.exampleForm.show() QTimer.singleShot(5000, self.update) self.updateStatus("Created stackup db") def layerEdit(self): self.dirty= True self.updateStatus("Call edit layer code here") # This way of doing it is modal - window doesn't go away and covers up other windows until it is dismissed. form= MatlForm() form.exec_() def viaEdit(self): self.dirty= True self.updateStatus("Call edit via code here") def zzzEdit(self): self.dirty= True self.updateStatus("Call code to be triggered by zzz button here") def editInvert(self, on): if self.image.isNull(): return self.image.invertPixels() self.showImage() self.dirty = True self.updateStatus("Inverted" if on else "Uninverted") def editSwapRedAndBlue(self, on): if self.image.isNull(): return self.image = self.image.rgbSwapped() self.showImage() self.dirty = True self.updateStatus(("Swapped Red and Blue" if on else "Unswapped Red and Blue")) def editUnMirror(self, on): if self.image.isNull(): return if self.mirroredhorizontally: self.editMirrorHorizontal(False) if self.mirroredvertically: self.editMirrorVertical(False) def editMirrorHorizontal(self, on): if self.image.isNull(): return self.image = self.image.mirrored(True, False) self.showImage() self.mirroredhorizontally = not self.mirroredhorizontally self.dirty = True self.updateStatus(("Mirrored Horizontally" if on else "Unmirrored Horizontally")) def editMirrorVertical(self, on): if self.image.isNull(): return self.image = self.image.mirrored(False, True) self.showImage() self.mirroredvertically = not self.mirroredvertically self.dirty = True self.updateStatus(("Mirrored Vertically" if on else "Unmirrored Vertically")) def editZoom(self): if self.image.isNull(): return percent, ok = QInputDialog.getInteger(self, "Thermapythia - Zoom", "Percent:", self.zoomSpinBox.value(), 1, 400) if ok: self.zoomSpinBox.setValue(percent) def showImage(self, percent=None): if self.image.isNull(): return if percent is None: percent = self.zoomSpinBox.value() factor = percent / 100.0 width = self.image.width() * factor height = self.image.height() * factor image = self.image.scaled(width, height, Qt.KeepAspectRatio) self.imageLabel.setPixmap(QPixmap.fromImage(image)) def helpAbout(self): QMessageBox.about(self, "About Thermapythia", """<b>Thermapythia</b> v {0} <p>Thermal Analyzer in Python predicts circuit board temperature <p>Python {1} - Qt {2} - PyQt {3} on {4}""".format( __version__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system())) def helpHelp(self): form = HelpForm.HelpForm("index.html", self) form.show()
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self._create_components() self._place_components() self._create_controller() self.setWindowTitle("Job Crawler") def _create_components(self): self.site_gb = QGroupBox(u"Choix des sites") self.param_gb = QGroupBox(u"Autres Paramètres") self.search_gb = QGroupBox(u"Mots-clé") self.log_gb = QGroupBox(u"Logs") self.apec_cb = QCheckBox(u"APEC") self.apec_cb.setDisabled(True) self.caoe_cb = QCheckBox(u"CAO Emploi") self.caoe_cb.setDisabled(True) self.inde_cb = QCheckBox(u"Indeed") self.mons_cb = QCheckBox(u"Monster Job") self.mons_cb.setDisabled(True) self.pole_cb = QCheckBox(u"Pole Enmploi") self.pole_cb.setDisabled(True) self.regi_cb = QCheckBox(u"Région Job") self.regi_cb.setDisabled(True) self.search_label = QLabel(u"Mots-clé de recherche") self.filter_label = QLabel(u"Critère de filtrage") self.region_label = QLabel(u"Région") self.daterange_label = QLabel(u"Plage de recherche") self.search_qle = QLineEdit() self.filter_qle = QLineEdit() self.start_button = QPushButton(u"Rechercher") self.stop_button = QPushButton(u"Stopper") self.stop_button.setDisabled(True) self.daterange_sb = QSpinBox() self.daterange_sb.setMaximum(40) self.daterange_sb.setProperty("value", 3) self.daterange_sb.setSuffix(u" Jours") self.region_cb = QComboBox() region_list = toolbox.getconfigvalue("STATIC", "regions").split(',') self.region_cb.addItems(region_list) self.log_te = QTextEdit() self.log_te.setReadOnly(True) self.log_te.setLineWrapMode(QTextEdit.NoWrap) self.file_menu = QMenu(u"Fichier") self.help_menu = QMenu(u"Aide") def _place_components(self): site_layout = QHBoxLayout() temp = QVBoxLayout() temp.addWidget(self.apec_cb) temp.addWidget(self.caoe_cb) temp.addWidget(self.inde_cb) site_layout.addLayout(temp) temp = QVBoxLayout() temp.addWidget(self.mons_cb) temp.addWidget(self.pole_cb) temp.addWidget(self.regi_cb) site_layout.addLayout(temp) self.site_gb.setLayout(site_layout) search_layout = QVBoxLayout() search_layout.addWidget(self.search_label) search_layout.addWidget(self.search_qle) search_layout.addWidget(self.filter_label) search_layout.addWidget(self.filter_qle) self.search_gb.setLayout(search_layout) param_layout = QVBoxLayout() param_layout.addWidget(self.daterange_label) param_layout.addWidget(self.daterange_sb) param_layout.addWidget(self.region_label) param_layout.addWidget(self.region_cb) self.param_gb.setLayout(param_layout) log_layout = QVBoxLayout() log_layout.addWidget(self.log_te) self.log_gb.setLayout(log_layout) command_layout = QHBoxLayout() command_layout.addWidget(self.start_button) command_layout.addWidget(self.stop_button) main_layout = QVBoxLayout() main_layout.addWidget(self.site_gb) main_layout.addWidget(self.search_gb) main_layout.addWidget(self.param_gb) main_layout.addWidget(self.log_gb) main_layout.addLayout(command_layout) centralwidget = QWidget(self) centralwidget.setLayout(main_layout) self.setCentralWidget(centralwidget) menubar = self.menuBar() menubar.addMenu(self.file_menu) menubar.addMenu(self.help_menu) def _create_controller(self): adminAction = QAction(u'Administration', self) adminAction.setStatusTip(u'Régler les paramètres de l\'application') adminAction.triggered.connect(self.admin) exitAction = QAction(u'Quitter', self) exitAction.setStatusTip(u'Quitter Job Crawler') exitAction.triggered.connect(qApp.quit) aboutAction = QAction(u'A propos', self) aboutAction.setStatusTip(u'Afficher la fenêtre à propos') aboutAction.triggered.connect(self.about) self.file_menu.addAction(adminAction) self.file_menu.addSeparator() self.file_menu.addAction(exitAction) self.help_menu.addAction(aboutAction) self.start_button.clicked.connect(self.start) self.stop_button.clicked.connect(self.stop) # Controller for logging XStream.stdout().messageWritten.connect( self.log_te.insertPlainText ) XStream.stderr().messageWritten.connect( self.log_te.insertPlainText ) def validate_fields(self): error = False error_list = u"" inde = self.inde_cb.isChecked() apec = self.apec_cb.isChecked() caoe = self.caoe_cb.isChecked() mons = self.mons_cb.isChecked() pole = self.pole_cb.isChecked() regi = self.regi_cb.isChecked() if not (inde or apec or caoe or mons or pole or regi): error = True error_list += u"<li>Site à requêter</li>" searchkeyword = unidecode(unicode(self.search_qle.text())) if searchkeyword == u"": error = True error_list += u"<li>Mots clé de recherche</li>" filterkeyword = unidecode(unicode(self.filter_qle.text())) if filterkeyword == u"": error = True error_list += u"<li>Critère de filtrage</li>" if error: message = u"Veuillez renseigner le(s) champ(s) suivant(s) :<ul>" + error_list + u"</ul>" QMessageBox.warning(self, u"Erreur", message) return not error def validate_admin(self): dbpath = toolbox.getconfigvalue("GENERAL", "dbfile") if not (dbpath != "" and os.access(os.path.dirname(dbpath), os.W_OK)): message = u"<p>Veuiller renseigner l'emplacement de la base de données dans l'administration (Fichier > Administration).</p>"\ u"<p>Si cela a déjà été fait, ce message signifie que vous n'avez pas les droits d'écriture dans ce répertoire. Veuillez déplacer la base de données et reconfigurer l'emplacement dans l'administration.</p>" QMessageBox.warning(self, u"Erreur", message) return False return True @pyqtSlot() def start(self): def run(): self.start_button.setDisabled(True) # self.stop_button.setEnabled(True) logger.info(u"Début") inde = self.inde_cb.isChecked() apec = self.apec_cb.isChecked() caoe = self.caoe_cb.isChecked() mons = self.mons_cb.isChecked() pole = self.pole_cb.isChecked() regi = self.regi_cb.isChecked() searchkeyword = unidecode(unicode(self.search_qle.text())).split(",") filterkeyword = unidecode(unicode(self.filter_qle.text())).split(",") daterange = self.daterange_sb.value() region = str(self.region_cb.currentText()) dbpath = toolbox.getconfigvalue("GENERAL", "dbfile") excludelist = unidecode(toolbox.getconfigvalue("GENERAL", "excludes")).split(",") c = core.core(dbpath) logger.info(u"Recherche d'annonces") c.found_annonce(searchkeyword, daterange, region, None, apec, caoe, inde, mons, pole, regi) logger.info(u"Tri des annonces par rapport aux mots-clé d'exclusion") c.exclude_annouces(excludelist) logger.info(u"Tri des annonces par rapport aux critères de filtrage") c.filter_announces(filterkeyword) logger.info(u"Fin") # self.stop_button.setDisabled(True) self.start_button.setEnabled(True) if self.validate_fields() and self.validate_admin(): self.thread = threading.Thread(target=run) self.thread.start() @pyqtSlot() def stop(self): self.thread._Thread__stop() self.stop_button.setDisabled(True) self.start_button.setEnabled(True) @pyqtSlot() def about(self): self.aboutwindow = aboutdialog.AboutDialog(self).exec_() @pyqtSlot() def admin(self): admindialog.AdminDialog(self).exec_()
class Indenting(preferences.Group): def __init__(self, page): super(Indenting, self).__init__(page) layout = QGridLayout(spacing=1) self.setLayout(layout) self.tabwidthBox = QSpinBox(minimum=1, maximum=99) self.tabwidthLabel = l = QLabel() l.setBuddy(self.tabwidthBox) self.nspacesBox = QSpinBox(minimum=0, maximum=99) self.nspacesLabel = l = QLabel() l.setBuddy(self.nspacesBox) self.dspacesBox = QSpinBox(minimum=0, maximum=99) self.dspacesLabel = l = QLabel() l.setBuddy(self.dspacesBox) layout.addWidget(self.tabwidthLabel, 0, 0) layout.addWidget(self.tabwidthBox, 0, 1) layout.addWidget(self.nspacesLabel, 1, 0) layout.addWidget(self.nspacesBox, 1, 1) layout.addWidget(self.dspacesLabel, 2, 0) layout.addWidget(self.dspacesBox, 2, 1) self.tabwidthBox.valueChanged.connect(page.changed) self.nspacesBox.valueChanged.connect(page.changed) self.dspacesBox.valueChanged.connect(page.changed) self.translateUI() def translateUI(self): self.setTitle(_("Indenting Preferences")) self.tabwidthLabel.setText(_("Visible Tab Width:")) self.tabwidthBox.setToolTip(_( "The visible width of a Tab character in the editor.")) self.nspacesLabel.setText(_("Indent text with:")) self.nspacesBox.setToolTip(_( "How many spaces to use for indenting one level.\n" "Move to zero to use a Tab character for indenting.")) self.nspacesBox.setSpecialValueText(_("Tab")) self.dspacesLabel.setText(_("Tab ouside indent inserts:")) self.dspacesBox.setToolTip(_( "How many spaces to insert when Tab is pressed outside the indent, " "elsewhere in the document.\n" "Move to zero to insert a literal Tab character in this case.")) self.nspacesBox.setSpecialValueText(_("Tab")) self.dspacesBox.setSpecialValueText(_("Tab")) # L10N: abbreviation for "n spaces" in spinbox, n >= 1, no plural forms prefix, suffix = _("{num} spaces").split("{num}") self.nspacesBox.setPrefix(prefix) self.nspacesBox.setSuffix(suffix) self.dspacesBox.setPrefix(prefix) self.dspacesBox.setSuffix(suffix) def loadSettings(self): s = QSettings() s.beginGroup("indent") self.tabwidthBox.setValue(s.value("tab_width", 8, int)) self.nspacesBox.setValue(s.value("indent_spaces", 2, int)) self.dspacesBox.setValue(s.value("document_spaces", 8, int)) def saveSettings(self): s = QSettings() s.beginGroup("indent") s.setValue("tab_width", self.tabwidthBox.value()) s.setValue("indent_spaces", self.nspacesBox.value()) s.setValue("document_spaces", self.dspacesBox.value())
class IndustrialDualAnalogInV2(COMCUPluginBase): def __init__(self, *args): COMCUPluginBase.__init__(self, BrickletIndustrialDualAnalogInV2, *args) self.analog_in = self.device self.cbe_voltage0 = CallbackEmulator(functools.partial(self.analog_in.get_voltage, 0), functools.partial(self.cb_voltage, 0), self.increase_error_count) self.cbe_voltage1 = CallbackEmulator(functools.partial(self.analog_in.get_voltage, 1), functools.partial(self.cb_voltage, 1), self.increase_error_count) self.calibration = None self.sample_rate_label = QLabel('Sample Rate:') self.sample_rate_combo = QComboBox() self.sample_rate_combo.addItem('976 Hz') self.sample_rate_combo.addItem('488 Hz') self.sample_rate_combo.addItem('244 Hz') self.sample_rate_combo.addItem('122 Hz') self.sample_rate_combo.addItem('61 Hz') self.sample_rate_combo.addItem('4 Hz') self.sample_rate_combo.addItem('2 Hz') self.sample_rate_combo.addItem('1 Hz') self.current_voltage = [None, None] # float, V self.calibration_button = QPushButton('Calibration...') self.sample_rate_combo.currentIndexChanged.connect(self.sample_rate_combo_index_changed) self.calibration_button.clicked.connect(self.calibration_button_clicked) plots = [('Channel 0', Qt.red, lambda: self.current_voltage[0], format_voltage), ('Channel 1', Qt.blue, lambda: self.current_voltage[1], format_voltage)] self.plot_widget = PlotWidget('Voltage [V]', plots) # Define lines line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) line1 = QFrame() line1.setFrameShape(QFrame.HLine) line1.setFrameShadow(QFrame.Sunken) line2 = QFrame() line2.setFrameShape(QFrame.HLine) line2.setFrameShadow(QFrame.Sunken) # Define channel LED status config widgets self.led_config_ch0_label = QLabel('Channel 0') self.led_config_ch1_label = QLabel('Channel 1') self.led_config_label = QLabel('LED Config:') self.led_status_config_label = QLabel('LED Status Config:') self.led_status_config_ch0_min_label = QLabel('Min:') self.led_status_config_ch0_max_label = QLabel('Max:') self.led_status_config_ch1_min_label = QLabel('Min:') self.led_status_config_ch1_max_label = QLabel('Max:') self.led_config_ch0_combo = QComboBox() self.led_config_ch0_combo.addItem('Off') self.led_config_ch0_combo.addItem('On') self.led_config_ch0_combo.addItem('Show Heartbeat') self.led_config_ch0_combo.addItem('Show Channel Status') self.led_config_ch0_combo.currentIndexChanged.connect(self.led_config_ch0_combo_changed) self.led_config_ch1_combo = QComboBox() self.led_config_ch1_combo.addItem('Off') self.led_config_ch1_combo.addItem('On') self.led_config_ch1_combo.addItem('Show Heartbeat') self.led_config_ch1_combo.addItem('Show Channel Status') self.led_config_ch1_combo.currentIndexChanged.connect(self.led_config_ch1_combo_changed) self.led_status_config_ch0_combo = QComboBox() self.led_status_config_ch0_combo.addItem('Threshold') self.led_status_config_ch0_combo.addItem('Intensity') self.led_status_config_ch0_combo.currentIndexChanged.connect(self.led_status_config_ch0_combo_changed) self.led_status_config_ch1_combo = QComboBox() self.led_status_config_ch1_combo.addItem('Threshold') self.led_status_config_ch1_combo.addItem('Intensity') self.led_status_config_ch1_combo.currentIndexChanged.connect(self.led_status_config_ch1_combo_changed) self.led_status_config_ch0_min_sbox = QSpinBox() self.led_status_config_ch0_min_sbox.setMinimum(-35000) self.led_status_config_ch0_min_sbox.setMaximum(35000) self.led_status_config_ch0_min_sbox.setValue(0) self.led_status_config_ch0_min_sbox.setSingleStep(1) self.led_status_config_ch0_min_sbox.setSuffix(' mV') self.led_status_config_ch0_min_sbox.valueChanged.connect(self.led_status_config_ch0_min_sbox_changed) self.led_status_config_ch0_max_sbox = QSpinBox() self.led_status_config_ch0_max_sbox.setMinimum(-35000) self.led_status_config_ch0_max_sbox.setMaximum(35000) self.led_status_config_ch0_max_sbox.setValue(0) self.led_status_config_ch0_max_sbox.setSingleStep(1) self.led_status_config_ch0_max_sbox.setSuffix(' mV') self.led_status_config_ch0_max_sbox.valueChanged.connect(self.led_status_config_ch0_max_sbox_changed) self.led_status_config_ch1_min_sbox = QSpinBox() self.led_status_config_ch1_min_sbox.setMinimum(-35000) self.led_status_config_ch1_min_sbox.setMaximum(35000) self.led_status_config_ch1_min_sbox.setValue(0) self.led_status_config_ch1_min_sbox.setSingleStep(1) self.led_status_config_ch1_min_sbox.setSuffix(' mV') self.led_status_config_ch1_min_sbox.valueChanged.connect(self.led_status_config_ch1_min_sbox_changed) self.led_status_config_ch1_max_sbox = QSpinBox() self.led_status_config_ch1_max_sbox.setMinimum(-35000) self.led_status_config_ch1_max_sbox.setMaximum(35000) self.led_status_config_ch1_max_sbox.setValue(0) self.led_status_config_ch1_max_sbox.setSingleStep(1) self.led_status_config_ch1_max_sbox.setSuffix(' mV') self.led_status_config_ch1_max_sbox.valueChanged.connect(self.led_status_config_ch1_max_sbox_changed) # Define size policies h_sp = QSizePolicy() h_sp.setHorizontalPolicy(QSizePolicy.Expanding) # Set size policies self.sample_rate_combo.setSizePolicy(h_sp) self.led_config_ch0_combo.setSizePolicy(h_sp) self.led_config_ch1_combo.setSizePolicy(h_sp) self.led_status_config_ch0_combo.setSizePolicy(h_sp) self.led_status_config_ch1_combo.setSizePolicy(h_sp) self.led_status_config_ch0_min_sbox.setSizePolicy(h_sp) self.led_status_config_ch0_max_sbox.setSizePolicy(h_sp) self.led_status_config_ch1_min_sbox.setSizePolicy(h_sp) self.led_status_config_ch1_max_sbox.setSizePolicy(h_sp) # Define layouts hlayout = QHBoxLayout() vlayout = QVBoxLayout() glayout = QGridLayout() layout = QVBoxLayout(self) hlayout_ch0_min_max = QHBoxLayout() hlayout_ch1_min_max = QHBoxLayout() # Populate layouts vlayout.addWidget(self.calibration_button) hlayout.addWidget(self.sample_rate_label) hlayout.addWidget(self.sample_rate_combo) vlayout.addLayout(hlayout) vlayout.addWidget(line1) hlayout_ch0_min_max.addWidget(self.led_status_config_ch0_min_label) hlayout_ch0_min_max.addWidget(self.led_status_config_ch0_min_sbox) hlayout_ch0_min_max.addWidget(self.led_status_config_ch0_max_label) hlayout_ch0_min_max.addWidget(self.led_status_config_ch0_max_sbox) hlayout_ch1_min_max.addWidget(self.led_status_config_ch1_min_label) hlayout_ch1_min_max.addWidget(self.led_status_config_ch1_min_sbox) hlayout_ch1_min_max.addWidget(self.led_status_config_ch1_max_label) hlayout_ch1_min_max.addWidget(self.led_status_config_ch1_max_sbox) glayout.addWidget(self.led_config_ch0_label, 0, 1, 1, 1) # R, C, RS, CS glayout.addWidget(self.led_config_ch1_label, 0, 2, 1, 1) glayout.addWidget(line2, 1, 0, 1, 3) glayout.addWidget(self.led_config_label, 2, 0, 1, 1) glayout.addWidget(self.led_config_ch0_combo, 2, 1, 1, 1) glayout.addWidget(self.led_config_ch1_combo, 2, 2, 1, 1) glayout.addWidget(self.led_status_config_label, 3, 0, 1, 1) glayout.addWidget(self.led_status_config_ch0_combo, 3, 1, 1, 1) glayout.addWidget(self.led_status_config_ch1_combo, 3, 2, 1, 1) glayout.addLayout(hlayout_ch0_min_max, 4, 1, 1, 1) glayout.addLayout(hlayout_ch1_min_max, 4, 2, 1, 1) layout.addWidget(self.plot_widget) layout.addWidget(line) layout.addLayout(vlayout) layout.addLayout(glayout) self.ui_group_ch_status_ch0 = [self.led_status_config_ch0_combo, self.led_status_config_ch0_min_sbox, self.led_status_config_ch0_max_sbox] self.ui_group_ch_status_ch1 = [self.led_status_config_ch1_combo, self.led_status_config_ch1_min_sbox, self.led_status_config_ch1_max_sbox] def start(self): async_call(self.analog_in.get_voltage, 0, lambda x: self.cb_voltage(0, x), self.increase_error_count) async_call(self.analog_in.get_voltage, 1, lambda x: self.cb_voltage(1, x), self.increase_error_count) async_call(self.analog_in.get_sample_rate, None, self.get_sample_rate_async, self.increase_error_count) async_call(self.analog_in.get_channel_led_config, CH_0, lambda config: self.get_channel_led_config_async(CH_0, config), self.increase_error_count) async_call(self.analog_in.get_channel_led_status_config, CH_0, lambda config: self.get_channel_led_status_config_async(CH_0, config), self.increase_error_count) async_call(self.analog_in.get_channel_led_config, CH_1, lambda config: self.get_channel_led_config_async(CH_1, config), self.increase_error_count) async_call(self.analog_in.get_channel_led_status_config, CH_1, lambda config: self.get_channel_led_status_config_async(CH_1, config), self.increase_error_count) self.cbe_voltage0.set_period(100) self.cbe_voltage1.set_period(100) self.plot_widget.stop = False def stop(self): self.cbe_voltage0.set_period(0) self.cbe_voltage1.set_period(0) self.plot_widget.stop = True def destroy(self): if self.calibration != None: self.calibration.close() @staticmethod def has_device_identifier(device_identifier): return device_identifier == BrickletIndustrialDualAnalogInV2.DEVICE_IDENTIFIER def calibration_button_clicked(self): if self.calibration == None: self.calibration = Calibration(self) self.calibration_button.setEnabled(False) self.calibration.show() def sample_rate_combo_index_changed(self, index): async_call(self.analog_in.set_sample_rate, index, None, self.increase_error_count) def led_config_ch0_combo_changed(self, index): if index != self.analog_in.CHANNEL_LED_CONFIG_SHOW_CHANNEL_STATUS: for e in self.ui_group_ch_status_ch0: e.setEnabled(False) else: for e in self.ui_group_ch_status_ch0: e.setEnabled(True) self.analog_in.set_channel_led_config(CH_0, index) def led_config_ch1_combo_changed(self, index): if index != self.analog_in.CHANNEL_LED_CONFIG_SHOW_CHANNEL_STATUS: for e in self.ui_group_ch_status_ch1: e.setEnabled(False) else: for e in self.ui_group_ch_status_ch1: e.setEnabled(True) self.analog_in.set_channel_led_config(CH_1, index) def led_status_config_ch0_combo_changed(self, index): self.analog_in.set_channel_led_status_config(CH_0, self.led_status_config_ch0_min_sbox.value(), self.led_status_config_ch0_max_sbox.value(), index) def led_status_config_ch1_combo_changed(self, index): self.analog_in.set_channel_led_status_config(CH_1, self.led_status_config_ch1_min_sbox.value(), self.led_status_config_ch1_max_sbox.value(), index) def led_status_config_ch0_min_sbox_changed(self, value): QObject.sender(self).blockSignals(True) self.analog_in.set_channel_led_status_config(CH_0, self.led_status_config_ch0_min_sbox.value(), self.led_status_config_ch0_max_sbox.value(), self.led_status_config_ch0_combo.currentIndex()) QObject.sender(self).blockSignals(False) def led_status_config_ch0_max_sbox_changed(self, value): QObject.sender(self).blockSignals(True) self.analog_in.set_channel_led_status_config(CH_0, self.led_status_config_ch0_min_sbox.value(), self.led_status_config_ch0_max_sbox.value(), self.led_status_config_ch0_combo.currentIndex()) QObject.sender(self).blockSignals(False) def led_status_config_ch1_min_sbox_changed(self, value): QObject.sender(self).blockSignals(True) self.analog_in.set_channel_led_status_config(CH_1, self.led_status_config_ch1_min_sbox.value(), self.led_status_config_ch1_max_sbox.value(), self.led_status_config_ch1_combo.currentIndex()) QObject.sender(self).blockSignals(False) def led_status_config_ch1_max_sbox_changed(self, value): QObject.sender(self).blockSignals(True) self.analog_in.set_channel_led_status_config(CH_1, self.led_status_config_ch1_min_sbox.value(), self.led_status_config_ch1_max_sbox.value(), self.led_status_config_ch1_combo.currentIndex()) QObject.sender(self).blockSignals(False) def get_voltage_value0(self): return self.voltage_value[0] def get_voltage_value1(self): return self.voltage_value[1] def get_sample_rate_async(self, rate): self.sample_rate_combo.blockSignals(True) self.sample_rate_combo.setCurrentIndex(rate) self.sample_rate_combo.blockSignals(False) def get_channel_led_config_async(self, channel, config): self.led_config_ch0_combo.blockSignals(True) self.led_config_ch1_combo.blockSignals(True) if channel == CH_0: self.led_config_ch0_combo.setCurrentIndex(config) elif channel == CH_1: self.led_config_ch1_combo.setCurrentIndex(config) self.led_config_ch0_combo.blockSignals(False) self.led_config_ch1_combo.blockSignals(False) def get_channel_led_status_config_async(self, channel, config): self.led_status_config_ch0_combo.blockSignals(True) self.led_status_config_ch1_combo.blockSignals(True) if channel == CH_0: self.led_status_config_ch0_combo.setCurrentIndex(config.config) self.led_status_config_ch0_max_sbox.setValue(config.max) self.led_status_config_ch0_min_sbox.setValue(config.min) elif channel == CH_1: self.led_status_config_ch1_combo.setCurrentIndex(config.config) self.led_status_config_ch1_max_sbox.setValue(config.max) self.led_status_config_ch1_min_sbox.setValue(config.min) self.led_status_config_ch0_combo.blockSignals(False) self.led_status_config_ch1_combo.blockSignals(False) def cb_voltage(self, sensor, voltage): self.current_voltage[sensor] = voltage / 1000.0
class Window(QMainWindow): def __init__(self, parent=None): super(Window, self).__init__(parent) self.image = QImage() self.dirty = False self.filename = None self.mirroredvertically = False self.mirroredhorizontally = False self.printer = None self.create_widgets() self.create_actions() self.load_settings() self.setWindowTitle("Image Changer") self.updateFileMenu() QTimer.singleShot(0, self.loadInitialFile) def create_widgets(self): self.imageLabel = QLabel() self.imageLabel.setMinimumSize(200, 200) self.imageLabel.setAlignment(Qt.AlignCenter) self.imageLabel.setContextMenuPolicy(Qt.ActionsContextMenu) self.setCentralWidget(self.imageLabel) logDockWidget = QDockWidget("Log", self) logDockWidget.setObjectName("LogDockWidget") logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.listWidget = QListWidget() logDockWidget.setWidget(self.listWidget) self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget) self.sizeLabel = QLabel() self.sizeLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) status = self.statusBar() status.setSizeGripEnabled(False) status.addPermanentWidget(self.sizeLabel) status.showMessage("Ready", 5000) def create_actions(self): fileNewAction = self.createAction("&New...", self.fileNew, QKeySequence.New, "filenew", "Create an image file") fileOpenAction = self.createAction("&Open...", self.fileOpen, QKeySequence.Open, "fileopen", "Open an existing image file") fileSaveAction = self.createAction("&Save", self.fileSave, QKeySequence.Save, "filesave", "Save the image") fileSaveAsAction = self.createAction( "Save &As...", self.fileSaveAs, icon="filesaveas", tip="Save the image using a new name") filePrintAction = self.createAction("&Print", self.filePrint, QKeySequence.Print, "fileprint", "Print the image") fileQuitAction = self.createAction("&Quit", self.close, "Ctrl+Q", "filequit", "Close the application") editInvertAction = self.createAction("&Invert", None, "Ctrl+I", "editinvert", "Invert the image's colors", True) editInvertAction.toggled.connect(self.editInvert) editSwapRedAndBlueAction = self.createAction( "Sw&ap Red and Blue", None, "Ctrl+A", "editswap", "Swap the image's red and blue color components", True) editSwapRedAndBlueAction.toggled.connect(self.editSwapRedAndBlue) editZoomAction = self.createAction("&Zoom...", self.editZoom, "Alt+Z", "editzoom", "Zoom the image") mirrorGroup = QActionGroup(self) editUnMirrorAction = self.createAction("&Unmirror", None, "Ctrl+U", "editunmirror", "Unmirror the image", True) editUnMirrorAction.toggled.connect(self.editUnMirror) mirrorGroup.addAction(editUnMirrorAction) editMirrorHorizontalAction = self.createAction( "Mirror &Horizontally", None, "Ctrl+H", "editmirrorhoriz", "Horizontally mirror the image", True) editMirrorHorizontalAction.toggled.connect(self.editMirrorHorizontal) mirrorGroup.addAction(editMirrorHorizontalAction) editMirrorVerticalAction = self.createAction( "Mirror &Vertically", None, "Ctrl+V", "editmirrorvert", "Vertically mirror the image", True) editMirrorVerticalAction.toggled.connect(self.editMirrorVertical) mirrorGroup.addAction(editMirrorVerticalAction) editUnMirrorAction.setChecked(True) helpAboutAction = self.createAction("&About Image Changer", self.helpAbout) helpHelpAction = self.createAction("&Help", self.helpHelp, QKeySequence.HelpContents) self.fileMenu = self.menuBar().addMenu("&File") self.fileMenuActions = (fileNewAction, fileOpenAction, fileSaveAction, fileSaveAsAction, None, filePrintAction, fileQuitAction) self.fileMenu.aboutToShow.connect(self.updateFileMenu) editMenu = self.menuBar().addMenu("&Edit") self.addActions( editMenu, (editInvertAction, editSwapRedAndBlueAction, editZoomAction)) mirrorMenu = editMenu.addMenu(QIcon(":/editmirror.png"), "&Mirror") self.addActions(mirrorMenu, (editUnMirrorAction, editMirrorHorizontalAction, editMirrorVerticalAction)) helpMenu = self.menuBar().addMenu("&Help") self.addActions(helpMenu, (helpAboutAction, helpHelpAction)) fileToolbar = self.addToolBar("File") fileToolbar.setObjectName("FileToolBar") self.addActions(fileToolbar, (fileNewAction, fileOpenAction, fileSaveAsAction)) editToolbar = self.addToolBar("Edit") editToolbar.setObjectName("EditToolBar") self.addActions( editToolbar, (editInvertAction, editSwapRedAndBlueAction, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction)) self.zoomSpinBox = QSpinBox() self.zoomSpinBox.setRange(1, 400) self.zoomSpinBox.setSuffix(" %") self.zoomSpinBox.setValue(100) self.zoomSpinBox.setToolTip("Zoom the image") self.zoomSpinBox.setStatusTip(self.zoomSpinBox.toolTip()) self.zoomSpinBox.setFocusPolicy(Qt.NoFocus) self.zoomSpinBox.valueChanged.connect(self.showImage) editToolbar.addWidget(self.zoomSpinBox) self.addActions( self.imageLabel, (editInvertAction, editSwapRedAndBlueAction, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction)) self.resetableActions = ((editInvertAction, False), (editSwapRedAndBlueAction, False), (editUnMirrorAction, True)) def load_settings(self): settings = QSettings() self.recentFiles = settings.value("RecentFiles").toStringList() self.restoreGeometry( settings.value("MainWindow/Geometry").toByteArray()) self.restoreState(settings.value("MainWindow/State").toByteArray()) def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/{0}.png".format(icon))) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.triggered.connect(slot) if checkable: action.setCheckable(True) return action def addActions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def closeEvent(self, event): if self.okToContinue(): settings = QSettings() filename = (QVariant(QString(self.filename)) if self.filename is not None else QVariant()) settings.setValue("LastFile", filename) recentFiles = (QVariant(self.recentFiles) if self.recentFiles else QVariant()) settings.setValue("RecentFiles", recentFiles) settings.setValue("MainWindow/Geometry", QVariant(self.saveGeometry())) settings.setValue("MainWindow/State", QVariant(self.saveState())) else: event.ignore() def okToContinue(self): if self.dirty: reply = QMessageBox.question( self, "Image Changer - Unsaved Changes", "Save unsaved changes?", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if reply == QMessageBox.Cancel: return False elif reply == QMessageBox.Yes: return self.fileSave() return True def loadInitialFile(self): settings = QSettings() fname = unicode(settings.value("LastFile").toString()) if fname and QFile.exists(fname): self.loadFile(fname) def updateStatus(self, message): self.statusBar().showMessage(message, 5000) self.listWidget.addItem(message) if self.filename is not None: self.setWindowTitle("Image Changer - {0}[*]".format( os.path.basename(self.filename))) elif not self.image.isNull(): self.setWindowTitle("Image Changer - Unnamed[*]") else: self.setWindowTitle("Image Changer[*]") self.setWindowModified(self.dirty) def updateFileMenu(self): self.fileMenu.clear() self.addActions(self.fileMenu, self.fileMenuActions[:-1]) current = (QString(self.filename) if self.filename is not None else None) recentFiles = [] for fname in self.recentFiles: if fname != current and QFile.exists(fname): recentFiles.append(fname) if recentFiles: self.fileMenu.addSeparator() for i, fname in enumerate(recentFiles): action = QAction( QIcon(":/icon.png"), "&{0} {1}".format(i + 1, QFileInfo(fname).fileName()), self) action.setData(QVariant(fname)) action.triggered.connect(self.loadFile) self.fileMenu.addAction(action) self.fileMenu.addSeparator() self.fileMenu.addAction(self.fileMenuActions[-1]) def fileNew(self): if not self.okToContinue(): return dialog = newimagedlg.NewImageDlg(self) if dialog.exec_(): self.addRecentFile(self.filename) self.image = QImage() for action, check in self.resetableActions: action.setChecked(check) self.image = dialog.image() self.filename = None self.dirty = True self.showImage() self.sizeLabel.setText("{0} x {1}".format(self.image.width(), self.image.height())) self.updateStatus("Created new image") def fileOpen(self): if not self.okToContinue(): return dir = (os.path.dirname(self.filename) if self.filename is not None else ".") formats = ([ "*.{0}".format(unicode(format).lower()) for format in QImageReader.supportedImageFormats() ]) fname = unicode( QFileDialog.getOpenFileName( self, "Image Changer - Choose Image", dir, "Image files ({0})".format(" ".join(formats)))) if fname: self.loadFile(fname) def loadFile(self, fname=None): if fname is None: action = self.sender() if isinstance(action, QAction): fname = unicode(action.data().toString()) if not self.okToContinue(): return else: return if fname: self.filename = None image = QImage(fname) if image.isNull(): message = "Failed to read {0}".format(fname) else: self.addRecentFile(fname) self.image = QImage() for action, check in self.resetableActions: action.setChecked(check) self.image = image self.filename = fname self.showImage() self.dirty = False self.sizeLabel.setText("{0} x {1}".format( image.width(), image.height())) message = "Loaded {0}".format(os.path.basename(fname)) self.updateStatus(message) def addRecentFile(self, fname): if fname is None: return if not self.recentFiles.contains(fname): self.recentFiles.prepend(QString(fname)) while self.recentFiles.count() > 9: self.recentFiles.takeLast() def fileSave(self): if self.image.isNull(): return True if self.filename is None: return self.fileSaveAs() else: if self.image.save(self.filename, None): self.updateStatus("Saved as {0}".format(self.filename)) self.dirty = False return True else: self.updateStatus("Failed to save {0}".format(self.filename)) return False def fileSaveAs(self): if self.image.isNull(): return True fname = self.filename if self.filename is not None else "." formats = ([ "*.{0}".format(unicode(format).lower()) for format in QImageWriter.supportedImageFormats() ]) fname = unicode( QFileDialog.getSaveFileName( self, "Image Changer - Save Image", fname, "Image files ({0})".format(" ".join(formats)))) if fname: if "." not in fname: fname += ".png" self.addRecentFile(fname) self.filename = fname return self.fileSave() return False def filePrint(self): if self.image.isNull(): return if self.printer is None: self.printer = QPrinter(QPrinter.HighResolution) self.printer.setPageSize(QPrinter.Letter) form = QPrintDialog(self.printer, self) if form.exec_(): painter = QPainter(self.printer) rect = painter.viewport() size = self.image.size() size.scale(rect.size(), Qt.KeepAspectRatio) painter.setViewport(rect.x(), rect.y(), size.width(), size.height()) painter.drawImage(0, 0, self.image) def editInvert(self, on): if self.image.isNull(): return self.image.invertPixels() self.showImage() self.dirty = True self.updateStatus("Inverted" if on else "Uninverted") def editSwapRedAndBlue(self, on): if self.image.isNull(): return self.image = self.image.rgbSwapped() self.showImage() self.dirty = True self.updateStatus( ("Swapped Red and Blue" if on else "Unswapped Red and Blue")) def editUnMirror(self, on): if self.image.isNull(): return if self.mirroredhorizontally: self.editMirrorHorizontal(False) if self.mirroredvertically: self.editMirrorVertical(False) def editMirrorHorizontal(self, on): if self.image.isNull(): return self.image = self.image.mirrored(True, False) self.showImage() self.mirroredhorizontally = not self.mirroredhorizontally self.dirty = True self.updateStatus( ("Mirrored Horizontally" if on else "Unmirrored Horizontally")) def editMirrorVertical(self, on): if self.image.isNull(): return self.image = self.image.mirrored(False, True) self.showImage() self.mirroredvertically = not self.mirroredvertically self.dirty = True self.updateStatus( ("Mirrored Vertically" if on else "Unmirrored Vertically")) def editZoom(self): if self.image.isNull(): return percent, ok = QInputDialog.getInteger(self, "Image Changer - Zoom", "Percent:", self.zoomSpinBox.value(), 1, 400) if ok: self.zoomSpinBox.setValue(percent) def showImage(self, percent=None): if self.image.isNull(): return if percent is None: percent = self.zoomSpinBox.value() factor = percent / 100.0 width = self.image.width() * factor height = self.image.height() * factor image = self.image.scaled(width, height, Qt.KeepAspectRatio) self.imageLabel.setPixmap(QPixmap.fromImage(image)) def helpAbout(self): QMessageBox.about( self, "About Image Changer", """<b>Image Changer</b> v {0} <p>Copyright © 2008-14 Qtrac Ltd. All rights reserved. <p>This application can be used to perform simple image manipulations. <p>Python {1} - Qt {2} - PyQt {3} on {4}""".format( __version__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system())) def helpHelp(self): form = helpform.HelpForm("index.html", self) form.show()
class Img2GifWidget(QDialog): AppName = u"GIF生成工具" def __init__(self, parent=None): super(Img2GifWidget, self).__init__(parent) self.setWindowTitle(Img2GifWidget.AppName) self.listWidget = QListWidget() self.listWidget.setMinimumSize(400, 300) self.btnAdd = QPushButton("&Add") self.btnUp = QPushButton("&Up") self.btnDown = QPushButton("&Down") self.btnDel = QPushButton("&Delete") self.btnClear = QPushButton("&Clear") topLeftLay = QVBoxLayout() topLeftLay.addWidget(self.btnAdd) topLeftLay.addWidget(self.btnUp) topLeftLay.addWidget(self.btnDown) topLeftLay.addWidget(self.btnDel) topLeftLay.addWidget(self.btnClear) topLeftLay.addStretch() topLay = QHBoxLayout() topLay.addWidget(self.listWidget) topLay.addLayout(topLeftLay) label = QLabel(u"Gif文件路径:") self.txtGifPath = QLineEdit() self.btnBrowser = QPushButton('...') midLay = QHBoxLayout() midLay.addWidget(label) midLay.addWidget(self.txtGifPath) midLay.addWidget(self.btnBrowser) timeLabel = QLabel(u"时间间隔:") self.spbTime = QDoubleSpinBox() self.spbTime.setRange(0.001, 10) self.spbTime.setSingleStep(0.001) self.spbTime.setValue(1) self.spbTime.setSuffix('s') loopLabel = QLabel(u"循环:") self.spbLoop = QDoubleSpinBox() self.spbLoop = QSpinBox() self.spbLoop.setRange(0, 1000) self.spbLoop.setSingleStep(1) self.spbLoop.setValue(0) self.spbLoop.setToolTip(u"0次循环表示永久循环") self.spbLoop.setSuffix(u"次") self.btnBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bottomLay = QHBoxLayout() bottomLay.addWidget(timeLabel) bottomLay.addWidget(self.spbTime) bottomLay.addWidget(loopLabel) bottomLay.addWidget(self.spbLoop) bottomLay.addStretch() bottomLay.addWidget(self.btnBox) mainLay = QVBoxLayout() mainLay.addLayout(topLay) mainLay.addLayout(midLay) mainLay.addLayout(bottomLay) self.setLayout(mainLay) self.btnAdd.clicked.connect(self.itemAdd) self.btnUp.clicked.connect(self.itemUp) self.btnDown.clicked.connect(self.itemDown) self.btnDel.clicked.connect(self.itemDel) self.btnClear.clicked.connect(self.listWidget.clear) self.btnBrowser.clicked.connect(self.setGifPath) self.btnBox.rejected.connect(self.close) self.btnBox.accepted.connect(self.makeGif) self.txtGifPath.returnPressed.connect(self.updateGifPath) def itemAdd(self): fileNames = QFileDialog.getOpenFileNames(None, u"{0} -- {1}".format(qApp.applicationName(), Img2GifWidget.AppName), '.', u'所有文件(*.*);;BMP文件(*.bmp);;PNG文件(*.png);;JPG文件(*.jpg *.jpeg)') for fn in fileNames: f = QFileInfo(fn) if unicode(f.suffix().toLower()) in ['jpg', 'png', 'bmp', 'jpeg']: self.listWidget.addItem(fn) def itemUp(self): row = self.listWidget.currentRow() if row <= 0: return item = self.listWidget.currentItem() self.listWidget.takeItem(row) self.listWidget.insertItem(row - 1, item) self.listWidget.setCurrentRow(row - 1) def itemDown(self): rows = self.listWidget.count() row = self.listWidget.currentRow() if (row < 0) or (row == rows - 1): return item = self.listWidget.currentItem() self.listWidget.takeItem(row) self.listWidget.insertItem(row + 1, item) self.listWidget.setCurrentRow(row + 1) def itemDel(self): row = self.listWidget.currentRow() if row >= 0: self.listWidget.takeItem(row) def setGifPath(self): filename = QFileDialog.getSaveFileName(self, u"{0} -- {1}".format(qApp.applicationName(), Img2GifWidget.AppName), ".", "Gif(*.gif)") self.txtGifPath.setText(filename) def updateGifPath(self): fileName = self.txtGifPath.text() f = QFileInfo(fileName) if f.dir().exists and not f.baseName().isEmpty() and not f.suffix().isEmpty(): self.txtGifPath.setText(fileName) return True else: QMessageBox.warning(self, u"{0} -- warning".format(Img2GifWidget.AppName), u"要生成的GIF存储路径{0}不是有效的GIF文件".format(unicode(fileName))) return False def makeGif(self): imgs = [unicode(self.listWidget.item(i).text()) for i in range(self.listWidget.count())] if len(imgs) <= 1: QMessageBox.warning(self, u"{0} - {1}".format(qApp.applicationName(), Img2GifWidget.AppName), u"GIF动画文件必须要给定大于一张图片。") return if not self.updateGifPath(): return durations = self.spbTime.value() loops = self.spbLoop.value() ok, msg = img2gif.images2gif(imgs, self.txtGifPath.text(), durations=durations, loops=loops) if ok: QMessageBox.about(self, u"{0} - {1}".format(qApp.applicationName(), Img2GifWidget.AppName), u"Succeed!\n{0}".format(msg)) qApp.processEvents() else: QMessageBox.about(u"{0} - {1}".format(qApp.applicationName(), Img2GifWidget.AppName), u"sorry! Failed to generate the {0}".format(unicode(self.txtGifPath)))