# HG changeset patch # User Chris Cannam # Date 1213027310 0 # Node ID a00902d5f0aba52cd5e32b0f3b171b1f9c2b7799 # Parent e37e446817202812a0d729c3f7aa5de3da91c070 * basics of data editing in data table view diff -r e37e44681720 -r a00902d5f0ab data/model/ModelDataTableModel.cpp --- 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(m_model)) { - return dataSparse(row, col); + return dataSparse(row, col, withUnit); } else if (dynamic_cast(m_model)) { - return dataSparse(row, col); + return dataSparse(row, col, withUnit); } return QVariant(); @@ -56,7 +58,7 @@ template 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(m_model)) { const SparseOneDimensionalModel::Point *cp = reinterpret_cast(point); @@ -102,10 +111,15 @@ const SparseTimeValueModel::Point *cp = reinterpret_cast(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(m_model)->getScaleUnits())); + } else { + return cp->value; + } } else return QVariant(); - case 2: + case 3: if (dynamic_cast(m_model)) { return QVariant(); } else if (dynamic_cast(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(m_model)) { + return setDataSparse(row, col, value); + } else if (dynamic_cast(m_model)) { + return setDataSparse(row, col, value); + } + + return false; +} + +template +bool +ModelDataTableModel::setDataSparse(int row, int col, QVariant value) +{ + size_t frame = m_rows[row]; + + typedef SparseModel ModelType; + typedef std::multiset + PointListType; + typedef typename ModelType::EditCommand EditCommandType; + + ModelType *sm = dynamic_cast(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(m_model)) { return QVariant(tr("Label")); } else if (dynamic_cast(m_model)) { return QVariant(tr("Value")); } - } else if (section == 2) { + } else if (section == 3) { if (dynamic_cast(m_model)) { return QVariant(tr("Label")); } @@ -175,12 +277,21 @@ if (!canHandleModelType(m_model)) return 0; if (dynamic_cast(m_model)) { - return 2; + return 3; } else if (dynamic_cast(m_model)) { - return 3; + return 4; } - return 1; + return 2; +} + +QModelIndex +ModelDataTableModel::getModelIndexForFrame(size_t frame) const +{ + std::vector::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() diff -r e37e44681720 -r a00902d5f0ab data/model/ModelDataTableModel.h --- a/data/model/ModelDataTableModel.h Mon Jun 09 16:01:22 2008 +0000 +++ b/data/model/ModelDataTableModel.h Mon Jun 09 16:01:50 2008 +0000 @@ -20,6 +20,8 @@ #include "Model.h" +class Command; + class ModelDataTableModel : public QAbstractItemModel { Q_OBJECT @@ -45,8 +47,14 @@ int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; + QModelIndex getModelIndexForFrame(size_t frame) const; + static bool canHandleModelType(Model *); +signals: + void frameSelected(size_t); + void executeCommand(Command *); + protected slots: void modelChanged(); void modelChanged(size_t, size_t); @@ -61,7 +69,10 @@ void rebuildRowVector(); template void rebuildRowVectorSparse(); - template QVariant dataSparse(int row, int col) const; + template QVariant dataSparse(int row, int col, + bool withUnit) const; + template bool setDataSparse(int row, int col, + QVariant value); }; #endif diff -r e37e44681720 -r a00902d5f0ab data/model/SparseModel.h --- a/data/model/SparseModel.h Mon Jun 09 16:01:22 2008 +0000 +++ b/data/model/SparseModel.h Mon Jun 09 16:01:50 2008 +0000 @@ -218,9 +218,9 @@ /** * If any points have been added or deleted, return this * command (so the caller can add it to the command history). - * Otherwise delete the command. + * Otherwise delete the command and return NULL. */ - virtual Command *finish(); + virtual EditCommand *finish(); protected: virtual void addCommand(Command *command, bool executeFirst); @@ -605,7 +605,7 @@ } template -Command * +typename SparseModel::EditCommand * SparseModel::EditCommand::finish() { if (!m_commands.empty()) {