diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2016-02-19 19:22:08 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2016-02-19 19:22:08 +0100 |
commit | c3f043e4937bd9ed7c68a38488e588866943f4c5 (patch) | |
tree | 48ecf37a9c135f85786e7ba9d1d24c75b4366c29 /chimere | |
parent | b3058742a5acc9ca19a5edc31260b9ad0ca5ba5a (diff) | |
download | Chimère-c3f043e4937bd9ed7c68a38488e588866943f4c5.tar.bz2 Chimère-c3f043e4937bd9ed7c68a38488e588866943f4c5.zip |
Flake8
Diffstat (limited to 'chimere')
-rw-r--r-- | chimere/actions.py | 24 | ||||
-rw-r--r-- | chimere/admin.py | 165 | ||||
-rw-r--r-- | chimere/feeds.py | 46 | ||||
-rw-r--r-- | chimere/managers.py | 22 | ||||
-rw-r--r-- | chimere/route.py | 24 | ||||
-rw-r--r-- | chimere/urls.py | 89 | ||||
-rw-r--r-- | chimere/widgets.py | 340 |
7 files changed, 403 insertions, 307 deletions
diff --git a/chimere/actions.py b/chimere/actions.py index e83d8c3..9b66492 100644 --- a/chimere/actions.py +++ b/chimere/actions.py @@ -21,12 +21,12 @@ Actions available in the main interface """ from django.conf import settings -from django.contrib.auth import models from django.core.urlresolvers import reverse, NoReverseMatch from django.utils.translation import ugettext_lazy as _ from models import Page + class Action: def __init__(self, id, path, label, extra_url_args=[]): self.id, self.path, self.label = id, path, label @@ -34,18 +34,22 @@ class Action: def update_url(self, area_name): try: - self.url = reverse(self.path, - args=[area_name if area_name else ''] + self.extra_url_args) + self.url = reverse( + self.path, + args=[area_name if area_name else ''] + self.extra_url_args) except NoReverseMatch: # backward url management - self.url = reverse(self.path, - args=[area_name + '/' if area_name else ''] + self.extra_url_args) + self.url = reverse( + self.path, + args=[area_name + '/' if area_name else ''] + + self.extra_url_args) -default_actions = [(Action('view', 'chimere:index', _('View')), []), - (Action('contribute', 'chimere:edit', _('Contribute')), - (Action('edit', 'chimere:edit', _('Add a new point of interest')), - Action('edit-route', 'chimere:editroute', _('Add a new route'))), - ),] +default_actions = [ + (Action('view', 'chimere:index', _('View')), []), + (Action('contribute', 'chimere:edit', _('Contribute')), + (Action('edit', 'chimere:edit', _('Add a new point of interest')), + Action('edit-route', 'chimere:editroute', _('Add a new route'))), + )] if hasattr(settings, 'CHIMERE_DIRECTORY') and settings.CHIMERE_DIRECTORY: default_actions.append((Action('categories', 'chimere:category-directory', diff --git a/chimere/admin.py b/chimere/admin.py index 686a656..3ea5b7b 100644 --- a/chimere/admin.py +++ b/chimere/admin.py @@ -37,17 +37,16 @@ except ImportError: pass from chimere.forms import MarkerAdminForm, RouteAdminForm, AreaAdminForm,\ - NewsAdminForm, CategoryAdminForm, ImporterAdminForm, OSMForm, \ - PageAdminForm, PictureFileAdminForm, MultimediaFileAdminForm + NewsAdminForm, CategoryAdminForm, ImporterAdminForm, OSMForm, \ + PageAdminForm, PictureFileAdminForm, MultimediaFileAdminForm from chimere import models from chimere.models import Category, Icon, SubCategory, Marker, \ - PropertyModel, News, Route, Area, ColorTheme, Color, \ - MultimediaFile, PictureFile, Importer, Layer, AreaLayers,\ - PropertyModelChoice, MultimediaExtension, Page,\ - get_areas_for_user, get_users_by_area, ImporterKeyCategories,\ - SubCategoryUserLimit -from chimere.utils import unicode_normalize, ShapefileManager, KMLManager,\ - CSVManager + PropertyModel, News, Route, Area, ColorTheme, Color, \ + MultimediaFile, PictureFile, Importer, Layer, AreaLayers,\ + PropertyModelChoice, Page, get_areas_for_user, \ + ImporterKeyCategories, SubCategoryUserLimit +from chimere.utils import ShapefileManager, KMLManager, CSVManager + def disable(modeladmin, request, queryset): for item in queryset: @@ -55,23 +54,26 @@ def disable(modeladmin, request, queryset): item.save() disable.short_description = _(u"Disable") + def validate(modeladmin, request, queryset): for item in queryset: item.status = 'A' item.save() validate.short_description = _(u"Validate") + def export_to_kml(modeladmin, request, queryset): u""" Export data to KML """ filename, result = KMLManager.export(queryset) response = HttpResponse(result, - mimetype='application/vnd.google-earth.kml+xml') + mimetype='application/vnd.google-earth.kml+xml') response['Content-Disposition'] = 'attachment; filename=%s' % filename return response export_to_kml.short_description = _(u"Export to KML") + def export_to_shapefile(modeladmin, request, queryset): u""" Export data to Shapefile @@ -86,6 +88,7 @@ def export_to_shapefile(modeladmin, request, queryset): return response export_to_shapefile.short_description = _(u"Export to Shapefile") + def export_to_csv(modeladmin, request, queryset): u""" Export data to CSV @@ -96,6 +99,7 @@ def export_to_csv(modeladmin, request, queryset): return response export_to_csv.short_description = _(u"Export to CSV") + def managed_modified(modeladmin, request, queryset): # not very clean... There is must be a better way to do that redirect_url = request.get_full_path().split('admin_modification')[0] @@ -108,8 +112,8 @@ def managed_modified(modeladmin, request, queryset): item = queryset.all()[0] if not item.ref_item or item.ref_item == item: try: - item = modeladmin.model.objects.filter(ref_item=item - ).exclude(pk=item.pk).all()[0] + item = modeladmin.model.objects.filter(ref_item=item)\ + .exclude(pk=item.pk).all()[0] except IndexError: messages.error(request, _(u"No modified item associated " u"to the selected item.")) @@ -160,7 +164,7 @@ def managed_modified(modeladmin, request, queryset): messages.success(request, _(u"Modified item traited.")) return HttpResponseRedirect(redirect_url) return render_to_response('admin/chimere/managed_modified.html', - {'item':item, 'item_ref':item_ref}, + {'item': item, 'item_ref': item_ref}, context_instance=RequestContext(request)) managed_modified.short_description = _(u"Managed modified items") @@ -284,28 +288,24 @@ class MarkerAdmin(admin.ModelAdmin): export_to_shapefile, export_to_csv] exclude = ['submiter_session_key', 'import_key', 'import_version', 'available_date', 'ref_item'] - readonly_fields = ['submiter_email', 'submiter_comment', 'import_source', - 'submiter_name', 'ref_item', 'modified_since_import', 'route'] + readonly_fields = [ + 'submiter_email', 'submiter_comment', 'import_source', + 'submiter_name', 'ref_item', 'modified_since_import', 'route'] form = MarkerAdminForm fieldsets = ((None, { - 'fields': ['point', 'name', 'status', 'categories', - 'description', 'keywords', 'start_date', 'end_date'] - }), - (_(u"Submitter"), { - 'classes':('collapse',), - 'fields': ('submiter_name', 'submiter_email', - 'submiter_comment') - }), - (_(u"Import"), { - 'classes':('collapse',), - 'fields': ('not_for_osm', 'modified_since_import', - 'import_source', 'origin', 'license') - }), - (_(u"Associated items"), { - 'classes':('collapse',), - 'fields': ('ref_item', 'route',) - }), - ) + 'fields': ['point', 'name', 'status', 'categories', 'description', + 'keywords', 'start_date', 'end_date'] + }), (_(u"Submitter"), { + 'classes': ('collapse',), + 'fields': ('submiter_name', 'submiter_email', 'submiter_comment') + }), (_(u"Import"), { + 'classes': ('collapse',), + 'fields': ('not_for_osm', 'modified_since_import', 'import_source', + 'origin', 'license') + }), (_(u"Associated items"), { + 'classes': ('collapse',), + 'fields': ('ref_item', 'route',) + }),) inlines = [MultimediaInline, PictureInline] has_properties = True @@ -315,8 +315,8 @@ class MarkerAdmin(admin.ModelAdmin): """ if self.has_properties: main_fields = self.fieldsets[0][1]['fields'] - for pm in PropertyModel.objects.filter(available=True).order_by('order' - ).all(): + for pm in PropertyModel.objects.filter(available=True)\ + .order_by('order').all(): pm_name = pm.getNamedId() if pm_name not in main_fields: main_fields.append(pm_name) @@ -334,13 +334,14 @@ class MarkerAdmin(admin.ModelAdmin): ''' Redirect to the marker modification form ''' - return managed_modified(self, request, - Marker.objects.filter(pk=item_id)) + return managed_modified( + self, request, Marker.objects.filter(pk=item_id)) def get_urls(self): from django.conf.urls.defaults import patterns, url urls = super(MarkerAdmin, self).get_urls() - my_urls = patterns('', + my_urls = patterns( + '', url(r'^admin_modification/(?P<item_id>\d+)/$', self.admin_site.admin_view(self.admin_modification), name='admin-modification'), @@ -372,25 +373,19 @@ class RouteAdmin(MarkerAdmin): actions = [validate, disable, managed_modified, export_to_kml, export_to_shapefile, export_to_csv] fieldsets = ((None, { - 'fields': ['route', 'name', 'status', 'categories', - 'start_date', 'end_date'] - }), - (_(u"Submitter"), { - 'classes':('collapse',), - 'fields': ('submiter_name', 'submiter_email', - 'submiter_comment') - }), - (_(u"Import"), { - 'classes':('collapse',), - 'fields': ('modified_since_import', 'import_source', - 'origin', 'license') - }), - (_(u"Associated items"), { - 'classes':('collapse',), - 'fields': ('ref_item', 'associated_file', - 'has_associated_marker') - }), - ) + 'fields': ['route', 'name', 'status', 'categories', 'start_date', + 'end_date'] + }), (_(u"Submitter"), { + 'classes': ('collapse',), + 'fields': ('submiter_name', 'submiter_email', 'submiter_comment') + }), (_(u"Import"), { + 'classes': ('collapse',), + 'fields': ('modified_since_import', 'import_source', 'origin', + 'license') + }), (_(u"Associated items"), { + 'classes': ('collapse',), + 'fields': ('ref_item', 'associated_file', 'has_associated_marker') + }),) inlines = [] has_properties = False @@ -409,10 +404,12 @@ class RouteAdmin(MarkerAdmin): return managed_modified(self, request, Route.objects.filter(pk=item_id)) + class LayerInline(admin.TabularInline): model = AreaLayers extra = 1 + class AreaAdmin(admin.ModelAdmin): """ Specialized the area field. @@ -422,6 +419,7 @@ class AreaAdmin(admin.ModelAdmin): inlines = [LayerInline] list_display = ['name', 'order', 'available', 'default'] + def importing(modeladmin, request, queryset): for importer in queryset: importer.state = unicode(tasks.IMPORT_MESSAGES['import_pending'][0]) @@ -429,63 +427,72 @@ def importing(modeladmin, request, queryset): tasks.importing(importer.pk) importing.short_description = _(u"Import") + def cancel_import(modeladmin, request, queryset): for importer in queryset: importer.state = tasks.IMPORT_MESSAGES['import_cancel'][0] importer.save() cancel_import.short_description = _(u"Cancel import") + def cancel_export(modeladmin, request, queryset): for importer in queryset: importer.state = tasks.IMPORT_MESSAGES['export_cancel'][0] importer.save() cancel_export.short_description = _(u"Cancel export") + def export_to_osm(modeladmin, request, queryset): if queryset.count() > 1: - messages.error(request, _(u"Can manage only one OSM export at a time.")) + messages.error(request, + _(u"Can manage only one OSM export at a time.")) return HttpResponseRedirect(request.get_full_path()) importer = queryset.all()[0] if Marker.objects.filter(categories__in=importer.categories.all(), status='I').count(): - messages.error(request, _(u"You must treat all item with the status "\ + messages.error(request, _(u"You must treat all item with the status " u"\"imported\" before exporting to OSM.")) return HttpResponseRedirect(request.get_full_path()) if importer.importer_type != 'OSM': - messages.error(request, _(u"Only OSM importer are managed for export.")) + messages.error(request, + _(u"Only OSM importer are managed for export.")) return HttpResponseRedirect(request.get_full_path()) - item_nb = Marker.objects.filter(status='A', - categories=importer.categories.all(), - not_for_osm=False, modified_since_import=True, - route=None).count() + item_nb = Marker.objects.filter( + status='A', categories=importer.categories.all(), not_for_osm=False, + modified_since_import=True, route=None).count() if not item_nb: - messages.error(request, _(u"No point of interest are concerned by this " - u"export.")) + messages.error(request, + _(u"No point of interest are concerned by this " + u"export.")) return HttpResponseRedirect(request.get_full_path()) form = None if request.method == 'POST' and ( - 'email' in request.POST or 'api' in request.POST - or 'password' in request.POST): + 'email' in request.POST or 'api' in request.POST + or 'password' in request.POST): form = OSMForm(request.POST) if form.is_valid(): - importer.state = unicode(tasks.IMPORT_MESSAGES['export_pending'][0]) + importer.state = unicode( + tasks.IMPORT_MESSAGES['export_pending'][0]) importer.save() tasks.exporting(importer.pk, form.cleaned_data) messages.success(request, _(u"Export launched.")) return HttpResponseRedirect(request.get_full_path()) else: form = OSMForm() - msg_item = _(u"%s point(s) of interest concerned by this export before "\ + msg_item = _(u"%s point(s) of interest concerned by this export before " u"bounding box filter.") % item_nb - return render_to_response('admin/chimere/osm_export.html', {'item':importer, - 'form':form, 'msg_item':msg_item}, + return render_to_response('admin/chimere/osm_export.html', + {'item': importer, 'form': form, + 'msg_item': msg_item}, context_instance=RequestContext(request)) export_to_osm.short_description = _(u"Export to osm") + class ImporterKeyInline(admin.TabularInline): model = ImporterKeyCategories extra = 1 + class ImporterAdmin(admin.ModelAdmin): form = ImporterAdminForm list_display = ('importer_type', 'display_categories', 'default_name', @@ -496,14 +503,13 @@ class ImporterAdmin(admin.ModelAdmin): inlines = [ImporterKeyInline] admin.site.register(Importer, ImporterAdmin) + class PageAdmin(admin.ModelAdmin): """ Use the TinyMCE widget for the page content """ form = PageAdminForm -class PropertyModelAdmin(admin.ModelAdmin): - list_display = ('name', 'order', 'available') class NewsAdmin(admin.ModelAdmin): """ @@ -511,10 +517,12 @@ class NewsAdmin(admin.ModelAdmin): """ form = NewsAdminForm + class SubcatInline(admin.TabularInline): model = SubCategory extra = 1 + class CategoryAdmin(admin.ModelAdmin): """ Use the TinyMCE widget for categories @@ -523,20 +531,27 @@ class CategoryAdmin(admin.ModelAdmin): inlines = [SubcatInline] list_display = ['name', 'order'] + class ColorInline(admin.TabularInline): model = Color + class ColorThemeAdmin(admin.ModelAdmin): - inlines = [ColorInline,] + inlines = [ColorInline] + class IconAdmin(admin.ModelAdmin): exclude = ['height', 'width'] list_display = ['name'] + class PropertyModelChoiceInline(admin.TabularInline): model = PropertyModelChoice extra = 1 + + class PropertyModelAdmin(admin.ModelAdmin): + list_display = ('name', 'order', 'available') inlines = [PropertyModelChoiceInline] # register of differents database fields diff --git a/chimere/feeds.py b/chimere/feeds.py index 53444ac..025ceb0 100644 --- a/chimere/feeds.py +++ b/chimere/feeds.py @@ -31,6 +31,7 @@ from django.shortcuts import get_object_or_404 from chimere.models import Category, SubCategory, Marker, Area + class BaseFeed(Feed): """ Base feed for Chimere objects @@ -42,8 +43,8 @@ class BaseFeed(Feed): if item.categories.all() and item.categories.all()[0]: cat = item.categories.all()[0].pk return reverse('chimere:index') + '?zoom=16&lat=%f&lon=%f&'\ - 'current_feature=%d&checked_categories=%d' % (coord.y, coord.x, item.id, - cat) + 'current_feature=%d&checked_categories=%d' % (coord.y, coord.x, + item.id, cat) def item_pubdate(self, item): """ @@ -57,6 +58,7 @@ class BaseFeed(Feed): def item_geometry(self, obj): return obj.point + class LatestPOIsByCategory(BaseFeed): ''' Last Points of interests by category in Feeds @@ -87,11 +89,13 @@ class LatestPOIsByCategory(BaseFeed): and its status is available This returns a list of the 15 last markers/POIs ordering by date """ - q = Marker.objects.filter(status__exact='A', + q = Marker.objects.filter( + status__exact='A', categories__category__id__exact=obj.id, available_date__isnull=False).order_by('-available_date')[:15] return q + class LatestPOIsBySubCategory(BaseFeed): ''' Last Points of interests by SubCategory in Feeds @@ -112,11 +116,13 @@ class LatestPOIsBySubCategory(BaseFeed): return reverse('chimere:feeds-subcat', args=['', obj.id]) def items(self, obj): - q = Marker.objects.filter(categories__id__exact=obj.id, - available_date__isnull=False, status__exact='A').order_by( - '-available_date')[:15] + q = Marker.objects.filter( + categories__id__exact=obj.id, + available_date__isnull=False, status__exact='A')\ + .order_by('-available_date')[:15] return q + class LatestPOIs(BaseFeed): ''' Last Points of interests @@ -134,10 +140,12 @@ class LatestPOIs(BaseFeed): return _("Latest points of interest from ") + settings.PROJECT_NAME def items(self): - q = Marker.objects.filter(status__exact='A', - available_date__isnull=False).order_by('-available_date')[:15] + q = Marker.objects.filter( + status__exact='A', + available_date__isnull=False).order_by('-available_date')[:15] return q + class LatestPOIsByZone(BaseFeed): ''' Last Points of interests by zone by coordinates @@ -168,16 +176,16 @@ class LatestPOIsByZone(BaseFeed): lower_left_lon = upper_left_lon # Define a Polygon with the 4 points of the zone. areaBox = Polygon(((upper_left_lon, upper_left_lat), - (upper_right_lon, upper_right_lat), - (lower_right_lon, lower_right_lat), - (lower_left_lon, lower_left_lat), - (upper_left_lon, upper_left_lat)), - srid=settings.CHIMERE_EPSG_DISPLAY_PROJECTION) + (upper_right_lon, upper_right_lat), + (lower_right_lon, lower_right_lat), + (lower_left_lon, lower_left_lat), + (upper_left_lon, upper_left_lat)), + srid=settings.CHIMERE_EPSG_DISPLAY_PROJECTION) return areaBox def title(self, obj): return settings.PROJECT_NAME + u" - " +\ - _(u"Last points of interest by area") + _(u"Last points of interest by area") def link(self, obj): """ @@ -187,7 +195,7 @@ class LatestPOIsByZone(BaseFeed): if not obj: raise FeedDoesNotExist area = str(self.upper_left_lat) + '_' + str(self.upper_left_lon) + \ - '_' + str(self.lower_right_lat) + '_' + str(self.lower_right_lon) + '_' + str(self.lower_right_lat) + '_' + str(self.lower_right_lon) return reverse('chimere:feeds-area', args=['', area]) def items(self, obj): @@ -196,10 +204,12 @@ class LatestPOIsByZone(BaseFeed): which is requested. This returns a list of the 15 last markers/POIs ordering by date """ - q = Marker.objects.filter(point__contained=obj, status__exact='A', - available_date__isnull=False).order_by('-available_date')[:15] + q = Marker.objects.filter( + point__contained=obj, status__exact='A', + available_date__isnull=False).order_by('-available_date')[:15] return q + class LatestPOIsByZoneID(BaseFeed): ''' Last Points of interests by zone by id @@ -212,7 +222,7 @@ class LatestPOIsByZoneID(BaseFeed): def title(self, obj): return settings.PROJECT_NAME + u" - " + \ - _(u"Last points of interest") + u" - " + obj.name + _(u"Last points of interest") + u" - " + obj.name def link(self, obj): if not obj: diff --git a/chimere/managers.py b/chimere/managers.py index 89aa35f..807b493 100644 --- a/chimere/managers.py +++ b/chimere/managers.py @@ -1,14 +1,13 @@ # -*- coding: utf-8 -*- -import sys -from django.contrib.gis.db import models - -from logging import getLogger -from datetime import datetime, date, timedelta +from datetime import date, timedelta +from django.contrib.gis.db import models from django.conf import settings # BASE + + class BaseGeoQuerySet(models.query.QuerySet): """ Custom queryset for Geo objects. @@ -16,11 +15,11 @@ class BaseGeoQuerySet(models.query.QuerySet): def available(self): """ Chainable filter to retrieve only available elements. """ return self.filter(status="A") - + def submited(self): """ Chainable filter to retrieve only submited elements. """ return self.filter(status="S") - + def active(self): """ Returns objects where within the active date period of events. @@ -31,7 +30,8 @@ class BaseGeoQuerySet(models.query.QuerySet): today = date.today() after = today + timedelta(settings.CHIMERE_DAYS_BEFORE_EVENT) return self.filter(end_date__gte=today, start_date__lte=after) - + + class BaseGeoManager(models.GeoManager): """ Custom base manager for Geo objects. @@ -39,14 +39,14 @@ class BaseGeoManager(models.GeoManager): def get_query_set(self): """ Use our custom QuerySet. """ return BaseGeoQuerySet(self.model) - + # Methods defined in the queryset that we also want exposed in the # It would be nice to implement it with a magic method instead, later :) def available(self): return self.get_query_set().available() - + def submited(self): return self.get_query_set().submited() - + def active(self): return self.get_query_set().active() diff --git a/chimere/route.py b/chimere/route.py index 8c4638a..31cf4f0 100644 --- a/chimere/route.py +++ b/chimere/route.py @@ -22,7 +22,10 @@ Routing management """ -import os, re, shutil, tempfile +import os +import re +import shutil +import tempfile from BeautifulSoup import BeautifulSoup from subprocess import Popen, PIPE from django.contrib.gis.gdal import DataSource @@ -30,6 +33,7 @@ from django.contrib.gis.gdal.error import OGRException from django.conf import settings + class Router: def route(self, lon1, lat1, lon2, lat2, transport='foot'): ''' @@ -37,9 +41,11 @@ class Router: ''' return [] + class RoutinoRouter(Router): re_desc = [re.compile("<tr class='n'>"), re.compile("<tr class='s'>"), re.compile("<tr class='t'>")] + def route(self, lon1, lat1, lon2, lat2, steps=[], transport='foot', speed=None): ''' @@ -57,10 +63,12 @@ class RoutinoRouter(Router): "--lon1=%0.15f" % lon1, ] if speed: - args += ["--speed-%s=%s" % (highway, unicode(speed)) - for highway in ('motorway', 'trunk', 'primary', 'secondary', - 'tertiary', 'unclassified', 'residential', 'service', - 'track','cycleway','path','steps')] + args += [ + "--speed-%s=%s" % (highway, unicode(speed)) + for highway in ( + 'motorway', 'trunk', 'primary', 'secondary', 'tertiary', + 'unclassified', 'residential', 'service', 'track', + 'cycleway', 'path', 'steps')] lonlat_index = 1 for lon, lat in steps: lonlat_index += 1 @@ -97,9 +105,8 @@ class RoutinoRouter(Router): desc = desc[1:-2] # very fragile piece of code but only break the numerotation number_tpl = '<tr class="n"><span class="number">%d.</span>' - desc = [re.sub('<tr class="n">', number_tpl % (idx/2+1), d) - if idx % 2 else d - for idx, d in enumerate(desc)] + desc = [re.sub('<tr class="n">', number_tpl % (idx / 2 + 1), d) + if idx % 2 else d for idx, d in enumerate(desc)] desc = self.webify(BeautifulSoup('\n'.join(desc)).prettify()) desc = re.sub(" \[", "", desc) desc = re.sub(" \]", "", desc) @@ -118,4 +125,3 @@ router = None if hasattr(settings, 'CHIMERE_ROUTING_ENGINE') and \ settings.CHIMERE_ROUTING_ENGINE['ENGINE'] == 'routino': router = RoutinoRouter() - diff --git a/chimere/urls.py b/chimere/urls.py index b9ec380..0335d96 100644 --- a/chimere/urls.py +++ b/chimere/urls.py @@ -25,25 +25,29 @@ admin.autodiscover() from chimere.views import CategoryDirectoryView, CategoryView from chimere.feeds import LatestPOIsByCategory, LatestPOIsBySubCategory, \ - LatestPOIs, LatestPOIsByZone, LatestPOIsByZoneID + LatestPOIs, LatestPOIsByZone, LatestPOIsByZoneID def i18n_javascript(request): return admin.site.i18n_javascript(request) -urlpatterns = patterns('chimere.views', - url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?simple$', 'index', {'simple':True}, +urlpatterns = patterns( + 'chimere.views', + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?simple$', 'index', {'simple': True}, name="simple_index") ) if settings.CHIMERE_FEEDS: - urlpatterns += patterns('', + urlpatterns += patterns( + '', url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?feeds$', 'chimere.views.rss', name='feeds-form'), - url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?feeds/category/(?P<category_id>\d+)$', + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?feeds/category/' + r'(?P<category_id>\d+)$', LatestPOIsByCategory(), name='feeds-cat'), - url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?feeds/subcategory/(?P<category_id>\d+)$', + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?feeds/subcategory/' + r'(?P<category_id>\d+)$', LatestPOIsBySubCategory(), name='feeds-subcat'), url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?feeds/global/$', LatestPOIs(), name='feeds-global'), @@ -56,17 +60,19 @@ if settings.CHIMERE_FEEDS: if hasattr(settings, 'CHIMERE_ENABLE_ROUTING') \ and settings.CHIMERE_ENABLE_ROUTING: if not hasattr(settings, 'CHIMERE_ROUTING_TRANSPORT') \ - or not settings.CHIMERE_ROUTING_TRANSPORT: - raise ImproperlyConfigured(u"CHIMERE_ROUTING_TRANSPORT must be set in"\ + or not settings.CHIMERE_ROUTING_TRANSPORT: + raise ImproperlyConfigured(u"CHIMERE_ROUTING_TRANSPORT must be set in" u" settings if you enable routing") - urlpatterns += patterns('chimere.views', - url(r'^(?P<area_name>[a-zA-Z0-9_-]*/)?route/'\ + urlpatterns += patterns( + 'chimere.views', + url(r'^(?P<area_name>[a-zA-Z0-9_-]*/)?route/' r'(?P<transport>(%s))/((?P<speed>[0-9][0-9]*)/)?' - r'(?P<lon1>[-]?[0-9]+[.]?[0-9]*)_(?P<lat1>[-]?[0-9]+[.]?[0-9]*)_'\ - r'(?P<lonlat_steps>([-]?[0-9]+[.]?[0-9]*_[-]?[0-9]+[.]?[0-9]*_)*)'\ + r'(?P<lon1>[-]?[0-9]+[.]?[0-9]*)_(?P<lat1>[-]?[0-9]+[.]?[0-9]*)_' + r'(?P<lonlat_steps>([-]?[0-9]+[.]?[0-9]*_[-]?[0-9]+[.]?[0-9]*_)*)' r'(?P<lon2>[-]?[0-9]+[.]?[0-9]*)_(?P<lat2>[-]?[0-9]+[.]?[0-9]*)$' % - ('|'.join([key for key, lbl in settings.CHIMERE_ROUTING_TRANSPORT])), - 'route', name="route"), + ('|'.join([key + for key, lbl in settings.CHIMERE_ROUTING_TRANSPORT])), + 'route', name="route"), ) if hasattr(settings, 'CHIMERE_SEARCH_ENGINE') \ @@ -74,7 +80,8 @@ if hasattr(settings, 'CHIMERE_SEARCH_ENGINE') \ from chimere.forms import SearchForm from chimere.views import SearchView from haystack.views import search_view_factory - urlpatterns += patterns('chimere.views', + urlpatterns += patterns( + 'chimere.views', url(r'^search/?$', search_view_factory( view_class=SearchView, template='search/search.html', @@ -83,48 +90,52 @@ if hasattr(settings, 'CHIMERE_SEARCH_ENGINE') \ url(r'^search/autocomplete/$', 'autocomplete', name='autocomplete-search') ) - #urlpatterns += [url(r'^search/', include('haystack.urls')),] + # urlpatterns += [url(r'^search/', include('haystack.urls')),] -urlpatterns += patterns('chimere.views', +urlpatterns += patterns( + 'chimere.views', url(r'^charte/?$', 'charte', name="charte"), url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?contact/?$', 'contactus', name="contact"), url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?edit/$', 'edit', name="edit"), - url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?edit/(?P<item_id>\w+)/(?P<submited>\w+)?$', - 'edit', name="edit-item"), + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?edit/(?P<item_id>\w+)/' + r'(?P<submited>\w+)?$', 'edit', name="edit-item"), url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?edit-route/$', 'editRoute', name="editroute"), - url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?edit-route/(?P<item_id>\w+)/(?P<submited>\w+)?$', + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?edit-route/(?P<item_id>\w+)/' + r'(?P<submited>\w+)?$', 'editRoute', name="editroute-item"), - url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getDetail/(?P<marker_id>\d+)/?$', 'getDetail', - name="get_detail"), - url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getDescriptionDetail/?(?P<category_id>\d+)/?$', - 'getDescriptionDetail', name="get_description_detail"), - url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getGeoObjects/'\ - r'(?P<category_ids>[a-zA-Z0-9_-]+)(/(?P<status>\w+))?$', 'getGeoObjects', - name="getgeoobjects"), - url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?get-marker/'\ + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getDetail/(?P<marker_id>\d+)/?$', + 'getDetail', name="get_detail"), + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getDescriptionDetail/' + r'?(?P<category_id>\d+)/?$', 'getDescriptionDetail', + name="get_description_detail"), + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getGeoObjects/' + r'(?P<category_ids>[a-zA-Z0-9_-]+)(/(?P<status>\w+))?$', + 'getGeoObjects', name="getgeoobjects"), + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?get-marker/' r'(?P<pk>[0-9]+)$', 'getMarker', name="get-marker"), url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getAvailableCategories/$', - 'get_available_categories', name="get_categories"), + 'get_available_categories', name="get_categories"), url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getAllCategories/$', - 'get_all_categories', name="get_all_categories"), + 'get_all_categories', name="get_all_categories"), url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?getCategory/(?P<category_id>\d+)/?$', - 'getCategory', name="get_category"), + 'getCategory', name="get_category"), url(r'^(?P<area_name>[a-zA-Z0-9_-]*/)?get-share-url/(?P<network>\w+)?$', - 'getShareUrl', name="get-share-url"), + 'getShareUrl', name="get-share-url"), url(r'^(?P<area_name>[a-zA-Z0-9_-]*/)?ty/(?P<tiny_urn>\w+)$', - 'redirectFromTinyURN', name="tiny"), - url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?upload_file/((?P<category_id>\w+)/)?$', - 'uploadFile', name='upload_file'), - url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?process_route_file/(?P<file_id>\d+)/$', - 'processRouteFile', name='process_route_file'), + 'redirectFromTinyURN', name="tiny"), + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?upload_file/' + r'((?P<category_id>\w+)/)?$', 'uploadFile', name='upload_file'), + url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?process_route_file/' + r'(?P<file_id>\d+)/$', 'processRouteFile', name='process_route_file'), url(r'^(?P<area_name>[a-zA-Z0-9_-]+/)?dyn/(?P<page_id>\w+)/$', - 'extraPage', name='extra_page'), + 'extraPage', name='extra_page'), url(r'^(?:(?P<area_name>[a-zA-Z0-9_-]*)/)?categories/$', CategoryDirectoryView.as_view(), name='category-directory'), - url(r'^(?:(?P<area_name>[a-zA-Z0-9_-]*)/)?categories/(?P<category_slug>[a-zA-Z0-9_-]+)$', + url(r'^(?:(?P<area_name>[a-zA-Z0-9_-]*)/)?categories/' + r'(?P<category_slug>[a-zA-Z0-9_-]+)$', CategoryView.as_view(), name='category-directory-detail'), # At the end, because it catches large url(r'^(?P<area_name>[a-zA-Z0-9_-]+)?', 'index', name="index"), diff --git a/chimere/widgets.py b/chimere/widgets.py index ea3fe16..f8bb11b 100644 --- a/chimere/widgets.py +++ b/chimere/widgets.py @@ -20,7 +20,6 @@ """ Extra widgets and fields """ -from django import conf from django import forms from django.conf import settings from django.contrib.gis.db import models @@ -36,6 +35,7 @@ from django.template.loader import render_to_string import re + def getMapJS(area_name=''): '''Variable initialization for drawing the map ''' @@ -44,10 +44,10 @@ def getMapJS(area_name=''): u";\n" % settings.CHIMERE_EPSG_DISPLAY_PROJECTION js += u"OpenLayers.ImgPath = '%schimere/img/';\n" % settings.STATIC_URL js += u"var epsg_projection = new OpenLayers.Projection('EPSG:%d');\n" % \ - settings.CHIMERE_EPSG_PROJECTION + settings.CHIMERE_EPSG_PROJECTION js += u"var centerLonLat = new OpenLayers.LonLat(%f,"\ u"%f).transform(epsg_display_projection, epsg_projection);\n" % \ - settings.CHIMERE_DEFAULT_CENTER + settings.CHIMERE_DEFAULT_CENTER js += u"var media_path = '%s';\n" % settings.MEDIA_URL js += u"var static_path = '%s';\n" % settings.STATIC_URL js += u"var map_layer = %s;\n" % settings.CHIMERE_DEFAULT_MAP_LAYER @@ -59,6 +59,7 @@ def getMapJS(area_name=''): u"%s// !--></script>\n" % js return js + def get_map_layers(area_name=''): from chimere.models import Area area = None @@ -74,8 +75,9 @@ def get_map_layers(area_name=''): pass map_layers, default = [], None if area and area.layers.count(): - map_layers = [[layer.name, layer.layer_code, False] - for layer in area.layers.order_by('arealayers__order').all()] + map_layers = [ + [layer.name, layer.layer_code, False] + for layer in area.layers.order_by('arealayers__order').all()] def_layer = area.layers.filter(arealayers__default=True) if def_layer.count(): def_layer = def_layer.all()[0] @@ -93,28 +95,33 @@ def get_map_layers(area_name=''): True)] return map_layers, default + class ChosenSelectWidget(forms.Select): """ Chosen select widget. """ class Media: - js = ["%schosen/chosen/chosen.jquery.min.js" % settings.STATIC_URL,] - css = {'all': - ["%schosen/chosen/chosen.css" % settings.STATIC_URL,] - } + js = ["%schosen/chosen/chosen.jquery.min.js" % settings.STATIC_URL] + css = { + 'all': + ["%schosen/chosen/chosen.css" % settings.STATIC_URL] + } + def render(self, *args, **kwargs): if 'attrs' not in kwargs: kwargs['attrs'] = {} kwargs['attrs'].update({'class': 'chzn-select'}) rendered = super(ChosenSelectWidget, self).render(*args, **kwargs) rendered += u"\n<script type='text/javascript'>\n"\ - u" $('#%s').chosen();\n"\ - u"</script>\n" % kwargs['attrs']['id'] + u" $('#%s').chosen();\n"\ + u"</script>\n" % kwargs['attrs']['id'] return mark_safe(rendered) """ JQuery UI button select widget. """ + + class ButtonRadioInput(RadioInput): def render(self, name=None, value=None, attrs=None, choices=()): name = name or self.name @@ -127,13 +134,18 @@ class ButtonRadioInput(RadioInput): choice_label = conditional_escape(force_unicode(self.choice_label)) return mark_safe(u'%s <label%s>%s</label>' % (self.tag(), label_for, choice_label)) + + class ButtonRadioFieldRenderer(RadioFieldRenderer): def __iter__(self): for i, choice in enumerate(self.choices): yield ButtonRadioInput(self.name, self.value, self.attrs.copy(), choice, i) + def render(self): return mark_safe(u'\n'.join([force_unicode(w) for w in self])) + + class ButtonSelectWidget(forms.RadioSelect): def __init__(self, *args, **kwargs): self.renderer = ButtonRadioFieldRenderer @@ -143,16 +155,18 @@ class ButtonSelectWidget(forms.RadioSelect): rendered = "<div id='%s'>\n" % kwargs['attrs']['id'] rendered += super(ButtonSelectWidget, self).render(*args, **kwargs) rendered += u"\n<script type='text/javascript'>\n"\ - u" $('#%s').buttonset();\n"\ - u"</script>\n</div>\n" % kwargs['attrs']['id'] + u" $('#%s').buttonset();\n"\ + u"</script>\n</div>\n" % kwargs['attrs']['id'] return mark_safe(rendered) + class ImporterChoicesWidget(forms.Select): ''' Importer select widget. ''' class Media: - js = ["%schimere/js/importer_interface.js" % settings.STATIC_URL,] + js = ["%schimere/js/importer_interface.js" % settings.STATIC_URL] + class TextareaWidgetBase(forms.Textarea): """ @@ -169,6 +183,7 @@ class TextareaWidgetBase(forms.Textarea): rendered = super(TextareaWidgetBase, self).render(*args, **kwargs) return mark_safe(rendered) + class FullTextareaWidget(TextareaWidgetBase): """ Manage the edition of a text using TinyMCE @@ -196,18 +211,21 @@ tinyMCE.init({ """ return mark_safe(rendered) + class TextareaWidget(TextareaWidgetBase): """ Manage the edition of a text using TinyMCE """ class Media: js = ["%stiny_mce.js" % settings.TINYMCE_URL, - "%schimere/js/textareas.js" % settings.STATIC_URL,] + "%schimere/js/textareas.js" % settings.STATIC_URL] + class TextareaAdminWidget(TextareaWidgetBase): class Media: js = ["%stiny_mce.js" % settings.TINYMCE_URL, - "%schimere/js/textareas_admin.js" % settings.STATIC_URL,] + "%schimere/js/textareas_admin.js" % settings.STATIC_URL] + class DatePickerWidget(forms.TextInput): """ @@ -218,18 +236,25 @@ class DatePickerWidget(forms.TextInput): def render(self, *args, **kwargs): rendered = super(DatePickerWidget, self).render(*args, **kwargs) rendered += u"\n<script type='text/javascript'>\n"\ - u" $(function() {$('#%s').datepicker({ dateFormat: 'yy-mm-dd' });});\n"\ - u"</script>\n" % kwargs['attrs']['id'] + u" $(function() {$('#%s').datepicker("\ + u"{ dateFormat: 'yy-mm-dd' });});\n"\ + u"</script>\n" % kwargs['attrs']['id'] return mark_safe(rendered) + class NominatimWidget(forms.TextInput): class Media: js = ["%schimere/js/nominatim-widget.js" % settings.STATIC_URL] + def render(self, name, value, attrs=None, area_name=''): + dct = {'id': name, 'nominatim_url': settings.NOMINATIM_URL, + 'label': _(u"Street, City, Country")} + tpl = u""" <input type='hidden' name='nominatim_%(id)s_lat' id='nominatim_%(id)s_lat'/> <input type='hidden' name='nominatim_%(id)s_lon' id='nominatim_%(id)s_lon'/> -<input type='text' class='nominatim-widget' name='nominatim_%(id)s' id='nominatim_%(id)s' value=""/> +<input type='text' class='nominatim-widget' name='nominatim_%(id)s' + id='nominatim_%(id)s' value=""/> <label class='nominatim-label' id='nominatim_%(id)s_label'> </label> <script type='text/javascript'> var default_nominatim_lbl = "%(label)s"; @@ -239,21 +264,21 @@ $("#nominatim_%(id)s").click(function(){ $("#nominatim_%(id)s").val(''); }); </script> -""" % {'id':name, 'nominatim_url':settings.NOMINATIM_URL, - 'label':_(u"Street, City, Country")} +""" % dct return mark_safe(tpl) + class PointChooserWidget(forms.TextInput): """ Manage the edition of point on a map """ class Media: css = { - "all": settings.MAP_CSS_URLS + \ - ["%schimere/css/forms.css" % settings.STATIC_URL,] + "all": settings.MAP_CSS_URLS + + ["%schimere/css/forms.css" % settings.STATIC_URL] } js = settings.MAP_JS_URLS + list(settings.JQUERY_JS_URLS) + \ - ["%schimere/js/jquery.chimere.js" % settings.STATIC_URL] + ["%schimere/js/jquery.chimere.js" % settings.STATIC_URL] def render(self, name, value, attrs=None, area_name='', initialized=True): ''' @@ -275,7 +300,7 @@ class PointChooserWidget(forms.TextInput): value = None map_layers, default_area = get_map_layers(area_name) map_layers = [js for n, js, default in map_layers] - #TODO: manage area + # TODO: manage area return mark_safe( render_to_string('chimere/blocks/live_coordinates.html', {'lat': _("Latitude"), @@ -286,8 +311,9 @@ class PointChooserWidget(forms.TextInput): 'val': val, 'initialized': initialized, 'isvalue': bool(value), - 'default_area': "true" if default_area else "false", - }) % \ + 'default_area': "true" if default_area + else "false", + }) % (settings.STATIC_URL, settings.CHIMERE_EPSG_DISPLAY_PROJECTION, settings.CHIMERE_EPSG_PROJECTION, @@ -296,7 +322,8 @@ class PointChooserWidget(forms.TextInput): settings.STATIC_URL, ", ".join(map_layers) ) - ) + ) + class HiddenPointChooserWidget(PointChooserWidget): """ @@ -307,13 +334,14 @@ class HiddenPointChooserWidget(PointChooserWidget): kwargs['initialized'] = False return super(HiddenPointChooserWidget, self).render(*args, **kwargs) + class PointField(models.PointField): ''' Set the widget for the form field ''' def __init__(self, *args, **kwargs): self.widget = kwargs.pop('widget') if 'widget' in kwargs \ - else PointChooserWidget + else PointChooserWidget return super(PointField, self).__init__(*args, **kwargs) def formfield(self, **keys): @@ -323,21 +351,23 @@ class PointField(models.PointField): def clean(self, value, instance=None): if len(value) != 2 and self.required: - raise ValidationError(_("Invalid point")) + raise forms.ValidationError(_("Invalid point")) return value + class RouteChooserWidget(forms.TextInput): """ Manage the edition of route on a map """ class Media: - css = {"all": settings.MAP_CSS_URLS + \ - ["%schimere/css/forms.css" % settings.STATIC_URL,] + css = { + "all": settings.MAP_CSS_URLS + + ["%schimere/css/forms.css" % settings.STATIC_URL] } js = settings.MAP_JS_URLS + list(settings.JQUERY_JS_URLS) + \ - ["%schimere/js/jquery.chimere.js" % settings.STATIC_URL, - "%schimere/js/edit_route_map.js" % settings.STATIC_URL, - "%schimere/js/base.js" % settings.STATIC_URL,] + ["%schimere/js/jquery.chimere.js" % settings.STATIC_URL, + "%schimere/js/edit_route_map.js" % settings.STATIC_URL, + "%schimere/js/base.js" % settings.STATIC_URL] def render(self, name, value, attrs=None, area_name='', routefile_id=None): ''' @@ -352,9 +382,13 @@ class RouteChooserWidget(forms.TextInput): var extra_url = "%s"; OpenLayers.ImgPath = '%schimere/img/'; - var EPSG_DISPLAY_PROJECTION = epsg_display_projection = new OpenLayers.Projection('EPSG:%s'); - var EPSG_PROJECTION = epsg_projection = new OpenLayers.Projection('EPSG:%s'); - var CENTER_LONLAT = centerLonLat = new OpenLayers.LonLat%s.transform(epsg_display_projection, epsg_projection); + epsg_display_projection = new OpenLayers.Projection('EPSG:%s'); + var EPSG_DISPLAY_PROJECTION = epsg_display_projection; + epsg_projection = new OpenLayers.Projection('EPSG:%s'); + var EPSG_PROJECTION = epsg_projection; + centerLonLat = new OpenLayers.LonLat%s.transform( + epsg_display_projection, epsg_projection); + var CENTER_LONLAT = centerLonLat; var DEFAULT_ZOOM = %s; var chimere_init_options = {}; chimere_init_options["map_layers"] = [%s]; @@ -363,49 +397,53 @@ class RouteChooserWidget(forms.TextInput): chimere_init_options['edition_type_is_route'] = true; chimere_init_options["checked_categories"] = []; """ % (reverse("chimere:index"), settings.STATIC_URL, - settings.CHIMERE_EPSG_DISPLAY_PROJECTION, - settings.CHIMERE_EPSG_PROJECTION, settings.CHIMERE_DEFAULT_CENTER, - settings.CHIMERE_DEFAULT_ZOOM, ", ".join(map_layers)) + settings.CHIMERE_EPSG_DISPLAY_PROJECTION, + settings.CHIMERE_EPSG_PROJECTION, + settings.CHIMERE_DEFAULT_CENTER, + settings.CHIMERE_DEFAULT_ZOOM, ", ".join(map_layers)) if default_area: js += "chimere_init_options['selected_map_layer'] = %d;\n" % \ default_area tpl = u"<script type='text/javascript'><!--\n"\ u"%s// !--></script>\n" % js - #TODO: manage area + # TODO: manage area help_create = '' if not value: help_create = u"<h3>%s</h3>\n"\ + u"<p>%s</p>\n"\ + u"<p>%s</p>\n"\ + u"<p>%s</p>\n"\ + u"<p>%s</p>\n"\ + u"<p>%s</p>\n" % ( + _(u"Creation mode"), + _(u"To start drawing the route click on the toggle " + u"button: \"Draw\"."), + _(u"Then click on the map to begin the drawing."), + _(u"You can add points by clicking again."), + _(u"To finish the drawing double click. When the drawing " + u"is finished you can edit it."), + _(u"While creating to undo a drawing click again on the " + u"toggle button \"Stop drawing\".")) + help_modify = u"<h3>%s</h3>\n"\ u"<p>%s</p>\n"\ u"<p>%s</p>\n"\ - u"<p>%s</p>\n"\ - u"<p>%s</p>\n"\ - u"<p>%s</p>\n" % (_(u"Creation mode"), - _(u"To start drawing the route click on the toggle button: "\ - u"\"Draw\"."), - _(u"Then click on the map to begin the drawing."), - _(u"You can add points by clicking again."), - _(u"To finish the drawing double click. When the drawing is "\ - u"finished you can edit it."), - _(u"While creating to undo a drawing click again on the toggle "\ - u"button \"Stop drawing\".")) - help_modify = u"<h3>%s</h3>\n"\ - u"<p>%s</p>\n"\ - u"<p>%s</p>\n"\ - u"<p>%s</p>\n" % (_(u"Modification mode"), - _(u"To move a point click on it and drag it to the desired position."), - _(u"To delete a point move the mouse cursor over it and press the "\ - u"\"d\" or \"Del\" key."), - _(u"To add a point click in the middle of a segment and drag the new "\ - u"point to the desired position")) + u"<p>%s</p>\n" % ( + _(u"Modification mode"), + _(u"To move a point click on it and drag it to the desired " + u"position."), + _(u"To delete a point move the mouse cursor over it and press " + u"the \"d\" or \"Del\" key."), + _(u"To add a point click in the middle of a segment and drag " + u"the new point to the desired position")) if not value: # upload a file tpl += u"<script type='text/javascript'><!--\n"\ u" var error_msg = \"%s\";"\ - u"// --></script>" % ( - _(u"Give a name and set category before uploading a file.")) + u"// --></script>" % \ + _(u"Give a name and set category before uploading a file.") tpl += u'<div id="upload"><a href="#" class="upload-button" '\ - u'onclick="uploadFile(error_msg);return false;">%s</a></div>' % ( - _(u"Upload a route file (GPX or KML)")) + u'onclick="uploadFile(error_msg);return false;">%s</a></div>' \ + % (_(u"Upload a route file (GPX or KML)")) tpl += u"\n<p id='draw-or'>%s</p>\n" % _(u"or") tpl += u"<div id='draw-label'><div id='draw-toggle-off' "\ u"onclick='toggleDraw();'>\n"\ @@ -416,25 +454,26 @@ class RouteChooserWidget(forms.TextInput): if value: style = " style='display:block'" tpl += u"\n<div class='help-route' id='help-route-modify'%s>%s</div>"\ - u"\n<hr class='spacer'/>\n"\ - u"<input type='hidden' name='%s' id='id_%s' value=\"%s\"/>\n"\ - u"<input type='hidden' name='associated_file_id' "\ - u"id='id_associated_file_id' value=\"%s\"/>\n" % ( - style, help_modify, name, name, value, routefile_id) + u"\n<hr class='spacer'/>\n"\ + u"<input type='hidden' name='%s' id='id_%s' value=\"%s\"/>\n"\ + u"<input type='hidden' name='associated_file_id' "\ + u"id='id_associated_file_id' value=\"%s\"/>\n" % ( + style, help_modify, name, name, value, routefile_id) if value: tpl += u"\n<div id='map_edit'></div>" else: tpl += "\n<div class='help-route' id='help-route-create'>%s</div>"\ % help_create - tpl += u"\n<div id='map_edit'>\n"\ - u" <div class='map_button'>\n"\ - u" <a href='#' id='button-move-map' class='toggle-button "\ - u"toggle-button-active' onclick='toggleDrawOff();return false;'>%s"\ - u"</a>\n"\ - u"<a href='#' id='button-draw-map' class='toggle-button "\ - u"toggle-button-inactive' onclick='toggleDrawOn();return false;'>"\ - u"%s</a></div>\n"\ - u" </div>" % (_(u"Move on the map"), _(u"Draw")) + tpl += \ + u"\n<div id='map_edit'>\n"\ + u" <div class='map_button'>\n"\ + u" <a href='#' id='button-move-map' class='toggle-button "\ + u"toggle-button-active' "\ + u"onclick='toggleDrawOff();return false;'>%s</a>\n"\ + u"<a href='#' id='button-draw-map' class='toggle-button "\ + u"toggle-button-inactive' "\ + u"onclick='toggleDrawOn();return false;'>%s</a></div>\n"\ + u" </div>" % (_(u"Move on the map"), _(u"Draw")) tpl += u"<script type='text/javascript'><!--\n" if not value: tpl += u"jQuery('#map_edit').hide();" @@ -453,6 +492,7 @@ class RouteChooserWidget(forms.TextInput): tpl += u"\n// --></script>\n" return mark_safe(tpl) + class RouteField(models.LineStringField): ''' Set the widget for the form field @@ -462,18 +502,19 @@ class RouteField(models.LineStringField): keys.update(defaults) return super(RouteField, self).formfield(**keys) + class AreaWidget(forms.TextInput): """ Manage the edition of an area on the map """ class Media: css = { - "all": settings.MAP_CSS_URLS + \ - ["%schimere/css/forms.css" % settings.STATIC_URL,] + "all": settings.MAP_CSS_URLS + + ["%schimere/css/forms.css" % settings.STATIC_URL] } js = settings.MAP_JS_URLS + [ - "%schimere/js/edit_area.js" % settings.STATIC_URL, - "%schimere/js/base.js" % settings.STATIC_URL,] + "%schimere/js/edit_area.js" % settings.STATIC_URL, + "%schimere/js/base.js" % settings.STATIC_URL] def get_bounding_box_from_value(self, value): ''' @@ -483,7 +524,7 @@ class AreaWidget(forms.TextInput): lower_right_lat, lower_right_lon = 0, 0 if not value: return upper_left_lat, upper_left_lon, lower_right_lat, \ - lower_right_lon + lower_right_lon if len(value) == 2: upper_left = value[0] lower_right = value[1] @@ -497,7 +538,7 @@ class AreaWidget(forms.TextInput): pass if hasattr(lower_right, 'x') and hasattr(lower_right, 'y'): lower_right_lon, lower_right_lat = lower_right.x, \ - lower_right.y + lower_right.y elif len(lower_right) == 2: lower_right_lon, lower_right_lat = lower_right try: @@ -512,29 +553,30 @@ class AreaWidget(forms.TextInput): Render a map """ upper_left_lat, upper_left_lon, lower_right_lat, lower_right_lon = \ - self.get_bounding_box_from_value(value) + self.get_bounding_box_from_value(value) tpl = getMapJS() tpl += u"</div>\n"\ - u"<input type='hidden' name='upper_left_lat' id='upper_left_lat' "\ - u"value='%f'/>\n"\ - u"<input type='hidden' name='upper_left_lon' id='upper_left_lon' "\ - u"value='%f'/>\n"\ - u"<input type='hidden' name='lower_right_lat' id='lower_right_lat' "\ - u"value='%f'/>\n"\ - u"<input type='hidden' name='lower_right_lon' id='lower_right_lon' "\ - u"value='%f'/>\n" % ( - upper_left_lat, upper_left_lon, lower_right_lat, lower_right_lon) + u"<input type='hidden' name='upper_left_lat' id='upper_left_lat' "\ + u"value='%f'/>\n"\ + u"<input type='hidden' name='upper_left_lon' id='upper_left_lon' "\ + u"value='%f'/>\n"\ + u"<input type='hidden' name='lower_right_lat' id='lower_right_lat'"\ + u" value='%f'/>\n"\ + u"<input type='hidden' name='lower_right_lon' id='lower_right_lon'"\ + u" value='%f'/>\n" % ( + upper_left_lat, upper_left_lon, lower_right_lat, + lower_right_lon) help_msg = _(u"Hold CTRL, click and drag to select area on the map") tpl += u"<p class='help-osm'>%s</p>\n" % help_msg tpl += u"<script type='text/javascript'>\n" tpl += u"function init_map_form (){\ninit('map_edit_area');\n" if value: tpl += u"var extent = new OpenLayers.Bounds(%f, %f, %f, %f);\n"\ - u"extent.transform(epsg_display_projection, epsg_projection);\n"\ - u"updateForm(extent);\n"\ - u"area_map.zoomToExtent(extent, true);\n"\ - u"area_map.zoomOut();" % (upper_left_lon, upper_left_lat, - lower_right_lon, lower_right_lat) + u"extent.transform(epsg_display_projection, epsg_projection);\n"\ + u"updateForm(extent);\n"\ + u"area_map.zoomToExtent(extent, true);\n"\ + u"area_map.zoomOut();" % (upper_left_lon, upper_left_lat, + lower_right_lon, lower_right_lat) tpl += u"}\n" if initialized: tpl += u"$(document).ready(function($) {init_map_form()});\n" @@ -558,8 +600,10 @@ class AreaWidget(forms.TextInput): values.append(value) return values -RE_XAPI = re.compile('(node|way)\[(.*=.*)\]\[bbox='\ - '(-*[0-9]*.[0-9]*,-*[0-9]*.[0-9]*,-*[0-9]*.[0-9]*,-*[0-9]*.[0-9]*)\]') +RE_XAPI = re.compile( + '(node|way)\[(.*=.*)\]\[bbox=' + '(-*[0-9]*.[0-9]*,-*[0-9]*.[0-9]*,-*[0-9]*.[0-9]*,-*[0-9]*.[0-9]*)\]') + class ImportFiltrWidget(AreaWidget): """ @@ -567,53 +611,55 @@ class ImportFiltrWidget(AreaWidget): """ class Media: css = { - "all": settings.MAP_CSS_URLS + \ - ["%schimere/css/forms.css" % settings.STATIC_URL,] + "all": settings.MAP_CSS_URLS + + ["%schimere/css/forms.css" % settings.STATIC_URL] } js = settings.MAP_JS_URLS + [ - "%schimere/js/edit_area.js" % settings.STATIC_URL, - "%schimere/js/base.js" % settings.STATIC_URL,] + "%schimere/js/edit_area.js" % settings.STATIC_URL, + "%schimere/js/base.js" % settings.STATIC_URL] def render(self, name, value, attrs=None): """ Render a map """ tpl = super(ImportFiltrWidget, self).render(name, value, attrs, - initialized=False) + initialized=False) tpl += u"</div><hr class='spacer'/>" - vals = {'lbl':_(u"Type:"), 'name':name, 'node':_(u"Node"), - 'way':_(u"Way")} + vals = {'lbl': _(u"Type:"), 'name': name, 'node': _(u"Node"), + 'way': _(u"Way")} vals['way_selected'] = ' checked="checked"'\ - if self.xapi_type == 'way' else '' + if self.xapi_type == 'way' else '' vals['node_selected'] = ' checked="checked"'\ - if self.xapi_type == 'node' else '' + if self.xapi_type == 'node' else '' tpl += u"<div class='input-osm'><label>%(lbl)s</label>"\ - u"<input type='radio' name='id_%(name)s_type' id='id_%(name)s_node'"\ - u" value='node'%(node_selected)s/> <label for='id_%(name)s_node'>"\ - u"%(node)s</label> <input type='radio' name='id_%(name)s_type' "\ - u"id='id_%(name)s_way' value='way'%(way_selected)s/> <label "\ - u"for='id_%(name)s_way'>%(way)s</label></div>" % vals - help_msg = _(u"Enter an OSM \"tag=value\" string such as "\ - u"\"amenity=pub\". A list of common tag is available "\ - u"<a href='https://wiki.openstreetmap.org/wiki/Map_Features' "\ - u" target='_blank'>here</a>.") + u"<input type='radio' name='id_%(name)s_type' "\ + u"id='id_%(name)s_node' value='node'%(node_selected)s/> "\ + u"<label for='id_%(name)s_node'>"\ + u"%(node)s</label> <input type='radio' name='id_%(name)s_type' "\ + u"id='id_%(name)s_way' value='way'%(way_selected)s/> <label "\ + u"for='id_%(name)s_way'>%(way)s</label></div>" % vals + help_msg = _( + u"Enter an OSM \"tag=value\" string such as " + u"\"amenity=pub\". A list of common tag is available " + u"<a href='https://wiki.openstreetmap.org/wiki/Map_Features' " + u" target='_blank'>here</a>.") tpl += u"<p class='help-osm'>%s</p>\n" % help_msg tpl += u"<div class='input-osm'><label for='id_%s_tag'>%s</label>"\ u"<input type='text' id='id_%s_tag' value=\"%s\"/></div>" % ( - name, _(u"Tag:"), name, self.xapi_tag) + name, _(u"Tag:"), name, self.xapi_tag) tpl += u"<script type='text/javascript'>\n" tpl += u"var default_xapi='%s';" % settings.CHIMERE_XAPI_URL tpl += u'var msg_missing_area = "%s";' % \ - _(u"You have to select an area.") + _(u"You have to select an area.") tpl += u'var msg_missing_type = "%s";' % \ - _(u"You have to select a type.") + _(u"You have to select a type.") tpl += u'var msg_missing_filtr = "%s";' % \ - _(u"You have to insert a filter tag.") + _(u"You have to insert a filter tag.") tpl += u"</script>\n" - help_msg = _(u"If you change the above form don't forget to refresh "\ + help_msg = _(u"If you change the above form don't forget to refresh " u"before submit!") tpl += u"<p class='help-osm errornote'>%s</p>\n" % help_msg - help_msg = _(u"You can put a Folder name of the KML file to filter on "\ + help_msg = _(u"You can put a Folder name of the KML file to filter on " u"it.") tpl += u"<p class='help-kml'>%s</p>\n" % help_msg if not value: @@ -628,7 +674,7 @@ class ImportFiltrWidget(AreaWidget): """ Return the appropriate values """ - return data.get('id_'+name, None) + return data.get('id_' + name, None) def get_bounding_box_from_value(self, value): ''' @@ -640,17 +686,18 @@ class ImportFiltrWidget(AreaWidget): self.xapi_type, self.xapi_tag, self.bounding_box = None, '', None if not value: return upper_left_lat, upper_left_lon, lower_right_lat, \ - lower_right_lon + lower_right_lon xapi_m = RE_XAPI.match(value) if not xapi_m: return upper_left_lat, upper_left_lon, lower_right_lat, \ - lower_right_lon + lower_right_lon # as the regexp pass, we could be pretty confident self.xapi_type, self.xapi_tag, self.bounding_box = xapi_m.groups() upper_left_lon, lower_right_lat, lower_right_lon, upper_left_lat = \ - self.bounding_box.split(',') + self.bounding_box.split(',') return float(upper_left_lat), float(upper_left_lon), \ - float(lower_right_lat), float(lower_right_lon) + float(lower_right_lat), float(lower_right_lon) + class AreaField(forms.MultiValueField): ''' @@ -663,33 +710,36 @@ class AreaField(forms.MultiValueField): return None return data_list + class MultiSelectWidget(forms.SelectMultiple): class Media: css = {'all': list(settings.JQUERY_CSS_URLS) + [ settings.STATIC_URL + 'bsmSelect/css/jquery.bsmselect.css', settings.STATIC_URL + 'bsmSelect/css/jquery.bsmselect.custom.css', - ] + ] } js = list(settings.JQUERY_JS_URLS) + [ settings.STATIC_URL + 'bsmSelect/js/jquery.bsmselect.js', - settings.STATIC_URL + 'bsmSelect/js/jquery.bsmselect.compatibility.js', - ] + settings.STATIC_URL + + 'bsmSelect/js/jquery.bsmselect.compatibility.js', + ] def render(self, name, value, attrs=None): rendered = super(MultiSelectWidget, self).render(name, value, attrs) rendered += u"<hr class='spacer'/><script type='text/javascript'>\n"\ - u"$.bsmSelect.conf['title'] = \"%(title)s\";\n"\ - u"$(\"#id_%(name)s\").bsmSelect({\n"\ - u" removeLabel: '<strong>X</strong>',\n"\ - u" containerClass: 'bsmContainer',\n"\ - u" listClass: 'bsmList-custom',\n"\ - u" listItemClass: 'bsmListItem-custom',\n"\ - u" listItemLabelClass: 'bsmListItemLabel-custom',\n"\ - u" removeClass: 'bsmListItemRemove-custom'\n"\ - u"});\n"\ - u"</script>\n" % {'name':name, 'title':_("Select...")} + u"$.bsmSelect.conf['title'] = \"%(title)s\";\n"\ + u"$(\"#id_%(name)s\").bsmSelect({\n"\ + u" removeLabel: '<strong>X</strong>',\n"\ + u" containerClass: 'bsmContainer',\n"\ + u" listClass: 'bsmList-custom',\n"\ + u" listItemClass: 'bsmListItem-custom',\n"\ + u" listItemLabelClass: 'bsmListItemLabel-custom',\n"\ + u" removeClass: 'bsmListItemRemove-custom'\n"\ + u"});\n"\ + u"</script>\n" % {'name': name, 'title': _("Select...")} return mark_safe(rendered) + class SelectMultipleField(models.ManyToManyField): ''' Set the widget for the category field |