Index: htdocs/css/roadmap.css
===================================================================
--- htdocs/css/roadmap.css	(revision 1516)
+++ htdocs/css/roadmap.css	(working copy)
@@ -9,6 +9,7 @@
 }
 div.progress :link:hover, div.progress :visited:hover { background: #fff }
 div.progress .closed:link, div.progress .closed:visited { background: #bae0ba }
+div.progress .resolved:link, div.progress .resolved:visited { background: #bacaf4 }
 p.percent { font-size: 10px; line-height: 2.4em; margin: 0.9em 0 0 }
 
 /* Styles for the roadmap view */
Index: trac/Milestone.py
===================================================================
--- trac/Milestone.py	(revision 1516)
+++ trac/Milestone.py	(working copy)
@@ -57,43 +57,37 @@
         tickets.append(ticket)
     return tickets
 
-
-def get_query_links(env, milestone, grouped_by='component', group=None):
-    q = {}
-    if not group:
-        q['all_tickets'] = env.href.query(milestone=milestone)
-        q['active_tickets'] = env.href.query(milestone=milestone,
-                                             status=('new', 'assigned', 'reopened'))
-        q['closed_tickets'] = env.href.query(milestone=milestone, status='closed')
-    else:
-        q['all_tickets'] = env.href.query(milestone=milestone, grouped_by=group)
-        q['active_tickets'] = env.href.query(milestone=milestone,
-                                             grouped_by=group,
-                                             status=('new', 'assigned', 'reopened'))
-        q['closed_tickets'] = env.href.query(milestone=milestone, grouped_by=group,
-                                             status='closed')
-    return q
-
-
-def calc_ticket_stats(tickets):
+def get_tickets_progressbar(tickets, env, milestone, grouped_by='component', group=None):
     total_cnt = len(tickets)
-    active = [ticket for ticket in tickets if ticket['status'] != 'closed']
-    active_cnt = len(active)
-    closed_cnt = total_cnt - active_cnt
-
-    percent_active, percent_closed = 0, 0
+    closed_cnt = len([ticket for ticket in tickets if ticket['status'] in ('verified', 'closed')])
+    resolved_cnt = len([ticket for ticket in tickets if ticket['status'] == 'resolved'])
+    active_cnt = total_cnt - closed_cnt - resolved_cnt
+
+    # Determine percentages
+    percent_active, percent_resolved, percent_closed = 0, 0, 0
     if total_cnt > 0:
-        percent_active = round(float(active_cnt) / float(total_cnt) * 100)
-        percent_closed = round(float(closed_cnt) / float(total_cnt) * 100)
-        if percent_active + percent_closed > 100:
-            percent_closed -= 1
-
+        percent_resolved = round(float(resolved_cnt) / float(total_cnt) * 100)
+        percent_closed = round(float(closed_cnt) / float(total_cnt) * 100)
+        percent_active = 100 - percent_resolved - percent_closed
+
+    # Determine the links
+    extra = {}
+    if group: extra = {grouped_by:group} # Additional flags
+    closed_href = env.href.query(milestone=milestone, status=('verified', 'closed'), **extra)
+    resolved_href = env.href.query(milestone=milestone, status=('resolved',),**extra)
+    active_href = env.href.query(milestone=milestone, status=('new', 'assigned', 'reopened'),**extra)
+    all_href = env.href.query(milestone=milestone, **extra)
+
+    # Construct result    
+    progress = [
+        {'name': 'closed',  'capsname': 'Closed',   'pct': percent_closed,  'cnt': closed_cnt, 'url': closed_href},
+        {'name': 'resolved','capsname': 'Resolved', 'pct': percent_resolved,'cnt': resolved_cnt, 'url': resolved_href},
+        {'name': 'active',  'capsname': 'Active',   'pct': percent_active,  'cnt': active_cnt , 'url': active_href}]
     return {
         'total_tickets': total_cnt,
-        'active_tickets': active_cnt,
-        'percent_active': percent_active,
-        'closed_tickets': closed_cnt,
-        'percent_closed': percent_closed
+        'bar': progress,
+        'all_tickets_url' : all_href,
+        'right_text': '%d%%' % percent_closed
     }
 
 
@@ -333,10 +327,8 @@
         req.hdf['milestone.stats.grouped_by'] = by
 
         tickets = get_tickets_for_milestone(self.env, self.db, id, by)
-        stats = calc_ticket_stats(tickets)
+        stats = get_tickets_progressbar(tickets, self.env, milestone['name'])
         req.hdf['milestone.stats'] = stats
-        queries = get_query_links(self.env, milestone['name'])
-        req.hdf['milestone.queries'] = queries
 
         groups = self.get_groups(by)
         group_no = 0
@@ -353,9 +345,7 @@
                 if percent_total > max_percent_total:
                     max_percent_total = percent_total
             req.hdf['%s.percent_total' % prefix] = percent_total * 100
-            stats = calc_ticket_stats(group_tickets)
+            stats = get_tickets_progressbar(group_tickets, self.env, milestone['name'], by, group)
             req.hdf[prefix] = stats
-            queries = get_query_links(self.env, milestone['name'], by, group)
-            req.hdf['%s.queries' % prefix] = queries
             group_no += 1
         req.hdf['milestone.stats.max_percent_total'] = max_percent_total * 100
Index: trac/scripts/admin.py
===================================================================
--- trac/scripts/admin.py	(revision 1516)
+++ trac/scripts/admin.py	(working copy)
@@ -32,7 +32,7 @@
 
 from trac import perm, util
 from trac.env import Environment
-import trac.siteconfig
+import trac
 
 def my_sum(list):
     """Python2.2 doesn't have sum()"""
Index: trac/Timeline.py
===================================================================
--- trac/Timeline.py	(revision 1516)
+++ trac/Timeline.py	(working copy)
@@ -52,19 +52,18 @@
             sql.append("SELECT time,id,'','newticket',summary,reporter"
                        " FROM ticket WHERE time>=%s AND time<=%s")
             params += (start, stop)
-            sql.append("SELECT time,ticket,'','reopenedticket','',author "
+            sql.append("SELECT time,ticket,'',(newvalue || 'ticket'),'',author "
                        "FROM ticket_change WHERE field='status' "
-                       "AND newvalue='reopened' AND time>=%s AND time<=%s")
+                       "AND newvalue IN ('reopened', 'verified') AND time>=%s AND time<=%s")
             params += (start, stop)
-            sql.append("SELECT t1.time,t1.ticket,t2.newvalue,'closedticket',"
+            sql.append("SELECT t1.time,t1.ticket,t2.newvalue,(t1.newvalue || 'ticket'),"
                        "t3.newvalue,t1.author"
                        " FROM ticket_change t1"
-                       "   INNER JOIN ticket_change t2 ON t1.ticket = t2.ticket"
-                       "     AND t1.time = t2.time"
+                       "   LEFT OUTER JOIN ticket_change t2 ON t1.ticket = t2.ticket"
+                       "     AND t1.time = t2.time AND t2.field = 'resolution'"
                        "   LEFT OUTER JOIN ticket_change t3 ON t1.time = t3.time"
                        "     AND t1.ticket = t3.ticket AND t3.field = 'comment'"
-                       " WHERE t1.field = 'status' AND t1.newvalue = 'closed'"
-                       "   AND t2.field = 'resolution'"
+                       " WHERE t1.field = 'status' AND t1.newvalue IN ('closed', 'resolved')"
                        "   AND t1.time >= %s AND t1.time <= %s")
             params += (start,stop)
         if 'wiki' in filters:
@@ -243,7 +242,9 @@
         return item
     _render_reopenedticket = _render_ticket
     _render_newticket = _render_ticket
-    _render_closedticket = _render_ticket
+    _render_closedticket = _render_ticket
+    _render_resolvedticket = _render_ticket
+    _render_verifiedticket = _render_ticket
 
     def _render_milestone(self, req, item):
         absurls = req.args.get('format') == 'rss'
Index: trac/Roadmap.py
===================================================================
--- trac/Roadmap.py	(revision 1516)
+++ trac/Roadmap.py	(working copy)
@@ -92,10 +92,8 @@
             tickets = Milestone.get_tickets_for_milestone(self.env, self.db,
                                                           milestone['name'],
                                                           'owner')
-            stats = Milestone.calc_ticket_stats(tickets)
+            stats = Milestone.get_tickets_progressbar(tickets, self.env, milestone['name'])
             req.hdf['roadmap.milestones.%s.stats' % milestone_no] = stats
-            queries = Milestone.get_query_links(self.env, milestone['name'])
-            req.hdf['roadmap.milestones.%s.queries' % milestone_no] = queries
             milestone['tickets'] = tickets # for the iCalendar view
             milestone_no += 1
 
@@ -116,7 +114,7 @@
             status = ticket['status']
             if status == 'new' or status == 'reopened' and not ticket['owner']:
                 return 'NEEDS-ACTION'
-            elif status == 'assigned' or status == 'reopened':
+            elif status != 'closed':
                 return 'IN-PROCESS'
             elif status == 'closed':
                 if ticket['resolution'] == 'fixed': return 'COMPLETED'
Index: trac/web/cgi_frontend.py
===================================================================
--- trac/web/cgi_frontend.py	(revision 1516)
+++ trac/web/cgi_frontend.py	(working copy)
@@ -37,7 +37,7 @@
         self.__environ = environ
         self.__input = input
         self.__output = output
-
+        
         self.method = self.__environ.get('REQUEST_METHOD')
         self.remote_addr = self.__environ.get('REMOTE_ADDR')
         self.remote_user = self.__environ.get('REMOTE_USER')
Index: trac/Changeset.py
===================================================================
--- trac/Changeset.py	(revision 1516)
+++ trac/Changeset.py	(working copy)
@@ -68,7 +68,7 @@
             'time': time.asctime(time.localtime(chgset.date)),
             'author': util.escape(chgset.author or 'anonymous'),
             'message': wiki_to_html(util.wiki_escape_newline(chgset.message or '--'),
-                                    req.hdf, self.env, self.db)
+                                    req.hdf, self.env, self.db, ignore_missing_links=1)
         }
 
         oldest_rev = repos.oldest_rev
Index: trac/Ticket.py
===================================================================
--- trac/Ticket.py	(revision 1516)
+++ trac/Ticket.py	(working copy)
@@ -275,6 +275,22 @@
             hdf['%s.height' % pfx] = f['height']
         i += 1
 
+def get_default_owner(ticket, db):
+    cursor = db.cursor()
+    # Owner defaults to the component owner
+    if ticket.get('component'):
+        cursor.execute('SELECT owner FROM component '
+                       'WHERE name=%s', ticket['component'])
+        owner = cursor.fetchone()[0]
+        if owner: return owner
+    # Otherwise use the milestone owner
+    if ticket.get('milestone'):
+        cursor.execute('SELECT owner FROM milestone '
+                       'WHERE name=%s', ticket['milestone'])
+        owner = cursor.fetchone()[0]
+        if owner: return owner
+    # Otherwise use the empty owner
+    return ''
 
 class NewticketModule(Module):
 
@@ -286,13 +302,9 @@
         ticket.populate(req.args)
         ticket.setdefault('reporter', req.authname)
 
-        # The owner field defaults to the component owner
-        cursor = self.db.cursor()
-        if ticket.get('component') and ticket.get('owner', '') == '':
-            cursor.execute('SELECT owner FROM component '
-                           'WHERE name=%s', ticket['component'])
-            owner = cursor.fetchone()[0]
-            ticket['owner'] = owner
+        # Determine default owner if the owner is not set explicitly
+        if not ticket.get('owner'):
+            ticket['owner'] = get_default_owner(ticket, self.db)
 
         tktid = ticket.insert(self.db)
 
@@ -333,7 +345,7 @@
 
         req.hdf['title'] = 'New Ticket'
         req.hdf['newticket'] = dict(zip(ticket.keys(),
-                                    map(lambda x: util.escape(x), ticket.values())))
+                         map(lambda x: util.escape(x), ticket.values())))
 
         util.sql_to_hdf(self.db, "SELECT name FROM component ORDER BY name",
                         req.hdf, 'newticket.components')
@@ -364,39 +376,71 @@
 
         req.display('newticket.cs')
 
-def available_actions(ticket, perm_):
-    """ Returns the actions that can be performed on the ticket"""
-    actions = {
-        'new':      ['leave', 'resolve', 'reassign', 'accept'],
-        'assigned': ['leave', 'resolve', 'reassign'          ],
-        'reopened': ['leave', 'resolve', 'reassign'          ],
-        'closed':   ['leave',                        'reopen']
-    }
-    perm_map = {
-        'resolve': perm.TICKET_MODIFY,
-        'reassign': perm.TICKET_CHGPROP,
-        'accept': perm.TICKET_CHGPROP,
-        'reopen': perm.TICKET_CREATE
-    }
-    def has_permission(action):
-        if not action in perm_map:
-            return 1
-        return perm_.has_permission(perm_map[action])
-    return filter(has_permission, actions.get(ticket['status'], ['leave']))
 
+class TicketModule (Module):
+    def get_ticket_actions(self, ticket):
+        """ Returns the actions that can be performed on the ticket"""
+        actions_simple = {
+            'new':      ['leave', 'resolve', 'reassign', 'accept'],
+            'assigned': ['leave', 'resolve', 'reassign'          ],
+            'reopened': ['leave', 'resolve', 'reassign'          ],
+            'closed':   ['leave',                        'reopen']
+        }
+        actions_complex = {
+            'new':      ['leave','reassign','resolve',                          'accept'],
+            'assigned': ['leave','reassign','resolve',                                  ],
+            'reopened': ['leave','reassign','resolve',                                  ],
+            'resolved': ['leave','reassign',          'reopen',         'close','verify'],
+            'verified': ['leave','reassign',          'reopen','retest','close'         ],
+            'closed':   ['leave',                     'reopen','retest'                 ]
+        }
+        perm_map = {
+            'resolve': perm.TICKET_MODIFY,
+            'reassign': perm.TICKET_CHGPROP,
+            'accept': perm.TICKET_CHGPROP,
+            'reopen': perm.TICKET_CREATE,
+            'close' : perm.TICKET_MODIFY,
+            'verify': perm.TICKET_MODIFY,
+            'retest': perm.TICKET_CHGPROP,
+        }
+        complex = self.env.config.get('ticket', 'complex_workflow', 0)
+        actions = complex and actions_complex or actions_simple
+        def has_perm(p):
+            return p not in perm_map or self.perm.has_permission(perm_map[p])
+        return filter(has_perm, actions.get(ticket['status'], ['leave']))
 
-class TicketModule(Module):
-
+    def do_ticket_action(self, ticket, action, req):
+        if action == 'accept':
+            ticket['status'] =  'assigned'
+            ticket['owner'] = req.authname
+        elif action == 'resolve':
+            complex = self.env.config.get('ticket', 'complex_workflow', 0)
+            ticket['status'] = complex and 'resolved' or 'closed'
+            ticket['resolution'] = req.args.get('resolve_resolution')
+        elif action == 'reassign':
+            ticket['owner'] = req.args.get('reassign_owner') or get_default_owner(ticket, self.db)
+            if ticket['status'] == 'assigned':
+                ticket['status'] = 'new'
+        elif action == 'reopen':
+            ticket['status'] = 'reopened'
+            ticket['resolution'] = ''
+        elif action == 'verify':
+            ticket['status'] = 'verified'
+        elif action == 'close':
+            ticket['status'] = 'closed'
+        elif action == 'retest':
+            ticket['status'] = 'resolved'
+            
     def save_changes(self, req, id):
         if self.perm.has_permission(perm.TICKET_CHGPROP):
             # TICKET_CHGPROP gives permission to edit the ticket
             if not req.args.get('summary'):
                 raise util.TracError('Tickets must contain summary.')
 
-            ticket = Ticket(self.db, id)
             if 'description' in req.args or 'reporter' in req.args:
                 self.perm.assert_permission(perm.TICKET_ADMIN)
-
+
+            ticket = Ticket(self.db, id)
             ticket.populate(req.args)
 
         elif self.perm.has_permission(perm.TICKET_APPEND):
@@ -408,22 +452,11 @@
 
         # Do any action on the ticket?
         action = req.args.get('action', 'leave')
-        if action not in available_actions(ticket, self.perm):
+        if action not in self.get_ticket_actions(ticket):
             raise util.TracError('Invalid action')
 
-        # TODO: this should not be hard-coded like this
-        if action == 'accept':
-            ticket['status'] =  'assigned'
-            ticket['owner'] = req.authname
-        if action == 'resolve':
-            ticket['status'] = 'closed'
-            ticket['resolution'] = req.args.get('resolve_resolution')
-        elif action == 'reassign':
-            ticket['owner'] = req.args.get('reassign_owner')
-            ticket['status'] = 'new'
-        elif action == 'reopen':
-            ticket['status'] = 'reopened'
-            ticket['resolution'] = ''
+        # Do the action
+        self.do_ticket_action(ticket, action, req)
 
         now = int(time.time())
         ticket.save_changes(self.db, req.args.get('author', req.authname),
@@ -441,7 +474,7 @@
     def insert_ticket_data(self, req, id, ticket, reporter_id):
         """Insert ticket data into the hdf"""
         req.hdf['ticket'] = dict(zip(ticket.keys(),
-                                 map(lambda x: util.escape(x), ticket.values())))
+                         map(lambda x: util.escape(x), ticket.values())))
 
         util.sql_to_hdf(self.db, "SELECT name FROM component ORDER BY name",
                         req.hdf, 'ticket.components')
@@ -520,13 +553,13 @@
             req.hdf['ticket.attach_href'] = self.env.href.attachment('ticket', id)
 
         # Add the possible actions to hdf
-        for action in available_actions(ticket, self.perm):
+        for action in self.get_ticket_actions(ticket):
             req.hdf['ticket.actions.' + action] = '1'
 
     def render(self, req):
-        self.perm.assert_permission(perm.TICKET_VIEW)
+        self.perm.assert_permission (perm.TICKET_VIEW)
 
-        action = req.args.get('action', 'view')
+        action = req.args.get('action', None)
         preview = req.args.has_key('preview')
 
         if not req.args.has_key('id'):
@@ -534,8 +567,7 @@
 
         id = int(req.args.get('id'))
 
-        if not preview \
-           and action in ('leave', 'accept', 'reopen', 'resolve', 'reassign'):
+        if not preview and action:
             self.save_changes(req, id)
 
         ticket = Ticket(self.db, id)
Index: trac/WikiFormatter.py
===================================================================
--- trac/WikiFormatter.py	(revision 1516)
+++ trac/WikiFormatter.py	(working copy)
@@ -136,9 +136,10 @@
     env = None
     absurls = 0
 
-    def __init__(self, env, db, absurls=0):
+    def __init__(self, env, db, absurls=0, ignore_missing_links=0):
         self.env = env
-        self.db = db
+        self.db = db
+        self.ignore_missing_links = ignore_missing_links
         self._href = absurls and env.abs_href or env.href
         self._local = env.config.get('project', 'url', '') or env.abs_href.base
 
@@ -252,12 +253,14 @@
             page = page[:page.find('#')]
         page = urllib.unquote(page)
         text = urllib.unquote(text)
-        if not self.env._wiki_pages.has_key(page):
-            return '<a class="missing wiki" href="%s" rel="nofollow">%s?</a>' \
-                   % (self._href.wiki(page) + anchor, text)
-        else:
+        if self.env._wiki_pages.has_key(page):
             return '<a class="wiki" href="%s">%s</a>' \
                    % (self._href.wiki(page) + anchor, text)
+        elif self.ignore_missing_links:
+            return text
+        else:
+            return '<a class="missing wiki" href="%s" rel="nofollow">%s?</a>' \
+                   % (self._href.wiki(page) + anchor, text)
 
     def _make_changeset_link(self, rev, text):
         cursor = self.db.cursor()
@@ -390,8 +393,8 @@
                                          'meta|param|doctype)')
     _htmlproc_disallow_attribute = re.compile('(?i)<[^>]*\s+(on\w+)=')
 
-    def __init__(self, hdf, env, db, absurls=0):
-        CommonFormatter.__init__(self, env, db, absurls)
+    def __init__(self, hdf, env, db, absurls=0, ignore_missing_links=0):
+        CommonFormatter.__init__(self, env, db, absurls, ignore_missing_links)
         self.hdf = hdf
         self.anchors = []
 
@@ -636,14 +639,12 @@
         self.close_indentation()
         self.close_list()
 
-
-def wiki_to_html(wikitext, hdf, env, db, absurls=0):
+def wiki_to_html(wikitext, hdf, env, db, absurls=0, ignore_missing_links=0):
     out = StringIO.StringIO()
-    Formatter(hdf, env, db, absurls).format(wikitext, out)
+    Formatter(hdf, env, db, absurls, ignore_missing_links).format(wikitext, out)
     return out.getvalue()
 
-
-def wiki_to_oneliner(wikitext, env, db, absurls=0):
+def wiki_to_oneliner(wikitext, env, db, absurls=0, ignore_missing_links=0):
     out = StringIO.StringIO()
-    OneLinerFormatter(env, db, absurls).format(wikitext, out)
+    OneLinerFormatter(env, db, absurls, ignore_missing_links).format(wikitext, out)
     return out.getvalue()
Index: templates/roadmap.cs
===================================================================
--- templates/roadmap.cs	(revision 1516)
+++ templates/roadmap.cs	(working copy)
@@ -39,27 +39,21 @@
     with:stats = milestone.stats ?><?cs
      if:#stats.total_tickets > #0 ?>
       <div class="progress">
-       <a class="closed" href="<?cs
-         var:milestone.queries.closed_tickets ?>" style="width: <?cs
-         var:#stats.percent_closed ?>%" title="<?cs
-         var:#stats.closed_tickets ?> of <?cs
+       <?cs each:bar = stats.bar ?>
+       <a class="<?cs var:bar.name ?>" href="<?cs
+         var:bar.url ?>" style="width: <?cs
+         var:#bar.pct ?>%" title="<?cs
+         var:#bar.cnt ?> of <?cs
          var:#stats.total_tickets ?> ticket<?cs
-         if:#stats.total_tickets != #1 ?>s<?cs /if ?> closed"></a>
-       <a class="open" href="<?cs
-         var:milestone.queries.active_tickets ?>" style="width: <?cs
-         var:#stats.percent_active ?>%" title="<?cs
-         var:#stats.active_tickets ?> of <?cs
-         var:#stats.total_tickets ?> ticket<?cs
-         if:#stats.total_tickets != #1 ?>s<?cs /if ?> active"></a>
+         if:#stats.total_tickets != #1 ?>s<?cs /if ?> <?cs var:bar.name ?>"></a>
+       <?cs /each ?>
       </div>
-      <p class="percent"><?cs var:#stats.percent_closed ?>%</p>
+      <p class="percent"><?cs var:stats.right_text ?></p>
       <dl>
-       <dt>Active tickets:</dt>
-       <dd><a href="<?cs var:milestone.queries.active_tickets ?>"><?cs
-         var:stats.active_tickets ?></a></dd>
-       <dt>Closed tickets:</dt>
-       <dd><a href="<?cs var:milestone.queries.closed_tickets ?>"><?cs
-         var:stats.closed_tickets ?></a></dd>
+       <?cs each:bar = stats.bar ?>
+       <dt><?cs var:bar.capsname ?> tickets:</dt>
+       <dd><a href="<?cs var:bar.url ?>"><?cs var:bar.cnt ?></a></dd>
+       <?cs /each ?>
       </dl><?cs
      /if ?><?cs
     /with ?>
Index: templates/ticket.cs
===================================================================
--- templates/ticket.cs	(revision 1516)
+++ templates/ticket.cs	(working copy)
@@ -30,7 +30,7 @@
 <div id="content" class="ticket">
 
  <h1>Ticket #<?cs var:ticket.id ?> <?cs
- if:ticket.status == 'closed' ?>(Closed: <?cs var:ticket.resolution ?>)<?cs
+ if:ticket.resolution ?>(<?cs var:ticket.status ?>: <?cs var:ticket.resolution ?>)<?cs
  elif:ticket.status != 'new' ?>(<?cs var:ticket.status ?>)<?cs
  /if ?></h1>
 
@@ -205,7 +205,9 @@
  </fieldset><?cs /if ?>
 
  <?cs if:ticket.actions.accept || ticket.actions.reopen ||
-         ticket.actions.resolve || ticket.actions.reassign ?>
+         ticket.actions.resolve || ticket.actions.reassign ||
+         ticket.actions.retest || ticket.actions.verify ||
+         ticket.actions.close ?>
  <fieldset id="action">
   <legend>Action</legend><?cs
   if:!ticket.action ?><?cs set:ticket.action = 'leave' ?><?cs
@@ -216,7 +218,7 @@
      /if ?> /><?cs
   /def ?>
   <?cs call:action_radio('leave') ?>
-   <label for="leave">leave as <?cs var:ticket.status ?></label><br /><?cs
+  <label for="leave">leave as <?cs var:ticket.status ?></label><br /><?cs
   if:ticket.actions.accept ?><?cs
    call:action_radio('accept') ?>
    <label for="accept">accept ticket</label><br /><?cs
@@ -225,8 +227,20 @@
    call:action_radio('reopen') ?>
    <label for="reopen">reopen ticket</label><br /><?cs
   /if ?><?cs
+  if:ticket.actions.retest ?><?cs
+    call:action_radio('retest') ?>
+    <label for="retest">retest ticket</label><br /><?cs
+  /if ?><?cs
+  if:ticket.actions.verify ?><?cs
+    call:action_radio('verify') ?>
+    <label for="verify">verify ticket</label><br /><?cs
+  /if ?><?cs
+  if:ticket.actions.close ?><?cs
+    call:action_radio('close') ?>
+    <label for="close">close ticket</label><br /><?cs
+  /if ?><?cs
   if:ticket.actions.resolve ?><?cs
-   call:action_radio('resolve') ?>
+    call:action_radio('resolve') ?>
    <label for="resolve">resolve</label>
    <label for="resolve_resolution">as:</label>
    <?cs call:hdf_select(enums.resolution, "resolve_resolution",
@@ -237,7 +251,7 @@
    <label for="reassign">reassign</label>
    <label>to:<?cs
    if:len(ticket.users) ?><?cs
-    call:hdf_select(ticket.users, "reassign_owner", ticket.reassign_owner, 0) ?><?cs
+     call:hdf_select(ticket.users, "reassign_owner", ticket.reassign_owner, 1) ?><?cs
    else ?>
     <input type="text" id="reassign_owner" name="reassign_owner" size="40" value="<?cs
       var:ticket.reassign_owner ?>" /><?cs
@@ -259,8 +273,9 @@
    </script><?cs
   /if ?>
  </fieldset>
+ <?cs else ?>
+  <input type="hidden" name="action" value="leave" />
  <?cs /if ?>
-
  <script type="text/javascript" src="<?cs
    var:htdocs_location ?>js/wikitoolbar.js"></script>
 
Index: templates/newticket.cs
===================================================================
--- templates/newticket.cs	(revision 1516)
+++ templates/newticket.cs	(working copy)
@@ -2,7 +2,7 @@
 <?cs include "header.cs" ?>
 <?cs include "macros.cs" ?>
 <script type="text/javascript">
-addEvent(window, 'load', function() { document.getElementById('summary').focus()}); 
+addEvent(window, 'load', function() { document.getElementById('summary').focus()});
 </script>
 
 <div id="ctxtnav" class="nav"></div>
Index: templates/milestone.cs
===================================================================
--- templates/milestone.cs	(revision 1516)
+++ templates/milestone.cs	(working copy)
@@ -94,7 +94,7 @@
    <select name="target" id="target">
     <option value="">None</option><?cs
      each:other = milestones ?><?cs if:other != milestone.name ?>
-      <option><?cs var:other ?></option><?cs 
+      <option><?cs var:other ?></option><?cs
      /if ?><?cs /each ?>
    </select>
    <div class="buttons">
@@ -121,27 +121,21 @@
    with:stats = milestone.stats ?><?cs
     if:#stats.total_tickets > #0 ?>
      <div class="progress">
-      <a class="closed" href="<?cs
-        var:milestone.queries.closed_tickets ?>" style="width: <?cs
-        var:#stats.percent_closed ?>%" title="<?cs
-        var:#stats.closed_tickets ?> of <?cs
-        var:#stats.total_tickets ?> ticket<?cs
-        if:#stats.total_tickets != #1 ?>s<?cs /if ?> closed"></a>
-      <a class="open" href="<?cs
-        var:milestone.queries.active_tickets ?>" style="width: <?cs
-        var:#stats.percent_active ?>%" title="<?cs
-        var:#stats.active_tickets ?> of <?cs
-        var:#stats.total_tickets ?> ticket<?cs
-        if:#stats.total_tickets != #1 ?>s<?cs /if ?> active"></a>
+       <?cs each:bar = stats.bar ?>
+       <a class="<?cs var:bar.name ?>" href="<?cs
+         var:bar.url ?>" style="width: <?cs
+         var:#bar.pct ?>%" title="<?cs
+         var:#bar.cnt ?> of <?cs
+         var:#stats.total_tickets ?> ticket<?cs
+         if:#stats.total_tickets != #1 ?>s<?cs /if ?> <?cs var:bar.name ?>"></a>
+       <?cs /each ?>
      </div>
-     <p class="percent"><?cs var:#stats.percent_closed ?>%</p>
+     <p class="percent"><?cs var:stats.right_text ?></p>
      <dl>
-      <dt>Active tickets:</dt>
-      <dd><a href="<?cs var:milestone.queries.active_tickets ?>"><?cs
-        var:stats.active_tickets ?></a></dd>
-      <dt>Closed tickets:</dt>
-      <dd><a href="<?cs var:milestone.queries.closed_tickets ?>"><?cs
-        var:stats.closed_tickets ?></a></dd>
+       <?cs each:bar = stats.bar ?>
+       <dt><?cs var:bar.capsname ?> tickets:</dt>
+       <dd><a href="<?cs var:bar.url ?>"><?cs var:bar.cnt ?></a></dd>
+       <?cs /each ?>
      </dl><?cs
     /if ?><?cs
    /with ?>
@@ -165,25 +159,20 @@
      each:group = milestone.stats.groups ?>
       <tr>
        <th scope="row"><a href="<?cs
-         var:group.queries.all_tickets ?>"><?cs var:group.name ?></a></th>
+         var:group.all_tickets_url ?>"><?cs var:group.name ?></a></th>
        <td nowrap=nowrap><?cs if:#group.total_tickets ?>
         <div class="progress" style="width: <?cs
           var:#group.percent_total * #80 / #milestone.stats.max_percent_total ?>%">
-         <a class="closed" href="<?cs
-           var:group.queries.closed_tickets ?>" style="width: <?cs
-           var:#group.percent_closed ?>%" title="<?cs
-          var:group.closed_tickets ?> of <?cs
-          var:group.total_tickets ?> ticket<?cs
-          if:group.total_tickets != #1 ?>s<?cs /if ?> closed"></a>
-         <a class="open" href="<?cs
-           var:group.queries.active_tickets ?>" style="width: <?cs
-           var:#group.percent_active - 1 ?>%" title="<?cs
-          var:group.active_tickets ?> of <?cs
-          var:group.total_tickets ?> ticket<?cs
-          if:group.total_tickets != 1 ?>s<?cs /if ?> active"></a>
+				 <?cs each:bar = group.bar ?>
+				 <a class="<?cs var:bar.name ?>" href="<?cs
+					 var:bar.url ?>" style="width: <?cs
+					 var:#bar.pct ?>%" title="<?cs
+					 var:#bar.cnt ?> of <?cs
+					 var:#group.total_tickets ?> ticket<?cs
+					 if:#group.total_tickets != #1 ?>s<?cs /if ?> <?cs var:bar.name ?>"></a>
+				 <?cs /each ?>
         </div>
-        <p class="percent"><?cs var:group.closed_tickets ?>/<?cs
-         var:group.total_tickets ?></p>
+        <p class="percent"><?cs set:sep="" ?><?cs each:bar = group.bar ?><?cs var:sep ?><?cs var:#bar.cnt ?><?cs set:sep="/" ?><?cs /each ?></p>
        <?cs /if ?></td>
       </tr><?cs
      /each ?>
Index: templates/timeline.cs
===================================================================
--- templates/timeline.cs	(revision 1516)
+++ templates/timeline.cs	(working copy)
@@ -59,12 +59,25 @@
    set:imessage = '' ?><?cs
   /if ?><?cs
   call:tlitem(item.href, 'closedticket',
+              'Ticket <em>#' + item.idata + '</em> closed by ' + item.author,
+              item.tdata + imessage) ?><?cs
+ elif:item.type == 'resolvedticket' ?><?cs
+  if:item.message ?><?cs
+   set:imessage = ' - ' + item.message ?><?cs
+  else ?><?cs
+   set:imessage = '' ?><?cs
+  /if ?><?cs
+  call:tlitem(item.href, 'closedticket',
               'Ticket <em>#' + item.idata + '</em> resolved by ' + item.author,
               item.tdata + imessage) ?><?cs
  elif:item.type == 'reopenedticket' ?><?cs
   call:tlitem(item.href, 'newticket',
               'Ticket <em>#' + item.idata + '</em> reopened by ' + item.author,
               '') ?><?cs
+ elif:item.type == 'verifiedticket' ?><?cs
+  call:tlitem(item.href, 'newticket',
+              'Ticket <em>#' + item.idata + '</em> verified by ' + item.author,
+              '') ?><?cs
  elif:item.type == 'wiki' ?><?cs
   call:tlitem(item.href, 'wiki',
               '<em>' + item.tdata + '</em> edited by ' + item.author,
@@ -78,7 +91,7 @@
 
 <div id="help">
  <hr />
- <strong>Note:</strong> See <a href="<?cs var:trac.href.wiki ?>/TracTimeline">TracTimeline</a> 
+ <strong>Note:</strong> See <a href="<?cs var:trac.href.wiki ?>/TracTimeline">TracTimeline</a>
  for information about the timeline view.
 </div>
 

