Exemple #1
0
    def selectFeatureClicked(self, layer, column, message, searchsize, bindto):
        """
        Loads the select from map action tool. Switchs to the map to allow the
        user to select a feature.

        controlname - The control name when looking up in the settings for the
                      button config.
        """
        self.tool = SelectFeatureTool(self.canvas, layer, column, bindto,
                                      searchsize)
        self.tool.foundFeature.connect(self.bindHighlightedFeature)
        self.tool.setActive()
        self.beginSelectFeature.emit(message)
Exemple #2
0
    def selectFeatureClicked(self, layer, column, message, searchsize, bindto):
        """
        Loads the select from map action tool. Switchs to the map to allow the
        user to select a feature.

        controlname - The control name when looking up in the settings for the
                      button config.
        """
        self.tool = SelectFeatureTool(self.canvas, layer, column, bindto, searchsize)
        self.tool.foundFeature.connect(self.bindHighlightedFeature)
        self.tool.setActive()
        self.beginSelectFeature.emit(message)
Exemple #3
0
class FormBinder(QObject):
    beginSelectFeature = pyqtSignal(str)
    endSelectFeature = pyqtSignal()
    """
    Handles binding of values to and out of the form.
    """

    def __init__(self, layer, formInstance, canvas, settings, formmodule, db):
        QObject.__init__(self)
        self.layer = layer
        self.canvas = canvas
        self.forminstance = formInstance
        self.fields = self.layer.pendingFields()
        self.fieldtocontrol = {}
        self.actionlist = []
        self.settings = settings
        self.images = {}
        self.mandatory_group = MandatoryGroup()
        self.forsaving = set()
        self.formmodule = formmodule
        self.db = db

    def bindFeature(self, qgsfeature, mandatory_fields=True, editing=False):
        """
        Binds a features values to the form. If the control has the mandatory
        property set then it will be added to the mandatory group.

        qgsfeature - A QgsFeature to bind the values from
        mandatory_fields - True if mandatory fields should be respected (default)
        """
        self.feature = qgsfeature
        self.connectControlsToSQLCommands()
        defaults = self.getDefaults()
        for index, value in qgsfeature.attributeMap().items():
            field = self.fields[index]

            try:
                control = self.getControl(field.name())
            except ControlNotFound as ex:
                warning(ex.message)
                continue

            if mandatory_fields:
                mandatory = control.property("mandatory").toBool()
                if mandatory:
                    buddy = self.getBuddy(control)
                    self.mandatory_group.addWidget(control, buddy)

            info("Binding %s to %s" % (control.objectName(), value.toString()))

            isdefaultset = False
            if not editing:
                try:
                    # Get the default value from the database and use that instead.
                    value = defaults[control]
                    isdefaultset = control in defaults
                except KeyError:
                    pass

            try:
                self.bindValueToControl(control, value)
            except BindingError as er:
                warning(er.reason)

            self.bindSaveValueButton(control, indefaults=isdefaultset)
            self.createHelpLink(control)

            self.fieldtocontrol[index] = control

    def createHelpLink(self, control):
        name = control.objectName()
        helpfile = self.formmodule.getHelpFile(name)
        if helpfile:
            label = self.getBuddy(control)
            if label is control:
                return
            if label is None:
                return
            text = '<a href="%s">%s<a>' % (helpfile, label.text())
            label.setText(text)
            label.linkActivated.connect(self.showHelp)

    def showHelp(self, url):
        dlg = HelpViewDialog()
        dlg.loadFile(url)
        dlg.exec_()

    def getDefaults(self):
        query = QSqlQuery("SELECT control, value FROM DefaultValues")
        query.exec_()
        defaults = {}
        while query.next():
            try:
                name = query.value(0).toString()
                control = self.getControl(name)
            except ControlNotFound:
                continue

            value = query.value(1)
            defaults[control] = value
        return defaults

    def connectControlsToSQLCommands(self):
        """
            Loops all the controls and connects update signals
            in order to use SQL commands correctly.

            Note: We check all control because we can use SQL on non
            field bound controls in order to show information.
        """
        for control in self.forminstance.findChildren(QWidget):
            self.connectSQL(control)

    def getBuddy(self, control):
        try:
            label = self.getControl(control.objectName() + "_label", control_type=QLabel)
            return label
        except ControlNotFound:
            return control

    def getControl(self, name, control_type=QWidget):
        control = self.forminstance.findChild(control_type, name)
        if not control:
            raise ControlNotFound(name)

        return control

    def bindByName(self, controlname, value):
        """
        Binds a value to a control based on the control name.

        controlname - Name of the control to bind
        value - QVariant holding the value.
        """
        control = self.getControl(controlname)

        try:
            self.bindValueToControl(control, value)
        except BindingError as er:
            warning(er.reason)

    def saveComboValues(self, combobox, text):
        """
        Save the value of the combo box into the form settings values.
        Only saves new values.
        """
        comboitems = [combobox.itemText(i) for i in range(combobox.count())]
        name = combobox.objectName()
        query = QSqlQuery()
        query.prepare("SELECT value FROM ComboBoxItems WHERE control = :contorl")
        query.bindValue(":control", name)
        query.exec_()
        log("LAST ERROR")
        log(query.lastError().text())
        items = []
        while query.next():
            value = query.value(0).toString()
            if not value.isEmpty():
                items.append(str(value))

        if not text in comboitems and not text in items:
            query = QSqlQuery()
            query.prepare("INSERT INTO ComboBoxItems (control, value)" "VALUES (:control,:value)")
            query.bindValue(":control", name)
            query.bindValue(":value", text)
            query.exec_()
            log("LAST ERROR FOR INSERT")
            log(query.lastError().text())

    def updateControl(self, control, mapping, sql, *args):
        """
            Update control with result from SQL query.
        """
        query = QSqlQuery()
        query.prepare(sql)
        # Loop though all the placeholders and get value from the
        # function assigned to each one.
        for holder, function in mapping.items():
            value = function()
            query.bindValue(":%s" % holder, value)

        query.exec_()

        for key, value in query.boundValues().items():
            log("%s is %s" % (key, value.toString()))

        if isinstance(control, QComboBox):
            control.clear()
            control.addItem("")
            while query.next():
                value = query.value(0).toString()
                if not value.isEmpty():
                    control.addItem(value)

    def connectSQL(self, control):
        sql = control.property("sql").toString()
        if not sql.isEmpty():
            log("QUERY:%s" % sql)
            placeholders = re.findall(r":(\w+)", sql)
            mapping = {}
            # Loop though all the sql placeholders and look for a
            # control with that name to get updates from.
            for holder in placeholders:
                linked_control = self.getControl(holder)
                if linked_control is None:
                    continue

                if isinstance(linked_control, QListWidget):
                    mapping[holder] = lambda c=linked_control: c.currentItem().text()
                    linked_control.currentItemChanged.connect(partial(self.updateControl, control, mapping, sql))

    def bindValueToControl(self, control, value):
        """
        Binds a control to the supplied value.
        Raises BindingError() if control is not supported.

        control - QWidget based control that takes the new value
        value - A QVariant holding the value
        """
        if isinstance(control, QCalendarWidget):
            control.setSelectedDate(QDate.fromString(value.toString(), Qt.ISODate))

        elif isinstance(control, QListWidget):
            items = control.findItems(value.toString(), Qt.MatchExactly)
            try:
                control.setCurrentItem(items[0])
                control.currentItemChanged.emit(None, items[0])
            except IndexError:
                pass

        elif isinstance(control, QLineEdit) or isinstance(control, QTextEdit):
            control.setText(value.toString())

        elif isinstance(control, QCheckBox) or isinstance(control, QGroupBox):
            control.setChecked(value.toBool())

        elif isinstance(control, QPlainTextEdit):
            control.setPlainText(value.toString())

        elif isinstance(control, QComboBox):
            # Add items stored in the database
            query = QSqlQuery()
            query.prepare("SELECT value FROM ComboBoxItems WHERE control = :contorl")
            query.bindValue(":control", control.objectName())
            query.exec_()
            while query.next():
                newvalue = query.value(0).toString()
                if not newvalue.isEmpty():
                    control.addItem(newvalue)

            itemindex = control.findText(value.toString())
            control.setCurrentIndex(itemindex)

        elif isinstance(control, QDoubleSpinBox):
            double, passed = value.toDouble()
            control.setValue(double)

        elif isinstance(control, QSpinBox):
            integer, passed = value.toInt()
            control.setValue(integer)

        elif isinstance(control, QDateTimeEdit):
            control.setDateTime(QDateTime.fromString(value.toString(), Qt.ISODate))
            # Wire up the date picker button
            parent = control.parentWidget()
            if parent:
                button = parent.findChild(QPushButton, control.objectName() + "_pick")
                if button:
                    button.setIcon(QIcon(":/icons/calender"))
                    button.setText("Pick")
                    button.setIconSize(QSize(24, 24))
                    button.pressed.connect(partial(self.pickDateTime, control, "DateTime"))
        elif isinstance(control, QPushButton):
            if control.text() == "Drawing":
                control.setIcon(QIcon(":/icons/draw"))
                control.setIconSize(QSize(24, 24))
                control.pressed.connect(partial(self.loadDrawingTool, control))
        else:
            raise BindingError(control, value.toString(), "Unsupported widget %s" % control)

    def loadDrawingTool(self, control):
        """
        Load the drawing tool.

        control - The control (QWidget) who owns this drawing.  Its name is used
                  in the naming of the final image.
        """
        controlname = str(control.objectName())
        self.forminstance.hide()
        curdir = os.path.dirname(__file__)
        id = self.feature.attributeMap()[self.layer.fieldNameIndex("UniqueID")].toString()
        savedname = str(id) + "_" + controlname + ".jpg"
        imagename = os.path.join(curdir, "data", str(self.layer.name()), "images", savedname)

        tempname = "drawingFor_{0}".format(controlname)
        tempimage = os.path.join(tempfile.gettempdir(), tempname)

        log("Looking for {0} or {1}".format(imagename, tempimage))
        imagetoload = self.images.get(controlname, imagename)

        drawingpad = DrawingPad(imagetoload)
        drawingpad.setWindowState(Qt.WindowFullScreen | Qt.WindowActive)
        drawingpad.ui.actionMapSnapshot.triggered.connect(partial(self.drawingPadMapSnapshot, drawingpad))
        if drawingpad.exec_():
            # Save the image to a temporay location until commit.
            self.images[controlname] = tempimage + ".png"
            drawingpad.saveImage(tempimage)
            self.forminstance.show()
        else:
            self.forminstance.show()

    def drawingPadMapSnapshot(self, pad):
        """
        Saves the current view of the map canvas to a image and it into the
        drawing pad.

        pad - The drawing pad that will take the final image.
        """
        # TODO Refactor me!!
        image = QPixmap.fromImage(pad.scribbleArea.image)
        tempimage = os.path.join(tempfile.gettempdir(), "mapcanvascapture.png")
        self.canvas.saveAsImage(tempimage, image)
        pad.openImage(tempimage)

    def unbindFeature(self, qgsfeature):
        """
        Unbinds the feature from the form saving the values back to the QgsFeature.

        qgsfeature -- A QgsFeature that will store the new values.
        TODO: If the parent of the control is a QGroupBox and is disabled, the control is ignored for changing.
        """
        for index, control in self.fieldtocontrol.items():
            value = None
            if isinstance(control, QLineEdit):
                value = control.text()

            elif isinstance(control, QTextEdit) or isinstance(control, QPlainTextEdit):
                value = control.toPlainText()

            elif isinstance(control, QCalendarWidget):
                value = control.selectedDate().toString(Qt.ISODate)

            elif isinstance(control, QCheckBox) or isinstance(control, QGroupBox):
                value = 0
                if control.isChecked():
                    value = 1
            elif isinstance(control, QComboBox):
                value = control.currentText()
                if control.isEditable():
                    self.saveComboValues(control, value)

            elif isinstance(control, QDoubleSpinBox) or isinstance(control, QSpinBox):
                value = control.value()

            elif isinstance(control, QDateTimeEdit):
                value = control.dateTime().toString(Qt.ISODate)

            elif isinstance(control, QListWidget):
                item = control.currentItem()
                if item:
                    value = item.text()
                else:
                    return QString("")

            info("Setting value to %s from %s" % (value, control.objectName()))
            qgsfeature.changeAttribute(index, value)

            # Save the value to the database as a default if it is needed.
            if self.shouldSaveValue(control):
                self.saveDefault(control, value)
            else:
                self.removeDefault(control)

        return qgsfeature

    def pickDateTime(self, control, mode):
        """
        Open the date time picker dialog

        control - The control that will recive the user set date time.
        """
        dlg = DateTimePickerDialog(mode)
        dlg.setWindowTitle("Select a date")
        dlg.setDateTime(control.dateTime())
        if dlg.exec_():
            if hasattr(control, "setDate"):
                control.setDate(dlg.getSelectedDate())

            if hasattr(control, "setTime"):
                control.setTime(dlg.getSelectedTime())

    def shouldSaveValue(self, control):
        try:
            button = self.getControl(control.objectName() + "_save", QToolButton)
        except ControlNotFound:
            log("_save button not found for %s" % control.objectName())
            return

        log("_save button for %s is %s" % (control.objectName(), str(button.isChecked())))
        return button.isChecked()

    def bindSaveValueButton(self, control, indefaults=False):
        try:
            button = self.getControl(control.objectName() + "_save", QToolButton)
        except ControlNotFound:
            return

        button.setCheckable(True)
        button.setIcon(QIcon(":/icons/save_default"))
        button.setIconSize(QSize(24, 24))
        button.setChecked(indefaults)

    def removeDefault(self, control):
        name = control.objectName()
        query = QSqlQuery()
        query.prepare("DELETE FROM DefaultValues WHERE control = :control")
        query.bindValue(":control", name)
        query.exec_()

    def saveDefault(self, control, value):
        self.removeDefault(control)
        name = control.objectName()
        query = QSqlQuery()
        query.prepare("INSERT INTO DefaultValues (control, value)" "VALUES (:control,:value)")
        query.bindValue(":control", name)
        query.bindValue(":value", value)
        query.exec_()

    def bindSelectButtons(self):
        """
        Binds all the buttons on the form that need a select from map action.
        """
        tools = self.forminstance.findChildren(QToolButton, QRegExp(".*_mapselect"))
        log(tools)
        layers = {QString(l.name()): l for l in self.canvas.layers()}
        log(layers)
        for tool in tools:
            try:
                control = self.getControl(tool.objectName()[:-10])
            except ControlNotFound as ex:
                warning(ex.message)
                tool.setEnabled(False)
                continue

            settings = tool.dynamicPropertyNames()
            if not "from_layer" in settings or not "using_column" in settings:
                warning("from_layer or using_column not found")
                tool.setEnabled(False)
                continue

            layer_name = tool.property("from_layer").toString()
            column_name = tool.property("using_column").toString()

            layer = None
            try:
                layer = layers[QString(layer_name)]
            except KeyError:
                warning("layer not found in list")
                tool.setEnabled(False)
                continue

            message = tool.property("message").toString()
            if message.isEmpty():
                message = "Please select a feature in the map"

            radius, valid = tool.property("radius").toInt()
            if not valid:
                radius = 5

            tool.pressed.connect(
                partial(self.selectFeatureClicked, layer, column_name, message, radius, control.objectName())
            )
            tool.setIcon(QIcon(":/icons/select"))
            tool.setIconSize(QSize(24, 24))

    def selectFeatureClicked(self, layer, column, message, searchsize, bindto):
        """
        Loads the select from map action tool. Switchs to the map to allow the
        user to select a feature.

        controlname - The control name when looking up in the settings for the
                      button config.
        """
        self.tool = SelectFeatureTool(self.canvas, layer, column, bindto, searchsize)
        self.tool.foundFeature.connect(self.bindHighlightedFeature)
        self.tool.setActive()
        self.beginSelectFeature.emit(message)

    def bindHighlightedFeature(self, feature, value, bindto):
        """
        Binds the selected features value to a control.
        """
        self.bindByName(bindto, value)
        self.endSelectFeature.emit()
Exemple #4
0
class FormBinder(QObject):
    beginSelectFeature = pyqtSignal(str)
    endSelectFeature = pyqtSignal()
    """
    Handles binding of values to and out of the form.
    
    TODO: This whole class is really messy and needs a good clean up.
    """
    def __init__(self, layer, formInstance, canvas):
        QObject.__init__(self)
        self.layer = layer
        self.canvas = canvas
        self.forminstance = formInstance
        self.images = {}
        self.mandatory_group = MandatoryGroup()
        self.boundControls = []

    def bindFeature(self, qgsfeature, mandatory_fields=True, editing=False):
        """
        Binds a features values to the form. If the control has the mandatory
        property set then it will be added to the mandatory group.

        qgsfeature - A QgsFeature to bind the values from
        mandatory_fields - True if mandatory fields should be respected (default)
        """
        self.feature = qgsfeature
        defaults = qmaplayer.getSavedValues(self.layer)

        for index in xrange(qgsfeature.fields().count()):
            value = qgsfeature[index]
            name = qgsfeature.fields()[index].name()

            try:
                control = self.getControl(name)
            except ControlNotFound as ex:
                warning(ex.message)
                continue

            if mandatory_fields:
                mandatory = control.property("mandatory")
                if mandatory:
                    buddy = self.getBuddy(control)
                    self.mandatory_group.addWidget(control, buddy)

            self.bindSaveValueButton(control, defaults, editingmode=editing)
            if not editing:
                try:
                    value = defaults[name]
                except KeyError:
                    pass

            try:
                self.bindValueToControl(control, value, index)
            except BindingError as er:
                warning(er.reason)

            self.createHelpLink(control)
            self.mandatory_group.validateAll()

    def createHelpLink(self, control):
        name = control.objectName()
        helpfile = qmaplayer.getHelpFile(self.layer, name)
        log(helpfile)
        log(name)
        if helpfile:
            label = self.getBuddy(control)
            if label is control: return
            if label is None: return
            text = '<a href="{}">{}<a>'.format(helpfile, label.text())
            label.setText(text)
            label.linkActivated.connect(self.showHelp)

    def showHelp(self, url):
        dlg = HelpViewDialog()
        dlg.loadFile(url)
        dlg.exec_()

    def getBuddy(self, control):
        try:
            label = self.getControl(control.objectName() + "_label",
                                    control_type=QLabel)
            return label
        except ControlNotFound:
            return control

    def getControl(self, name, control_type=QWidget):
        control = self.forminstance.findChild(control_type, name)
        if control is None:
            raise ControlNotFound(name)

        return control

    def bindByName(self, controlname, value):
        """
        Binds a value to a control based on the control name.

        controlname - Name of the control to bind
        value - QVariant holding the value.
        """
        control = self.getControl(controlname)

        try:
            self.bindValueToControl(control, value)
        except BindingError as er:
            warning(er.reason)

    def bindValueToControl(self, control, value, index=0):
        """
        Binds a control to the supplied value.

        control - QWidget based control that takes the new value
        value - A QVariant holding the value
        """
        if isinstance(control, QDateTimeEdit):
            # Can be removed after http://hub.qgis.org/issues/7013 is fixed.
            if isinstance(value, QDateTime):
                control.setDateTime(value)
            else:
                control.setDateTime(QDateTime.fromString(value, Qt.ISODate))

            try:
                button = self.getControl(control.objectName() + "_pick",
                                         QPushButton)
                button.setIcon(QIcon(":/icons/calender"))
                button.setText("Pick")
                button.setIconSize(QSize(24, 24))
                log("{} : {}".format(control.objectName(),
                                     type(control) is QDateEdit))
                if type(control) is QDateEdit:
                    log("Type is QDateEdit")
                    button.pressed.connect(
                        partial(self.pickDateTime, control, "Date"))
                else:
                    button.pressed.connect(
                        partial(self.pickDateTime, control, "DateTime"))

            except ControlNotFound:
                pass

            self.boundControls.append(control)

        elif isinstance(control, QPushButton):
            if control.text() == "Drawing":
                control.setIcon(QIcon(":/icons/draw"))
                control.setIconSize(QSize(24, 24))
                control.pressed.connect(partial(self.loadDrawingTool, control))
                self.boundControls.append(control)

        elif hasattr(control, 'loadImage'):
            image = value
            control.loadImage(image)
            self.boundControls.append(control)

        else:
            if (isinstance(control, QComboBox) and self.layer.editType(index)
                    == QgsVectorLayer.UniqueValuesEditable):

                for v in self.layer.dataProvider().uniqueValues(index):
                    control.addItem(v, v)

                control.setEditText(value)
                self.boundControls.append(control)

            try:
                # Remove the validator because there seems to be a bug with the
                # MS SQL layers and validators.
                control.setValidator(None)
            except AttributeError:
                pass

            QgsAttributeEditor.setValue(control, self.layer, index, value)

    def unbindFeature(self, feature):
        """
        Unbinds the feature from the form saving the values back to the QgsFeature.

        feature -- A QgsFeature that will store the new values.
        """
        for control in self.boundControls:
            name = control.objectName()
            if isinstance(control, QDateTimeEdit):
                value = control.dateTime().toString(Qt.ISODate)
                try:
                    feature[name] = value
                except KeyError as e:
                    log(e)
                    continue

            elif hasattr(control, 'getImage'):
                image = control.getImage()
                value = image
                try:
                    feature[name] = value
                except KeyError:
                    log("No field named " + name)
                    pass

        return feature

    def saveValues(self, feature):
        tosave = {}
        for field, shouldsave in self._getSaveButtons():
            log(field)
            log(shouldsave)
            if shouldsave:
                tosave[field] = feature[field]

        qmaplayer.setSavedValues(self.layer, tosave)

    def _getSaveButtons(self):
        buttons = self.forminstance.findChildren(QToolButton)
        for button in buttons:
            name = button.objectName()
            if name.endswith('_save'):
                yield name[:-5], button.isChecked()

    def loadDrawingTool(self, control):
        """
        Load the drawing tool.

        control - The control (QWidget) who owns this drawing.  Its name is used
                  in the naming of the final image.
        """
        raise NotImplementedError

        controlname = control.objectName()
        self.forminstance.hide()
        curdir = os.path.dirname(__file__)
        id = self.feature.attributeMap()[self.layer.fieldNameIndex("UniqueID")]
        savedname = str(id) + "_" + controlname + ".jpg"
        imagename = os.path.join(curdir, "data", self.layer.name(), "images", \
                                savedname)

        tempname = "drawingFor_{0}".format(controlname)
        tempimage = os.path.join(tempfile.gettempdir(), tempname)

        log("Looking for {0} or {1}".format(imagename, tempimage))
        imagetoload = self.images.get(controlname, imagename)

        drawingpad = DrawingPad(imagetoload)
        drawingpad.setWindowState(Qt.WindowFullScreen | Qt.WindowActive)
        drawingpad.ui.actionMapSnapshot.triggered.connect(
            partial(self.drawingPadMapSnapshot, drawingpad))
        if drawingpad.exec_():
            #Save the image to a temporay location until commit.
            self.images[controlname] = tempimage + ".png"
            drawingpad.saveImage(tempimage)
            self.forminstance.show()
        else:
            self.forminstance.show()

    def drawingPadMapSnapshot(self, pad):
        """
        Saves the current view of the map canvas to a image and it into the
        drawing pad.

        pad - The drawing pad that will take the final image.
        """
        #TODO Refactor me!!
        image = QPixmap.fromImage(pad.scribbleArea.image)
        tempimage = os.path.join(tempfile.gettempdir(), "mapcanvascapture.png")
        self.canvas.saveAsImage(tempimage, image)
        pad.openImage(tempimage)

    def pickDateTime(self, control, mode):
        """
        Open the date time picker dialog

        control - The control that will recive the user set date time.
        """
        log(mode)
        dlg = DateTimePickerDialog(mode)
        dlg.setWindowTitle("Select a date")
        if control.dateTime() == QDateTime(2000, 1, 1, 00, 00, 00, 0):
            dlg.setAsNow()
        else:
            dlg.setDateTime(control.dateTime())

        if dlg.exec_():
            if hasattr(control, 'setDate'):
                control.setDate(dlg.getSelectedDate())

            if hasattr(control, 'setTime'):
                control.setTime(dlg.getSelectedTime())

    def shouldSaveValue(self, control):
        try:
            button = self.getControl(control.objectName() + "_save",
                                     QToolButton)
        except ControlNotFound:
            return

        return button.isChecked()

    def bindSaveValueButton(self, control, defaults, editingmode=False):
        name = control.objectName()
        try:
            button = self.getControl("{}_save".format(name), QToolButton)
        except ControlNotFound:
            return

        button.setCheckable(not editingmode)
        button.setIcon(QIcon(":/icons/save_default"))
        button.setIconSize(QSize(24, 24))
        button.setChecked(name in defaults)
        button.setVisible(not editingmode)

    def bindSelectButtons(self):
        """
        Binds all the buttons on the form that need a select from map action.
        """
        tools = self.forminstance.findChildren(QToolButton,
                                               QRegExp('.*_mapselect'))
        layers = {l.name(): l for l in self.canvas.layers()}
        for tool in tools:
            try:
                control = self.getControl(tool.objectName()[:-10])
            except ControlNotFound as ex:
                warning(ex.message)
                tool.setEnabled(False)
                continue

            settings = tool.dynamicPropertyNames()
            if not 'from_layer' in settings or not 'using_column' in settings:
                warning('from_layer or using_column not found')
                tool.setEnabled(False)
                continue

            layer_name = tool.property('from_layer')
            column_name = tool.property('using_column')

            layer = None
            try:
                layer = layers[layer_name]
            except KeyError:
                warning('layer not found in list')
                tool.setEnabled(False)
                continue

            message = tool.property('message')
            if message.isEmpty():
                message = "Please select a feature in the map"

            radius, valid = tool.property('radius')
            if not valid:
                radius = 5

            tool.pressed.connect(
                partial(self.selectFeatureClicked, layer, column_name, message,
                        radius, control.objectName()))
            tool.setIcon(QIcon(":/icons/select"))
            tool.setIconSize(QSize(24, 24))

    def selectFeatureClicked(self, layer, column, message, searchsize, bindto):
        """
        Loads the select from map action tool. Switchs to the map to allow the
        user to select a feature.

        controlname - The control name when looking up in the settings for the
                      button config.
        """
        self.tool = SelectFeatureTool(self.canvas, layer, column, bindto,
                                      searchsize)
        self.tool.foundFeature.connect(self.bindHighlightedFeature)
        self.tool.setActive()
        self.beginSelectFeature.emit(message)

    def bindHighlightedFeature(self, feature, value, bindto):
        """
        Binds the selected features value to a control.
        """
        self.bindByName(bindto, value)
        self.endSelectFeature.emit()
Exemple #5
0
class FormBinder(QObject):
    beginSelectFeature = pyqtSignal(str)
    endSelectFeature = pyqtSignal()
    """
    Handles binding of values to and out of the form.
    
    TODO: This whole class is really messy and needs a good clean up.
    """
    def __init__(self, layer, formInstance, canvas):
        QObject.__init__(self)
        self.layer = layer
        self.canvas = canvas
        self.forminstance = formInstance
        self.images = {}
        self.mandatory_group = MandatoryGroup()
        self.boundControls = []

    def bindFeature(self, qgsfeature, mandatory_fields=True, editing=False):
        """
        Binds a features values to the form. If the control has the mandatory
        property set then it will be added to the mandatory group.

        qgsfeature - A QgsFeature to bind the values from
        mandatory_fields - True if mandatory fields should be respected (default)
        """
        self.feature = qgsfeature
        defaults = qmaplayer.getSavedValues(self.layer)
        
        for index in xrange(qgsfeature.fields().count()):
            value = qgsfeature[index]
            name = qgsfeature.fields()[index].name()
            
            try:
                control = self.getControl(name)
            except ControlNotFound as ex:
                warning(ex.message)
                continue

            if mandatory_fields:
                mandatory = control.property("mandatory")
                if mandatory:
                    buddy = self.getBuddy(control)
                    self.mandatory_group.addWidget(control, buddy)

            self.bindSaveValueButton(control, defaults, editingmode=editing)
            if not editing:
                try:
                    value = defaults[name]
                except KeyError:
                    pass

            try:
                self.bindValueToControl(control, value, index)
            except BindingError as er:
                warning(er.reason)

            self.createHelpLink(control)
            self.mandatory_group.validateAll()

    def createHelpLink(self, control):
        name = control.objectName()
        helpfile = qmaplayer.getHelpFile(self.layer, name)
        log(helpfile)
        log(name)
        if helpfile:
            label = self.getBuddy(control)
            if label is control: return
            if label is None: return
            text = '<a href="{}">{}<a>'.format(helpfile, label.text())
            label.setText(text)
            label.linkActivated.connect(self.showHelp)
    
    def showHelp(self, url):
        dlg = HelpViewDialog()
        dlg.loadFile(url)
        dlg.exec_()

    def getBuddy(self, control):
        try:
            label = self.getControl(control.objectName() + "_label", control_type=QLabel)
            return label
        except ControlNotFound:
            return control

    def getControl(self, name, control_type=QWidget):
        control = self.forminstance.findChild(control_type, name)
        if control is None:
            raise ControlNotFound(name)

        return control

    def bindByName(self, controlname, value):
        """
        Binds a value to a control based on the control name.

        controlname - Name of the control to bind
        value - QVariant holding the value.
        """
        control = self.getControl(controlname)

        try:
            self.bindValueToControl(control, value)
        except BindingError as er:
            warning(er.reason)

    def bindValueToControl(self, control, value, index=0):
        """
        Binds a control to the supplied value.

        control - QWidget based control that takes the new value
        value - A QVariant holding the value
        """
        if isinstance(control, QDateTimeEdit):
            # Can be removed after http://hub.qgis.org/issues/7013 is fixed.
            if isinstance(value, QDateTime):
                control.setDateTime(value)
            else:
                control.setDateTime(QDateTime.fromString(value, Qt.ISODate))
                
            try:
                button = self.getControl(control.objectName() + "_pick", QPushButton)
                button.setIcon(QIcon(":/icons/calender"))
                button.setText("Pick")
                button.setIconSize(QSize(24, 24))
                log("{} : {}".format(control.objectName(), type(control) is QDateEdit))
                if type(control) is QDateEdit:
                    log("Type is QDateEdit")
                    button.pressed.connect(partial(self.pickDateTime, control, "Date"))
                else:
                    button.pressed.connect(partial(self.pickDateTime, control, "DateTime"))
                    
            except ControlNotFound:
                pass
            
            self.boundControls.append(control)

        elif isinstance(control, QPushButton):
            if control.text() == "Drawing":
                control.setIcon(QIcon(":/icons/draw"))
                control.setIconSize(QSize(24, 24))
                control.pressed.connect(partial(self.loadDrawingTool, control))
                self.boundControls.append(control)
                
        elif hasattr(control, 'loadImage'):
            image = value
            control.loadImage(image)
            self.boundControls.append(control)
            
        else:
            if (isinstance(control, QComboBox) and
                self.layer.editType(index) == QgsVectorLayer.UniqueValuesEditable):
                
                for v in self.layer.dataProvider().uniqueValues(index):
                    control.addItem(v, v)
                                    
                control.setEditText(value)
                self.boundControls.append(control)
                
            try:
                # Remove the validator because there seems to be a bug with the 
                # MS SQL layers and validators.
                control.setValidator(None)
            except AttributeError:
                pass
            
            QgsAttributeEditor.setValue(control, self.layer, index, value)

    def unbindFeature(self, feature):
        """
        Unbinds the feature from the form saving the values back to the QgsFeature.

        feature -- A QgsFeature that will store the new values.
        """
        for control in self.boundControls:
            name = control.objectName()
            if isinstance(control, QDateTimeEdit):
                value = control.dateTime().toString(Qt.ISODate)
                try:
                    feature[name] = value
                except KeyError as e:
                    log(e)
                    continue
                
            elif hasattr(control, 'getImage'):
                image = control.getImage()
                value = image
                try:
                    feature[name] = value
                except KeyError:
                    log("No field named " + name)
                    pass  
                   
        return feature
    
    def saveValues(self, feature):
        tosave = {}
        for field, shouldsave in self._getSaveButtons():
            log(field)
            log(shouldsave)
            if shouldsave:
                tosave[field] = feature[field]
                    
        qmaplayer.setSavedValues(self.layer, tosave)
        
    def _getSaveButtons(self):
        buttons = self.forminstance.findChildren(QToolButton)
        for button in buttons:
            name = button.objectName()
            if name.endswith('_save'):
                yield name[:-5], button.isChecked()


    def loadDrawingTool(self, control):
        """
        Load the drawing tool.

        control - The control (QWidget) who owns this drawing.  Its name is used
                  in the naming of the final image.
        """
        raise NotImplementedError
    
        controlname = control.objectName()
        self.forminstance.hide()
        curdir = os.path.dirname(__file__)
        id = self.feature.attributeMap()[self.layer.fieldNameIndex("UniqueID")]
        savedname = str(id) + "_" + controlname + ".jpg"
        imagename = os.path.join(curdir, "data", self.layer.name(), "images", \
                                savedname)

        tempname = "drawingFor_{0}".format(controlname)
        tempimage = os.path.join(tempfile.gettempdir(), tempname)

        log("Looking for {0} or {1}".format(imagename, tempimage))
        imagetoload = self.images.get(controlname, imagename)

        drawingpad = DrawingPad(imagetoload)
        drawingpad.setWindowState(Qt.WindowFullScreen | Qt.WindowActive)
        drawingpad.ui.actionMapSnapshot.triggered.connect(partial(self.drawingPadMapSnapshot, drawingpad))
        if drawingpad.exec_():
            #Save the image to a temporay location until commit.
            self.images[controlname] = tempimage + ".png"
            drawingpad.saveImage(tempimage)
            self.forminstance.show()
        else:
            self.forminstance.show()

    def drawingPadMapSnapshot(self, pad):
        """
        Saves the current view of the map canvas to a image and it into the
        drawing pad.

        pad - The drawing pad that will take the final image.
        """
        #TODO Refactor me!!
        image = QPixmap.fromImage(pad.scribbleArea.image)
        tempimage = os.path.join(tempfile.gettempdir(), "mapcanvascapture.png")
        self.canvas.saveAsImage(tempimage, image)
        pad.openImage(tempimage)

    def pickDateTime(self, control, mode):
        """
        Open the date time picker dialog

        control - The control that will recive the user set date time.
        """
        log(mode)
        dlg = DateTimePickerDialog(mode)
        dlg.setWindowTitle("Select a date")
        if control.dateTime() == QDateTime(2000, 1, 1, 00, 00, 00, 0):
            dlg.setAsNow()
        else:
            dlg.setDateTime(control.dateTime())

        if dlg.exec_():
            if hasattr(control, 'setDate'):
                control.setDate(dlg.getSelectedDate())

            if hasattr(control, 'setTime'):
                control.setTime(dlg.getSelectedTime())

    def shouldSaveValue(self, control):
        try:
            button = self.getControl(control.objectName() + "_save", QToolButton)
        except ControlNotFound:
            return

        return button.isChecked()

    def bindSaveValueButton(self, control, defaults, editingmode=False):
        name = control.objectName()
        try:
            button = self.getControl("{}_save".format(name), QToolButton)
        except ControlNotFound:
            return

        button.setCheckable(not editingmode)
        button.setIcon(QIcon(":/icons/save_default"))
        button.setIconSize(QSize(24, 24))
        button.setChecked(name in defaults)
        button.setVisible(not editingmode)

    def bindSelectButtons(self):
        """
        Binds all the buttons on the form that need a select from map action.
        """
        tools = self.forminstance.findChildren(QToolButton, QRegExp('.*_mapselect'))
        layers = {l.name(): l for l in self.canvas.layers()}
        for tool in tools:
            try:
                control = self.getControl(tool.objectName()[:-10])
            except ControlNotFound as ex:
                warning(ex.message)
                tool.setEnabled(False)
                continue

            settings = tool.dynamicPropertyNames()
            if not 'from_layer' in settings or not 'using_column' in settings:
                warning('from_layer or using_column not found')
                tool.setEnabled(False)
                continue

            layer_name = tool.property('from_layer')
            column_name = tool.property('using_column')

            layer = None
            try:
                layer = layers[layer_name]
            except KeyError:
                warning('layer not found in list')
                tool.setEnabled(False)
                continue

            message = tool.property('message')
            if message.isEmpty():
                message = "Please select a feature in the map"

            radius, valid = tool.property('radius')
            if not valid:
                radius = 5

            tool.pressed.connect(partial(self.selectFeatureClicked,
                                                      layer,
                                                      column_name,
                                                      message,
                                                      radius,
                                                      control.objectName()))
            tool.setIcon(QIcon(":/icons/select"))
            tool.setIconSize(QSize(24, 24))

    def selectFeatureClicked(self, layer, column, message, searchsize, bindto):
        """
        Loads the select from map action tool. Switchs to the map to allow the
        user to select a feature.

        controlname - The control name when looking up in the settings for the
                      button config.
        """
        self.tool = SelectFeatureTool(self.canvas, layer, column, bindto, searchsize)
        self.tool.foundFeature.connect(self.bindHighlightedFeature)
        self.tool.setActive()
        self.beginSelectFeature.emit(message)

    def bindHighlightedFeature(self, feature, value, bindto):
        """
        Binds the selected features value to a control.
        """
        self.bindByName(bindto, value)
        self.endSelectFeature.emit()
Exemple #6
0
class FormBinder(QObject):
    beginSelectFeature = pyqtSignal(str)
    endSelectFeature = pyqtSignal()
    """
    Handles binding of values to and out of the form.
    """

    def __init__(self, layer, formInstance, canvas, settings, form):
        QObject.__init__(self)
        self.layer = layer
        self.canvas = canvas
        self.forminstance = formInstance
        self.fields = self.layer.pendingFields()
        self.fieldtocontrol = {}
        self.actionlist = []
        self.settings = settings
        self.images = {}
        self.mandatory_group = MandatoryGroup()
        self.form = form

    def bindFeature(self, qgsfeature, mandatory_fields=True, editing=False):
        """
        Binds a features values to the form. If the control has the mandatory
        property set then it will be added to the mandatory group.

        qgsfeature - A QgsFeature to bind the values from
        mandatory_fields - True if mandatory fields should be respected (default)
        """
        self.feature = qgsfeature
        defaults = self.form.getSavedValues()

        for index, value in qgsfeature.attributeMap().items():
            name = str(self.fields[index].name())

            try:
                control = self.getControl(name)
            except ControlNotFound as ex:
                warning(ex.message)
                continue

            if mandatory_fields:
                mandatory = control.property("mandatory").toBool()
                if mandatory:
                    buddy = self.getBuddy(control)
                    self.mandatory_group.addWidget(control, buddy)

            info("Binding %s to %s" % (control.objectName(), value.toString()))

            self.bindSaveValueButton(control, defaults, editingmode=editing)
            if not editing:
                try:
                    value = defaults[name]
                except KeyError:
                    pass

            try:
                self.bindValueToControl(control, value, index)
            except BindingError as er:
                warning(er.reason)

            self.createHelpLink(control)

            self.fieldtocontrol[index] = control

    def createHelpLink(self, control):
        name = control.objectName()
        helpfile = self.form.getHelpFile(name)
        if helpfile:
            label = self.getBuddy(control)
            if label is control:
                return
            if label is None:
                return
            text = '<a href="%s">%s<a>' % (helpfile, label.text())
            label.setText(text)
            label.linkActivated.connect(self.showHelp)

    def showHelp(self, url):
        dlg = HelpViewDialog()
        dlg.loadFile(url)
        dlg.exec_()

    def getBuddy(self, control):
        try:
            label = self.getControl(control.objectName() + "_label", control_type=QLabel)
            return label
        except ControlNotFound:
            return control

    def getControl(self, name, control_type=QWidget):
        control = self.forminstance.findChild(control_type, name)
        if control is None:
            raise ControlNotFound(name)

        return control

    def bindByName(self, controlname, value):
        """
        Binds a value to a control based on the control name.

        controlname - Name of the control to bind
        value - QVariant holding the value.
        """
        control = self.getControl(controlname)

        try:
            self.bindValueToControl(control, value)
        except BindingError as er:
            warning(er.reason)

    def bindValueToControl(self, control, value, index=0):
        """
        Binds a control to the supplied value.

        control - QWidget based control that takes the new value
        value - A QVariant holding the value
        """
        if isinstance(control, QDateTimeEdit):
            # Can be removed after http://hub.qgis.org/issues/7013 is fixed.
            control.setDateTime(QDateTime.fromString(value.toString(), Qt.ISODate))
            button = self.getControl(control.objectName() + "_pick", QPushButton)
            if not button:
                return

            button.setIcon(QIcon(":/icons/calender"))
            button.setText("Pick")
            button.setIconSize(QSize(24, 24))
            button.pressed.connect(partial(self.pickDateTime, control, "DateTime"))

        elif isinstance(control, QPushButton):
            if control.text() == "Drawing":
                control.setIcon(QIcon(":/icons/draw"))
                control.setIconSize(QSize(24, 24))
                control.pressed.connect(partial(self.loadDrawingTool, control))
        else:
            if self.layer.editType(index) == QgsVectorLayer.UniqueValues:
                editable = control.isEditable()

            widget = QgsAttributeEditor.createAttributeEditor(self.forminstance, control, self.layer, index, value)
            wasset = QgsAttributeEditor.setValue(control, self.layer, index, value)
            log(widget)

            try:
                control.setValidator(None)
            except AttributeError:
                pass

            if self.layer.editType(index) == QgsVectorLayer.UniqueValues:
                # Set the control back to the editable state the form says it should be.
                # This is to work around http://hub.qgis.org/issues/7012
                control.setEditable(editable)

    def unbindFeature(self, qgsfeature, editingmode=False):
        """
        Unbinds the feature from the form saving the values back to the QgsFeature.

        qgsfeature -- A QgsFeature that will store the new values.
        """
        savefields = []
        for index, control in self.fieldtocontrol.items():
            value = QVariant()
            if isinstance(control, QDateTimeEdit):
                value = control.dateTime().toString(Qt.ISODate)
            else:
                if self.layer.editType(index) == QgsVectorLayer.UniqueValues and control.isEditable():
                    # Due to http://hub.qgis.org/issues/7012 we can't have editable
                    # comboxs using QgsAttributeEditor. If the value isn't in the
                    # dataset already it will return null.  Until that bug is fixed
                    # we are just going to handle ourself.
                    value = control.currentText()
                else:
                    modified = QgsAttributeEditor.retrieveValue(control, self.layer, index, value)

            info("Setting value to %s from %s" % (value, control.objectName()))
            qgsfeature.changeAttribute(index, value)

            # Save the value to the database as a default if it is needed.
            if self.shouldSaveValue(control):
                savefields.append(index)

        if not editingmode:
            m = qgsfeature.attributeMap()
            fields_map = self.layer.pendingFields()
            attr = {str(fields_map[k].name()): str(v.toString()) for k, v in m.items() if k in savefields}
            self.form.setSavedValues(attr)

        return qgsfeature

    def loadDrawingTool(self, control):
        """
        Load the drawing tool.

        control - The control (QWidget) who owns this drawing.  Its name is used
                  in the naming of the final image.
        """
        controlname = str(control.objectName())
        self.forminstance.hide()
        curdir = os.path.dirname(__file__)
        id = self.feature.attributeMap()[self.layer.fieldNameIndex("UniqueID")].toString()
        savedname = str(id) + "_" + controlname + ".jpg"
        imagename = os.path.join(curdir, "data", str(self.layer.name()), "images", savedname)

        tempname = "drawingFor_{0}".format(controlname)
        tempimage = os.path.join(tempfile.gettempdir(), tempname)

        log("Looking for {0} or {1}".format(imagename, tempimage))
        imagetoload = self.images.get(controlname, imagename)

        drawingpad = DrawingPad(imagetoload)
        drawingpad.setWindowState(Qt.WindowFullScreen | Qt.WindowActive)
        drawingpad.ui.actionMapSnapshot.triggered.connect(partial(self.drawingPadMapSnapshot, drawingpad))
        if drawingpad.exec_():
            # Save the image to a temporay location until commit.
            self.images[controlname] = tempimage + ".png"
            drawingpad.saveImage(tempimage)
            self.forminstance.show()
        else:
            self.forminstance.show()

    def drawingPadMapSnapshot(self, pad):
        """
        Saves the current view of the map canvas to a image and it into the
        drawing pad.

        pad - The drawing pad that will take the final image.
        """
        # TODO Refactor me!!
        image = QPixmap.fromImage(pad.scribbleArea.image)
        tempimage = os.path.join(tempfile.gettempdir(), "mapcanvascapture.png")
        self.canvas.saveAsImage(tempimage, image)
        pad.openImage(tempimage)

    def pickDateTime(self, control, mode):
        """
        Open the date time picker dialog

        control - The control that will recive the user set date time.
        """
        dlg = DateTimePickerDialog(mode)
        dlg.setWindowTitle("Select a date")
        if control.dateTime() == QDateTime(2000, 1, 1, 00, 00, 00, 0):
            dlg.setAsNow()
        else:
            dlg.setDateTime(control.dateTime())

        if dlg.exec_():
            if hasattr(control, "setDate"):
                control.setDate(dlg.getSelectedDate())

            if hasattr(control, "setTime"):
                control.setTime(dlg.getSelectedTime())

    def shouldSaveValue(self, control):
        try:
            button = self.getControl(control.objectName() + "_save", QToolButton)
        except ControlNotFound:
            return

        return button.isChecked()

    def bindSaveValueButton(self, control, defaults, editingmode=False):
        name = str(control.objectName())
        try:
            button = self.getControl(name + "_save", QToolButton)
        except ControlNotFound:
            return

        button.setCheckable(not editingmode)
        button.setIcon(QIcon(":/icons/save_default"))
        button.setIconSize(QSize(24, 24))
        button.setChecked(name in defaults)
        button.setVisible(not editingmode)

    def bindSelectButtons(self):
        """
        Binds all the buttons on the form that need a select from map action.
        """
        tools = self.forminstance.findChildren(QToolButton, QRegExp(".*_mapselect"))
        log(tools)
        layers = {QString(l.name()): l for l in self.canvas.layers()}
        log(layers)
        for tool in tools:
            try:
                control = self.getControl(tool.objectName()[:-10])
            except ControlNotFound as ex:
                warning(ex.message)
                tool.setEnabled(False)
                continue

            settings = tool.dynamicPropertyNames()
            if not "from_layer" in settings or not "using_column" in settings:
                warning("from_layer or using_column not found")
                tool.setEnabled(False)
                continue

            layer_name = tool.property("from_layer").toString()
            column_name = tool.property("using_column").toString()

            layer = None
            try:
                layer = layers[QString(layer_name)]
            except KeyError:
                warning("layer not found in list")
                tool.setEnabled(False)
                continue

            message = tool.property("message").toString()
            if message.isEmpty():
                message = "Please select a feature in the map"

            radius, valid = tool.property("radius").toInt()
            if not valid:
                radius = 5

            tool.pressed.connect(
                partial(self.selectFeatureClicked, layer, column_name, message, radius, control.objectName())
            )
            tool.setIcon(QIcon(":/icons/select"))
            tool.setIconSize(QSize(24, 24))

    def selectFeatureClicked(self, layer, column, message, searchsize, bindto):
        """
        Loads the select from map action tool. Switchs to the map to allow the
        user to select a feature.

        controlname - The control name when looking up in the settings for the
                      button config.
        """
        self.tool = SelectFeatureTool(self.canvas, layer, column, bindto, searchsize)
        self.tool.foundFeature.connect(self.bindHighlightedFeature)
        self.tool.setActive()
        self.beginSelectFeature.emit(message)

    def bindHighlightedFeature(self, feature, value, bindto):
        """
        Binds the selected features value to a control.
        """
        self.bindByName(bindto, value)
        self.endSelectFeature.emit()
Exemple #7
0
class FormBinder(QObject):
    beginSelectFeature = pyqtSignal(str)
    endSelectFeature = pyqtSignal()
    """
    Handles binding of values to and out of the form.
    
    TODO: This whole class is really messy and needs a good clean up.
    """
    def __init__(self, layer, formInstance, canvas):
        QObject.__init__(self)
        self.layer = layer
        self.canvas = canvas
        self.forminstance = formInstance
        self.images = {}
        self.mandatory_group = MandatoryGroup()
        self.boundControls = []


    def loadDrawingTool(self, control):
        """
        Load the drawing tool.

        control - The control (QWidget) who owns this drawing.  Its name is used
                  in the naming of the final image.
        """
        raise NotImplementedError
    
        controlname = control.objectName()
        self.forminstance.hide()
        curdir = os.path.dirname(__file__)
        id = self.feature.attributeMap()[self.layer.fieldNameIndex("UniqueID")]
        savedname = str(id) + "_" + controlname + ".jpg"
        imagename = os.path.join(curdir, "data", self.layer.name(), "images", \
                                savedname)

        tempname = "drawingFor_{0}".format(controlname)
        tempimage = os.path.join(tempfile.gettempdir(), tempname)

        log("Looking for {0} or {1}".format(imagename, tempimage))
        imagetoload = self.images.get(controlname, imagename)

        drawingpad = DrawingPad(imagetoload)
        drawingpad.setWindowState(Qt.WindowFullScreen | Qt.WindowActive)
        drawingpad.ui.actionMapSnapshot.triggered.connect(partial(self.drawingPadMapSnapshot, drawingpad))
        if drawingpad.exec_():
            #Save the image to a temporay location until commit.
            self.images[controlname] = tempimage + ".png"
            drawingpad.saveImage(tempimage)
            self.forminstance.show()
        else:
            self.forminstance.show()

    def drawingPadMapSnapshot(self, pad):
        """
        Saves the current view of the map canvas to a image and it into the
        drawing pad.

        pad - The drawing pad that will take the final image.
        """
        #TODO Refactor me!!
        image = QPixmap.fromImage(pad.scribbleArea.image)
        tempimage = os.path.join(tempfile.gettempdir(), "mapcanvascapture.png")
        self.canvas.saveAsImage(tempimage, image)
        pad.openImage(tempimage)

    def bindSelectButtons(self):
        """
        Binds all the buttons on the form that need a select from map action.
        """
        tools = self.forminstance.findChildren(QToolButton, QRegExp('.*_mapselect'))
        layers = {l.name(): l for l in self.canvas.layers()}
        for tool in tools:
            try:
                control = self.getControl(tool.objectName()[:-10])
            except ControlNotFound as ex:
                warning(ex.message)
                tool.setEnabled(False)
                continue

            settings = tool.dynamicPropertyNames()
            if not 'from_layer' in settings or not 'using_column' in settings:
                warning('from_layer or using_column not found')
                tool.setEnabled(False)
                continue

            layer_name = tool.property('from_layer')
            column_name = tool.property('using_column')

            layer = None
            try:
                layer = layers[layer_name]
            except KeyError:
                warning('layer not found in list')
                tool.setEnabled(False)
                continue

            message = tool.property('message')
            if message.isEmpty():
                message = "Please select a feature in the map"

            radius, valid = tool.property('radius')
            if not valid:
                radius = 5

            tool.pressed.connect(partial(self.selectFeatureClicked,
                                                      layer,
                                                      column_name,
                                                      message,
                                                      radius,
                                                      control.objectName()))
            tool.setIcon(QIcon(":/icons/select"))
            tool.setIconSize(QSize(24, 24))

    def selectFeatureClicked(self, layer, column, message, searchsize, bindto):
        """
        Loads the select from map action tool. Switchs to the map to allow the
        user to select a feature.

        controlname - The control name when looking up in the settings for the
                      button config.
        """
        self.tool = SelectFeatureTool(self.canvas, layer, column, bindto, searchsize)
        self.tool.foundFeature.connect(self.bindHighlightedFeature)
        self.tool.setActive()
        self.beginSelectFeature.emit(message)

    def bindHighlightedFeature(self, feature, value, bindto):
        """
        Binds the selected features value to a control.
        """
        self.bindByName(bindto, value)
        self.endSelectFeature.emit()