# -*- coding: utf-8 -*- from datetime import datetime, timedelta from os import mkdir from os.path import join from re import match, sub from collections import defaultdict from sqlite3 import IntegrityError from operator import attrgetter from trac.config import * from trac.core import Component, implements, TracError from trac.perm import PermissionError, IPermissionRequestor from trac.resource import Resource, get_resource_url, get_resource_name from trac.util import get_reporter_id from trac.util.text import to_unicode from trac.util.datefmt import utc, get_timezone, localtz, timezone from trac.util.translation import _ from trac.util.html import html from trac.web.chrome import INavigationContributor, ITemplateProvider, add_stylesheet, add_warning, add_notice, add_ctxtnav, add_script from trac.web import IRequestHandler from genshi.builder import tag from tracrendezvous.location.loc_xml import * from tracrendezvous.location.model import * from tracrendezvous.location.utils import * __all__ = ['LocationModule',] class LocationModule(Component): '''The web ui frontend for the location management system''' implements(INavigationContributor, IRequestHandler, IPermissionRequestor, ITemplateProvider) # INavigationContributor methods def get_active_navigation_item(self, req): return 'location' def get_navigation_items(self, req): if "LOCATION_VIEW" in req.perm: yield ('mainnav', 'location', html.A('Locations', href=req.href.location())) # IPermissionRequestor methods def get_permission_actions(self): '''returns all permissions this component provides''' return ['LOCATION_VIEW', 'LOCATION_ADD', 'LOCATION_DELETE', 'LOCATION_MODIFY', ('LOCATION_ADMIN', ('LOCATION_VIEW', 'LOCATION_ADD', 'LOCATION_DELETE', 'LOCATION_MODIFY'))] def match_request(self, req): self.env.log.debug("LocationModule.match_request %r\n" % req.__dict__) res = req.path_info == "/location" self.env.log.debug("LocationModule.match_request res = %r\n" % res) return res def process_request(self, req): self.env.log.debug("LocationModule.process_request %r\n" % req.__dict__) '''process add,change,delete actions''' req.perm.require("LOCATION_VIEW") #add_stylesheet(req, 'hw/css/base.css') add_stylesheet (req, 'hw/css/location.css') #add_stylesheet (req, 'hw/css/map.css') add_script(req, 'http://www.openlayers.org/api/OpenLayers.js') add_script(req, 'http://www.openstreetmap.org/openlayers/OpenStreetMap.js') add_script(req, 'hw/script/tom.js') data = {"results": []} if req.args.has_key("from") and req.args.has_key("id"): req.session["from"] = req.args["from"] req.session["id"] = req.args["id"] req.session.save() if req.session.has_key("edited"): try: from_resource = req.session.get("from") resource_id = int(req.session.get("id")) resource = Resource(from_resource, id=resource_id) link = get_resource_url(self.env, resource, req.href) add_notice(req, tag.p("Location edited successfully. Back to " , tag.a(get_resource_description(self.env, resource, "summary"), href=link))) del req.session["from"] del req.session["id"] except Exception, e: add_notice(req, _("Location edited successfully.")) del req.session["edited"] req.session.save() if req.session.has_key("added"): try: from_resource = req.args.get("from") resource_id = int(req.args.get("id")) resource = Resource(from_resource, id=resource_id) link = get_resource_url(from_resource, resource_id) add_notice(req, tag.p(_("Location created successfully. Back to ") % resource, tag.a(resource, href=link))) except Exception: add_notice(req, _("Location created successfully.")) del req.session["added"] req.session.save() if req.method == "POST": if req.args.has_key("location_search"): query = unicode(req.args["location_search"]) results = search_location(query) data["location_results"] = results if req.args.has_key("savelocations"): req.perm.require("LOCATION_MODIFY") deleted = [] locations = {} changed = {} if req.args.has_key("default"): default_location = self.config.getint("rendezvous", "default_location") default = int(req.args["default"]) if default_location != default: default_location = default self.config.set("rendezvous", "default_location", default) self.config.save() for key in req.args: kind = location_id = None try: kind, location_id = key.split(":", 1) except ValueError: continue location_id = int(location_id) if location_id in deleted: continue if not locations.has_key(location_id): location = ItemLocation.fetch_one(self.env, location_id) if not location: add_warning(req, "Could not find ItemLocation with location_id '%d'" % location_id) continue locations[location_id] = location if kind == "delete": req.perm.require("LOCATION_DELETE") ItemLocation.delete(self.env, location_id) deleted.append(location_id) del locations[location_id] elif kind == "name": name = req.args[key] if not name: add_warning(req, "location name must be specified for ItemLocation '%d'" % location_id) continue if name != locations[location_id].name: locations[location_id].name = name changed[location_id] = True elif kind == "location": coordinates = req.args[key] if coordinates: try: lat, lon = validate_dd_coordinates(coordinates) lat_side, lat_deg, lat_min, lat_sec, lon_side, lon_deg, lon_min, lon_sec = convert_dd_2_dms(lat, lon) except ValueError: try: lat_side, lat_deg, lat_min, lat_sec, lon_side, lon_deg, lon_min, lon_sec = validate_dms_coordinates(coordinates) lat, lon = convert_dms_2_dd(lat_side, lat_deg, lat_min, lat_sec, lon_side, lon_deg, lon_min, lon_sec) except ValueError: add_warning(req, "coordinates have wrong format") continue if lat != location.lat: location.lat = lat changed[location_id] = True if lon != location.lon: location.lon = lon changed[location_id] = True if lat_side != location.lat_side: location.lat_side = lat_side changed[location_id] = True if lat_deg != location.lat_deg: location.lat_deg = lat_deg changed[location_id] = True if lat_min != location.lat_min: location.lat_min = lat_min changed[location_id] = True if lat_sec != location.lat_sec: location.lat_sec= lat_sec changed[location_id] = True if lon_side != location.lon_side: location.lon_side = lon_side changed[location_id] = True if lon_deg != location.lon_deg: location.lon_deg = lon_deg changed[location_id] = True if lon_min != location.lon_min: location.lon_min = lon_min changed[location_id] = True if lon_sec != location.lon_sec: location.lon_sec = lon_sec changed[location_id] = True done=True for dvi in changed: if dvi not in deleted: try: locations[dvi].update() except Exception, err: add_warning(req, str(err)) done=False continue if done: req.session["edited"] = True req.session.save() req.redirect(req.href.location()) if req.args.has_key("addlocation") and req.args.has_key("location_name"): req.perm.require("LOCATION_ADD") rl = ItemLocation(self.env, name=req.args["location_name"]) is_valid = True if not rl.name: add_warning(req, "Coordinate name is empty") is_valid = False if req.args.has_key("coordinates"): coordinates = unicode(req.args["coordinates"]) if coordinates: try: rl.lat, rl.lon = validate_dd_coordinates(coordinates) rl.lat_side, rl.lat_deg, rl.lat_min, rl.lat_sec, rl.lon_side, rl.lon_deg, rl.lon_min, rl.lon_sec = convert_dd_2_dms(rl.lat, rl.lon) except ValueError: try: rl.lat_side, rl.lat_deg, rl.lat_min, rl.lat_sec, rl.lon_side, rl.lon_deg, rl.lon_min, rl.lon_sec = validate_dms_coordinates(coordinates) rl.lat, rl.lon = convert_dms_2_dd(rl.lat_side, rl.lat_deg, rl.lat_min, rl.lat_sec, rl.lon_side, rl.lon_deg, rl.lon_min, rl.lon_sec) except ValueError: add_warning(req, "coordinates have wrong format") is_valid = False if is_valid: rl.commit() req.session["added"] = True req.session.save() req.redirect(req.href.location()) data.update({"results" : None, "default_location" : self.config.getint("rendezvous", "default_location"), "locations" : ItemLocation.fetch_all(self.env)}) return 'location.html', data, None # ITemplateProvider methods def get_templates_dirs(self): from pkg_resources import resource_filename return [resource_filename(__name__, 'templates')] def get_htdocs_dirs(self): from pkg_resources import resource_filename return [('hw', resource_filename(__name__, 'htdocs'))]