/**
	 * Renders question table with header and proposal views
	 */
	function renderTable() {
		$questionTable = array();
		# add header views to $questionTable
		foreach ( $this->hviews as $header ) {
			$rowattrs = array();
			$attribute_maps = array();
			if ( is_object( $header ) ) {
				$row = &$header->row;
				$rowattrs['class'] = $header->className;
				$attribute_maps = &$header->attribute_maps;
			} else {
				$row = &$header;
			}
			qp_Renderer::addRow( $questionTable, $row, $rowattrs, 'th', $attribute_maps );
		}
		foreach ( $this->pviews as $pkey => $propview ) {
			$prop = $this->renderParsedProposal( $pkey, $propview );
			$rowattrs = array( 'class' => $propview->rowClass );
			if ( $this->transposed ) {
				qp_Renderer::addColumn( $questionTable, $prop, $rowattrs );
			} else {
				qp_Renderer::addRow( $questionTable, $prop, $rowattrs );
			}
		}
		return $questionTable;
	}
	/**
	 * Add interpretation results to tagarray of poll view
	 */
	function showInterpResults( array &$tagarray, qp_InterpResult $ctrl, $showDescriptions = false ) {
		if ( $ctrl->hasVisibleProperties() ) {
			return;
		}
		$interp = array();
		if ( $showDescriptions ) {
				$interp[] = array( '__tag' => 'div', wfMsg( 'qp_results_interpretation_header' ) );
		}
		# currently, error is not stored in DB, only the vote and long / short interpretations
		# todo: is it worth to store it?
		if ( ( $scriptError = $ctrl->error ) != '' ) {
			$interp[] = array( '__tag' => 'div', 'class' => 'interp_error', qp_Setup::specialchars( $scriptError ) );
		}
		# output long result, when permitted and available
		if ( $this->showInterpretation['long'] &&
				( $answer = $ctrl->long ) !== '' ) {
			if ( $showDescriptions ) {
				$interp[] = array( '__tag' => 'div', 'class' => 'interp_header', wfMsg( 'qp_results_long_interpretation' ) );
			}
			$interp[] = array( '__tag' => 'div', 'class' => 'interp_answer_body', is_null( $this->pview ) ? nl2br( qp_Setup::specialchars( $answer ) ) : $this->pview->rtp( $answer ) );
		}
		# output short result, when permitted and available
		if ( $this->showInterpretation['short'] &&
				( $answer = $ctrl->short ) !== '' ) {
			if ( $showDescriptions ) {
				$interp[] = array( '__tag' => 'div', 'class' => 'interp_header', wfMsg( 'qp_results_short_interpretation' ) );
			}
			$interp[] = array( '__tag' => 'div', 'class' => 'interp_answer_body', nl2br( qp_Setup::specialchars( $answer ) ) );
		}
		if ( $this->showInterpretation['structured'] &&
				( $answer = $ctrl->structured ) !== '' ) {
			if ( $showDescriptions ) {
				$interp[] = array( '__tag' => 'div', 'class' => 'interp_header', wfMsg( 'qp_results_structured_interpretation' ) );
			}
			$strucTable = $ctrl->getStructuredAnswerTable();
			$rows = array();
			foreach ( $strucTable as &$line ) {
				if ( isset( $line['keys'] ) ) {
					# current node is associative array
					qp_Renderer::addRow( $rows, $line['keys'], array(), 'th' );
					qp_Renderer::addRow( $rows, $line['vals'] );
				} else {
					# current node is scalar value
					qp_Renderer::addRow( $rows, array( $line['vals'] ) );
				}
			}
			$interp[] = array( '__tag' => 'table', 'class' => 'structured_answer', $rows );
			unset( $strucTable );
		}
		$tagarray[] = array( '__tag' => 'div', 'class' => 'interp_answer', $interp );
	}
	/**
	 * Renders question table with header and proposal views
	 */
	function renderTable() {
		$questionTable = array();
		# add header views to $questionTable
		$rowattrs = array();
		foreach ( $this->hviews as $header ) {
			$rowattrs['class'] = $header->className;
			if ( $this->transposed ) {
				qp_Renderer::addColumn( $questionTable, $header->row, $rowattrs, 'th', $header->attribute_maps );
			} else {
				qp_Renderer::addRow( $questionTable, $header->row, $rowattrs, 'th', $header->attribute_maps );
			}
		}
		# add proposal views to $questionTable
		ksort( $this->pviews );
		foreach ( $this->pviews as $propview ) {
			$row = &$propview->row;
			$rowattrs = array( 'class' => $propview->rowClass );
			$text = array( '__tag' => 'td', '__end' => "\n", 'class' => 'proposaltext', 'style' => $this->proposalTextStyle, 0 => $this->rtp( $propview->text ) );
			# insert proposal text to the beginning / end according to proposalsFirst property
			if ( $this->proposalsFirst ) {
				# first element is proposaltext
				array_unshift( $row, $text );
			} else {
				# last element is proposaltext
				$row[] = $text;
			}
			if ( $this->transposed ) {
				qp_Renderer::addColumn( $questionTable, $row, $rowattrs );
			} else {
				qp_Renderer::addRow( $questionTable, $row, $rowattrs );
			}
		}
		return $questionTable;
	}
	/**
	 * Renders question table with header and proposal views
	 */
	function renderTable() {
		$questionTable = array();
		# add header views to $questionTable
		$rowattrs = array();
		foreach ( $this->hviews as $header ) {
			$rowattrs['class'] = $header->className;
			qp_Renderer::addRow( $questionTable, $header->row, $rowattrs, 'th', $header->attribute_maps );
		}
		return $questionTable;
	}