Index: /trunk/src/VBox/ValidationKit/testmanager/core/base.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/core/base.py	(revision 65153)
+++ /trunk/src/VBox/ValidationKit/testmanager/core/base.py	(revision 65154)
@@ -1180,6 +1180,8 @@
     ## @name The kind of filtering.
     ## @{
-    ksKind_AnyOf = 'any-of';    ##< Any of the selected values are included (common).
-    ksKind_AllOf = 'all-of';    ##< All of the selected values must be matched (rare).
+    ## 'Element of' by default, 'not an element of' when fInverted is False.
+    ksKind_ElementOfOrNot = 'element-of-or-not';
+    ## The criterion is a special one and cannot be inverted.
+    ksKind_Special        = 'special';
     ## @}
 
@@ -1190,13 +1192,15 @@
     ## @}
 
-    def __init__(self, sName, sVarNm = None, sType = ksType_UInt, sState = ksState_NotSelected, sKind = ksKind_AnyOf,
+    def __init__(self, sName, sVarNm = None, sType = ksType_UInt, sState = ksState_NotSelected, sKind = ksKind_ElementOfOrNot,
                  sTable = None, sColumn = None, oSub = None):
-        assert len(sVarNm) in (2,3); # required by wuimain.py
+        assert len(sVarNm) == 2;    # required by wuimain.py for filtering.
         self.sName      = sName;
         self.sState     = sState;
-        self.sVarNm     = sVarNm if sVarNm is not None else sName;
         self.sType      = sType;
         self.sKind      = sKind;
-        self.aoSelected = [];       ##< Single value, any type.
+        self.sVarNm     = sVarNm;
+        self.aoSelected = [];       ##< User input from sVarNm. Single value, type according to sType.
+        self.sInvVarNm  = 'i' + sVarNm if sKind == self.ksKind_ElementOfOrNot else None;
+        self.fInverted  = False;    ##< User input from sInvVarNm. Inverts the operation (-> not an element of).
         self.aoPossible = [];       ##< type: list[FilterCriterionValueAndDescription]
         self.sTable     = sTable;
@@ -1251,7 +1255,10 @@
             assert False;
         if len(oCriterion.aoSelected) > 0:
-            oCriterion.sState     = FilterCriterion.ksState_Selected;
+            oCriterion.sState = FilterCriterion.ksState_Selected;
         else:
-            oCriterion.sState     = FilterCriterion.ksState_NotSelected;
+            oCriterion.sState = FilterCriterion.ksState_NotSelected;
+
+        if oCriterion.sKind == FilterCriterion.ksKind_ElementOfOrNot:
+            oCriterion.fInverted = oDisp.getBoolParam(oCriterion.sInvVarNm, fDefault = False);
 
         if oCriterion.oSub is not None:
Index: /trunk/src/VBox/ValidationKit/testmanager/core/testresults.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/core/testresults.py	(revision 65153)
+++ /trunk/src/VBox/ValidationKit/testmanager/core/testresults.py	(revision 65154)
@@ -720,5 +720,6 @@
         assert self.aCriteria[self.kiMemory] is oCrit;
 
-        oCrit = FilterCriterion('Misc', sVarNm = 'cf', sTable = 'TestBoxesWithStrings', sColumn = 'it_is_complicated');
+        oCrit = FilterCriterion('Misc', sVarNm = 'cf', sKind = FilterCriterion.ksKind_Special,
+                                sTable = 'TestBoxesWithStrings', sColumn = 'it_is_complicated');
         oCrit.aoPossible = [
             FilterCriterionValueAndDescription(self.kiMisc_NestedPaging,      "req nested paging"),
@@ -775,7 +776,11 @@
             else:
                 if iCrit == self.kiMemory:
-                    sQuery += '%s   AND (%s.%s / 1024) IN (' % (sExtraIndent, oCrit.sTable, oCrit.sColumn,);
+                    sQuery += '%s   AND (%s.%s / 1024)' % (sExtraIndent, oCrit.sTable, oCrit.sColumn,);
                 else:
-                    sQuery += '%s   AND %s.%s IN (' % (sExtraIndent, oCrit.sTable, oCrit.sColumn,);
+                    sQuery += '%s   AND %s.%s' % (sExtraIndent, oCrit.sTable, oCrit.sColumn,);
+                if not oCrit.fInverted:
+                    sQuery += ' IN (';
+                else:
+                    sQuery += ' NOT IN (';
                 if oCrit.sType == FilterCriterion.ksType_String:
                     sQuery += ', '.join('\'%s\'' % (sValue,) for sValue in oCrit.aoSelected) + ')\n';
Index: /trunk/src/VBox/ValidationKit/testmanager/htdocs/css/common.css
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/htdocs/css/common.css	(revision 65153)
+++ /trunk/src/VBox/ValidationKit/testmanager/htdocs/css/common.css	(revision 65154)
@@ -25,4 +25,5 @@
  */
 
+@charset "UTF-8";
 
 /*
@@ -332,4 +333,21 @@
 }
 
+.tm-side-filter-union-input {
+    float:          right;
+}
+
+/* The following is for the element of / not element of checkbox, supplying text and hiding the actual box. */
+input.tm-side-filter-union-input {
+    display:        none;
+}
+input.tm-side-filter-union-input + label {
+    vertical-align: middle;
+}
+input.tm-side-filter-union-input:checked + label::after {
+    content:        '∉'; /* U+2209: not an element of. */
+}
+input.tm-side-filter-union-input + label::after {
+    content:        '∈'; /* U+2208: element of. */
+}
 
 /* Webkit: Pretty scroll bars on the menu body as well as inside filter criteria. */
Index: /trunk/src/VBox/ValidationKit/testmanager/webui/wuimain.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/webui/wuimain.py	(revision 65153)
+++ /trunk/src/VBox/ValidationKit/testmanager/webui/wuimain.py	(revision 65154)
@@ -948,9 +948,15 @@
                     sChar  = '&#9654;';
 
-                sHtml += u'  <dt class="%s"><a href="javascript:void(0)" onclick="toggleCollapsibleDtDd(this);">%s'\
-                         u' %s</a></dt>\n' \
+                sHtml += u'  <dt class="%s"><a href="javascript:void(0)" onclick="toggleCollapsibleDtDd(this);">%s %s</a> ' \
+                       % (sClass, sChar, webutils.escapeElem(oCrit.sName),);
+                if oCrit.sInvVarNm is not None:
+                    sHtml += u'<input  id="sf-union-%s" class="tm-side-filter-union-input" ' \
+                             u'name="%s" value="1" type="checkbox"%s />' \
+                             u'<label for="sf-union-%s" class="tm-side-filter-union-input"/>' \
+                           % ( oCrit.sInvVarNm, oCrit.sInvVarNm, ' checked' if oCrit.fInverted else '', oCrit.sInvVarNm,);
+                sHtml += u'</dt>\n' \
                          u'  <dd class="%s">\n' \
                          u'   <ul>\n' \
-                         % (sClass, sChar, webutils.escapeElem(oCrit.sName), sClass);
+                         % (sClass, );
 
                 for oDesc in oCrit.aoPossible:
