Example #1
0
 def create_spinbox(self, prefix, suffix, option, 
                    min_=None, max_=None, step=None, tip=None):
     if prefix:
         plabel = QLabel(prefix)
     else:
         plabel = None
     if suffix:
         slabel = QLabel(suffix)
     else:
         slabel = None
     spinbox = QSpinBox()
     if min_ is not None:
         spinbox.setMinimum(min_)
     if max_ is not None:
         spinbox.setMaximum(max_)
     if step is not None:
         spinbox.setSingleStep(step)
     if tip is not None:
         spinbox.setToolTip(tip)
     self.spinboxes[spinbox] = option
     layout = QHBoxLayout()
     for subwidget in (plabel, spinbox, slabel):
         if subwidget is not None:
             layout.addWidget(subwidget)
     layout.addStretch(1)
     layout.setContentsMargins(0, 0, 0, 0)
     widget = QWidget(self)
     widget.setLayout(layout)
     widget.spin = spinbox
     return widget
Example #2
0
 def create_spinbox(self, prefix, suffix, option, default=NoDefault,
                    min_=None, max_=None, step=None, tip=None):
     if prefix:
         plabel = QLabel(prefix)
     else:
         plabel = None
     if suffix:
         slabel = QLabel(suffix)
     else:
         slabel = None
     spinbox = QSpinBox()
     if min_ is not None:
         spinbox.setMinimum(min_)
     if max_ is not None:
         spinbox.setMaximum(max_)
     if step is not None:
         spinbox.setSingleStep(step)
     if tip is not None:
         spinbox.setToolTip(tip)
     self.spinboxes[spinbox] = (option, default)
     layout = QHBoxLayout()
     for subwidget in (plabel, spinbox, slabel):
         if subwidget is not None:
             layout.addWidget(subwidget)
     layout.addStretch(1)
     layout.setContentsMargins(0, 0, 0, 0)
     widget = QWidget(self)
     widget.setLayout(layout)
     return widget
Example #3
0
    def __init__(self, parent, prefix = None, suffix = None, option = None, min_ = None, max_ = None,
                 step = None, tip = None, value = None, changed =None):
        super(MySpinBox, self).__init__(parent)
    
        if prefix:
            plabel = QLabel(prefix)
        else:
            plabel = None
        if suffix:
            slabel = QLabel(suffix)
        else:
            slabel = None
        spinbox = QSpinBox(parent)
        if min_ is not None:
            spinbox.setMinimum(min_)
        if max_ is not None:
            spinbox.setMaximum(max_)
        if step is not None:
            spinbox.setSingleStep(step)
        if tip is not None:
            spinbox.setToolTip(tip)
        layout = QHBoxLayout()
        for subwidget in (plabel, spinbox, slabel):
            if subwidget is not None:
                layout.addWidget(subwidget)
        if value is not None:
            spinbox.setValue(value)
        
        if changed is not None:
            self.connect(spinbox, SIGNAL('valueChanged(int)'), changed)

        layout.addStretch(1)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)
        self.spin = spinbox
Example #4
0
class Organ(KeyboardPart):
    @staticmethod
    def title(_=_base.translate):
        return _("Organ")
    
    @staticmethod
    def short(_=_base.translate):
        return _("abbreviation for Organ", "Org.")
    
    midiInstrument = 'church organ'

    def createWidgets(self, layout):
        super(Organ, self).createWidgets(layout)
        grid = layout.itemAt(layout.count() - 1).layout()
        self.pedalVoices = QSpinBox(minimum=0, maximum=4, value=1)
        self.pedalVoicesLabel = QLabel()
        self.pedalVoicesLabel.setBuddy(self.pedalVoices)
        grid.addWidget(self.pedalVoicesLabel, 2, 0)
        grid.addWidget(self.pedalVoices)
        
    def translateWidgets(self):
        super(Organ, self).translateWidgets()
        self.pedalVoicesLabel.setText(_("Pedal:"))
        self.pedalVoices.setToolTip(_(
            "Set to 0 to disable the pedal altogether."))
    
    def build(self, data, builder):
        super(Organ, self).build(data, builder)
        if self.pedalVoices.value():
            data.nodes.append(self.buildStaff(data, builder,
                'pedal', -1, self.pedalVoices.value(), clef="bass"))
class IntegerParameterWidget(NumericParameterWidget):
    """Widget class for Integer parameter."""
    def __init__(self, parameter, parent=None):
        """Constructor

        .. versionadded:: 2.2

        :param parameter: A IntegerParameter object.
        :type parameter: IntegerParameter

        """
        super(IntegerParameterWidget, self).__init__(parameter, parent)

        self._input = QSpinBox()
        self._input.setValue(self._parameter.value)
        self._input.setMinimum(self._parameter.minimum_allowed_value)
        self._input.setMaximum(self._parameter.maximum_allowed_value)
        tool_tip = 'Choose a number between %d and %d' % (
            self._parameter.minimum_allowed_value,
            self._parameter.maximum_allowed_value)
        self._input.setToolTip(tool_tip)

        self._input.setSizePolicy(self._spin_box_size_policy)

        self.inner_input_layout.addWidget(self._input)
        self.inner_input_layout.addWidget(self._unit_widget)
Example #6
0
class IntegerParameterWidget(NumericParameterWidget):
    """Widget class for Integer parameter."""
    def __init__(self, parameter, parent=None):
        """Constructor

        .. versionadded:: 2.2

        :param parameter: A IntegerParameter object.
        :type parameter: IntegerParameter

        """
        super(IntegerParameterWidget, self).__init__(parameter, parent)

        self._input = QSpinBox()
        self._input.setValue(self._parameter.value)
        self._input.setMinimum(self._parameter.minimum_allowed_value)
        self._input.setMaximum(self._parameter.maximum_allowed_value)
        tool_tip = 'Choose a number between %d and %d' % (
            self._parameter.minimum_allowed_value,
            self._parameter.maximum_allowed_value)
        self._input.setToolTip(tool_tip)

        self._input.setSizePolicy(self._spin_box_size_policy)

        self._inner_input_layout.addWidget(self._input)
        self._inner_input_layout.addWidget(self._unit_widget)
Example #7
0
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)
Example #8
0
    def addSpinBox(self,
                   attribute_name,
                   title,
                   tool_tip=None,
                   min_value=1,
                   max_value=10,
                   single_step=1):
        sb = QSpinBox()
        self[attribute_name] = sb
        sb.setMaximumHeight(25)
        sb_layout = QHBoxLayout()
        sb_layout.addWidget(sb)
        sb_layout.addStretch()
        self.addRow(title, sb_layout)

        if tool_tip is not None:
            sb.setToolTip(tool_tip)

        sb.setMinimum(min_value)
        sb.setMaximum(max_value)
        sb.setSingleStep(single_step)

        def getter(self):
            return self[attribute_name].value()

        def setter(self, value):
            self[attribute_name].setValue(value)

        self.updateProperty(attribute_name, getter, setter)
        return sb
Example #9
0
class Organ(KeyboardPart):
    @staticmethod
    def title(_=__builtin__._):
        return _("Organ")
    
    @staticmethod
    def short(_=__builtin__._):
        return _("abbreviation for Organ", "Org.")
    
    midiInstrument = 'church organ'

    def createWidgets(self, layout):
        super(Organ, self).createWidgets(layout)
        grid = layout.itemAt(layout.count() - 1).layout()
        self.pedalVoices = QSpinBox(minimum=0, maximum=4, value=1)
        self.pedalVoicesLabel = QLabel()
        self.pedalVoicesLabel.setBuddy(self.pedalVoices)
        grid.addWidget(self.pedalVoicesLabel, 2, 0)
        grid.addWidget(self.pedalVoices)
        
    def translateWidgets(self):
        super(Organ, self).translateWidgets()
        self.pedalVoicesLabel.setText(_("Pedal:"))
        self.pedalVoices.setToolTip(_(
            "Set to 0 to disable the pedal altogether."))
    
    def build(self, data, builder):
        super(Organ, self).build(data, builder)
        if self.pedalVoices.value():
            data.nodes.append(self.buildStaff(data, builder,
                'pedal', -1, self.pedalVoices.value(), clef="bass"))
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)
Example #11
0
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())
Example #12
0
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)
Example #13
0
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())
Example #14
0
class ViewSettings(preferences.Group):
    def __init__(self, page):
        super(ViewSettings, self).__init__(page)
        
        layout = QGridLayout(spacing=1)
        self.setLayout(layout)
        
        self.wrapLines = QCheckBox(toggled=self.changed)
        self.numContextLines = QSpinBox(minimum=0, maximum=20, valueChanged=self.changed)
        self.numContextLinesLabel = l = QLabel()
        l.setBuddy(self.numContextLines)
        
        layout.addWidget(self.wrapLines, 0, 0, 1, 1)
        layout.addWidget(self.numContextLinesLabel, 1, 0)
        layout.addWidget(self.numContextLines, 1, 1)
        app.translateUI(self)
    
    def translateUI(self):
        self.setTitle(_("View Preferences"))
        self.wrapLines.setText(_("Wrap long lines by default"))
        self.wrapLines.setToolTip('<qt>' + _(
            "If enabled, lines that don't fit in the editor width are wrapped "
            "by default. "
            "Note: when the document is displayed by multiple views, they all "
            "share the same line wrapping width, which might look strange."))
        self.numContextLinesLabel.setText(_("Number of surrounding lines:"))
        self.numContextLines.setToolTip('<qt>' + _(
            "When jumping between search results or clicking on a link, the "
            "text view tries to scroll as few lines as possible. "
            "Here you can speficy how many surrounding lines at least should "
            "be visible."))
        self.numContextLinesLabel.setToolTip(self.numContextLines.toolTip())

    def loadSettings(self):
        s = QSettings()
        s.beginGroup("view_preferences")
        self.wrapLines.setChecked(s.value("wrap_lines", False, bool))
        self.numContextLines.setValue(s.value("context_lines", 3, int))
    
    def saveSettings(self):
        s = QSettings()
        s.beginGroup("view_preferences")
        s.setValue("wrap_lines", self.wrapLines.isChecked())
        s.setValue("context_lines", self.numContextLines.value())
Example #15
0
class ViewSettings(preferences.Group):
    def __init__(self, page):
        super(ViewSettings, self).__init__(page)

        layout = QGridLayout(spacing=1)
        self.setLayout(layout)

        self.wrapLines = QCheckBox(toggled=self.changed)
        self.numContextLines = QSpinBox(minimum=0, maximum=20, valueChanged=self.changed)
        self.numContextLinesLabel = l = QLabel()
        l.setBuddy(self.numContextLines)

        layout.addWidget(self.wrapLines, 0, 0, 1, 1)
        layout.addWidget(self.numContextLinesLabel, 1, 0)
        layout.addWidget(self.numContextLines, 1, 1)
        app.translateUI(self)

    def translateUI(self):
        self.setTitle(_("View Preferences"))
        self.wrapLines.setText(_("Wrap long lines by default"))
        self.wrapLines.setToolTip('<qt>' + _(
            "If enabled, lines that don't fit in the editor width are wrapped "
            "by default. "
            "Note: when the document is displayed by multiple views, they all "
            "share the same line wrapping width, which might look strange."))
        self.numContextLinesLabel.setText(_("Number of surrounding lines:"))
        self.numContextLines.setToolTip('<qt>' + _(
            "When jumping between search results or clicking on a link, the "
            "text view tries to scroll as few lines as possible. "
            "Here you can specify how many surrounding lines at least should "
            "be visible."))
        self.numContextLinesLabel.setToolTip(self.numContextLines.toolTip())

    def loadSettings(self):
        s = QSettings()
        s.beginGroup("view_preferences")
        self.wrapLines.setChecked(s.value("wrap_lines", False, bool))
        self.numContextLines.setValue(s.value("context_lines", 3, int))

    def saveSettings(self):
        s = QSettings()
        s.beginGroup("view_preferences")
        s.setValue("wrap_lines", self.wrapLines.isChecked())
        s.setValue("context_lines", self.numContextLines.value())
Example #16
0
    def __init__(self,
                 parent,
                 prefix=None,
                 suffix=None,
                 option=None,
                 min_=None,
                 max_=None,
                 step=None,
                 tip=None,
                 value=None,
                 changed=None):
        super(MySpinBox, self).__init__(parent)

        if prefix:
            plabel = QLabel(prefix)
        else:
            plabel = None
        if suffix:
            slabel = QLabel(suffix)
        else:
            slabel = None
        spinbox = QSpinBox(parent)
        if min_ is not None:
            spinbox.setMinimum(min_)
        if max_ is not None:
            spinbox.setMaximum(max_)
        if step is not None:
            spinbox.setSingleStep(step)
        if tip is not None:
            spinbox.setToolTip(tip)
        layout = QHBoxLayout()
        for subwidget in (plabel, spinbox, slabel):
            if subwidget is not None:
                layout.addWidget(subwidget)
        if value is not None:
            spinbox.setValue(value)

        if changed is not None:
            self.connect(spinbox, SIGNAL('valueChanged(int)'), changed)

        layout.addStretch(1)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)
        self.spin = spinbox
def _get_pos_widget(name, backgroundColor, foregroundColor):
    label = QLabel()
    label.setAttribute(Qt.WA_TransparentForMouseEvents, True)

    pixmap = QPixmap(25*10, 25*10)
    pixmap.fill(backgroundColor)
    painter = QPainter()
    painter.begin(pixmap)
    pen = QPen(foregroundColor)
    painter.setPen(pen)
    painter.setRenderHint(QPainter.Antialiasing)
    font = QFont()
    font.setBold(True)
    font.setPixelSize(25*10-30)
    path = QPainterPath()
    path.addText(QPointF(50, 25*10-50), font, name)
    brush = QBrush(foregroundColor)
    painter.setBrush(brush)
    painter.drawPath(path)
    painter.setFont(font)
    painter.end()
    pixmap = pixmap.scaled(QSize(20,20),
                           Qt.KeepAspectRatio,
                           Qt.SmoothTransformation)
    label.setPixmap(pixmap)

    spinbox = QSpinBox()
    spinbox.setAttribute(Qt.WA_TransparentForMouseEvents, True)
    spinbox.setEnabled(False)
    spinbox.setAlignment(Qt.AlignCenter)
    spinbox.setToolTip("{0} Spin Box".format(name))
    spinbox.setButtonSymbols(QAbstractSpinBox.NoButtons)
    spinbox.setMaximumHeight(20)
    spinbox.setMaximum(9999)
    font = spinbox.font()
    font.setPixelSize(14)
    spinbox.setFont(font)
    sheet = TEMPLATE.format(foregroundColor.name(),
                            backgroundColor.name())
    spinbox.setStyleSheet(sheet)
    return label, spinbox
Example #18
0
def _get_pos_widget(name, backgroundColor, foregroundColor):
    label = QLabel()
    label.setAttribute(Qt.WA_TransparentForMouseEvents, True)

    pixmap = QPixmap(25*10, 25*10)
    pixmap.fill(backgroundColor)
    painter = QPainter()
    painter.begin(pixmap)
    pen = QPen(foregroundColor)
    painter.setPen(pen)
    painter.setRenderHint(QPainter.Antialiasing)
    font = QFont()
    font.setBold(True)
    font.setPixelSize(25*10-30)
    path = QPainterPath()
    path.addText(QPointF(50, 25*10-50), font, name)
    brush = QBrush(foregroundColor)
    painter.setBrush(brush)
    painter.drawPath(path)
    painter.setFont(font)
    painter.end()
    pixmap = pixmap.scaled(QSize(20,20),
                           Qt.KeepAspectRatio,
                           Qt.SmoothTransformation)
    label.setPixmap(pixmap)

    spinbox = QSpinBox()
    spinbox.setAttribute(Qt.WA_TransparentForMouseEvents, True)
    spinbox.setEnabled(False)
    spinbox.setAlignment(Qt.AlignCenter)
    spinbox.setToolTip("{0} Spin Box".format(name))
    spinbox.setButtonSymbols(QAbstractSpinBox.NoButtons)
    spinbox.setMaximumHeight(20)
    spinbox.setMaximum(9999)
    font = spinbox.font()
    font.setPixelSize(14)
    spinbox.setFont(font)
    sheet = TEMPLATE.format(foregroundColor.name(),
                            backgroundColor.name())
    spinbox.setStyleSheet(sheet)
    return label, spinbox
Example #19
0
class PointParameterWidget(GenericParameterWidget):
    """Widget class for Integer parameter."""
    def __init__(self, parameter, parent=None):
        """Constructor

        .. versionadded:: 2.2

        :param parameter: A IntegerParameter object.
        :type parameter: IntegerParameter

        """
        # Size policy
        self._spin_box_size_policy = QSizePolicy(
            QSizePolicy.Fixed, QSizePolicy.Fixed)

        super(PointParameterWidget, self).__init__(parameter, parent)

        self._input_x = QSpinBox()
        self._input_x.setValue(self._parameter.value[0])
        tool_tip = 'X'
        self._input_x.setToolTip(tool_tip)
        self._input_x.setSizePolicy(self._spin_box_size_policy)

        self._input_y = QSpinBox()
        self._input_y.setValue(self._parameter.value[1])
        tool_tip = 'Y'
        self._input_y.setToolTip(tool_tip)
        self._input_y.setSizePolicy(self._spin_box_size_policy)

        self._inner_input_layout.addWidget(self._input_x)
        self._inner_input_layout.addWidget(self._input_y)

    def get_parameter(self):
        """Obtain boolean parameter object from the current widget state.

        :returns: A BooleanParameter from the current state of widget

        """
        self._parameter.value = (self._input_x.value(), self._input_y.value())
        return self._parameter
Example #20
0
class CADOptionsToolbar_RPolygon(CADOptionsToolbar):
    def __init__(self):
        super(CADOptionsToolbar_RPolygon, self).__init__()
        self.settings = QSettings()

        self.spinBox = QSpinBox(self.optionsToolBar)
        self.spinBox.setMinimum(3)
        self.spinBox.setMaximum(3600)
        segvalue = self.settings.value("/CADDigitize/rpolygon/nbedges",
                                       5,
                                       type=int)
        if not segvalue:
            self.settings.setValue("/CADDigitize/rpolygon/nbedges", 5)
        self.spinBox.setValue(segvalue)
        self.spinBox.setSingleStep(1)
        self.spinBoxAction = self.optionsToolBar.addWidget(self.spinBox)
        self.spinBox.setToolTip(tr(u"Number of edges"))
        self.spinBoxAction.setEnabled(True)

        self.spinBox.valueChanged["int"].connect(self.edgesSettingsRPolygon)

    def edgesSettingsRPolygon(self):
        self.settings.setValue("/CADDigitize/rpolygon/nbedges",
                               self.spinBox.value())
Example #21
0
class CADOptionsToolbar_Ellipse(CADOptionsToolbar):
    def __init__(self):
        super(CADOptionsToolbar_Ellipse, self).__init__()
        self.settings = QSettings()

        self.spinBox = QSpinBox(self.optionsToolBar)
        self.spinBox.setMinimum(3)
        self.spinBox.setMaximum(3600)
        segvalue = self.settings.value("/CADDigitize/ellipse/segments",
                                       36,
                                       type=int)
        if not segvalue:
            self.settings.setValue("/CADDigitize/ellipse/segments", 36)
        self.spinBox.setValue(segvalue)
        self.spinBox.setSingleStep(1)
        self.spinBoxAction = self.optionsToolBar.addWidget(self.spinBox)
        self.spinBox.setToolTip(tr(u"Number of points"))
        self.spinBoxAction.setEnabled(True)

        self.spinBox.valueChanged["int"].connect(self.segmentsettingsEllipse)

    def segmentsettingsEllipse(self):
        self.settings.setValue("/CADDigitize/ellipse/segments",
                               self.spinBox.value())
Example #22
0
    def addSpinBox(self, attribute_name, title, tool_tip=None, min_value=1, max_value=10, single_step=1):
        sb = QSpinBox()
        self[attribute_name] = sb
        sb.setMaximumHeight(25)
        sb_layout = QHBoxLayout()
        sb_layout.addWidget(sb)
        sb_layout.addStretch()
        self.addRow(title, sb_layout)

        if tool_tip is not None:
            sb.setToolTip(tool_tip)

        sb.setMinimum(min_value)
        sb.setMaximum(max_value)
        sb.setSingleStep(single_step)

        def getter(self):
            return self[attribute_name].value()

        def setter(self, value):
            self[attribute_name].setValue(value)

        self.updateProperty(attribute_name, getter, setter)
        return sb
Example #23
0
class QuadStatusBar(QHBoxLayout):
    def __init__(self, parent=None ):
        QHBoxLayout.__init__(self, parent)
        self.setContentsMargins(0,4,0,0)
        self.setSpacing(0)   
        
    def createQuadViewStatusBar(self, xbackgroundColor, xforegroundColor, ybackgroundColor, yforegroundColor, zbackgroundColor, zforegroundColor, graybackgroundColor, grayforegroundColor):             
        
        self.xLabel = QLabel()
        self.xLabel.setAttribute(Qt.WA_TransparentForMouseEvents, True)
        self.addWidget(self.xLabel)
        pixmap = QPixmap(25*10, 25*10)
        pixmap.fill(xbackgroundColor)
        painter = QPainter()
        painter.begin(pixmap)
        pen = QPen(xforegroundColor)
        painter.setPen(pen)
        painter.setRenderHint(QPainter.Antialiasing)
        font = QFont()
        font.setBold(True)
        font.setPixelSize(25*10-30)
        path = QPainterPath()
        path.addText(QPointF(50, 25*10-50), font, "X")
        brush = QBrush(xforegroundColor)
        painter.setBrush(brush)
        painter.drawPath(path)        
        painter.setFont(font)
        painter.end()
        pixmap = pixmap.scaled(QSize(20,20),Qt.KeepAspectRatio, Qt.SmoothTransformation)
        self.xLabel.setPixmap(pixmap)
        self.xSpinBox = QSpinBox()
        self.xSpinBox.setAttribute(Qt.WA_TransparentForMouseEvents, True)
        self.xSpinBox.setEnabled(False)
        self.xSpinBox.setAlignment(Qt.AlignCenter)
        self.xSpinBox.setToolTip("xSpinBox")
        self.xSpinBox.setButtonSymbols(QAbstractSpinBox.NoButtons)
        self.xSpinBox.setMaximumHeight(20)
        self.xSpinBox.setMaximum(9999)
        font = self.xSpinBox.font()
        font.setPixelSize(14)
        self.xSpinBox.setFont(font)
        self.xSpinBox.setStyleSheet("QSpinBox { color: " + str(xforegroundColor.name()) + "; font: bold; background-color: " + str(xbackgroundColor.name()) + "; border:0;}")
        self.addWidget(self.xSpinBox)
        
        self.yLabel = QLabel()
        self.yLabel.setAttribute(Qt.WA_TransparentForMouseEvents, True)
        self.addWidget(self.yLabel)
        pixmap = QPixmap(25*10, 25*10)
        pixmap.fill(ybackgroundColor)
        painter = QPainter()
        painter.begin(pixmap)
        pen = QPen(yforegroundColor)
        painter.setPen(pen)
        painter.setRenderHint(QPainter.Antialiasing)
        font = QFont()
        font.setBold(True)
        font.setPixelSize(25*10-30)
        path = QPainterPath()
        path.addText(QPointF(50, 25*10-50), font, "Y")
        brush = QBrush(yforegroundColor)
        painter.setBrush(brush)
        painter.drawPath(path)        
        painter.setFont(font)
        painter.end()
        pixmap = pixmap.scaled(QSize(20,20),Qt.KeepAspectRatio, Qt.SmoothTransformation)
        self.yLabel.setPixmap(pixmap)
        self.ySpinBox = QSpinBox()
        self.ySpinBox.setAttribute(Qt.WA_TransparentForMouseEvents, True)
        self.ySpinBox.setEnabled(False)
        self.ySpinBox.setAlignment(Qt.AlignCenter)
        self.ySpinBox.setToolTip("ySpinBox")
        self.ySpinBox.setButtonSymbols(QAbstractSpinBox.NoButtons)
        self.ySpinBox.setMaximumHeight(20)
        self.ySpinBox.setMaximum(9999)
        font = self.ySpinBox.font()
        font.setPixelSize(14)
        self.ySpinBox.setFont(font)
        self.ySpinBox.setStyleSheet("QSpinBox { color: " + str(yforegroundColor.name()) + "; font: bold; background-color: " + str(ybackgroundColor.name()) + "; border:0;}")
        self.addWidget(self.ySpinBox)
        
        self.zLabel = QLabel()
        self.zLabel.setAttribute(Qt.WA_TransparentForMouseEvents, True)
        self.addWidget(self.zLabel)
        pixmap = QPixmap(25*10, 25*10)
        pixmap.fill(zbackgroundColor)
        painter = QPainter()
        painter.begin(pixmap)
        pen = QPen(zforegroundColor)
        painter.setPen(pen)
        painter.setRenderHint(QPainter.Antialiasing)
        font = QFont()
        font.setBold(True)
        font.setPixelSize(25*10-30)
        path = QPainterPath()
        path.addText(QPointF(50, 25*10-50), font, "Z")
        brush = QBrush(zforegroundColor)
        painter.setBrush(brush)
        painter.drawPath(path)        
        painter.setFont(font)
        painter.end()
        pixmap = pixmap.scaled(QSize(20,20),Qt.KeepAspectRatio, Qt.SmoothTransformation)
        self.zLabel.setPixmap(pixmap)
        self.zSpinBox = QSpinBox()
        self.zSpinBox.setAttribute(Qt.WA_TransparentForMouseEvents, True)
        self.zSpinBox.setEnabled(False)
        self.zSpinBox.setAlignment(Qt.AlignCenter)
        self.zSpinBox.setToolTip("zSpinBox")
        self.zSpinBox.setButtonSymbols(QAbstractSpinBox.NoButtons)
        self.zSpinBox.setMaximumHeight(20)
        self.zSpinBox.setMaximum(9999)
        font = self.zSpinBox.font()
        font.setPixelSize(14)
        self.zSpinBox.setFont(font)
        self.zSpinBox.setStyleSheet("QSpinBox { color: " + str(zforegroundColor.name()) + "; font: bold; background-color: " + str(zbackgroundColor.name()) + "; border:0;}")
        self.addWidget(self.zSpinBox)
        
        self.addSpacing(4)
        
        self.grayScaleLabel = QLabel()
        self.grayScaleLabel.setAttribute(Qt.WA_TransparentForMouseEvents, True)
        self.addWidget(self.grayScaleLabel)
        pixmap = QPixmap(610, 250)
        pixmap.fill(graybackgroundColor)
        painter = QPainter()
        painter.begin(pixmap)
        pen = QPen(grayforegroundColor)
        painter.setPen(pen)
        painter.setRenderHint(QPainter.Antialiasing)
        font = QFont()
        font.setBold(True)
        font.setPixelSize(25*10-30)
        path = QPainterPath()
        path.addText(QPointF(50, 25*10-50), font, "Gray")
        brush = QBrush(grayforegroundColor)
        painter.setBrush(brush)
        painter.drawPath(path)        
        painter.setFont(font)
        painter.end()
        pixmap = pixmap.scaled(QSize(61,20),Qt.KeepAspectRatio, Qt.SmoothTransformation)
        
        """
        self.grayScaleLabel.setPixmap(pixmap)
        self.grayScaleSpinBox = QSpinBox()
        self.grayScaleSpinBox.setAttribute(Qt.WA_TransparentForMouseEvents, True)
        self.grayScaleSpinBox.setEnabled(False)
        self.grayScaleSpinBox.setAlignment(Qt.AlignCenter)
        self.grayScaleSpinBox.setToolTip("grayscaleSpinBox")
        self.grayScaleSpinBox.setButtonSymbols(QAbstractSpinBox.NoButtons)
        self.grayScaleSpinBox.setMaximum(255)
        self.grayScaleSpinBox.setMaximumHeight(20)
        self.grayScaleSpinBox.setMaximum(255)
        font = self.grayScaleSpinBox.font()
        font.setPixelSize(14)
        self.grayScaleSpinBox.setFont(font)
        self.grayScaleSpinBox.setStyleSheet("QSpinBox { color: " + str(grayforegroundColor.name()) + "; font: bold; background-color: " + str(graybackgroundColor.name()) + "; border:0;}")
        self.addWidget(self.grayScaleSpinBox)
        """
        
        self.addStretch()
        
        self.positionCheckBox = QCheckBox()
        self.positionCheckBox.setChecked(True)
        self.positionCheckBox.setCheckable(True)
        self.positionCheckBox.setText("Position")
        self.addWidget(self.positionCheckBox)
        
        self.addSpacing(20)
        
        self.channelLabel = QLabel("Channel:")
        self.addWidget(self.channelLabel)
        
        self.channelSpinBox = QSpinBox()
        self.addWidget(self.channelSpinBox)
        self.addSpacing(20)
        
        self.timeLabel = QLabel("Time:")
        self.addWidget(self.timeLabel)
        
        self.timeSpinBox = QSpinBox()
        self.addWidget(self.timeSpinBox)
    """    
    def setGrayScale(self, gray):
        self.grayScaleSpinBox.setValue(gray)
    """
        
    def setMouseCoords(self, x, y, z):
        self.xSpinBox.setValue(x)
        self.ySpinBox.setValue(y)
        self.zSpinBox.setValue(z)
Example #24
0
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
Example #25
0
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())
Example #26
0
    def initAppletDrawerUi(self):
        """
        Overridden from base class (LayerViewerGui)
        """
        op = self.topLevelOperatorView

        def configure_update_handlers(qt_signal, op_slot):
            qt_signal.connect(self.configure_operator_from_gui)
            op_slot.notifyDirty(self.configure_gui_from_operator)
            self.__cleanup_fns.append(
                partial(op_slot.unregisterDirty,
                        self.configure_gui_from_operator))

        def control_layout(label_text, widget):
            row_layout = QHBoxLayout()
            row_layout.addWidget(QLabel(label_text))
            row_layout.addSpacerItem(QSpacerItem(10, 0, QSizePolicy.Expanding))
            row_layout.addWidget(widget)
            return row_layout

        drawer_layout = QVBoxLayout()

        channel_button = QPushButton()
        self.channel_menu = QMenu(
            self)  # Must retain menus (in self) or else they get deleted.
        channel_button.setMenu(self.channel_menu)
        channel_button.clicked.connect(channel_button.showMenu)

        def populate_channel_menu(*args):
            if sip.isdeleted(channel_button):
                return
            self.channel_menu.clear()
            self.channel_actions = []
            for ch in range(op.Input.meta.getTaggedShape()['c']):
                action = QAction("Channel {}".format(ch), self.channel_menu)
                action.setCheckable(True)
                self.channel_menu.addAction(action)
                self.channel_actions.append(action)
                configure_update_handlers(action.toggled, op.ChannelSelections)

        populate_channel_menu()
        op.Input.notifyMetaChanged(populate_channel_menu)
        self.__cleanup_fns.append(
            partial(op.Input.unregisterMetaChanged, populate_channel_menu))
        channel_button.setToolTip(
            "Boundary channel index in the probability map")
        drawer_layout.addLayout(control_layout("Input Channel",
                                               channel_button))
        self.channel_button = channel_button

        threshold_box = QDoubleSpinBox()
        threshold_box.setDecimals(2)
        threshold_box.setMinimum(0.00)
        threshold_box.setMaximum(1.0)
        threshold_box.setSingleStep(0.1)
        configure_update_handlers(threshold_box.valueChanged, op.Pmin)
        threshold_box.setToolTip("Boundary probability threshold")
        drawer_layout.addLayout(control_layout("Threshold", threshold_box))
        self.threshold_box = threshold_box

        membrane_size_box = QSpinBox()
        membrane_size_box.setMinimum(0)
        membrane_size_box.setMaximum(1000000)
        configure_update_handlers(membrane_size_box.valueChanged,
                                  op.MinMembraneSize)
        membrane_size_box.setToolTip(
            "Size filter for boundary pieces, in pixels")
        drawer_layout.addLayout(
            control_layout("Min Boundary Size", membrane_size_box))
        self.membrane_size_box = membrane_size_box

        seed_presmoothing_box = QDoubleSpinBox()
        seed_presmoothing_box.setDecimals(1)
        seed_presmoothing_box.setMinimum(0.0)
        seed_presmoothing_box.setMaximum(10.0)
        seed_presmoothing_box.setSingleStep(0.1)
        configure_update_handlers(seed_presmoothing_box.valueChanged,
                                  op.SigmaMinima)
        seed_presmoothing_box.setToolTip(
            "Smooth the distance transform map with this sigma")
        drawer_layout.addLayout(
            control_layout("Presmooth before Seeds", seed_presmoothing_box))
        self.seed_presmoothing_box = seed_presmoothing_box

        seed_method_combo = QComboBox()
        seed_method_combo.addItem("Connected")
        seed_method_combo.addItem("Clustered")
        configure_update_handlers(seed_method_combo.currentIndexChanged,
                                  op.GroupSeeds)
        seed_method_combo.setToolTip(
            "Connected: combine directly adjacent pixels into seeds (more superpixels). Clustered: group pixels into seeds by distance heuristic (less superpixels)"
        )
        drawer_layout.addLayout(
            control_layout("Seed Labeling", seed_method_combo))
        self.seed_method_combo = seed_method_combo

        superpixel_size_box = QSpinBox()
        superpixel_size_box.setMinimum(0)
        superpixel_size_box.setMaximum(1000000)
        configure_update_handlers(superpixel_size_box.valueChanged,
                                  op.MinSegmentSize)
        superpixel_size_box.setToolTip("Minimal size of a superpixel")
        drawer_layout.addLayout(
            control_layout("Min Superpixel Size", superpixel_size_box))
        self.superpixel_size_box = superpixel_size_box

        preserve_pmaps_box = QCheckBox()
        configure_update_handlers(preserve_pmaps_box.toggled,
                                  op.PreserveMembranePmaps)
        preserve_pmaps_box.setToolTip(
            "Preserve thin structures. Use that option when some of your foreground objects have long and thin parts"
        )
        drawer_layout.addLayout(
            control_layout("Preserve Thin Structures", preserve_pmaps_box))
        self.preserve_pmaps_box = preserve_pmaps_box

        enable_debug_box = QCheckBox()
        configure_update_handlers(enable_debug_box.toggled,
                                  op.EnableDebugOutputs)
        drawer_layout.addLayout(
            control_layout("Show Debug Layers", enable_debug_box))
        self.enable_debug_box = enable_debug_box

        op.Superpixels.notifyReady(self.configure_gui_from_operator)
        op.Superpixels.notifyUnready(self.configure_gui_from_operator)
        self.__cleanup_fns.append(
            partial(op.Superpixels.unregisterReady,
                    self.configure_gui_from_operator))
        self.__cleanup_fns.append(
            partial(op.Superpixels.unregisterUnready,
                    self.configure_gui_from_operator))

        self.update_ws_button = QPushButton(
            "Update Watershed", clicked=self.onUpdateWatershedsButton)
        drawer_layout.addWidget(self.update_ws_button)

        drawer_layout.setSpacing(0)
        drawer_layout.addSpacerItem(
            QSpacerItem(0, 10, QSizePolicy.Minimum, QSizePolicy.Expanding))

        # Finally, the whole drawer widget
        drawer = QWidget(parent=self)
        drawer.setLayout(drawer_layout)

        # Save these members for later use
        self._drawer = drawer

        # Initialize everything with the operator's initial values
        self.configure_gui_from_operator()
Example #27
0
class AnimationWindow(PyDialog):
    """
    +-------------------+
    | Animation         |
    +-------------------------+
    | icase   ______          |
    | scale   ______  Default |
    | time    ______  Default |
    |                         |
    | nframes ______  Default |
    | resolu. ______  Default |
    | Dir     ______  Browse  |
    | iFrame  ______          |
    |                         |
    | Animations:             |
    | o Scale, Phase, Time    |  # TODO: add time
    |                         |
    | x delete images         |
    | x repeat                |  # TODO: change to an integer
    | x make gif              |
    |                         |
    |      Step, RunAll       |
    |         Close           |
    +-------------------------+

    TODO: add key-frame support
    """
    def __init__(self, data, win_parent=None):
        PyDialog.__init__(self, data, win_parent)
        self.set_font_size(data['font_size'])
        self.istep = 0
        self._animate_type = 'time'

        self._updated_animation = False
        self._icase = data['icase']
        self._default_name = data['name']
        self._default_time = data['time']
        self._default_fps = data['frames/sec']
        self._default_resolution = data['resolution']

        self._scale = data['scale']
        self._default_scale = data['default_scale']
        self._default_is_scale = data['is_scale']

        self._phase = data['phase']
        self._default_phase = data['default_phase']

        self._default_dirname = data['dirname']
        self._default_gif_name = os.path.join(self._default_dirname,
                                              data['name'] + '.gif')

        self.animation_types = [
            'Animate Scale',
        ]
        #'Animate Phase',
        #'Animate Time',
        #'Animate Frequency Sweep'
        #]

        self.setWindowTitle('Animate Model')
        self.create_widgets()
        self.create_layout()
        self.set_connections()

        self.is_gui = False
        if hasattr(self.win_parent, '_updated_legend'):
            self.win_parent.is_animate_open = True
            self.is_gui = True

    def create_widgets(self):
        """creates the menu objects"""
        icase_max = 1000  # TODO: update 1000

        self.icase = QLabel("iCase:")
        self.icase_edit = QSpinBox(self)
        self.icase_edit.setRange(1, icase_max)
        self.icase_edit.setSingleStep(1)
        self.icase_edit.setValue(self._icase)
        self.icase_edit.setToolTip(
            'Case Number for the Scale/Phase Animation Type.\n'
            'Defaults to the result you had shown when you clicked "Create Animation".\n'
            'iCase can be seen by clicking "Apply" on a result.')

        self.scale = QLabel("Scale:")
        self.scale_edit = QLineEdit(str(self._scale))
        self.scale_button = QPushButton("Default")
        self.scale_edit.setToolTip('Scale factor of the "deflection"')
        self.scale_button.setToolTip('Sets the scale factor of the gif to %s' %
                                     self._scale)

        self.time = QLabel("Total Time (sec):")
        self.time_edit = QDoubleSpinBox(self)
        self.time_edit.setValue(self._default_time)
        self.time_edit.setRange(0.1, 10.0)
        self.time_edit.setDecimals(2)
        self.time_edit.setSingleStep(0.1)
        self.time_button = QPushButton("Default")
        self.time_edit.setToolTip("Total time of the gif")
        self.time_button.setToolTip('Sets the total time of the gif to %.2f' %
                                    self._default_time)

        self.fps = QLabel("Frames/Second:")
        self.fps_edit = QSpinBox(self)
        self.fps_edit.setRange(1, 60)
        self.fps_edit.setSingleStep(1)
        self.fps_edit.setValue(self._default_fps)
        self.fps_button = QPushButton("Default")
        self.fps_edit.setToolTip(
            "A higher FPS is smoother, but may not play well for large gifs")
        self.fps_button.setToolTip('Sets the FPS to %s' % self._default_fps)

        self.resolution = QLabel("Resolution Scale:")
        self.resolution_edit = QSpinBox(self)
        self.resolution_edit.setRange(1, 5)
        self.resolution_edit.setSingleStep(1)
        self.resolution_edit.setValue(self._default_resolution)
        self.resolution_button = QPushButton("Default")
        self.resolution_edit.setToolTip(
            'Scales the window resolution by an integer factor')
        self.resolution_button.setToolTip('Sets the resolution to %s' %
                                          self._default_resolution)

        #-----------------
        # Time plot
        self.icase_start = QLabel("iCase Start:")
        self.icase_start_edit = QSpinBox(self)
        self.icase_start_edit.setRange(0, icase_max)
        self.icase_start_edit.setSingleStep(1)
        self.icase_start_edit.setValue(self._icase)
        self.icase_start_button = QPushButton("Default")

        self.icase_end = QLabel("iCase End:")
        self.icase_end_edit = QSpinBox(self)
        self.icase_end_edit.setRange(0, icase_max)
        self.icase_end_edit.setSingleStep(1)
        self.icase_end_edit.setValue(self._icase)
        self.icase_end_button = QPushButton("Default")

        self.icase_delta = QLabel("iCase Delta:")
        self.icase_delta_edit = QSpinBox(self)
        self.icase_delta_edit.setRange(1, icase_max)
        self.icase_delta_edit.setSingleStep(1)
        self.icase_delta_edit.setValue(1)
        self.icase_delta_button = QPushButton("Default")

        self.min_value = QLabel("Min Value:")
        self.min_value_edit = QLineEdit(str(0.))
        #self.min_value_edit.setRange(1, 1000)
        #self.min_value_edit.setSingleStep(1)
        #self.min_value_edit.setValue(1)
        self.min_value_button = QPushButton("Default")

        self.max_value = QLabel("Max Value:")
        self.max_value_edit = QLineEdit(str(1.))
        #self.min_value_edit.setRange(1, 1000)  # TODO: update 1000
        #self.min_value_edit.setSingleStep(1)
        #self.min_value_edit.setValue(1)
        self.max_value_button = QPushButton("Default")

        self.icase_start_edit.setToolTip('The first frame of the animation')
        self.icase_end_edit.setToolTip(
            'The last frame of the animation\n'
            'Assumes icase_start + nframes * icase_delta = icase_end')
        self.icase_delta_edit.setToolTip(
            'The frame step size (to skip non-consecutive results).\n'
            'Frame skipping can be used to:\n'
            "  - skip across results that you don't want to plot\n"
            '  - adjust the FPS')

        self.min_value_edit.setToolTip(
            'Min value of the legend (not supported)')
        self.max_value_edit.setToolTip(
            'Max value of the legend (not supported)')
        #'time' : 0.,
        #'default_time' : 0,
        #'icase_start' : 10,
        #'icase_delta' : 3,
        #'min_value' : 0.,
        #'max_value' : 1000.,

        self.browse_folder = QLabel('Output Directory:')
        self.browse_folder_edit = QLineEdit(str(self._default_dirname))
        self.browse_folder_button = QPushButton('Browse')
        self.browse_folder_edit.setToolTip(
            'Location to save the png/gif files')

        self.gif = QLabel("Gif Filename:")
        self.gif_edit = QLineEdit(str(self._default_name + '.gif'))
        self.gif_button = QPushButton('Default')
        self.gif_edit.setToolTip('Name of the gif')
        self.gif_button.setToolTip('Sets the name of the gif to %s.gif' %
                                   self._default_name)

        # scale / phase
        self.animate_scale_radio = QRadioButton("Animate Scale")
        self.animate_phase_radio = QRadioButton("Animate Phase")
        self.animate_time_radio = QRadioButton("Animate Time")
        self.animate_freq_sweeep_radio = QRadioButton(
            "Animate Frequency Sweep")
        self.animate_scale_radio.setToolTip(
            'Animates the scale factor based on the "Animation Type"')
        self.animate_time_radio.setToolTip('Animates the time/load/mode step')

        self.animate_scale_radio.setChecked(self._default_is_scale)
        self.animate_phase_radio.setChecked(not self._default_is_scale)
        self.animate_time_radio.setChecked(False)

        msg = 'Scale : Animates the scale factor based on the "Animation Profile"\n'
        if self._default_phase is None:
            self.animate_phase_radio.setDisabled(True)
            self.animate_phase_radio.setToolTip('Animates the phase angle '
                                                '(only for complex results)')
            msg += 'Phase : Animates the phase angle (only for complex results)\n'
        else:
            self.animate_phase_radio.setToolTip("Animates the phase angle")
            msg += 'Phase : Animates the phase angle\n'
        msg += (
            'Time : Animates the time/load/mode step\n'
            'Freq Sweep : Animates a complex result across a range of frequencies '
            '(not supported)\n')

        self.animate_freq_sweeep_radio.setDisabled(True)
        self.animate_freq_sweeep_radio.setToolTip(
            'Animates a complex result across a range of frequencies (not supported)'
        )
        self.animation_type = QLabel("Animation Type:")
        animation_type = OrderedDict()
        #scale_msg = 'Scale\n'
        #phase_msg = 'Phase\n'
        #time_msg = 'Time\n'
        #animation_types = [
        #('Animate Scale', scale_msg),
        #('Animate Phase', phase_msg),
        #('Animate Time', time_msg),
        ##'Animate Frequency Sweep'
        #]

        if self._phase is not None:
            self.animation_types.append('Animate Phase')
        self.animation_types.append('Animate Time')

        self.animation_profile = QLabel("Animation Profile:")

        self.animation_profile_edit = QComboBox()
        for animation_profile in ANIMATION_PROFILES:
            self.animation_profile_edit.addItem(animation_profile)
        self.animation_profile_edit.setToolTip('The profile for a scaled GIF')

        self.animation_type_edit = QComboBox()
        # TODO: add a tooltip for each item
        for animation_type in self.animation_types:
            self.animation_type_edit.addItem(animation_type)
        #self.animation_type_edit.setToolTip('The profile for a scaled GIF')
        self.animation_type_edit.setToolTip(msg)

        self.csv_profile = QLabel("CSV profile:")
        self.csv_profile_edit = QLineEdit()
        self.csv_profile_browse_button = QPushButton('Browse')
        self.csv_profile_edit.setToolTip(
            'The path to the CSV file of (Scale1, Scale2, Scale3, ...)')

        widget = QWidget(self)
        horizontal_vertical_group = QButtonGroup(widget)
        horizontal_vertical_group.addButton(self.animate_scale_radio)
        horizontal_vertical_group.addButton(self.animate_phase_radio)
        horizontal_vertical_group.addButton(self.animate_time_radio)
        horizontal_vertical_group.addButton(self.animate_freq_sweeep_radio)

        # one / two sided
        self.onesided_radio = QRadioButton("One Sided")
        self.onesided_radio.setToolTip(
            "A one sided gif doesn't return to the starting point (e.g., 0 to 360 degrees)"
        )
        self.twosided_radio = QRadioButton("Two Sided")
        self.twosided_radio.setToolTip(
            'A two sided gif returns to the starting point (e.g., 0 to 10 to 0)'
        )

        if self._default_phase is None:
            self.onesided_radio.setChecked(False)
            self.twosided_radio.setChecked(True)
        else:
            self.onesided_radio.setChecked(True)
            self.twosided_radio.setChecked(False)
        widget = QWidget(self)
        horizontal_vertical_group = QButtonGroup(widget)
        horizontal_vertical_group.addButton(self.onesided_radio)
        horizontal_vertical_group.addButton(self.twosided_radio)

        # animate in gui
        self.animate_in_gui_checkbox = QCheckBox("Animate In GUI?")
        self.animate_in_gui_checkbox.setChecked(True)

        # make images
        self.make_images_checkbox = QCheckBox("Make images?")
        self.make_images_checkbox.setChecked(True)

        # make images
        self.overwrite_images_checkbox = QCheckBox("Overwrite images?")
        self.overwrite_images_checkbox.setChecked(True)

        # delete images when finished
        self.delete_images_checkbox = QCheckBox("Delete images when finished?")
        self.delete_images_checkbox.setChecked(True)

        # endless loop
        self.repeat_checkbox = QCheckBox("Repeat?")
        self.repeat_checkbox.setChecked(True)
        self.repeat_checkbox.setToolTip(
            "Repeating creates an infinitely looping gif")

        # endless loop
        self.make_gif_checkbox = QCheckBox("Make Gif?")
        if IS_IMAGEIO:
            self.make_gif_checkbox.setChecked(True)
        else:
            self.make_gif_checkbox.setChecked(False)
            self.make_gif_checkbox.setEnabled(False)
            self.make_gif_checkbox.setToolTip(
                'imageio is not available; install it')

        # bottom buttons
        self.step_button = QPushButton("Step")
        self.stop_button = QPushButton("Stop")
        self.run_button = QPushButton("Run All")

        #self.apply_button = QPushButton("Apply")
        #self.ok_button = QPushButton("OK")
        self.cancel_button = QPushButton("Close")

        #self.set_grid_time(enabled=False)
        #self.set_grid_scale(enabled=self._default_is_scale)
        if self._default_phase:
            self.on_animate_phase(force=True)
        else:
            self.on_animate_scale(force=True)

    def set_connections(self):
        """creates button actions"""
        self.scale_button.clicked.connect(self.on_default_scale)
        self.time_button.clicked.connect(self.on_default_time)

        self.fps_button.clicked.connect(self.on_default_fps)
        self.resolution_button.clicked.connect(self.on_default_resolution)
        self.browse_folder_button.clicked.connect(self.on_browse_folder)
        self.csv_profile_browse_button.clicked.connect(self.on_browse_csv)
        self.gif_button.clicked.connect(self.on_default_name)

        self.step_button.clicked.connect(self.on_step)
        self.stop_button.clicked.connect(self.on_stop)
        self.run_button.clicked.connect(self.on_run)

        #self.animate_scale_radio.clicked.connect(self.on_animate_scale)
        #self.animate_phase_radio.clicked.connect(self.on_animate_phase)
        #self.animate_time_radio.clicked.connect(self.on_animate_time)
        self.animation_type_edit.currentIndexChanged.connect(self.on_animate)
        #self.animate_freq_sweeep_radio

        #self.apply_button.clicked.connect(self.on_apply)
        #self.ok_button.clicked.connect(self.on_ok)
        self.cancel_button.clicked.connect(self.on_cancel)

        self.animate_in_gui_checkbox.clicked.connect(self.on_animate_in_gui)
        self.animate_in_gui_checkbox.setChecked(True)
        self.on_animate_in_gui()

    def on_animate_in_gui(self):
        animate_in_gui = self.animate_in_gui_checkbox.isChecked()
        enable = not animate_in_gui
        self.make_images_checkbox.setEnabled(enable)
        self.delete_images_checkbox.setEnabled(enable)
        self.make_gif_checkbox.setEnabled(enable)
        self.repeat_checkbox.setEnabled(enable)
        self.resolution_button.setEnabled(enable)
        self.resolution_edit.setEnabled(enable)
        self.gif_edit.setEnabled(enable)
        self.gif_button.setEnabled(enable)
        self.browse_folder_button.setEnabled(enable)
        self.browse_folder_edit.setEnabled(enable)
        self.step_button.setEnabled(enable)

    def on_animate(self, value):
        """
        animate pulldown

        Parameters
        ----------
        value : int
            index in animation_types
        """
        #animation_types = ['Animate Scale', 'Animate Phase', 'Animate Time',
        #'Animate Frequency Sweep']
        animation_type = self.animation_types[value]
        if animation_type == 'Animate Scale':
            self.on_animate_scale()
        elif animation_type == 'Animate Phase':
            self.on_animate_phase()
        elif animation_type == 'Animate Time':
            self.on_animate_time()
        else:
            raise NotImplementedError('value = ', value)

    def on_animate_time(self, force=False):
        """enables the secondary input"""
        #print('on_animate_time')
        if self._animate_type == 'scale' or force:
            self.set_grid_scale(False, 'time')
        self.set_grid_time(True, 'time')
        self._animate_type = 'time'

    def on_animate_scale(self, force=False):
        """enables the secondary input"""
        #print('on_animate_scale')
        self.set_grid_scale(True, 'scale')
        if self._animate_type == 'time' or force:
            self.set_grid_time(False, 'scale')
        self._animate_type = 'scale'

    def on_animate_phase(self, force=False):
        """enables the secondary input"""
        #print('on_animate_phase')
        if self._animate_type == 'scale' or force:
            self.set_grid_scale(False, 'phase')
        if self._animate_type == 'time' or force:
            self.set_grid_time(False, 'phase')
        self._animate_type = 'phase'

    def set_grid_scale(self, enabled=True, word=''):
        """enables/disables the secondary input"""
        #print('%s-set_grid_scale; enabled = %r' % (word, enabled))
        self.animation_profile.setEnabled(enabled)
        self.animation_profile_edit.setEnabled(enabled)

        # TODO: doesn't work...
        #self.csv_profile.setEnabled(enabled)
        #self.csv_profile_edit.setEnabled(enabled)
        #self.csv_profile_button.setEnabled(enabled)

    def set_grid_time(self, enabled=True, word=''):
        """enables/disables the secondary input"""
        #print('%s-set_grid_time; enabled = %r' % (word, enabled))
        self.icase_start.setEnabled(enabled)
        self.icase_start_edit.setEnabled(enabled)
        self.icase_start_button.setEnabled(enabled)

        self.icase_end.setEnabled(enabled)
        self.icase_end_edit.setEnabled(enabled)
        self.icase_end_button.setEnabled(enabled)

        self.icase_delta.setEnabled(enabled)
        self.icase_delta_edit.setEnabled(enabled)
        self.icase_delta_button.setEnabled(enabled)

        self.min_value.setEnabled(enabled)
        self.min_value_edit.setEnabled(enabled)
        self.min_value_button.setEnabled(enabled)

        self.max_value.setEnabled(enabled)
        self.max_value_edit.setEnabled(enabled)
        self.max_value_button.setEnabled(enabled)

        self.icase.setEnabled(not enabled)
        self.icase_edit.setEnabled(not enabled)
        self.fps.setEnabled(not enabled)
        self.fps_edit.setEnabled(not enabled)
        self.fps_button.setEnabled(not enabled)

    def on_browse_folder(self):
        """opens a folder dialog"""
        dirname = open_directory_dialog(self, 'Select a Directory')
        if not dirname:
            return
        self.browse_folder_edit.setText(dirname)

    def on_browse_csv(self):
        """opens a file dialog"""
        default_filename = ''
        file_types = 'Delimited Text (*.txt; *.dat; *.csv)'
        dirname = open_file_dialog(self, 'Select a CSV File', default_filename,
                                   file_types)
        if not dirname:
            return
        self.csv_profile_browse_button.setText(dirname)

    def on_default_name(self):
        """sets the default gif name"""
        self.gif_edit.setText(self._default_name + '.gif')

    def on_default_scale(self):
        """sets the default displacement scale factor"""
        self.scale_edit.setText(str(self._default_scale))
        self.scale_edit.setStyleSheet("QLineEdit{background: white;}")

    def on_default_time(self):
        """sets the default gif time"""
        self.time_edit.setValue(self._default_time)

    def on_default_fps(self):
        """sets the default FPS"""
        self.fps_edit.setValue(self._default_fps)

    def on_default_resolution(self):
        """sets the default image resolution scale factor"""
        self.resolution_edit.setValue(self._default_resolution)

    def create_layout(self):
        """displays the menu objects"""
        grid = QGridLayout()

        grid.addWidget(self.icase, 0, 0)
        grid.addWidget(self.icase_edit, 0, 1)

        grid.addWidget(self.scale, 1, 0)
        grid.addWidget(self.scale_edit, 1, 1)
        grid.addWidget(self.scale_button, 1, 2)

        grid.addWidget(self.time, 2, 0)
        grid.addWidget(self.time_edit, 2, 1)
        grid.addWidget(self.time_button, 2, 2)

        # spacer
        spacer = QLabel('')

        grid.addWidget(self.fps, 3, 0)
        grid.addWidget(self.fps_edit, 3, 1)
        grid.addWidget(self.fps_button, 3, 2)

        grid.addWidget(self.resolution, 4, 0)
        grid.addWidget(self.resolution_edit, 4, 1)
        grid.addWidget(self.resolution_button, 4, 2)

        grid.addWidget(self.browse_folder, 5, 0)
        grid.addWidget(self.browse_folder_edit, 5, 1)
        grid.addWidget(self.browse_folder_button, 5, 2)

        grid.addWidget(self.gif, 6, 0)
        grid.addWidget(self.gif_edit, 6, 1)
        grid.addWidget(self.gif_button, 6, 2)

        grid.addWidget(self.animation_type, 7, 0)
        grid.addWidget(self.animation_type_edit, 7, 1)

        grid.addWidget(spacer, 8, 0)

        #----------
        #Time
        grid_time = QGridLayout()
        grid_time.addWidget(self.icase_start, 0, 0)
        grid_time.addWidget(self.icase_start_edit, 0, 1)
        #grid_time.addWidget(self.icase_start_button, 0, 2)

        grid_time.addWidget(self.icase_end, 1, 0)
        grid_time.addWidget(self.icase_end_edit, 1, 1)
        #grid_time.addWidget(self.icase_end_button, 1, 2)

        grid_time.addWidget(self.icase_delta, 2, 0)
        grid_time.addWidget(self.icase_delta_edit, 2, 1)
        #grid_time.addWidget(self.icase_delta_button, 2, 2)

        #grid_time.addWidget(self.min_value, 3, 0)
        #grid_time.addWidget(self.min_value_edit, 3, 1)
        #grid_time.addWidget(self.min_value_button, 3, 2)

        #grid_time.addWidget(self.max_value, 4, 0)
        #grid_time.addWidget(self.max_value_edit, 4, 1)
        #grid_time.addWidget(self.max_value_button, 4, 2)
        grid_time.addWidget(spacer, 5, 0)

        #--------------
        grid_scale = QGridLayout()
        grid_scale.addWidget(self.animation_profile, 0, 0)
        grid_scale.addWidget(self.animation_profile_edit, 0, 1)

        #grid_scale.addWidget(self.csv_profile, 1, 0)
        #grid_scale.addWidget(self.csv_profile_edit, 1, 1)
        #grid_scale.addWidget(self.csv_profile_browse_button, 1, 2)

        self.csv_profile = QLabel("CSV profile:")
        self.csv_profile_edit = QLineEdit()
        self.csv_profile_button = QPushButton('Browse')

        #box_time = QVBoxLayout()
        # TODO: It's super annoying that the animate time box doesn't
        #       line up with the previous box
        box_scale = QGroupBox('Animate Scale')
        box_scale.setLayout(grid_scale)

        box_time = QGroupBox('Animate Time')
        box_time.setLayout(grid_time)
        #----------

        grid2 = QGridLayout()
        #grid2.addWidget(self.animate_scale_radio, 8, 0)
        #grid2.addWidget(self.animate_phase_radio, 8, 1)
        #grid2.addWidget(self.animate_time_radio, 8, 2)
        #grid2.addWidget(self.animate_freq_sweeep_radio, 8, 3)

        grid2.addWidget(self.animate_in_gui_checkbox, 10, 0)
        grid2.addWidget(self.make_images_checkbox, 11, 0)
        #grid2.addWidget(self.overwrite_images_checkbox, 11, 0)
        grid2.addWidget(self.delete_images_checkbox, 11, 1)
        grid2.addWidget(self.make_gif_checkbox, 11, 2)
        grid2.addWidget(self.repeat_checkbox, 12, 0)

        grid2.addWidget(spacer, 13, 0)
        grid_hbox = QHBoxLayout()
        grid_hbox.addWidget(spacer)
        grid_hbox.addLayout(grid2)
        grid_hbox.addWidget(spacer)

        # bottom buttons
        step_run_box = QHBoxLayout()
        step_run_box.addWidget(self.step_button)
        step_run_box.addWidget(self.stop_button)
        step_run_box.addWidget(self.run_button)

        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.cancel_button)

        vbox = QVBoxLayout()
        vbox.addLayout(grid)
        vbox.addWidget(box_scale)
        vbox.addWidget(box_time)
        #vbox.addLayout(checkboxes)
        vbox.addLayout(grid_hbox)
        vbox.addStretch()
        vbox.addLayout(step_run_box)
        vbox.addLayout(ok_cancel_box)
        self.setLayout(vbox)

    def on_step(self):
        """click the Step button"""
        passed, validate_out = self.on_validate()
        if passed:
            try:
                self._make_gif(validate_out, istep=self.istep)
                self.istep += 1
            except IndexError:
                self._make_gif(validate_out, istep=0)
                self.istep += 1

    def on_stop(self):
        passed, validate_out = self.on_validate()
        if passed:
            self._make_gif(validate_out, stop_animation=True)

    def on_run(self):
        """click the Run button"""
        self.istep = 0
        passed, validate_out = self.on_validate()
        if passed:
            self._make_gif(validate_out, istep=None)
        return passed

    def _make_gif(self, validate_out, istep=None, stop_animation=False):
        """interface for making the gif"""
        icase, scale, time, fps, animate_in_gui, magnify, output_dir, gifbase = validate_out

        gif_filename = None
        if not stop_animation and not animate_in_gui:
            if gifbase.lower().endswith('.gif'):
                gifbase = gifbase[:-4]
            gif_filename = os.path.join(output_dir, gifbase + '.gif')

        animate_scale = self.animate_scale_radio.isChecked()
        animate_phase = self.animate_phase_radio.isChecked()
        animate_time = self.animate_time_radio.isChecked()

        animate_scale = False
        animate_phase = False
        animate_time = False
        if self._animate_type == 'scale':
            animate_scale = True
        elif self._animate_type == 'phase':
            animate_phase = True
        elif self._animate_type == 'time':
            animate_time = True
        else:
            raise NotImplementedError(self._animate_type)

        make_images = self.make_images_checkbox.isChecked()
        delete_images = self.delete_images_checkbox.isChecked()
        make_gif = self.make_gif_checkbox.isChecked()
        key = str(self.animation_profile_edit.currentText())
        #profile = ANIMATION_PROFILES[key]

        #ANIMATION_PROFILES['0 to Scale'] = [0., 1.]
        #ANIMATION_PROFILES['0 to Scale to 0'] = [0., 1., 0.]
        if key == '0 to Scale':
            onesided = True
        else:
            onesided = False

        icase_start = self.icase_start_edit.value()
        icase_end = self.icase_end_edit.value()
        icase_delta = self.icase_delta_edit.value()

        #onesided = self.onesided_radio.isChecked()
        bool_repeat = self.repeat_checkbox.isChecked(
        )  # TODO: change this to an integer
        if bool_repeat:
            nrepeat = 0
        else:
            nrepeat = 1
        #self.out_data['is_shown'] = self.show_radio.isChecked()
        #icase = self._icase
        if self.is_gui:
            self.win_parent.win_parent.make_gif(
                gif_filename,
                scale,
                istep=istep,
                animate_scale=animate_scale,
                animate_phase=animate_phase,
                animate_time=animate_time,
                icase=icase,
                icase_start=icase_start,
                icase_end=icase_end,
                icase_delta=icase_delta,
                time=time,
                onesided=onesided,
                nrepeat=nrepeat,
                fps=fps,
                magnify=magnify,
                make_images=make_images,
                delete_images=delete_images,
                make_gif=make_gif,
                stop_animation=stop_animation,
                animate_in_gui=animate_in_gui,
            )

        self.out_data['clicked_ok'] = True
        self.out_data['close'] = True

    def on_validate(self):
        """checks to see if the input is valid"""
        icase, flag0 = self.check_int(self.icase_edit)
        scale, flag1 = self.check_float(self.scale_edit)
        time, flag2 = self.check_float(self.time_edit)
        fps, flag3 = self.check_float(self.fps_edit)
        animate_in_gui = self.animate_in_gui_checkbox.isChecked()

        if animate_in_gui:
            passed = all([flag0, flag1, flag2, flag3])
            return passed, (icase, scale, time, fps, animate_in_gui, None,
                            None, None)

        magnify, flag4 = self.check_int(self.resolution_edit)
        output_dir, flag5 = self.check_path(self.browse_folder_edit)
        gifbase, flag6 = self.check_name(self.gif_edit)
        passed = all([flag0, flag1, flag2, flag3, flag4, flag5, flag6])
        return passed, (icase, scale, time, fps, animate_in_gui, magnify,
                        output_dir, gifbase)

    @staticmethod
    def check_name(cell):
        """verifies that the data is string-able"""
        cell_value = cell.text()
        try:
            text = str(cell_value).strip()
        except UnicodeEncodeError:
            cell.setStyleSheet("QLineEdit{background: red;}")
            return None, False

        if len(text):
            cell.setStyleSheet("QLineEdit{background: white;}")
            return text, True
        else:
            cell.setStyleSheet("QLineEdit{background: red;}")
            return None, False

    def check_path(self, cell):
        """verifies that the path exists"""
        text, passed = self.check_name(cell)
        if not passed:
            return None, False

        if os.path.exists(text):
            cell.setStyleSheet("QLineEdit{background: white;}")
            return text, True
        else:
            cell.setStyleSheet("QLineEdit{background: red;}")
            return None, False

    #def on_ok(self):
    #"""click the OK button"""
    #passed = self.on_apply()
    #if passed:
    #self.win_parent._animation_window_shown = False
    #self.close()
    ##self.destroy()

    def on_cancel(self):
        """click the Cancel button"""
        self.on_stop()
        self.out_data['close'] = True
        self.close()
class SizeWidget(QWidget):
	def __init__(self, obj = None, parent= None):
		QWidget.__init__(self, parent)

		self.Settings = obj.Settings
		self.obj = obj

		self.Settings.beginGroup("Size")
		self.marginVar = self.Settings.value('Margin', 3).toString()
		self.thicknessVar = self.Settings.value('Thickness', 5).toString()
		self.handlerThicknessVar = self.Settings.value('HThickness', 5).toString()
		self.handlerLedgeVar = self.Settings.value('HLedge', 3).toString()
		self.Settings.endGroup()

		self.testSliders = TestSliders(obj, self)
		self.VBLayout = QGridLayout()
		
		self.marginBox = QSpinBox()
		self.marginBox.setToolTip("Margin around slider")
		self.marginBox.setMinimum(3)
		self.marginBox.setMaximum(400)
		self.marginBox.setSingleStep(1)
		self.VBLayout.addWidget(self.marginBox, 0, 0)
		
		self.thicknessBox = QSpinBox()
		self.thicknessBox.setToolTip("Thickness of slider")
		self.thicknessBox.setMinimum(5)
		self.thicknessBox.setMaximum(400)
		self.thicknessBox.setSingleStep(1)
		self.VBLayout.addWidget(self.thicknessBox, 0, 1)
		
		self.handlerThicknessBox = QSpinBox()
		self.handlerThicknessBox.setToolTip("Thickness of handler")
		self.handlerThicknessBox.setMinimum(5)
		self.handlerThicknessBox.setMaximum(100)
		self.handlerThicknessBox.setSingleStep(1)
		self.VBLayout.addWidget(self.handlerThicknessBox, 1, 0)
		
		self.handlerLedgeBox = QSpinBox()
		self.handlerLedgeBox.setToolTip("Ledge of handler")
		self.handlerLedgeBox.setMinimum(3)
		self.handlerLedgeBox.setMaximum(100)
		self.handlerLedgeBox.setSingleStep(1)
		self.VBLayout.addWidget(self.handlerLedgeBox, 1, 1)

		self.VBLayout.addWidget(self.testSliders, 2, 0, 3, 2, Qt.AlignCenter)

		self.setLayout(self.VBLayout)
		self.restoreValues()
		self.marginBox.valueChanged[int].connect(self.marginSet)
		self.thicknessBox.valueChanged[int].connect(self.thicknessSet)
		self.handlerThicknessBox.valueChanged[int].connect(self.handlerThicknessSet)
		self.handlerLedgeBox.valueChanged[int].connect(self.handlerLedgeSet)

	def restoreValues(self):
		self.Settings.beginGroup("Size")
		self.marginVar = self.Settings.value('Margin', 3).toString()
		self.thicknessVar = self.Settings.value('Thickness', 5).toString()
		self.handlerThicknessVar = self.Settings.value('HThickness', 5).toString()
		self.handlerLedgeVar = self.Settings.value('HLedge', 3).toString()
		self.Settings.endGroup()
		
		self.marginBox.setValue(int(self.marginVar))
		self.thicknessBox.setValue(int(self.thicknessVar))
		self.handlerThicknessBox.setValue(int(self.handlerThicknessVar))
		self.handlerLedgeBox.setValue(int(self.handlerLedgeVar))

	def marginSet(self, value = 0):
		self.marginVar = str(value)
		self._updateStyle()
	def thicknessSet(self, value = 0):
		self.thicknessVar = str(value)
		self._updateStyle()
	def handlerThicknessSet(self, value = 0):
		self.handlerThicknessVar = str(value)
		self._updateStyle()
	def handlerLedgeSet(self, value = 0):
		self.handlerLedgeVar = str(value)
		self._updateStyle()

	def _updateStyle(self):
		self.testSliders.setSlidersStyleSheet()
		self.obj.colorSelect.testSliders.setSlidersStyleSheet()

	def setSlidersSize(self, get_Style = None):
		return self.testSliders.setSlidersSize(\
			self.marginVar, self.thicknessVar, \
			self.handlerThicknessVar, \
			self.handlerLedgeVar, get_Style)

	def refreshInterfaceSettings(self):
		self.Settings.beginGroup("Size")
		self.Settings.setValue('Margin', self.marginVar)
		self.Settings.setValue('Thickness', self.thicknessVar)
		self.Settings.setValue('HThickness', self.handlerThicknessVar)
		self.Settings.setValue('HLedge', self.handlerLedgeVar)
		self.Settings.endGroup()
		self.Settings.sync()
Example #29
0
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()
Example #30
0
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)))
Example #31
0
class VocalPart(_base.Part):
    """Base class for vocal parts."""
    midiInstrument = 'choir aahs'

    def createWidgets(self, layout):
        self.createStanzaWidget(layout)
        self.createAmbitusWidget(layout)
        
    def translateWidgets(self):
        self.translateStanzaWidget()
        self.translateAmbitusWidget()
        
    def createStanzaWidget(self, layout):
        self.stanzas = QSpinBox(minimum=1, maximum=99, value=1)
        self.stanzasLabel = QLabel()
        self.stanzasLabel.setBuddy(self.stanzas)
        box = QHBoxLayout(spacing=0)
        box.addWidget(self.stanzasLabel)
        box.addWidget(self.stanzas)
        layout.addLayout(box)
        
    def translateStanzaWidget(self):
        self.stanzasLabel.setText(_("Stanzas:"))
        self.stanzas.setToolTip(_("The number of stanzas."))
    
    def createAmbitusWidget(self, layout):
        self.ambitus = QCheckBox()
        layout.addWidget(self.ambitus)
        
    def translateAmbitusWidget(self):
        self.ambitus.setText(_("Ambitus"))
        self.ambitus.setToolTip(_(
            "Show the pitch range of the voice at the beginning of the staff."))
    
    def assignLyrics(self, data, name, verse=0):
        """Creates an empty assignment for lyrics.
        
        Returns the assignment.
        
        """
        l = ly.dom.LyricMode()
        if verse:
            name = name + ly.util.int2text(verse)
            ly.dom.Line('\\set stanza = "{0}."'.format(verse), l)
        a = data.assign(name)
        a.append(l)
        ly.dom.LineComment(_("Lyrics follow here."), l)
        ly.dom.BlankLine(l)
        return a
    
    def addStanzas(self, data, node):
        """Add stanzas to the given (Voice) node.
        
        The stanzas (as configured in self.stanzas.value()) are added
        using \\addlyrics.
        
        """
        if self.stanzas.value() == 1:
            ly.dom.Identifier(self.assignLyrics(data, 'verse').name, ly.dom.AddLyrics(node))
        else:
            for i in range(self.stanzas.value()):
                ly.dom.Identifier(self.assignLyrics(data, 'verse', i + 1).name, ly.dom.AddLyrics(node))
Example #32
0
class LayoutWindow(QWidget):
    SLIDER_RESOLUTION = 1000
    DIAL_RESOLUTION = 50 
    def __init__(self,parent=None):
        QWidget.__init__(self,parent)
        self.initWidgets()
        

    def initWidgets(self):
        
        self.ui_VideoFrame = VideoWidget(self)
        self.ui_Slider =  QtGui.QSlider(QtCore.Qt.Horizontal)
        #contribution:
        #self.ui_Slider.setStyleSheet(stylesheet(self))
        
        self.ui_Slider.setMinimum(0)
        self.ui_Slider.setMaximum(self.SLIDER_RESOLUTION)
        self.ui_Slider.setToolTip("Video track")
        #self.ui_Slider.setTickPosition(Qt.TicksAbove)
        
        self.ui_Dial = QDial(self)
        
        self.ui_Dial.setProperty("value", 0)
        self.ui_Dial.setNotchesVisible(True)
        self.ui_Dial.setWrapping(False)
        self.ui_Dial.setNotchTarget(5.0)
        self.ui_Dial.setToolTip("Fine tuning")
        self.setDialResolution(self.DIAL_RESOLUTION)

        self.ui_GotoField = QSpinBox(self)
        self.ui_GotoField.setValue(1)
        self.ui_GotoField.setToolTip("Goto Frame")
        
        self.ui_InfoLabel = QLabel(self)
        changeBackgroundColor(self.ui_InfoLabel , "lightblue")
        self.ui_InfoLabel.setText("")
        self.ui_InfoLabel.setToolTip("Infos about the video position")
        
        self.ui_CB_Reencode = QCheckBox(self)
        self.ui_CB_Reencode.setText("Exact cut")
        self.ui_CB_Reencode.setChecked(False)
        self.ui_CB_Reencode.setToolTip("Exact cut is slow, but precise")
        
        self.ui_List = self.__createListWidget()
        
        #self._listSplitter = QSplitter() ->add as widget...+QVBoxLayout
        #self._listSplitter.addWidget(iconList)
        
        #status bar
        self.statusbar = QStatusBar(self)
        self.statusbar.setSizeGripEnabled(True)
        self.statusbar.showMessage("Idle")
        self.statusbar.addPermanentWidget(self.__createProgressBar())
        self.setLayout(self.makeGridLayout())
        self.adjustSize()

    def makeGridLayout(self):
        gridLayout = QGridLayout()
        self.ui_List.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.Expanding)
        gridLayout.addWidget(self.ui_List,0,0,5,1)
        #row column, rowSpan, columnSpan
        gridLayout.addWidget(self.ui_VideoFrame,0,2,3,-1);
        gridLayout.addWidget(self.ui_GotoField,4,1,1,20)
        gridLayout.addWidget(self.ui_InfoLabel,4,26,1,90)
        gridLayout.addWidget(self.ui_CB_Reencode,4,121)
        gridLayout.addWidget(self.ui_Slider,5,0,1,120)
        gridLayout.addWidget(self.ui_Dial,5,121)
        gridLayout.addWidget(self.statusbar,6,0,1,122)

        return gridLayout
                                                  
                         

    def makeBoxLayout(self):
        vbox = QVBoxLayout()
        vbox.addWidget(self.ui_VideoFrame)
        vbox.addWidget(self.ui_InfoLabel );
        
        slidehbox = QHBoxLayout()
        slidehbox.addWidget(self.ui_Slider)
        slidehbox.addWidget(self.ui_Dial)

        midHBox = QHBoxLayout()
        midHBox.addWidget(self.ui_List)
        self.ui_List.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.Expanding)
        midHBox.addLayout(vbox)
        
        mainVBox = QVBoxLayout()
        mainVBox.addLayout(midHBox)
        mainVBox.addStretch(1)
        mainVBox.addLayout(slidehbox)
        return mainVBox
    
    def showInfo(self,text):
        self.ui_InfoLabel.setText(text)
    
    def showStatusMessage(self,text):
        self.statusbar.showMessage(text)
    
    def setDialResolution(self,resolution):
        self.ui_Dial.setMinimum(-resolution/2)
        self.ui_Dial.setMaximum(resolution/2)


    def syncSliderPos(self,pos):
        self.ui_Slider.setSliderPosition(pos)
    
    def setSliderTicks(self,ticks):
        self.ui_Slider.setSingleStep(ticks)
        self.ui_Slider.setPageStep(ticks*2)
    
    def setGotoFieldMaximum(self,count):
        self.ui_GotoField.setMaximum(count)
    
    def clearVideoFrame(self):
        self.ui_VideoFrame.showFrame(None)
 
    ### Marks 
    def addCutMark(self,frame,cutEntry,rowIndex):
        item = QListWidgetItem()
        img = CVImage(frame).scaled(self.ui_VideoFrame.imageRatio*SIZE_ICON, SIZE_ICON)
        pix = QtGui.QPixmap.fromImage(img)
        item.setIcon(QIcon(pix))
        if cutEntry.isStartMode():
            item.setBackgroundColor(QColor(224,255,224))
        else:
            item.setBackgroundColor(QColor(255,224,224))

        self.ui_List.insertItem(rowIndex,item)
        text = "%s <br> F: %s<br> T: %s" %(cutEntry.modeString,str(cutEntry.frameNumber),str(cutEntry.getTimeString()))
        marker = QLabel(text)
        marker.setWordWrap(True)
        marker.layout()
        self.ui_List.setItemWidget(item,marker)
        self.ui_List.setIconSize(QSize(SIZE_ICON,SIZE_ICON)) #Forces an update!
        self.ui_List.setCurrentItem(item)
        
 
    def hookEvents(self,aVideoController):
        self.__videoController=aVideoController #for menu callbacks
        self.ui_Slider.valueChanged.connect(aVideoController.sliderMoved)
        
        self.ui_Dial.valueChanged.connect(aVideoController.dialChanged)
        self.ui_Dial.sliderReleased.connect(self.__resetDial)
        
        self.ui_GotoField.editingFinished.connect(self.__gotoFrame)
        
        self.ui_CB_Reencode.stateChanged.connect(aVideoController.setExactCut)
        
        self.statusMessenger = StatusDispatcher()
        self.connect(self.statusMessenger,self.statusMessenger.signal,self.showStatusMessage)
        
        self._hookListActions()
    
    def keyReleaseEvent(self,event):
        self.__resetDial()
     
    def _hookListActions(self):
        #TOO bad-the list model -should be here... 
        rmAction = QtGui.QAction(QtGui.QIcon('icons/close-x.png'), 'Delete', self)
        rmAction.triggered.connect(self._removeMarker)
        rmAllAction = QtGui.QAction(QtGui.QIcon('icons/clear-all.png'), 'Remove all', self)
        rmAllAction.triggered.connect(self.purgeMarker)
        self.gotoAction = QtGui.QAction(QtGui.QIcon('icons/go-next.png'), 'Goto', self)
        self.gotoAction.triggered.connect(self._gotoFromMarker)
  
        #menus      
        self.ui_List.customContextMenuRequested.connect(self._openListMenu)
        self._listMenu = QMenu()
        self._listMenu.addAction(self.gotoAction)
        self._listMenu.addSeparator()
        self._listMenu.addAction(rmAction)
        self._listMenu.addAction(rmAllAction)

        
 
    def __resetDial(self):
        self.ui_Dial.setProperty("value", 0)

    def __gotoFrame(self):
        self.__videoController._gotoFrame(self.ui_GotoField.value())

    def __createProgressBar(self):
        self.progressBar = QtGui.QProgressBar(self)
        #self.progressBar.setRange(0,1)
        #self.progressBar.setValue(-1)
        #self.progressBar.reset()
        self.progressBar.setMinimum(0)
        self.progressBar.setMaximumWidth(150)
        self.progressBar.setVisible(False)
        return self.progressBar
    
    def showBusy(self):
        self.progressBar.setRange(0,0)
        self.progressBar.setVisible(True)
    
    def stopProgress(self):
        self.progressBar.setVisible(False)            

    def __createListWidget(self):
        iconList=QListWidget()
        iconList.setAlternatingRowColors(True)
        iconList.setContextMenuPolicy(Qt.CustomContextMenu)
        #iconList.setStyleSheet("QListWidget { background: red; } QListWidget::item { background: yellow; } QListWidget::item:selected { background: blue; }")
        iconList.setStyleSheet("QListWidget::item:selected:active { background: #28D9FF; color:#FFFFFF; } ")#that text color seems not to work!
        return iconList

    #---List widget context menu
    def _removeMarker(self,whatis):
        selectionList = self.ui_List.selectedIndexes()
        if len(selectionList)==0:
            return
        item = selectionList[0]
        self.ui_List.takeItem(item.row())
        self.__videoController.removeVideoCutIndex(item.row())

  
    def clearMarkerList(self):
        self.ui_List.clear()

    #remove contents, remove file 
    def purgeMarker(self):
        self.ui_List.clear()
        self.__videoController.purgeVideoCuts()
        
    def _gotoFromMarker(self,whatis):
        selectionList = self.ui_List.selectedIndexes()
        if len(selectionList)==0:
            return
        item = selectionList[0]
        self.__videoController.gotoCutIndex(item.row())
        
        
    def _openListMenu(self,position):
        selectionList = self.ui_List.selectedIndexes()
        if len(selectionList)==0:
            return
        self._listMenu.exec_(self.ui_List.viewport().mapToGlobal(position)) 
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 &copy; 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()
Example #34
0
class LayerItemWidget( QWidget ):
    @property
    def layer(self):
        return self._layer
    @layer.setter
    def layer(self, layer):
        if self._layer:
            self._layer.changed.disconnect(self._updateState)
        self._layer = layer
        self._updateState()
        self._layer.changed.connect(self._updateState)

    def __init__( self, parent=None ):
        QWidget.__init__( self, parent=parent )
        self._layer = None

        self._font = QFont(QFont().defaultFamily(), 9)
        self._fm = QFontMetrics( self._font )
        self.bar = FractionSelectionBar( initial_fraction = 0. )
        self.bar.setFixedHeight(10)
        self.nameLabel = QLabel()
        self.nameLabel.setFont( self._font )
        self.nameLabel.setText( "None" )
        self.opacityLabel = QLabel()
        self.opacityLabel.setAlignment(Qt.AlignRight)
        self.opacityLabel.setFont( self._font )
        self.opacityLabel.setText( u"\u03B1=%0.1f%%" % (100.0*(self.bar.fraction())))
        self.toggleEye = ToggleEye()
        self.toggleEye.setActive(False)
        self.toggleEye.setFixedWidth(35)
        self.toggleEye.setToolTip("Visibility")
        self.channelSelector = QSpinBox()
        self.channelSelector.setFrame( False )
        self.channelSelector.setFont( self._font )
        self.channelSelector.setMaximumWidth( 35 )
        self.channelSelector.setAlignment(Qt.AlignRight)
        self.channelSelector.setToolTip("Channel")
        self.channelSelector.setVisible(False)

        self._layout = QGridLayout()
        self._layout.addWidget( self.toggleEye, 0, 0 )
        self._layout.addWidget( self.nameLabel, 0, 1 )
        self._layout.addWidget( self.opacityLabel, 0, 2 )
        self._layout.addWidget( self.channelSelector, 1, 0)
        self._layout.addWidget( self.bar, 1, 1, 1, 2 )

        self._layout.setColumnMinimumWidth( 0, 35 )
        self._layout.setSpacing(0)
        self._layout.setContentsMargins(5,2,5,2)

        self.setLayout( self._layout)

        self.bar.fractionChanged.connect( self._onFractionChanged )
        self.toggleEye.activeChanged.connect( self._onEyeToggle )
        self.channelSelector.valueChanged.connect( self._onChannelChanged )

    def mousePressEvent( self, ev ):
        print "plonk", ev.pos(), ev.globalPos()
        QWidget.mousePressEvent( self, ev )

    def _onFractionChanged( self, fraction ):
        if self._layer and (fraction != self._layer.opacity):
            self._layer.opacity = fraction

    def _onEyeToggle( self, active ):
        if self._layer and (active != self._layer.visible):
            self._layer.visible = active

    def _onChannelChanged( self, channel ):
        if self._layer and (channel != self._layer.channel):
            self._layer.channel = channel

    def _updateState( self ):
        if self._layer:
            self.toggleEye.setActive(self._layer.visible)
            self.bar.setFraction( self._layer.opacity )
            self.opacityLabel.setText( u"\u03B1=%0.1f%%" % (100.0*(self.bar.fraction())))
            self.nameLabel.setText( self._layer.name )
            
            if self._layer.numberOfChannels > 1:
                self.channelSelector.setVisible( True )
                self.channelSelector.setMaximum( self._layer.numberOfChannels - 1 )
                self.channelSelector.setValue( self._layer.channel )
            else:
                self.channelSelector.setVisible( False )
                self.channelSelector.setMaximum( self._layer.numberOfChannels - 1)
                self.channelSelector.setValue( self._layer.channel )
            self.update()
Example #35
0
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())
Example #36
0
class LayerItemWidget( QWidget ):
    @property
    def layer(self):
        return self._layer
    @layer.setter
    def layer(self, layer):
        if self._layer:
            self._layer.changed.disconnect(self._updateState)
        self._layer = layer
        self._updateState()
        self._layer.changed.connect(self._updateState)

    def __init__( self, parent=None ):
        super(LayerItemWidget, self).__init__( parent=parent )
        self._layer = None

        self._font = QFont(QFont().defaultFamily(), 9)
        self._fm = QFontMetrics( self._font )
        self.bar = FractionSelectionBar( initial_fraction = 0. )
        self.bar.setFixedHeight(10)
        self.nameLabel = QLabel( parent=self )
        self.nameLabel.setFont( self._font )
        self.nameLabel.setText( "None" )
        self.opacityLabel = QLabel( parent=self )
        self.opacityLabel.setAlignment(Qt.AlignRight)
        self.opacityLabel.setFont( self._font )
        self.opacityLabel.setText( u"\u03B1=%0.1f%%" % (100.0*(self.bar.fraction())))
        self.toggleEye = ToggleEye( parent=self )
        self.toggleEye.setActive(False)
        self.toggleEye.setFixedWidth(35)
        self.toggleEye.setToolTip("Visibility")
        self.channelSelector = QSpinBox( parent=self )
        self.channelSelector.setFrame( False )
        self.channelSelector.setFont( self._font )
        self.channelSelector.setMaximumWidth( 35 )
        self.channelSelector.setAlignment(Qt.AlignRight)
        self.channelSelector.setToolTip("Channel")
        self.channelSelector.setVisible(False)

        self._layout = QGridLayout( self )
        self._layout.addWidget( self.toggleEye, 0, 0 )
        self._layout.addWidget( self.nameLabel, 0, 1 )
        self._layout.addWidget( self.opacityLabel, 0, 2 )
        self._layout.addWidget( self.channelSelector, 1, 0)
        self._layout.addWidget( self.bar, 1, 1, 1, 2 )

        self._layout.setColumnMinimumWidth( 0, 35 )
        self._layout.setSpacing(0)
        self._layout.setContentsMargins(5,2,5,2)

        self.setLayout( self._layout )

        self.bar.fractionChanged.connect( self._onFractionChanged )
        self.toggleEye.activeChanged.connect( self._onEyeToggle )
        self.channelSelector.valueChanged.connect( self._onChannelChanged )

    def mousePressEvent( self, ev ):
        super(LayerItemWidget, self).mousePressEvent( ev )

    def _onFractionChanged( self, fraction ):
        if self._layer and (fraction != self._layer.opacity):
            self._layer.opacity = fraction

    def _onEyeToggle( self, active ):
        if self._layer and (active != self._layer.visible):
            
            if self._layer._allowToggleVisible:
                self._layer.visible = active
            else:
                self.toggleEye.setActive(True)

    def _onChannelChanged( self, channel ):
        if self._layer and (channel != self._layer.channel):
            self._layer.channel = channel

    def _updateState( self ):
        if self._layer:
            self.toggleEye.setActive(self._layer.visible)
            self.bar.setFraction( self._layer.opacity )
            self.opacityLabel.setText( u"\u03B1=%0.1f%%" % (100.0*(self.bar.fraction())))
            self.nameLabel.setText( self._layer.name )
            
            if self._layer.numberOfChannels > 1:
                self.channelSelector.setVisible( True )
                self.channelSelector.setMaximum( self._layer.numberOfChannels - 1 )
                self.channelSelector.setValue( self._layer.channel )
            else:
                self.channelSelector.setVisible( False )
                self.channelSelector.setMaximum( self._layer.numberOfChannels - 1)
                self.channelSelector.setValue( self._layer.channel )
            self.update()
Example #37
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 &copy; 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()
Example #38
0
class Main(plugin.Plugin):
    ' main class for plugin '
    def initialize(self, *args, **kwargs):
        ' class init '
        super(Main, self).initialize(*args, **kwargs)
        self.process = QProcess()
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self.process.readyReadStandardError.connect(self.readErrors)
        self.process.finished.connect(self._process_finished)
        self.process.error.connect(self._process_finished)
        # directory auto completer
        self.completer, self.dirs = QCompleter(self), QDirModel(self)
        self.dirs.setFilter(QDir.Dirs | QDir.NoDotAndDotDot)
        self.completer.setModel(self.dirs)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)

        menu = QMenu('Clones')
        menu.addAction('Analyze for Code Clones here', lambda: self.make_clon())
        self.locator.get_service('explorer').add_project_menu(menu, lang='all')

        self.group1 = QGroupBox()
        self.group1.setTitle(' Target ')
        self.outdir, self.igndir = QLineEdit(path.expanduser("~")), QLineEdit()
        self.outdir.setCompleter(self.completer)
        self.btn1 = QPushButton(QIcon.fromTheme("document-open"), ' Open ')
        self.btn1.clicked.connect(lambda: self.outdir.setText(str(
            QFileDialog.getExistingDirectory(self.dock,
            'Please, Open a Target Directory...', path.expanduser("~")))))
        self.btn1a = QPushButton(QIcon.fromTheme("face-smile"),
                                 'Get from Ninja active project')
        self.btn1a.clicked.connect(lambda: self.outdir.setText(
          self.locator.get_service('explorer').get_current_project_item().path))

        self.ignckb, self.ignmor = QComboBox(), QTextEdit()
        self.ignckb.addItems(['Single Directory', 'Multiple Directories CSV'])
        self.ignckb.currentIndexChanged.connect(self.on_ignore_changed)
        self.ignmor.hide()
        self.igndir.setPlaceholderText('Exclude directory')
        self.igndir.setCompleter(self.completer)
        self.btn2 = QPushButton(QIcon.fromTheme("document-open"), ' Open ')
        self.btn2.clicked.connect(lambda: self.igndir.setText(str(
            QFileDialog.getExistingDirectory(self.dock,
            'Please, Open a Ignore Directory...', path.expanduser("~")))))
        vboxg1 = QVBoxLayout(self.group1)
        for each_widget in (QLabel('<b>Target directory path: '), self.outdir,
            self.btn1, self.btn1a, QLabel('<b>Ignore directory path: '),
            self.ignckb, self.ignmor, self.igndir, self.btn2, ):
            vboxg1.addWidget(each_widget)

        self.group2 = QGroupBox()
        self.group2.setTitle(' Output ')
        self.outfle = QLineEdit(path.join(path.expanduser("~"), 'output.html'))
        self.outfle.setPlaceholderText('Exclude directory')
        self.outfle.setCompleter(self.completer)
        self.btn3 = QPushButton(QIcon.fromTheme("document-save"), ' Save ')
        self.btn3.clicked.connect(lambda: self.outfle.setText(
            QFileDialog.getSaveFileName(self.dock, 'Save', path.expanduser("~"),
            'XML(*.xml)' if self.xmlo.isChecked() is True else 'HTML(*.html)')))
        vboxg2 = QVBoxLayout(self.group2)
        for each_widget in (QLabel('<b>Output report file path:'),
            self.outfle, self.btn3):
            vboxg2.addWidget(each_widget)

        self.group3 = QGroupBox()
        self.group3.setTitle(' Options ')
        self.group3.setCheckable(True)
        self.group3.setGraphicsEffect(QGraphicsBlurEffect(self))
        self.group3.graphicsEffect().setEnabled(False)
        self.group3.toggled.connect(self.toggle_options_group)
        self.qckb1, self.qckb2 = QCheckBox('Recursive'), QCheckBox('Time-less')
        self.qckb3, self.qckb4 = QCheckBox('Force Diff'), QCheckBox('Fast Mode')
        self.qckb5, self.tm = QCheckBox('Save a LOG file to target'), QLabel('')
        self.xmlo = QCheckBox('XML Output instead of HTML')
        self.opeo = QCheckBox('Open Clones Report when done')
        self.chrt = QCheckBox('LOW CPU priority for Backend Process')
        self.mdist, self.hdep, self.output = QSpinBox(), QSpinBox(), QTextEdit()
        self.ign_func = QLineEdit('test, forward, backward, Migration')
        self.mdist.setValue(5)
        self.hdep.setValue(1)
        self.mdist.setToolTip('''<b>Maximum amount of difference between pair of
        sequences in clone pair (5 default).Larger value more false positive''')
        self.hdep.setToolTip('''<b>Computation can be speeded up by increasing
                       this value, but some clones can be missed (1 default)''')
        [a.setChecked(True) for a in (self.qckb1, self.qckb3, self.qckb5,
                                      self.chrt, self.opeo)]
        vboxg3 = QVBoxLayout(self.group3)
        for each_widget in (self.qckb1, self.qckb2, self.qckb3, self.qckb4,
            self.qckb5, self.chrt, self.xmlo, self.opeo,
            QLabel('<b>Max Distance Threshold:'), self.mdist,
            QLabel('<b>Max Hashing Depth:'), self.hdep,
            QLabel('<b>Ignore code block prefix:'), self.ign_func):
            vboxg3.addWidget(each_widget)

        self.group4, self.auto = QGroupBox(), QComboBox()
        self.group4.setTitle(' Automation ')
        self.group4.setCheckable(True)
        self.group4.setToolTip('<font color="red"><b>WARNING:Advanced Setting!')
        self.group4.toggled.connect(lambda: self.group4.hide())
        self.auto.addItems(['Never run automatically', 'Run when File Saved',
            'Run when File Executed', 'Run when Tab Changed',
            'Run when File Opened', 'Run before File Saved'])
        self.auto.currentIndexChanged.connect(self.on_auto_changed)
        QVBoxLayout(self.group4).addWidget(self.auto)

        self.button = QPushButton(' Analyze for Clones ')
        self.button.setMinimumSize(75, 50)
        self.button.clicked.connect(self.run)
        glow = QGraphicsDropShadowEffect(self)
        glow.setOffset(0)
        glow.setBlurRadius(99)
        glow.setColor(QColor(99, 255, 255))
        self.button.setGraphicsEffect(glow)

        self.butkil = QPushButton(' Force Kill Clones ')
        self.butkil.clicked.connect(lambda: self.process.kill())

        class TransientWidget(QWidget):
            ' persistant widget thingy '
            def __init__(self, widget_list):
                ' init sub class '
                super(TransientWidget, self).__init__()
                vbox = QVBoxLayout(self)
                for each_widget in widget_list:
                    vbox.addWidget(each_widget)

        tw = TransientWidget((QLabel('<i>D.R.Y. principle analyzer'),
            self.group1, self.group2, self.group3, self.group4,
            QLabel('<b>Backend Logs'), self.output, self.tm, self.button,
            self.butkil))
        self.scrollable, self.dock = QScrollArea(), QDockWidget()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(tw)
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setWidget(self.scrollable)
        ExplorerContainer().addTab(self.dock, "Clones")
        QPushButton(QIcon.fromTheme("help-about"), 'About', self.dock
            ).clicked.connect(lambda:
            QMessageBox.information(self.dock, __doc__, HELPMSG))

    def readOutput(self):
        """Read and append output to the logBrowser"""
        self.output.append(str(self.process.readAllStandardOutput()).strip())

    def readErrors(self):
        """Read and append errors to the logBrowser"""
        self.output.append(self.formatErrorMsg(str(
                                        self.process.readAllStandardError())))

    def formatErrorMsg(self, msg):
        """Format error messages in red color"""
        return self.formatMsg(msg, 'red')

    def formatInfoMsg(self, msg):
        """Format informative messages in blue color"""
        return self.formatMsg(msg, 'green')

    def formatMsg(self, msg, color):
        """Format message with the given color"""
        return '<font color="{}">{}</font>'.format(color, msg)

    def make_clon(self):
        ' make clones analyze from contextual sub menu '
        self.outdir.setText(
          self.locator.get_service('explorer').get_current_project_item().path)
        self.run()

    def run(self):
        ' run the actions '
        self.output.clear()
        self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now())))
        self.tm.setText('<center><b>Last Clone: </b>' +
                        datetime.now().isoformat().split('.')[0])
        self.button.setDisabled(True)
        if not len(self.outdir.text()) and not len(self.outfle.text()):
            self.output.append(self.formatErrorMsg('ERROR: FAIL: Target empty'))
            self.button.setEnabled(True)
            return
        # run the subprocesses
        cmd = ' '.join((
            'chrt -i 0' if self.chrt.isChecked() is True else '', 'clonedigger',
            '' if self.qckb1.isChecked() is True else '--no-recursion',
            '--dont-print-time' if self.qckb2.isChecked() is True else '',
            '--force' if self.qckb3.isChecked() is True else '',
            '--fast' if self.qckb4.isChecked() is True else '',
            '--cpd-output' if self.xmlo.isChecked() is True else '',
            '' if self.xmlo.isChecked() is True else '--report-unifiers',
            '--distance-threshold={}'.format(self.mdist.value()),
            '--hashing-depth={}'.format(self.hdep.value()),
            '--ignore-dir="{}"'.format(self.igndir.text()
                if self.ignckb.currentIndex() is 0
                else self.ignmor.toPlainText()),
            '--func-prefixes="{}"'.format(self.ign_func.text()),
            '--output="{}"'.format(self.outfle.text()),
            '--language=python', path.abspath(self.outdir.text()),
        ))
        self.output.append(self.formatInfoMsg('INFO:OK:Command:{}'.format(cmd)))
        self.process.start(cmd)
        if not self.process.waitForStarted():
            self.output.append(self.formatErrorMsg(' ERROR: FAIL: Meh. '))
            self.output.append(self.formatErrorMsg('ERROR:FAIL:{}'.format(cmd)))
            self.button.setEnabled(True)
            return
        self.readOutput()
        self.readErrors()
        self.button.setEnabled(True)

    def _process_finished(self):
        """ finished sucessfully """
        self.output.append(self.formatInfoMsg('INFO:{}'.format(datetime.now())))
        # write a .log file on target
        if self.qckb5.isChecked() is True:
            log_file = 'ninja_clones.log'
            with open(path.join(str(self.outdir.text()), log_file), 'w') as log:
                self.output.append(self.formatInfoMsg('''INFO: OK: Writing Logs:
                    {}'''.format(path.join(str(self.outdir.text()), log_file))))
                log.write(self.output.toPlainText())
                log.close()
        # open target output
        if self.opeo.isChecked() is True and self.xmlo.isChecked() is False:
            try:
                startfile(self.outfle.text())
            except:
                Popen(["xdg-open", self.outfle.text()])
        self.output.selectAll()
        self.output.setFocus()

    def toggle_options_group(self):
        ' toggle on off the options group '
        if self.group3.isChecked() is True:
            [a.setChecked(True) for a in (self.qckb1, self.qckb3, self.qckb5,
                                          self.chrt, self.opeo)]
            self.mdist.setValue(5)
            self.hdep.setValue(1)
            self.group3.graphicsEffect().setEnabled(False)
        else:
            [a.setChecked(False) for a in (self.qckb1, self.qckb3, self.qckb5,
                                           self.chrt, self.opeo)]
            self.group3.graphicsEffect().setEnabled(True)

    def on_ignore_changed(self):
        'hide or show one widget or another depending what kind of input need'
        if self.ignckb.currentIndex() is 0:
            self.igndir.show()
            self.btn2.show()
            self.ignmor.hide()
        else:
            self.igndir.hide()
            self.btn2.hide()
            self.ignmor.show()

    def on_auto_changed(self):
        ' automation connects '
        if self.auto.currentIndex() is 1:
            self.locator.get_service('editor').fileSaved.connect(lambda:
                self.run())
            QMessageBox.information(self.dock, __doc__,
            '<b>Now Actions will Run Automatically when any File is Saved !')
        elif self.auto.currentIndex() is 2:
            self.locator.get_service('editor').fileExecuted.connect(lambda:
                self.run())
            QMessageBox.information(self.dock, __doc__,
            '<b>Now Actions will Run Automatically when any File is Executed !')
        elif self.auto.currentIndex() is 3:
            self.locator.get_service('editor').currentTabChanged.connect(lambda:
                self.run())
            QMessageBox.information(self.dock, __doc__,
            '<b>Now Actions will Run Automatically when current Tab is Changed')
        elif self.auto.currentIndex() is 4:
            self.locator.get_service('editor').fileOpened.connect(lambda:
                self.run())
            QMessageBox.information(self.dock, __doc__,
            '<b>Now Actions will Run Automatically when any File is Opened !')
        elif self.auto.currentIndex() is 5:
            self.locator.get_service('editor').beforeFileSaved.connect(lambda:
                self.run())
            QMessageBox.information(self.dock, __doc__,
            '<b>Now Actions will Run Automatically before any File is Saved !')
        self.group4.setDisabled(True)

    def finish(self):
        ' clear when finish '
        self.process.kill()