[web, formatting] move Interval data type display logic from final view to printable_value (closes #1984742)
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 06 Oct 2011 16:14:08 +0200
changeset 7913 d0c6a7993cec
parent 7910 e5d5609e3bf1
child 7914 fb757a7d887e
[web, formatting] move Interval data type display logic from final view to printable_value (closes #1984742) also, fix implementation so that negative time delta are properly considered
uilib.py
web/views/baseviews.py
--- a/uilib.py	Tue Oct 04 18:45:38 2011 +0200
+++ b/uilib.py	Thu Oct 06 16:14:08 2011 +0200
@@ -79,6 +79,39 @@
         return ustrftime(value, req.property_value('ui.datetime-format')) + u' UTC'
     return ustrftime(value, req.property_value('ui.date-format'))
 
+_('%d years')
+_('%d months')
+_('%d weeks')
+_('%d days')
+_('%d hours')
+_('%d minutes')
+_('%d seconds')
+
+def print_timedelta(value, req, props, displaytime=True):
+    if isinstance(value, (int, long)):
+        # `date - date`, unlike `datetime - datetime` gives an int
+        # (number of days), not a timedelta
+        # XXX should rql be fixed to return Int instead of Interval in
+        #     that case? that would be probably the proper fix but we
+        #     loose information on the way...
+        value = timedelta(days=value)
+    if value.days > 730 or value.days < -730: # 2 years
+        return req._('%d years') % (value.days // 365)
+    elif value.days > 60 or value.days < -60: # 2 months
+        return req._('%d months') % (value.days // 30)
+    elif value.days > 14 or value.days < -14: # 2 weeks
+        return req._('%d weeks') % (value.days // 7)
+    elif value.days > 2 or value.days < -2:
+        return req._('%d days') % int(value.days)
+    else:
+        minus = 1 if value.days > 0 else -1
+        if value.seconds > 3600:
+            return req._('%d hours') % (int(value.seconds // 3600) * minus)
+        elif value.seconds >= 120:
+            return req._('%d minutes') % (int(value.seconds // 60) * minus)
+        else:
+            return req._('%d seconds') % (int(value.seconds) * minus)
+
 def print_boolean(value, req, props, displaytime=True):
     if value:
         return req._('yes')
@@ -98,7 +131,7 @@
     'Boolean': print_boolean,
     'Float': print_float,
     'Decimal': print_float,
-    # XXX Interval
+    'Interval': print_timedelta,
     }
 
 def printable_value(req, attrtype, value, props=None, displaytime=True):
--- a/web/views/baseviews.py	Tue Oct 04 18:45:38 2011 +0200
+++ b/web/views/baseviews.py	Thu Oct 06 16:14:08 2011 +0200
@@ -149,48 +149,22 @@
     _('%d seconds')
 
     def cell_call(self, row, col, props=None, format='text/html'):
-        etype = self.cw_rset.description[row][col]
         value = self.cw_rset.rows[row][col]
-
         if value is None:
             self.w(u'')
             return
+        etype = self.cw_rset.description[row][col]
         if etype == 'String':
             entity, rtype = self.cw_rset.related_entity(row, col)
             if entity is not None:
-                # yes !
+                # call entity's printable_value which may have more information
+                # about string format & all
                 self.w(entity.printable_value(rtype, value, format=format))
                 return
-        elif etype in ('Time', 'Interval'):
-            if etype == 'Interval' and isinstance(value, (int, long)):
-                # `date - date`, unlike `datetime - datetime` gives an int
-                # (number of days), not a timedelta
-                # XXX should rql be fixed to return Int instead of Interval in
-                #     that case? that would be probably the proper fix but we
-                #     loose information on the way...
-                value = timedelta(days=value)
-            # value is DateTimeDelta but we have no idea about what is the
-            # reference date here, so we can only approximate years and months
-            if format == 'text/html':
-                space = '&#160;'
-            else:
-                space = ' '
-            if value.days > 730: # 2 years
-                self.w(self._cw.__('%%d%syears' % space) % (value.days // 365))
-            elif value.days > 60: # 2 months
-                self.w(self._cw.__('%%d%smonths' % space) % (value.days // 30))
-            elif value.days > 14: # 2 weeks
-                self.w(self._cw.__('%%d%sweeks' % space) % (value.days // 7))
-            elif value.days > 2:
-                self.w(self._cw.__('%%d%sdays' % space) % int(value.days))
-            elif value.seconds > 3600:
-                self.w(self._cw.__('%%d%shours' % space) % int(value.seconds // 3600))
-            elif value.seconds >= 120:
-                self.w(self._cw.__('%%d%sminutes' % space) % int(value.seconds // 60))
-            else:
-                self.w(self._cw.__('%%d%sseconds' % space) % int(value.seconds))
-            return
-        self.wdata(printable_value(self._cw, etype, value, props))
+        value = printable_value(self._cw, etype, value, props)
+        if etype in ('Time', 'Interval'):
+            value = value.replace(' ', '&#160;')
+        self.wdata(value)
 
 
 class InContextView(EntityView):