Commits

Kai Diefenbach committed 6cd3589

A lot of changes :-)

Comments (0)

Files changed (30)

+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html      to make standalone HTML files"
+	@echo "  dirhtml   to make HTML files named index.html in directories"
+	@echo "  pickle    to make pickle files"
+	@echo "  json      to make JSON files"
+	@echo "  htmlhelp  to make HTML files and a HTML help project"
+	@echo "  qthelp    to make HTML files and a qthelp project"
+	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  changes   to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck to check all external links for integrity"
+	@echo "  doctest   to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/LFCCompositor.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/LFCCompositor.qhc"
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+	      "run these through (pdf)latex."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."
+# -*- coding: utf-8 -*-
+#
+# LFC Compositor documentation build configuration file, created by
+# sphinx-quickstart on Sun Feb 14 13:27:05 2010.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+
+sys.path.append(os.path.abspath("../../../lfc_project"))
+sys.path.append(os.path.abspath("../../../parts/lfc"))
+sys.path.append(os.path.abspath("../../../parts/django"))
+sys.path.append(os.path.abspath("../../../parts/tagging"))
+sys.path.append(os.path.abspath("../../../parts/portlets"))
+sys.path.append(os.path.abspath("../../../parts/lfc_compositor"))
+
+# -- General configuration -----------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'LFC Compositor'
+copyright = u'2010, Kai Diefenbach'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '1.0a1'
+# The full version, including alpha/beta/rc tags.
+release = '1.0a1'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  Major themes that come with
+# Sphinx are currently 'default' and 'sphinxdoc'.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'LFCCompositordoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'LFCCompositor.tex', u'LFC Compositor Documentation',
+   u'Kai Diefenbach', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True

docs/glossary.rst

+.. _glossary:
+
+Glossary
+========
+
+.. glossary::
+    
+  Widget
+    A Widget is a piece of content which lives within columns of a :term:`Composite`
+
+  Widgets
+    See :term:`Widget`
+  
+  Composite
+    A composite is the new content type which is added by LFC Compositor. It 
+    is the main wrapper for rows, columns and :term:`Widgets`.
+.. _index:
+
+==============
+LFC Compositor
+==============
+
+What is it?
+===========
+
+LFC is a web page compositor for `LFC <http://www.lfcproject.com>`_. That 
+means you can create complex web pages out of existing and new content.
+
+Installation
+============
+
+1. Install LFC Compositor with easy_install::
+
+    $ easy_install lfc_compositor
+
+3. Add it to INSTALLED_APPS::
+
+    INSTALLED_APPS = (
+        ...
+        "lfc_compositor",
+        ...
+    )
+    
+4. Login to LFC
+5. Go to the Management Interface (MI) / Applications
+6. Install LFC Compositor
+
+
+Usage
+=====
+
+1. Go to your content, add a :term:`Composite`, fill in the add form and save it
+2. Go to the "Layout" tab and add at least a row and a column
+3. Within the columns start to add :term:`Widgets`
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`

lfc_compositor/__init__.py

     register_content_type(Composite, name = "Composite", templates=["Composite"], default_template="Composite")
 
     # Register Templates
-    register_template(name = "Composite", path="compositor/composite.html")
+    register_template(name = "Composite", path="lfc_compositor/composite.html")
     
 def uninstall():
     """Uninstalls the compositor application.

lfc_compositor/models.py

         for row in self.get_rows():
             content += row.render(request)
 
-        return render_to_string("compositor/widgets/composite.html", RequestContext(request, {
+        return render_to_string("lfc_compositor/widgets/composite.html", RequestContext(request, {
             "composite" : self,
             "content" : content
         }))
         for column in self.get_columns():
             content += column.render(request)
 
-        return render_to_string("compositor/widgets/row.html", RequestContext(request, {
+        return render_to_string("lfc_compositor/widgets/row.html", RequestContext(request, {
             "row" : self,
             "content" : content
         }))
     def get_widgets(self):
         """
         """
-        return self.widgets.all()
+        return self.widgets.order_by("position")
 
     def render(self, request):
         """
 
         width = 100 / columns
 
-        return render_to_string("compositor/widgets/column.html", RequestContext(request, {
+        return render_to_string("lfc_compositor/widgets/column.html", RequestContext(request, {
             "content" : content,
             "column" : self,
             "width" : width,
     position = models.IntegerField(_(u"Position"), blank=True, null=True)
     content_type = models.CharField(blank=True, max_length=100)
 
+    class Meta:
+        ordering = ("position", )
+
     def save(self, force_insert=False, force_update=False):
         """
         """
         return TextWidgetForm(**kwargs)
 
     def render(self, request):
-        return render_to_string("compositor/widgets/text.html", RequestContext(request, {
+        return render_to_string("lfc_compositor/widgets/text.html", RequestContext(request, {
             "widget" : self,
         }))
 
 class TextWidgetForm(forms.ModelForm):
     class Meta:
         model = TextWidget
-        fields = ("content", )
+        fields = ("position", "content", )
 
 class ImageWidget(Widget):
     """An simple image widget.
         """Renders the widget as HTML.
         """
         image_url = getattr(self.image, "url_%s" % self.get_size_display())
-        return render_to_string("compositor/widgets/image.html", RequestContext(request, {
+        return render_to_string("lfc_compositor/widgets/image.html", RequestContext(request, {
             "widget" : self,
             "image_url" : image_url,
         }))
 class ImageWidgetForm(forms.ModelForm):
     class Meta:
         model = ImageWidget
-        fields = ("size", "image", )
+        fields = ("position", "size", "image", )
 
-class TextWithImage(Widget):
+class TextWithImageWidget(Widget):
     """A text with a image widget. The image can be at the left or right site.
 
     **Parameters**:
     image_position
         The position of the image: left, right.
     """
-    image_position = models.IntegerField(_(u"Position"), default = LEFT)
     content = models.TextField(_(u"Text"), blank=True)
     image = ImageWithThumbsField(_(u"Image"), upload_to="uploads",
         sizes=((60, 60), (100, 100), (200, 200), (400, 400), (600, 600), (800, 800)))
-
+    image_position = models.IntegerField(_(u"Position"), default = LEFT)
+    size = models.PositiveSmallIntegerField(_(u"Size"), choices=((0, "60x60"), (1, "100x100"), (2, "200x200"), (3, "400x400"), (4, "600x600"), (5, "800x800")), default=2)
+    
     def get_searchable_text(self):
         return self.content
 
-    def render(self):
-        return render_to_string("compositor/widgets/text_with_image.html", RequestContext(request, {
+    def form(self, **kwargs):
+        """Returns the add/edit form of the image widget.
+        """
+        return TextWithImageWidgetForm(**kwargs)
+
+    def render(self, request):
+        image_url = getattr(self.image, "url_%s" % self.get_size_display())
+        return render_to_string("lfc_compositor/widgets/text_with_image.html", RequestContext(request, {
             "widget" : self,
+            "image_url" : image_url,
             "IMAGE_LEFT" : self.image_position == LEFT,
-        }))
+        }))
+
+class TextWithImageWidgetForm(forms.ModelForm):
+    class Meta:
+        model = TextWithImageWidget
+        fields = ("position", "image", "size",  "image_position", "content")
+
+class ReferenceWidget(Widget):
+    """A widget to display existing content.
+
+    **Parameters**:
+
+    parent
+        The composite the of the row.
+
+    reference
+        The referenced content object.
+    """
+    reference = models.ForeignKey(BaseContent, verbose_name=_(u"Reference"), blank=True, null=True)
+
+    def get_searchable_text(self):
+        try:
+            return self.reference.get_content_object().get_searchable_text()
+        except AttributeError:
+            return ""
+
+    def form(self, **kwargs):
+        """Returns the add/edit form of the text widget.
+        """
+        return ReferenceWidgetForm(**kwargs)
+
+    def render(self, request):
+        # content = self.reference.get_content_object()
+        return render_to_string("lfc_compositor/widgets/reference.html", RequestContext(request, {
+            "widget" : self,
+        }))
+
+class ReferenceWidgetForm(forms.ModelForm):
+    class Meta:
+        model = ReferenceWidget
+        fields = ("position", "reference", )

lfc_compositor/static/compositor.css

+table.lfc-compositor-default {
+    width: 100%;
+}
+
+table.lfc-compositor-default td {
+    vertical-align: top;
+}
+
 #composite-dialog {
     background-color:#eee;
     display:none;

lfc_compositor/templates/compositor/composite.html

-{% extends "lfc/base.html" %}
-{% load compositor_tags %}
-
-{% block css %}
-    <link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}compositor/compositor.css">
-{% endblock %}
-
-{% block javascript %}
-    <script type="text/javascript" src="{{ MEDIA_URL }}compositor/compositor.js"></script>
-{% endblock %}
-
-{% block content %}
-    {% if lfc_context.display_title %}
-        <h1 class="first-heading">{{ lfc_context.title }}</h1>
-    {% endif %}
-
-    <table>{% render %}</table>
-
-    <div id="composite-dialog"><div id="close"></div></div>
-
-{% endblock %}

lfc_compositor/templates/compositor/widgets/column.html

-{% load i18n %}
-
-<td width="{{ width }}%">
-
-    {% if request.user.is_superuser %}
-        <form action="{% url compositor_add_widget column.id %}">
-            <select name="type">
-                <option value="textwidget">{% trans "Text" %}</option>
-                <option value="imagewidget">{% trans "Image" %}</option>
-            </select>
-            <input type="submit" value='{% trans "Go" %}' />
-        </form>
-    {% endif %}
-
-    {{ content|safe }}
-</td>

lfc_compositor/templates/compositor/widgets/composite.html

-{{ content|safe }}
-{% if request.user.is_superuser %}
-    <a href="{% url composite_add_row composite.id %}">add row</a>
-{% endif %}

lfc_compositor/templates/compositor/widgets/form.html

-{% load i18n %}
-<form action="{% url composite_save_widget widget.id %}"
-      method="POST"
-      enctype="multipart/form-data">
-
-    <h1>{% trans "Edit Widget" %}</h1>
-
-    <table>
-        {% include "lfc/manage/lfc_form.html" %}
-    </table>
-
-    <input type="submit" />
-</form>

lfc_compositor/templates/compositor/widgets/image.html

-<div>
-    <img alt="image" src="{{ image_url }}" />  
-    {% if request.user.is_superuser %}
-        <a class="compositor-edit" href="{% url composite_get_widget_form widget.id %}">Edit</a>
-    {% endif %}
-</div>

lfc_compositor/templates/compositor/widgets/render.html

-{{ html|safe }}

lfc_compositor/templates/compositor/widgets/row.html

-{% if request.user.is_superuser %}
-    <div><a href="{% url compositor_add_column row.id %}">add column</a></div>
-{% endif %}
-<table {% if request.user.is_superuser %}border="1"{% endif %} width="100%">
-    <tr>{{ content|safe }}</tr>
-</table>

lfc_compositor/templates/compositor/widgets/text.html

-<div>
-    {{ widget.content|safe }} 
-    {% if request.user.is_superuser %}
-        <a class="compositor-edit" href="{% url composite_get_widget_form widget.id %}">Edit</a>
-    {% endif %}
-<div>

lfc_compositor/templates/compositor/widgets/text_with_image.html

-{% if IMAGE_LEFT  %}
-<img alt="image" class="left" src="{{ image.url_200x200 }}" /><p>{{ text|safe }}</p>
-{% else %}
-<img alt="image" class="right" src="{{ image.url_200x200 }}" /><p>{{ text|safe }}</p>
-{% endif %}

lfc_compositor/templates/lfc_compositor/composite.html

+{% extends "lfc/base.html" %}
+{% load compositor_tags %}
+
+{% block css %}
+    <link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}lfc_compositor/compositor.css">
+{% endblock %}
+
+{% block javascript %}
+    <script type="text/javascript" src="{{ MEDIA_URL }}lfc_compositor/compositor.js"></script>
+{% endblock %}
+
+{% block content %}
+    {% if lfc_context.display_title %}
+        <h1 class="first-heading">{{ lfc_context.title }}</h1>
+    {% endif %}
+    
+    <div>
+        {% render %}
+    </div>
+    <div id="composite-dialog"><div id="close"></div></div>
+
+{% endblock %}

lfc_compositor/templates/lfc_compositor/widgets/column.html

+{% load i18n %}
+
+<td width="{{ width }}%">
+
+    {% if request.user.is_superuser %}
+        <a href="{% url compositor_delete_column column.id %}">delete column</a>
+        <form action="{% url compositor_add_widget column.id %}">
+            <select name="type">
+                <option value="textwidget">{% trans "Text" %}</option>
+                <option value="imagewidget">{% trans "Image" %}</option>
+                <option value="textwithimagewidget">{% trans "Text with Image" %}</option>
+                <option value="referencewidget">{% trans "Reference" %}</option>
+            </select>
+            <input type="submit" value='{% trans "Go" %}' />
+        </form>
+    {% endif %}
+
+    {{ content|safe }}
+</td>

lfc_compositor/templates/lfc_compositor/widgets/composite.html

+{{ content|safe }}
+{% if request.user.is_superuser %}
+    <a href="{% url compositor_add_row composite.id %}">add row</a>
+{% endif %}

lfc_compositor/templates/lfc_compositor/widgets/form.html

+{% load i18n %}
+<form action="{% url compositor_save_widget widget.id %}"
+      method="POST"
+      enctype="multipart/form-data">
+
+    <h1>{% trans "Edit Widget" %}</h1>
+
+    <table>
+        {% include "lfc/manage/lfc_form.html" %}
+    </table>
+
+    <input type="submit" />
+</form>

lfc_compositor/templates/lfc_compositor/widgets/image.html

+<div>
+    <img alt="image" src="{{ image_url }}" />
+    {% if request.user.is_superuser %}
+        <div>
+            <a class="compositor-edit" href="{% url compositor_get_widget_form widget.id %}">Edit</a>
+            <a class="compositor-delete" href="{% url compositor_delete_widget widget.id %}">Delete</a>
+        </div>
+    {% endif %}
+</div>

lfc_compositor/templates/lfc_compositor/widgets/reference.html

+<div>
+    {{ widget.reference.get_content_object.text|safe }}
+    {% if request.user.is_superuser %}
+        <div>
+            <a class="compositor-edit" href="{% url compositor_get_widget_form widget.id %}">Edit</a>
+            <a class="compositor-delete" href="{% url compositor_delete_widget widget.id %}">Delete</a>
+        </div>
+    {% endif %}
+<div>

lfc_compositor/templates/lfc_compositor/widgets/render.html

+{{ html|safe }}

lfc_compositor/templates/lfc_compositor/widgets/row.html

+{% if request.user.is_superuser %}
+    <div>
+        <a href="{% url compositor_delete_row row.id %}">delete row</a>
+        <a href="{% url compositor_add_column row.id %}">add column</a>
+    </div>
+{% endif %}
+<table class="lfc-compositor-default" {% if request.user.is_superuser %}border="1"{% endif %}>
+    <tr>{{ content|safe }}</tr>
+</table>

lfc_compositor/templates/lfc_compositor/widgets/text.html

+<div>
+    <p>
+        {{ widget.content|safe }} 
+    </p>
+    {% if request.user.is_superuser %}
+        <div>
+            <a class="compositor-edit" href="{% url compositor_get_widget_form widget.id %}">Edit</a> |
+            <a class="compositor-delete" href="{% url compositor_delete_widget widget.id %}">Delete</a>
+        </div>
+    {% endif %}
+<div>

lfc_compositor/templates/lfc_compositor/widgets/text_with_image.html

+<div>
+    {% if IMAGE_LEFT  %}
+        <img alt="image" class="left" src="{{ image_url }}" /><p>{{ widget.content|safe }}</p>
+    {% else %}
+        <img alt="image" class="right" src="{{ image_url }}" /><p>{{ widget.content|safe }}</p>
+    {% endif %}
+    {% if request.user.is_superuser %}
+        <div>
+            <a class="compositor-edit" href="{% url compositor_get_widget_form widget.id %}">Edit</a>
+            <a class="compositor-delete" href="{% url compositor_delete_widget widget.id %}">Delete</a>
+        </div>
+    {% endif %}
+</div>

lfc_compositor/templatetags/compositor_tags.py

 
 register = template.Library()
 
-@register.inclusion_tag('compositor/widgets/render.html', takes_context=True)
+@register.inclusion_tag('lfc_compositor/widgets/render.html', takes_context=True)
 def render(context):
     """
     """

lfc_compositor/tests.py

 from lfc_compositor.models import Composite
 from lfc_compositor.models import Row
 from lfc_compositor.models import TextWidget
-from lfc_compositor.models import Image
-from lfc_compositor.models import TextWithImage
+from lfc_compositor.models import ImageWidget
+from lfc_compositor.models import TextWithImageWidget
 from lfc_compositor import config
 
 class ModelsTestCase(TestCase):
         text2 = TextWidget.objects.create(parent=self.col1, position=1, content="Schnurz")
         self.assertEqual(self.comp.searchable_text, "Hurz Schnurz")
 
-        text3 = TextWithImage.objects.create(parent=self.col2, position=1, content="Knurz")
-        self.assertEqual(self.comp.searchable_text, "Hurz Schnurz Knurz")
-        
-    def test_render_1(self):
-        """
-        """
-        html = self.comp.render()
-        self.assertEqual(html, "<table><tr><td></td><td></td></tr></table>")
-        
-    def test_render_2(self):
-        """
-        """
-        text1 = TextWidget.objects.create(parent=self.col1, position=1, content="Hurz1")
-        text2 = TextWidget.objects.create(parent=self.col1, position=2, content="Hurz2")
-        text2 = TextWidget.objects.create(parent=self.col2, position=1, content="Hurz3")
-        
-        html = self.comp.render()
-        self.assertEqual(html, "<table><tr><td>Hurz1Hurz2</td><td>Hurz3</td></tr></table>")
-        
-    def test_render_3(self):
-        """
-        """
-        text1 = TextWidget.objects.create(parent=self.col1, position=1, content="Hurz1")
-        image1 = Image.objects.create(parent=self.col2, position=1)
-
-        html = self.comp.render()
-        self.assertEqual(html, """<table><tr><td>Hurz1</td><td><img alt="image" src="" /></td></tr></table>""")
-        
-    def test_render_4(self):
-        """
-        """
-        text_with_image = TextWithImage.objects.create(parent=self.col1, position=1, content="Hurz1", image_position=config.LEFT)
-        html = self.comp.render()
-        self.assertEqual(html, """<table><tr><td>\n<img alt="image" class="left" src="" /><p>Hurz1</p>\n</td><td></td></tr></table>""")
-        
-    def test_render_5(self):
-        """
-        """
-        text_with_image = TextWithImage.objects.create(parent=self.col1, position=1, content="Hurz1", image_position=config.RIGHT)
-        html = self.comp.render()
-        self.assertEqual(html, """<table><tr><td>\n<img alt="image" class="right" src="" /><p>Hurz1</p>\n</td><td></td></tr></table>""")
+        text3 = TextWithImageWidget.objects.create(parent=self.col2, position=1, content="Knurz")
+        self.assertEqual(self.comp.searchable_text, "Hurz Schnurz Knurz")

lfc_compositor/urls.py

 from django.conf.urls.defaults import *
 
 # URL patterns for compositor
-urlpatterns = patterns('compositor.views',
-    url(r'^add-row/(?P<id>\d*)$', "add_row", name="composite_add_row"),
+urlpatterns = patterns('lfc_compositor.views',
+    url(r'^add-row/(?P<id>\d*)$', "add_row", name="compositor_add_row"),
+    url(r'^delete-row/(?P<id>\d*)$', "delete_row", name="compositor_delete_row"),
+
     url(r'^add-column/(?P<id>\d*)$', "add_column", name="compositor_add_column"),
+    url(r'^delete-column/(?P<id>\d*)$', "delete_column", name="compositor_delete_column"),
+    
+    
     url(r'^add-widget/(?P<id>\d*)$', "add_widget", name="compositor_add_widget"),
 
-    url(r'^get-widget-form/(?P<id>\d*)$', "get_widget_form", name="composite_get_widget_form"),
-    url(r'^save-widget/(?P<id>\d*)$', "save_widget", name="composite_save_widget"),
+    url(r'^get-widget-form/(?P<id>\d*)$', "get_widget_form", name="compositor_get_widget_form"),
+    url(r'^save-widget/(?P<id>\d*)$', "save_widget", name="compositor_save_widget"),
+    url(r'^delete-widget/(?P<id>\d*)$', "delete_widget", name="compositor_delete_widget"),
+
 )

lfc_compositor/views.py

 
     return HttpResponseRedirect(_get_composite(widget).get_absolute_url())
 
-def get_widget_form(request, id, template="compositor/widgets/form.html"):
+def get_widget_form(request, id, template="lfc_compositor/widgets/form.html"):
     """Returns the form of the widget with the id.
     """
     widget = Widget.objects.get(pk=id)
 
     return HttpResponseRedirect(composite.get_absolute_url())
 
+def delete_row(request, id):
+    """
+    """
+    try:
+        row = Row.objects.get(pk=id)
+    except Row.DoesNotExist:
+        pass
+    else:
+        row.delete()
+
+    return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
+
 def add_column(request, id):
     """
     """
 
     return HttpResponseRedirect(_get_composite(row).get_absolute_url())
 
+def delete_column(request, id):
+    """
+    """
+    try:
+        column = Column.objects.get(pk=id)
+    except Column.DoesNotExist:
+        pass
+    else:
+        column.delete()
+
+    return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
+
 def add_widget(request, id):
     """
     """
 
     mc.objects.create(parent=column)
 
-    return HttpResponseRedirect(_get_composite(column).get_absolute_url())
+    return HttpResponseRedirect(_get_composite(column).get_absolute_url())
+
+def delete_widget(request, id):
+    """
+    """
+    try:
+        widget = Widget.objects.get(pk=id)
+    except Widget.DoesNotExist:
+        pass
+    else:
+        widget.delete()
+
+    return HttpResponseRedirect(request.META.get("HTTP_REFERER"))