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
483 483
   */
484 484
  virtual void sort(int column, SortOrder order = AscendingOrder);
485 485

  
486
  /*! \brief Sorts the model according to a particular columns.
487
  *
488
  * If the model supports sorting, then it should emit the
489
  * layoutAboutToBeChanged() signal, rearrange its items, and
490
  * afterwards emit the layoutChanged() signal.
491
  *
492
  * \sa layoutAboutToBeChanged(), layoutChanged()
493
  */
494
  virtual void sort(std::vector<int> const &columns, std::vector<SortOrder> const &orders);
495

  
486 496
  /*! \brief Expands a column.
487 497
   *
488 498
   * Expands a column. This may only be called by a view when the
src/Wt/WAbstractItemModel.C
112 112
void WAbstractItemModel::sort(int column, SortOrder order)
113 113
{ }
114 114

  
115
void WAbstractItemModel::sort(std::vector<int> const & columns, std::vector<SortOrder> const & orders)
116
{}
117

  
115 118
void WAbstractItemModel::expandColumn(int column)
116 119
{ }
117 120

  
src/Wt/WAbstractItemView
286 286
   */
287 287
  void sortByColumn(int column, SortOrder order);
288 288

  
289
  /*! \brief Sorts the data according to a columns.
290
   *
291
   * Sorts the data according to data in columns \p columns and sort
292
   * orders \p orders.
293
   *
294
   *
295
   * \sa WAbstractItemModel::sort()
296
   */
297
  void sortByColumns(std::vector<int> const & columns, std::vector<SortOrder> const &order);
298

  
299
  /*! \brief Add/remove the colum for actual sorting.
300
   *
301
   * Sorts the data according to data in column \p column and sort
302
   * order \p order.
303
   *
304
   *
305
   * \sa WAbstractItemModel::sort()
306
   */
307
  void modifySortByColumn(int column, SortOrder order, bool append);
308

  
289 309
  /*! \brief Returns the current sorting columm.
290 310
   *
291 311
   * \sa sortByColumn(), sortOrder()
......
298 318
   */
299 319
  SortOrder sortOrder() const;
300 320

  
321
  /*! \brief Returns the current sorting order.
322
  *
323
  * \sa sortByColumn(), sortColumn(), sortByColumns()
324
  */
325
  std::vector<SortOrder> sortOrders() const;
326

  
301 327
  /*! \brief Enables or disables sorting for all columns.
302 328
   *
303 329
   * Enable or disable sorting by the user on all columns.
......
990 1016
  WSignalMapper<WModelIndex, WMouseEvent> *clickedMapper_;
991 1017

  
992 1018
  mutable std::vector<ColumnInfo> columns_;
993
  int currentSortColumn_;
1019
  //int currentSortColumn_;
1020
  std::vector<int> currentSortColumns_;
994 1021

  
995 1022
  bool dragEnabled_, dropsEnabled_;
996 1023
  WWidget *dragWidget_;
......
1150 1177
  void handleHeaderMouseUp(int columnid, WMouseEvent event);
1151 1178
  void handleHeaderClicked(int columnid, WMouseEvent event);
1152 1179
  void handleHeaderDblClicked(int columnid, WMouseEvent event);
1153
  void toggleSortColumn(int columnid);
1180
  void toggleSortColumn(int columnid, bool AppendRemove);
1154 1181
  void updateColumnWidth(int columnId, int width);
1155 1182

  
1156 1183
  virtual WContainerWidget* headerContainer() = 0;
src/Wt/WAbstractItemView.C
214 214
  : WCompositeWidget(parent),
215 215
    impl_(new WContainerWidget()),
216 216
    renderState_(NeedRerender),
217
    currentSortColumn_(-1),
218 217
    dragEnabled_(false),
219 218
    dropsEnabled_(false),
220 219
    model_(0),
......
702 701
  ColumnInfo& info = columnInfo(column);
703 702

  
704 703
  if (sortEnabled_ && info.sorting)
705
    toggleSortColumn(columnid);
704
    toggleSortColumn(columnid, event.ctrlKey());
706 705

  
707 706
  headerClicked_.emit(column, event);
708 707
}
......
722 721
  headerMouseWentUp_.emit(columnById(columnid), event);
723 722
}
724 723

  
725
void WAbstractItemView::toggleSortColumn(int columnid)
724
void WAbstractItemView::toggleSortColumn(int columnid, bool appendRemove)
726 725
{
727 726
  int column = columnById(columnid);
727
  bool const column_exist = (std::find(currentSortColumns_.cbegin(), currentSortColumns_.cend(), column) != currentSortColumns_.cend());
728 728

  
729
  if (column != currentSortColumn_)
730
    sortByColumn(column, columnInfo(column).sortOrder);
729
  // Append/Remove should be handled separately
730
  if(appendRemove)
731
  {
732
	  SortOrder order = AscendingOrder;
733
	  // If the column is sorted, remove it
734
	  if(column_exist)
735
		  modifySortByColumn(column, (order = AscendingOrder), false);
736
	  // Otherwise add it
737
	  else
738
		  modifySortByColumn(column, (order = columnInfo(column).sortOrder), true);
739

  
740
	  // Backward compatibility
741
	  if(currentSortColumns_.size() == 1)
742
		  model_->sort(currentSortColumns_.front(), order);
743

  
744
	  model_->sort(currentSortColumns_, sortOrders());
745
  }
746
  // Changing sort order or complet new sorting
731 747
  else
732
    sortByColumn(column, columnInfo(column).sortOrder == AscendingOrder
733
		 ? DescendingOrder : AscendingOrder);
748
  {
749
	  if(!column_exist)
750
		  sortByColumn(column, columnInfo(column).sortOrder);
751
	  else
752
		  sortByColumn(column, columnInfo(column).sortOrder == AscendingOrder
753
			  ? DescendingOrder : AscendingOrder);
754
  }
755
}
756

  
757
void WAbstractItemView::sortByColumns(std::vector<int> const &columns, std::vector<SortOrder> const &orders)
758
{
759
	for(auto end = columns.size(), i = 0U; i < end; ++i)
760
		modifySortByColumn(columns.at(i), orders.at(i), true);
761

  
762
	model_->sort(currentSortColumns_, sortOrders());
763
}
764

  
765
void WAbstractItemView::modifySortByColumn(int column, SortOrder order, bool append)
766
{
767
	// Add new column for sorting
768
	if(append)
769
	{
770
		currentSortColumns_.push_back(column);
771
		WText* t = headerSortIconWidget(column);
772
		if(t)
773
		{
774
			t->setStyleClass(order == AscendingOrder
775
				? "Wt-tv-sh Wt-tv-sh-up" : "Wt-tv-sh Wt-tv-sh-down");
776
			columnInfo(column).sortOrder = order;
777
		}
778
	}
779
	else
780
	{
781
		currentSortColumns_.erase(std::find(currentSortColumns_.begin(), currentSortColumns_.end(), column));
782
		WText* t = headerSortIconWidget(column);
783
		if(t)
784
			t->setStyleClass("Wt-tv-sh Wt-tv-sh-none");
785
	}
786
	
734 787
}
735 788

  
736 789
int WAbstractItemView::sortColumn() const
737 790
{
738
  return currentSortColumn_;
791
  return currentSortColumns_.empty() ? -1 : currentSortColumns_.front();
739 792
}
740 793

  
741 794
SortOrder WAbstractItemView::sortOrder() const
742 795
{
743
  if (currentSortColumn_ >= 0
744
      && currentSortColumn_ < static_cast<int>(columns_.size()))
745
    return columns_[currentSortColumn_].sortOrder;
796
  if (!currentSortColumns_.empty() 
797
      && currentSortColumns_.front() < static_cast<int>(columns_.size()))
798
    return columns_[currentSortColumns_.front()].sortOrder;
746 799
  else
747 800
    return AscendingOrder;
748 801
}
749 802

  
803
std::vector<Wt::SortOrder> WAbstractItemView::sortOrders() const
804
{
805
	std::vector<Wt::SortOrder> ret;
806

  
807
	for(auto it = currentSortColumns_.cbegin(), end = currentSortColumns_.cend(); it != end; ++it)
808
		ret.push_back(columnInfo(*it).sortOrder);
809

  
810
	return ret;
811
}
812

  
750 813
int WAbstractItemView::columnById(int columnid) const
751 814
{
752 815
  for (unsigned i = 0; i < columns_.size(); ++i)
......
788 851

  
789 852
void WAbstractItemView::sortByColumn(int column, SortOrder order)
790 853
{
791
  if (currentSortColumn_ != -1) {
792
    WText* t = headerSortIconWidget(currentSortColumn_);
793
    if (t)
794
      t->setStyleClass("Wt-tv-sh Wt-tv-sh-none");
795
  }
854
  auto const it_column = std::find(currentSortColumns_.cbegin(), currentSortColumns_.cend(), column);
796 855

  
797
  currentSortColumn_ = column;
798
  columnInfo(column).sortOrder = order;
856
  // Column isn't in sorted columns, need to reset all the columns and add the new one
857
  if (it_column == currentSortColumns_.cend()) {
858
	for(auto it = currentSortColumns_.cbegin(), end = currentSortColumns_.cend(); it != end; ++it)
859
	{
860
		WText* t = headerSortIconWidget(*it);
861
		if(t)
862
			t->setStyleClass("Wt-tv-sh Wt-tv-sh-none");
863
	}
864
	currentSortColumns_.clear();
799 865

  
800
  if (renderState_ != NeedRerender) {
801
    WText* t = headerSortIconWidget(currentSortColumn_);
802
    if (t)
803
      t->setStyleClass(order == AscendingOrder
804
		       ? "Wt-tv-sh Wt-tv-sh-up" : "Wt-tv-sh Wt-tv-sh-down");
866
	// Add new column
867
	currentSortColumns_.push_back(column);
868
	columnInfo(column).sortOrder = order;
869
  }
870
  // Just change order
871
  else
872
  {
873
	  columnInfo(*it_column).sortOrder = order;
874
	  
875
	  if(renderState_ != NeedRerender)
876
	  {
877
		  WText* t = headerSortIconWidget(*it_column);
878
		  if(t)
879
			  t->setStyleClass(order == AscendingOrder
880
				  ? "Wt-tv-sh Wt-tv-sh-up" : "Wt-tv-sh Wt-tv-sh-down");
881
	  }
805 882
  }
806 883

  
807
  model_->sort(column, order);
884
  if(currentSortColumns_.size() == 1)
885
	model_->sort(column, order);
886
  
887
  model_->sort(currentSortColumns_, sortOrders());
808 888
}
809 889

  
810 890
void WAbstractItemView::setSortingEnabled(bool enabled)
......
1060 1140
    sortIcon->setObjectName("sort");
1061 1141
    sortIcon->setInline(false);
1062 1142
    sortIcon->setStyleClass("Wt-tv-sh Wt-tv-sh-none");
1063
    if (currentSortColumn_ == column)
1143

  
1144
    if (std::find(currentSortColumns_.cbegin(), currentSortColumns_.cend() ,column) != currentSortColumns_.cend())
1064 1145
      sortIcon->setStyleClass(info.sortOrder == AscendingOrder
1065 1146
			      ? "Wt-tv-sh Wt-tv-sh-up"
1066 1147
			      : "Wt-tv-sh Wt-tv-sh-down");
src/Wt/WTableView.C
1360 1360
  if (ajaxMode())
1361 1361
    canvas_->setWidth(canvas_->width().toPixels() - width);
1362 1362

  
1363
  if (start <= currentSortColumn_ && currentSortColumn_ <= end)
1364
    currentSortColumn_ = -1;
1363
  for(auto it = currentSortColumns_.cbegin(), end_it = currentSortColumns_.cend(); it != end_it; ++it)
1364
  {
1365
	  if (start <= *it && *it <= end)
1366
	  {
1367
		  currentSortColumns_.clear();
1368
		  break;
1365 1369

  
1370
	  }
1371
  }
1372
  
1366 1373
  if (renderState_ < NeedRerenderHeader)
1367 1374
    scheduleRerender(NeedRerenderHeader);
1368 1375

  
src/Wt/WTreeView.C
1941 1941
	c->removeColumns(start, count);
1942 1942
  }
1943 1943

  
1944
  if (start <= currentSortColumn_ && currentSortColumn_ <= end)
1945
    currentSortColumn_ = -1;
1944
  for(auto it = currentSortColumns_.cbegin(), end_it = currentSortColumns_.cend(); it != end_it; ++it)
1945
  {
1946
	  if(start <= *it && *it <= end)
1947
	  {
1948
		  currentSortColumns_.clear();
1949
		  break;
1950

  
1951
	  }
1952
  }
1946 1953
}
1947 1954

  
1948 1955
void WTreeView::modelRowsInserted(const WModelIndex& parent,
1949
- 
(1-1/2)