Index: /trunk/src/VBox/ValidationKit/testmanager/core/globalresource.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/core/globalresource.py	(revision 61471)
+++ /trunk/src/VBox/ValidationKit/testmanager/core/globalresource.py	(revision 61472)
@@ -73,5 +73,5 @@
     def initFromDbRow(self, aoRow):
         """
-        Reinitialize from a SELECT * FROM TestCases row.
+        Reinitialize from a SELECT * FROM GlobalResources row.
         Returns self. Raises exception if no row.
         """
Index: /trunk/src/VBox/ValidationKit/testmanager/core/schedgroup.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/core/schedgroup.py	(revision 61471)
+++ /trunk/src/VBox/ValidationKit/testmanager/core/schedgroup.py	(revision 61472)
@@ -65,4 +65,5 @@
     kiMax_iSchedPriority        = 32;
 
+    kcDbColumns                 = 8
 
     def __init__(self):
@@ -125,5 +126,5 @@
         """
         SchedGroupMemberData.initFromDbRow(self, aoRow);
-        self.oTestGroup = TestGroupData().initFromDbRow(aoRow[8:]);
+        self.oTestGroup = TestGroupData().initFromDbRow(aoRow[SchedGroupMemberData.kcDbColumns:]);
         return self;
 
@@ -170,8 +171,11 @@
     ksParam_idBuildSrc          = 'SchedGroup_idBuildSrc';
     ksParam_idBuildSrcTestSuite = 'SchedGroup_idBuildSrcTestSuite';
+    ksParam_sComment            = 'SchedGroup_sComment';
 
     kasAllowNullAttributes      = ['idSchedGroup', 'tsEffective', 'tsExpire', 'uidAuthor', 'sDescription',
-                                   'idBuildSrc', 'idBuildSrcTestSuite'];
+                                   'idBuildSrc', 'idBuildSrcTestSuite', 'sComment' ];
     kasValidValues_enmScheduler = [ksScheduler_BestEffortContinousItegration, ];
+
+    kcDbColumns                 = 11;
 
     # Scheduler types
@@ -197,5 +201,6 @@
         self.enmScheduler            = SchedGroupData.ksScheduler_BestEffortContinousItegration;
         self.idBuildSrc              = None;
-        self.idBuildSrcTestSuite = None;
+        self.idBuildSrcTestSuite     = None;
+        self.sComment                = None;
 
     def initFromDbRow(self, aoRow):
@@ -218,5 +223,6 @@
         self.enmScheduler            = aoRow[7];
         self.idBuildSrc              = aoRow[8];
-        self.idBuildSrcTestSuite = aoRow[9];
+        self.idBuildSrcTestSuite     = aoRow[9];
+        self.sComment                = aoRow[10];
         return self;
 
@@ -496,14 +502,16 @@
                           '         enmScheduler,\n'
                           '         idBuildSrc,\n'
-                          '         idBuildSrcTestSuite)\n'
-                          'VALUES (%s, %s, %s, %s, %s, %s, %s)\n'
+                          '         idBuildSrcTestSuite,\n'
+                          '         sComment)\n'
+                          'VALUES (%s, %s, %s, %s, %s, %s, %s, %s)\n'
                           'RETURNING idSchedGroup\n'
-                          , (uidAuthor,
-                             oData.sName,
-                             oData.sDescription,
-                             oData.fEnabled,
-                             oData.enmScheduler,
-                             oData.idBuildSrc,
-                             oData.idBuildSrcTestSuite));
+                          , ( uidAuthor,
+                              oData.sName,
+                              oData.sDescription,
+                              oData.fEnabled,
+                              oData.enmScheduler,
+                              oData.idBuildSrc,
+                              oData.idBuildSrcTestSuite,
+                              oData.sComment ));
         idSchedGroup = self._oDb.fetchOne()[0];
         oData.idSchedGroup = idSchedGroup;
@@ -803,8 +811,9 @@
     def exists(self, sName):
         """Checks if a group with the given name exists."""
-        self._oDb.execute('SELECT *\n'
+        self._oDb.execute('SELECT idSchedGroup\n'
                           'FROM   SchedGroups\n'
                           'WHERE  tsExpire   = \'infinity\'::TIMESTAMP\n'
-                          '   AND sName = %s\n'
+                          '   AND sName      = %s\n'
+                          'LIMIT 1\n'
                           , (sName,));
         return self._oDb.getRowCount() > 0;
@@ -814,5 +823,5 @@
         self._oDb.execute('SELECT   *\n'
                           'FROM     SchedGroups\n'
-                          'WHERE    tsExpire   = \'infinity\'::timestamp\n'
+                          'WHERE    tsExpire     = \'infinity\'::timestamp\n'
                           '  AND    idSchedGroup = %s;', (idSchedGroup,))
         aRows = self._oDb.fetchAll()
@@ -825,15 +834,4 @@
             return None
 
-    def remove(self, uidAuthor, idScedGroup, fNeedCommit=True):
-        """Historize Scheduling Group record"""
-        self._oDb.execute('UPDATE SchedGroups\n'
-                          'SET    tsExpire     = CURRENT_TIMESTAMP,\n'
-                          '       uidAuthor    = %s\n'
-                          'WHERE  idSchedGroup = %s\n'
-                          '   AND tsExpire     = \'infinity\'::TIMESTAMP\n',
-                          (uidAuthor, idScedGroup))
-        if fNeedCommit:
-            self._oDb.commit()
-        return True
 
     #
@@ -878,6 +876,7 @@
                           '         enmScheduler,\n'
                           '         idBuildSrc,\n'
-                          '         idBuildSrcTestSuite )\n'
-                          'VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, %s )\n'
+                          '         idBuildSrcTestSuite,\n'
+                          '         sComment )\n'
+                          'VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )\n'
                           , ( uidAuthor,
                               tsEffective,
@@ -888,5 +887,6 @@
                               oData.enmScheduler,
                               oData.idBuildSrc,
-                              oData.idBuildSrcTestSuite, ));
+                              oData.idBuildSrcTestSuite,
+                              oData.sComment, ));
         return True;
 
Index: /trunk/src/VBox/ValidationKit/testmanager/core/testcase.pgsql
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/core/testcase.pgsql	(revision 61471)
+++ /trunk/src/VBox/ValidationKit/testmanager/core/testcase.pgsql	(revision 61472)
@@ -32,4 +32,10 @@
 DROP FUNCTION IF EXISTS del_testcase(INTEGER);
 DROP FUNCTION IF EXISTS TestCaseLogic_delEntry(INTEGER, INTEGER);
+DROP FUNCTION IF EXISTS TestCaseLogic_addEntry(a_uidAuthor INTEGER, a_sName TEXT, a_sDescription TEXT,
+                                               a_fEnabled BOOL, a_cSecTimeout INTEGER,  a_sTestBoxReqExpr TEXT,
+                                               a_sBuildReqExpr TEXT, a_sBaseCmd TEXT, a_sTestSuiteZips TEXT);
+DROP FUNCTION IF EXISTS TestCaseLogic_editEntry(a_uidAuthor INTEGER, a_idTestCase INTEGER, a_sName TEXT, a_sDescription TEXT,
+                                                a_fEnabled BOOL, a_cSecTimeout INTEGER,  a_sTestBoxReqExpr TEXT,
+                                                a_sBuildReqExpr TEXT, a_sBaseCmd TEXT, a_sTestSuiteZips TEXT);
 
 ---
@@ -96,7 +102,9 @@
 $$ LANGUAGE plpgsql;
 
+
 CREATE OR REPLACE function TestCaseLogic_addEntry(a_uidAuthor INTEGER, a_sName TEXT, a_sDescription TEXT, 
                                                   a_fEnabled BOOL, a_cSecTimeout INTEGER,  a_sTestBoxReqExpr TEXT, 
-                                                  a_sBuildReqExpr TEXT, a_sBaseCmd TEXT, a_sTestSuiteZips TEXT) 
+                                                  a_sBuildReqExpr TEXT, a_sBaseCmd TEXT, a_sTestSuiteZips TEXT,
+                                                  a_sComment TEXT)
     RETURNS INTEGER AS $$
     DECLARE 
@@ -106,7 +114,7 @@
 
         INSERT INTO TestCases (uidAuthor, sName, sDescription, fEnabled, cSecTimeout, 
-                               sTestBoxReqExpr, sBuildReqExpr, sBaseCmd, sTestSuiteZips)
+                               sTestBoxReqExpr, sBuildReqExpr, sBaseCmd, sTestSuiteZips, sComment)
             VALUES (a_uidAuthor, a_sName, a_sDescription, a_fEnabled, a_cSecTimeout, 
-                    a_sTestBoxReqExpr, a_sBuildReqExpr, a_sBaseCmd, a_sTestSuiteZips)
+                    a_sTestBoxReqExpr, a_sBuildReqExpr, a_sBaseCmd, a_sTestSuiteZips, a_Comment)
             RETURNING idTestcase INTO v_idTestCase;
         RETURN v_idTestCase;
@@ -114,7 +122,9 @@
 $$ LANGUAGE plpgsql;
 
+
 CREATE OR REPLACE function TestCaseLogic_editEntry(a_uidAuthor INTEGER, a_idTestCase INTEGER, a_sName TEXT, a_sDescription TEXT, 
                                                    a_fEnabled BOOL, a_cSecTimeout INTEGER,  a_sTestBoxReqExpr TEXT, 
-                                                   a_sBuildReqExpr TEXT, a_sBaseCmd TEXT, a_sTestSuiteZips TEXT) 
+                                                   a_sBuildReqExpr TEXT, a_sBaseCmd TEXT, a_sTestSuiteZips TEXT,
+                                                   a_sComment TEXT)
     RETURNS INTEGER AS $$
     DECLARE 
@@ -126,7 +136,7 @@
         PERFORM TestCaseLogic_historizeEntry(a_idTestCase, CURRENT_TIMESTAMP);
         INSERT INTO TestCases (idTestCase, uidAuthor, sName, sDescription, fEnabled, cSecTimeout, 
-                               sTestBoxReqExpr, sBuildReqExpr, sBaseCmd, sTestSuiteZips)
+                               sTestBoxReqExpr, sBuildReqExpr, sBaseCmd, sTestSuiteZips, sComment)
             VALUES (a_idTestCase, a_uidAuthor, a_sName, a_sDescription, a_fEnabled, a_cSecTimeout, 
-                    a_sTestBoxReqExpr, a_sBuildReqExpr, a_sBaseCmd, a_sTestSuiteZips)
+                    a_sTestBoxReqExpr, a_sBuildReqExpr, a_sBaseCmd, a_sTestSuiteZips, a_sComment)
             RETURNING idGenTestCase INTO v_idGenTestCase;
        RETURN v_idGenTestCase;
Index: /trunk/src/VBox/ValidationKit/testmanager/core/testcase.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/core/testcase.py	(revision 61471)
+++ /trunk/src/VBox/ValidationKit/testmanager/core/testcase.py	(revision 61472)
@@ -438,8 +438,10 @@
     ksParam_sBaseCmd        = 'TestCase_sBaseCmd'
     ksParam_sValidationKitZips = 'TestCase_sValidationKitZips'
+    ksParam_sComment        = 'TestCase_sComment'
 
     kasAllowNullAttributes  = [ 'idTestCase', 'tsEffective', 'tsExpire', 'uidAuthor', 'idGenTestCase', 'sDescription',
-                                'sTestBoxReqExpr', 'sBuildReqExpr', 'sValidationKitZips', ];
-
+                                'sTestBoxReqExpr', 'sBuildReqExpr', 'sValidationKitZips', 'sComment' ];
+
+    kcDbColumns             = 14;
 
     def __init__(self):
@@ -463,4 +465,5 @@
         self.sBaseCmd           = None;
         self.sValidationKitZips = None;
+        self.sComment           = None;
 
     def initFromDbRow(self, aoRow):
@@ -485,4 +488,5 @@
         self.sBaseCmd           = aoRow[11];
         self.sValidationKitZips = aoRow[12];
+        self.sComment           = aoRow[13];
         return self;
 
@@ -1148,5 +1152,6 @@
         self._oDb.callProc('TestCaseLogic_addEntry',
                            ( uidAuthor, oData.sName, oData.sDescription, oData.fEnabled, oData.cSecTimeout,
-                             oData.sTestBoxReqExpr, oData.sBuildReqExpr, oData.sBaseCmd, oData.sValidationKitZips ));
+                             oData.sTestBoxReqExpr, oData.sBuildReqExpr, oData.sBaseCmd, oData.sValidationKitZips,
+                             oData.sComment ));
         oData.idTestCase = self._oDb.fetchOne()[0];
 
@@ -1203,5 +1208,6 @@
             self._oDb.callProc('TestCaseLogic_editEntry', ( uidAuthor, oData.idTestCase, oData.sName, oData.sDescription,
                                                             oData.fEnabled, oData.cSecTimeout, oData.sTestBoxReqExpr,
-                                                            oData.sBuildReqExpr, oData.sBaseCmd, oData.sValidationKitZips ));
+                                                            oData.sBuildReqExpr, oData.sBaseCmd, oData.sValidationKitZips,
+                                                            oData.sComment ));
             oData.idGenTestCase = self._oDb.fetchOne()[0];
 
Index: /trunk/src/VBox/ValidationKit/testmanager/core/testgroup.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/core/testgroup.py	(revision 61471)
+++ /trunk/src/VBox/ValidationKit/testmanager/core/testgroup.py	(revision 61472)
@@ -54,4 +54,5 @@
     kiMax_iSchedPriority        = 31;
 
+    kcDbColumns                 = 7;
 
     def __init__(self):
@@ -133,5 +134,5 @@
         TestGroupMemberData.initFromDbRow(self, aoRow);
         self.oTestCase = TestCaseDataEx();
-        self.oTestCase.initFromDbRowEx(aoRow[7:], oDb, tsNow);
+        self.oTestCase.initFromDbRowEx(aoRow[TestGroupMemberData.kcDbColumns:], oDb, tsNow);
         return self;
 
@@ -168,17 +169,7 @@
     def initFromDbRowEx(self, aoRow):
         """
-        Reinitialize from a :WRONG QUERY:
-
-            SELECT TestCases.idTestCase,
-                   TestGroupMembers.tsEffective,
-                   TestGroupMembers.tsExpire,
-                   TestGroupMembers.uidAuthor,
-                   TestCases.idGenTestCase,
-                   TestCases.sName,
-                   TestCases.sDescription,
-                   TestCases.fEnabled,
-                   TestCases.cSecTimeout,
-                   TestCases.sBaseCmd,
-                   TestCases.sValidationKitZips,
+        Reinitialize from this query:
+
+            SELECT TestCases.*,
                    TestGroupMembers.idTestGroup,
                    TestGroupMembers.aidTestCaseArgs
@@ -186,5 +177,5 @@
             WHERE TestCases.idTestCase = TestGroupMembers.idTestCase
 
-        ..row. Represents complete test group member (test case) info.
+        Represents complete test group member (test case) info.
         Returns object of type TestGroupMemberData2. Raises exception if no row.
         """
@@ -208,6 +199,9 @@
     ksParam_sName           = 'TestGroup_sName'
     ksParam_sDescription    = 'TestGroup_sDescription'
-
-    kasAllowNullAttributes      = ['idTestGroup', 'tsEffective', 'tsExpire', 'uidAuthor', 'sDescription' ];
+    ksParam_sComment        = 'TestGroup_sComment'
+
+    kasAllowNullAttributes      = ['idTestGroup', 'tsEffective', 'tsExpire', 'uidAuthor', 'sDescription', 'sComment' ];
+
+    kcDbColumns             = 7;
 
     def __init__(self):
@@ -224,4 +218,5 @@
         self.sName           = None
         self.sDescription    = None
+        self.sComment        = None
 
     def initFromDbRow(self, aoRow):
@@ -239,4 +234,5 @@
         self.sName           = aoRow[4]
         self.sDescription    = aoRow[5]
+        self.sComment        = aoRow[6]
         return self
 
@@ -425,10 +421,11 @@
         # Do the job.
         #
-        self._oDb.execute('INSERT INTO TestGroups (uidAuthor, sName, sDescription)\n'
+        self._oDb.execute('INSERT INTO TestGroups (uidAuthor, sName, sDescription, sComment)\n'
                           'VALUES (%s, %s, %s)\n'
                           'RETURNING idTestGroup\n'
                           , ( uidAuthor,
                               oData.sName,
-                              oData.sDescription,));
+                              oData.sDescription,
+                              oData.sComment, ));
         idTestGroup = self._oDb.fetchOne()[0];
         oData.idTestGroup = idTestGroup;
@@ -464,10 +461,11 @@
             self._historizeTestGroup(oData.idTestGroup);
             self._oDb.execute('INSERT INTO TestGroups\n'
-                              '       (uidAuthor, idTestGroup, sName, sDescription)\n'
-                              'VALUES (%s, %s, %s, %s)\n'
+                              '       (uidAuthor, idTestGroup, sName, sDescription, sComment)\n'
+                              'VALUES (%s, %s, %s, %s, %s)\n'
                               , ( uidAuthor,
                                   oData.idTestGroup,
                                   oData.sName,
-                                  oData.sDescription, ));
+                                  oData.sDescription,
+                                  oData.sComment ));
 
         # Create a lookup dictionary for old entries.
@@ -634,5 +632,6 @@
                               'WHERE    tsExpire     = \'infinity\'::timestamp\n'
                               '  AND    idTestGroup  = %s\n'
-                              'ORDER BY idTestGroup ASC;', (idTestGroup,))
+                              'ORDER BY idTestGroup ASC;'
+                              , (idTestGroup,))
         else:
             self._oDb.execute('SELECT   *\n'
@@ -641,6 +640,6 @@
                               '  AND    tsEffective <= %s\n'
                               '  AND    idTestGroup  = %s\n'
-                              'ORDER BY idTestGroup ASC;',
-                              (tsNow, tsNow, idTestGroup))
+                              'ORDER BY idTestGroup ASC;'
+                              , (tsNow, tsNow, idTestGroup))
 
         aRows = self._oDb.fetchAll()
Index: /trunk/src/VBox/ValidationKit/testmanager/db/TestManagerDatabaseInit.pgsql
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/db/TestManagerDatabaseInit.pgsql	(revision 61471)
+++ /trunk/src/VBox/ValidationKit/testmanager/db/TestManagerDatabaseInit.pgsql	(revision 61472)
@@ -301,4 +301,7 @@
     -- @DOWNLOAD_BASE_URL@ prefix can be used to refer to this area.
     sTestSuiteZips      TEXT        DEFAULT NULL,
+
+    -- Comment regarding a change or something.
+    sComment            TEXT        DEFAULT NULL,
 
     PRIMARY KEY (idTestCase, tsExpire)
@@ -511,7 +514,9 @@
 
     --- The name of the scheduling group.
-    sName               text        NOT NULL,
+    sName               TEXT        NOT NULL,
     --- Optional group description.
-    sDescription        text,
+    sDescription        TEXT,
+    -- Comment regarding a change or something.
+    sComment            TEXT        DEFAULT NULL,
 
     PRIMARY KEY (idTestGroup, tsExpire)
@@ -604,7 +609,7 @@
 
     --- The name of the scheduling group.
-    sName               text        NOT NULL,
+    sName               TEXT        NOT NULL,
     --- Optional group description.
-    sDescription        text,
+    sDescription        TEXT,
     --- Indicates whether this group is currently enabled.
     fEnabled            boolean     NOT NULL,
@@ -619,4 +624,6 @@
     -- Non-unique foreign key: BuildSources(idBuildSrc)
     idBuildSrcTestSuite INTEGER     DEFAULT NULL,
+    -- Comment regarding a change or something.
+    sComment            TEXT        DEFAULT NULL,
 
     PRIMARY KEY (idSchedGroup, tsExpire)
Index: /trunk/src/VBox/ValidationKit/testmanager/db/tmdb-r20-testcases-1-testgroups-1-schedgroups-1.pgsql
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/db/tmdb-r20-testcases-1-testgroups-1-schedgroups-1.pgsql	(revision 61472)
+++ /trunk/src/VBox/ValidationKit/testmanager/db/tmdb-r20-testcases-1-testgroups-1-schedgroups-1.pgsql	(revision 61472)
@@ -0,0 +1,57 @@
+-- $Id$
+--- @file
+-- VBox Test Manager Database - Adds sComment to TestCases, TestGroups
+--                              and SchedGroups.
+--
+
+--
+-- Copyright (C) 2013-2016 Oracle Corporation
+--
+-- This file is part of VirtualBox Open Source Edition (OSE), as
+-- available from http://www.virtualbox.org. This file is free software;
+-- you can redistribute it and/or modify it under the terms of the GNU
+-- General Public License (GPL) as published by the Free Software
+-- Foundation, in version 2 as it comes in the "COPYING" file of the
+-- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+-- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+--
+-- The contents of this file may alternatively be used under the terms
+-- of the Common Development and Distribution License Version 1.0
+-- (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+-- VirtualBox OSE distribution, in which case the provisions of the
+-- CDDL are applicable instead of those of the GPL.
+--
+-- You may elect to license modified versions of this file under the
+-- terms and conditions of either the GPL or the CDDL or both.
+--
+
+
+
+\set ON_ERROR_STOP 1
+\set AUTOCOMMIT 0
+
+LOCK TABLE TestBoxes          IN ACCESS EXCLUSIVE MODE;
+LOCK TABLE TestBoxStatuses    IN ACCESS EXCLUSIVE MODE;
+LOCK TABLE TestCases          IN ACCESS EXCLUSIVE MODE;
+LOCK TABLE TestGroups         IN ACCESS EXCLUSIVE MODE;
+LOCK TABLE SchedGroups        IN ACCESS EXCLUSIVE MODE;
+
+--
+-- All the changes are rather simple and we'll just add the sComment column last.
+--
+\d TestCases;
+\d TestGroups;
+\d SchedGroups;
+
+ALTER TABLE TestCases   ADD COLUMN sComment TEXT DEFAULT NULL;
+ALTER TABLE TestGroups  ADD COLUMN sComment TEXT DEFAULT NULL;
+ALTER TABLE SchedGroups ADD COLUMN sComment TEXT DEFAULT NULL;
+
+\d TestCases;
+\d TestGroups;
+\d SchedGroups;
+
+\prompt "Update python files while everything is locked. Hurry!"  dummy
+
+COMMIT;
+
Index: /trunk/src/VBox/ValidationKit/testmanager/webui/wuiadminschedgroup.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/webui/wuiadminschedgroup.py	(revision 61471)
+++ /trunk/src/VBox/ValidationKit/testmanager/webui/wuiadminschedgroup.py	(revision 61472)
@@ -84,4 +84,5 @@
                                          fReadOnly = self._sMode == WuiFormContentBase.ksMode_Show);
 
+        oForm.addMultilineText  (SchedGroupData.ksParam_sComment,     oData.sComment,         'Comment');
         oForm.addSubmit()
 
@@ -100,10 +101,10 @@
         self._asColumnHeaders = [
             'ID',  'Name', 'Enabled', 'Scheduler Type',
-            'Build Source', 'Validation Kit Source', 'Test Groups', 'TestBoxes', 'Actions',
+            'Build Source', 'Validation Kit Source', 'Test Groups', 'TestBoxes', 'Note', 'Actions',
         ];
 
         self._asColumnAttribs = [
             'align="right"', 'align="center"', 'align="center"', 'align="center"',
-            'align="center"', 'align="center"', '', '', 'align="center"',
+            'align="center"', 'align="center"', '', '', 'align="center"', 'align="center"',
         ];
 
@@ -181,4 +182,5 @@
             aoMembers,
             aoTestBoxes,
+            self._formatCommentCell(oEntry.sComment),
             aoActions,
         ];
Index: /trunk/src/VBox/ValidationKit/testmanager/webui/wuiadmintestbox.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/webui/wuiadmintestbox.py	(revision 61471)
+++ /trunk/src/VBox/ValidationKit/testmanager/webui/wuiadmintestbox.py	(revision 61472)
@@ -235,12 +235,5 @@
                                    fBracketed = False);
         # Comment
-        oComment = None;
-        if oEntry.sComment is not None:
-            sComment = oEntry.sComment.strip();
-            if len(sComment) > 64:
-                oComment = WuiRawHtml('<span title="%s">%s...</span>'
-                                      % (webutils.escapeAttr(sComment), webutils.escapeElem(sComment[:60]),));
-            elif len(sComment) > 0:
-                oComment = WuiRawHtml(webutils.escapeElem(sComment));
+        oComment = self._formatCommentCell(oEntry.sComment);
 
         # Group link.
Index: /trunk/src/VBox/ValidationKit/testmanager/webui/wuiadmintestcase.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/webui/wuiadmintestcase.py	(revision 61471)
+++ /trunk/src/VBox/ValidationKit/testmanager/webui/wuiadmintestcase.py	(revision 61472)
@@ -64,11 +64,11 @@
         self._asColumnHeaders = \
         [
-            'Name', 'Active', 'Default Timeout', 'Base Command / Variations', 'Validation Kit Files',
-            'Test Case Prereqs', 'Global Resources', 'Actions'
+            'Name', 'Active', 'Timeout', 'Base Command / Variations', 'Validation Kit Files',
+            'Test Case Prereqs', 'Global Rsrces', 'Note', 'Actions'
         ];
         self._asColumnAttribs = \
         [
-            '', '', '', '', '',
-            'valign="top"', 'valign="top"', 'align="center"'
+            '', '', 'align="center"', '', '',
+            'valign="top"', 'valign="top"', 'align="center"', 'align="center"'
         ];
 
@@ -154,4 +154,7 @@
         aoRet.append(WuiRawHtml(sHtml));
 
+        # Comment (note).
+        aoRet.append(self._formatCommentCell(oEntry.sComment));
+
         # Show actions that can be taken.
         aoActions = [ WuiTmLink('Details', WuiAdmin.ksScriptName,
@@ -237,4 +240,6 @@
         oForm.addListOfResources(TestCaseDataEx.ksParam_aoDepGlobalResources, aoGlobalResrcDeps, 'Depends on resources')
 
+        oForm.addMultilineText(TestCaseDataEx.ksParam_sComment, oData.sComment, 'Comment');
+
         oForm.addSubmit();
 
Index: /trunk/src/VBox/ValidationKit/testmanager/webui/wuiadmintestgroup.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/webui/wuiadmintestgroup.py	(revision 61471)
+++ /trunk/src/VBox/ValidationKit/testmanager/webui/wuiadmintestgroup.py	(revision 61472)
@@ -74,4 +74,5 @@
                                         fReadOnly = self._sMode == WuiFormContentBase.ksMode_Show);
 
+        oForm.addMultilineText  (TestGroupData.ksParam_sComment,         self._oData.sComment,       'Comment');
         oForm.addSubmit();
         return True;
@@ -88,6 +89,6 @@
         WuiListContentBase.__init__(self, aoEntries, iPage, cItemsPerPage, tsEffective,
                                     sTitle = 'Test Groups', fnDPrint = fnDPrint, oDisp = oDisp);
-        self._asColumnHeaders = [ 'ID', 'Name', 'Description', 'Test Cases', 'Actions' ];
-        self._asColumnAttribs = [ 'align="right"', '', '', '', 'align="center"' ];
+        self._asColumnHeaders = [ 'ID', 'Name', 'Description', 'Test Cases', 'Note', 'Actions' ];
+        self._asColumnAttribs = [ 'align="right"', '', '', '', 'align="center"', 'align="center"' ];
 
 
@@ -178,4 +179,5 @@
                  oEntry.sDescription if oEntry.sDescription is not None else '',
                  oTestCases,
+                 self._formatCommentCell(oEntry.sComment, cMaxLines = max(3, len(oEntry.aoMembers) * 2)),
                  aoActions ];
 
Index: /trunk/src/VBox/ValidationKit/testmanager/webui/wuicontentbase.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/webui/wuicontentbase.py	(revision 61471)
+++ /trunk/src/VBox/ValidationKit/testmanager/webui/wuicontentbase.py	(revision 61472)
@@ -203,8 +203,14 @@
     Outputs the given text within a span of the given CSS class.
     """
-    def __init__(self, sSpanClass, sText):
-        WuiRawHtml.__init__(self,
-                            u'<span class="%s">%s</span>'
-                            % (webutils.escapeAttr(sSpanClass), webutils.escapeElem(sText),));
+    def __init__(self, sSpanClass, sText, sTitle = None):
+        if sTitle is None:
+            WuiRawHtml.__init__(self,
+                                u'<span class="%s">%s</span>'
+                                % ( webutils.escapeAttr(sSpanClass),  webutils.escapeElem(sText),));
+        else:
+            WuiRawHtml.__init__(self,
+                                u'<span class="%s" title="%s">%s</span>'
+                                % ( webutils.escapeAttr(sSpanClass), webutils.escapeAttr(sTitle), webutils.escapeElem(sText),));
+
 
 
@@ -692,4 +698,34 @@
         self._asColumnAttribs   = [];
 
+    def _formatCommentCell(self, sComment, cMaxLines = 3, cchMaxLine = 63):
+        """
+        Helper functions for formatting comment cell.
+        Returns None or WuiRawHtml instance.
+        """
+        # Nothing to do for empty comments.
+        if sComment is None:
+            return None;
+        sComment = sComment.strip();
+        if len(sComment) == 0:
+            return None;
+
+        # Restrict the text if necessary, making the whole text available thru mouse-over.
+        ## @todo this would be better done by java script or smth, so it could automatically adjust to the table size.
+        if len(sComment) > cchMaxLine or sComment.count('\n') >= cMaxLines:
+            sShortHtml = '';
+            for iLine, sLine in enumerate(sComment.split('\n')):
+                if iLine >= cMaxLines:
+                    break;
+                if iLine > 0:
+                    sShortHtml += '<br>\n';
+                if len(sLine) > cchMaxLine:
+                    sShortHtml += webutils.escapeElem(sLine[:(cchMaxLine - 3)]);
+                    sShortHtml += '...';
+                else:
+                    sShortHtml += webutils.escapeElem(sLine);
+            return WuiRawHtml('<span class="tmcomment" title="%s">%s</span>' % (webutils.escapeAttr(sComment), sShortHtml,));
+
+        return WuiRawHtml('<span class="tmcomment">%s</span>' % (webutils.escapeElem(sComment).replace('\n', '<br>'),));
+
     def _formatListEntry(self, iEntry):
         """
