Index: branches/ReportPatch/trac/ticket/report.py
===================================================================
--- branches/ReportPatch/trac/ticket/report.py	(Revision 20)
+++ branches/ReportPatch/trac/ticket/report.py	(Arbeitskopie)
@@ -436,6 +436,22 @@
                 header_groups.append([])
             header_group.append(header)
 
+        maxcols = 0 
+        for header_group in header_groups:
+            numhidden = 0
+            numcols = 0
+            for header in header_group:
+                if header['hidden']:
+                    numhidden += 1
+                else:
+                    numcols += 1
+            maxcols = numcols > maxcols and numcols or maxcols
+	    i = 1
+            for header in header_group:
+                header['numhidden'] = numhidden
+                header['grpindex'] = i
+                i += 1
+
         # Structure the rows and cells:
         #  - group rows according to __group__ value, if defined
         #  - group cells the same way headers are grouped
+
Index: branches/ReportPatch/trac/ticket/templates/report_view.html
===================================================================
--- branches/ReportPatch/trac/ticket/templates/report_view.html	(Revision 20)
+++ branches/ReportPatch/trac/ticket/templates/report_view.html	(Arbeitskopie)
@@ -96,9 +96,14 @@
         </h2>
         <table class="listing tickets">
           <thead>
-            <tr py:for="header_group in header_groups">
-              <th py:for="header in header_group" py:if="not header.hidden" py:with="fullrow = header is header_group[-1]"
-                colspan="${fullrow and '100' or None}">
+            <tr py:for="header_group in header_groups" py:if="not (header_group[0].hidden and len(header_group)==1)"> 
+              <th py:for="header in header_group" py:if="not header.hidden"
+                  py:with="fullrow = header is header_group[-1];
+                           grpnumcols = len(header_group);
+                           curcol = header.grpindex;
+                           grpnumhidden = header.numhidden;
+                           colspan = (grpnumcols - grpnumhidden &lt; maxcols and curcol == grpnumcols) and (maxcols - curcol + grpnumhidden + 1) or 1;"
+                colspan="$colspan">
                 <a py:strip="not sorting_enabled"
                    py:with="filtered_args = dict([(k,v) for k,v in args.items() if k not in ('sort', 'asc')])"
                   href="${href.report(report.id, filtered_args, sort=header.col, asc=not header.asc and '1' or '0')}">
@@ -108,11 +113,13 @@
             </tr>
           </thead>
 
-          <tbody>
-            <py:for each="row in row_group">
+          <tbody py:for="row in row_group">
               <tr py:for="cell_group in row.cell_groups"
+                py:if="not (cell_group[0].header.hidden and len(cell_group) == 1)"
                 py:with="fullrow = len(cell_group) == 1;
-                         td_attrs = fullrow and {'class': 'fullrow', 'colspan': 100} or {}"
+                         grpnumcols = len(cell_group);
+                         td_attrs = fullrow and {'class': 'fullrow', 'colspan': maxcols} or {};
+                         td_attrs = fullrow and {'colspan': maxcols} or {}"
                 class="${'__color__' in row and 'color'+row.__color__+'-' or ''}${row.__idx__ % 2 and 'odd' or 'even'}"
                 style="${'__bgcolor__' in row and 'background: '+row.__bgcolor__+';' or None
                 }${'__fgcolor__' in row and 'color: '+row.__fgcolor__+';' or None
@@ -120,67 +127,71 @@
                 }${fullrow and 'border: none; padding: 0;' or None}">
 
                 <py:for each="cell in cell_group">
-                  <py:if test="not cell.header.hidden">
-                    <py:with vars="col = cell.header.col.strip('_')">
+                  <py:if test="not cell.header.hidden"> 
+                    <py:with vars="col = cell.header.col.strip('_');
+                                   curcol = cell.header.grpindex;
+                                   grpnumhidden = cell.header.numhidden;
+                                   colspan_last = (grpnumcols - grpnumhidden &lt; maxcols) and (maxcols - curcol + grpnumhidden + 1) or 1;
+                                   td_attrs = (not fullrow and ( curcol == grpnumcols )) and {'colspan': colspan_last} or td_attrs;">
                       <py:choose>
 
                         <py:when test="col == 'report'">
                           <td class="$col" py:attrs="td_attrs">
                             <a title="View report" href="${href.report(cell.value)}">{$cell.value}</a>
-                            <hr py:if="fullrow"/>
+                            <!-- ! <hr py:if="fullrow"/> -->
                           </td>
                         </py:when>
 
                         <py:when test="col in ('ticket', 'id')">
                           <td class="ticket" py:attrs="td_attrs">
                             <a title="View ${row.resource.realm}" href="${url_of(row.resource)}">#$cell.value</a>
-                            <hr py:if="fullrow"/>
+                            <!-- ! <hr py:if="fullrow"/> -->
                           </td>
                         </py:when>
 
                         <py:when test="col == 'summary' and row.id">
                           <td class="$col" py:attrs="td_attrs">
                             <a title="View ${row.resource.realm}" href="${url_of(row.resource)}">$cell.value</a>
-                            <hr py:if="fullrow"/>
+                            <!-- ! <hr py:if="fullrow"/> -->
                           </td>
                         </py:when>
 
                         <!--! generic fields -->
                         <py:when test="col == 'time'">
                           <td class="date" py:attrs="td_attrs">${cell.value != '' and format_time(int(cell.value)) or '--'}
-                            <hr py:if="fullrow"/>
+                            <!-- ! <hr py:if="fullrow"/> -->
                           </td>
                         </py:when>
 
                         <py:when test="col in ('date', 'created', 'modified')">
                           <td class="date" py:attrs="td_attrs">${cell.value != '' and format_date(int(cell.value)) or '--'}
-                            <hr py:if="fullrow"/>
+                            <!-- ! <hr py:if="fullrow"/> -->
                           </td>
                         </py:when>
 
                         <py:when test="col == 'datetime'">
                           <td class="date" py:attrs="td_attrs">${cell.value != '' and format_datetime(int(cell.value)) or '--'}
-                            <hr py:if="fullrow"/>
+                            <!-- ! <hr py:if="fullrow"/> -->
                           </td>
                         </py:when>
 
                         <py:when test="col == 'description'">
                           <td class="$col" py:attrs="td_attrs" xml:space="preserve">
                             ${wiki_to_html(context(row.resource), cell.value)}
-                            <hr py:if="fullrow"/>
+                            <!-- ! <hr py:if="fullrow"/> -->
                           </td>
                         </py:when>
 
                         <py:when test="col == 'milestone'">
                           <td class="$col" py:attrs="td_attrs">
                             <a title="View milestone" href="${href.milestone(cell.value)}">$cell.value</a>
-                            <hr py:if="fullrow"/>
+                            <!-- ! <hr py:if="fullrow"/> -->
                           </td>
                         </py:when>
 
                         <py:otherwise>
                           <td class="$col" py:attrs="td_attrs">$cell.value
-                            <hr py:if="fullrow"/>
+                            <!-- ! <hr py:if="fullrow"/> -->
                           </td>
                         </py:otherwise>
 
@@ -189,7 +200,6 @@
                   </py:if>
                 </py:for>
               </tr>
-            </py:for>
           </tbody>
         </table>
       </py:for>

