VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testmanager/webui/wuihlpform.py@ 77922

Last change on this file since 77922 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 51.2 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: wuihlpform.py 76553 2019-01-01 01:45:53Z vboxsync $
3
4"""
5Test Manager Web-UI - Form Helpers.
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2012-2019 Oracle Corporation
11
12This file is part of VirtualBox Open Source Edition (OSE), as
13available from http://www.virtualbox.org. This file is free software;
14you can redistribute it and/or modify it under the terms of the GNU
15General Public License (GPL) as published by the Free Software
16Foundation, in version 2 as it comes in the "COPYING" file of the
17VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
20The contents of this file may alternatively be used under the terms
21of the Common Development and Distribution License Version 1.0
22(CDDL) only, as it comes in the "COPYING.CDDL" file of the
23VirtualBox OSE distribution, in which case the provisions of the
24CDDL are applicable instead of those of the GPL.
25
26You may elect to license modified versions of this file under the
27terms and conditions of either the GPL or the CDDL or both.
28"""
29__version__ = "$Revision: 76553 $"
30
31# Standard python imports.
32import copy;
33import sys;
34
35# Validation Kit imports.
36from common import utils;
37from common.webutils import escapeAttr, escapeElem;
38from testmanager import config;
39from testmanager.core.schedgroup import SchedGroupMemberData, SchedGroupDataEx;
40from testmanager.core.testcaseargs import TestCaseArgsData;
41from testmanager.core.testgroup import TestGroupMemberData, TestGroupDataEx;
42
43# Python 3 hacks:
44if sys.version_info[0] >= 3:
45 unicode = str; # pylint: disable=redefined-builtin,invalid-name
46
47
48class WuiHlpForm(object):
49 """
50 Helper for constructing a form.
51 """
52
53 ksItemsList = 'ksItemsList'
54
55 ksOnSubmit_AddReturnToFieldWithCurrentUrl = '+AddReturnToFieldWithCurrentUrl+';
56
57 def __init__(self, sId, sAction, dErrors = None, fReadOnly = False, sOnSubmit = None):
58 self._fFinalized = False;
59 self._fReadOnly = fReadOnly;
60 self._dErrors = dErrors if dErrors is not None else dict();
61
62 if sOnSubmit == self.ksOnSubmit_AddReturnToFieldWithCurrentUrl:
63 sOnSubmit = u'return addRedirectToInputFieldWithCurrentUrl(this)';
64 if sOnSubmit is None: sOnSubmit = u'';
65 else: sOnSubmit = u' onsubmit=\"%s\"' % (escapeAttr(sOnSubmit),);
66
67 self._sBody = u'\n' \
68 u'<div id="%s" class="tmform">\n' \
69 u' <form action="%s" method="post"%s>\n' \
70 u' <ul>\n' \
71 % (sId, sAction, sOnSubmit);
72
73 def _add(self, sText):
74 """Internal worker for appending text to the body."""
75 assert not self._fFinalized;
76 if not self._fFinalized:
77 self._sBody += unicode(sText, errors='ignore') if isinstance(sText, str) else sText;
78 return True;
79 return False;
80
81 def _escapeErrorText(self, sText):
82 """Escapes error text, preserving some predefined HTML tags."""
83 if sText.find('<br>') >= 0:
84 asParts = sText.split('<br>');
85 for i, _ in enumerate(asParts):
86 asParts[i] = escapeElem(asParts[i].strip());
87 sText = '<br>\n'.join(asParts);
88 else:
89 sText = escapeElem(sText);
90 return sText;
91
92 def _addLabel(self, sName, sLabel, sDivSubClass = 'normal'):
93 """Internal worker for adding a label."""
94 if sName in self._dErrors:
95 sError = self._dErrors[sName];
96 if utils.isString(sError): # List error trick (it's an associative array).
97 return self._add(u' <li>\n'
98 u' <div class="tmform-field"><div class="tmform-field-%s">\n'
99 u' <label for="%s" class="tmform-error-label">%s\n'
100 u' <span class="tmform-error-desc">%s</span>\n'
101 u' </label>\n'
102 % (escapeAttr(sDivSubClass), escapeAttr(sName), escapeElem(sLabel),
103 self._escapeErrorText(sError), ) );
104 return self._add(u' <li>\n'
105 u' <div class="tmform-field"><div class="tmform-field-%s">\n'
106 u' <label for="%s">%s</label>\n'
107 % (escapeAttr(sDivSubClass), escapeAttr(sName), escapeElem(sLabel)) );
108
109
110 def finalize(self):
111 """
112 Finalizes the form and returns the body.
113 """
114 if not self._fFinalized:
115 self._add(u' </ul>\n'
116 u' </form>\n'
117 u'</div>\n'
118 u'<div class="clear"></div>\n' );
119 return self._sBody;
120
121 def addTextHidden(self, sName, sValue, sExtraAttribs = ''):
122 """Adds a hidden text input."""
123 return self._add(u' <div class="tmform-field-hidden">\n'
124 u' <input name="%s" id="%s" type="text" hidden%s value="%s" class="tmform-hidden">\n'
125 u' </div>\n'
126 u' </li>\n'
127 % ( escapeAttr(sName), escapeAttr(sName), sExtraAttribs, escapeElem(str(sValue)) ));
128 #
129 # Non-input stuff.
130 #
131 def addNonText(self, sValue, sLabel, sName = 'non-text', sPostHtml = ''):
132 """Adds a read-only text input."""
133 self._addLabel(sName, sLabel, 'string');
134 if sValue is None: sValue = '';
135 return self._add(u' <p>%s%s</p>\n'
136 u' </div></div>\n'
137 u' </li>\n'
138 % (escapeElem(unicode(sValue)), sPostHtml ));
139
140 def addRawHtml(self, sRawHtml, sLabel, sName = 'raw-html'):
141 """Adds a read-only text input."""
142 self._addLabel(sName, sLabel, 'string');
143 self._add(sRawHtml);
144 return self._add(u' </div></div>\n'
145 u' </li>\n');
146
147
148 #
149 # Text input fields.
150 #
151 def addText(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = '', sPostHtml = ''):
152 """Adds a text input."""
153 if self._fReadOnly:
154 return self.addTextRO(sName, sValue, sLabel, sSubClass, sExtraAttribs);
155 if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp', 'wide'): raise Exception(sSubClass);
156 self._addLabel(sName, sLabel, sSubClass);
157 if sValue is None: sValue = '';
158 return self._add(u' <input name="%s" id="%s" type="text"%s value="%s">%s\n'
159 u' </div></div>\n'
160 u' </li>\n'
161 % ( escapeAttr(sName), escapeAttr(sName), sExtraAttribs, escapeElem(sValue), sPostHtml ));
162
163 def addTextRO(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = '', sPostHtml = ''):
164 """Adds a read-only text input."""
165 if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp', 'wide'): raise Exception(sSubClass);
166 self._addLabel(sName, sLabel, sSubClass);
167 if sValue is None: sValue = '';
168 return self._add(u' <input name="%s" id="%s" type="text" readonly%s value="%s" class="tmform-input-readonly">'
169 u'%s\n'
170 u' </div></div>\n'
171 u' </li>\n'
172 % ( escapeAttr(sName), escapeAttr(sName), sExtraAttribs, escapeElem(unicode(sValue)), sPostHtml ));
173
174 def addWideText(self, sName, sValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
175 """Adds a wide text input."""
176 return self.addText(sName, sValue, sLabel, 'wide', sExtraAttribs, sPostHtml = sPostHtml);
177
178 def addWideTextRO(self, sName, sValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
179 """Adds a wide read-only text input."""
180 return self.addTextRO(sName, sValue, sLabel, 'wide', sExtraAttribs, sPostHtml = sPostHtml);
181
182 def _adjustMultilineTextAttribs(self, sExtraAttribs, sValue):
183 """ Internal helper for setting good default sizes for textarea based on content."""
184 if sExtraAttribs.find('cols') < 0 and sExtraAttribs.find('width') < 0:
185 sExtraAttribs = 'cols="96%" ' + sExtraAttribs;
186
187 if sExtraAttribs.find('rows') < 0 and sExtraAttribs.find('width') < 0:
188 if sValue is None: sValue = '';
189 else: sValue = sValue.strip();
190
191 cRows = sValue.count('\n') + (not sValue.endswith('\n'));
192 if cRows * 80 < len(sValue):
193 cRows += 2;
194 cRows = max(min(cRows, 16), 2);
195 sExtraAttribs = ('rows="%s" ' % (cRows,)) + sExtraAttribs;
196
197 return sExtraAttribs;
198
199 def addMultilineText(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = ''):
200 """Adds a multiline text input."""
201 if self._fReadOnly:
202 return self.addMultilineTextRO(sName, sValue, sLabel, sSubClass, sExtraAttribs);
203 if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp'): raise Exception(sSubClass)
204 self._addLabel(sName, sLabel, sSubClass)
205 if sValue is None: sValue = '';
206 sNewValue = unicode(sValue) if not isinstance(sValue, list) else '\n'.join(sValue)
207 return self._add(u' <textarea name="%s" id="%s" %s>%s</textarea>\n'
208 u' </div></div>\n'
209 u' </li>\n'
210 % ( escapeAttr(sName), escapeAttr(sName), self._adjustMultilineTextAttribs(sExtraAttribs, sNewValue),
211 escapeElem(sNewValue)))
212
213 def addMultilineTextRO(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = ''):
214 """Adds a multiline read-only text input."""
215 if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp'): raise Exception(sSubClass)
216 self._addLabel(sName, sLabel, sSubClass)
217 if sValue is None: sValue = '';
218 sNewValue = unicode(sValue) if not isinstance(sValue, list) else '\n'.join(sValue)
219 return self._add(u' <textarea name="%s" id="%s" readonly %s>%s</textarea>\n'
220 u' </div></div>\n'
221 u' </li>\n'
222 % ( escapeAttr(sName), escapeAttr(sName), self._adjustMultilineTextAttribs(sExtraAttribs, sNewValue),
223 escapeElem(sNewValue)))
224
225 def addInt(self, sName, iValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
226 """Adds an integer input."""
227 return self.addText(sName, unicode(iValue), sLabel, 'int', sExtraAttribs, sPostHtml = sPostHtml);
228
229 def addIntRO(self, sName, iValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
230 """Adds an integer input."""
231 return self.addTextRO(sName, unicode(iValue), sLabel, 'int', sExtraAttribs, sPostHtml = sPostHtml);
232
233 def addLong(self, sName, lValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
234 """Adds a long input."""
235 return self.addText(sName, unicode(lValue), sLabel, 'long', sExtraAttribs, sPostHtml = sPostHtml);
236
237 def addLongRO(self, sName, lValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
238 """Adds a long input."""
239 return self.addTextRO(sName, unicode(lValue), sLabel, 'long', sExtraAttribs, sPostHtml = sPostHtml);
240
241 def addUuid(self, sName, uuidValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
242 """Adds an UUID input."""
243 return self.addText(sName, unicode(uuidValue), sLabel, 'uuid', sExtraAttribs, sPostHtml = sPostHtml);
244
245 def addUuidRO(self, sName, uuidValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
246 """Adds a read-only UUID input."""
247 return self.addTextRO(sName, unicode(uuidValue), sLabel, 'uuid', sExtraAttribs, sPostHtml = sPostHtml);
248
249 def addTimestampRO(self, sName, sTimestamp, sLabel, sExtraAttribs = '', sPostHtml = ''):
250 """Adds a read-only database string timstamp input."""
251 return self.addTextRO(sName, sTimestamp, sLabel, 'timestamp', sExtraAttribs, sPostHtml = sPostHtml);
252
253
254 #
255 # Text areas.
256 #
257
258
259 #
260 # Combo boxes.
261 #
262 def addComboBox(self, sName, sSelected, sLabel, aoOptions, sExtraAttribs = '', sPostHtml = ''):
263 """Adds a combo box."""
264 if self._fReadOnly:
265 return self.addComboBoxRO(sName, sSelected, sLabel, aoOptions, sExtraAttribs, sPostHtml);
266 self._addLabel(sName, sLabel, 'combobox');
267 self._add(' <select name="%s" id="%s" class="tmform-combobox"%s>\n'
268 % (escapeAttr(sName), escapeAttr(sName), sExtraAttribs));
269 sSelected = unicode(sSelected);
270 for iValue, sText, _ in aoOptions:
271 sValue = unicode(iValue);
272 self._add(' <option value="%s"%s>%s</option>\n'
273 % (escapeAttr(sValue), ' selected' if sValue == sSelected else '',
274 escapeElem(sText)));
275 return self._add(u' </select>' + sPostHtml + '\n'
276 u' </div></div>\n'
277 u' </li>\n');
278
279 def addComboBoxRO(self, sName, sSelected, sLabel, aoOptions, sExtraAttribs = '', sPostHtml = ''):
280 """Adds a read-only combo box."""
281 self.addTextHidden(sName, sSelected);
282 self._addLabel(sName, sLabel, 'combobox-readonly');
283 self._add(u' <select name="%s" id="%s" disabled class="tmform-combobox"%s>\n'
284 % (escapeAttr(sName), escapeAttr(sName), sExtraAttribs));
285 sSelected = unicode(sSelected);
286 for iValue, sText, _ in aoOptions:
287 sValue = unicode(iValue);
288 self._add(' <option value="%s"%s>%s</option>\n'
289 % (escapeAttr(sValue), ' selected' if sValue == sSelected else '',
290 escapeElem(sText)));
291 return self._add(u' </select>' + sPostHtml + '\n'
292 u' </div></div>\n'
293 u' </li>\n');
294
295 #
296 # Check boxes.
297 #
298 @staticmethod
299 def _reinterpretBool(fValue):
300 """Reinterprets a value as a boolean type."""
301 if fValue is not type(True):
302 if fValue is None:
303 fValue = False;
304 elif str(fValue) in ('True', 'true', '1'):
305 fValue = True;
306 else:
307 fValue = False;
308 return fValue;
309
310 def addCheckBox(self, sName, fChecked, sLabel, sExtraAttribs = ''):
311 """Adds an check box."""
312 if self._fReadOnly:
313 return self.addCheckBoxRO(sName, fChecked, sLabel, sExtraAttribs);
314 self._addLabel(sName, sLabel, 'checkbox');
315 fChecked = self._reinterpretBool(fChecked);
316 return self._add(u' <input name="%s" id="%s" type="checkbox"%s%s value="1" class="tmform-checkbox">\n'
317 u' </div></div>\n'
318 u' </li>\n'
319 % (escapeAttr(sName), escapeAttr(sName), ' checked' if fChecked else '', sExtraAttribs));
320
321 def addCheckBoxRO(self, sName, fChecked, sLabel, sExtraAttribs = ''):
322 """Adds an readonly check box."""
323 self._addLabel(sName, sLabel, 'checkbox');
324 fChecked = self._reinterpretBool(fChecked);
325 # Hack Alert! The onclick and onkeydown are for preventing editing and fake readonly/disabled.
326 return self._add(u' <input name="%s" id="%s" type="checkbox"%s readonly%s value="1" class="readonly"\n'
327 u' onclick="return false" onkeydown="return false">\n'
328 u' </div></div>\n'
329 u' </li>\n'
330 % (escapeAttr(sName), escapeAttr(sName), ' checked' if fChecked else '', sExtraAttribs));
331
332 #
333 # List of items to check
334 #
335 def _addList(self, sName, aoRows, sLabel, fUseTable = False, sId = 'dummy', sExtraAttribs = ''):
336 """
337 Adds a list of items to check.
338
339 @param sName Name of HTML form element
340 @param aoRows List of [sValue, fChecked, sName] sub-arrays.
341 @param sLabel Label of HTML form element
342 """
343 fReadOnly = self._fReadOnly; ## @todo add this as a parameter.
344 if fReadOnly:
345 sExtraAttribs += ' readonly onclick="return false" onkeydown="return false"';
346
347 self._addLabel(sName, sLabel, 'list');
348 if not aoRows:
349 return self._add('No items</div></div></li>')
350 sNameEscaped = escapeAttr(sName);
351
352 self._add(' <div class="tmform-checkboxes-container" id="%s">\n' % (escapeAttr(sId),));
353 if fUseTable:
354 self._add(' <table>\n');
355 for asRow in aoRows:
356 assert len(asRow) == 3; # Don't allow sloppy input data!
357 fChecked = self._reinterpretBool(asRow[1])
358 self._add(u' <tr>\n'
359 u' <td><input type="checkbox" name="%s" value="%s"%s%s></td>\n'
360 u' <td>%s</td>\n'
361 u' </tr>\n'
362 % ( sNameEscaped, escapeAttr(unicode(asRow[0])), ' checked' if fChecked else '', sExtraAttribs,
363 escapeElem(unicode(asRow[2])), ));
364 self._add(u' </table>\n');
365 else:
366 for asRow in aoRows:
367 assert len(asRow) == 3; # Don't allow sloppy input data!
368 fChecked = self._reinterpretBool(asRow[1])
369 self._add(u' <div class="tmform-checkbox-holder">'
370 u'<input type="checkbox" name="%s" value="%s"%s%s> %s</input></div>\n'
371 % ( sNameEscaped, escapeAttr(unicode(asRow[0])), ' checked' if fChecked else '', sExtraAttribs,
372 escapeElem(unicode(asRow[2])),));
373 return self._add(u' </div></div></div>\n'
374 u' </li>\n');
375
376
377 def addListOfOsArches(self, sName, aoOsArches, sLabel, sExtraAttribs = ''):
378 """
379 List of checkboxes for OS/ARCH selection.
380 asOsArches is a list of [sValue, fChecked, sName] sub-arrays.
381 """
382 return self._addList(sName, aoOsArches, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-os-arches',
383 sExtraAttribs = sExtraAttribs);
384
385 def addListOfTypes(self, sName, aoTypes, sLabel, sExtraAttribs = ''):
386 """
387 List of checkboxes for build type selection.
388 aoTypes is a list of [sValue, fChecked, sName] sub-arrays.
389 """
390 return self._addList(sName, aoTypes, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-build-types',
391 sExtraAttribs = sExtraAttribs);
392
393 def addListOfTestCases(self, sName, aoTestCases, sLabel, sExtraAttribs = ''):
394 """
395 List of checkboxes for test box (dependency) selection.
396 aoTestCases is a list of [sValue, fChecked, sName] sub-arrays.
397 """
398 return self._addList(sName, aoTestCases, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-testcases',
399 sExtraAttribs = sExtraAttribs);
400
401 def addListOfResources(self, sName, aoTestCases, sLabel, sExtraAttribs = ''):
402 """
403 List of checkboxes for resource selection.
404 aoTestCases is a list of [sValue, fChecked, sName] sub-arrays.
405 """
406 return self._addList(sName, aoTestCases, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-resources',
407 sExtraAttribs = sExtraAttribs);
408
409 def addListOfTestGroups(self, sName, aoTestGroups, sLabel, sExtraAttribs = ''):
410 """
411 List of checkboxes for test group selection.
412 aoTestGroups is a list of [sValue, fChecked, sName] sub-arrays.
413 """
414 return self._addList(sName, aoTestGroups, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-testgroups',
415 sExtraAttribs = sExtraAttribs);
416
417 def addListOfTestCaseArgs(self, sName, aoVariations, sLabel): # pylint: disable=R0915
418 """
419 Adds a list of test case argument variations to the form.
420
421 @param sName Name of HTML form element
422 @param aoVariations List of TestCaseArgsData instances.
423 @param sLabel Label of HTML form element
424 """
425 self._addLabel(sName, sLabel);
426
427 sTableId = u'TestArgsExtendingListRoot';
428 fReadOnly = self._fReadOnly; ## @todo argument?
429 sReadOnlyAttr = u' readonly class="tmform-input-readonly"' if fReadOnly else '';
430
431 sHtml = u'<li>\n'
432
433 #
434 # Define javascript function for extending the list of test case
435 # variations. Doing it here so we can use the python constants. This
436 # also permits multiple argument lists on one page should that ever be
437 # required...
438 #
439 if not fReadOnly:
440 sHtml += u'<script type="text/javascript">\n'
441 sHtml += u'\n';
442 sHtml += u'g_%s_aItems = { %s };\n' % (sName, ', '.join(('%s: 1' % (i,)) for i in range(len(aoVariations))),);
443 sHtml += u'g_%s_cItems = %s;\n' % (sName, len(aoVariations),);
444 sHtml += u'g_%s_iIdMod = %s;\n' % (sName, len(aoVariations) + 32);
445 sHtml += u'\n';
446 sHtml += u'function %s_removeEntry(sId)\n' % (sName,);
447 sHtml += u'{\n';
448 sHtml += u' if (g_%s_cItems > 1)\n' % (sName,);
449 sHtml += u' {\n';
450 sHtml += u' g_%s_cItems--;\n' % (sName,);
451 sHtml += u' delete g_%s_aItems[sId];\n' % (sName,);
452 sHtml += u' setElementValueToKeyList(\'%s\', g_%s_aItems);\n' % (sName, sName);
453 sHtml += u'\n';
454 for iInput in range(8):
455 sHtml += u' removeHtmlNode(\'%s[\' + sId + \'][%s]\');\n' % (sName, iInput,);
456 sHtml += u' }\n';
457 sHtml += u'}\n';
458 sHtml += u'\n';
459 sHtml += u'function %s_extendListEx(sSubName, cGangMembers, cSecTimeout, sArgs, sTestBoxReqExpr, sBuildReqExpr)\n' \
460 % (sName,);
461 sHtml += u'{\n';
462 sHtml += u' var oElement = document.getElementById(\'%s\');\n' % (sTableId,);
463 sHtml += u' var oTBody = document.createElement(\'tbody\');\n';
464 sHtml += u' var sHtml = \'\';\n';
465 sHtml += u' var sId;\n';
466 sHtml += u'\n';
467 sHtml += u' g_%s_iIdMod += 1;\n' % (sName,);
468 sHtml += u' sId = g_%s_iIdMod.toString();\n' % (sName,);
469
470 oVarDefaults = TestCaseArgsData();
471 oVarDefaults.convertToParamNull();
472 sHtml += u'\n';
473 sHtml += u' sHtml += \'<tr class="tmform-testcasevars-first-row">\';\n';
474 sHtml += u' sHtml += \' <td>Sub-Name:</td>\';\n';
475 sHtml += u' sHtml += \' <td class="tmform-field-subname">' \
476 '<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][0]" value="\' + sSubName + \'"></td>\';\n' \
477 % (sName, TestCaseArgsData.ksParam_sSubName, sName,);
478 sHtml += u' sHtml += \' <td>Gang Members:</td>\';\n';
479 sHtml += u' sHtml += \' <td class="tmform-field-tiny-int">' \
480 '<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][0]" value="\' + cGangMembers + \'"></td>\';\n' \
481 % (sName, TestCaseArgsData.ksParam_cGangMembers, sName,);
482 sHtml += u' sHtml += \' <td>Timeout:</td>\';\n';
483 sHtml += u' sHtml += \' <td class="tmform-field-int">' \
484 u'<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][1]" value="\'+ cSecTimeout + \'"></td>\';\n' \
485 % (sName, TestCaseArgsData.ksParam_cSecTimeout, sName,);
486 sHtml += u' sHtml += \' <td><a href="#" onclick="%s_removeEntry(\\\'\' + sId + \'\\\');"> Remove</a></td>\';\n' \
487 % (sName, );
488 sHtml += u' sHtml += \' <td></td>\';\n';
489 sHtml += u' sHtml += \'</tr>\';\n'
490 sHtml += u'\n';
491 sHtml += u' sHtml += \'<tr class="tmform-testcasevars-inner-row">\';\n';
492 sHtml += u' sHtml += \' <td>Arguments:</td>\';\n';
493 sHtml += u' sHtml += \' <td class="tmform-field-wide100" colspan="6">' \
494 u'<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][2]" value="\' + sArgs + \'"></td>\';\n' \
495 % (sName, TestCaseArgsData.ksParam_sArgs, sName,);
496 sHtml += u' sHtml += \' <td></td>\';\n';
497 sHtml += u' sHtml += \'</tr>\';\n'
498 sHtml += u'\n';
499 sHtml += u' sHtml += \'<tr class="tmform-testcasevars-inner-row">\';\n';
500 sHtml += u' sHtml += \' <td>TestBox Reqs:</td>\';\n';
501 sHtml += u' sHtml += \' <td class="tmform-field-wide100" colspan="6">' \
502 u'<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][2]" value="\' + sTestBoxReqExpr' \
503 u' + \'"></td>\';\n' \
504 % (sName, TestCaseArgsData.ksParam_sTestBoxReqExpr, sName,);
505 sHtml += u' sHtml += \' <td></td>\';\n';
506 sHtml += u' sHtml += \'</tr>\';\n'
507 sHtml += u'\n';
508 sHtml += u' sHtml += \'<tr class="tmform-testcasevars-final-row">\';\n';
509 sHtml += u' sHtml += \' <td>Build Reqs:</td>\';\n';
510 sHtml += u' sHtml += \' <td class="tmform-field-wide100" colspan="6">' \
511 u'<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][2]" value="\' + sBuildReqExpr + \'"></td>\';\n' \
512 % (sName, TestCaseArgsData.ksParam_sBuildReqExpr, sName,);
513 sHtml += u' sHtml += \' <td></td>\';\n';
514 sHtml += u' sHtml += \'</tr>\';\n'
515 sHtml += u'\n';
516 sHtml += u' oTBody.id = \'%s[\' + sId + \'][6]\';\n' % (sName,);
517 sHtml += u' oTBody.innerHTML = sHtml;\n';
518 sHtml += u'\n';
519 sHtml += u' oElement.appendChild(oTBody);\n';
520 sHtml += u'\n';
521 sHtml += u' g_%s_aItems[sId] = 1;\n' % (sName,);
522 sHtml += u' g_%s_cItems++;\n' % (sName,);
523 sHtml += u' setElementValueToKeyList(\'%s\', g_%s_aItems);\n' % (sName, sName);
524 sHtml += u'}\n';
525 sHtml += u'function %s_extendList()\n' % (sName,);
526 sHtml += u'{\n';
527 sHtml += u' %s_extendListEx("%s", "%s", "%s", "%s", "%s", "%s");\n' % (sName,
528 escapeAttr(unicode(oVarDefaults.sSubName)), escapeAttr(unicode(oVarDefaults.cGangMembers)),
529 escapeAttr(unicode(oVarDefaults.cSecTimeout)), escapeAttr(oVarDefaults.sArgs),
530 escapeAttr(oVarDefaults.sTestBoxReqExpr), escapeAttr(oVarDefaults.sBuildReqExpr), );
531 sHtml += u'}\n';
532 if config.g_kfVBoxSpecific:
533 sSecTimeoutDef = escapeAttr(unicode(oVarDefaults.cSecTimeout));
534 sHtml += u'function vbox_%s_add_uni()\n' % (sName,);
535 sHtml += u'{\n';
536 sHtml += u' %s_extendListEx("1-raw", "1", "%s", "--cpu-counts 1 --virt-modes raw", ' \
537 u' "", "");\n' % (sName, sSecTimeoutDef);
538 sHtml += u' %s_extendListEx("1-hw", "1", "%s", "--cpu-counts 1 --virt-modes hwvirt", ' \
539 u' "fCpuHwVirt is True", "");\n' % (sName, sSecTimeoutDef);
540 sHtml += u' %s_extendListEx("1-np", "1", "%s", "--cpu-counts 1 --virt-modes hwvirt-np", ' \
541 u' "fCpuNestedPaging is True", "");\n' % (sName, sSecTimeoutDef);
542 sHtml += u'}\n';
543 sHtml += u'function vbox_%s_add_uni_amd64()\n' % (sName,);
544 sHtml += u'{\n';
545 sHtml += u' %s_extendListEx("1-hw", "1", "%s", "--cpu-counts 1 --virt-modes hwvirt", ' \
546 u' "fCpuHwVirt is True", "");\n' % (sName, sSecTimeoutDef);
547 sHtml += u' %s_extendListEx("1-np", "%s", "--cpu-counts 1 --virt-modes hwvirt-np", ' \
548 u' "fCpuNestedPaging is True", "");\n' % (sName, sSecTimeoutDef);
549 sHtml += u'}\n';
550 sHtml += u'function vbox_%s_add_smp()\n' % (sName,);
551 sHtml += u'{\n';
552 sHtml += u' %s_extendListEx("2-hw", "1", "%s", "--cpu-counts 2 --virt-modes hwvirt",' \
553 u' "fCpuHwVirt is True and cCpus >= 2", "");\n' % (sName, sSecTimeoutDef);
554 sHtml += u' %s_extendListEx("2-np", "1", "%s", "--cpu-counts 2 --virt-modes hwvirt-np",' \
555 u' "fCpuNestedPaging is True and cCpus >= 2", "");\n' % (sName, sSecTimeoutDef);
556 sHtml += u' %s_extendListEx("3-hw", "1", "%s", "--cpu-counts 3 --virt-modes hwvirt",' \
557 u' "fCpuHwVirt is True and cCpus >= 3", "");\n' % (sName, sSecTimeoutDef);
558 sHtml += u' %s_extendListEx("4-np", "1", "%s", "--cpu-counts 4 --virt-modes hwvirt-np ",' \
559 u' "fCpuNestedPaging is True and cCpus >= 4", "");\n' % (sName, sSecTimeoutDef);
560 #sHtml += u' %s_extendListEx("6-hw", "1", "%s", "--cpu-counts 6 --virt-modes hwvirt",' \
561 # u' "fCpuHwVirt is True and cCpus >= 6", "");\n' % (sName, sSecTimeoutDef);
562 #sHtml += u' %s_extendListEx("8-np", "1", "%s", "--cpu-counts 8 --virt-modes hwvirt-np",' \
563 # u' "fCpuNestedPaging is True and cCpus >= 8", "");\n' % (sName, sSecTimeoutDef);
564 sHtml += u'}\n';
565 sHtml += u'</script>\n';
566
567
568 #
569 # List current entries.
570 #
571 sHtml += u'<input type="hidden" name="%s" id="%s" value="%s">\n' \
572 % (sName, sName, ','.join(unicode(i) for i in range(len(aoVariations))), );
573 sHtml += u' <table id="%s" class="tmform-testcasevars">\n' % (sTableId,)
574 if not fReadOnly:
575 sHtml += u' <caption>\n' \
576 u' <a href="#" onClick="%s_extendList()">Add</a>\n' % (sName,);
577 if config.g_kfVBoxSpecific:
578 sHtml += u' [<a href="#" onClick="vbox_%s_add_uni()">Single CPU Variations</a>\n' % (sName,);
579 sHtml += u' <a href="#" onClick="vbox_%s_add_uni_amd64()">amd64</a>]\n' % (sName,);
580 sHtml += u' [<a href="#" onClick="vbox_%s_add_smp()">SMP Variations</a>]\n' % (sName,);
581 sHtml += u' </caption>\n';
582
583 dSubErrors = {};
584 if sName in self._dErrors and isinstance(self._dErrors[sName], dict):
585 dSubErrors = self._dErrors[sName];
586
587 for iVar, _ in enumerate(aoVariations):
588 oVar = copy.copy(aoVariations[iVar]);
589 oVar.convertToParamNull();
590
591 sHtml += u'<tbody id="%s[%s][6]">\n' % (sName, iVar,)
592 sHtml += u' <tr class="tmform-testcasevars-first-row">\n' \
593 u' <td>Sub-name:</td>' \
594 u' <td class="tmform-field-subname"><input name="%s[%s][%s]" id="%s[%s][1]" value="%s"%s></td>\n' \
595 u' <td>Gang Members:</td>' \
596 u' <td class="tmform-field-tiny-int"><input name="%s[%s][%s]" id="%s[%s][1]" value="%s"%s></td>\n' \
597 u' <td>Timeout:</td>' \
598 u' <td class="tmform-field-int"><input name="%s[%s][%s]" id="%s[%s][2]" value="%s"%s></td>\n' \
599 % ( sName, iVar, TestCaseArgsData.ksParam_sSubName, sName, iVar, oVar.sSubName, sReadOnlyAttr,
600 sName, iVar, TestCaseArgsData.ksParam_cGangMembers, sName, iVar, oVar.cGangMembers, sReadOnlyAttr,
601 sName, iVar, TestCaseArgsData.ksParam_cSecTimeout, sName, iVar,
602 utils.formatIntervalSeconds2(oVar.cSecTimeout), sReadOnlyAttr, );
603 if not fReadOnly:
604 sHtml += u' <td><a href="#" onclick="%s_removeEntry(\'%s\');">Remove</a></td>\n' \
605 % (sName, iVar);
606 else:
607 sHtml += u' <td></td>\n';
608 sHtml += u' <td class="tmform-testcasevars-stupid-border-column"></td>\n' \
609 u' </tr>\n';
610
611 sHtml += u' <tr class="tmform-testcasevars-inner-row">\n' \
612 u' <td>Arguments:</td>' \
613 u' <td class="tmform-field-wide100" colspan="6">' \
614 u'<input name="%s[%s][%s]" id="%s[%s][3]" value="%s"%s></td>\n' \
615 u' <td></td>\n' \
616 u' </tr>\n' \
617 % ( sName, iVar, TestCaseArgsData.ksParam_sArgs, sName, iVar, escapeAttr(oVar.sArgs), sReadOnlyAttr)
618
619 sHtml += u' <tr class="tmform-testcasevars-inner-row">\n' \
620 u' <td>TestBox Reqs:</td>' \
621 u' <td class="tmform-field-wide100" colspan="6">' \
622 u'<input name="%s[%s][%s]" id="%s[%s][4]" value="%s"%s></td>\n' \
623 u' <td></td>\n' \
624 u' </tr>\n' \
625 % ( sName, iVar, TestCaseArgsData.ksParam_sTestBoxReqExpr, sName, iVar,
626 escapeAttr(oVar.sTestBoxReqExpr), sReadOnlyAttr)
627
628 sHtml += u' <tr class="tmform-testcasevars-final-row">\n' \
629 u' <td>Build Reqs:</td>' \
630 u' <td class="tmform-field-wide100" colspan="6">' \
631 u'<input name="%s[%s][%s]" id="%s[%s][5]" value="%s"%s></td>\n' \
632 u' <td></td>\n' \
633 u' </tr>\n' \
634 % ( sName, iVar, TestCaseArgsData.ksParam_sBuildReqExpr, sName, iVar,
635 escapeAttr(oVar.sBuildReqExpr), sReadOnlyAttr)
636
637
638 if iVar in dSubErrors:
639 sHtml += u' <tr><td colspan="4"><p align="left" class="tmform-error-desc">%s</p></td></tr>\n' \
640 % (self._escapeErrorText(dSubErrors[iVar]),);
641
642 sHtml += u'</tbody>\n';
643 sHtml += u' </table>\n'
644 sHtml += u'</li>\n'
645
646 return self._add(sHtml)
647
648 def addListOfTestGroupMembers(self, sName, aoTestGroupMembers, aoAllTestCases, sLabel, # pylint: disable=R0914
649 fReadOnly = True):
650 """
651 For WuiTestGroup.
652 """
653 assert len(aoTestGroupMembers) <= len(aoAllTestCases);
654 self._addLabel(sName, sLabel);
655 if not aoAllTestCases:
656 return self._add('<li>No testcases available.</li>\n')
657
658 self._add(u'<input name="%s" type="hidden" value="%s">\n'
659 % ( TestGroupDataEx.ksParam_aidTestCases,
660 ','.join([unicode(oTestCase.idTestCase) for oTestCase in aoAllTestCases]), ));
661
662 self._add(u'<table class="tmformtbl">\n'
663 u' <thead>\n'
664 u' <tr>\n'
665 u' <th rowspan="2"></th>\n'
666 u' <th rowspan="2">Test Case</th>\n'
667 u' <th rowspan="2">All Vars</th>\n'
668 u' <th rowspan="2">Priority [0..31]</th>\n'
669 u' <th colspan="4" align="center">Variations</th>\n'
670 u' </tr>\n'
671 u' <tr>\n'
672 u' <th>Included</th>\n'
673 u' <th>Gang size</th>\n'
674 u' <th>Timeout</th>\n'
675 u' <th>Arguments</th>\n'
676 u' </tr>\n'
677 u' </thead>\n'
678 u' <tbody>\n'
679 );
680
681 if self._fReadOnly:
682 fReadOnly = True;
683 sCheckBoxAttr = ' readonly onclick="return false" onkeydown="return false"' if fReadOnly else '';
684
685 oDefMember = TestGroupMemberData();
686 aoTestGroupMembers = list(aoTestGroupMembers); # Copy it so we can pop.
687 for iTestCase, _ in enumerate(aoAllTestCases):
688 oTestCase = aoAllTestCases[iTestCase];
689
690 # Is it a member?
691 oMember = None;
692 for i, _ in enumerate(aoTestGroupMembers):
693 if aoTestGroupMembers[i].oTestCase.idTestCase == oTestCase.idTestCase:
694 oMember = aoTestGroupMembers.pop(i);
695 break;
696
697 # Start on the rows...
698 sPrefix = u'%s[%d]' % (sName, oTestCase.idTestCase,);
699 self._add(u' <tr class="%s">\n'
700 u' <td rowspan="%d">\n'
701 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestCase
702 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestGroup
703 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
704 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
705 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
706 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
707 u' </td>\n'
708 % ( 'tmodd' if iTestCase & 1 else 'tmeven',
709 len(oTestCase.aoTestCaseArgs),
710 sPrefix, TestGroupMemberData.ksParam_idTestCase, oTestCase.idTestCase,
711 sPrefix, TestGroupMemberData.ksParam_idTestGroup, -1 if oMember is None else oMember.idTestGroup,
712 sPrefix, TestGroupMemberData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
713 sPrefix, TestGroupMemberData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
714 sPrefix, TestGroupMemberData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
715 TestGroupDataEx.ksParam_aoMembers, '' if oMember is None else ' checked', sCheckBoxAttr,
716 oTestCase.idTestCase, oTestCase.idTestCase, escapeElem(oTestCase.sName),
717 ));
718 self._add(u' <td rowspan="%d" align="left">%s</td>\n'
719 % ( len(oTestCase.aoTestCaseArgs), escapeElem(oTestCase.sName), ));
720
721 self._add(u' <td rowspan="%d" title="Include all variations (checked) or choose a set?">\n'
722 u' <input name="%s[%s]" type="checkbox"%s%s value="-1">\n'
723 u' </td>\n'
724 % ( len(oTestCase.aoTestCaseArgs),
725 sPrefix, TestGroupMemberData.ksParam_aidTestCaseArgs,
726 ' checked' if oMember is None or oMember.aidTestCaseArgs is None else '', sCheckBoxAttr, ));
727
728 self._add(u' <td rowspan="%d" align="center">\n'
729 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
730 u' </td>\n'
731 % ( len(oTestCase.aoTestCaseArgs),
732 sPrefix, TestGroupMemberData.ksParam_iSchedPriority,
733 (oMember if oMember is not None else oDefMember).iSchedPriority,
734 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
735
736 # Argument variations.
737 aidTestCaseArgs = [] if oMember is None or oMember.aidTestCaseArgs is None else oMember.aidTestCaseArgs;
738 for iVar in range(len(oTestCase.aoTestCaseArgs)):
739 oVar = oTestCase.aoTestCaseArgs[iVar];
740 if iVar > 0:
741 self._add(' <tr class="%s">\n' % ('tmodd' if iTestCase & 1 else 'tmeven',));
742 self._add(u' <td align="center">\n'
743 u' <input name="%s[%s]" type="checkbox"%s%s value="%d">'
744 u' </td>\n'
745 % ( sPrefix, TestGroupMemberData.ksParam_aidTestCaseArgs,
746 ' checked' if oVar.idTestCaseArgs in aidTestCaseArgs else '', sCheckBoxAttr, oVar.idTestCaseArgs,
747 ));
748 self._add(u' <td align="center">%s</td>\n'
749 u' <td align="center">%s</td>\n'
750 u' <td align="left">%s</td>\n'
751 % ( oVar.cGangMembers,
752 'Default' if oVar.cSecTimeout is None else oVar.cSecTimeout,
753 escapeElem(oVar.sArgs) ));
754
755 self._add(u' </tr>\n');
756
757
758
759 if not oTestCase.aoTestCaseArgs:
760 self._add(u' <td></td> <td></td> <td></td> <td></td>\n'
761 u' </tr>\n');
762 return self._add(u' </tbody>\n'
763 u'</table>\n');
764
765 def addListOfSchedGroupMembers(self, sName, aoSchedGroupMembers, aoAllTestGroups, # pylint: disable=R0914
766 sLabel, fReadOnly = True):
767 """
768 For WuiAdminSchedGroup.
769 """
770 if fReadOnly is None or self._fReadOnly:
771 fReadOnly = self._fReadOnly;
772 assert len(aoSchedGroupMembers) <= len(aoAllTestGroups);
773 self._addLabel(sName, sLabel);
774 if not aoAllTestGroups:
775 return self._add(u'<li>No test groups available.</li>\n')
776
777 self._add(u'<input name="%s" type="hidden" value="%s">\n'
778 % ( SchedGroupDataEx.ksParam_aidTestGroups,
779 ','.join([unicode(oTestGroup.idTestGroup) for oTestGroup in aoAllTestGroups]), ));
780
781 self._add(u'<table class="tmformtbl">\n'
782 u' <thead>\n'
783 u' <tr>\n'
784 u' <th></th>\n'
785 u' <th>Test Group</th>\n'
786 u' <th>Priority [0..31]</th>\n'
787 u' <th>Prerequisite Test Group</th>\n'
788 u' <th>Weekly schedule</th>\n'
789 u' </tr>\n'
790 u' </thead>\n'
791 u' <tbody>\n'
792 );
793
794 sCheckBoxAttr = u' readonly onclick="return false" onkeydown="return false"' if fReadOnly else '';
795 sComboBoxAttr = u' disabled' if fReadOnly else '';
796
797 oDefMember = SchedGroupMemberData();
798 aoSchedGroupMembers = list(aoSchedGroupMembers); # Copy it so we can pop.
799 for iTestGroup, _ in enumerate(aoAllTestGroups):
800 oTestGroup = aoAllTestGroups[iTestGroup];
801
802 # Is it a member?
803 oMember = None;
804 for i, _ in enumerate(aoSchedGroupMembers):
805 if aoSchedGroupMembers[i].oTestGroup.idTestGroup == oTestGroup.idTestGroup:
806 oMember = aoSchedGroupMembers.pop(i);
807 break;
808
809 # Start on the rows...
810 sPrefix = u'%s[%d]' % (sName, oTestGroup.idTestGroup,);
811 self._add(u' <tr class="%s">\n'
812 u' <td>\n'
813 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestGroup
814 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
815 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
816 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
817 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
818 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
819 u' </td>\n'
820 % ( 'tmodd' if iTestGroup & 1 else 'tmeven',
821 sPrefix, SchedGroupMemberData.ksParam_idTestGroup, oTestGroup.idTestGroup,
822 sPrefix, SchedGroupMemberData.ksParam_idSchedGroup, -1 if oMember is None else oMember.idSchedGroup,
823 sPrefix, SchedGroupMemberData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
824 sPrefix, SchedGroupMemberData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
825 sPrefix, SchedGroupMemberData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
826 SchedGroupDataEx.ksParam_aoMembers, '' if oMember is None else ' checked', sCheckBoxAttr,
827 oTestGroup.idTestGroup, oTestGroup.idTestGroup, escapeElem(oTestGroup.sName),
828 ));
829 self._add(u' <td align="left">%s</td>\n' % ( escapeElem(oTestGroup.sName), ));
830
831 self._add(u' <td align="center">\n'
832 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
833 u' </td>\n'
834 % ( sPrefix, SchedGroupMemberData.ksParam_iSchedPriority,
835 (oMember if oMember is not None else oDefMember).iSchedPriority,
836 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
837
838 self._add(u' <td align="center">\n'
839 u' <select name="%s[%s]" id="%s[%s]" class="tmform-combobox"%s>\n'
840 u' <option value="-1"%s>None</option>\n'
841 % ( sPrefix, SchedGroupMemberData.ksParam_idTestGroupPreReq,
842 sPrefix, SchedGroupMemberData.ksParam_idTestGroupPreReq,
843 sComboBoxAttr,
844 ' selected' if oMember is None or oMember.idTestGroupPreReq is None else '',
845 ));
846 for oTestGroup2 in aoAllTestGroups:
847 if oTestGroup2 != oTestGroup:
848 fSelected = oMember is not None and oTestGroup2.idTestGroup == oMember.idTestGroupPreReq;
849 self._add(' <option value="%s"%s>%s</option>\n'
850 % ( oTestGroup2.idTestGroup, ' selected' if fSelected else '', escapeElem(oTestGroup2.sName), ));
851 self._add(u' </select>\n'
852 u' </td>\n');
853
854 self._add(u' <td align="left">\n'
855 u' Todo<input name="%s[%s]" type="hidden" value="%s">\n'
856 u' </td>\n'
857 % ( sPrefix, SchedGroupMemberData.ksParam_bmHourlySchedule,
858 '' if oMember is None else oMember.bmHourlySchedule, ));
859
860 self._add(u' </tr>\n');
861 return self._add(u' </tbody>\n'
862 u'</table>\n');
863
864 def addListOfSchedGroupsForTestBox(self, sName, aoInSchedGroups, aoAllSchedGroups, sLabel, # pylint: disable=R0914
865 fReadOnly = None):
866 # type: (str, TestBoxInSchedGroupDataEx, SchedGroupData, str, bool) -> str
867 """
868 For WuiTestGroup.
869 """
870 from testmanager.core.testbox import TestBoxInSchedGroupData, TestBoxDataEx;
871
872 if fReadOnly is None or self._fReadOnly:
873 fReadOnly = self._fReadOnly;
874 assert len(aoInSchedGroups) <= len(aoAllSchedGroups);
875
876 # Only show selected groups in read-only mode.
877 if fReadOnly:
878 aoAllSchedGroups = [oCur.oSchedGroup for oCur in aoInSchedGroups]
879
880 self._addLabel(sName, sLabel);
881 if not aoAllSchedGroups:
882 return self._add('<li>No scheduling groups available.</li>\n')
883
884 # Add special parameter with all the scheduling group IDs in the form.
885 self._add(u'<input name="%s" type="hidden" value="%s">\n'
886 % ( TestBoxDataEx.ksParam_aidSchedGroups,
887 ','.join([unicode(oSchedGroup.idSchedGroup) for oSchedGroup in aoAllSchedGroups]), ));
888
889 # Table header.
890 self._add(u'<table class="tmformtbl">\n'
891 u' <thead>\n'
892 u' <tr>\n'
893 u' <th rowspan="2"></th>\n'
894 u' <th rowspan="2">Schedulding Group</th>\n'
895 u' <th rowspan="2">Priority [0..31]</th>\n'
896 u' </tr>\n'
897 u' </thead>\n'
898 u' <tbody>\n'
899 );
900
901 # Table body.
902 if self._fReadOnly:
903 fReadOnly = True;
904 sCheckBoxAttr = ' readonly onclick="return false" onkeydown="return false"' if fReadOnly else '';
905
906 oDefMember = TestBoxInSchedGroupData();
907 aoInSchedGroups = list(aoInSchedGroups); # Copy it so we can pop.
908 for iSchedGroup, oSchedGroup in enumerate(aoAllSchedGroups):
909
910 # Is it a member?
911 oMember = None;
912 for i, _ in enumerate(aoInSchedGroups):
913 if aoInSchedGroups[i].idSchedGroup == oSchedGroup.idSchedGroup:
914 oMember = aoInSchedGroups.pop(i);
915 break;
916
917 # Start on the rows...
918 sPrefix = u'%s[%d]' % (sName, oSchedGroup.idSchedGroup,);
919 self._add(u' <tr class="%s">\n'
920 u' <td>\n'
921 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
922 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestBox
923 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
924 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
925 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
926 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
927 u' </td>\n'
928 % ( 'tmodd' if iSchedGroup & 1 else 'tmeven',
929 sPrefix, TestBoxInSchedGroupData.ksParam_idSchedGroup, oSchedGroup.idSchedGroup,
930 sPrefix, TestBoxInSchedGroupData.ksParam_idTestBox, -1 if oMember is None else oMember.idTestBox,
931 sPrefix, TestBoxInSchedGroupData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
932 sPrefix, TestBoxInSchedGroupData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
933 sPrefix, TestBoxInSchedGroupData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
934 TestBoxDataEx.ksParam_aoInSchedGroups, '' if oMember is None else ' checked', sCheckBoxAttr,
935 oSchedGroup.idSchedGroup, oSchedGroup.idSchedGroup, escapeElem(oSchedGroup.sName),
936 ));
937 self._add(u' <td align="left">%s</td>\n' % ( escapeElem(oSchedGroup.sName), ));
938
939 self._add(u' <td align="center">\n'
940 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
941 u' </td>\n'
942 % ( sPrefix, TestBoxInSchedGroupData.ksParam_iSchedPriority,
943 (oMember if oMember is not None else oDefMember).iSchedPriority,
944 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
945 self._add(u' </tr>\n');
946
947 return self._add(u' </tbody>\n'
948 u'</table>\n');
949
950
951 #
952 # Buttons.
953 #
954 def addSubmit(self, sLabel = 'Submit'):
955 """Adds the submit button to the form."""
956 if self._fReadOnly:
957 return True;
958 return self._add(u' <li>\n'
959 u' <br>\n'
960 u' <div class="tmform-field"><div class="tmform-field-submit">\n'
961 u' <label>&nbsp;</label>\n'
962 u' <input type="submit" value="%s">\n'
963 u' </div></div>\n'
964 u' </li>\n'
965 % (escapeElem(sLabel),));
966
967 def addReset(self):
968 """Adds a reset button to the form."""
969 if self._fReadOnly:
970 return True;
971 return self._add(u' <li>\n'
972 u' <div class="tmform-button"><div class="tmform-button-reset">\n'
973 u' <input type="reset" value="%s">\n'
974 u' </div></div>\n'
975 u' </li>\n');
976
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette