def test_is_valid_sg_code(self):
        """Test for is_valid_sg_code."""

        self.assertTrue(is_valid_sg_code('C01900000000026300000'))
        self.assertTrue(is_valid_sg_code('B01900000000026300000'))

        # issue #20
        self.assertTrue(is_valid_sg_code('T0JP00000000010800008'))

        self.assertFalse(is_valid_sg_code('Foo'))
        # Too long
        self.assertFalse(is_valid_sg_code('B019000000000263000000'))
        # Too short
        self.assertFalse(is_valid_sg_code('B01900000000026300'))
        # not valid regex
        self.assertFalse(is_valid_sg_code('C0190000000002630000X'))
        # Null
        # noinspection PyUnresolvedReferences
        null_variant = QtCore.QPyNullVariant(str)
        self.assertFalse(is_valid_sg_code(null_variant))

        # unicode
        unicode_sg_code = unicode('B01900000000026300000')
        self.assertTrue(is_valid_sg_code(unicode_sg_code))
        unicode_sg_code = unicode('B0190000000002630000X')
        self.assertFalse(is_valid_sg_code(unicode_sg_code))
    def test_is_valid_sg_code(self):
        """Test for is_valid_sg_code."""

        self.assertTrue(is_valid_sg_code('C01900000000026300000'))
        self.assertTrue(is_valid_sg_code('B01900000000026300000'))

        # issue #20
        self.assertTrue(is_valid_sg_code('T0JP00000000010800008'))

        self.assertFalse(is_valid_sg_code('Foo'))
        # Too long
        self.assertFalse(is_valid_sg_code('B019000000000263000000'))
        # Too short
        self.assertFalse(is_valid_sg_code('B01900000000026300'))
        # not valid regex
        self.assertFalse(is_valid_sg_code('C0190000000002630000X'))
        # Null
        # noinspection PyUnresolvedReferences
        null_variant = QtCore.QPyNullVariant(str)
        self.assertFalse(is_valid_sg_code(null_variant))

        # unicode
        unicode_sg_code = unicode('B01900000000026300000')
        self.assertTrue(is_valid_sg_code(unicode_sg_code))
        unicode_sg_code = unicode('B0190000000002630000X')
        self.assertFalse(is_valid_sg_code(unicode_sg_code))
    def canvasReleaseEvent(self, event):
        """Slot called when the mouse button is released on the canvas.

        :param event: Canvas event containing position of click, which button
            was clicked etc.
        """
        if not event.button() == Qt.LeftButton:
            return

        def progress_callback(current, maximum, message=None):
            """GUI based callback implementation for showing progress.

            :param current: Current progress.
            :type current: int

            :param maximum: Maximum range (point at which task is complete.
            :type maximum: int

            :param message: Optional message to display in the progress bar
            :type message: str, QString
            """
            if message is not None:
                self.message_bar.setText(message)
            if self.progress_bar is not None:
                self.progress_bar.setMaximum(maximum)
                self.progress_bar.setValue(current)

        self.iface.messageBar().pushMessage(
            self.tr('SG Downloader.'),
            self.tr('Preparing for download'),
            level=QgsMessageBar.INFO)

        # No need to check that it is a valid, polygon layer
        # as the QAction for this map tool already does that
        layer = self.canvas.currentLayer()

        place = self.toMapCoordinates(event.pos())
        rectangle = point_to_rectangle(place)

        request = QgsFeatureRequest(QgsFeatureRequest.FilterRect)
        # Ensure only those features really intersecting the rect are returned
        request.setFlags(QgsFeatureRequest.ExactIntersect)
        request.setFilterRect(rectangle)
        polygons = layer.getFeatures(request)
        feature = QgsFeature()
        fetch_list = []
        all_fields = layer.pendingFields()
        text_fields = []

        # Ignore any columns that don't contain text data
        for field in all_fields:
            if field.typeName() == 'TEXT':
                text_fields.append(field)

        self.setup_messagebar()

        sg_field = None
        while polygons.nextFeature(feature):
            geom = feature.geometry()
            attributes = feature.attributes()
            matched = False
            sg_code = None
            if sg_field is None:
                for field in text_fields:
                    value = str(feature[field.name()])
                    if not is_valid_sg_code(value):
                        continue
                    sg_field = field.name()
                    fetch_list.append(value)
            else:
                # We already know which column has SG codes
                value = str(feature[sg_field])
                fetch_list.append(value)

        if len(fetch_list) == 0:
            self.iface.messageBar().pushMessage(
                self.tr('SG Downloader.'),
                self.tr('No parcels found with a valid 21 Digit code'),
                level=QgsMessageBar.WARNING,
                duration=10)
            return

        province = province_for_point(place, self.provinces_layer)
        result = ''
        output_path = diagram_directory()

        for sg_code in fetch_list:
            result += download_sg_diagram(
                sg_code,
                province,
                output_path,
                progress_callback)

        log = file('sg_downloader.log', 'a')
        log.write(result)
        log.close()
    def canvasReleaseEvent(self, event):
        """Slot called when the mouse button is released on the canvas.

        :param event: Canvas event containing position of click, which button
            was clicked etc.
        """
        if not event.button() == Qt.LeftButton:
            return

        def progress_callback(current, maximum, message=None):
            """GUI based callback implementation for showing progress.

            :param current: Current progress.
            :type current: int

            :param maximum: Maximum range (point at which task is complete.
            :type maximum: int

            :param message: Optional message to display in the progress bar
            :type message: str, QString
            """
            if message is not None:
                self.message_bar.setText(message)
            if self.progress_bar is not None:
                self.progress_bar.setMaximum(maximum)
                self.progress_bar.setValue(current)

        self.iface.messageBar().pushMessage(self.tr('SG Downloader.'),
                                            self.tr('Preparing for download'),
                                            level=QgsMessageBar.INFO,
                                            duration=10)

        # No need to check that it is a valid, polygon layer
        # as the QAction for this map tool already does that
        layer = self.canvas.currentLayer()

        place = self.toMapCoordinates(event.pos())
        rectangle = point_to_rectangle(place)

        request = QgsFeatureRequest(QgsFeatureRequest.FilterRect)
        # Ensure only those features really intersecting the rect are returned
        request.setFlags(QgsFeatureRequest.ExactIntersect)
        request.setFilterRect(rectangle)
        polygons = layer.getFeatures(request)
        feature = QgsFeature()
        fetch_list = []
        all_fields = layer.pendingFields()
        text_fields = []
        # Ignore any columns that don't contain text data
        for field in all_fields:
            if field.typeName() == 'String' or field.typeName() == 'Text':
                text_fields.append(field)

        self.setup_message_bar()
        sg_field = None
        while polygons.nextFeature(feature):
            # geom = feature.geometry()
            # attributes = feature.attributes()
            # matched = False
            # sg_code = None
            if sg_field is None:
                for field in text_fields:
                    value = str(feature[field.name()])
                    if not is_valid_sg_code(value):
                        continue
                    sg_field = field.name()
                    fetch_list.append(value)
            else:
                # We already know which column has SG codes
                value = str(feature[sg_field])
                fetch_list.append(value)
        if len(fetch_list) == 0:
            self.iface.messageBar().pushMessage(
                self.tr('SG Downloader.'),
                self.tr('No parcels found with a valid 21 Digit code'),
                level=QgsMessageBar.WARNING,
                duration=10)
            return

        province = province_for_point(self.db_manager, place)

        report = ''
        sg_diagrams_database = os.path.join(DATA_DIR, 'sg_diagrams.sqlite')
        data_manager = DatabaseManager(sg_diagrams_database)

        i = 0
        for sg_code in fetch_list:
            i += 1
            message = 'Downloading SG Code %s from %s' % (sg_code, province)
            progress_callback(i, len(fetch_list), message)
            report += download_sg_diagram(data_manager,
                                          sg_code,
                                          province,
                                          self.output_directory,
                                          callback=progress_callback)
        data_manager.close()

        try:
            write_log(report, self.log_file)
        except IOError as e:
            print e

        self.show_log(report, self.log_file)