changeset 422:4caa28a0a8a2

* sorting arbitrary columns in data editor
author Chris Cannam
date Thu, 12 Jun 2008 09:03:00 +0000
parents 397fe91dc8e0
children 6a96bff0bd59
files data/model/ModelDataTableModel.cpp data/model/ModelDataTableModel.h data/model/SparseModel.h data/model/SparseOneDimensionalModel.h data/model/SparseTimeValueModel.h data/model/TabularModel.h
diffstat 6 files changed, 124 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/data/model/ModelDataTableModel.cpp	Wed Jun 11 17:00:04 2008 +0000
+++ b/data/model/ModelDataTableModel.cpp	Thu Jun 12 09:03:00 2008 +0000
@@ -18,6 +18,7 @@
 #include "TabularModel.h"
 #include "Model.h"
 
+#include <map>
 #include <algorithm>
 #include <iostream>
 
@@ -122,9 +123,11 @@
 {
     std::cerr << "ModelDataTableModel::sort(" << column << ", " << sortOrder
               << ")" << std::endl;
+    if (m_sortColumn != column) {
+        m_sort.clear();
+    }
     m_sortColumn = column;
     m_sortOrdering = sortOrder;
-    m_sort.clear();
     emit layoutChanged();
 }
 
@@ -157,8 +160,15 @@
     if (m_sort.empty()) {
         resort();
     }
-    if (row < 0 || row >= m_sort.size()) return 0;
-    return m_sort[row];
+    int result = 0;
+    if (row >= 0 && row < m_sort.size()) {
+        result = m_sort[row];
+    }
+    if (m_sortOrdering == Qt::DescendingOrder) {
+        result = rowCount() - result - 1;
+    }
+
+    return result;
 }
 
 int
@@ -171,17 +181,91 @@
             return rowCount() - row - 1;
         }
     }
-//!!! need the reverse of this
+
     if (m_sort.empty()) {
         resort();
     }
-    if (row < 0 || row >= m_sort.size()) return 0;
-    return m_sort[row];
+
+    int result = 0;
+    if (row >= 0 && row < m_sort.size()) {
+        if (m_sortOrdering == Qt::AscendingOrder) {
+            result = m_rsort[row];
+        } else {
+            result = m_rsort[rowCount() - row - 1];
+        }
+    }
+
+    return result;
 }
 
 void
 ModelDataTableModel::resort()
 {
-    
+    bool numeric = (m_model->getSortType(m_sortColumn) ==
+                    TabularModel::SortNumeric);
+
+    m_sort.clear();
+    m_rsort.clear();
+
+    if (numeric) resortNumeric();
+    else resortAlphabetical();
+
+    std::map<int, int> tmp;
+
+    // rsort maps from sorted row number to original row number
+
+    for (int i = 0; i < m_rsort.size(); ++i) {
+        tmp[m_rsort[i]] = i;
+    }
+
+    // tmp now maps from original row number to sorted row number
+
+    for (std::map<int, int>::const_iterator i = tmp.begin(); i != tmp.end(); ++i) {
+        m_sort.push_back(i->second);
+    }
+
+    // and sort now maps from original row number to sorted row number
 }
 
+void
+ModelDataTableModel::resortNumeric()
+{
+    typedef std::multimap<double, int> MapType;
+
+    MapType rowMap;
+    int rows = m_model->getRowCount();
+
+    for (int i = 0; i < rows; ++i) {
+        QVariant value =
+            m_model->getData(i, m_sortColumn, TabularModel::SortRole);
+        rowMap.insert(MapType::value_type(value.toDouble(), i));
+    }
+
+    for (MapType::iterator i = rowMap.begin(); i != rowMap.end(); ++i) {
+        m_rsort.push_back(i->second);
+    }
+
+    // rsort now maps from sorted row number to original row number
+}
+
+void
+ModelDataTableModel::resortAlphabetical()
+{
+    typedef std::multimap<QString, int> MapType;
+
+    MapType rowMap;
+    int rows = m_model->getRowCount();
+
+    for (int i = 0; i < rows; ++i) {
+        QVariant value =
+            m_model->getData(i, m_sortColumn, TabularModel::SortRole);
+        rowMap.insert(MapType::value_type(value.toString(), i));
+    }
+
+    for (MapType::iterator i = rowMap.begin(); i != rowMap.end(); ++i) {
+        m_rsort.push_back(i->second);
+    }
+
+    // rsort now maps from sorted row number to original row number
+}
+
--- a/data/model/ModelDataTableModel.h	Wed Jun 11 17:00:04 2008 +0000
+++ b/data/model/ModelDataTableModel.h	Thu Jun 12 09:03:00 2008 +0000
@@ -67,9 +67,12 @@
     Qt::SortOrder m_sortOrdering;
     typedef std::vector<int> RowList;
     RowList m_sort;
+    RowList m_rsort;
     int getSorted(int row);
     int getUnsorted(int row);
     void resort();
+    void resortNumeric();
+    void resortAlphabetical();
 };
 
 #endif
--- a/data/model/SparseModel.h	Wed Jun 11 17:00:04 2008 +0000
+++ b/data/model/SparseModel.h	Thu Jun 12 09:03:00 2008 +0000
@@ -293,6 +293,7 @@
         return QVariant();
     }
     virtual bool isColumnTimeValue(int column) const { return true; }
+    virtual SortType getSortType(int column) const { return SortNumeric; }
     
 protected:
     size_t m_sampleRate;
--- a/data/model/SparseOneDimensionalModel.h	Wed Jun 11 17:00:04 2008 +0000
+++ b/data/model/SparseOneDimensionalModel.h	Thu Jun 12 09:03:00 2008 +0000
@@ -130,17 +130,20 @@
 
     virtual QVariant getData(int row, int column, int role) const
     {
-        if (role != Qt::EditRole && role != Qt::DisplayRole) return QVariant();
+        if (role != Qt::EditRole &&
+            role != Qt::DisplayRole &&
+            role != SortRole) return QVariant();
         PointListIterator i = getPointListIteratorForRow(row);
         if (i == m_points.end()) return QVariant();
 
         switch (column) {
         case 0: {
+            if (role == SortRole) return int(i->frame);
             RealTime rt = RealTime::frame2RealTime(i->frame, getSampleRate());
             return QVariant(rt.toText().c_str());
         }
-        case 1: return QVariant(int(i->frame));
-        case 2: return QVariant(i->label);
+        case 1: return int(i->frame);
+        case 2: return i->label;
         default: return QVariant();
         }
     }
@@ -149,6 +152,12 @@
     {
         return (column < 2); 
     }
+
+    virtual SortType getSortType(int column) const
+    {
+        if (column == 2) return SortAlphabetical;
+        return SortNumeric;
+    }
 };
 
 #endif
--- a/data/model/SparseTimeValueModel.h	Wed Jun 11 17:00:04 2008 +0000
+++ b/data/model/SparseTimeValueModel.h	Thu Jun 12 09:03:00 2008 +0000
@@ -120,18 +120,21 @@
 
     virtual QVariant getData(int row, int column, int role) const
     {
-        if (role != Qt::EditRole && role != Qt::DisplayRole) return QVariant();
+        if (role != Qt::EditRole && 
+            role != Qt::DisplayRole &&
+            role != SortRole) return QVariant();
         PointListIterator i = getPointListIteratorForRow(row);
         if (i == m_points.end()) return QVariant();
 
         switch (column) {
         case 0: {
+            if (role == SortRole) return int(i->frame);
             RealTime rt = RealTime::frame2RealTime(i->frame, getSampleRate());
             return rt.toText().c_str();
         }
         case 1: return int(i->frame);
         case 2:
-            if (role == Qt::EditRole) return i->value;
+            if (role == Qt::EditRole || role == SortRole) return i->value;
             else return QString("%1 %2").arg(i->value).arg(getScaleUnits());
         case 3: return i->label;
         default: return QVariant();
@@ -170,6 +173,12 @@
     {
         return (column < 2); 
     }
+
+    virtual SortType getSortType(int column) const
+    {
+        if (column == 3) return SortAlphabetical;
+        return SortNumeric;
+    }
 };
 
 
--- a/data/model/TabularModel.h	Wed Jun 11 17:00:04 2008 +0000
+++ b/data/model/TabularModel.h	Thu Jun 12 09:03:00 2008 +0000
@@ -38,13 +38,17 @@
     virtual int getColumnCount() const = 0;
 
     virtual QString getHeading(int column) const = 0;
+
+    enum { SortRole = Qt::UserRole };
+    enum SortType { SortNumeric, SortAlphabetical };
+
     virtual QVariant getData(int row, int column, int role) const = 0;
+    virtual bool isColumnTimeValue(int col) const = 0;
+    virtual SortType getSortType(int col) const = 0;
 
     virtual long getFrameForRow(int row) const = 0;
     virtual int getRowForFrame(long frame) const = 0;
 
-    virtual bool isColumnTimeValue(int col) const = 0;
-
     virtual bool isEditable() const { return false; }
     virtual Command *getSetDataCommand(int row, int column, const QVariant &, int role) const { return 0; }
 };