Projet

Général

Profil

0001-map-field-5668.patch

Frédéric Péters, 17 octobre 2014 17:38

Télécharger (8,71 ko)

Voir les différences:

Subject: [PATCH] map field (#5668)

 wcs/fields.py                      | 51 ++++++++++++++++++++++++++++++++++++++
 wcs/qommon/form.py                 | 35 ++++++++++++++++++++++++++
 wcs/qommon/http_response.py        |  4 +++
 wcs/qommon/static/css/qommon.css   |  4 +++
 wcs/qommon/static/js/qommon.map.js | 51 ++++++++++++++++++++++++++++++++++++++
 wcs/root.py                        |  4 +++
 6 files changed, 149 insertions(+)
 create mode 100644 wcs/qommon/static/js/qommon.map.js
wcs/fields.py
15 15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16 16

  
17 17
import time
18
import random
18 19
import re
19 20
import xml.etree.ElementTree as ET
20 21

  
......
1348 1349
register_field_class(TableRowsField)
1349 1350

  
1350 1351

  
1352
class MapField(WidgetField):
1353
    key = 'map'
1354
    description = N_('Map')
1355

  
1356
    initial_zoom = None
1357
    min_zoom = None
1358
    max_zoom = None
1359
    default_position = None
1360
    init_with_geoloc = False
1361

  
1362
    widget_class = MapWidget
1363
    extra_attributes = ['initial_zoom', 'min_zoom', 'max_zoom',
1364
            'default_position', 'init_with_geoloc']
1365

  
1366
    def fill_admin_form(self, form):
1367
        WidgetField.fill_admin_form(self, form)
1368
        # 0: whole world, 9: wide area, 11: area, 13: town, 16: small road
1369
        zoom_levels = [(None, '---'),
1370
                ('0', _('Whole world')),
1371
                ('9', _('Wide area')),
1372
                ('11', _('Area')),
1373
                ('13', _('Town')),
1374
                ('16', _('Small road'))]
1375
        form.add(SingleSelectWidget, 'initial_zoom', title=_('Initial zoom level'),
1376
                value=self.initial_zoom or '13', options=zoom_levels)
1377
        form.add(SingleSelectWidget, 'min_zoom', title=_('Minimal zoom level'),
1378
                value=self.min_zoom, options=zoom_levels, required=False)
1379
        form.add(SingleSelectWidget, 'max_zoom', title=_('Maximal zoom level'),
1380
                value=self.max_zoom, options=zoom_levels, required=False)
1381
        form.add(MapWidget, 'default_position', title=_('Initial Position'),
1382
                value=self.default_position, default_zoom='9', required=False)
1383
        form.add(CheckboxWidget, 'init_with_geoloc',
1384
                title=_('Initialize position using device geolocation'),
1385
                value=self.init_with_geoloc, required=False)
1386

  
1387
    def get_admin_attributes(self):
1388
        return WidgetField.get_admin_attributes(self) + ['initial_zoom',
1389
                'min_zoom', 'max_zoom', 'default_position',
1390
                'init_with_geoloc']
1391

  
1392
    def get_view_value(self, value):
1393
        widget = self.widget_class('x%s' % random.random(), value, readonly=True)
1394
        return widget.render_content()
1395

  
1396
    def get_rst_view_value(self, value, indent=''):
1397
        return indent + value
1398

  
1399
register_field_class(MapField)
1400

  
1401

  
1351 1402
class RankedItemsField(WidgetField):
1352 1403
    key = 'ranked-items'
1353 1404
    description = N_('Ranked Items')
wcs/qommon/form.py
1747 1747
            self.value = hashlib.sha1(pwd1).hexdigest()
1748 1748
        else:
1749 1749
            self.value = None
1750

  
1751

  
1752
class MapWidget(CompositeWidget):
1753
    def __init__(self, name, value=None, **kwargs):
1754
        CompositeWidget.__init__(self, name, value, **kwargs)
1755
        self.add(HiddenWidget, 'latlng')
1756
        self.readonly = kwargs.pop('readonly', False)
1757
        self.kwargs = kwargs
1758

  
1759
    def render_content(self):
1760
        get_response().add_javascript(['qommon.map.js'])
1761
        r = TemplateIO(html=True)
1762
        for widget in self.get_widgets():
1763
            r += widget.render()
1764
        attrs = {
1765
            'class': 'qommon-map',
1766
            'id': 'map-%s' % self.name,
1767
        }
1768
        if self.value:
1769
            attrs['data-init-lat'], attrs['data-init-lng'] = self.value.split(';')
1770
        if self.readonly:
1771
            attrs['data-readonly'] = 'true'
1772
        for attribute in ('initial_zoom', 'min_zoom', 'max_zoom'):
1773
            if attribute in self.kwargs:
1774
                attrs['data-%s' % attribute] = self.kwargs.get(attribute)
1775
        if self.kwargs.get('default_position'):
1776
            attrs['data-def-lat'], attrs['data-def-lng'] = self.kwargs.get('default_position').split(';')
1777
        if self.kwargs.get('init_with_geoloc'):
1778
            attrs['data-init-with-geologc'] = 1
1779
        r += htmltext('<div %s></div>' % ' '.join(['%s="%s"' % x for x in attrs.items()]))
1780
        return r.getvalue()
1781

  
1782
    def _parse(self, request):
1783
        CompositeWidget._parse(self, request)
1784
        self.value = self.get('latlng')
wcs/qommon/http_response.py
61 61
            self.javascript_scripts = []
62 62
        for script_name in script_names:
63 63
            if not script_name in self.javascript_scripts:
64
                if script_name == 'qommon.map.js':
65
                    self.add_javascript(['jquery.js'])
66
                    self.add_javascript(['../../leaflet/leaflet.js'])
67
                    self.add_css_include('../../leaflet/leaflet.css')
64 68
                self.javascript_scripts.append(str(script_name))
65 69
                if script_name == 'afterjob.js':
66 70
                    self.add_javascript_code('var QOMMON_ROOT_URL = "%s";\n' % \
wcs/qommon/static/css/qommon.css
389 389
        outline: 0;
390 390
        border: 1px solid #aaa;
391 391
}
392

  
393
div.qommon-map {
394
	height: 280px;
395
}
wcs/qommon/static/js/qommon.map.js
1
$(function() {
2
  $('.qommon-map').each(function() {
3
     var map_options = Object();
4
     var initial_zoom = parseInt($(this).data('initial_zoom'));
5
     if (! isNaN(initial_zoom)) {
6
       map_options.zoom = initial_zoom;
7
     } else {
8
       map_options.zoom = 13;
9
     }
10
     var max_zoom = parseInt($(this).data('max_zoom'));
11
     if (! isNaN(max_zoom)) map_options.maxZoom = max_zoom;
12
     var min_zoom = parseInt($(this).data('min_zoom'));
13
     if (! isNaN(min_zoom)) map_options.minZoom = min_zoom;
14
     var map = L.map($(this).attr('id'), map_options);
15
     var hidden = $(this).prev();
16
     map.marker = null;
17
     var latlng;
18
     if ($(this).data('init-lat')) {
19
       latlng = [$(this).data('init-lat'), $(this).data('init-lng')]
20
       map.marker = L.marker(latlng);
21
       map.marker.addTo(map);
22
     } else if ($(this).data('def-lat')) {
23
       latlng = [$(this).data('def-lat'), $(this).data('def-lng')]
24
     } else {
25
       latlng = [50.84, 4.36];
26
     }
27
     map.setView(latlng, map_options.zoom);
28
     L.tileLayer(
29
        'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
30
        {
31
                attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
32
        }).addTo(map);
33
     if (! $(this).data('readonly')) {
34
       map.on('click', function(e) {
35
         if (map.marker === null) {
36
           map.marker = L.marker([0, 0]);
37
           map.marker.addTo(map);
38
         }
39
         map.marker.setLatLng(e.latlng);
40
         hidden.val(e.latlng.lat + ';' + e.latlng.lng);
41
       });
42
     }
43
     if ($(this).data('init-with-geoloc')) {
44
       map.on('locationfound', function(e) {
45
         hidden.val(e.latlng.lat + ';' + e.latlng.lng);
46
         map.setView(e.latlng, map_options.zoom);
47
       });
48
       map.locate({timeout: 1000, maximumAge: 60000});
49
     }
50
  });
51
});
wcs/root.py
359 359
            dirname = os.path.join(get_publisher().data_dir, 'qommon')
360 360
            return StaticDirectory(dirname, follow_symlinks = True)
361 361

  
362
        # maps /leaflet/ to the directory provided by the libjs-openlayers package
363
        if component == 'leaflet':
364
            return StaticDirectory('/usr/share/javascript/leaflet')
365

  
362 366
        # is this a category ?
363 367
        try:
364 368
            category = Category.get_by_urlname(component)
365
-