Exemplo n.º 1
0
def add_filter(request, view_id):
    """ Respond to the "/add_filter/NNN/" URL.

        We let the user add a new filter to the given tableau view.
    """
    if not request.user.is_authenticated:
        return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW))

    try:
        view = TableauView.objects.get(id=view_id)
    except TableauView.DoesNotExist:
        return HttpResponseRedirect(reverse("location_editor.views.main"))

    # See what the user wants to do.

    if request.method == "POST":
        # The user is submitting the form.  See what the user wants to do.

        if request.POST.get("cancel") != None:
            # The user clicked on the "Cancel" button -> redirect the user back
            # to the "Edit View" page for this view.
            return HttpResponseRedirect(
                        reverse("tableau_editor.views.edit_view",
                                args=[view.id]))

        # If we get here, the user wants to add a new view filter.

        type = request.POST.get("type")

        filter = TableauViewFilter()
        filter.tableauView = view

        if type == "cur_loc":
            filter.type  = TableauViewFilter.TYPE_CUR_LOCATION
            filter.value = ""
        elif type == "level":
            filter.type  = TableauViewFilter.TYPE_LEVEL
            filter.value = ""
        elif type == "location":
            filter.type  = TableauViewFilter.TYPE_LOCATION
            filter.value = ""
        elif type == "parents":
            filter.type  = TableauViewFilter.TYPE_RELATION
            filter.value = "parent"
        elif type == "children":
            filter.type  = TableauViewFilter.TYPE_RELATION
            filter.value = "child"
        elif type == "neighbors":
            filter.type  = TableauViewFilter.TYPE_RELATION
            filter.value = "neighbor"
        elif type == "peers":
            filter.type  = TableauViewFilter.TYPE_RELATION
            filter.value = "peer"
        else:
            filter.type  = TableauViewFilter.TYPE_LEVEL
            filter.value = ""
        
        filter.save()   

        return HttpResponseRedirect(
                    reverse("tableau_editor.views.edit_view",
                            args=[view.id]))

    # If we get here, we're displaying the form for the first time -> do so.

    cur_loc = view.tableau.location

    menu_html = menus.generate(request, "Tableau Editor",
                               "tableau_editor", "add_filter")

    return render_to_response("tableau_editor/templates/add_view_filter.html",
                              {'menu_html' : menu_html,
                               'heading'   : "Add Filter for Tableau View '" +
                                             view.name + "'",
                               'cur_loc'   : cur_loc,
                              },
                              context_instance=RequestContext(request))
Exemplo n.º 2
0
def create_tableau(factory, location):
    """ Create a single tableau for a given location using a given factory.

        This function does the actual work of generating an individual tableau
        based upon the factory definition.  It can be called directly to
        generate a desired tableau, or it can be called indirectly by the
        daemon (using the private 'create_tableau' API call) to generate
        tableaux en masse.

        Upon completion, we return None if the tableau-generation attempt was
        successful.  Otherwise, we return a suitable error message explaining
        why the tableau could not be generated.
    """
    # Get the location's outline.

    try:
        outline = Outline.objects.get(location=location)
    except Outline.DoesNotExist:
        # We can't create a tableau for a location without an outline ->
        # tell the user the bad news.
        return "Location has no outline."

    # Delete the existing tableau with this name, if any.

    Tableau.objects.filter(location=location,
                           name=factory.tableau_name).delete()

    # Create the new Tableau for this location.

    tableau = Tableau()
    tableau.location      = location
    tableau.name          = factory.tableau_name
    tableau.meta_data     = factory.tableau_meta_data
    tableau.bounds_render = factory.tableau_bounds_render
    tableau.save()

    # Create a single view for the tableau, covering the location's entire
    # extent.

    min_long,min_lat,max_long,max_lat = outline.outline.extent

    # Add a margin around the edges so that the location is easier to see.

    width = abs(max_long - min_long)
    height = abs(max_lat - min_lat)

    buffer = 0.02 * (width + height) / 2

    min_long = min_long - buffer
    max_long = max_long + buffer
    min_lat  = min_lat  - buffer
    max_lat  = max_lat  + buffer

    # Ensure the calculated view bounds are allowable.

    if min_lat < MIN_ALLOWED_LATITUDE:
        min_lat = MIN_ALLOWED_LATITUDE
    elif min_lat > MAX_ALLOWED_LATITUDE:
        min_lat = MAX_ALLOWED_LATITUDE

    if max_lat < MIN_ALLOWED_LATITUDE:
        max_lat = MIN_ALLOWED_LATITUDE
    elif max_lat > MAX_ALLOWED_LATITUDE:
        max_lat = MAX_ALLOWED_LATITUDE

    if min_long < MIN_ALLOWED_LONGITUDE:
        min_long = MIN_ALLOWED_LONGITUDE
    elif min_long > MAX_ALLOWED_LONGITUDE:
        min_long = MAX_ALLOWED_LONGITUDE

    if max_long < MIN_ALLOWED_LONGITUDE:
        max_long = MIN_ALLOWED_LONGITUDE
    elif max_long > MAX_ALLOWED_LONGITUDE:
        max_long = MAX_ALLOWED_LONGITUDE

    # Create the view.

    view = TableauView()
    view.tableau       = tableau
    view.ordinal_rank  = 1
    view.name          = location.display_name
    view.min_lat       = "%0.4f" % min_lat
    view.max_lat       = "%0.4f" % max_lat
    view.min_long      = "%0.4f" % min_long
    view.max_long      = "%0.4f" % max_long
    view.meta_data     = factory.view_meta_data
    view.bounds_render = factory.view_bounds_render
    view.save()

    # Add the factory's filter(s) to the tableau's view.

    for factory_filter in factory.tableaufactoryviewfilter_set.all():
        filter = TableauViewFilter()
        filter.tableauView    = view
        filter.type           = factory_filter.filter_type
        filter.value          = factory_filter.filter_value
        filter.meta_data      = factory_filter.filter_meta_data
        filter.draw_bubbles   = factory_filter.filter_draw_bubbles
        filter.polygon_render = factory_filter.filter_polygon_render
        filter.bubble_render  = factory_filter.filter_bubble_render
        filter.save()

    # Calculate the aspect ratio for the tableau's view.

    proj = GlobalMercator()

    min_x,min_y = proj.LatLonToMeters(min_lat, min_long)
    max_x,max_y = proj.LatLonToMeters(max_lat, max_long)

    viewWidth  = max_x - min_x
    viewHeight = max_y - min_y

    if viewWidth == 0: viewWidth = 1.0
    if viewHeight == 0: viewHeight = 1.0

    aspectRatio = viewWidth / viewHeight

    # Create a single layout for the tableau.  The size of the layout is
    # based on the view's aspect ratio.

    layout_width = LAYOUT_MAX_WIDTH
    layout_height = layout_width / aspectRatio

    if layout_height > LAYOUT_MAX_HEIGHT:
        layout_height = LAYOUT_MAX_HEIGHT
        layout_width  = layout_height * aspectRatio

    layout = TableauLayout()
    layout.tableau = tableau
    layout.width   = layout_width
    layout.height  = layout_height
    layout.save()

    # Create a single TableauLayoutViewPosition record, positioning the view
    # within the layout.

    position = TableauLayoutViewPosition()
    position.tableauLayout = layout
    position.tableauView   = view
    position.min_x         = 0
    position.min_y         = 0
    position.max_x         = layout_width
    position.max_y         = layout_height
    position.save()

    # Finally, tell the caller that the tableau was successfully generated.

    return None