Commits

Gustavo Picon  committed c0612f5 Merge

Merging Jaap Roes branch after cleanup and updating tests.

  • Participants
  • Parent commits 0e72103, 457e83a

Comments (0)

Files changed (22)

File setup.py

File contents unchanged.

File treebeard/admin.py

 "Django admin support for treebeard"
 
+from django.conf.urls.defaults import patterns, url
 from django.contrib import admin, messages
 from django.contrib.admin.views.main import ChangeList
-from django.conf.urls.defaults import url, patterns
-from django.http import HttpResponseBadRequest, HttpResponse
-
-from treebeard.forms import MoveNodeForm
+from django.http import HttpResponse, HttpResponseBadRequest
+from django.utils.encoding import force_unicode
+from django.utils.translation import ugettext_lazy as _
 from treebeard.templatetags.admin_tree import check_empty_dict
 from treebeard.exceptions import (InvalidPosition, MissingNodeOrderBy,
         InvalidMoveToDescendant, PathOverflow)
+from treebeard.forms import MoveNodeForm
 
 
 class TreeChangeList(ChangeList):
         new_urls = patterns('',
             url('^move/$',
                 self.admin_site.admin_view(self.move_node),),
+            url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', {
+                'packages': ('treebeard',)}),
         )
         return new_urls + urls
 
                 # If it happened because the node is not a 'sorted-sibling'
                 # or 'sorted-child' then try to move just a child without
                 # preserving the order, so try a different move
-                if  as_child:
+                if as_child:
                     try:
                         # Try as unsorted tree
                         node.move(sibling, pos='last-child')
                 else:
                     node.move(sibling)
 
-            # If we are here, means that we moved it in onf of the tries
-            messages.info(request, u'Moved node "%s" as %s of "%s"' % (node,
-                ('sibling', 'child')[as_child], sibling))
+            # Call the save method on the (reloaded) node in order to trigger
+            # possible signal handlers etc.
+            node = self.model.objects.get(pk=node.pk)
+            node.save()
+            # If we are here, means that we moved it in one of the tries
+            if as_child:
+                messages.info(request,
+                    _(u'Moved node "%(node)s" as child of "%(other)s"') % {
+                        'node': node,
+                        'other': sibling
+                    })
+            else:
+                messages.info(request,
+                    _(u'Moved node "%(node)s" as sibling of "%(other)s"') % {
+                        'node': node,
+                        'other': sibling
+                    })
 
         except (MissingNodeOrderBy, PathOverflow, InvalidMoveToDescendant,
             InvalidPosition), e:
             # An error was raised while trying to move the node, then set an
             # error message and return 400, this will cause a reload on the
             # client to show the message
-            messages.error(
-                    request, u'Exception raised while moving node: %s' % e)
+            # error message and return 400, this will cause a reload on
+            # the client to show the message
+            messages.error(request,
+                _(u'Exception raised while moving node: %s') % _(
+                    force_unicode(e)))
             return HttpResponseBadRequest(u'Exception raised during move')
 
         return HttpResponse('OK')

File treebeard/al_tree.py

 "Adjacency List"
 
 from django.core import serializers
-from django.db import models, transaction, connection
+from django.db import connection, models, transaction
+from django.utils.translation import ugettext_noop as _
 
+from treebeard.exceptions import InvalidMoveToDescendant
 from treebeard.models import Node
-from treebeard.exceptions import InvalidMoveToDescendant
 
 
 class AL_NodeManager(models.Manager):
                     sib_order = 1
 
         if target.is_descendant_of(self):
-            raise InvalidMoveToDescendant("Can't move node to a descendant.")
+            raise InvalidMoveToDescendant(_("Can't move node to a descendant."))
 
         if self == target and (
               (pos == 'left') or \

File treebeard/forms.py

 "Forms for treebeard."
 
-from django.forms.models import model_to_dict, ErrorList, BaseModelForm
 from django import forms
 from django.db.models.query import QuerySet
-from django.utils.translation import ugettext as _
+from django.forms.models import BaseModelForm, ErrorList, model_to_dict
+from django.utils.safestring import mark_safe
+from django.utils.translation import ugettext_lazy as _
 
 
 class MoveNodeForm(forms.ModelForm):
             is_loop_safe = lambda(possible_parent): True
             # Do actual check only if for_node is provided
             if for_node is not None:
-                is_loop_safe = lambda(possible_parent): not (\
-                            possible_parent == for_node) or \
-                            possible_parent.is_descendant_of(for_node)
+                is_loop_safe = lambda(possible_parent): not (
+                            possible_parent == for_node) or (
+                            possible_parent.is_descendant_of(for_node))
 
-            mk_indent = lambda(level): '. . ' * (level - 1)
+            mk_indent = lambda(level): '    ' * (level - 1)
 
             def add_subtree(node, options):
                 """ Recursively build options tree. """
                 if is_loop_safe(node):
                     options.append(
-                        (node.pk, mk_indent(node.get_depth()) + str(node)))
+                        (node.pk,
+                         mark_safe(mk_indent(node.get_depth()) + str(node))))
                     for subnode in node.get_children():
                         add_subtree(subnode, options)
 

File treebeard/locale/es/LC_MESSAGES/django.mo

Binary file modified.

File treebeard/locale/es/LC_MESSAGES/django.po

 msgstr ""
 "Project-Id-Version: Django-treebeard\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-05-03 23:53-0500\n"
+"POT-Creation-Date: 2011-07-18 17:36+0200\n"
 "PO-Revision-Date: 2010-05-03 23:40-0500\n"
 "Last-Translator: Gustavo Picon <tabo@tabo.pe>\n"
 "Language-Team: Spanish\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms:  nplurals=2; plural=(n != 1);\n"
 
-#: forms.py:16
+#: admin.py:113
+#, python-format
+msgid "Moved node \"%(node)s\" as child of \"%(other)s\""
+msgstr ""
+
+#: admin.py:119
+#, python-format
+msgid "Moved node \"%(node)s\" as sibling of \"%(other)s\""
+msgstr ""
+
+#: admin.py:129
+#, python-format
+msgid "Exception raised while moving node: %s"
+msgstr ""
+
+#: al_tree.py:319 mp_tree.py:641 ns_tree.py:308
+msgid "Can't move node to a descendant."
+msgstr ""
+
+#: forms.py:17
 msgid "Child of"
 msgstr "Hijo de"
 
-#: forms.py:17
+#: forms.py:18
 msgid "Sibling of"
 msgstr "Hermano de"
 
-#: forms.py:21
+#: forms.py:22
 msgid "First child of"
 msgstr "Primer hijo de"
 
-#: forms.py:22
+#: forms.py:23
 msgid "Before"
 msgstr "Antes"
 
-#: forms.py:23
+#: forms.py:24
 msgid "After"
 msgstr "Después"
 
-#: forms.py:26
+#: forms.py:27
 msgid "Position"
 msgstr "Posición"
 
-#: forms.py:30
+#: forms.py:31
 msgid "Relative to"
 msgstr "Relativo a"
 
-#: forms.py:80
+#: forms.py:81
 msgid "-- root --"
 msgstr "-- raíz --"
+
+#: mp_tree.py:521
+msgid ""
+"The new node is too deep in the tree, try increasing the path.max_length "
+"property and UPDATE your database"
+msgstr ""
+
+#: mp_tree.py:702
+#, python-format
+msgid "Path Overflow from: '%s'"
+msgstr ""
+
+#: templatetags/admin_tree.py:148
+msgid "Return to ordered tree"
+msgstr ""

File treebeard/locale/es/LC_MESSAGES/djangojs.mo

Binary file added.

File treebeard/locale/es/LC_MESSAGES/djangojs.po

+msgid ""
+msgstr ""
+"Project-Id-Version: Django-treebeard\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-07-18 14:12+0200\n"
+"PO-Revision-Date: 2011-07-18 14:12+0200\n"
+"Last-Translator: \n"
+"Language-Team: Spanish\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms:  nplurals=2; plural=(n != 1);\n"
+
+#: static/treebeard/treebeard-admin.js:157
+msgid "Abort"
+msgstr ""
+
+#: static/treebeard/treebeard-admin.js:172
+msgid "As Sibling"
+msgstr ""
+
+#: static/treebeard/treebeard-admin.js:190
+msgid "As child"
+msgstr ""

File treebeard/locale/nl/LC_MESSAGES/django.mo

Binary file added.

File treebeard/locale/nl/LC_MESSAGES/django.po

+msgid ""
+msgstr ""
+"Project-Id-Version: Django-treebeard\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-07-18 17:36+0200\n"
+"PO-Revision-Date: 2011-07-18 14:11+0200\n"
+"Last-Translator: Jaap Roes <jaap@eight.nl>\n"
+"Language-Team: Dutch\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: admin.py:113
+#, python-format
+msgid "Moved node \"%(node)s\" as child of \"%(other)s\""
+msgstr "\"%(node)s\" is nu onderdeel van \"%(other)s\""
+
+#: admin.py:119
+#, python-format
+msgid "Moved node \"%(node)s\" as sibling of \"%(other)s\""
+msgstr "\"%(node)s\" staat nu voor \"%(other)s\""
+
+#: admin.py:129
+#, python-format
+msgid "Exception raised while moving node: %s"
+msgstr "Fatale fout tijdens het verplaatsen: %s"
+
+#: al_tree.py:319 mp_tree.py:641 ns_tree.py:308
+msgid "Can't move node to a descendant."
+msgstr "Kan node niet naar eigen subnode verplaatsen"
+
+#: forms.py:17
+msgid "Child of"
+msgstr "Onderdeel"
+
+#: forms.py:18
+msgid "Sibling of"
+msgstr "Naast"
+
+#: forms.py:22
+msgid "First child of"
+msgstr "1e onderdeel"
+
+#: forms.py:23
+msgid "Before"
+msgstr "Voor"
+
+#: forms.py:24
+msgid "After"
+msgstr "Na"
+
+#: forms.py:27
+msgid "Position"
+msgstr "Positie"
+
+#: forms.py:31
+msgid "Relative to"
+msgstr "Ten opzichte van"
+
+#: forms.py:81
+msgid "-- root --"
+msgstr "-- hoofdniveau --"
+
+#: mp_tree.py:521
+msgid ""
+"The new node is too deep in the tree, try increasing the path.max_length "
+"property and UPDATE your database"
+msgstr ""
+"De nieuwe node bevindt zich te diep in de boom. Verhoog de path.max_lenght "
+"waarde en UPDATE de database."
+
+#: mp_tree.py:702
+#, python-format
+msgid "Path Overflow from: '%s'"
+msgstr "Path overflow van: '%s'"
+
+#: templatetags/admin_tree.py:148
+msgid "Return to ordered tree"
+msgstr "Als gesorteerde boom"

File treebeard/locale/nl/LC_MESSAGES/djangojs.mo

Binary file added.

File treebeard/locale/nl/LC_MESSAGES/djangojs.po

+msgid ""
+msgstr ""
+"Project-Id-Version: Django-treebeard\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-07-18 14:12+0200\n"
+"PO-Revision-Date: 2011-07-18 14:12+0200\n"
+"Last-Translator: Jaap Roes <jaap@eight.nl>\n"
+"Language-Team: Dutch\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: static/treebeard/treebeard-admin.js:157
+msgid "Abort"
+msgstr "Annuleren"
+
+#: static/treebeard/treebeard-admin.js:172
+msgid "As Sibling"
+msgstr "Als naastliggend onderdeel"
+
+#: static/treebeard/treebeard-admin.js:190
+msgid "As child"
+msgstr "Als subonderdeel"

File treebeard/locale/ru/LC_MESSAGES/django.mo

Binary file modified.

File treebeard/locale/ru/LC_MESSAGES/django.po

 msgstr ""
 "Project-Id-Version: Django-treebeard\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-05-02 17:51-0500\n"
+"POT-Creation-Date: 2011-07-18 17:36+0200\n"
 "PO-Revision-Date: 2009-04-10 18:37+0400\n"
 "Last-Translator: chembervint <chembervint@gmail.com>\n"
 "Language-Team: Russian\n"
 "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
 "10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
 
-#: forms.py:16
+#: admin.py:113
+#, python-format
+msgid "Moved node \"%(node)s\" as child of \"%(other)s\""
+msgstr ""
+
+#: admin.py:119
+#, python-format
+msgid "Moved node \"%(node)s\" as sibling of \"%(other)s\""
+msgstr ""
+
+#: admin.py:129
+#, python-format
+msgid "Exception raised while moving node: %s"
+msgstr ""
+
+#: al_tree.py:319 mp_tree.py:641 ns_tree.py:308
+msgid "Can't move node to a descendant."
+msgstr ""
+
+#: forms.py:17
 msgid "Child of"
 msgstr "Вложенный"
 
-#: forms.py:17
+#: forms.py:18
 msgid "Sibling of"
 msgstr "Соседний к"
 
-#: forms.py:21
+#: forms.py:22
 msgid "First child of"
 msgstr "Первый вложенный"
 
-#: forms.py:22
+#: forms.py:23
 msgid "Before"
 msgstr "До"
 
-#: forms.py:23
+#: forms.py:24
 msgid "After"
 msgstr "После"
 
-#: forms.py:26
+#: forms.py:27
 msgid "Position"
 msgstr "Позиция"
 
-#: forms.py:30
+#: forms.py:31
 msgid "Relative to"
 msgstr "Относительно"
 
-#: forms.py:80
+#: forms.py:81
 msgid "-- root --"
 msgstr "-- корень --"
+
+#: mp_tree.py:521
+msgid ""
+"The new node is too deep in the tree, try increasing the path.max_length "
+"property and UPDATE your database"
+msgstr ""
+
+#: mp_tree.py:702
+#, python-format
+msgid "Path Overflow from: '%s'"
+msgstr ""
+
+#: templatetags/admin_tree.py:148
+msgid "Return to ordered tree"
+msgstr ""

File treebeard/locale/ru/LC_MESSAGES/djangojs.mo

Binary file added.

File treebeard/locale/ru/LC_MESSAGES/djangojs.po

+msgid ""
+msgstr ""
+"Project-Id-Version: Django-treebeard\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-07-18 14:12+0200\n"
+"PO-Revision-Date: 2011-07-18 14:12+0200\n"
+"Last-Translator: \n"
+"Language-Team: Russian\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+#: static/treebeard/treebeard-admin.js:157
+msgid "Abort"
+msgstr ""
+
+#: static/treebeard/treebeard-admin.js:172
+msgid "As Sibling"
+msgstr ""
+
+#: static/treebeard/treebeard-admin.js:190
+msgid "As child"
+msgstr ""

File treebeard/mp_tree.py

 from django.core import serializers
 from django.db import models, transaction, connection
 from django.db.models import Q
+from django.utils.translation import ugettext_noop as _
 
 from treebeard.models import Node
 from treebeard.exceptions import InvalidMoveToDescendant, PathOverflow
             newobj.path = self._get_path(self.path, newobj.depth, 1)
             if len(newobj.path) > \
                     newobj.__class__._meta.get_field('path').max_length:
-                raise PathOverflow('The new node is too deep in the tree, try'
+                raise PathOverflow(_('The new node is too deep in the tree, try'
                                    ' increasing the path.max_length property'
-                                   ' and UPDATE your  database')
+                                   ' and UPDATE your database'))
         # saving the instance before returning it
         newobj.save()
         newobj._cached_parent_obj = self
             target, target.depth)
 
         if target.is_descendant_of(self):
-            raise InvalidMoveToDescendant("Can't move node to a descendant.")
+            raise InvalidMoveToDescendant(_("Can't move node to a descendant."))
 
         if oldpath == target.path and (
               (pos == 'left') or \
         newpos = cls._str2int(path[-cls.steplen:]) + 1
         key = cls._int2str(newpos)
         if len(key) > cls.steplen:
-            raise PathOverflow("Path Overflow from: '%s'" % (path, ))
+            raise PathOverflow(_("Path Overflow from: '%s'" % (path, )))
         return '%s%s%s' % (path[:-cls.steplen],
                            '0' * (cls.steplen - len(key)),
                            key)

File treebeard/ns_tree.py

 "Nested Sets"
 
+from django.core import serializers
+from django.db import connection, models, transaction
+from django.db.models import Q
+from django.utils.translation import ugettext_noop as _
+
 import operator
-
-from django.db.models import Q
-from django.core import serializers
-from django.db import models, transaction, connection
-
+from treebeard.exceptions import InvalidMoveToDescendant
 from treebeard.models import Node
-from treebeard.exceptions import InvalidMoveToDescendant
 
 
 class NS_NodeQuerySet(models.query.QuerySet):
                        'sorted-child': 'sorted-sibling'}[pos]
 
         if target.is_descendant_of(self):
-            raise InvalidMoveToDescendant("Can't move node to a descendant.")
+            raise InvalidMoveToDescendant(_("Can't move node to a descendant."))
 
         if self == target and (
               (pos == 'left') or \

File treebeard/static/treebeard/treebeard-admin.css

 #roots li input {
 margin: 0 5px;
 }
+.oder-grabber {
+    width: 1.5em;
+    text-align: center;
+}
 .drag-handler span {
 width: 16px;
 background: transparent url(expand-collapse.png) no-repeat left -48px;

File treebeard/static/treebeard/treebeard-admin.js

                 // Check if you are dragging over the same node
                 if (evt2.pageY >= node_top && evt2.pageY <= node_top + rowHeight) {
                     $targetRow = null;
-                    $tooltip.text('Abort');
+                    $tooltip.text(gettext('Abort'));
                     $drag_line.css({
                         'top': node_top,
                         'height': rowHeight,
                         'height': 0,
                         'opacity': 1
                     });
-                    $tooltip.text('As Sibling');
+                    $tooltip.text(gettext('As Sibling'));
                 } else if (evt2.pageY >= rtop + rowHeight/2 && evt2.pageY <= rtop + rowHeight) {
                     // The mouse is positioned on the bottom half of a row
                     $targetRow = $row;
                         'borderWidth': 0,
                         'backgroundColor': DRAG_LINE_COLOR
                     });
-                    $tooltip.text('As child');
+                    $tooltip.text(gettext('As child'));
                 }
             });
         }).bind('mouseup', function() {

File treebeard/templatetags/admin_tree.py

 
 from django.db import models
 from django.conf import settings
+from django.contrib.admin.templatetags.admin_list import (
+    _boolean_icon, result_headers, result_hidden_fields)
+from django.contrib.admin.util import display_for_field, lookup_field
 from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
+from django.core.exceptions import ObjectDoesNotExist
 from django.template import Library
-from django.core.exceptions import ObjectDoesNotExist
-from django.contrib.admin.templatetags.admin_list import (
-    result_hidden_fields, result_headers, _boolean_icon)
-from django.contrib.admin.util import lookup_field, display_for_field
+from django.utils.encoding import force_unicode, smart_unicode
+from django.utils.html import conditional_escape, escape
 from django.utils.safestring import mark_safe
-from django.utils.encoding import smart_unicode, force_unicode
-from django.utils.html import escape, conditional_escape
+from django.utils.translation import ugettext_lazy as _
 
 
 register = Library()
         'text': '+',
         'sortable': True,
         'url': request.path,
-        'tooltip': u'Return to ordered Tree',
+        'tooltip': _(u'Return to ordered tree'),
+        'class_attrib': mark_safe(' class="oder-grabber"')
         })
     return {
         'filtered': not check_empty_dict(request.GET),
     """
     path = get_static_url()
     SCRIPT_HTML = """<script type="text/javascript" src="%s"></script>"""
-    js_file = urljoin(path, 'treebeard/treebeard-admin.js')
+    js_file = '/'.join([path.rstrip('/'), 'treebeard', 'treebeard-admin.js'])
 
     # Jquery UI is needed to call disableSelection() on drag and drop so
     # text selections arent marked while dragging a table row
     """
     jquery_ui = urljoin(path, 'treebeard/jquery-ui-1.8.5.custom.min.js')
 
-    scripts = [SCRIPT_HTML % js_file, JQUERY_UI % jquery_ui]
+    scripts = [SCRIPT_HTML % 'jsi18n',
+               SCRIPT_HTML % js_file,
+               JQUERY_UI % jquery_ui]
     return ''.join(scripts)

File treebeard/tests/test_treebeard.py

         for obj in self.model.get_tree():
             if node != obj or obj.is_descendant_of(node):
                 rtpl += '<option value="%d">%sNode %d</option>\n' % (
-                    obj.pk, '. . ' * (obj.get_depth() - 1), obj.pk)
+                    obj.pk,
+                    '&nbsp;&nbsp;&nbsp;&nbsp;' * (obj.get_depth() - 1),
+                    obj.pk
+                )
         rtpl += '</select></td></tr>'
         formstr = unicode(form).replace(u' selected="selected"', u'')
         self.assertEqual(rtpl, formstr)
         for obj in self.model.get_tree():
             if node != obj or obj.is_descendant_of(node):
                 rtpl += '<option value="%d">%sNode %d</option>\n' % (
-                    obj.pk, '. . ' * (obj.get_depth() - 1), obj.pk)
+                    obj.pk,
+                    '&nbsp;&nbsp;&nbsp;&nbsp;' * (obj.get_depth() - 1),
+                    obj.pk
+                )
         rtpl += '</select></td></tr>'
         formstr = unicode(form).replace(u' selected="selected"', u'')
         self.assertEqual(rtpl, formstr)
                '<option value="0">-- root --</option>\n'
                '<option value="%d">Node %d</option>\n'
                '<option value="%d">Node %d</option>\n'
-               '<option value="%d">. . Node %d</option>\n'
-               '<option value="%d">. . Node %d</option>\n'
-               '<option value="%d">. . Node %d</option>\n'
-               '<option value="%d">. . . . Node %d</option>\n'
-               '<option value="%d">. . Node %d</option>\n'
+               '<option value="%d">&nbsp;&nbsp;&nbsp;&nbsp;Node %d</option>\n'
+               '<option value="%d">&nbsp;&nbsp;&nbsp;&nbsp;Node %d</option>\n'
+               '<option value="%d">&nbsp;&nbsp;&nbsp;&nbsp;Node %d</option>\n'
+               '<option value="%d">'
+               '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Node %d'
+               '</option>\n'
+               '<option value="%d">&nbsp;&nbsp;&nbsp;&nbsp;Node %d</option>\n'
                '<option value="%d">Node %d</option>\n'
                '<option value="%d">Node %d</option>\n'
-               '<option value="%d">. . Node %d</option>\n'
+               '<option value="%d">&nbsp;&nbsp;&nbsp;&nbsp;Node %d</option>\n'
                '</select></td></tr>')
         request = None
         self.model.load_bulk(BASE_DATA)