diff data/model/ModelDataTableModel.cpp @ 416:a00902d5f0ab

* basics of data editing in data table view
author Chris Cannam
date Mon, 09 Jun 2008 16:01:50 +0000
parents 0b274e1aaf10
children 12b7bf0c3915
line wrap: on
line diff
--- a/data/model/ModelDataTableModel.cpp	Mon Jun 09 16:01:22 2008 +0000
+++ b/data/model/ModelDataTableModel.cpp	Mon Jun 09 16:01:50 2008 +0000
@@ -35,10 +35,12 @@
 QVariant
 ModelDataTableModel::data(const QModelIndex &index, int role) const
 {
-    if (role != Qt::DisplayRole) {
+    if (role != Qt::DisplayRole && role != Qt::EditRole) {
         return QVariant();
     }
 
+    bool withUnit = (role == Qt::DisplayRole);
+
     if (!index.isValid()) return QVariant();
 
     int row = index.row(), col = index.column();
@@ -46,9 +48,9 @@
     if (row < 0 || row >= m_rows.size()) return QVariant();
 
     if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) {
-        return dataSparse<SparseOneDimensionalModel::Point>(row, col);
+        return dataSparse<SparseOneDimensionalModel::Point>(row, col, withUnit);
     } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) {
-        return dataSparse<SparseTimeValueModel::Point>(row, col);
+        return dataSparse<SparseTimeValueModel::Point>(row, col, withUnit);
     }
 
     return QVariant();
@@ -56,7 +58,7 @@
 
 template <typename PointType>
 QVariant
-ModelDataTableModel::dataSparse(int row, int col) const
+ModelDataTableModel::dataSparse(int row, int col, bool withUnit) const
 {
     size_t frame = m_rows[row];
     
@@ -89,10 +91,17 @@
         switch (col) {
 
         case 0:
+        {
+            RealTime rt = RealTime::frame2RealTime(frame, m_model->getSampleRate());
+            std::cerr << "Returning time " << rt << std::endl;
+            return QVariant(rt.toText().c_str());
+        }
+
+        case 1:
             std::cerr << "Returning frame " << frame << std::endl;
             return QVariant(frame); //!!! RealTime
 
-        case 1:
+        case 2:
             if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) {
                 const SparseOneDimensionalModel::Point *cp = 
                     reinterpret_cast<const SparseOneDimensionalModel::Point *>(point);
@@ -102,10 +111,15 @@
                 const SparseTimeValueModel::Point *cp = 
                     reinterpret_cast<const SparseTimeValueModel::Point *>(point);
                 std::cerr << "Returning value " << cp->value << std::endl;
-                return cp->value;
+                if (withUnit) {
+                    return QVariant(QString("%1 %2").arg(cp->value)
+                                    .arg(dynamic_cast<const SparseTimeValueModel *>(m_model)->getScaleUnits()));
+                } else {
+                    return cp->value;
+                }
             } else return QVariant();
 
-        case 2: 
+        case 3: 
             if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) {
                 return QVariant();
             } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) {
@@ -120,27 +134,115 @@
 bool
 ModelDataTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
 {
+    if (role != Qt::EditRole) {
+        std::cerr << "setData: ignoring role " << role << std::endl;
+        return false;
+    }
+
+    //!!! see comment about disgustuality of this whole process, in
+    //dataSparse above
+
+    if (!index.isValid()) return false;
+
+    int row = index.row(), col = index.column();
+
+    if (row < 0 || row >= m_rows.size()) return false;
+
+    if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) {
+        return setDataSparse<SparseOneDimensionalModel::Point>(row, col, value);
+    } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) {
+        return setDataSparse<SparseTimeValueModel::Point>(row, col, value);
+    }
+
+    return false;
+}
+
+template <typename PointType>
+bool
+ModelDataTableModel::setDataSparse(int row, int col, QVariant value)
+{
+    size_t frame = m_rows[row];
+    
+    typedef SparseModel<PointType> ModelType;
+    typedef std::multiset<PointType, typename PointType::OrderComparator> 
+        PointListType;
+    typedef typename ModelType::EditCommand EditCommandType;
+
+    ModelType *sm = dynamic_cast<const ModelType *>(m_model);
+    const PointListType &points = sm->getPoints(frame);
+
+    // it is possible to have more than one point at the same frame
+
+    int indexAtFrame = 0;
+    int ri = row;
+    while (ri > 0 && m_rows[ri-1] == m_rows[row]) { --ri; ++indexAtFrame; }
+
+    for (typename PointListType::const_iterator i = points.begin();
+         i != points.end(); ++i) {
+
+        const PointType *point = &(*i);
+        if (point->frame < frame) continue;
+        if (point->frame > frame) return false;
+        if (indexAtFrame > 0) { --indexAtFrame; continue; }
+
+        switch (col) {
+
+        case 0:
+        {
+/*
+            RealTime rt = RealTime::frame2RealTime(frame, m_model->getSampleRate());
+            std::cerr << "Returning time " << rt << std::endl;
+            return QVariant(rt.toText().c_str());
+*/
+        }
+
+        case 1:
+        {
+            EditCommandType *command = 
+                new EditCommandType(sm, tr("Edit point time"));
+            PointType newPoint(*point);
+            newPoint.frame = value.toInt(); //!!! check validity
+            command->deletePoint(*point);
+            command->addPoint(newPoint);
+            command = command->finish();
+            if (command) emit executeCommand(command);
+            return true;
+        }
+//            std::cerr << "Returning frame " << frame << std::endl;
+//            return QVariant(frame); //!!! RealTime
+
+        case 2:
+            break;
+
+        case 3: 
+            break;
+        }
+    }
+
     return false;
 }
 
 Qt::ItemFlags
 ModelDataTableModel::flags(const QModelIndex &index) const
 {
-    return Qt::ItemFlags();
+    Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsEditable |
+        Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsSelectable;
+    return flags;
 }
 
 QVariant
 ModelDataTableModel::headerData(int section, Qt::Orientation orientation, int role) const
 {
     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
-        if (section == 0) return QVariant(tr("Frame"));
-        else if (section == 1) {
+        if (section == 0) return QVariant(tr("Time"));
+        if (section == 1) return QVariant(tr("Frame"));
+        else if (section == 2) {
             if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) {
                 return QVariant(tr("Label"));
             } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) {
                 return QVariant(tr("Value"));
             }
-        } else if (section == 2) {
+        } else if (section == 3) {
             if (dynamic_cast<const SparseTimeValueModel *>(m_model)) {
                 return QVariant(tr("Label"));
             }
@@ -175,12 +277,21 @@
     if (!canHandleModelType(m_model)) return 0;
 
     if (dynamic_cast<SparseOneDimensionalModel *>(m_model)) {
-        return 2;
+        return 3;
     } else if (dynamic_cast<SparseTimeValueModel *>(m_model)) {
-        return 3;
+        return 4;
     }
 
-    return 1;
+    return 2;
+}
+
+QModelIndex 
+ModelDataTableModel::getModelIndexForFrame(size_t frame) const
+{
+    std::vector<size_t>::const_iterator i =
+        std::lower_bound(m_rows.begin(), m_rows.end(), frame);
+    size_t dist = std::distance(m_rows.begin(), i);
+    return createIndex(dist, 0, 0);
 }
 
 void
@@ -191,8 +302,13 @@
 }
 
 void 
-ModelDataTableModel::modelChanged(size_t, size_t)
-{}
+ModelDataTableModel::modelChanged(size_t f0, size_t f1)
+{
+    std::cerr << "ModelDataTableModel::modelChanged(" << f0 << "," << f1 << ")" << std::endl;
+    //!!! highly inefficient
+    rebuildRowVector();
+    emit layoutChanged();
+}
 
 void
 ModelDataTableModel::rebuildRowVector()