Project

General

Profile

Feature #4380 » 0001-Add-support-for-multiple-column-sort-in-TableView.patch

Multiple column sort patch - Trigve Siver, 09/14/2016 05:29 PM

View differences:

src/Wt/WAbstractItemModel
*/
virtual void sort(int column, SortOrder order = AscendingOrder);
/*! \brief Sorts the model according to a particular columns.
*
* If the model supports sorting, then it should emit the
* layoutAboutToBeChanged() signal, rearrange its items, and
* afterwards emit the layoutChanged() signal.
*
* \sa layoutAboutToBeChanged(), layoutChanged()
*/
virtual void sort(std::vector<int> const &columns, std::vector<SortOrder> const &orders);
/*! \brief Expands a column.
*
* Expands a column. This may only be called by a view when the
src/Wt/WAbstractItemModel.C
void WAbstractItemModel::sort(int column, SortOrder order)
{ }
void WAbstractItemModel::sort(std::vector<int> const & columns, std::vector<SortOrder> const & orders)
{}
void WAbstractItemModel::expandColumn(int column)
{ }
src/Wt/WAbstractItemView
*/
void sortByColumn(int column, SortOrder order);
/*! \brief Sorts the data according to a columns.
*
* Sorts the data according to data in columns \p columns and sort
* orders \p orders.
*
*
* \sa WAbstractItemModel::sort()
*/
void sortByColumns(std::vector<int> const & columns, std::vector<SortOrder> const &order);
/*! \brief Add/remove the colum for actual sorting.
*
* Sorts the data according to data in column \p column and sort
* order \p order.
*
*
* \sa WAbstractItemModel::sort()
*/
void modifySortByColumn(int column, SortOrder order, bool append);
/*! \brief Returns the current sorting columm.
*
* \sa sortByColumn(), sortOrder()
......
*/
SortOrder sortOrder() const;
/*! \brief Returns the current sorting order.
*
* \sa sortByColumn(), sortColumn(), sortByColumns()
*/
std::vector<SortOrder> sortOrders() const;
/*! \brief Enables or disables sorting for all columns.
*
* Enable or disable sorting by the user on all columns.
......
WSignalMapper<WModelIndex, WMouseEvent> *clickedMapper_;
mutable std::vector<ColumnInfo> columns_;
int currentSortColumn_;
//int currentSortColumn_;
std::vector<int> currentSortColumns_;
bool dragEnabled_, dropsEnabled_;
WWidget *dragWidget_;
......
void handleHeaderMouseUp(int columnid, WMouseEvent event);
void handleHeaderClicked(int columnid, WMouseEvent event);
void handleHeaderDblClicked(int columnid, WMouseEvent event);
void toggleSortColumn(int columnid);
void toggleSortColumn(int columnid, bool AppendRemove);
void updateColumnWidth(int columnId, int width);
virtual WContainerWidget* headerContainer() = 0;
src/Wt/WAbstractItemView.C
: WCompositeWidget(parent),
impl_(new WContainerWidget()),
renderState_(NeedRerender),
currentSortColumn_(-1),
dragEnabled_(false),
dropsEnabled_(false),
model_(0),
......
ColumnInfo& info = columnInfo(column);
if (sortEnabled_ && info.sorting)
toggleSortColumn(columnid);
toggleSortColumn(columnid, event.ctrlKey());
headerClicked_.emit(column, event);
}
......
headerMouseWentUp_.emit(columnById(columnid), event);
}
void WAbstractItemView::toggleSortColumn(int columnid)
void WAbstractItemView::toggleSortColumn(int columnid, bool appendRemove)
{
int column = columnById(columnid);
bool const column_exist = (std::find(currentSortColumns_.cbegin(), currentSortColumns_.cend(), column) != currentSortColumns_.cend());
if (column != currentSortColumn_)
sortByColumn(column, columnInfo(column).sortOrder);
// Append/Remove should be handled separately
if(appendRemove)
{
SortOrder order = AscendingOrder;
// If the column is sorted, remove it
if(column_exist)
modifySortByColumn(column, (order = AscendingOrder), false);
// Otherwise add it
else
modifySortByColumn(column, (order = columnInfo(column).sortOrder), true);
// Backward compatibility
if(currentSortColumns_.size() == 1)
model_->sort(currentSortColumns_.front(), order);
model_->sort(currentSortColumns_, sortOrders());
}
// Changing sort order or complet new sorting
else
sortByColumn(column, columnInfo(column).sortOrder == AscendingOrder
? DescendingOrder : AscendingOrder);
{
if(!column_exist)
sortByColumn(column, columnInfo(column).sortOrder);
else
sortByColumn(column, columnInfo(column).sortOrder == AscendingOrder
? DescendingOrder : AscendingOrder);
}
}
void WAbstractItemView::sortByColumns(std::vector<int> const &columns, std::vector<SortOrder> const &orders)
{
for(auto end = columns.size(), i = 0U; i < end; ++i)
modifySortByColumn(columns.at(i), orders.at(i), true);
model_->sort(currentSortColumns_, sortOrders());
}
void WAbstractItemView::modifySortByColumn(int column, SortOrder order, bool append)
{
// Add new column for sorting
if(append)
{
currentSortColumns_.push_back(column);
WText* t = headerSortIconWidget(column);
if(t)
{
t->setStyleClass(order == AscendingOrder
? "Wt-tv-sh Wt-tv-sh-up" : "Wt-tv-sh Wt-tv-sh-down");
columnInfo(column).sortOrder = order;
}
}
else
{
currentSortColumns_.erase(std::find(currentSortColumns_.begin(), currentSortColumns_.end(), column));
WText* t = headerSortIconWidget(column);
if(t)
t->setStyleClass("Wt-tv-sh Wt-tv-sh-none");
}
}
int WAbstractItemView::sortColumn() const
{
return currentSortColumn_;
return currentSortColumns_.empty() ? -1 : currentSortColumns_.front();
}
SortOrder WAbstractItemView::sortOrder() const
{
if (currentSortColumn_ >= 0
&& currentSortColumn_ < static_cast<int>(columns_.size()))
return columns_[currentSortColumn_].sortOrder;
if (!currentSortColumns_.empty()
&& currentSortColumns_.front() < static_cast<int>(columns_.size()))
return columns_[currentSortColumns_.front()].sortOrder;
else
return AscendingOrder;
}
std::vector<Wt::SortOrder> WAbstractItemView::sortOrders() const
{
std::vector<Wt::SortOrder> ret;
for(auto it = currentSortColumns_.cbegin(), end = currentSortColumns_.cend(); it != end; ++it)
ret.push_back(columnInfo(*it).sortOrder);
return ret;
}
int WAbstractItemView::columnById(int columnid) const
{
for (unsigned i = 0; i < columns_.size(); ++i)
......
void WAbstractItemView::sortByColumn(int column, SortOrder order)
{
if (currentSortColumn_ != -1) {
WText* t = headerSortIconWidget(currentSortColumn_);
if (t)
t->setStyleClass("Wt-tv-sh Wt-tv-sh-none");
}
auto const it_column = std::find(currentSortColumns_.cbegin(), currentSortColumns_.cend(), column);
currentSortColumn_ = column;
columnInfo(column).sortOrder = order;
// Column isn't in sorted columns, need to reset all the columns and add the new one
if (it_column == currentSortColumns_.cend()) {
for(auto it = currentSortColumns_.cbegin(), end = currentSortColumns_.cend(); it != end; ++it)
{
WText* t = headerSortIconWidget(*it);
if(t)
t->setStyleClass("Wt-tv-sh Wt-tv-sh-none");
}
currentSortColumns_.clear();
if (renderState_ != NeedRerender) {
WText* t = headerSortIconWidget(currentSortColumn_);
if (t)
t->setStyleClass(order == AscendingOrder
? "Wt-tv-sh Wt-tv-sh-up" : "Wt-tv-sh Wt-tv-sh-down");
// Add new column
currentSortColumns_.push_back(column);
columnInfo(column).sortOrder = order;
}
// Just change order
else
{
columnInfo(*it_column).sortOrder = order;
if(renderState_ != NeedRerender)
{
WText* t = headerSortIconWidget(*it_column);
if(t)
t->setStyleClass(order == AscendingOrder
? "Wt-tv-sh Wt-tv-sh-up" : "Wt-tv-sh Wt-tv-sh-down");
}
}
model_->sort(column, order);
if(currentSortColumns_.size() == 1)
model_->sort(column, order);
model_->sort(currentSortColumns_, sortOrders());
}
void WAbstractItemView::setSortingEnabled(bool enabled)
......
sortIcon->setObjectName("sort");
sortIcon->setInline(false);
sortIcon->setStyleClass("Wt-tv-sh Wt-tv-sh-none");
if (currentSortColumn_ == column)
if (std::find(currentSortColumns_.cbegin(), currentSortColumns_.cend() ,column) != currentSortColumns_.cend())
sortIcon->setStyleClass(info.sortOrder == AscendingOrder
? "Wt-tv-sh Wt-tv-sh-up"
: "Wt-tv-sh Wt-tv-sh-down");
src/Wt/WTableView.C
if (ajaxMode())
canvas_->setWidth(canvas_->width().toPixels() - width);
if (start <= currentSortColumn_ && currentSortColumn_ <= end)
currentSortColumn_ = -1;
for(auto it = currentSortColumns_.cbegin(), end_it = currentSortColumns_.cend(); it != end_it; ++it)
{
if (start <= *it && *it <= end)
{
currentSortColumns_.clear();
break;
}
}
if (renderState_ < NeedRerenderHeader)
scheduleRerender(NeedRerenderHeader);
src/Wt/WTreeView.C
c->removeColumns(start, count);
}
if (start <= currentSortColumn_ && currentSortColumn_ <= end)
currentSortColumn_ = -1;
for(auto it = currentSortColumns_.cbegin(), end_it = currentSortColumns_.cend(); it != end_it; ++it)
{
if(start <= *it && *it <= end)
{
currentSortColumns_.clear();
break;
}
}
}
void WTreeView::modelRowsInserted(const WModelIndex& parent,
(1-1/2)