예제 #1
0
class ChooseBlogDialog(QDialog, Ui_ChooseBlogDialog):
    def __init__(self, available_blogs, addToDB):
        QDialog.__init__(self)
        Ui_ChooseBlogDialog.__init__(self)
        self.func = addToDB
        self.setupUi(self)
        radioboxLayout = QVBoxLayout()
        self.radiobuttonGroup = QButtonGroup()
        self.radios = []
        for blog in available_blogs:
            radio = BlogRadio("Blog Title: %s,   Url: %s" %(blog.blogname, blog.homeurl), blog)
            self.radiobuttonGroup.addButton(radio)
            radioboxLayout.addWidget(radio)
            self.radios.append(radio)
        self.chooseBlogFrame.setLayout(radioboxLayout)
        self.adjustSize()
        connect(self.chooseBlogButtonBox, SIGNAL("accepted()"), self.addBlog) #AddBlogDialog.accept)
        connect(self.chooseBlogButtonBox, SIGNAL("rejected()"), self.reject)#AddBlogDialog.reject)

    def addBlog(self):
        if self.radiobuttonGroup.checkedButton():
            self.func(self.radiobuttonGroup.checkedButton().blog)
            self.accept()
        else:
            QMessageBox.warning(self, "Choose A Blog", "Please choose a blog and click OK.  If you do not want to add a blog, Please click 'Cancel'", QMessageBox.Ok, QMessageBox.Ok)
        pass
예제 #2
0
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 AutoFieldsDockWidget( QDockWidget, Ui_AutoFieldsDockWidget ):
    """ Class in charge of all the UI logic """

    def __init__( self, parent, iface, autoFieldManager, messageManager, language='en' ):
        self.iface = iface
        self.msg = messageManager
        self.language = language
        QDockWidget.__init__( self, parent )
        # Set up the user interface from Designer.
        self.setupUi( self )

        self.autoFieldManager = autoFieldManager
        self.geometryDict = ['points','lines','polygons']
        self.fieldTypesDict = ['Integer','Real','String','Date']

        self.root = QgsProject.instance().layerTreeRoot()

        # UI stuff that wasn't set/initialized in Qt-Designer
        self.tblLayers.setColumnWidth( 0, 24 )
        self.tblLayers.setColumnWidth( 1, 140 )
        self.tblLayers.setColumnWidth( 2, 110 )
        self.tblLayers.horizontalHeader().setResizeMode( 0, QHeaderView.Fixed )
        self.tblLayers.sortItems(1, Qt.AscendingOrder)
        self.cboField.setEnabled( False )
        self.cboFieldType.setItemData( 0, QVariant.Int, Qt.UserRole )
        self.cboFieldType.setItemData( 1, QVariant.Double, Qt.UserRole )
        self.cboFieldType.setItemData( 2, QVariant.String, Qt.UserRole )
        self.cboFieldType.setItemData( 3, QVariant.Date, Qt.UserRole )
        self.fieldTypeChanged( self.cboFieldType.currentIndex() ) # Update length/precision controls
        self.btnGroup = QButtonGroup()
        self.btnGroup.addButton( self.optXCoord )
        self.btnGroup.addButton( self.optYCoord )
        self.btnGroup.addButton( self.optLength )
        self.btnGroup.addButton( self.optPerimeter )
        self.btnGroup.addButton( self.optArea )
        self.btnGroup.addButton( self.optDate )
        self.btnGroup.addButton( self.optCustomExpression )
        #self.btnGroup.addButton( self.optSpatialValue )
        self.updateExpressionControls( self.optCustomExpression )

        self.frameFields.setEnabled( False )
        self.frameExpression.setEnabled( False )
        self.populateLayersTable()

        QgsMapLayerRegistry.instance().legendLayersAdded.connect( self.populateLayersTable )
        QgsMapLayerRegistry.instance().layersRemoved.connect( self.populateLayersTable )
        # Also listen to Layer Tree node position changes
        self.root.addedChildren.connect( self.populateLayersTable )
        self.root.removedChildren.connect( self.populateLayersTable )

        self.tblLayers.itemSelectionChanged.connect( self.updateFieldAndExpressionControls )
        self.optNewField.toggled.connect( self.newFieldToggled )
        self.cboField.currentIndexChanged.connect( self.fieldChanged )
        self.cboFieldType.currentIndexChanged.connect( self.fieldTypeChanged )
        self.btnSaveAutoField.clicked.connect( self.saveAutoField )
        self.btnNewCustomExpression.clicked.connect( self.setCustomExpression )
        self.btnGroup.buttonClicked.connect( self.updateExpressionControls )

        self.expressionDlg = None

        # 'List of AutoFields' Tab
        settings = QSettings()
        check = settings.value(
            self.autoFieldManager.settingsPrefix + "/showOnlyEnabledAutoFields",
            True, type=bool )
        self.chkOnlyEnabledAutoFields.setChecked( check )
        check = settings.value(
            self.autoFieldManager.settingsPrefix + "/calculateOnExistingFeatures",
            True, type=bool )
        self.chkCalculateOnExisting.setChecked( check )
        self.btnRemoveAutoFields.setEnabled( False )
        self.tblAutoFields.sortItems(0, Qt.AscendingOrder)
        self.populateAutoFieldsTable()
        self.autoFieldManager.autoFieldCreated.connect( self.populateAutoFieldsTable )
        self.autoFieldManager.autoFieldRemoved.connect( self.populateAutoFieldsTable )
        self.autoFieldManager.autoFieldEnabled.connect( self.populateAutoFieldsTable )
        self.autoFieldManager.autoFieldDisabled.connect( self.populateAutoFieldsTable )
        self.tblAutoFields.itemSelectionChanged.connect( self.updateRemoveAutoFieldButton )
        self.chkOnlyEnabledAutoFields.toggled.connect( self.saveShowOnlyEnabledPreference )
        self.chkCalculateOnExisting.toggled.connect( self.saveCalculateOnExistingPreference )
        self.btnRemoveAutoFields.clicked.connect( self.removeAutoFieldFromTable )

        # Context menu
        self.tblAutoFields.setContextMenuPolicy( Qt.CustomContextMenu )
        self.tblAutoFields.customContextMenuRequested.connect( self.openAutoFieldContextMenu )

        # About Tab
        self.btnHelp.clicked.connect( self.openDocumentation )


    def populateLayersTable( self, foo=None, foo2=None, foo3=None ):
        """ List vector layers that support changes in attributes and are writable.
            Arguments are 3 and optional because this function listens to several
            SIGNALs.
        """

        # Initialize Layers Table
        self.tblLayers.clearContents()
        self.tblLayers.setRowCount( 0 )

        vLayers = []
        for layer in QgsMapLayerRegistry.instance().mapLayers().values():
            if layer.type() == QgsMapLayer.VectorLayer:
                if layer.dataProvider().capabilities() & QgsVectorDataProvider.ChangeAttributeValues:
                    if not layer.isReadOnly():
                        if layer.geometryType() < 3: # Avoid UnknownGeometry and NoGeometry
                            vLayers.append( layer )

        self.tblLayers.setRowCount( len( vLayers ) )
        self.tblLayers.setColumnCount( 3 )

        self.tblLayers.setSortingEnabled( False )
        for row, lyr in enumerate( vLayers ):
            item = QTableWidgetItem( QIcon( ":/plugins/AutoFields/icons/" + \
                self.geometryDict[lyr.geometryType()] + ".png"),
                str( lyr.geometryType() ) )
            self.tblLayers.setItem( row, 0, item )

            item = QTableWidgetItem( lyr.name() )
            item.setData( Qt.UserRole, lyr.id() )
            self.tblLayers.setItem( row, 1, item )

            tmpTreeLayer = self.root.findLayer( lyr.id() )
            if tmpTreeLayer:
                group = tmpTreeLayer.parent().name()
                self.tblLayers.setItem(row, 2,
                    QTableWidgetItem( group if group else QApplication.translate("AutoFieldsDockWidgetPy",
                        "< root >" ) ) )

        self.tblLayers.setSortingEnabled( True )


    def updateFieldAndExpressionControls( self ):
        """ After a selection is changed, reflect possible values in field controls """
        self.msg.show( "New selection " + str(len( self.tblLayers.selectedItems() ) / 3), 'info', True )

        if not self.tblLayers.selectedItems():
            self.frameFields.setEnabled( False )
            self.frameExpression.setEnabled( False )
            return
        else:
            self.frameFields.setEnabled( True )
            self.frameExpression.setEnabled( True )

        # List common fields in cboField and get geometries selected
        geometryTypeSet = self.updateFieldList()


        # Update expression controls
        if 0 in geometryTypeSet and len( geometryTypeSet ) == 1: # Points
            self.optXCoord.setEnabled( True )
            self.optYCoord.setEnabled( True )
            self.optLength.setEnabled( False )
            self.optPerimeter.setEnabled( False )
            self.optArea.setEnabled( False )
        elif 1 in geometryTypeSet and len( geometryTypeSet ) == 1: # Lines
            self.optXCoord.setEnabled( False )
            self.optYCoord.setEnabled( False )
            self.optLength.setEnabled( True )
            self.optPerimeter.setEnabled( False )
            self.optArea.setEnabled( False )
        elif 2 in geometryTypeSet and len( geometryTypeSet ) == 1: # Polygons
            self.optXCoord.setEnabled( False )
            self.optYCoord.setEnabled( False )
            self.optLength.setEnabled( False )
            self.optPerimeter.setEnabled( True )
            self.optArea.setEnabled( True )
        else:
            self.optXCoord.setEnabled( False )
            self.optYCoord.setEnabled( False )
            self.optLength.setEnabled( False )
            self.optPerimeter.setEnabled( False )
            self.optArea.setEnabled( False )

        if not self.btnGroup.checkedButton().isEnabled():
            self.optCustomExpression.setChecked( True ) # Default selection
            self.updateExpressionControls( self.optCustomExpression )

        self.expressionDlg = None # Initialize the dialog


    def updateFieldList( self ):
        """ Update field list and return geometries selected """
        commonFields = []
        geometryTypeSet = set()
        bFirstFlag = True
        for item in self.tblLayers.selectedItems():
            if item.column() == 1: # It's the layer name item
                self.msg.show( "ID " + item.data( Qt.UserRole ), 'info', True ) # Get layer id
                layer = QgsMapLayerRegistry.instance().mapLayer( item.data( Qt.UserRole ) )
                geometryTypeSet.add( layer.geometryType() )
                tmpFields = [field.name() for field in layer.dataProvider().fields()] # Get field names stored in the provider
                if bFirstFlag: # Initialize commonFields
                    commonFields = tmpFields
                    bFirstFlag = False
                else: # Intersect fields
                    if commonFields: # Avoid intersecting if no common fields
                        commonFields = list( set( commonFields ) & set( tmpFields ) )

        commonFields.sort()
        self.msg.show( "FIELDS: "+ str(commonFields), 'info', True)

        self.cboField.clear()
        if not commonFields:
            self.optExistingField.setEnabled( False )
            self.optNewField.setChecked( True )
        else:
            self.optExistingField.setEnabled( True )
            self.cboField.addItems( commonFields )

        return geometryTypeSet


    def newFieldToggled( self ):
        """ Alternate between controls of new field and existing field """
        newIsChecked = self.optNewField.isChecked()

        self.cboField.setEnabled( not newIsChecked )

        self.lblFieldName.setEnabled( newIsChecked )
        self.lblFieldType.setEnabled( newIsChecked )
        self.txtFieldName.setEnabled( newIsChecked )
        self.cboFieldType.setEnabled( newIsChecked )

        if newIsChecked:
            self.fieldTypeChanged( self.cboFieldType.currentIndex() )
        else:
            self.lblFieldLength.setEnabled( newIsChecked )
            self.lblFieldPrecision.setEnabled( newIsChecked )
            self.txtFieldLength.setEnabled( newIsChecked )
            self.txtFieldPrecision.setEnabled( newIsChecked )

        self.expressionDlg = None # Initialize the dialog


    def fieldTypeChanged( self, idx ):
        """ Update field length and field precision controls' state and values """
        text = self.fieldTypesDict[idx]
        if text == 'Integer':
            self.txtFieldLength.setRange( 1, 10 )
            self.txtFieldLength.setEnabled( True )
            self.txtFieldPrecision.setEnabled( False )
            self.lblFieldLength.setEnabled( True )
            self.lblFieldPrecision.setEnabled( False )
        elif text == 'Real':
            self.txtFieldLength.setRange( 1, 20 )
            self.txtFieldPrecision.setRange( 0, 15 )
            self.txtFieldLength.setEnabled( True )
            self.txtFieldPrecision.setEnabled( True )
            self.lblFieldLength.setEnabled( True )
            self.lblFieldPrecision.setEnabled( True )
        elif text == 'String':
            self.txtFieldLength.setRange( 1, 255 )
            self.txtFieldLength.setEnabled( True )
            self.txtFieldPrecision.setEnabled( False )
            self.lblFieldLength.setEnabled( True )
            self.lblFieldPrecision.setEnabled( False )
        else: # Date
            self.txtFieldLength.setEnabled( False )
            self.txtFieldPrecision.setEnabled( False )
            self.lblFieldLength.setEnabled( False )
            self.lblFieldPrecision.setEnabled( False )


    def fieldChanged( self, idx ):
        """ Just to initialize the expression dialog if selected field changes """
        self.expressionDlg = None # Initialize the dialog


    def saveAutoField( self ):
        """ Do some validation and then call AutoFieldManager """

        # Check layers
        if not self.tblLayers.selectedItems():
            self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy",
                "[Warning] Please first select a layer." ), 'warning' )
            return

        # Check expression
        expression = u''
        if self.optXCoord.isChecked():
            expression = u'$x'
        elif self.optYCoord.isChecked():
            expression = u'$y'
        elif self.optLength.isChecked():
            expression = u'$length'
        elif self.optPerimeter.isChecked():
            expression = u'$perimeter'
        elif self.optArea.isChecked():
            expression = u'$area'
        elif self.optDate.isChecked():
            expression = u'now()'
        elif self.optCustomExpression.isChecked():
            if self.expressionDlg:
                expression = self.expressionDlg.expression
            if not self.expressionDlg or not expression:
                self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy",
                    "[Warning] Please first set a valid custom expression." ),
                    'warning' )
                return
        else: # optSpatialValue
            pass

        # Check fields
        fieldName = ''
        if self.optNewField.isChecked():
            if self.txtFieldName.text():

                fieldName = self.txtFieldName.text().strip()
                newField = QgsField( fieldName,
                    self.cboFieldType.itemData( self.cboFieldType.currentIndex(), Qt.UserRole) )

                length = self.txtFieldLength.value()
                precision = self.txtFieldPrecision.value()
                # Ensure length and precision are valid values when dealing with Real numbers
                if self.fieldTypesDict[self.cboFieldType.currentIndex()] == 'Real':
                    if precision > length:
                        precision = length
                newField.setLength( length )
                newField.setPrecision( precision )

                for item in self.tblLayers.selectedItems():
                    if item.column() == 1: # It's the layer name item
                        layer = QgsMapLayerRegistry.instance().mapLayer( item.data( Qt.UserRole ) )
                        if layer.fieldNameIndex( fieldName ) != -1:
                            self.msg.show(
                                QApplication.translate( "AutoFieldsDockWidgetPy",
                                    "[Error] The field " ) + fieldName + \
                                QApplication.translate( "AutoFieldsDockWidgetPy",
                                    " already exists in layer " ) + layer.name() + ". " + \
                                QApplication.translate( "AutoFieldsDockWidgetPy",
                                    " If you want to create an AutoField on it, you need to choose it from 'Existing Field' list." ),
                                'warning' )
                        else:
                            res = layer.dataProvider().addAttributes( [ newField ] )
                            if res:
                                layer.updateFields()

                                # Check if fieldName is preserved by the provider after field creation.
                                if layer.fieldNameIndex( fieldName ) == -1:
                                    self.msg.show(
                                        QApplication.translate( "AutoFieldsDockWidgetPy",
                                            "[Error] The field " ) + fieldName + \
                                        QApplication.translate( "AutoFieldsDockWidgetPy",
                                            " was probably created with another name by the layer (" ) + \
                                        layer.name() + \
                                        QApplication.translate( "AutoFieldsDockWidgetPy",
                                            ") provider. " ) + \
                                        QApplication.translate( "AutoFieldsDockWidgetPy",
                                            " If you want to create an AutoField on it, you need to choose it from 'Existing Field' list." ),
                                        'warning' )
                                else:

                                    self.doSaveAutoField( layer, fieldName, expression )

                            else:
                                self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy",
                                    "[Error] Couldn't create " ) + newField.name() + \
                                    QApplication.translate( "AutoFieldsDockWidgetPy",
                                        " field in " ) + layer.name() + \
                                    QApplication.translate( "AutoFieldsDockWidgetPy", " layer." ),
                                    'warning' )

                # Some fields might have been created, update the field list once
                self.updateFieldList()

            else:
                self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy",
                    "[Warning] Please first set a name for the new field." ), 'warning' )
                return
        else:
            fieldName = self.cboField.currentText()

            for item in self.tblLayers.selectedItems():
                if item.column() == 1: # It's the layer name item
                    layer = QgsMapLayerRegistry.instance().mapLayer( item.data( Qt.UserRole ) )
                    self.doSaveAutoField( layer, fieldName, expression )


    def doSaveAutoField( self, layer, fieldName, expression ):
        """ Repetitive logic to save or overwrite an AutoField """
        # Check if the field is an AutoField and ask if we should overwrite it
        res = True
        bCalculateOnExisting = self.chkCalculateOnExisting.isChecked()
        if self.autoFieldManager.isFieldAnAutoField( layer, fieldName ):
            reply = QMessageBox.question( self.iface.mainWindow(),
                QApplication.translate( "AutoFieldsDockWidgetPy", "Confirmation" ),
                QApplication.translate( "AutoFieldsDockWidgetPy", "The field '" ) + \
                fieldName + QApplication.translate( "AutoFieldsDockWidgetPy",
                    "' from layer '" ) + layer.name() + \
                QApplication.translate( "AutoFieldsDockWidgetPy",
                    "' is already an AutoField.\nDo you want to overwrite it?" ),
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No )

            if reply == QMessageBox.Yes:
                res = self.autoFieldManager.overwriteAutoField( layer, fieldName, expression, calculateOnExisting=bCalculateOnExisting )

        else:
            res = self.autoFieldManager.createAutoField( layer, fieldName, expression, calculateOnExisting=bCalculateOnExisting )

        if not res:
            # res will only be False if create/overwriteAutoField return False
            self.msg.show( "[Error] The AutoField for layer '" + layer.name() + \
                "' and field '" + fieldName + "' couldn't be created.", 'warning', True )


    def setCustomExpression( self ):
        """ Initialize and show the expression builder dialog """
        layer = None
        if len( self.tblLayers.selectedItems() ) / 3 == 1: # Single layer selected?
            for item in self.tblLayers.selectedItems():
                if item.column() == 1: # It's the layer name item
                    layer = QgsMapLayerRegistry.instance().mapLayer( item.data( Qt.UserRole ) )

        if not self.expressionDlg:
            self.expressionDlg = ExpressionBuilderDialog( self.iface.mainWindow() )
            context = QgsExpressionContext()
            context.appendScope( QgsExpressionContextUtils.globalScope() )
            context.appendScope( QgsExpressionContextUtils.projectScope() )

            # Initialize dialog with layer-based names and variables if single layer selected
            if len( self.tblLayers.selectedItems() ) / 3 == 1:
                context.appendScope( QgsExpressionContextUtils.layerScope( layer ) )
                self.expressionDlg.expressionBuilderWidget.setLayer( layer )
                self.expressionDlg.expressionBuilderWidget.loadFieldNames()

                # This block was borrowed from QGIS/python/plugins/processing/algs/qgis/FieldsCalculator.py
                da = QgsDistanceArea()
                da.setSourceCrs( layer.crs().srsid() )
                da.setEllipsoidalMode( self.iface.mapCanvas().mapSettings().hasCrsTransformEnabled() )
                da.setEllipsoid( QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE )[0] )
                self.expressionDlg.expressionBuilderWidget.setGeomCalculator( da )

                # If this layer-field is an AutoField, get its expression
                if self.optExistingField.isChecked():
                    fieldName = self.cboField.currentText()
                    expression = self.autoFieldManager.getFieldExpression( layer, fieldName )
                    self.expressionDlg.expressionBuilderWidget.setExpressionText( expression )
                    self.expressionDlg.expression = expression # To remember it when closing/opening

            self.expressionDlg.expressionBuilderWidget.setExpressionContext( context )

        self.expressionDlg.show()


    def updateExpressionControls( self, button ):
        """ Enable/disable push buttons when appropriate """
        if button.objectName() == 'optCustomExpression':
            self.btnNewCustomExpression.setEnabled( True )
            #self.btnNewSpatialValue.setEnabled( False )
        #elif button.objectName() == 'optSpatialValue':
            #self.btnNewCustomExpression.setEnabled( False )
            #self.btnNewSpatialValue.setEnabled( True )
        else:
            self.btnNewCustomExpression.setEnabled( False )
            #self.btnNewSpatialValue.setEnabled( False )


    def populateAutoFieldsTable( self, autoFieldId=None ):
        """ Listens to any modification on AutoFields to update the list """
        dictAutoFields = self.autoFieldManager.listAutoFields()
        if autoFieldId: # Just update this one
            if not autoFieldId in dictAutoFields: # AutoField removed
                self.msg.show( "[Info] Removing AutoField from table.", 'info', True )
                # Iterate through AF rows and remove row where data matches AFID
                deleteRow = self.findRowOfItemDataInAutoFieldsTable( autoFieldId, 0)
                if deleteRow != -1:
                    self.tblAutoFields.removeRow( deleteRow )
            else:
                # if it's in the table: remove it and re-add it (from new dict)
                deleteRow = self.findRowOfItemDataInAutoFieldsTable( autoFieldId, 0)
                if deleteRow != -1:
                    self.msg.show( "[Info] Refreshing AutoField status in table.", 'info', True )
                    self.tblAutoFields.removeRow( deleteRow )
                    self.addAutoFieldToAutoFieldsTable( autoFieldId, dictAutoFields[autoFieldId] )
                else: # New AutoField, just add it to table
                    self.msg.show( "[Info] Adding new AutoField to table.", 'info', True )
                    self.addAutoFieldToAutoFieldsTable( autoFieldId, dictAutoFields[autoFieldId] )
        else:
            # Initialize AutoFields Table
            self.tblAutoFields.clearContents()
            self.tblAutoFields.setRowCount( 0 )

            #self.tblAutoFields.setRowCount( len( dictAutoFields ) )
            self.tblAutoFields.setColumnCount( 4 )

            self.tblAutoFields.setSortingEnabled( False )
            for key in dictAutoFields.keys():
                autoField = dictAutoFields[key]
                self.addAutoFieldToAutoFieldsTable( key, autoField, False )

            self.tblAutoFields.setSortingEnabled( True )


    def findRowOfItemDataInAutoFieldsTable( self, data, col ):
        """ Get the row number that matches its data to a given data (check only the given column) """
        for numRow in range( self.tblAutoFields.rowCount() ):
            item = self.tblAutoFields.item( numRow, col )
            if item.data( Qt.UserRole ) == data:
                return numRow
        return -1


    def addAutoFieldToAutoFieldsTable( self, autoFieldId, autoField, freezeSorting=True ):
        """ Add a whole row to the AutoFields table """
        if self.chkOnlyEnabledAutoFields.isChecked() and not autoField['enabled']:
            return

        if freezeSorting:
            self.tblAutoFields.setSortingEnabled( False )

        row = self.tblAutoFields.rowCount()
        self.tblAutoFields.insertRow( row )
        name = autoField['layer']
        if 'layerId' in autoField:
            lyr = QgsMapLayerRegistry.instance().mapLayer( autoField['layerId'] )
            name = lyr.name()
        item = QTableWidgetItem( name )
        item.setData( Qt.UserRole, autoFieldId )
        item.setData( Qt.ToolTipRole, autoField['layer'] )
        if not autoField['enabled']:
            item.setForeground( QBrush( Qt.gray ) )
        self.tblAutoFields.setItem( row, 0, item )
        item = QTableWidgetItem( autoField['field'] )
        if not autoField['enabled']:
            item.setForeground( QBrush( Qt.gray ) )
        self.tblAutoFields.setItem( row, 1, item )
        item = QTableWidgetItem( autoField['expression'] )
        if not autoField['enabled']:
            item.setForeground( QBrush( Qt.gray ) )
        self.tblAutoFields.setItem( row, 2, item )
        item = QTableWidgetItem( QApplication.translate( "AutoFieldsDockWidgetPy",
            "Enabled" ) if autoField['enabled'] else QApplication.translate( "AutoFieldsDockWidgetPy", "Disabled" ) )
        item.setData( Qt.UserRole, 'enabled' if autoField['enabled'] else 'disabled' )
        if not autoField['enabled']:
            item.setForeground( QBrush( Qt.gray ) )
        self.tblAutoFields.setItem( row, 3, item )

        if freezeSorting:
            self.tblAutoFields.setSortingEnabled( True )


    def openAutoFieldContextMenu( self, position ):
        bLayers = False
        layers = QgsMapLayerRegistry.instance().mapLayers().values()
        for layer in layers:
            if layer.type() == QgsMapLayer.VectorLayer:
                if layer.dataProvider().capabilities() & QgsVectorDataProvider.AddFeatures:
                    bLayers = True
                    break

        item = self.tblAutoFields.itemAt( position )
        if item:
            row = item.row()
            self.menu = QMenu()
            self.action = QAction( "Assign this AutoField to another layer", None )
            self.action.setObjectName('action')
            if self.tblAutoFields.item( row, 3 ).data( Qt.UserRole ) == 'enabled':
                self.action.setEnabled( False )
            self.menu.addAction( self.action )
            action = self.menu.exec_(self.tblAutoFields.mapToGlobal(position))
            if action and action.objectName() == 'action':
                if not bLayers:
                    self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy",
                        "First load some vector layers to QGIS to be able to assign disabled AutoFields." ), 'warning' )
                    return

                autoFieldId = self.tblAutoFields.item( row, 0 ).data( Qt.UserRole )
                bCalculateOnExisting = self.chkCalculateOnExisting.isChecked()
                dlg = AssignAutoFieldToLayerDialog( self.iface.mainWindow(), self.autoFieldManager, autoFieldId, bCalculateOnExisting )
                dlg.show()


    def updateRemoveAutoFieldButton( self ):
        """ Enable/disable button to remove AutoFields when appropriate """
        self.btnRemoveAutoFields.setEnabled( len( self.tblAutoFields.selectedItems() ) / 4 )


    def removeAutoFieldFromTable( self ):
        """ Show a confirmation dialog for all AutoFields selected.
            If confirmed, remove AutoFields from table.
        """
        # Column 0 has the AutoField id
        autoFieldsToRemove = [ item.data( Qt.UserRole ) for item in self.tblAutoFields.selectedItems() if item.column() == 0 ]

        reply = QMessageBox.question( self.iface.mainWindow(),
            QApplication.translate( "AutoFieldsDockWidgetPy", "Confirmation" ),
            QApplication.translate( "AutoFieldsDockWidgetPy",
                "Do you really want to remove " ) + \
            str(len( autoFieldsToRemove )) + \
            (" AutoFields?" if len( autoFieldsToRemove ) > 1 else " AutoField?"),
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No )

        if reply == QMessageBox.Yes:
            for autoFieldId in autoFieldsToRemove:
                self.autoFieldManager.removeAutoField( autoFieldId )


    def saveShowOnlyEnabledPreference( self, status ):
        """ Saves the preference in QSettings and updates list of AutoFields """
        settings = QSettings()
        settings.setValue( self.autoFieldManager.settingsPrefix + "/showOnlyEnabledAutoFields" , status )
        self.populateAutoFieldsTable()


    def saveCalculateOnExistingPreference( self, status ):
        """ Saves the preference in QSettings """
        settings = QSettings()
        settings.setValue( self.autoFieldManager.settingsPrefix + "/calculateOnExistingFeatures" , status )


    def openDocumentation( self ):
        """ Open a browser to show documentation page """
        import webbrowser
        webbrowser.open( "http://geotux.tuxfamily.org/index.php/"+ self.language +"/geo-blogs/item/333-autofields-plugin-for-qgis" )


    def disconnectAll( self ):
        """ Terminates all SIGNAL/SLOT connections created by this class """
        QgsMapLayerRegistry.instance().legendLayersAdded.disconnect( self.populateLayersTable )
        QgsMapLayerRegistry.instance().layersRemoved.disconnect( self.populateLayersTable )
        self.root.addedChildren.disconnect( self.populateLayersTable )
        self.root.removedChildren.disconnect( self.populateLayersTable )

        self.tblLayers.itemSelectionChanged.disconnect( self.updateFieldAndExpressionControls )
        self.optNewField.toggled.disconnect( self.newFieldToggled )
        self.cboField.currentIndexChanged.disconnect( self.fieldChanged )
        self.cboFieldType.currentIndexChanged.disconnect( self.fieldTypeChanged )
        self.btnSaveAutoField.clicked.disconnect( self.saveAutoField )
        self.btnNewCustomExpression.clicked.disconnect( self.setCustomExpression )
        self.btnGroup.buttonClicked.disconnect( self.updateExpressionControls )

        self.autoFieldManager.autoFieldCreated.disconnect( self.populateAutoFieldsTable )
        self.autoFieldManager.autoFieldRemoved.disconnect( self.populateAutoFieldsTable )
        self.autoFieldManager.autoFieldEnabled.disconnect( self.populateAutoFieldsTable )
        self.autoFieldManager.autoFieldDisabled.disconnect( self.populateAutoFieldsTable )
        self.tblAutoFields.itemSelectionChanged.disconnect( self.updateRemoveAutoFieldButton )
        self.chkOnlyEnabledAutoFields.toggled.disconnect( self.saveShowOnlyEnabledPreference )
        self.btnRemoveAutoFields.clicked.disconnect( self.removeAutoFieldFromTable )
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)
예제 #5
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 xrange(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.
                        print showcolor
                        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
예제 #6
0
class OptionWidget(EditorWidget):
    widgettype = 'Option Row'

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

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

    def _buildfromlist(self, listconfig):
        items = listconfig['items']
        for item in items:
            parts = item.split(';')
            data = parts[0]
            try:
                desc = parts[1]
            except IndexError:
                desc = data

            button = QPushButton()

            icon = QIcon()
            try:
                path = parts[2]
                if path.startswith("#"):
                    # Colour the button with the hex value
                    style = """
                        QPushButton:checked  {{
                            border: 3px solid rgb(137, 175, 255);
                        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))
            self.widget.layout().addWidget(button)
            self.group.addButton(button)

    def initWidget(self, widget):
        if not widget.layout():
            widget.setLayout(QHBoxLayout())
            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']
        self._buildfromlist(listconfig)

        super(OptionWidget, self).endupdatefromconfig()

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

        return False

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

    def setvalue(self, value):
        if value in self.nullvalues:
            value = None

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

    def value(self):
        button = self.group.checkedButton()
        if not button:
            return None

        value = button.property("value")

        if value in self.nullvalues:
            value = None
        return value
예제 #7
0
class ItemWidget(QWidget):
    """
	@brief Auflistung der Gegenstände.

	\todo Drag&Drop wäre auch nicht schlecht.

	\todo Momentan finde ich die Waffenkategorie über die Hintergrundfarbe heraus. Das ist nicht wirklich gut.
	"""
    def __init__(self, template, character, parent=None):
        super(ItemWidget, self).__init__(parent)

        self.ui = Ui_ItemWidget()
        self.ui.setupUi(self)

        self.__character = character
        self.__storage = template

        ## Weapons
        weaponStore = AbstractStoreWidget(template, character)
        weaponStore.setEnhancedItemTraitsVisible(True)
        weaponStore.setMagicalItemTraitsVisible(False)
        weaponStore.setAddCustomVisible(False)
        self.ui.layout_weapons.addWidget(weaponStore)

        for category in self.__storage.weapons:
            for weapon in self.__storage.weapons[category]:
                weaponStore.addItemToStore(
                    weapon, category, QIcon(Config.ICONS_WEAPONS[category]))

        weaponStore.itemBought.connect(self.__character.addWeapon)
        weaponStore.itemSold.connect(self.__character.deleteWeapon)
        self.__character.weaponAdded.connect(weaponStore.moveItemToInventory)
        self.__character.weaponRemoved.connect(weaponStore.moveItemToStore)

        ## Equipment
        equipmentStore = AbstractStoreWidget(template, character)
        equipmentStore.setEnhancedItemTraitsVisible(False)
        equipmentStore.setMagicalItemTraitsVisible(False)
        equipmentStore.setAddCustomVisible(True)
        self.ui.layout_equipment.addWidget(equipmentStore)

        for equipment in self.__storage.equipment:
            equipmentStore.addItemToStore(equipment)

        equipmentStore.itemBought.connect(self.__character.addEquipment)
        equipmentStore.itemSold.connect(self.__character.deleteEquipment)
        self.__character.equipmentAdded.connect(
            equipmentStore.moveItemToInventory)
        self.__character.equipmentRemoved.connect(
            equipmentStore.moveItemToStore)

        ## Automobiles
        automobileStore = AbstractStoreWidget(template, character)
        automobileStore.setEnhancedItemTraitsVisible(False)
        automobileStore.setMagicalItemTraitsVisible(False)
        automobileStore.setAddCustomVisible(False)
        self.ui.layout_automobiles.addWidget(automobileStore)

        for category in self.__storage.automobiles:
            for automobile in self.__storage.automobiles[category]:
                automobileStore.addItemToStore(
                    automobile, category,
                    QIcon(Config.ICONS_AUTOMOBILES[category]))

        automobileStore.itemBought.connect(self.__character.addAutomobile)
        automobileStore.itemSold.connect(self.__character.deleteAutomobile)
        self.__character.automobileAdded.connect(
            automobileStore.moveItemToInventory)
        self.__character.automobileRemoved.connect(
            automobileStore.moveItemToStore)

        ## ExtraordinaryItems
        extraordinaryItemStore = AbstractStoreWidget(template, character)
        extraordinaryItemStore.setEnhancedItemTraitsVisible(False)
        extraordinaryItemStore.setMagicalItemTraitsVisible(True)
        extraordinaryItemStore.setAddCustomVisible(False)
        self.ui.layout_extraordinaryItems.addWidget(extraordinaryItemStore)

        for category in self.__storage.extraordinaryItems:
            for extraordinaryItem in self.__storage.extraordinaryItems[
                    category]:
                extraordinaryItemStore.addItemToStore(
                    extraordinaryItem, category,
                    QIcon(Config.ICONS_ITEMS_EXTRAORDINARY[category]))

        extraordinaryItemStore.itemBought.connect(
            self.__character.addExtraordinaryItem)
        extraordinaryItemStore.itemSold.connect(
            self.__character.deleteExtraordinaryItem)
        self.__character.extraordinaryItemAdded.connect(
            extraordinaryItemStore.moveItemToInventory)
        self.__character.extraordinaryItemRemoved.connect(
            extraordinaryItemStore.moveItemToStore)

        ## \todo Sollte nicht vom Betriebssystem, sondern vom verwendeten Style abhängen.
        self.ui.tabWidget_items.setObjectName("transparentWidget")
        if os.name == "nt":
            self.ui.tabWidget_items.setStyleSheet(
                "QWidget#transparentWidget { background: transparent; }")

        self.ui.tabWidget_items.setCurrentIndex(0)

        ## Resources
        self.ui.traitDots_armorResources.valueChanged.connect(
            self.__character.traits["Merit"]["Social"]["Resources"].setValue)
        #self.ui.traitDots_equipmentResources.valueChanged.connect(self.__character.traits["Merit"]["Social"]["Resources"].setValue)
        self.__character.traits["Merit"]["Social"][
            "Resources"].valueChanged.connect(
                self.ui.traitDots_armorResources.setValue)
        #self.__character.traits["Merit"]["Social"]["Resources"].valueChanged.connect(self.ui.traitDots_equipmentResources.setValue)
        self.ui.traitDots_armorEnhancedItem.valueChanged.connect(
            self.__character.traits["Merit"]["Item"]["Enhanced Item"].setValue)
        #self.ui.traitDots_equipmentEnhancedItem.valueChanged.connect(self.__character.traits["Merit"]["Item"]["Enhanced Item"].setValue)
        self.__character.traits["Merit"]["Item"][
            "Enhanced Item"].valueChanged.connect(
                self.ui.traitDots_armorEnhancedItem.setValue)
        #self.__character.traits["Merit"]["Item"]["Enhanced Item"].valueChanged.connect(self.ui.traitDots_equipmentEnhancedItem.setValue)

        ## Armor

        self.__noArmorText = "None"
        self.__buttonArmorDict = {}
        self.__buttonGroup_armor = QButtonGroup(self)
        ## Natürlich muß auch die Wahl bestehen, keine Rüstung zu tragen. Dies ist zu Anfang gewählt.
        radioButton = QRadioButton(self.__noArmorText)
        self.ui.layout_armor.addWidget(radioButton)
        self.__buttonGroup_armor.addButton(radioButton)
        radioButton.setChecked(True)
        self.__buttonArmorDict[radioButton.text()] = radioButton
        for armor in self.__storage.armor:
            radioButton = QRadioButton(armor)
            self.ui.layout_armor.addWidget(radioButton)
            self.__buttonGroup_armor.addButton(radioButton)
            self.__buttonArmorDict[radioButton.text()] = radioButton

        self.__buttonGroup_armor.buttonClicked.connect(self.takeArmor)
        self.ui.checkBox_armorDedicated.toggled.connect(self.takeArmor)

        self.__character.armorChanged.connect(self.selectArmor)
        self.__character.speciesChanged.connect(self.hideShowDedicated)

        ### Equipment

        #self.ui.pushButton_equipmentAdd.setIcon(QIcon(":/icons/images/actions/1leftarrow.png"))
        #self.ui.pushButton_equipmentRemove.setIcon(QIcon(":/icons/images/actions/1rightarrow.png"))

        #for item in self.__storage.equipment:
        #listItem = QListWidgetItem()
        #listItem.setText(item)
        ##listItem.setIcon(QIcon(Config.ICONS_WEAPONS[category]))
        ##listItem.setData(Qt.BackgroundRole, QColor(Config.weaponsColor[category]))
        #self.ui.listWidget_equipmentStore.addItem(listItem)

        #self.ui.pushButton_equipmentAdd.clicked.connect(self.addEquipment)
        #self.ui.listWidget_equipmentStore.itemDoubleClicked.connect(self.addEquipment)
        #self.ui.pushButton_equipmentRemove.clicked.connect(self.removeEquipment)
        #self.ui.listWidget_equipmentInventory.itemDoubleClicked.connect(self.removeEquipment)
        #self.ui.pushButton_equipmentAddCustom.clicked.connect(self.addCustomEquipment)
        #self.__character.equipmentChanged.connect(self.refillEquipmentInventory)
        #self.__character.equipmentChanged.connect(self.refillEquipmentStore)
        #self.__character.equipmentChanged.connect(self.checkButtonEnabledEquipment)

        ## Magical Tool
        self.__character.speciesChanged.connect(self.hideShowMagicalTool)
        self.ui.lineEdit_magicalTool.textEdited.connect(
            self.__character.setMagicalTool)
        self.__character.magicalToolChanged.connect(
            self.ui.lineEdit_magicalTool.setText)

    def takeArmor(self):
        """
		Speichert die gewählte Rüstung im Charakter-Speicher.
		"""

        armorName = self.__buttonGroup_armor.checkedButton().text()
        if armorName == self.__noArmorText:
            armorName = ""
        dedicated = False
        if self.ui.checkBox_armorDedicated.isChecked():
            dedicated = True
        self.__character.setArmor(armorName, dedicated=dedicated)

    def selectArmor(self, armor, dedicated):
        """
		Wählt den Knopf mit der Passenden Bezeichnung aus.
		"""

        armorName = armor
        if not armorName:
            armorName = self.__noArmorText

        if armorName in self.__buttonArmorDict:
            self.__buttonArmorDict[armorName].setChecked(True)
            if dedicated:
                self.ui.checkBox_armorDedicated.setChecked(True)
            else:
                self.ui.checkBox_armorDedicated.setChecked(False)

    def hideShowDedicated(self, species):
        """
		Nur bei Werwölfen macht es Sinn, eine Rüstung zuzueignen. Entsprechendes Widget wird für alle anderen Spezies versteckt.
		"""

        if species == "Werewolf":
            self.ui.checkBox_armorDedicated.setVisible(True)
        else:
            self.ui.checkBox_armorDedicated.setVisible(False)

    #def addCustomEquipment(self):
    #"""
    #Fügt dem Inventar des Charakters einen Gegenstand hinzu.

    #\todo Nach dem Drücken des Hinzufügen.Knopfes, sollte der Fokus wieder auf das LineEdit gehen.
    #"""

    #newItem = self.ui.lineEdit_equipmentCustom.text()
    #if newItem:
    #self.__character.addEquipment(newItem)
    ### Textzeile löschen
    #self.ui.lineEdit_equipmentCustom.setText("")

    #def addEquipment(self):
    #"""
    #Der Charakter erhält den in \ref listWidget_equipmentStore markierte Ausrüstungsgegenstand.
    #"""

    #item = self.ui.listWidget_equipmentStore.takeItem(self.ui.listWidget_equipmentStore.row(self.ui.listWidget_equipmentStore.currentItem()))
    #if item:
    #self.__character.addEquipment(item.text())

    #def removeEquipment(self):
    #"""
    #Entfernt einen Gegenstand aus dem Inventar des Charakters. Wenn er aus der Liste der vorgeschlagenen Ausrüsrtung stammt, wird er dort wieder hinzugefügt.
    #"""

    #if self.ui.listWidget_equipmentInventory.currentItem():
    #item = self.ui.listWidget_equipmentInventory.takeItem(self.ui.listWidget_equipmentInventory.row(self.ui.listWidget_equipmentInventory.currentItem()))
    #self.__character.delEquipment(item.text())

    #def refillEquipmentInventory(self, itemList):
    #"""
    #Schreibt alle Gegenstände aus dem Charakterspeicher in die Liste
    #"""

    #self.ui.listWidget_equipmentInventory.clear()
    #for item in itemList:
    #listItem = QListWidgetItem()
    #listItem.setText(item)
    ##listItem.setIcon(QIcon(Config.ICONS_WEAPONS[category]))
    ##listItem.setFlags(listItem.flags() | Qt.ItemIsEditable)
    #self.ui.listWidget_equipmentInventory.addItem(listItem)

    #def refillEquipmentStore(self, itemList):
    #"""
    #Löschte alle Gegenstände, die im Inventar des Charakters sind aus dem Laden.
    #"""

    #self.ui.listWidget_equipmentStore.clear()
    #for item in self.__storage.equipment:
    #if item not in itemList:
    #listItem = QListWidgetItem()
    #listItem.setText(item)
    #listItem = self.ui.listWidget_equipmentStore.addItem(listItem)

    #def checkButtonEnabledEquipment(self):
    #"""
    #Aktiviert/Deaktiviert die Knöpfe für das Übertragen von Ausrüstung.
    #"""

    #if self.ui.listWidget_equipmentStore.count() < 1:
    #self.ui.pushButton_equipmentAdd.setEnabled(False)
    #else:
    #self.ui.pushButton_equipmentAdd.setEnabled(True)

    def hideShowMagicalTool(self, species):
        """
		Nur bei Magiern wird ein Magische Werkzeug angeboten.
		"""

        if species == "Mage":
            self.ui.widget_magicalTool.setVisible(True)
        else:
            self.ui.widget_magicalTool.setVisible(False)
예제 #8
0
class OptionWidget(EditorWidget):
    widgettype = 'Option Row'
    def __init__(self, *args):
        super(OptionWidget, self).__init__(*args)
        self._bindvalue = None
        self.group = QButtonGroup()
        self.group.setExclusive(True)
        self.group.buttonClicked.connect(self.emitvaluechanged)

    def createWidget(self, parent):
        widget = QWidget(parent)
        widget.setLayout(QHBoxLayout())
        widget.layout().setContentsMargins(0,0,0,0)
        return widget

    def _buildfromlist(self, listconfig):
        items = listconfig['items']
        for item in items:
            parts = item.split(';')
            data = parts[0]
            try:
                desc = parts[1]
            except IndexError:
                desc = data

            try:
                path = parts[2]
                if path.endswith("_icon"):
                    icon = QIcon(":/icons/{}".format(path))
                else:
                    icon = QIcon(path)
            except:
                icon = QIcon()


            button = QPushButton()
            button.setCheckable(True)
            button.setText(desc)
            button.setProperty("value", data)
            button.setIcon(icon)
            button.setIconSize(QSize(24,24))
            self.widget.layout().addWidget(button)
            self.group.addButton(button)

    def initWidget(self, widget):
        pass

    def updatefromconfig(self):
        super(OptionWidget, self).updatefromconfig()
        listconfig = self.config['list']
        self._buildfromlist(listconfig)

        super(OptionWidget, self).endupdatefromconfig()

    def validate(self, *args):
        button = self.group.checkedButton()
        if button:
            self.raisevalidationupdate(True)
        else:
            self.raisevalidationupdate(False)
        self.emitvaluechanged()

    def setvalue(self, value):
        for button in self.group.buttons():
            if button.property("value") == value:
                button.setChecked(True)
                return

    def value(self):
        button = self.group.checkedButton()
        if not button:
            return None
        return button.property("value")
예제 #9
0
class AutoFieldsDockWidget(QDockWidget, Ui_AutoFieldsDockWidget):
    """ Class in charge of all the UI logic """
    def __init__(self,
                 parent,
                 iface,
                 autoFieldManager,
                 messageManager,
                 language='en'):
        self.iface = iface
        self.msg = messageManager
        self.language = language
        QDockWidget.__init__(self, parent)
        # Set up the user interface from Designer.
        self.setupUi(self)

        self.autoFieldManager = autoFieldManager
        self.geometryDict = ['points', 'lines', 'polygons']
        self.fieldTypesDict = ['Integer', 'Real', 'String', 'Date']

        self.root = QgsProject.instance().layerTreeRoot()

        # UI stuff that wasn't set/initialized in Qt-Designer
        self.tblLayers.setColumnWidth(0, 24)
        self.tblLayers.setColumnWidth(1, 140)
        self.tblLayers.setColumnWidth(2, 110)
        self.tblLayers.horizontalHeader().setResizeMode(0, QHeaderView.Fixed)
        self.tblLayers.sortItems(1, Qt.AscendingOrder)
        self.cboField.setEnabled(False)
        self.cboFieldType.setItemData(0, QVariant.Int, Qt.UserRole)
        self.cboFieldType.setItemData(1, QVariant.Double, Qt.UserRole)
        self.cboFieldType.setItemData(2, QVariant.String, Qt.UserRole)
        self.cboFieldType.setItemData(3, QVariant.Date, Qt.UserRole)
        self.fieldTypeChanged(self.cboFieldType.currentIndex()
                              )  # Update length/precision controls
        self.btnGroup = QButtonGroup()
        self.btnGroup.addButton(self.optXCoord)
        self.btnGroup.addButton(self.optYCoord)
        self.btnGroup.addButton(self.optLength)
        self.btnGroup.addButton(self.optPerimeter)
        self.btnGroup.addButton(self.optArea)
        self.btnGroup.addButton(self.optDate)
        self.btnGroup.addButton(self.optCustomExpression)
        #self.btnGroup.addButton( self.optSpatialValue )
        self.updateExpressionControls(self.optCustomExpression)

        self.frameFields.setEnabled(False)
        self.frameExpression.setEnabled(False)
        self.populateLayersTable()

        QgsMapLayerRegistry.instance().legendLayersAdded.connect(
            self.populateLayersTable)
        QgsMapLayerRegistry.instance().layersRemoved.connect(
            self.populateLayersTable)
        # Also listen to Layer Tree node position changes
        self.root.addedChildren.connect(self.populateLayersTable)
        self.root.removedChildren.connect(self.populateLayersTable)

        self.tblLayers.itemSelectionChanged.connect(
            self.updateFieldAndExpressionControls)
        self.optNewField.toggled.connect(self.newFieldToggled)
        self.cboField.currentIndexChanged.connect(self.fieldChanged)
        self.cboFieldType.currentIndexChanged.connect(self.fieldTypeChanged)
        self.btnSaveAutoField.clicked.connect(self.saveAutoField)
        self.btnNewCustomExpression.clicked.connect(self.setCustomExpression)
        self.btnGroup.buttonClicked.connect(self.updateExpressionControls)

        self.expressionDlg = None

        # 'List of AutoFields' Tab
        settings = QSettings()
        check = settings.value(self.autoFieldManager.settingsPrefix +
                               "/showOnlyEnabledAutoFields",
                               True,
                               type=bool)
        self.chkOnlyEnabledAutoFields.setChecked(check)
        check = settings.value(self.autoFieldManager.settingsPrefix +
                               "/calculateOnExistingFeatures",
                               True,
                               type=bool)
        self.chkCalculateOnExisting.setChecked(check)
        self.btnRemoveAutoFields.setEnabled(False)
        self.tblAutoFields.sortItems(0, Qt.AscendingOrder)
        self.populateAutoFieldsTable()
        self.autoFieldManager.autoFieldCreated.connect(
            self.populateAutoFieldsTable)
        self.autoFieldManager.autoFieldRemoved.connect(
            self.populateAutoFieldsTable)
        self.autoFieldManager.autoFieldEnabled.connect(
            self.populateAutoFieldsTable)
        self.autoFieldManager.autoFieldDisabled.connect(
            self.populateAutoFieldsTable)
        self.tblAutoFields.itemSelectionChanged.connect(
            self.updateRemoveAutoFieldButton)
        self.chkOnlyEnabledAutoFields.toggled.connect(
            self.saveShowOnlyEnabledPreference)
        self.chkCalculateOnExisting.toggled.connect(
            self.saveCalculateOnExistingPreference)
        self.btnRemoveAutoFields.clicked.connect(self.removeAutoFieldFromTable)

        # Context menu
        self.tblAutoFields.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tblAutoFields.customContextMenuRequested.connect(
            self.openAutoFieldContextMenu)

        # About Tab
        self.btnHelp.clicked.connect(self.openDocumentation)

    def populateLayersTable(self, foo=None, foo2=None, foo3=None):
        """ List vector layers that support changes in attributes and are writable.
            Arguments are 3 and optional because this function listens to several
            SIGNALs.
        """

        # Initialize Layers Table
        self.tblLayers.clearContents()
        self.tblLayers.setRowCount(0)

        vLayers = []
        for layer in QgsMapLayerRegistry.instance().mapLayers().values():
            if layer.type() == QgsMapLayer.VectorLayer:
                if layer.dataProvider().capabilities(
                ) & QgsVectorDataProvider.ChangeAttributeValues:
                    if not layer.isReadOnly():
                        if layer.geometryType(
                        ) < 3:  # Avoid UnknownGeometry and NoGeometry
                            vLayers.append(layer)

        self.tblLayers.setRowCount(len(vLayers))
        self.tblLayers.setColumnCount(3)

        self.tblLayers.setSortingEnabled(False)
        for row, lyr in enumerate(vLayers):
            item = QTableWidgetItem( QIcon( ":/plugins/AutoFields/icons/" + \
                self.geometryDict[lyr.geometryType()] + ".png"),
                str( lyr.geometryType() ) )
            self.tblLayers.setItem(row, 0, item)

            item = QTableWidgetItem(lyr.name())
            item.setData(Qt.UserRole, lyr.id())
            self.tblLayers.setItem(row, 1, item)

            tmpTreeLayer = self.root.findLayer(lyr.id())
            if tmpTreeLayer:
                group = tmpTreeLayer.parent().name()
                self.tblLayers.setItem(
                    row, 2,
                    QTableWidgetItem(
                        group if group else QApplication.
                        translate("AutoFieldsDockWidgetPy", "< root >")))

        self.tblLayers.setSortingEnabled(True)

    def updateFieldAndExpressionControls(self):
        """ After a selection is changed, reflect possible values in field controls """
        self.msg.show(
            "New selection " + str(len(self.tblLayers.selectedItems()) / 3),
            'info', True)

        if not self.tblLayers.selectedItems():
            self.frameFields.setEnabled(False)
            self.frameExpression.setEnabled(False)
            return
        else:
            self.frameFields.setEnabled(True)
            self.frameExpression.setEnabled(True)

        # List common fields in cboField and get geometries selected
        geometryTypeSet = self.updateFieldList()

        # Update expression controls
        if 0 in geometryTypeSet and len(geometryTypeSet) == 1:  # Points
            self.optXCoord.setEnabled(True)
            self.optYCoord.setEnabled(True)
            self.optLength.setEnabled(False)
            self.optPerimeter.setEnabled(False)
            self.optArea.setEnabled(False)
        elif 1 in geometryTypeSet and len(geometryTypeSet) == 1:  # Lines
            self.optXCoord.setEnabled(False)
            self.optYCoord.setEnabled(False)
            self.optLength.setEnabled(True)
            self.optPerimeter.setEnabled(False)
            self.optArea.setEnabled(False)
        elif 2 in geometryTypeSet and len(geometryTypeSet) == 1:  # Polygons
            self.optXCoord.setEnabled(False)
            self.optYCoord.setEnabled(False)
            self.optLength.setEnabled(False)
            self.optPerimeter.setEnabled(True)
            self.optArea.setEnabled(True)
        else:
            self.optXCoord.setEnabled(False)
            self.optYCoord.setEnabled(False)
            self.optLength.setEnabled(False)
            self.optPerimeter.setEnabled(False)
            self.optArea.setEnabled(False)

        if not self.btnGroup.checkedButton().isEnabled():
            self.optCustomExpression.setChecked(True)  # Default selection
            self.updateExpressionControls(self.optCustomExpression)

        self.expressionDlg = None  # Initialize the dialog

    def updateFieldList(self):
        """ Update field list and return geometries selected """
        commonFields = []
        geometryTypeSet = set()
        bFirstFlag = True
        for item in self.tblLayers.selectedItems():
            if item.column() == 1:  # It's the layer name item
                self.msg.show("ID " + item.data(Qt.UserRole), 'info',
                              True)  # Get layer id
                layer = QgsMapLayerRegistry.instance().mapLayer(
                    item.data(Qt.UserRole))
                geometryTypeSet.add(layer.geometryType())
                tmpFields = [
                    field.name() for field in layer.dataProvider().fields()
                ]  # Get field names stored in the provider
                if bFirstFlag:  # Initialize commonFields
                    commonFields = tmpFields
                    bFirstFlag = False
                else:  # Intersect fields
                    if commonFields:  # Avoid intersecting if no common fields
                        commonFields = list(set(commonFields) & set(tmpFields))

        commonFields.sort()
        self.msg.show("FIELDS: " + str(commonFields), 'info', True)

        self.cboField.clear()
        if not commonFields:
            self.optExistingField.setEnabled(False)
            self.optNewField.setChecked(True)
        else:
            self.optExistingField.setEnabled(True)
            self.cboField.addItems(commonFields)

        return geometryTypeSet

    def newFieldToggled(self):
        """ Alternate between controls of new field and existing field """
        newIsChecked = self.optNewField.isChecked()

        self.cboField.setEnabled(not newIsChecked)

        self.lblFieldName.setEnabled(newIsChecked)
        self.lblFieldType.setEnabled(newIsChecked)
        self.txtFieldName.setEnabled(newIsChecked)
        self.cboFieldType.setEnabled(newIsChecked)

        if newIsChecked:
            self.fieldTypeChanged(self.cboFieldType.currentIndex())
        else:
            self.lblFieldLength.setEnabled(newIsChecked)
            self.lblFieldPrecision.setEnabled(newIsChecked)
            self.txtFieldLength.setEnabled(newIsChecked)
            self.txtFieldPrecision.setEnabled(newIsChecked)

        self.expressionDlg = None  # Initialize the dialog

    def fieldTypeChanged(self, idx):
        """ Update field length and field precision controls' state and values """
        text = self.fieldTypesDict[idx]
        if text == 'Integer':
            self.txtFieldLength.setRange(1, 10)
            self.txtFieldLength.setEnabled(True)
            self.txtFieldPrecision.setEnabled(False)
            self.lblFieldLength.setEnabled(True)
            self.lblFieldPrecision.setEnabled(False)
        elif text == 'Real':
            self.txtFieldLength.setRange(1, 20)
            self.txtFieldPrecision.setRange(0, 15)
            self.txtFieldLength.setEnabled(True)
            self.txtFieldPrecision.setEnabled(True)
            self.lblFieldLength.setEnabled(True)
            self.lblFieldPrecision.setEnabled(True)
        elif text == 'String':
            self.txtFieldLength.setRange(1, 255)
            self.txtFieldLength.setEnabled(True)
            self.txtFieldPrecision.setEnabled(False)
            self.lblFieldLength.setEnabled(True)
            self.lblFieldPrecision.setEnabled(False)
        else:  # Date
            self.txtFieldLength.setEnabled(False)
            self.txtFieldPrecision.setEnabled(False)
            self.lblFieldLength.setEnabled(False)
            self.lblFieldPrecision.setEnabled(False)

    def fieldChanged(self, idx):
        """ Just to initialize the expression dialog if selected field changes """
        self.expressionDlg = None  # Initialize the dialog

    def saveAutoField(self):
        """ Do some validation and then call AutoFieldManager """

        # Check layers
        if not self.tblLayers.selectedItems():
            self.msg.show(
                QApplication.translate(
                    "AutoFieldsDockWidgetPy",
                    "[Warning] Please first select a layer."), 'warning')
            return

        # Check expression
        expression = u''
        if self.optXCoord.isChecked():
            expression = u'$x'
        elif self.optYCoord.isChecked():
            expression = u'$y'
        elif self.optLength.isChecked():
            expression = u'$length'
        elif self.optPerimeter.isChecked():
            expression = u'$perimeter'
        elif self.optArea.isChecked():
            expression = u'$area'
        elif self.optDate.isChecked():
            expression = u'now()'
        elif self.optCustomExpression.isChecked():
            if self.expressionDlg:
                expression = self.expressionDlg.expression
            if not self.expressionDlg or not expression:
                self.msg.show(
                    QApplication.translate(
                        "AutoFieldsDockWidgetPy",
                        "[Warning] Please first set a valid custom expression."
                    ), 'warning')
                return
        else:  # optSpatialValue
            pass

        # Check fields
        fieldName = ''
        if self.optNewField.isChecked():
            if self.txtFieldName.text():

                fieldName = self.txtFieldName.text().strip()
                newField = QgsField(
                    fieldName,
                    self.cboFieldType.itemData(
                        self.cboFieldType.currentIndex(), Qt.UserRole))

                length = self.txtFieldLength.value()
                precision = self.txtFieldPrecision.value()
                # Ensure length and precision are valid values when dealing with Real numbers
                if self.fieldTypesDict[
                        self.cboFieldType.currentIndex()] == 'Real':
                    if precision > length:
                        precision = length
                newField.setLength(length)
                newField.setPrecision(precision)

                for item in self.tblLayers.selectedItems():
                    if item.column() == 1:  # It's the layer name item
                        layer = QgsMapLayerRegistry.instance().mapLayer(
                            item.data(Qt.UserRole))
                        if layer.fieldNameIndex(fieldName) != -1:
                            self.msg.show(
                                QApplication.translate( "AutoFieldsDockWidgetPy",
                                    "[Error] The field " ) + fieldName + \
                                QApplication.translate( "AutoFieldsDockWidgetPy",
                                    " already exists in layer " ) + layer.name() + ". " + \
                                QApplication.translate( "AutoFieldsDockWidgetPy",
                                    " If you want to create an AutoField on it, you need to choose it from 'Existing Field' list." ),
                                'warning' )
                        else:
                            res = layer.dataProvider().addAttributes(
                                [newField])
                            if res:
                                layer.updateFields()

                                # Check if fieldName is preserved by the provider after field creation.
                                if layer.fieldNameIndex(fieldName) == -1:
                                    self.msg.show(
                                        QApplication.translate( "AutoFieldsDockWidgetPy",
                                            "[Error] The field " ) + fieldName + \
                                        QApplication.translate( "AutoFieldsDockWidgetPy",
                                            " was probably created with another name by the layer (" ) + \
                                        layer.name() + \
                                        QApplication.translate( "AutoFieldsDockWidgetPy",
                                            ") provider. " ) + \
                                        QApplication.translate( "AutoFieldsDockWidgetPy",
                                            " If you want to create an AutoField on it, you need to choose it from 'Existing Field' list." ),
                                        'warning' )
                                else:

                                    self.doSaveAutoField(
                                        layer, fieldName, expression)

                            else:
                                self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy",
                                    "[Error] Couldn't create " ) + newField.name() + \
                                    QApplication.translate( "AutoFieldsDockWidgetPy",
                                        " field in " ) + layer.name() + \
                                    QApplication.translate( "AutoFieldsDockWidgetPy", " layer." ),
                                    'warning' )

                # Some fields might have been created, update the field list once
                self.updateFieldList()

            else:
                self.msg.show(
                    QApplication.translate(
                        "AutoFieldsDockWidgetPy",
                        "[Warning] Please first set a name for the new field."
                    ), 'warning')
                return
        else:
            fieldName = self.cboField.currentText()

            for item in self.tblLayers.selectedItems():
                if item.column() == 1:  # It's the layer name item
                    layer = QgsMapLayerRegistry.instance().mapLayer(
                        item.data(Qt.UserRole))
                    self.doSaveAutoField(layer, fieldName, expression)

    def doSaveAutoField(self, layer, fieldName, expression):
        """ Repetitive logic to save or overwrite an AutoField """
        # Check if the field is an AutoField and ask if we should overwrite it
        res = True
        bCalculateOnExisting = self.chkCalculateOnExisting.isChecked()
        if self.autoFieldManager.isFieldAnAutoField(layer, fieldName):
            reply = QMessageBox.question( self.iface.mainWindow(),
                QApplication.translate( "AutoFieldsDockWidgetPy", "Confirmation" ),
                QApplication.translate( "AutoFieldsDockWidgetPy", "The field '" ) + \
                fieldName + QApplication.translate( "AutoFieldsDockWidgetPy",
                    "' from layer '" ) + layer.name() + \
                QApplication.translate( "AutoFieldsDockWidgetPy",
                    "' is already an AutoField.\nDo you want to overwrite it?" ),
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No )

            if reply == QMessageBox.Yes:
                res = self.autoFieldManager.overwriteAutoField(
                    layer,
                    fieldName,
                    expression,
                    calculateOnExisting=bCalculateOnExisting)

        else:
            res = self.autoFieldManager.createAutoField(
                layer,
                fieldName,
                expression,
                calculateOnExisting=bCalculateOnExisting)

        if not res:
            # res will only be False if create/overwriteAutoField return False
            self.msg.show( "[Error] The AutoField for layer '" + layer.name() + \
                "' and field '" + fieldName + "' couldn't be created.", 'warning', True )

    def setCustomExpression(self):
        """ Initialize and show the expression builder dialog """
        layer = None
        if len(self.tblLayers.selectedItems()
               ) / 3 == 1:  # Single layer selected?
            for item in self.tblLayers.selectedItems():
                if item.column() == 1:  # It's the layer name item
                    layer = QgsMapLayerRegistry.instance().mapLayer(
                        item.data(Qt.UserRole))

        if not self.expressionDlg:
            self.expressionDlg = ExpressionBuilderDialog(
                self.iface.mainWindow())
            context = QgsExpressionContext()
            context.appendScope(QgsExpressionContextUtils.globalScope())
            context.appendScope(QgsExpressionContextUtils.projectScope())

            # Initialize dialog with layer-based names and variables if single layer selected
            if len(self.tblLayers.selectedItems()) / 3 == 1:
                context.appendScope(
                    QgsExpressionContextUtils.layerScope(layer))
                self.expressionDlg.expressionBuilderWidget.setLayer(layer)
                self.expressionDlg.expressionBuilderWidget.loadFieldNames()

                # This block was borrowed from QGIS/python/plugins/processing/algs/qgis/FieldsCalculator.py
                da = QgsDistanceArea()
                da.setSourceCrs(layer.crs().srsid())
                da.setEllipsoidalMode(self.iface.mapCanvas().mapSettings().
                                      hasCrsTransformEnabled())
                da.setEllipsoid(QgsProject.instance().readEntry(
                    'Measure', '/Ellipsoid', GEO_NONE)[0])
                self.expressionDlg.expressionBuilderWidget.setGeomCalculator(
                    da)

                # If this layer-field is an AutoField, get its expression
                if self.optExistingField.isChecked():
                    fieldName = self.cboField.currentText()
                    expression = self.autoFieldManager.getFieldExpression(
                        layer, fieldName)
                    self.expressionDlg.expressionBuilderWidget.setExpressionText(
                        expression)
                    self.expressionDlg.expression = expression  # To remember it when closing/opening

            self.expressionDlg.expressionBuilderWidget.setExpressionContext(
                context)

        self.expressionDlg.show()

    def updateExpressionControls(self, button):
        """ Enable/disable push buttons when appropriate """
        if button.objectName() == 'optCustomExpression':
            self.btnNewCustomExpression.setEnabled(True)
            #self.btnNewSpatialValue.setEnabled( False )
        #elif button.objectName() == 'optSpatialValue':
        #self.btnNewCustomExpression.setEnabled( False )
        #self.btnNewSpatialValue.setEnabled( True )
        else:
            self.btnNewCustomExpression.setEnabled(False)
            #self.btnNewSpatialValue.setEnabled( False )

    def populateAutoFieldsTable(self, autoFieldId=None):
        """ Listens to any modification on AutoFields to update the list """
        dictAutoFields = self.autoFieldManager.listAutoFields()
        if autoFieldId:  # Just update this one
            if not autoFieldId in dictAutoFields:  # AutoField removed
                self.msg.show("[Info] Removing AutoField from table.", 'info',
                              True)
                # Iterate through AF rows and remove row where data matches AFID
                deleteRow = self.findRowOfItemDataInAutoFieldsTable(
                    autoFieldId, 0)
                if deleteRow != -1:
                    self.tblAutoFields.removeRow(deleteRow)
            else:
                # if it's in the table: remove it and re-add it (from new dict)
                deleteRow = self.findRowOfItemDataInAutoFieldsTable(
                    autoFieldId, 0)
                if deleteRow != -1:
                    self.msg.show(
                        "[Info] Refreshing AutoField status in table.", 'info',
                        True)
                    self.tblAutoFields.removeRow(deleteRow)
                    self.addAutoFieldToAutoFieldsTable(
                        autoFieldId, dictAutoFields[autoFieldId])
                else:  # New AutoField, just add it to table
                    self.msg.show("[Info] Adding new AutoField to table.",
                                  'info', True)
                    self.addAutoFieldToAutoFieldsTable(
                        autoFieldId, dictAutoFields[autoFieldId])
        else:
            # Initialize AutoFields Table
            self.tblAutoFields.clearContents()
            self.tblAutoFields.setRowCount(0)

            #self.tblAutoFields.setRowCount( len( dictAutoFields ) )
            self.tblAutoFields.setColumnCount(4)

            self.tblAutoFields.setSortingEnabled(False)
            for key in dictAutoFields.keys():
                autoField = dictAutoFields[key]
                self.addAutoFieldToAutoFieldsTable(key, autoField, False)

            self.tblAutoFields.setSortingEnabled(True)

    def findRowOfItemDataInAutoFieldsTable(self, data, col):
        """ Get the row number that matches its data to a given data (check only the given column) """
        for numRow in range(self.tblAutoFields.rowCount()):
            item = self.tblAutoFields.item(numRow, col)
            if item.data(Qt.UserRole) == data:
                return numRow
        return -1

    def addAutoFieldToAutoFieldsTable(self,
                                      autoFieldId,
                                      autoField,
                                      freezeSorting=True):
        """ Add a whole row to the AutoFields table """
        if self.chkOnlyEnabledAutoFields.isChecked(
        ) and not autoField['enabled']:
            return

        if freezeSorting:
            self.tblAutoFields.setSortingEnabled(False)

        row = self.tblAutoFields.rowCount()
        self.tblAutoFields.insertRow(row)
        name = autoField['layer']
        if 'layerId' in autoField:
            lyr = QgsMapLayerRegistry.instance().mapLayer(autoField['layerId'])
            name = lyr.name()
        item = QTableWidgetItem(name)
        item.setData(Qt.UserRole, autoFieldId)
        item.setData(Qt.ToolTipRole, autoField['layer'])
        if not autoField['enabled']:
            item.setForeground(QBrush(Qt.gray))
        self.tblAutoFields.setItem(row, 0, item)
        item = QTableWidgetItem(autoField['field'])
        if not autoField['enabled']:
            item.setForeground(QBrush(Qt.gray))
        self.tblAutoFields.setItem(row, 1, item)
        item = QTableWidgetItem(autoField['expression'])
        if not autoField['enabled']:
            item.setForeground(QBrush(Qt.gray))
        self.tblAutoFields.setItem(row, 2, item)
        item = QTableWidgetItem(
            QApplication.translate("AutoFieldsDockWidgetPy", "Enabled"
                                   ) if autoField['enabled'] else QApplication.
            translate("AutoFieldsDockWidgetPy", "Disabled"))
        item.setData(Qt.UserRole,
                     'enabled' if autoField['enabled'] else 'disabled')
        if not autoField['enabled']:
            item.setForeground(QBrush(Qt.gray))
        self.tblAutoFields.setItem(row, 3, item)

        if freezeSorting:
            self.tblAutoFields.setSortingEnabled(True)

    def openAutoFieldContextMenu(self, position):
        bLayers = False
        layers = QgsMapLayerRegistry.instance().mapLayers().values()
        for layer in layers:
            if layer.type() == QgsMapLayer.VectorLayer:
                if layer.dataProvider().capabilities(
                ) & QgsVectorDataProvider.AddFeatures:
                    bLayers = True
                    break

        item = self.tblAutoFields.itemAt(position)
        if item:
            row = item.row()
            self.menu = QMenu()
            self.action = QAction("Assign this AutoField to another layer",
                                  None)
            self.action.setObjectName('action')
            if self.tblAutoFields.item(row, 3).data(Qt.UserRole) == 'enabled':
                self.action.setEnabled(False)
            self.menu.addAction(self.action)
            action = self.menu.exec_(self.tblAutoFields.mapToGlobal(position))
            if action and action.objectName() == 'action':
                if not bLayers:
                    self.msg.show(
                        QApplication.translate(
                            "AutoFieldsDockWidgetPy",
                            "First load some vector layers to QGIS to be able to assign disabled AutoFields."
                        ), 'warning')
                    return

                autoFieldId = self.tblAutoFields.item(row, 0).data(Qt.UserRole)
                bCalculateOnExisting = self.chkCalculateOnExisting.isChecked()
                dlg = AssignAutoFieldToLayerDialog(self.iface.mainWindow(),
                                                   self.autoFieldManager,
                                                   autoFieldId,
                                                   bCalculateOnExisting)
                dlg.show()

    def updateRemoveAutoFieldButton(self):
        """ Enable/disable button to remove AutoFields when appropriate """
        self.btnRemoveAutoFields.setEnabled(
            len(self.tblAutoFields.selectedItems()) / 4)

    def removeAutoFieldFromTable(self):
        """ Show a confirmation dialog for all AutoFields selected.
            If confirmed, remove AutoFields from table.
        """
        # Column 0 has the AutoField id
        autoFieldsToRemove = [
            item.data(Qt.UserRole)
            for item in self.tblAutoFields.selectedItems()
            if item.column() == 0
        ]

        reply = QMessageBox.question( self.iface.mainWindow(),
            QApplication.translate( "AutoFieldsDockWidgetPy", "Confirmation" ),
            QApplication.translate( "AutoFieldsDockWidgetPy",
                "Do you really want to remove " ) + \
            str(len( autoFieldsToRemove )) + \
            (" AutoFields?" if len( autoFieldsToRemove ) > 1 else " AutoField?"),
            QMessageBox.Yes | QMessageBox.No, QMessageBox.No )

        if reply == QMessageBox.Yes:
            for autoFieldId in autoFieldsToRemove:
                self.autoFieldManager.removeAutoField(autoFieldId)

    def saveShowOnlyEnabledPreference(self, status):
        """ Saves the preference in QSettings and updates list of AutoFields """
        settings = QSettings()
        settings.setValue(
            self.autoFieldManager.settingsPrefix +
            "/showOnlyEnabledAutoFields", status)
        self.populateAutoFieldsTable()

    def saveCalculateOnExistingPreference(self, status):
        """ Saves the preference in QSettings """
        settings = QSettings()
        settings.setValue(
            self.autoFieldManager.settingsPrefix +
            "/calculateOnExistingFeatures", status)

    def openDocumentation(self):
        """ Open a browser to show documentation page """
        import webbrowser
        webbrowser.open("http://geotux.tuxfamily.org/index.php/" +
                        self.language +
                        "/geo-blogs/item/333-autofields-plugin-for-qgis")

    def disconnectAll(self):
        """ Terminates all SIGNAL/SLOT connections created by this class """
        QgsMapLayerRegistry.instance().legendLayersAdded.disconnect(
            self.populateLayersTable)
        QgsMapLayerRegistry.instance().layersRemoved.disconnect(
            self.populateLayersTable)
        self.root.addedChildren.disconnect(self.populateLayersTable)
        self.root.removedChildren.disconnect(self.populateLayersTable)

        self.tblLayers.itemSelectionChanged.disconnect(
            self.updateFieldAndExpressionControls)
        self.optNewField.toggled.disconnect(self.newFieldToggled)
        self.cboField.currentIndexChanged.disconnect(self.fieldChanged)
        self.cboFieldType.currentIndexChanged.disconnect(self.fieldTypeChanged)
        self.btnSaveAutoField.clicked.disconnect(self.saveAutoField)
        self.btnNewCustomExpression.clicked.disconnect(
            self.setCustomExpression)
        self.btnGroup.buttonClicked.disconnect(self.updateExpressionControls)

        self.autoFieldManager.autoFieldCreated.disconnect(
            self.populateAutoFieldsTable)
        self.autoFieldManager.autoFieldRemoved.disconnect(
            self.populateAutoFieldsTable)
        self.autoFieldManager.autoFieldEnabled.disconnect(
            self.populateAutoFieldsTable)
        self.autoFieldManager.autoFieldDisabled.disconnect(
            self.populateAutoFieldsTable)
        self.tblAutoFields.itemSelectionChanged.disconnect(
            self.updateRemoveAutoFieldButton)
        self.chkOnlyEnabledAutoFields.toggled.disconnect(
            self.saveShowOnlyEnabledPreference)
        self.btnRemoveAutoFields.clicked.disconnect(
            self.removeAutoFieldFromTable)
예제 #10
0
class EthernetEditor(QFrame):
    def __init__(self, ethernet, parent=None):
        QFrame.__init__(self, parent)

        self.ethernet = ethernet

        self.buildGUI()
        self.fillValues()

    def buildGUI(self):
        #general setup
        form = QFormLayout(self)

        self.label = OptionnalLine(hint="Optional interface name")
        form.addRow(self.tr("Interface name"), self.label)

        self.speed_group = QButtonGroup()
        self.speed_box = QGroupBox(tr("Force an ethernet speed"))
        speed_layout = QVBoxLayout(self.speed_box)

        self.speed_GFull = QRadioButton(tr("Gigabit full duplex"))
        self.speed_GHalf = QRadioButton(tr("Gigabit half duplex"))
        self.speed_100Full = QRadioButton(tr("100 Mb Full duplex"))
        self.speed_100Half = QRadioButton(tr("100 Mb Half duplex"))
        self.speed_10Full = QRadioButton(tr("10 Mb Full duplex"))
        self.speed_10Half = QRadioButton(tr("10 Mb Half duplex"))

        def toggle(value):
            if value:
                self.speed_GFull.click()

        self.speed_box.setCheckable(True)
        self.speed_box.setChecked(Qt.Unchecked)
        self.connect(self.speed_box, SIGNAL('toggled(bool)'), toggle)

        for item in (
            self.speed_GFull,
            self.speed_GHalf,
            self.speed_100Full,
            self.speed_100Half,
            self.speed_10Full,
            self.speed_10Half,
            ):
            self.speed_group.addButton(item)
            speed_layout.addWidget(item)

        form.addRow(self.speed_box)

    def fillValues(self):
        name = self.ethernet.user_label
        if name != "":
            self.label.setText(name)
            self.label.checkEmpty()
            self.label.setStyleSheet('')

        if self.ethernet.eth_auto:
            self.speed_box.setChecked(Qt.Unchecked)
            return

        self.speed_box.setChecked(Qt.Checked)
        if self.ethernet.eth_duplex == Ethernet.FULL:
            if self.ethernet.eth_speed == 10:
                button = self.speed_10Full
            elif self.ethernet.eth_speed == 100:
                button = self.speed_100Full
            else:
                button = self.speed_GFull
        else:
            if self.ethernet.eth_speed == 10:
                button = self.speed_10Half
            elif self.ethernet.eth_speed == 100:
                button = self.speed_100Half
            else:
                button = self.speed_GHalf


        button.setChecked(Qt.Checked)

    def getConfig(self):
        auto = not self.speed_box.isChecked()
        if auto:
            return True, None, None
        selection = self.speed_group.checkedButton()
        if selection is self.speed_GFull:
            return False, 1000, Ethernet.FULL
        elif self.speed_GHalf:
            return False, 1000, Ethernet.HALF
        elif self.speed_100Full:
            return False, 100, Ethernet.FULL
        elif self.speed_100Half:
            return False, 100, Ethernet.HALF
        elif self.speed_10Full:
            return False, 10, Ethernet.FULL
        elif self.speed_10Half:
            return False, 10, Ethernet.HALF

        assert False, "this selection is unknown"

    def setName(self):
        new_name = self.label.value()
        if new_name != self.ethernet.user_label:
            self.ethernet.user_label = new_name
            #message = tr("renamed ethernet interface to: %s'") % new_name
        return True

    def accept(self, *args, **kwargs):
        ok = True
        ok &= self.setName()
        self.ethernet.setEthernetMode(*self.getConfig())
        if ok:
            self.emit(SIGNAL('edited'), "edited ethernet interface '%s'" \
            % self.ethernet.fullName())
        return ok
예제 #11
0
class OptionWidget(EditorWidget):
    widgettype = 'Option Row'

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

    def createWidget(self, parent):
        widget = QWidget(parent)
        widget.setLayout(QHBoxLayout())
        widget.layout().setContentsMargins(0, 0, 0, 0)
        return widget

    def _buildfromlist(self, listconfig):
        items = listconfig['items']
        for item in items:
            parts = item.split(';')
            data = parts[0]
            try:
                desc = parts[1]
            except IndexError:
                desc = data

            try:
                path = parts[2]
                if path.endswith("_icon"):
                    icon = QIcon(":/icons/{}".format(path))
                else:
                    icon = QIcon(path)
            except:
                icon = QIcon()

            button = QPushButton()
            button.setCheckable(True)
            button.setText(desc)
            button.setProperty("value", data)
            button.setIcon(icon)
            button.setIconSize(QSize(24, 24))
            self.widget.layout().addWidget(button)
            self.group.addButton(button)

    def initWidget(self, widget):
        pass

    def updatefromconfig(self):
        super(OptionWidget, self).updatefromconfig()
        listconfig = self.config['list']
        self._buildfromlist(listconfig)

        super(OptionWidget, self).endupdatefromconfig()

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

        return False

    def setvalue(self, value):
        for button in self.group.buttons():
            if button.property("value") == str(value):
                button.setChecked(True)
                return

    def value(self):
        button = self.group.checkedButton()
        if not button:
            return None
        return button.property("value")
예제 #12
0
class CategoriesTab(QWidget):
    """ 
    Widget for displaying the categories tab in the SettingsDialog. 
    This is embedded into the SettingsDialog. 
    The user can add or remove a category using several options. 
    For some reason, PyQt does not recognize QButtonGroup objects, hence they
    need to be defined explicitely. 
    Also, a reference to FinanceagerWindow is stored as private attribute
    self.__parent because later referencing does not work otherwise.
    """
    def __init__(self, parent=None):
        super(CategoriesTab, self).__init__(parent)
        loadUi(__file__, self)
        self.__parent = parent

        self.removeFromMonthButtons = QButtonGroup()
        self.removeFromMonthButtons.addButton(self.removeAllMonthsButton)
        self.removeFromMonthButtons.addButton(
            self.removeAllMonthsFromNowButton)
        self.removeFromMonthButtons.addButton(self.removeCurrentMonthButton)
        self.addToMonthButtons = QButtonGroup()
        self.addToMonthButtons.addButton(self.addAllMonthsButton)
        self.addToMonthButtons.addButton(self.addAllMonthsFromNowButton)
        self.addToMonthButtons.addButton(self.addCurrentMonthButton)
        self.expAndRecButtons = QButtonGroup()
        self.expAndRecButtons.addButton(self.expendituresButton)
        self.expAndRecButtons.addButton(self.receiptsButton)
        self.removeCategoryCombo.addItems(self.categoriesStringList())
        # CONNECTIONS
        self.addCategoryGroup.clicked.connect(
            self.newCategoryLineEdit.setFocus)

    def categoriesStringList(self):
        """
        Returns a sorted list of all the categories that occur in the parentwidget's 
        (== FinanceagerWindow's) tabs.
        Used for both populating the removeCategoryCombo and preventing the
        user from adding an already existing category. The latter is important
        in order to avoid ambiguities when removing a category. 

        :return     list(str)
        """
        categories = set()
        tabWidget = self.__parent.monthsTabWidget
        for m in range(12):
            monthTab = tabWidget.widget(m)
            categories = categories.union(monthTab.categoriesStringList())
        categories = list(categories)
        categories.sort()
        return categories

    def checkForUniqueCategory(self, name):
        """
        Called from updateChangesToApply() to verify that the given category
        name is unique. Pops up a warning and resets newCategoryLineEdit if not. 

        :param      name | str 
        :return     uniqueCategory | bool 
        """
        #FIXME this also prevents adding a category that exists in any other month!
        if name in self.categoriesStringList():
            QMessageBox.warning(
                self.__parent, 'Name conflict',
                'This category name already exists. Please enter a unique name.'
            )
            self.newCategoryLineEdit.setText('')
            self.newCategoryLineEdit.setFocus()
            return False
        else:
            return True

    def updateChangesToApply(self, changes):
        """
        Checks for checked GroupBoxes. 
        Creates a tuple consisting of a function string and a tuple that contains 
        name, typ and option. Those three are fetched from the tab's widgets. 
        function:   'addCategory' | 'removeCategory' 
        name:       new category name | category to delete 
        option:     0 (all months) | 1 (all months from now) | 2 (current month)
        typ:        0 (expenditure) | 1 (receipt)
        The tuple is eventually evaluated by SettingsDialog.applyChanges() 
        if the dialog is not cancelled.

        :param      changes | set 
        """
        if self.addCategoryGroup.isChecked():
            name = unicode(self.newCategoryLineEdit.text()).strip()
            if len(name):
                if self.checkForUniqueCategory(name):
                    typ = self.expAndRecButtons.buttons().index(
                        self.expAndRecButtons.checkedButton())
                    option = self.addToMonthButtons.buttons().index(
                        self.addToMonthButtons.checkedButton())
                    changes.add(('addCategory', (name, typ, option)))
        if self.removeCategoryGroup.isChecked():
            name = unicode(self.removeCategoryCombo.currentText())
            option = self.removeFromMonthButtons.buttons().index(
                self.removeFromMonthButtons.checkedButton())
            changes.add(('removeCategory', (name, option)))