Feature #4380 » 0001-Add-support-for-multiple-column-sort-in-TableView.patch
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,
|