annotate data/model/ModelDataTableModel.cpp @ 558:1d7ebc05157e

* Some fairly simplistic code to set up layer type properties based on RDF data about feature types (both when running transforms and when importing features from RDF files).
author Chris Cannam
date Thu, 12 Feb 2009 15:26:43 +0000
parents ba7aaacb7211
children b1dc68507e46
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@454 36 connect(baseModel, SIGNAL(aboutToBeDeleted()),
Chris@454 37 this, SLOT(modelAboutToBeDeleted()));
Chris@413 38 }
Chris@413 39
Chris@413 40 ModelDataTableModel::~ModelDataTableModel()
Chris@413 41 {
Chris@413 42 }
Chris@413 43
Chris@413 44 QVariant
Chris@413 45 ModelDataTableModel::data(const QModelIndex &index, int role) const
Chris@413 46 {
Chris@454 47 if (!m_model) return QVariant();
Chris@424 48 if (role != Qt::EditRole && role != Qt::DisplayRole) return QVariant();
Chris@413 49 if (!index.isValid()) return QVariant();
Chris@420 50 return m_model->getData(getUnsorted(index.row()), index.column(), role);
Chris@413 51 }
Chris@413 52
Chris@413 53 bool
Chris@413 54 ModelDataTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
Chris@413 55 {
Chris@454 56 if (!m_model) return false;
Chris@420 57 if (!index.isValid()) return false;
Chris@421 58 Command *command = m_model->getSetDataCommand(getUnsorted(index.row()),
Chris@421 59 index.column(),
Chris@421 60 value, role);
Chris@420 61 if (command) {
Chris@427 62 emit addCommand(command);
Chris@420 63 return true;
Chris@420 64 } else {
Chris@416 65 return false;
Chris@416 66 }
Chris@413 67 }
Chris@413 68
Chris@427 69 bool
Chris@427 70 ModelDataTableModel::insertRow(int row, const QModelIndex &parent)
Chris@427 71 {
Chris@454 72 if (!m_model) return false;
Chris@427 73 if (parent.isValid()) return false;
Chris@427 74
Chris@427 75 emit beginInsertRows(parent, row, row);
Chris@427 76
Chris@427 77 Command *command = m_model->getInsertRowCommand(getUnsorted(row));
Chris@427 78
Chris@427 79 if (command) {
Chris@427 80 emit addCommand(command);
Chris@427 81 }
Chris@427 82
Chris@427 83 emit endInsertRows();
Chris@427 84
Chris@427 85 return (command ? true : false);
Chris@427 86 }
Chris@427 87
Chris@427 88 bool
Chris@427 89 ModelDataTableModel::removeRow(int row, const QModelIndex &parent)
Chris@427 90 {
Chris@454 91 if (!m_model) return false;
Chris@427 92 if (parent.isValid()) return false;
Chris@427 93
Chris@427 94 emit beginRemoveRows(parent, row, row);
Chris@427 95
Chris@427 96 Command *command = m_model->getRemoveRowCommand(getUnsorted(row));
Chris@427 97
Chris@427 98 if (command) {
Chris@427 99 emit addCommand(command);
Chris@427 100 }
Chris@427 101
Chris@427 102 emit endRemoveRows();
Chris@427 103
Chris@427 104 return (command ? true : false);
Chris@427 105 }
Chris@427 106
Chris@413 107 Qt::ItemFlags
Chris@413 108 ModelDataTableModel::flags(const QModelIndex &index) const
Chris@413 109 {
Chris@416 110 Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsEditable |
Chris@416 111 Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsSelectable;
Chris@416 112 return flags;
Chris@413 113 }
Chris@413 114
Chris@413 115 QVariant
Chris@413 116 ModelDataTableModel::headerData(int section, Qt::Orientation orientation, int role) const
Chris@413 117 {
Chris@454 118 if (!m_model) return QVariant();
Chris@454 119
Chris@425 120 if (orientation == Qt::Vertical && role == Qt::DisplayRole) {
Chris@425 121 return section + 1;
Chris@425 122 }
Chris@413 123 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
Chris@420 124 return m_model->getHeading(section);
Chris@425 125 }
Chris@413 126 return QVariant();
Chris@413 127 }
Chris@413 128
Chris@413 129 QModelIndex
Chris@413 130 ModelDataTableModel::index(int row, int column, const QModelIndex &parent) const
Chris@413 131 {
Chris@413 132 return createIndex(row, column, 0);
Chris@413 133 }
Chris@413 134
Chris@413 135 QModelIndex
Chris@413 136 ModelDataTableModel::parent(const QModelIndex &index) const
Chris@413 137 {
Chris@413 138 return QModelIndex();
Chris@413 139 }
Chris@413 140
Chris@413 141 int
Chris@413 142 ModelDataTableModel::rowCount(const QModelIndex &parent) const
Chris@413 143 {
Chris@454 144 if (!m_model) return 0;
Chris@413 145 if (parent.isValid()) return 0;
Chris@420 146 return m_model->getRowCount();
Chris@413 147 }
Chris@413 148
Chris@413 149 int
Chris@413 150 ModelDataTableModel::columnCount(const QModelIndex &parent) const
Chris@413 151 {
Chris@454 152 if (!m_model) return 0;
Chris@413 153 if (parent.isValid()) return 0;
Chris@420 154 return m_model->getColumnCount();
Chris@416 155 }
Chris@416 156
Chris@416 157 QModelIndex
Chris@416 158 ModelDataTableModel::getModelIndexForFrame(size_t frame) const
Chris@416 159 {
Chris@454 160 if (!m_model) return createIndex(0, 0);
Chris@420 161 int row = m_model->getRowForFrame(frame);
Chris@420 162 return createIndex(getSorted(row), 0, 0);
Chris@413 163 }
Chris@413 164
Chris@419 165 size_t
Chris@419 166 ModelDataTableModel::getFrameForModelIndex(const QModelIndex &index) const
Chris@419 167 {
Chris@454 168 if (!m_model) return 0;
Chris@420 169 return m_model->getFrameForRow(getUnsorted(index.row()));
Chris@420 170 }
Chris@420 171
Chris@420 172 void
Chris@420 173 ModelDataTableModel::sort(int column, Qt::SortOrder sortOrder)
Chris@420 174 {
Chris@437 175 // std::cerr << "ModelDataTableModel::sort(" << column << ", " << sortOrder
Chris@437 176 // << ")" << std::endl;
Chris@428 177 int prevCurrent = getCurrentRow();
Chris@422 178 if (m_sortColumn != column) {
Chris@428 179 clearSort();
Chris@422 180 }
Chris@420 181 m_sortColumn = column;
Chris@420 182 m_sortOrdering = sortOrder;
Chris@428 183 int current = getCurrentRow();
Chris@428 184 if (current != prevCurrent) {
Chris@437 185 // std::cerr << "Current row changed from " << prevCurrent << " to " << current << " for underlying row " << m_currentRow << std::endl;
Chris@428 186 emit currentChanged(createIndex(current, 0, 0));
Chris@428 187 }
Chris@420 188 emit layoutChanged();
Chris@419 189 }
Chris@419 190
Chris@413 191 void
Chris@413 192 ModelDataTableModel::modelChanged()
Chris@413 193 {
Chris@428 194 clearSort();
Chris@413 195 emit layoutChanged();
Chris@413 196 }
Chris@413 197
Chris@413 198 void
Chris@416 199 ModelDataTableModel::modelChanged(size_t f0, size_t f1)
Chris@416 200 {
Chris@420 201 //!!! inefficient
Chris@428 202 clearSort();
Chris@416 203 emit layoutChanged();
Chris@416 204 }
Chris@413 205
Chris@454 206 void
Chris@454 207 ModelDataTableModel::modelAboutToBeDeleted()
Chris@454 208 {
Chris@454 209 m_model = 0;
Chris@454 210 emit modelRemoved();
Chris@454 211 }
Chris@454 212
Chris@420 213 int
Chris@426 214 ModelDataTableModel::getSorted(int row) const
Chris@413 215 {
Chris@454 216 if (!m_model) return row;
Chris@454 217
Chris@420 218 if (m_model->isColumnTimeValue(m_sortColumn)) {
Chris@420 219 if (m_sortOrdering == Qt::AscendingOrder) {
Chris@420 220 return row;
Chris@420 221 } else {
Chris@420 222 return rowCount() - row - 1;
Chris@420 223 }
Chris@420 224 }
Chris@413 225
Chris@420 226 if (m_sort.empty()) {
Chris@420 227 resort();
Chris@413 228 }
Chris@422 229 int result = 0;
Chris@422 230 if (row >= 0 && row < m_sort.size()) {
Chris@422 231 result = m_sort[row];
Chris@422 232 }
Chris@422 233 if (m_sortOrdering == Qt::DescendingOrder) {
Chris@422 234 result = rowCount() - result - 1;
Chris@422 235 }
Chris@422 236
Chris@422 237 return result;
Chris@413 238 }
Chris@413 239
Chris@420 240 int
Chris@426 241 ModelDataTableModel::getUnsorted(int row) const
Chris@413 242 {
Chris@454 243 if (!m_model) return row;
Chris@454 244
Chris@420 245 if (m_model->isColumnTimeValue(m_sortColumn)) {
Chris@420 246 if (m_sortOrdering == Qt::AscendingOrder) {
Chris@420 247 return row;
Chris@420 248 } else {
Chris@420 249 return rowCount() - row - 1;
Chris@420 250 }
Chris@413 251 }
Chris@422 252
Chris@420 253 if (m_sort.empty()) {
Chris@420 254 resort();
Chris@420 255 }
Chris@422 256
Chris@422 257 int result = 0;
Chris@422 258 if (row >= 0 && row < m_sort.size()) {
Chris@422 259 if (m_sortOrdering == Qt::AscendingOrder) {
Chris@422 260 result = m_rsort[row];
Chris@422 261 } else {
Chris@422 262 result = m_rsort[rowCount() - row - 1];
Chris@422 263 }
Chris@422 264 }
Chris@422 265
Chris@422 266 return result;
Chris@413 267 }
Chris@413 268
Chris@420 269 void
Chris@426 270 ModelDataTableModel::resort() const
Chris@413 271 {
Chris@454 272 if (!m_model) return;
Chris@454 273
Chris@422 274 bool numeric = (m_model->getSortType(m_sortColumn) ==
Chris@422 275 TabularModel::SortNumeric);
Chris@422 276
Chris@422 277 m_sort.clear();
Chris@422 278 m_rsort.clear();
Chris@422 279
Chris@422 280 if (numeric) resortNumeric();
Chris@422 281 else resortAlphabetical();
Chris@422 282
Chris@422 283 std::map<int, int> tmp;
Chris@422 284
Chris@422 285 // rsort maps from sorted row number to original row number
Chris@422 286
Chris@422 287 for (int i = 0; i < m_rsort.size(); ++i) {
Chris@422 288 tmp[m_rsort[i]] = i;
Chris@422 289 }
Chris@422 290
Chris@422 291 // tmp now maps from original row number to sorted row number
Chris@422 292
Chris@422 293 for (std::map<int, int>::const_iterator i = tmp.begin(); i != tmp.end(); ++i) {
Chris@422 294 m_sort.push_back(i->second);
Chris@422 295 }
Chris@422 296
Chris@422 297 // and sort now maps from original row number to sorted row number
Chris@413 298 }
Chris@413 299
Chris@422 300 void
Chris@426 301 ModelDataTableModel::resortNumeric() const
Chris@422 302 {
Chris@454 303 if (!m_model) return;
Chris@454 304
Chris@422 305 typedef std::multimap<double, int> MapType;
Chris@422 306
Chris@422 307 MapType rowMap;
Chris@422 308 int rows = m_model->getRowCount();
Chris@422 309
Chris@422 310 for (int i = 0; i < rows; ++i) {
Chris@424 311 QVariant value = m_model->getData(i, m_sortColumn, TabularModel::SortRole);
Chris@422 312 rowMap.insert(MapType::value_type(value.toDouble(), i));
Chris@422 313 }
Chris@422 314
Chris@422 315 for (MapType::iterator i = rowMap.begin(); i != rowMap.end(); ++i) {
Chris@422 316 m_rsort.push_back(i->second);
Chris@422 317 }
Chris@422 318
Chris@422 319 // rsort now maps from sorted row number to original row number
Chris@422 320 }
Chris@422 321
Chris@422 322 void
Chris@426 323 ModelDataTableModel::resortAlphabetical() const
Chris@422 324 {
Chris@454 325 if (!m_model) return;
Chris@454 326
Chris@422 327 typedef std::multimap<QString, int> MapType;
Chris@422 328
Chris@422 329 MapType rowMap;
Chris@422 330 int rows = m_model->getRowCount();
Chris@422 331
Chris@422 332 for (int i = 0; i < rows; ++i) {
Chris@422 333 QVariant value =
Chris@422 334 m_model->getData(i, m_sortColumn, TabularModel::SortRole);
Chris@422 335 rowMap.insert(MapType::value_type(value.toString(), i));
Chris@422 336 }
Chris@422 337
Chris@422 338 for (MapType::iterator i = rowMap.begin(); i != rowMap.end(); ++i) {
Chris@422 339 m_rsort.push_back(i->second);
Chris@422 340 }
Chris@422 341
Chris@422 342 // rsort now maps from sorted row number to original row number
Chris@422 343 }
Chris@422 344
Chris@428 345 int
Chris@428 346 ModelDataTableModel::getCurrentRow()
Chris@428 347 {
Chris@428 348 return getSorted(m_currentRow);
Chris@428 349 }
Chris@428 350
Chris@428 351 void
Chris@428 352 ModelDataTableModel::setCurrentRow(int row)
Chris@428 353 {
Chris@428 354 m_currentRow = getUnsorted(row);
Chris@428 355 }
Chris@428 356
Chris@428 357 void
Chris@428 358 ModelDataTableModel::clearSort()
Chris@428 359 {
Chris@428 360 // int prevCurrent = getCurrentRow();
Chris@428 361 m_sort.clear();
Chris@428 362 // int current = getCurrentRow(); //!!! no -- not until the sort criteria have changed
Chris@428 363 // if (current != prevCurrent) {
Chris@428 364 // std::cerr << "Current row changed from " << prevCurrent << " to " << current << " for underlying row " << m_currentRow << std::endl;
Chris@428 365 // emit currentRowChanged(createIndex(current, 0, 0));
Chris@428 366 // }
Chris@428 367 }
Chris@428 368
Chris@428 369