class DefaultSelectParameterWidget(SelectParameterWidget):

    """Widget class for Default Select Parameter."""

    def __init__(self, parameter, parent=None):
        """Constructor

        :param parameter: A DefaultSelectParameter object.
        :type parameter: DefaultSelectParameter
        """
        super(DefaultSelectParameterWidget, self).__init__(parameter, parent)

        self.default_layout = QHBoxLayout()
        self.radio_button_layout = QHBoxLayout()
        self.radio_button_widget = QWidget()

        self.default_label = QLabel(tr('Default'))

        # Create radio button group
        self.default_input_button_group = QButtonGroup()

        # Define string enabler for radio button
        self.radio_button_enabler = self.input.itemData(0, Qt.UserRole)

        for i in range(len(self._parameter.default_labels)):
            if '%s' in self._parameter.default_labels[i]:
                label = (
                    self._parameter.default_labels[i] %
                    self._parameter.default_values[i])
            else:
                label = self._parameter.default_labels[i]

            radio_button = QRadioButton(label)
            self.radio_button_layout.addWidget(radio_button)
            self.default_input_button_group.addButton(radio_button, i)
            if self._parameter.default_value == \
                    self._parameter.default_values[i]:
                radio_button.setChecked(True)

        # Create double spin box for custom value
        self.custom_value = QDoubleSpinBox()
        if self._parameter.default_values[-1]:
            self.custom_value.setValue(self._parameter.default_values[-1])
        has_min = False
        if self._parameter.minimum is not None:
            has_min = True
            self.custom_value.setMinimum(self._parameter.minimum)
        has_max = False
        if self._parameter.maximum is not None:
            has_max = True
            self.custom_value.setMaximum(self._parameter.maximum)
        if has_min and has_max:
            step = (self._parameter.maximum - self._parameter.minimum) / 100.0
            self.custom_value.setSingleStep(step)
        self.radio_button_layout.addWidget(self.custom_value)

        self.toggle_custom_value()

        # Reset the layout
        self.input_layout.setParent(None)
        self.help_layout.setParent(None)

        self.label.setParent(None)
        self.inner_input_layout.setParent(None)

        self.input_layout = QGridLayout()
        self.input_layout.setSpacing(0)

        self.input_layout.addWidget(self.label, 0, 0)
        self.input_layout.addLayout(self.inner_input_layout, 0, 1)
        self.input_layout.addWidget(self.default_label, 1, 0)
        self.input_layout.addLayout(self.radio_button_layout, 1, 1)

        self.main_layout.addLayout(self.input_layout)
        self.main_layout.addLayout(self.help_layout)

        # check every added combobox, it could have been toggled by
        # the existing keyword
        self.toggle_input()

        # Connect
        # noinspection PyUnresolvedReferences
        self.input.currentIndexChanged.connect(self.toggle_input)
        self.default_input_button_group.buttonClicked.connect(
            self.toggle_custom_value)

    def raise_invalid_type_exception(self):
        message = 'Expecting element type of %s' % (
            self._parameter.element_type.__name__)
        err = ValueError(message)
        return err

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

        :returns: A DefaultSelectParameter from the current state of widget.
        """
        current_index = self.input.currentIndex()
        selected_value = self.input.itemData(current_index, Qt.UserRole)
        if hasattr(selected_value, 'toPyObject'):
            selected_value = selected_value.toPyObject()

        try:
            self._parameter.value = selected_value
        except ValueError:
            err = self.raise_invalid_type_exception()
            raise err

        radio_button_checked_id = self.default_input_button_group.checkedId()
        # No radio button checked, then default value = None
        if radio_button_checked_id == -1:
            self._parameter.default = None
        # The last radio button (custom) is checked, get the value from the
        # line edit
        elif (radio_button_checked_id
              == len(self._parameter.default_values) - 1):
            self._parameter.default_values[radio_button_checked_id] \
                = self.custom_value.value()
            self._parameter.default = self.custom_value.value()
        else:
            self._parameter.default = self._parameter.default_values[
                radio_button_checked_id]

        return self._parameter

    def set_default(self, default):
        """Set default value by item's string.

        :param default: The default.
        :type default: str, int

        :returns: True if success, else False.
        :rtype: bool
        """
        # Find index of choice
        try:
            default_index = self._parameter.default_values.index(default)
            self.default_input_button_group.button(default_index).setChecked(
                True)
        except ValueError:
            last_index = len(self._parameter.default_values) - 1
            self.default_input_button_group.button(last_index).setChecked(
                True)
            self.custom_value.setValue(default)

        self.toggle_custom_value()

    def toggle_custom_value(self):
        radio_button_checked_id = self.default_input_button_group.checkedId()
        if (radio_button_checked_id
                == len(self._parameter.default_values) - 1):
            self.custom_value.setDisabled(False)
        else:
            self.custom_value.setDisabled(True)

    def toggle_input(self):
        """Change behaviour of radio button based on input."""
        current_index = self.input.currentIndex()
        # If current input is not a radio button enabler, disable radio button.
        if self.input.itemData(current_index, Qt.UserRole) != (
                self.radio_button_enabler):
            self.disable_radio_button()
        # Otherwise, enable radio button.
        else:
            self.enable_radio_button()

    def set_selected_radio_button(self):
        """Set selected radio button to 'Do not report'."""
        dont_use_button = self.default_input_button_group.button(
            len(self._parameter.default_values) - 2)
        dont_use_button.setChecked(True)

    def disable_radio_button(self):
        """Disable radio button group and custom value input area."""
        checked = self.default_input_button_group.checkedButton()
        if checked:
            self.default_input_button_group.setExclusive(False)
            checked.setChecked(False)
            self.default_input_button_group.setExclusive(True)
        for button in self.default_input_button_group.buttons():
            button.setDisabled(True)
        self.custom_value.setDisabled(True)

    def enable_radio_button(self):
        """Enable radio button and custom value input area then set selected
        radio button to 'Do not report'.
        """
        for button in self.default_input_button_group.buttons():
            button.setEnabled(True)
        self.set_selected_radio_button()
        self.custom_value.setEnabled(True)
class SDEllipseDialog(QDialog, FORM_CLASS):

    def __init__(self, iface, parent=None):
        self.iface = iface
        self.plugin_dir = os.path.dirname(__file__)

        # Some constants
        self.SDELLIPSE = self.tr('SD Ellipse')
        self.CANCEL = self.tr('Cancel')
        self.HELP = self.tr('Help')
        self.CLOSE = self.tr('Close')
        self.OK = self.tr('OK')

        """Constructor."""
        super(SDEllipseDialog, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)

        self.method_group = QButtonGroup()
        self.method_group.addButton(self.yuill_rb)
        self.method_group.addButton(self.crimestat_rb)
        self.method_group.buttonClicked[QAbstractButton].connect(
                                                   self.methodChanged)
        self.yuill_rb.setChecked(True)
        self.method = 1
        okButton = self.button_box.button(QDialogButtonBox.Ok)
        okButton.setText(self.OK)
        cancelButton = self.button_box.button(QDialogButtonBox.Cancel)
        cancelButton.setText(self.CANCEL)
        cancelButton.setEnabled(False)
        # helpButton = self.button_box.button(QDialogButtonBox.Help)
        helpButton = self.helpButton
        helpButton.setText(self.HELP)
        closeButton = self.button_box.button(QDialogButtonBox.Close)
        closeButton.setText(self.CLOSE)

        # Connect signals
        okButton.clicked.connect(self.startWorker)
        cancelButton.clicked.connect(self.killWorker)
        helpButton.clicked.connect(self.giveHelp)
        closeButton.clicked.connect(self.reject)
        self.cumulative = False
        inpIndexCh = self.InputLayer.currentIndexChanged['QString']
        inpIndexCh.connect(self.layerchanged)
        # QObject.disconnect(self.button_box, SIGNAL("rejected()"),
        #                    self.reject)
        self.button_box.rejected.disconnect(self.reject)

        # Set instance variables
        self.worker = None
        self.inputlayerid = None
        self.layerlistchanging = False
        self.selectedFeatures_cb.setChecked(True)
        self.useWeights_cb.setChecked(False)
        self.result = None
    # end of __init__

    def giveHelp(self):
        self.showInfo('Giving help')
        QDesktopServices.openUrl(QUrl.fromLocalFile(
                         self.plugin_dir + "/help/html/index.html"))
        # showPluginHelp(None, "help/html/index")
    # end of giveHelp

    def startWorker(self):
        # self.showInfo('Ready to start worker')
        self.degfreedCorr = self.degfreedcorr_cb.isChecked()
        self.crimestatCorr = self.crimestatcorr_cb.isChecked()
        # Get the input layer
        layerindex = self.InputLayer.currentIndex()
        layerId = self.InputLayer.itemData(layerindex)
        inputlayer = QgsProject.instance().mapLayer(layerId)
        if inputlayer is None:
            self.showError(self.tr('No input layer defined'))
            return
        self.featureCount = 0
        if self.selectedFeatures_cb.isChecked():
            self.featureCount = inputlayer.selectedFeatureCount()
        if self.featureCount == 0:
            self.featureCount = inputlayer.featureCount()
        if self.featureCount < 2:
            self.showError(self.tr('Not enough features'))
            # self.scene.clear()
            return
        if (self.useWeights_cb.isChecked() and
                 self.inputField.count() == 0):
            self.showError(self.tr('Missing numerical field'))
            return
        fieldindex = self.inputField.currentIndex()
        fieldname = self.inputField.itemData(fieldindex)
        # inpfield = inputlayer.fieldNameIndex(fieldindex)
        # minval = inputlayer.minimumValue(inpfield)

        if (not self.useWeights_cb.isChecked()):
            fieldname = None
        self.result = None
        self.SDLayer = inputlayer
        self.method = 1
        if self.yuill_rb.isChecked():
            self.method = 1
        elif self.crimestat_rb.isChecked():
            self.method = 2
        if self.featureCount < 3 and (self.method == 2 or
                                      self.degfreedCorr):
            self.showError(self.tr('Not enough features'))
            return
        # create a new worker instance
        worker = Worker(inputlayer,
                        self.selectedFeatures_cb.isChecked(),
                        fieldname, self.method)
        # start the worker in a new thread
        thread = QThread(self)
        worker.moveToThread(thread)
        worker.finished.connect(self.workerFinished)
        worker.error.connect(self.workerError)
        worker.status.connect(self.workerInfo)
        worker.progress.connect(self.progressBar.setValue)
        # worker.progress.connect(self.aprogressBar.setValue)
        thread.started.connect(worker.run)
        thread.start()
        self.thread = thread
        self.worker = worker
        self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
        self.button_box.button(QDialogButtonBox.Close).setEnabled(False)
        self.button_box.button(QDialogButtonBox.Cancel).setEnabled(True)
        self.InputLayer.setEnabled(False)
        self.inputField.setEnabled(False)
    # end of startWorker

    def workerFinished(self, ok, ret):
        """Handles the output from the worker and cleans up after the
           worker has finished."""
        # clean up the worker and thread
        self.worker.deleteLater()
        self.thread.quit()
        self.thread.wait()
        self.thread.deleteLater()
        # remove widget from the message bar (pop)
        # self.iface.messageBar().popWidget(self.messageBar)
        if ok and ret is not None:
            # self.showInfo("Result: " + str(ret))
            self.result = ret
            # Draw the ellipse
            self.drawEllipse()
        else:
            # notify the user that something went wrong
            if not ok:
                self.showError(self.tr('Aborted') + '!')
            else:
                self.showError(self.tr('Not able to create ellipse') + '!')
        # Update the user interface
        self.progressBar.setValue(0.0)
        self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
        self.button_box.button(QDialogButtonBox.Close).setEnabled(True)
        self.button_box.button(QDialogButtonBox.Cancel).setEnabled(False)
        self.InputLayer.setEnabled(True)
        if self.method == 1 and self.inputField.count() > 0:
            self.inputField.setEnabled(True)
    # end of workerFinished(self, ok, ret)

    def workerError(self, exception_string):
        """Report an error from the worker."""
        self.showError(self.tr('Worker failed - exception') +
                               ': ' + exception_string)

    def workerInfo(self, message_string):
        """Report an info message from the worker."""
        self.showInfo(self.tr('Worker') + ': ' + message_string)

    def killWorker(self):
        """Kill the worker thread."""
        if self.worker is not None:
            QgsMessageLog.logMessage(self.tr('Killing worker'),
                                     self.SDELLIPSE,
                                     Qgis.Info)
            self.worker.kill()

    # Implement the reject method to have the possibility to avoid
    # exiting the dialog when cancelling
    def reject(self):
        """Reject override."""
        # exit the dialog
        QDialog.reject(self)

    def drawEllipse(self):
        # self.showInfo('Result: ' + str(self.result))
        meanx = self.result[0]
        meany = self.result[1]
        angle1 = self.result[2]
        angle2 = self.result[3]
        SD1 = self.result[4]
        SD2 = self.result[5]
        if self.method == 2:  # CrimeStat
            SD1 = SD1 * (sqrt(2) *
                         sqrt(self.featureCount) /
                         sqrt(self.featureCount - 2))
            SD2 = SD2 * (sqrt(2) *
                         sqrt(self.featureCount) /
                         sqrt(self.featureCount - 2))
        if self.crimestatCorr and self.method != 2:
            SD1 = SD1 * sqrt(2)
            SD2 = SD2 * sqrt(2)
        if self.degfreedCorr and self.method != 2:
            SD1 = SD1 * sqrt(self.featureCount) / sqrt(self.featureCount - 2)
            SD2 = SD2 * sqrt(self.featureCount) / sqrt(self.featureCount - 2)
            # SD1 = SD1 * sqrt(self.featureCount) / sqrt(self.featureCount - 1)
            # SD2 = SD2 * sqrt(self.featureCount) / sqrt(self.featureCount - 1)
        # Find the major and minor axis
        majoraxisangle = angle1
        minoraxisangle = angle2
        majorSD = SD2
        minorSD = SD1
        if SD2 < SD1:
            majoraxisangle = angle2
            minoraxisangle = angle1
            majorSD = SD1
            minorSD = SD2
        # Calculate the "compass" direction angle (clockwise from north)
        direction = 90.0 - majoraxisangle * 180 / pi
        # Calculte the eccentricity
        eccentricity = sqrt(1 - pow(minorSD, 2) / pow(majorSD, 2))
        # Create the memory layer for the ellipse
        sdefields = []
        sdefields.append(QgsField("meanx", QVariant.Double))
        sdefields.append(QgsField("meany", QVariant.Double))
        sdefields.append(QgsField("majoranglerad", QVariant.Double))
        # sdefields.append(QgsField("minoranglerad", QVariant.Double))
        sdefields.append(QgsField("directiondeg", QVariant.Double))
        sdefields.append(QgsField("majorsd", QVariant.Double))
        sdefields.append(QgsField("minorsd", QVariant.Double))
        sdefields.append(QgsField("eccentricity", QVariant.Double))
        layeruri = 'Polygon?'
        layeruri = (layeruri + 'crs=' +
                    str(self.SDLayer.dataProvider().crs().authid()))
        memSDlayer = QgsVectorLayer(layeruri, self.OutputLayerName.text(),
                                    "memory")
        # Set the CRS to the original CRS object
        memSDlayer.setCrs(self.SDLayer.dataProvider().crs())
        memSDlayer.startEditing()  # ?
        for field in sdefields:
            memSDlayer.dataProvider().addAttributes([field])
        sdfeature = QgsFeature()
        theta1 = majoraxisangle
        points = []
        step = pi / 180    # 360 points to draw the ellipse
        t = 0.0
        while t < 2 * pi:
            p1 = QPointF(meanx + majorSD * cos(t) * cos(majoraxisangle) -
                         minorSD * sin(t) * sin(majoraxisangle),
                         meany + majorSD * cos(t) * sin(majoraxisangle) +
                         minorSD * sin(t) * cos(majoraxisangle))
            points.append(QgsPointXY(p1))
            t = t + step
        # Close the polygon
        p1 = QPointF(meanx + majorSD * cos(majoraxisangle),
                     meany + majorSD * sin(majoraxisangle))
        points.append(QgsPointXY(p1))
        sdfeature.setGeometry(QgsGeometry.fromPolygonXY([points]))
        attrs = [meanx, meany, majoraxisangle, direction,
                 majorSD, minorSD, eccentricity]
        sdfeature.setAttributes(attrs)
        memSDlayer.dataProvider().addFeatures([sdfeature])
        memSDlayer.commitChanges()  # ?
        memSDlayer.updateExtents()
        QgsProject.instance().addMapLayers([memSDlayer])
    # end of drawEllipse

    def layerchanged(self, number=0):
        """Do the necessary updates after a layer selection has
           been changed."""
        self.layerselectionactive = True
        layerindex = self.InputLayer.currentIndex()
        layerId = self.InputLayer.itemData(layerindex)
        self.inputlayerid = layerId
        inputlayer = QgsProject.instance().mapLayer(layerId)
        while self.inputField.count() > 0:
            self.inputField.removeItem(0)
        self.useWeights_cb.setEnabled(False)
        self.inputField.setEnabled(False)
        self.layerselectionactive = False
        # Get the numerical fields
        if inputlayer is not None:
            provider = inputlayer.dataProvider()
            attribs = provider.fields()
            if str(type(attribs)) != "<type 'dict'>":
                atr = {}
                for i in range(attribs.count()):
                    atr[i] = attribs.at(i)
                attrdict = atr
            for id, attrib in attrdict.items():
                # Check for numeric attribute
                #if attrib.typeName().upper() in ('REAL', 'INTEGER', 'INT4',
                #                                 'INT8', 'FLOAT4'):
                if attrib.isNumeric():
                    self.inputField.addItem(attrib.name(), attrib.name())
            if (self.inputField.count() > 0):
                if self.method == 1:
                    self.useWeights_cb.setEnabled(True)
                    self.inputField.setEnabled(True)
            else:
                self.useWeights_cb.setChecked(False)
            self.OutputLayerName.setText(
                "SDE_" +
                self.method_group.checkedButton().text().strip('"') +
                "_" + self.InputLayer.currentText())
    # end of layerchanged

    def methodChanged(self, button):
        if self.InputLayer.currentText() is not None:
            self.OutputLayerName.setText("SDE_" + button.text().strip('"') +
                                         "_" + self.InputLayer.currentText())
        # Disable all options
        self.crimestatcorr_cb.setEnabled(False)
        self.crimestatcorr_cb.setChecked(False)
        self.degfreedcorr_cb.setEnabled(False)
        self.degfreedcorr_cb.setChecked(False)
        self.useWeights_cb.setEnabled(False)
        self.useWeights_cb.setChecked(False)
        self.inputField.setEnabled(False)
        if button.text() == '"CrimeStat"':
            self.method = 2
        elif button.text() == "Yuill":
            self.method = 1
            self.crimestatcorr_cb.setEnabled(True)
            self.degfreedcorr_cb.setEnabled(True)
            if self.inputField.count() > 0:
                self.useWeights_cb.setEnabled(True)
                self.inputField.setEnabled(True)
        else:  # Should not be reached yet
            if self.inputField.count() > 0:
                self.useWeights_cb.setEnabled(True)
                self.inputField.setEnabled(True)

    def showError(self, text):
        """Show an error."""
        # self.iface.messageBar().pushMessage(self.tr('Error'), text,
        #                                     level=QgsMessageBar.CRITICAL,
        #                                     duration=3)
        QgsMessageLog.logMessage('Error: ' + text,
                                 self.SDELLIPSE,
                                 Qgis.Critical)

    def showWarning(self, text):
        """Show a warning."""
        # self.iface.messageBar().pushMessage(self.tr('Warning'), text,
        #                                     level=QgsMessageBar.WARNING,
        #                                     duration=2)
        QgsMessageLog.logMessage('Warning: ' + text,
                                 self.SDELLIPSE,
                                 Qgis.Warning)

    def showInfo(self, text):
        """Show info."""
        # self.iface.messageBar().pushMessage(self.tr('Info'), text,
        #                                     level=QgsMessageBar.INFO,
        #                                     duration=2)
        QgsMessageLog.logMessage('Info: ' + text,
                                 self.SDELLIPSE,
                                 Qgis.Info)

    # Implement the accept method to avoid exiting the dialog when
    # starting the work
    def accept(self):
        """Accept override."""
        pass

    # Implement the reject method to have the possibility to avoid
    # exiting the dialog when cancelling
    def reject(self):
        """Reject override."""
        # exit the dialog
        QDialog.reject(self)

    # Translation
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        return QCoreApplication.translate('Dialog', message)

    # Overriding
    def resizeEvent(self, event):
        return
        # self.showInfo("resizeEvent")

    # Overriding
    def showEvent(self, event):
        return
Ejemplo n.º 3
0
class OptionWidget(EditorWidget):
    widgettype = 'Option Row'

    def __init__(self, *args, **kwargs):
        super(OptionWidget, self).__init__(*args, **kwargs)
        self._bindvalue = None
        self.group = QButtonGroup()
        self.group.buttonClicked.connect(self.emitvaluechanged)

    def createWidget(self, parent=None):
        widget = QWidget(parent)
        return widget

    def _buildfromlist(self, listconfig, multiselect):
        def chunks(l, n):
            """ Yield successive n-sized chunks from l.
            """
            for i in range(0, len(l), n):
                yield l[i:i + n]

        items = listconfig['items']
        wrap = self.config.get('wrap', 0)
        showcolor = self.config.get('always_color', False)
        if wrap > 0:
            rows = list(chunks(items, wrap))
        else:
            rows = [items]

        for rowcount, row in enumerate(rows):
            for column, item in enumerate(row):
                parts = item.split(';')
                data = parts[0]
                try:
                    desc = parts[1]
                except IndexError:
                    desc = data

                button = QPushButton()
                button.setCheckable(multiselect)
                self.group.setExclusive(not multiselect)

                icon = QIcon()
                try:
                    path = parts[2]
                    if path.startswith("#"):
                        # Colour the button with the hex value.
                        # If show color is enabled we always show the color regardless of selection.
                        if not showcolor:
                            style = """
                                QPushButton::checked {{
                                    border: 3px solid rgb(137, 175, 255);
                                    background-color: {colour};
                                }}""".format(colour=path)
                        else:
                            style = """
                                QPushButton::checked {{
                                    border: 3px solid rgb(137, 175, 255);
                                }}
                                QPushButton {{
                                    background-color: {colour};
                                }}""".format(colour=path)
                        button.setStyleSheet(style)
                    elif path.endswith("_icon"):
                        icon = QIcon(":/icons/{}".format(path))
                    else:
                        icon = QIcon(path)
                except:
                    icon = QIcon()

                button.setCheckable(True)
                button.setText(desc)
                button.setProperty("value", data)
                button.setIcon(icon)
                button.setIconSize(QSize(24, 24))
                if isinstance(self.widget.layout(), QBoxLayout):
                    self.widget.layout().addWidget(button)
                else:
                    self.widget.layout().addWidget(button, rowcount, column)
                self.group.addButton(button)

    def initWidget(self, widget, config):
        if not widget.layout():
            widget.setLayout(QGridLayout())
            widget.layout().setContentsMargins(0, 0, 0, 0)

    def updatefromconfig(self):
        super(OptionWidget, self).updatefromconfig()

        for button in self.group.buttons():
            self.group.removeButton(button)
            self.widget.layout().removeWidget(button)
            button.deleteLater()
            button.setParent(None)

        listconfig = self.config['list']
        multiselect = self.config.get('multi', False)
        self._buildfromlist(listconfig, multiselect)

        super(OptionWidget, self).endupdatefromconfig()

    def validate(self, *args):
        button = self.group.checkedButton()
        if button:
            return True

        return False

    @property
    def buttons(self):
        return self.group.buttons()

    @property
    def nullvalues(self):
        return ['NULL']

    @property
    def multioption(self):
        return self.config.get('multi', False)

    def setvalue(self, value):
        def set_button(setvalue):
            for button in self.group.buttons():
                buttonvalue = button.property("value")
                if (setvalue is None and buttonvalue in self.nullvalues) or buttonvalue == str(setvalue):
                    button.setChecked(True)
                    self.emitvaluechanged()
                    return

        if value in self.nullvalues:
            value = None

        if self.multioption and value:
            values = value.split(';')
        else:
            values = [value]

        for value in values:
            set_button(value)

    def value(self):
        def _returnvalue():
            if self.multioption:
                _values = []
                checked = [button for button in self.group.buttons() if button.isChecked()]
                for button in checked:
                    value = button.property("value")
                    _values.append(value)
                if not _values:
                    return None
                return ";".join(_values)
            else:
                checked = self.group.checkedButton()
                if not checked:
                    return None

                value = checked.property("value")
                return value

        returnvalue = _returnvalue()

        if returnvalue in self.nullvalues:
            returnvalue = None

        return returnvalue

    def reset(self):
        for button in self.group.buttons():
            if button.isChecked():
                button.setChecked(False)
                self.emitvaluechanged()
        return

    def togglebutton(self, value):
        for button in self.group.buttons():
            if button.property("value") == value:
                button.setChecked(not button.isChecked())
                self.emitvaluechanged()
                return
        return