diff --git a/framework/yii/widgets/GridView.php b/framework/yii/widgets/GridView.php
new file mode 100644
index 0000000..98b4884
--- /dev/null
+++ b/framework/yii/widgets/GridView.php
@@ -0,0 +1,326 @@
+<?php
+/**
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright (c) 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ */
+
+namespace yii\widgets;
+
+use Yii;
+use Closure;
+use yii\base\Formatter;
+use yii\base\InvalidConfigException;
+use yii\base\Widget;
+use yii\db\ActiveRecord;
+use yii\helpers\Html;
+use yii\widgets\grid\DataColumn;
+
+/**
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @since 2.0
+ */
+class GridView extends ListViewBase
+{
+	const FILTER_POS_HEADER = 'header';
+	const FILTER_POS_FOOTER = 'footer';
+	const FILTER_POS_BODY = 'body';
+
+	public $caption;
+	public $captionOptions = array();
+	public $tableOptions = array('class' => 'table table-striped table-bordered');
+	public $headerRowOptions = array();
+	public $footerRowOptions = array();
+	public $beforeRow;
+	public $afterRow;
+	public $showHeader = true;
+	public $showFooter = false;
+	/**
+	 * @var array|Closure
+	 */
+	public $rowOptions = array();
+	/**
+	 * @var array|Formatter the formatter used to format model attribute values into displayable texts.
+	 * This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]]
+	 * instance. If this property is not set, the "formatter" application component will be used.
+	 */
+	public $formatter;
+	/**
+	 * @var array grid column configuration. Each array element represents the configuration
+	 * for one particular grid column which can be either a string or an array.
+	 *
+	 * When a column is specified as a string, it should be in the format of "name:type:header",
+	 * where "type" and "header" are optional. A {@link CDataColumn} instance will be created in this case,
+	 * whose {@link CDataColumn::name}, {@link CDataColumn::type} and {@link CDataColumn::header}
+	 * properties will be initialized accordingly.
+	 *
+	 * When a column is specified as an array, it will be used to create a grid column instance, where
+	 * the 'class' element specifies the column class name (defaults to {@link CDataColumn} if absent).
+	 * Currently, these official column classes are provided: {@link CDataColumn},
+	 * {@link CLinkColumn}, {@link CButtonColumn} and {@link CCheckBoxColumn}.
+	 */
+	public $columns = array();
+	/**
+	 * @var string the layout that determines how different sections of the list view should be organized.
+	 * The following tokens will be replaced with the corresponding section contents:
+	 *
+	 * - `{summary}`: the summary section. See [[renderSummary()]].
+	 * - `{items}`: the list items. See [[renderItems()]].
+	 * - `{sorter}`: the sorter. See [[renderSorter()]].
+	 * - `{pager}`: the pager. See [[renderPager()]].
+	 */
+	public $layout = "{summary}\n{pager}{items}\n{pager}";
+	public $emptyCell = '&nbsp;';
+	/**
+	 * @var \yii\base\Model the model instance that keeps the user-entered filter data. When this property is set,
+	 * the grid view will enable column-based filtering. Each data column by default will display a text field
+	 * at the top that users can fill in to filter the data.
+	 * Note that in order to show an input field for filtering, a column must have its {@link CDataColumn::name}
+	 * property set or have {@link CDataColumn::filter} as the HTML code for the input field.
+	 * When this property is not set (null) the filtering is disabled.
+	 */
+	public $filterModel;
+	/**
+	 * @var string whether the filters should be displayed in the grid view. Valid values include:
+	 * <ul>
+	 *    <li>header: the filters will be displayed on top of each column's header cell.</li>
+	 *    <li>body: the filters will be displayed right below each column's header cell.</li>
+	 *    <li>footer: the filters will be displayed below each column's footer cell.</li>
+	 * </ul>
+	 */
+	public $filterPosition = 'body';
+	public $filterOptions = array('class' => 'filters');
+
+	/**
+	 * Initializes the grid view.
+	 * This method will initialize required property values and instantiate {@link columns} objects.
+	 */
+	public function init()
+	{
+		parent::init();
+		if ($this->formatter == null) {
+			$this->formatter = Yii::$app->getFormatter();
+		} elseif (is_array($this->formatter)) {
+			$this->formatter = Yii::createObject($this->formatter);
+		}
+		if (!$this->formatter instanceof Formatter) {
+			throw new InvalidConfigException('The "formatter" property must be either a Format object or a configuration array.');
+		}
+
+		$this->initColumns();
+	}
+
+	/**
+	 * Renders the data items for the grid view.
+	 */
+	public function renderItems()
+	{
+		$content = array_filter(array(
+			$this->renderCaption(),
+			$this->renderColumnGroup(),
+			$this->showHeader ? $this->renderTableHeader() : false,
+			$this->showFooter ? $this->renderTableFooter() : false,
+			$this->renderTableBody(),
+		));
+		return Html::tag('table', implode("\n", $content), $this->tableOptions);
+	}
+
+	public function renderCaption()
+	{
+		if (!empty($this->caption)) {
+			return Html::tag('caption', $this->caption, $this->captionOptions);
+		} else {
+			return false;
+		}
+	}
+
+	public function renderColumnGroup()
+	{
+		$requireColumnGroup = false;
+		foreach ($this->columns as $column) {
+			/** @var \yii\widgets\grid\Column $column */
+			if (!empty($column->options)) {
+				$requireColumnGroup = true;
+				break;
+			}
+		}
+		if ($requireColumnGroup) {
+			$cols = array();
+			foreach ($this->columns as $column) {
+				$cols[] = Html::tag('col', '', $column->options);
+			}
+			return Html::tag('colgroup', implode("\n", $cols));
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * Renders the table header.
+	 * @return string the rendering result
+	 */
+	public function renderTableHeader()
+	{
+		$cells = array();
+		foreach ($this->columns as $column) {
+			/** @var \yii\widgets\grid\Column $column */
+			$cells[] = $column->renderHeaderCell();
+		}
+		$content = implode('', $cells);
+		if ($this->filterPosition == self::FILTER_POS_HEADER) {
+			$content = $this->renderFilters() . $content;
+		} elseif ($this->filterPosition == self::FILTER_POS_BODY) {
+			$content .= $this->renderFilters();
+		}
+		return "<thead>\n" . Html::tag('tr', $content, $this->headerRowOptions) . "\n</thead>";
+	}
+
+	/**
+	 * Renders the table footer.
+	 * @return string the rendering result
+	 */
+	public function renderTableFooter()
+	{
+		$cells = array();
+		foreach ($this->columns as $column) {
+			/** @var \yii\widgets\grid\Column $column */
+			$cells[] = $column->renderFooterCell();
+		}
+		$content = implode('', $cells);
+		if ($this->filterPosition == self::FILTER_POS_FOOTER) {
+			$content .= $this->renderFilters();
+		}
+		return "<tfoot>\n" . Html::tag('tr', $content, $this->footerRowOptions) . "\n</tfoot>";
+	}
+
+	/**
+	 * Renders the filter.
+	 */
+	public function renderFilters()
+	{
+		if ($this->filterModel !== null) {
+			$cells = array();
+			foreach ($this->columns as $column) {
+				/** @var \yii\widgets\grid\Column $column */
+				$cells[] = $column->renderFilterCell();
+			}
+			return Html::tag('tr', implode('', $cells), $this->filterOptions);
+		} else {
+			return '';
+		}
+	}
+
+	/**
+	 * Renders the table body.
+	 * @return string the rendering result
+	 */
+	public function renderTableBody()
+	{
+		$items = array_values($this->dataProvider->getItems());
+		$keys = $this->dataProvider->getKeys();
+		$rows = array();
+		foreach ($items as $index => $item) {
+			$key = $keys[$index];
+			if ($this->beforeRow !== null) {
+				$row = call_user_func($this->beforeRow, $item, $key, $index);
+				if (!empty($row)) {
+					$rows[] = $row;
+				}
+			}
+
+			$rows[] = $this->renderTableRow($item, $key, $index);
+
+			if ($this->afterRow !== null) {
+				$row = call_user_func($this->afterRow, $item, $key, $index);
+				if (!empty($row)) {
+					$rows[] = $row;
+				}
+			}
+		}
+		return "<tbody>\n" . implode("\n", $rows) . "\n</tbody>";
+	}
+
+	/**
+	 * Renders a table row with the given data item and key.
+	 * @param mixed $item the data item
+	 * @param mixed $key the key associated with the data item
+	 * @param integer $index the zero-based index of the data item among the item array returned by [[dataProvider]].
+	 * @return string the rendering result
+	 */
+	public function renderTableRow($item, $key, $index)
+	{
+		$cells = array();
+		/** @var \yii\widgets\grid\Column $column */
+		foreach ($this->columns as $column) {
+			$cells[] = $column->renderDataCell($item, $index);
+		}
+		if ($this->rowOptions instanceof Closure) {
+			$options = call_user_func($this->rowOptions, $item, $key, $index);
+		} else {
+			$options = $this->rowOptions;
+		}
+		$options['data-key'] = $key;
+		return Html::tag('tr', implode('', $cells), $options);
+	}
+
+	/**
+	 * Creates column objects and initializes them.
+	 */
+	protected function initColumns()
+	{
+		if (empty($this->columns)) {
+			$this->guessColumns();
+		}
+		$id = $this->getId();
+		foreach ($this->columns as $i => $column) {
+			if (is_string($column)) {
+				$column = $this->createDataColumn($column);
+			} else {
+				$column = Yii::createObject(array_merge(array(
+					'class' => DataColumn::className(),
+					'grid' => $this,
+				), $column));
+			}
+			if (!$column->visible) {
+				unset($this->columns[$i]);
+				continue;
+			}
+			if ($column->id === null) {
+				$column->id = $id . '_c' . $i;
+			}
+			$this->columns[$i] = $column;
+		}
+	}
+
+	/**
+	 * Creates a {@link CDataColumn} based on a shortcut column specification string.
+	 * @param string $text the column specification string
+	 * @return DataColumn the column instance
+	 * @throws InvalidConfigException if the column specification is invalid
+	 */
+	protected function createDataColumn($text)
+	{
+		if (!preg_match('/^(\w+)(\s*:\s*(\w+))?$/', $text, $matches)) {
+			throw new InvalidConfigException('The column must be specified in the format of "Attribute" or "Attribute:Type"');
+		}
+		return Yii::createObject(array(
+			'class' => DataColumn::className(),
+			'grid' => $this,
+			'attribute' => $matches[1],
+			'type' => isset($matches[3]) ? $matches[3] : 'text',
+		));
+	}
+
+	protected function guessColumns()
+	{
+		$items = $this->dataProvider->getItems();
+		$item = reset($items);
+		if (is_array($item) || is_object($item)) {
+			foreach ($item as $name => $value) {
+				$this->columns[] = $name;
+			}
+		} else {
+			throw new InvalidConfigException('Unable to generate columns from data.');
+		}
+	}
+}
diff --git a/framework/yii/widgets/grid/CheckboxColumn.php b/framework/yii/widgets/grid/CheckboxColumn.php
new file mode 100644
index 0000000..e6bb327
--- /dev/null
+++ b/framework/yii/widgets/grid/CheckboxColumn.php
@@ -0,0 +1,191 @@
+<?php
+/**
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright (c) 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ */
+
+namespace yii\widgets\grid;
+
+/**
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @since 2.0
+ */
+class CheckboxColumn extends Column
+{
+	public $checked;
+	/**
+	 * @var string a PHP expression that will be evaluated for every data cell and whose result will
+	 * determine if checkbox for each data cell is disabled. In this expression, you can use the following variables:
+	 * <ul>
+	 *   <li><code>$row</code> the row number (zero-based)</li>
+	 *   <li><code>$data</code> the data model for the row</li>
+	 *   <li><code>$this</code> the column object</li>
+	 * </ul>
+	 * The PHP expression will be evaluated using {@link evaluateExpression}.
+	 *
+	 * A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
+	 * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
+	 *
+	 * Note that expression result will overwrite value set with <code>checkBoxHtmlOptions['disabled']</code>.
+	 * @since 1.1.13
+	 */
+	public $disabled;
+	/**
+	 * @var array the HTML options for the data cell tags.
+	 */
+	public $htmlOptions = array('class' => 'checkbox-column');
+	/**
+	 * @var array the HTML options for the header cell tag.
+	 */
+	public $headerHtmlOptions = array('class' => 'checkbox-column');
+	/**
+	 * @var array the HTML options for the footer cell tag.
+	 */
+	public $footerHtmlOptions = array('class' => 'checkbox-column');
+	/**
+	 * @var array the HTML options for the checkboxes.
+	 */
+	public $checkBoxHtmlOptions = array();
+	/**
+	 * @var integer the number of rows that can be checked.
+	 * Possible values:
+	 * <ul>
+	 * <li>0 - the state of the checkbox cannot be changed (read-only mode)</li>
+	 * <li>1 - only one row can be checked. Checking a checkbox has nothing to do with selecting the row</li>
+	 * <li>2 or more - multiple checkboxes can be checked. Checking a checkbox has nothing to do with selecting the row</li>
+	 * <li>null - {@link CGridView::selectableRows} is used to control how many checkboxes can be checked.
+	 * Checking a checkbox will also select the row.</li>
+	 * </ul>
+	 * You may also call the JavaScript function <code>$(gridID).yiiGridView('getChecked', columnID)</code>
+	 * to retrieve the key values of the checked rows.
+	 * @since 1.1.6
+	 */
+	public $selectableRows = null;
+	/**
+	 * @var string the template to be used to control the layout of the header cell.
+	 * The token "{item}" is recognized and it will be replaced with a "check all" checkbox.
+	 * By default if in multiple checking mode, the header cell will display an additional checkbox,
+	 * clicking on which will check or uncheck all of the checkboxes in the data cells.
+	 * See {@link selectableRows} for more details.
+	 * @since 1.1.11
+	 */
+	public $headerTemplate = '{item}';
+
+	/**
+	 * Initializes the column.
+	 * This method registers necessary client script for the checkbox column.
+	 */
+	public function init()
+	{
+		if (isset($this->checkBoxHtmlOptions['name'])) {
+			$name = $this->checkBoxHtmlOptions['name'];
+		} else {
+			$name = $this->id;
+			if (substr($name, -2) !== '[]') {
+				$name .= '[]';
+			}
+			$this->checkBoxHtmlOptions['name'] = $name;
+		}
+		$name = strtr($name, array('[' => "\\[", ']' => "\\]"));
+
+		if ($this->selectableRows === null) {
+			if (isset($this->checkBoxHtmlOptions['class'])) {
+				$this->checkBoxHtmlOptions['class'] .= ' select-on-check';
+			} else {
+				$this->checkBoxHtmlOptions['class'] = 'select-on-check';
+			}
+			return;
+		}
+
+		$cball = $cbcode = '';
+		if ($this->selectableRows == 0) {
+			//.. read only
+			$cbcode = "return false;";
+		} elseif ($this->selectableRows == 1) {
+			//.. only one can be checked, uncheck all other
+			$cbcode = "jQuery(\"input:not(#\"+this.id+\")[name='$name']\").prop('checked',false);";
+		} elseif (strpos($this->headerTemplate, '{item}') !== false) {
+			//.. process check/uncheck all
+			$cball = <<<CBALL
+jQuery(document).on('click','#{$this->id}_all',function() {
+	var checked=this.checked;
+	jQuery("input[name='$name']:enabled").each(function() {this.checked=checked;});
+});
+
+CBALL;
+			$cbcode = "jQuery('#{$this->id}_all').prop('checked', jQuery(\"input[name='$name']\").length==jQuery(\"input[name='$name']:checked\").length);";
+		}
+
+		if ($cbcode !== '') {
+			$js = $cball;
+			$js .= <<<EOD
+jQuery(document).on('click', "input[name='$name']", function() {
+	$cbcode
+});
+EOD;
+			Yii::app()->getClientScript()->registerScript(__CLASS__ . '#' . $this->id, $js);
+		}
+	}
+
+	/**
+	 * Renders the header cell content.
+	 * This method will render a checkbox in the header when {@link selectableRows} is greater than 1
+	 * or in case {@link selectableRows} is null when {@link CGridView::selectableRows} is greater than 1.
+	 */
+	protected function renderHeaderCellContent()
+	{
+		if (trim($this->headerTemplate) === '') {
+			echo $this->grid->blankDisplay;
+			return;
+		}
+
+		$item = '';
+		if ($this->selectableRows === null && $this->grid->selectableRows > 1) {
+			$item = CHtml::checkBox($this->id . '_all', false, array('class' => 'select-on-check-all'));
+		} elseif ($this->selectableRows > 1) {
+			$item = CHtml::checkBox($this->id . '_all', false);
+		} else {
+			ob_start();
+			parent::renderHeaderCellContent();
+			$item = ob_get_clean();
+		}
+
+		echo strtr($this->headerTemplate, array(
+			'{item}' => $item,
+		));
+	}
+
+	/**
+	 * Renders the data cell content.
+	 * This method renders a checkbox in the data cell.
+	 * @param integer $row the row number (zero-based)
+	 * @param mixed $data the data associated with the row
+	 */
+	protected function renderDataCellContent($row, $data)
+	{
+		if ($this->value !== null) {
+			$value = $this->evaluateExpression($this->value, array('data' => $data, 'row' => $row));
+		} elseif ($this->name !== null) {
+			$value = CHtml::value($data, $this->name);
+		} else {
+			$value = $this->grid->dataProvider->keys[$row];
+		}
+
+		$checked = false;
+		if ($this->checked !== null) {
+			$checked = $this->evaluateExpression($this->checked, array('data' => $data, 'row' => $row));
+		}
+
+		$options = $this->checkBoxHtmlOptions;
+		if ($this->disabled !== null) {
+			$options['disabled'] = $this->evaluateExpression($this->disabled, array('data' => $data, 'row' => $row));
+		}
+
+		$name = $options['name'];
+		unset($options['name']);
+		$options['value'] = $value;
+		$options['id'] = $this->id . '_' . $row;
+		echo CHtml::checkBox($name, $checked, $options);
+	}
+}
diff --git a/framework/yii/widgets/grid/Column.php b/framework/yii/widgets/grid/Column.php
new file mode 100644
index 0000000..8cb692d
--- /dev/null
+++ b/framework/yii/widgets/grid/Column.php
@@ -0,0 +1,147 @@
+<?php
+/**
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright (c) 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ */
+
+namespace yii\widgets\grid;
+
+use Closure;
+use yii\base\Object;
+use yii\helpers\Html;
+use yii\widgets\GridView;
+
+/**
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @since 2.0
+ */
+class Column extends Object
+{
+	/**
+	 * @var string the ID of this column. This value should be unique among all grid view columns.
+	 * If this is not set, it will be assigned one automatically.
+	 */
+	public $id;
+	/**
+	 * @var GridView the grid view object that owns this column.
+	 */
+	public $grid;
+	/**
+	 * @var string the header cell content. Note that it will not be HTML-encoded.
+	 */
+	public $header;
+	/**
+	 * @var string the footer cell content. Note that it will not be HTML-encoded.
+	 */
+	public $footer;
+	/**
+	 * @var callable
+	 */
+	public $content;
+	/**
+	 * @var boolean whether this column is visible. Defaults to true.
+	 */
+	public $visible = true;
+	public $options = array();
+	public $headerOptions = array();
+	/**
+	 * @var array|\Closure
+	 */
+	public $bodyOptions = array();
+	public $footerOptions = array();
+	/**
+	 * @var array the HTML attributes for the filter cell tag.
+	 */
+	public $filterOptions=array();
+
+
+	/**
+	 * Renders the header cell.
+	 */
+	public function renderHeaderCell()
+	{
+		return Html::tag('th', $this->renderHeaderCellContent(), $this->headerOptions);
+	}
+
+	/**
+	 * Renders the footer cell.
+	 */
+	public function renderFooterCell()
+	{
+		return Html::tag('td', $this->renderFooterCellContent(), $this->footerOptions);
+	}
+
+	/**
+	 * Renders a data cell.
+	 * @param mixed $item the data item
+	 * @param integer $index the zero-based index of the data item among the item array returned by [[dataProvider]].
+	 * @return string the rendering result
+	 */
+	public function renderDataCell($item, $index)
+	{
+		if ($this->bodyOptions instanceof Closure) {
+			$options = call_user_func($this->bodyOptions, $item, $index, $this);
+		} else {
+			$options = $this->bodyOptions;
+		}
+		return Html::tag('td', $this->renderDataCellContent($item, $index), $options);
+	}
+
+	/**
+	 * Renders the filter cell.
+	 */
+	public function renderFilterCell()
+	{
+		return Html::tag('td', $this->renderFilterCellContent(), $this->filterOptions);
+	}
+
+	/**
+	 * Renders the header cell content.
+	 * The default implementation simply renders {@link header}.
+	 * This method may be overridden to customize the rendering of the header cell.
+	 * @return string the rendering result
+	 */
+	protected function renderHeaderCellContent()
+	{
+		return trim($this->header) !== '' ? $this->header : $this->grid->emptyCell;
+	}
+
+	/**
+	 * Renders the footer cell content.
+	 * The default implementation simply renders {@link footer}.
+	 * This method may be overridden to customize the rendering of the footer cell.
+	 * @return string the rendering result
+	 */
+	protected function renderFooterCellContent()
+	{
+		return trim($this->footer) !== '' ? $this->footer : $this->grid->emptyCell;
+	}
+
+	/**
+	 * Renders the data cell content.
+	 * @param mixed $item the data item
+	 * @param integer $index the zero-based index of the data item among the item array returned by [[dataProvider]].
+	 * @return string the rendering result
+	 */
+	protected function renderDataCellContent($item, $index)
+	{
+		if ($this->content !== null) {
+			return call_user_func($this->content, $item, $index, $this);
+		} else {
+			return $this->grid->emptyCell;
+		}
+	}
+
+	/**
+	 * Renders the filter cell content.
+	 * The default implementation simply renders a space.
+	 * This method may be overridden to customize the rendering of the filter cell (if any).
+	 * @return string the rendering result
+	 */
+	protected function renderFilterCellContent()
+	{
+		return $this->grid->emptyCell;
+	}
+}
diff --git a/framework/yii/widgets/grid/DataColumn.php b/framework/yii/widgets/grid/DataColumn.php
new file mode 100644
index 0000000..6035ed2
--- /dev/null
+++ b/framework/yii/widgets/grid/DataColumn.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright (c) 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ */
+
+namespace yii\widgets\grid;
+use yii\base\InvalidConfigException;
+use yii\base\Model;
+use yii\data\ActiveDataProvider;
+use yii\db\ActiveQuery;
+use yii\helpers\ArrayHelper;
+use yii\helpers\Html;
+use yii\helpers\Inflector;
+
+/**
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @since 2.0
+ */
+class DataColumn extends Column
+{
+	public $attribute;
+	public $value;
+	public $type;
+	/**
+	 * @var boolean whether to allow sorting by this column. If true and [[attribute]] is found in
+	 * the sort definition of [[GridView::dataProvider]], then the header cell of this column
+	 * will contain a link that may trigger the sorting when being clicked.
+	 */
+	public $enableSorting = true;
+	/**
+	 * @var string|array|boolean the HTML code representing a filter input (eg a text field, a dropdown list)
+	 * that is used for this data column. This property is effective only when
+	 * {@link CGridView::filter} is set.
+	 * If this property is not set, a text field will be generated as the filter input;
+	 * If this property is an array, a dropdown list will be generated that uses this property value as
+	 * the list options.
+	 * If you don't want a filter for this data column, set this value to false.
+	 * @since 1.1.1
+	 */
+	public $filter;
+
+
+	protected function renderHeaderCellContent()
+	{
+		if ($this->attribute !== null && $this->header === null) {
+			$provider = $this->grid->dataProvider;
+			if ($this->enableSorting && ($sort = $provider->getSort()) !== false && $sort->hasAttribute($this->attribute)) {
+				return $sort->link($this->attribute);
+			}
+			$items = $provider->getItems();
+			if (($item = reset($items)) instanceof Model) {
+				/** @var Model $item */
+				return $item->getAttributeLabel($this->attribute);
+			} elseif ($provider instanceof ActiveDataProvider) {
+				if ($provider->query instanceof ActiveQuery) {
+					/** @var Model $model */
+					$model = new $provider->query->modelClass;
+					return $model->getAttributeLabel($this->attribute);
+				}
+			}
+			return Inflector::camel2words($this->attribute);
+		} else {
+			return parent::renderHeaderCellContent();
+		}
+	}
+
+	protected function renderFilterCellContent()
+	{
+		if (is_string($this->filter)) {
+			return $this->filter;
+		} elseif ($this->filter !== false && $this->grid->filterModel instanceof Model && $this->attribute !== null) {
+			if (is_array($this->filter)) {
+				return Html::activeDropDownList($this->grid->filterModel, $this->attribute, $this->filter, array('prompt' => ''));
+			} else {
+				return Html::activeTextInput($this->grid->filterModel, $this->attribute);
+			}
+		} else {
+			return parent::renderFilterCellContent();
+		}
+	}
+
+	protected function renderDataCellContent($item, $index)
+	{
+		if ($this->value !== null) {
+			$value = call_user_func($this->value, $item, $index, $this);
+		} elseif ($this->content === null && $this->attribute !== null) {
+			$value = ArrayHelper::getValue($item, $this->attribute);
+		} else {
+			return parent::renderDataCellContent($item, $index);
+		}
+		return $this->grid->formatter->format($value, $this->type);
+	}
+}