annotate data/model/ModelDataTableModel.cpp @ 430:304fd0223fa6

* Add playback controls to data edit dialog * Make data edit dialog close properly when layer is removed from view * More fixes to playback tracking & selection model in data edit dialog * Remove edit button from data edit dialog for now
author Chris Cannam
date Wed, 18 Jun 2008 15:53:23 +0000
parents 3e1d190048f4
children 7226ebac8bd3
rev   line source
Chris@413 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@413 2
Chris@413 3 /*
Chris@413 4 Sonic Visualiser
Chris@413 5 An audio file viewer and annotation editor.
Chris@413 6 Centre for Digital Music, Queen Mary, University of London.
Chris@413 7 This file copyright 2008 QMUL.
Chris@413 8
Chris@413 9 This program is free software; you can redistribute it and/or
Chris@413 10 modify it under the terms of the GNU General Public License as
Chris@413 11 published by the Free Software Foundation; either version 2 of the
Chris@413 12 License, or (at your option) any later version. See the file
Chris@413 13 COPYING included with this distribution for more information.
Chris@413 14 */
Chris@413 15
Chris@413 16 #include "ModelDataTableModel.h"
Chris@413 17
Chris@420 18 #include "TabularModel.h"
Chris@420 19 #include "Model.h"
Chris@413 20
Chris@422 21 #include <map>
Chris@417 22 #include <algorithm>
Chris@420 23 #include <iostream>
Chris@417 24
Chris@420 25 ModelDataTableModel::ModelDataTableModel(TabularModel *m) :
Chris@421 26 m_model(m),
Chris@421 27 m_sortColumn(0),
Chris@428 28 m_sortOrdering(Qt::AscendingOrder),
Chris@428 29 m_currentRow(0)
Chris@413 30 {
Chris@420 31 Model *baseModel = dynamic_cast<Model *>(m);
Chris@420 32
Chris@420 33 connect(baseModel, SIGNAL(modelChanged()), this, SLOT(modelChanged()));
Chris@420 34 connect(baseModel, SIGNAL(modelChanged(size_t, size_t)),
Chris@413 35 this, SLOT(modelChanged(size_t, size_t)));
Chris@413 36 }
Chris@413 37
Chris@413 38 ModelDataTableModel::~ModelDataTableModel()
Chris@413 39 {
Chris@413 40 }
Chris@413 41
Chris@413 42 QVariant
Chris@413 43 ModelDataTableModel::data(const QModelIndex &index, int role) const
Chris@413 44 {
Chris@424 45 if (role != Qt::EditRole && role != Qt::DisplayRole) return QVariant();
Chris@413 46 if (!index.isValid()) return QVariant();
Chris@420 47 return m_model->getData(getUnsorted(index.row()), index.column(), role);
Chris@413 48 }
Chris@413 49
Chris@413 50 bool
Chris@413 51 ModelDataTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
Chris@413 52 {
Chris@420 53 if (!index.isValid()) return false;
Chris@421 54 Command *command = m_model->getSetDataCommand(getUnsorted(index.row()),
Chris@421 55 index.column(),
Chris@421 56 value, role);
Chris@420 57 if (command) {
Chris@427 58 emit addCommand(command);
Chris@420 59 return true;
Chris@420 60 } else {
Chris@416 61 return false;
Chris@416 62 }
Chris@413 63 }
Chris@413 64
Chris@427 65 bool
Chris@427 66 ModelDataTableModel::insertRow(int row, const QModelIndex &parent)
Chris@427 67 {
Chris@427 68 if (parent.isValid()) return false;
Chris@427 69
Chris@427 70 emit beginInsertRows(parent, row, row);
Chris@427 71
Chris@427 72 Command *command = m_model->getInsertRowCommand(getUnsorted(row));
Chris@427 73
Chris@427 74 if (command) {
Chris@427 75 emit addCommand(command);
Chris@427 76 }
Chris@427 77
Chris@427 78 emit endInsertRows();
Chris@427 79
Chris@427 80 return (command ? true : false);
Chris@427 81 }
Chris@427 82
Chris@427 83 bool
Chris@427 84 ModelDataTableModel::removeRow(int row, const QModelIndex &parent)
Chris@427 85 {
Chris@427 86 if (parent.isValid()) return false;
Chris@427 87
Chris@427 88 emit beginRemoveRows(parent, row, row);
Chris@427 89
Chris@427 90 Command *command = m_model->getRemoveRowCommand(getUnsorted(row));
Chris@427 91
Chris@427 92 if (command) {
Chris@427 93 emit addCommand(command);
Chris@427 94 }
Chris@427 95
Chris@427 96 emit endRemoveRows();
Chris@427 97
Chris@427 98 return (command ? true : false);
Chris@427 99 }
Chris@427 100
Chris@413 101 Qt::ItemFlags
Chris@413 102 ModelDataTableModel::flags(const QModelIndex &index) const
Chris@413 103 {
Chris@416 104 Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsEditable |
Chris@416 105 Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsSelectable;
Chris@416 106 return flags;
Chris@413 107 }
Chris@413 108
Chris@413 109 QVariant
Chris@413 110 ModelDataTableModel::headerData(int section, Qt::Orientation orientation, int role) const
Chris@413 111 {
Chris@425 112 if (orientation == Qt::Vertical && role == Qt::DisplayRole) {
Chris@425 113 return section + 1;
Chris@425 114 }
Chris@413 115 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
Chris@420 116 return m_model->getHeading(section);
Chris@425 117 }
Chris@413 118 return QVariant();
Chris@413 119 }
Chris@413 120
Chris@413 121 QModelIndex
Chris@413 122 ModelDataTableModel::index(int row, int column, const QModelIndex &parent) const
Chris@413 123 {
Chris@413 124 return createIndex(row, column, 0);
Chris@413 125 }
Chris@413 126
Chris@413 127 QModelIndex
Chris@413 128 ModelDataTableModel::parent(const QModelIndex &index) const
Chris@413 129 {
Chris@413 130 return QModelIndex();
Chris@413 131 }
Chris@413 132
Chris@413 133 int
Chris@413 134 ModelDataTableModel::rowCount(const QModelIndex &parent) const
Chris@413 135 {
Chris@413 136 if (parent.isValid()) return 0;
Chris@420 137 return m_model->getRowCount();
Chris@413 138 }
Chris@413 139
Chris@413 140 int
Chris@413 141 ModelDataTableModel::columnCount(const QModelIndex &parent) const
Chris@413 142 {
Chris@413 143 if (parent.isValid()) return 0;
Chris@420 144 return m_model->getColumnCount();
Chris@416 145 }
Chris@416 146
Chris@416 147 QModelIndex
Chris@416 148 ModelDataTableModel::getModelIndexForFrame(size_t frame) const
Chris@416 149 {
Chris@420 150 int row = m_model->getRowForFrame(frame);
Chris@420 151 return createIndex(getSorted(row), 0, 0);
Chris@413 152 }
Chris@413 153
Chris@419 154 size_t
Chris@419 155 ModelDataTableModel::getFrameForModelIndex(const QModelIndex &index) const
Chris@419 156 {
Chris@420 157 return m_model->getFrameForRow(getUnsorted(index.row()));
Chris@420 158 }
Chris@420 159
Chris@420 160 void
Chris@420 161 ModelDataTableModel::sort(int column, Qt::SortOrder sortOrder)
Chris@420 162 {
Chris@420 163 std::cerr << "ModelDataTableModel::sort(" << column << ", " << sortOrder
Chris@420 164 << ")" << std::endl;
Chris@428 165 int prevCurrent = getCurrentRow();
Chris@422 166 if (m_sortColumn != column) {
Chris@428 167 clearSort();
Chris@422 168 }
Chris@420 169 m_sortColumn = column;
Chris@420 170 m_sortOrdering = sortOrder;
Chris@428 171 int current = getCurrentRow();
Chris@428 172 if (current != prevCurrent) {
Chris@428 173 std::cerr << "Current row changed from " << prevCurrent << " to " << current << " for underlying row " << m_currentRow << std::endl;
Chris@428 174 emit currentChanged(createIndex(current, 0, 0));
Chris@428 175 }
Chris@420 176 emit layoutChanged();
Chris@419 177 }
Chris@419 178
Chris@413 179 void
Chris@413 180 ModelDataTableModel::modelChanged()
Chris@413 181 {
Chris@428 182 clearSort();
Chris@413 183 emit layoutChanged();
Chris@413 184 }
Chris@413 185
Chris@413 186 void
Chris@416 187 ModelDataTableModel::modelChanged(size_t f0, size_t f1)
Chris@416 188 {
Chris@420 189 //!!! inefficient
Chris@428 190 clearSort();
Chris@416 191 emit layoutChanged();
Chris@416 192 }
Chris@413 193
Chris@420 194 int
Chris@426 195 ModelDataTableModel::getSorted(int row) const
Chris@413 196 {
Chris@420 197 if (m_model->isColumnTimeValue(m_sortColumn)) {
Chris@420 198 if (m_sortOrdering == Qt::AscendingOrder) {
Chris@420 199 return row;
Chris@420 200 } else {
Chris@420 201 return rowCount() - row - 1;
Chris@420 202 }
Chris@420 203 }
Chris@413 204
Chris@420 205 if (m_sort.empty()) {
Chris@420 206 resort();
Chris@413 207 }
Chris@422 208 int result = 0;
Chris@422 209 if (row >= 0 && row < m_sort.size()) {
Chris@422 210 result = m_sort[row];
Chris@422 211 }
Chris@422 212 if (m_sortOrdering == Qt::DescendingOrder) {
Chris@422 213 result = rowCount() - result - 1;
Chris@422 214 }
Chris@422 215
Chris@422 216 return result;
Chris@413 217 }
Chris@413 218
Chris@420 219 int
Chris@426 220 ModelDataTableModel::getUnsorted(int row) const
Chris@413 221 {
Chris@420 222 if (m_model->isColumnTimeValue(m_sortColumn)) {
Chris@420 223 if (m_sortOrdering == Qt::AscendingOrder) {
Chris@420 224 return row;
Chris@420 225 } else {
Chris@420 226 return rowCount() - row - 1;
Chris@420 227 }
Chris@413 228 }
Chris@422 229
Chris@420 230 if (m_sort.empty()) {
Chris@420 231 resort();
Chris@420 232 }
Chris@422 233
Chris@422 234 int result = 0;
Chris@422 235 if (row >= 0 && row < m_sort.size()) {
Chris@422 236 if (m_sortOrdering == Qt::AscendingOrder) {
Chris@422 237 result = m_rsort[row];
Chris@422 238 } else {
Chris@422 239 result = m_rsort[rowCount() - row - 1];
Chris@422 240 }
Chris@422 241 }
Chris@422 242
Chris@422 243 return result;
Chris@413 244 }
Chris@413 245
Chris@420 246 void
Chris@426 247 ModelDataTableModel::resort() const
Chris@413 248 {
Chris@422 249 bool numeric = (m_model->getSortType(m_sortColumn) ==
Chris@422 250 TabularModel::SortNumeric);
Chris@422 251
Chris@422 252 m_sort.clear();
Chris@422 253 m_rsort.clear();
Chris@422 254
Chris@422 255 if (numeric) resortNumeric();
Chris@422 256 else resortAlphabetical();
Chris@422 257
Chris@422 258 std::map<int, int> tmp;
Chris@422 259
Chris@422 260 // rsort maps from sorted row number to original row number
Chris@422 261
Chris@422 262 for (int i = 0; i < m_rsort.size(); ++i) {
Chris@422 263 tmp[m_rsort[i]] = i;
Chris@422 264 }
Chris@422 265
Chris@422 266 // tmp now maps from original row number to sorted row number
Chris@422 267
Chris@422 268 for (std::map<int, int>::const_iterator i = tmp.begin(); i != tmp.end(); ++i) {
Chris@422 269 m_sort.push_back(i->second);
Chris@422 270 }
Chris@422 271
Chris@422 272 // and sort now maps from original row number to sorted row number
Chris@413 273 }
Chris@413 274
Chris@422 275 void
Chris@426 276 ModelDataTableModel::resortNumeric() const
Chris@422 277 {
Chris@422 278 typedef std::multimap<double, int> MapType;
Chris@422 279
Chris@422 280 MapType rowMap;
Chris@422 281 int rows = m_model->getRowCount();
Chris@422 282
Chris@422 283 for (int i = 0; i < rows; ++i) {
Chris@424 284 QVariant value = m_model->getData(i, m_sortColumn, TabularModel::SortRole);
Chris@422 285 rowMap.insert(MapType::value_type(value.toDouble(), i));
Chris@422 286 }
Chris@422 287
Chris@422 288 for (MapType::iterator i = rowMap.begin(); i != rowMap.end(); ++i) {
Chris@422 289 m_rsort.push_back(i->second);
Chris@422 290 }
Chris@422 291
Chris@422 292 // rsort now maps from sorted row number to original row number
Chris@422 293 }
Chris@422 294
Chris@422 295 void
Chris@426 296 ModelDataTableModel::resortAlphabetical() const
Chris@422 297 {
Chris@422 298 typedef std::multimap<QString, int> MapType;
Chris@422 299
Chris@422 300 MapType rowMap;
Chris@422 301 int rows = m_model->getRowCount();
Chris@422 302
Chris@422 303 for (int i = 0; i < rows; ++i) {
Chris@422 304 QVariant value =
Chris@422 305 m_model->getData(i, m_sortColumn, TabularModel::SortRole);
Chris@422 306 rowMap.insert(MapType::value_type(value.toString(), i));
Chris@422 307 }
Chris@422 308
Chris@422 309 for (MapType::iterator i = rowMap.begin(); i != rowMap.end(); ++i) {
Chris@422 310 m_rsort.push_back(i->second);
Chris@422 311 }
Chris@422 312
Chris@422 313 // rsort now maps from sorted row number to original row number
Chris@422 314 }
Chris@422 315
Chris@428 316 int
Chris@428 317 ModelDataTableModel::getCurrentRow()
Chris@428 318 {
Chris@428 319 return getSorted(m_currentRow);
Chris@428 320 }
Chris@428 321
Chris@428 322 void
Chris@428 323 ModelDataTableModel::setCurrentRow(int row)
Chris@428 324 {
Chris@428 325 m_currentRow = getUnsorted(row);
Chris@428 326 }
Chris@428 327
Chris@428 328 void
Chris@428 329 ModelDataTableModel::clearSort()
Chris@428 330 {
Chris@428 331 // int prevCurrent = getCurrentRow();
Chris@428 332 m_sort.clear();
Chris@428 333 // int current = getCurrentRow(); //!!! no -- not until the sort criteria have changed
Chris@428 334 // if (current != prevCurrent) {
Chris@428 335 // std::cerr << "Current row changed from " << prevCurrent << " to " << current << " for underlying row " << m_currentRow << std::endl;
Chris@428 336 // emit currentRowChanged(createIndex(current, 0, 0));
Chris@428 337 // }
Chris@428 338 }
Chris@428 339
Chris@428 340