Example #1
0
    def handle(self, *args, **options):
        minx = options['minx']
        miny = options['miny']
        maxx = options['maxx']
        maxy = options['maxy']

        if minx >= maxx:
            raise CommandError(_('minx has to be lower than maxx'))
        if miny >= maxy:
            raise CommandError(_('miny has to be lower than maxy'))

        width = maxx-minx
        height = maxy-miny

        model = {'areas': Area, 'obstacles': Obstacle}[options['type']]

        namespaces = {'svg': 'http://www.w3.org/2000/svg'}

        svg = ElementTree.fromstring(options['svgfile'].read())
        svg_width = float(svg.attrib['width'])
        svg_height = float(svg.attrib['height'])

        for element in svg.findall('.//svg:clipPath/..', namespaces):
            for clippath in element.findall('./svg:clipPath', namespaces):
                element.remove(clippath)

        for element in svg.findall('.//svg:symbol/..', namespaces):
            for clippath in element.findall('./svg:symbol', namespaces):
                element.remove(clippath)

        if svg.findall('.//*[@transform]'):
            raise CommandError(_('svg contains transform attributes. Use inkscape apply transforms.'))

        if model.objects.filter(space=options['space'], import_tag=options['name']).exists():
            raise CommandError(_('objects with this import tag already exist in this space.'))

        with MapUpdate.lock():
            changed_geometries.reset()
            for path in svg.findall('.//svg:path', namespaces):
                for polygon in self.parse_svg_data(path.attrib['d']):
                    if len(polygon) < 3:
                        continue
                    polygon = Polygon(polygon)
                    polygon = scale(polygon, xfact=1, yfact=-1, origin=(0, svg_height/2))
                    polygon = scale(polygon, xfact=width / svg_width, yfact=height / svg_height, origin=(0, 0))
                    polygon = translate(polygon, xoff=minx, yoff=miny)
                    obj = model(geometry=polygon, space=options['space'], import_tag=options['name'])
                    obj.save()
            MapUpdate.objects.create(type='importsvg')

        logger = logging.getLogger('c3nav')
        logger.info('Imported, map update created.')
        logger.info('Next step: go into the shell and edit them using '
                    '%s.objects.filter(space_id=%r, import_tag=%r)' %
                    (model.__name__, options['space'].pk, options['name']))
Example #2
0
    def handle(self, *args, **options):
        minx = options['minx']
        miny = options['miny']
        maxx = options['maxx']
        maxy = options['maxy']

        if minx >= maxx:
            raise CommandError(_('minx has to be lower than maxx'))
        if miny >= maxy:
            raise CommandError(_('miny has to be lower than maxy'))

        width = maxx-minx
        height = maxy-miny

        model = {'areas': Area, 'obstacles': Obstacle}[options['type']]

        namespaces = {'svg': 'http://www.w3.org/2000/svg'}

        svg = ElementTree.fromstring(options['svgfile'].read())
        svg_width = float(svg.attrib['width'])
        svg_height = float(svg.attrib['height'])

        for element in svg.findall('.//svg:clipPath/..', namespaces):
            for clippath in element.findall('./svg:clipPath', namespaces):
                element.remove(clippath)

        for element in svg.findall('.//svg:symbol/..', namespaces):
            for clippath in element.findall('./svg:symbol', namespaces):
                element.remove(clippath)

        if svg.findall('.//*[@transform]'):
            raise CommandError(_('svg contains transform attributes. Use inkscape apply transforms.'))

        if model.objects.filter(space=options['space'], import_tag=options['name']).exists():
            raise CommandError(_('objects with this import tag already exist in this space.'))

        with MapUpdate.lock():
            changed_geometries.reset()
            for path in svg.findall('.//svg:path', namespaces):
                for polygon in self.parse_svg_data(path.attrib['d']):
                    if len(polygon) < 3:
                        continue
                    polygon = Polygon(polygon)
                    polygon = scale(polygon, xfact=1, yfact=-1, origin=(0, svg_height/2))
                    polygon = scale(polygon, xfact=width / svg_width, yfact=height / svg_height, origin=(0, 0))
                    polygon = translate(polygon, xoff=minx, yoff=miny)
                    obj = model(geometry=polygon, space=options['space'], import_tag=options['name'])
                    obj.save()
            MapUpdate.objects.create(type='importsvg')

        logger = logging.getLogger('c3nav')
        logger.info('Imported, map update created.')
        logger.info('Next step: go into the shell and edit them using '
                    '%s.objects.filter(space_id=%r, import_tag=%r)' %
                    (model.__name__, options['space'].pk, options['name']))
Example #3
0
    def lock_to_edit(self, request=None):
        with transaction.atomic():
            user = request.user if request is not None and request.user.is_authenticated else None
            if self.pk is not None:
                changeset = ChangeSet.objects.select_for_update().get(pk=self.pk)

                self._object_changed = False
                yield changeset
                if self._object_changed:
                    update = changeset.updates.create(user=user, objects_changed=True)
                    changeset.last_update = update
                    changeset.last_change = update
                    changeset.save()
            elif self.direct_editing:
                with MapUpdate.lock():
                    changed_geometries.reset()
                    ChangeSet.objects_changed_count = 0
                    yield self
                    if ChangeSet.objects_changed_count:
                        MapUpdate.objects.create(user=user, type='direct_edit')
            else:
                yield self
Example #4
0
    def lock_to_edit(self, request=None):
        with transaction.atomic():
            user = request.user if request is not None and request.user.is_authenticated else None
            if self.pk is not None:
                changeset = ChangeSet.objects.select_for_update().get(pk=self.pk)

                self._object_changed = False
                yield changeset
                if self._object_changed:
                    update = changeset.updates.create(user=user, objects_changed=True)
                    changeset.last_update = update
                    changeset.last_change = update
                    changeset.save()
            elif self.direct_editing:
                with MapUpdate.lock():
                    changed_geometries.reset()
                    ChangeSet.objects_changed_count = 0
                    yield self
                    if ChangeSet.objects_changed_count:
                        MapUpdate.objects.create(user=user, type='direct_edit')
            else:
                yield self
Example #5
0
    def apply(self, user):
        with MapUpdate.lock():
            changed_geometries.reset()

            self._clean_changes()
            changed_objects = self.relevant_changed_objects()
            created_objects = []
            existing_objects = []
            for changed_object in changed_objects:
                (created_objects if changed_object.is_created else existing_objects).append(changed_object)

            objects = self.get_objects(changed_objects=changed_objects)

            # remove slugs on all changed existing objects
            slugs_updated = set(changed_object.obj_pk for changed_object in existing_objects
                                if (issubclass(changed_object.model_class, LocationSlug) and
                                    'slug' in changed_object.updated_fields))
            LocationSlug.objects.filter(pk__in=slugs_updated).update(slug=None)

            redirects_deleted = set(changed_object.obj_pk for changed_object in existing_objects
                                    if (issubclass(changed_object.model_class, LocationRedirect) and
                                        changed_object.deleted))
            LocationRedirect.objects.filter(pk__in=redirects_deleted).delete()

            # create created objects
            created_pks = {}
            objects_to_create = set(created_objects)
            while objects_to_create:
                created_in_last_run = set()
                for created_object in objects_to_create:
                    model = created_object.model_class
                    pk = created_object.obj_pk

                    # lets try to create this object
                    obj = model()
                    try:
                        created_object.apply_to_instance(obj, created_pks=created_pks)
                    except ApplyToInstanceError:
                        continue

                    obj.save()
                    created_in_last_run.add(created_object)
                    created_pks.setdefault(model, {})[pk] = obj.pk
                    objects.setdefault(model, {})[pk] = obj

                objects_to_create -= created_in_last_run

            # update existing objects
            for existing_object in existing_objects:
                if existing_object.deleted:
                    continue
                model = existing_object.model_class
                pk = existing_object.obj_pk

                obj = objects[model][pk]
                existing_object.apply_to_instance(obj, created_pks=created_pks)
                obj.save()

            # delete existing objects
            for existing_object in existing_objects:
                if not existing_object.deleted and not issubclass(existing_object.model_class, LocationRedirect):
                    continue
                model = existing_object.model_class
                pk = existing_object.obj_pk

                obj = objects[model][pk]
                obj.delete()

            # update m2m
            for changed_object in changed_objects:
                obj = objects[changed_object.model_class][changed_object.obj_pk]
                for mode, updates in (('remove', changed_object.m2m_removed), ('add', changed_object.m2m_added)):
                    for name, pks in updates.items():
                        field = changed_object.model_class._meta.get_field(name)
                        pks = tuple(objects[field.related_model][pk].pk for pk in pks)
                        getattr(getattr(obj, name), mode)(*pks)

            update = self.updates.create(user=user, state='applied')
            map_update = MapUpdate.objects.create(user=user, type='changeset')
            self.state = 'applied'
            self.last_state_update = update
            self.last_update = update
            self.map_update = map_update
            self.save()
Example #6
0
    def apply(self, user):
        with MapUpdate.lock():
            changed_geometries.reset()

            self._clean_changes()
            changed_objects = self.relevant_changed_objects()
            created_objects = []
            existing_objects = []
            for changed_object in changed_objects:
                (created_objects if changed_object.is_created else
                 existing_objects).append(changed_object)

            objects = self.get_objects(changed_objects=changed_objects)

            # remove slugs on all changed existing objects
            slugs_updated = set(
                changed_object.obj_pk for changed_object in existing_objects
                if (issubclass(changed_object.model_class, LocationSlug)
                    and 'slug' in changed_object.updated_fields))
            LocationSlug.objects.filter(pk__in=slugs_updated).update(slug=None)

            redirects_deleted = set(
                changed_object.obj_pk for changed_object in existing_objects
                if (issubclass(changed_object.model_class, LocationRedirect)
                    and changed_object.deleted))
            LocationRedirect.objects.filter(pk__in=redirects_deleted).delete()

            # create created objects
            created_pks = {}
            objects_to_create = set(created_objects)
            while objects_to_create:
                created_in_last_run = set()
                for created_object in objects_to_create:
                    model = created_object.model_class
                    pk = created_object.obj_pk

                    # lets try to create this object
                    obj = model()
                    try:
                        created_object.apply_to_instance(
                            obj, created_pks=created_pks)
                    except ApplyToInstanceError:
                        continue

                    obj.save()
                    created_in_last_run.add(created_object)
                    created_pks.setdefault(model, {})[pk] = obj.pk
                    objects.setdefault(model, {})[pk] = obj

                objects_to_create -= created_in_last_run

            # update existing objects
            for existing_object in existing_objects:
                if existing_object.deleted:
                    continue
                model = existing_object.model_class
                pk = existing_object.obj_pk

                obj = objects[model][pk]
                existing_object.apply_to_instance(obj, created_pks=created_pks)
                obj.save()

            # delete existing objects
            for existing_object in existing_objects:
                if not existing_object.deleted and not issubclass(
                        existing_object.model_class, LocationRedirect):
                    continue
                model = existing_object.model_class
                pk = existing_object.obj_pk

                obj = objects[model][pk]
                obj.delete()

            # update m2m
            for changed_object in changed_objects:
                obj = objects[changed_object.model_class][
                    changed_object.obj_pk]
                for mode, updates in (('remove', changed_object.m2m_removed),
                                      ('add', changed_object.m2m_added)):
                    for name, pks in updates.items():
                        field = changed_object.model_class._meta.get_field(
                            name)
                        pks = tuple(objects[field.related_model][pk].pk
                                    for pk in pks)
                        getattr(getattr(obj, name), mode)(*pks)

            update = self.updates.create(user=user, state='applied')
            map_update = MapUpdate.objects.create(user=user, type='changeset')
            self.state = 'applied'
            self.last_state_update = update
            self.last_update = update
            self.map_update = map_update
            self.save()