Repository: kartoza/prj.app

Issue:
We need to generate a nice 'sponsors cloud'
- generate a nice 'sponsors cloud’ image that can be placed onto promotional material (with logos scaled to the correct sizes based on sponsorship level)
- we need to add logo size constraints to sponsorship level model



Discussion:
Hi @timlinux 

What do you think about this:
![sponsors](https://cloud.githubusercontent.com/assets/1979569/13959157/8946060e-f085-11e5-9701-0e20060cf482.png)

I generated this on backend using [Pillow](https://pillow.readthedocs.org/en/3.1.x/) library, any feedback or suggestion would be appreciated. Thanks.

@timlinux , second update, I tried to centering each logo 
![download 4](https://cloud.githubusercontent.com/assets/1979569/13982352/2c1bf384-f11c-11e5-8ea0-02da083fa48e.png)

That looks very nice (second version). Can you integrate this with the following tweaks:

When downloading the image have a separate view with these options:

a) ability to select which sponsorship levels to include in the image
b) ability to choose an image export (as per your example above) or an rst (with hyperlinks to sponsors) + sponsor images in a table as done in the changelog export) see for example https://www.qgis.org/en/site/about/sponsorship.html?highlight=sponsors

CC @andreasneumann

Can you add a button on the sponsors page (available to project admins only) that will let you get the 


Resolving patch:
diff --git a/django_project/changes/urls.py b/django_project/changes/urls.py
--- a/django_project/changes/urls.py
+++ b/django_project/changes/urls.py
@@ -74,6 +74,8 @@
     SponsorshipPeriodUpdateView,
     PendingSponsorshipPeriodListView,
     ApproveSponsorshipPeriodView,
+
+    generate_sponsor_cloud,
 )
 
 urlpatterns = patterns(
@@ -293,6 +295,11 @@
     url(regex='^(?P<project_slug>[\w-]+)/sponsorshipperiod/(?P<slug>[\w-]+)/update/$',
         view=SponsorshipPeriodUpdateView.as_view(),
         name='sponsorshipperiod-update'),
+
+    # Sponsor Cloud
+    url(regex='^(?P<project_slug>[\w-]+)/sponsor-cloud/$',
+        view=generate_sponsor_cloud,
+        name='sponsor-cloud'),
 )
 
 
diff --git a/django_project/changes/views/sponsor.py b/django_project/changes/views/sponsor.py
--- a/django_project/changes/views/sponsor.py
+++ b/django_project/changes/views/sponsor.py
@@ -1,12 +1,13 @@
 __author__ = 'rischan'
 
 
+import os
 import logging
 from base.models import Project
 
-
+from PIL import Image
 from django.core.urlresolvers import reverse
-from django.shortcuts import get_object_or_404
+from django.shortcuts import get_object_or_404, render
 from django.http import HttpResponse
 from django.views.generic import (
     ListView,
@@ -555,3 +556,66 @@ def get_redirect_url(self, project_slug, slug):
         return reverse(self.pattern_name, kwargs={
             'project_slug': project_slug
         })
+
+
+def generate_sponsor_cloud(request, **kwargs):
+    """Generate image for sponsor logos."""
+
+    project_slug = kwargs.pop('project_slug')
+    project = Project.objects.get(slug=project_slug)
+    project_name = project.name.lower().replace(' ', '_')
+    queryset = SponsorshipPeriod.objects.filter(
+        project=project).order_by('-sponsorship_level__value')
+    background = Image.new("RGB", (1200, 1000), "white")
+    max_x = 0
+    max_y = 0
+    y = 0
+    x = 0
+    sponsor_level = ''
+    xy_size = 100
+    for sponsor in queryset:
+        if sponsor.current_sponsor():
+            if sponsor.sponsorship_level.name != sponsor_level:
+                if sponsor_level != '':
+                    sponsor_level = sponsor.sponsorship_level.name
+                    xy_size -= 25
+                    y += 25
+                    if xy_size < 25:
+                        xy_size = 25
+                        y -= 25
+                else:
+                    sponsor_level = sponsor.sponsorship_level.name
+
+            im = Image.open(
+                sponsor.sponsor.logo).convert("RGBA")
+            size = xy_size, xy_size
+            im.thumbnail(size, Image.ANTIALIAS)
+            width, height = im.size
+            if (x + xy_size) >= 1000:
+                x = 0
+                y += xy_size
+            if max_x <= (x + xy_size):
+                max_x = x + xy_size
+            if max_y <= y:
+                max_y = y + xy_size
+            background.paste(
+                im, box=(x, y + ((xy_size - height) / 2)), mask=im)
+            x += xy_size
+
+    image_path = 'none'
+    if max_x != 0:
+        filepath = '/home/web/media/images/sponsors/'
+        if not os.path.exists(filepath):
+            os.makedirs(filepath)
+
+        background.crop(
+            (0, 0, max_x, max_y)).save(
+            filepath + '{}.png'.format(project_name))
+
+        image_path = '/images/sponsors/{}.png'.format(project_name)
+
+    return render(
+        request, 'sponsor/sponsor_cloud.html',
+        context={
+            'image': image_path,
+            'the_project': project})


Test patch: