svcore  1.9
ModelDataTableModel.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2008 QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "ModelDataTableModel.h"
17 
18 #include "TabularModel.h"
19 #include "Model.h"
20 
21 #include <map>
22 #include <algorithm>
23 #include <iostream>
24 
26  m_model(m),
27  m_sortColumn(0),
28  m_sortOrdering(Qt::AscendingOrder),
29  m_currentRow(0)
30 {
31  Model *baseModel = dynamic_cast<Model *>(m);
32 
33  connect(baseModel, SIGNAL(modelChanged()), this, SLOT(modelChanged()));
34  connect(baseModel, SIGNAL(modelChangedWithin(int, int)),
35  this, SLOT(modelChangedWithin(int, int)));
36  connect(baseModel, SIGNAL(aboutToBeDeleted()),
37  this, SLOT(modelAboutToBeDeleted()));
38 }
39 
41 {
42 }
43 
44 QVariant
45 ModelDataTableModel::data(const QModelIndex &index, int role) const
46 {
47  if (!m_model) return QVariant();
48  if (role != Qt::EditRole && role != Qt::DisplayRole) return QVariant();
49  if (!index.isValid()) return QVariant();
50  return m_model->getData(getUnsorted(index.row()), index.column(), role);
51 }
52 
53 bool
54 ModelDataTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
55 {
56  if (!m_model) return false;
57  if (!index.isValid()) return false;
59  index.column(),
60  value, role);
61  if (command) {
62  emit addCommand(command);
63  return true;
64  } else {
65  return false;
66  }
67 }
68 
69 bool
70 ModelDataTableModel::insertRow(int row, const QModelIndex &parent)
71 {
72  if (!m_model) return false;
73  if (parent.isValid()) return false;
74 
75  emit beginInsertRows(parent, row, row);
76 
78 
79  if (command) {
80  emit addCommand(command);
81  }
82 
83  emit endInsertRows();
84 
85  return (command ? true : false);
86 }
87 
88 bool
89 ModelDataTableModel::removeRow(int row, const QModelIndex &parent)
90 {
91  if (!m_model) return false;
92  if (parent.isValid()) return false;
93 
94  emit beginRemoveRows(parent, row, row);
95 
97 
98  if (command) {
99  emit addCommand(command);
100  }
101 
102  emit endRemoveRows();
103 
104  return (command ? true : false);
105 }
106 
107 Qt::ItemFlags
108 ModelDataTableModel::flags(const QModelIndex &) const
109 {
110  Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsEditable |
111  Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsSelectable;
112  return flags;
113 }
114 
115 QVariant
116 ModelDataTableModel::headerData(int section, Qt::Orientation orientation, int role) const
117 {
118  if (!m_model) return QVariant();
119 
120  if (orientation == Qt::Vertical && role == Qt::DisplayRole) {
121  return section + 1;
122  }
123  if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
124  return m_model->getHeading(section);
125  }
126  return QVariant();
127 }
128 
129 QModelIndex
130 ModelDataTableModel::index(int row, int column, const QModelIndex &) const
131 {
132  return createIndex(row, column, (void *)0);
133 }
134 
135 QModelIndex
136 ModelDataTableModel::parent(const QModelIndex &) const
137 {
138  return QModelIndex();
139 }
140 
141 int
142 ModelDataTableModel::rowCount(const QModelIndex &parent) const
143 {
144  if (!m_model) return 0;
145  if (parent.isValid()) return 0;
146  return m_model->getRowCount();
147 }
148 
149 int
150 ModelDataTableModel::columnCount(const QModelIndex &parent) const
151 {
152  if (!m_model) return 0;
153  if (parent.isValid()) return 0;
154  return m_model->getColumnCount();
155 }
156 
157 QModelIndex
159 {
160  if (!m_model) return createIndex(0, 0);
161  int row = m_model->getRowForFrame(frame);
162  return createIndex(getSorted(row), 0, (void *)0);
163 }
164 
165 int
166 ModelDataTableModel::getFrameForModelIndex(const QModelIndex &index) const
167 {
168  if (!m_model) return 0;
169  return m_model->getFrameForRow(getUnsorted(index.row()));
170 }
171 
172 QModelIndex
173 ModelDataTableModel::findText(QString text) const
174 {
175  if (text == "") return QModelIndex();
176  int rows = rowCount();
177  int cols = columnCount();
178  int current = getCurrentRow();
179  for (int row = 1; row <= rows; ++row) {
180  int wrapped = (row + current) % rows;
181  for (int col = 0; col < cols; ++col) {
183  continue;
184  }
185  QString cell = m_model->getData(getUnsorted(wrapped), col,
186  Qt::DisplayRole).toString();
187  if (cell.contains(text, Qt::CaseInsensitive)) {
188  return createIndex(wrapped, col);
189  }
190  }
191  }
192  return QModelIndex();
193 }
194 
195 void
196 ModelDataTableModel::sort(int column, Qt::SortOrder sortOrder)
197 {
198 // SVDEBUG << "ModelDataTableModel::sort(" << column << ", " << sortOrder
199 // << ")" << endl;
200  int prevCurrent = getCurrentRow();
201  if (m_sortColumn != column) {
202  clearSort();
203  }
204  m_sortColumn = column;
205  m_sortOrdering = sortOrder;
206  int current = getCurrentRow();
207  if (current != prevCurrent) {
208 // cerr << "Current row changed from " << prevCurrent << " to " << current << " for underlying row " << m_currentRow << endl;
209  emit currentChanged(createIndex(current, 0, (void *)0));
210  }
211  emit layoutChanged();
212 }
213 
214 void
216 {
217  clearSort();
218  emit layoutChanged();
219 }
220 
221 void
223 {
225  clearSort();
226  emit layoutChanged();
227 }
228 
229 void
231 {
232  m_model = 0;
233  emit modelRemoved();
234 }
235 
236 int
238 {
239  if (!m_model) return row;
240 
242  if (m_sortOrdering == Qt::AscendingOrder) {
243  return row;
244  } else {
245  return rowCount() - row - 1;
246  }
247  }
248 
249  if (m_sort.empty()) {
250  resort();
251  }
252  int result = 0;
253  if (row >= 0 && row < (int)m_sort.size()) {
254  result = m_sort[row];
255  }
256  if (m_sortOrdering == Qt::DescendingOrder) {
257  result = rowCount() - result - 1;
258  }
259 
260  return result;
261 }
262 
263 int
265 {
266  if (!m_model) return row;
267 
269  if (m_sortOrdering == Qt::AscendingOrder) {
270  return row;
271  } else {
272  return rowCount() - row - 1;
273  }
274  }
275 
276  if (m_sort.empty()) {
277  resort();
278  }
279 
280  int result = 0;
281  if (row >= 0 && row < (int)m_sort.size()) {
282  if (m_sortOrdering == Qt::AscendingOrder) {
283  result = m_rsort[row];
284  } else {
285  result = m_rsort[rowCount() - row - 1];
286  }
287  }
288 
289  return result;
290 }
291 
292 void
294 {
295  if (!m_model) return;
296 
297  bool numeric = (m_model->getSortType(m_sortColumn) ==
299 
300 // cerr << "resort: numeric == " << numeric << endl;
301 
302  m_sort.clear();
303  m_rsort.clear();
304 
305  if (numeric) resortNumeric();
306  else resortAlphabetical();
307 
308  std::map<int, int> tmp;
309 
310  // rsort maps from sorted row number to original row number
311 
312  for (int i = 0; i < (int)m_rsort.size(); ++i) {
313  tmp[m_rsort[i]] = i;
314  }
315 
316  // tmp now maps from original row number to sorted row number
317 
318  for (std::map<int, int>::const_iterator i = tmp.begin(); i != tmp.end(); ++i) {
319  m_sort.push_back(i->second);
320  }
321 
322  // and sort now maps from original row number to sorted row number
323 }
324 
325 void
327 {
328  if (!m_model) return;
329 
330  typedef std::multimap<double, int> MapType;
331 
332  MapType rowMap;
333  int rows = m_model->getRowCount();
334 
335  for (int i = 0; i < rows; ++i) {
336  QVariant value = m_model->getData(i, m_sortColumn, TabularModel::SortRole);
337  rowMap.insert(MapType::value_type(value.toDouble(), i));
338  }
339 
340  for (MapType::iterator i = rowMap.begin(); i != rowMap.end(); ++i) {
341 // cerr << "resortNumeric: " << i->second << ": " << i->first << endl;
342  m_rsort.push_back(i->second);
343  }
344 
345  // rsort now maps from sorted row number to original row number
346 }
347 
348 void
350 {
351  if (!m_model) return;
352 
353  typedef std::multimap<QString, int> MapType;
354 
355  MapType rowMap;
356  int rows = m_model->getRowCount();
357 
358  for (int i = 0; i < rows; ++i) {
359  QVariant value =
361  rowMap.insert(MapType::value_type(value.toString(), i));
362  }
363 
364  for (MapType::iterator i = rowMap.begin(); i != rowMap.end(); ++i) {
365 // cerr << "resortAlphabetical: " << i->second << ": " << i->first << endl;
366  m_rsort.push_back(i->second);
367  }
368 
369  // rsort now maps from sorted row number to original row number
370 }
371 
372 int
374 {
375  return getSorted(m_currentRow);
376 }
377 
378 void
380 {
381  m_currentRow = getUnsorted(row);
382 }
383 
384 void
386 {
387 // int prevCurrent = getCurrentRow();
388  m_sort.clear();
389 // int current = getCurrentRow(); //!!! no -- not until the sort criteria have changed
390 // if (current != prevCurrent) {
391 // cerr << "Current row changed from " << prevCurrent << " to " << current << " for underlying row " << m_currentRow << endl;
392 // emit currentRowChanged(createIndex(current, 0, 0));
393 // }
394 }
395 
396 
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const
int rowCount(const QModelIndex &parent=QModelIndex()) const
virtual Command * getSetDataCommand(int, int, const QVariant &, int)
Definition: TabularModel.h:55
void sort(int column, Qt::SortOrder order=Qt::AscendingOrder)
int getUnsorted(int row) const
bool removeRow(int row, const QModelIndex &parent=QModelIndex())
virtual int getRowForFrame(long frame) const =0
int getSorted(int row) const
virtual int getRowCount() const =0
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
Qt::ItemFlags flags(const QModelIndex &index) const
ModelDataTableModel(TabularModel *m)
virtual long getFrameForRow(int row) const =0
bool setData(const QModelIndex &index, const QVariant &value, int role)
QModelIndex getModelIndexForFrame(int frame) const
int columnCount(const QModelIndex &parent=QModelIndex()) const
bool insertRow(int row, const QModelIndex &parent=QModelIndex())
virtual SortType getSortType(int col) const =0
Model is the base class for all data models that represent any sort of data on a time scale based on ...
Definition: Model.h:35
TabularModel is an abstract base class for models that support direct access to data in a tabular for...
Definition: TabularModel.h:34
Qt::SortOrder m_sortOrdering
virtual QVariant getData(int row, int column, int role) const =0
virtual QString getHeading(int column) const =0
int getFrameForModelIndex(const QModelIndex &) const
QVariant data(const QModelIndex &index, int role) const
QModelIndex findText(QString text) const
QModelIndex parent(const QModelIndex &index) const
virtual Command * getRemoveRowCommand(int)
Definition: TabularModel.h:57
virtual Command * getInsertRowCommand(int)
Definition: TabularModel.h:56
void modelChangedWithin(int, int)
void addCommand(Command *)
virtual int getColumnCount() const =0
virtual bool isColumnTimeValue(int col) const =0
void currentChanged(const QModelIndex &)