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  auto model = ModelById::get(m);
32  if (model) {
33  connect(model.get(), SIGNAL(modelChanged(ModelId)),
34  this, SLOT(modelChanged(ModelId)));
35  connect(model.get(), SIGNAL(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)),
37  }
38 }
39 
41 {
42 }
43 
44 QVariant
45 ModelDataTableModel::data(const QModelIndex &index, int role) const
46 {
47  auto model = getTabularModel();
48  if (!model) return QVariant();
49  if (role != Qt::EditRole && role != Qt::DisplayRole) return QVariant();
50  if (!index.isValid()) return QVariant();
51  QVariant d = model->getData(getUnsorted(index.row()), index.column(), role);
52  return d;
53 }
54 
55 bool
56 ModelDataTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
57 {
58  auto model = getTabularModel();
59  if (!model) return false;
60  if (!index.isValid()) return false;
61  Command *command = model->getSetDataCommand(getUnsorted(index.row()),
62  index.column(),
63  value, role);
64  if (command) {
65  emit addCommand(command);
66  return true;
67  } else {
68  return false;
69  }
70 }
71 
72 bool
73 ModelDataTableModel::insertRow(int row, const QModelIndex &parent)
74 {
75  auto model = getTabularModel();
76  if (!model) return false;
77  if (parent.isValid()) return false;
78 
79  Command *command = model->getInsertRowCommand(getUnsorted(row));
80 
81  if (command) {
82  emit addCommand(command);
83  }
84 
85  return (command ? true : false);
86 }
87 
88 bool
89 ModelDataTableModel::removeRow(int row, const QModelIndex &parent)
90 {
91  auto model = getTabularModel();
92  if (!model) return false;
93  if (parent.isValid()) return false;
94 
95  Command *command = model->getRemoveRowCommand(getUnsorted(row));
96 
97  if (command) {
98  emit addCommand(command);
99  }
100 
101  return (command ? true : false);
102 }
103 
104 Qt::ItemFlags
105 ModelDataTableModel::flags(const QModelIndex &) const
106 {
107  Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsEditable |
108  Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsSelectable;
109  return flags;
110 }
111 
112 QVariant
113 ModelDataTableModel::headerData(int section, Qt::Orientation orientation, int role) const
114 {
115  auto model = getTabularModel();
116  if (!model) return QVariant();
117 
118  if (orientation == Qt::Vertical && role == Qt::DisplayRole) {
119  return section + 1;
120  }
121  if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
122  return model->getHeading(section);
123  }
124  return QVariant();
125 }
126 
127 QModelIndex
128 ModelDataTableModel::index(int row, int column, const QModelIndex &) const
129 {
130  return createIndex(row, column, (void *)nullptr);
131 }
132 
133 QModelIndex
134 ModelDataTableModel::parent(const QModelIndex &) const
135 {
136  return QModelIndex();
137 }
138 
139 int
140 ModelDataTableModel::rowCount(const QModelIndex &parent) const
141 {
142  auto model = getTabularModel();
143  if (!model) return 0;
144  if (parent.isValid()) return 0;
145  int count = model->getRowCount();
146  return count;
147 }
148 
149 int
150 ModelDataTableModel::columnCount(const QModelIndex &parent) const
151 {
152  auto model = getTabularModel();
153  if (!model) return 0;
154  if (parent.isValid()) return 0;
155  return model->getColumnCount();
156 }
157 
158 QModelIndex
160 {
161  auto model = getTabularModel();
162  if (!model) return createIndex(0, 0);
163  int row = model->getRowForFrame(frame);
164  return createIndex(getSorted(row), 0, (void *)nullptr);
165 }
166 
169 {
170  auto model = getTabularModel();
171  if (!model) return 0;
172  return model->getFrameForRow(getUnsorted(index.row()));
173 }
174 
175 QModelIndex
176 ModelDataTableModel::findText(QString text) const
177 {
178  auto model = getTabularModel();
179  if (!model) return QModelIndex();
180  if (text == "") return QModelIndex();
181  int rows = rowCount();
182  int cols = columnCount();
183  int current = getCurrentRow();
184  for (int row = 1; row <= rows; ++row) {
185  int wrapped = (row + current) % rows;
186  for (int col = 0; col < cols; ++col) {
187  if (model->getSortType(col) != TabularModel::SortAlphabetical) {
188  continue;
189  }
190  QString cell = model->getData(getUnsorted(wrapped), col,
191  Qt::DisplayRole).toString();
192  if (cell.contains(text, Qt::CaseInsensitive)) {
193  return createIndex(wrapped, col);
194  }
195  }
196  }
197  return QModelIndex();
198 }
199 
200 void
201 ModelDataTableModel::sort(int column, Qt::SortOrder sortOrder)
202 {
203 // SVDEBUG << "ModelDataTableModel::sort(" << column << ", " << sortOrder
204 // << ")" << endl;
205  int prevCurrent = getCurrentRow();
206  if (m_sortColumn != column) {
207  clearSort();
208  }
209  m_sortColumn = column;
210  m_sortOrdering = sortOrder;
211  int current = getCurrentRow();
212  if (current != prevCurrent) {
213 // cerr << "Current row changed from " << prevCurrent << " to " << current << " for underlying row " << m_currentRow << endl;
214  emit currentChanged(createIndex(current, 0, (void *)nullptr));
215  }
216  emit layoutChanged();
217 }
218 
219 void
221 {
222  SVDEBUG << "ModelDataTableModel::modelChanged" << endl;
223  QModelIndex ix0;
224  QModelIndex ix1;
225  if (rowCount() > 0) {
226  ix0 = createIndex(0, 0);
227  int lastCol = columnCount() - 1;
228  if (lastCol < 0) lastCol = 0;
229  ix1 = createIndex(rowCount(), lastCol);
230  }
231  SVDEBUG << "emitting dataChanged from row " << ix0.row() << " to " << ix1.row() << endl;
232  emit dataChanged(ix0, ix1);
233  clearSort();
234  emit layoutChanged();
235 }
236 
237 void
239 {
240  SVDEBUG << "ModelDataTableModel::modelChangedWithin(" << f0 << "," << f1 << ")" << endl;
241  QModelIndex ix0 = getModelIndexForFrame(f0);
242  QModelIndex ix1 = getModelIndexForFrame(f1);
243  int row0 = ix0.row();
244  int row1 = ix1.row();
245  if (row0 > 0) {
246  ix0 = createIndex(row0 - 1, ix0.column(), (void *)nullptr);
247  }
248  if (row1 + 1 < rowCount()) {
249  ix1 = createIndex(row1 + 1, ix1.column(), (void *)nullptr);
250  }
251  SVDEBUG << "emitting dataChanged from row " << ix0.row() << " to " << ix1.row() << endl;
252  emit dataChanged(ix0, ix1);
253  clearSort();
254  emit layoutChanged();
255 }
256 
257 int
259 {
260  auto model = getTabularModel();
261  if (!model) return row;
262 
263  if (model->isColumnTimeValue(m_sortColumn)) {
264  if (m_sortOrdering == Qt::AscendingOrder) {
265  return row;
266  } else {
267  return rowCount() - row - 1;
268  }
269  }
270 
271  if (m_sort.empty()) {
272  resort();
273  }
274  int result = 0;
275  if (row >= 0 && row < (int)m_sort.size()) {
276  result = m_sort[row];
277  }
278  if (m_sortOrdering == Qt::DescendingOrder) {
279  result = rowCount() - result - 1;
280  }
281 
282  return result;
283 }
284 
285 int
287 {
288  auto model = getTabularModel();
289  if (!model) return row;
290 
291  if (model->isColumnTimeValue(m_sortColumn)) {
292  if (m_sortOrdering == Qt::AscendingOrder) {
293  return row;
294  } else {
295  return rowCount() - row - 1;
296  }
297  }
298 
299  if (m_sort.empty()) {
300  resort();
301  }
302 
303  int result = 0;
304  if (row >= 0 && row < (int)m_sort.size()) {
305  if (m_sortOrdering == Qt::AscendingOrder) {
306  result = m_rsort[row];
307  } else {
308  result = m_rsort[rowCount() - row - 1];
309  }
310  }
311 
312  return result;
313 }
314 
315 void
317 {
318  auto model = getTabularModel();
319  if (!model) return;
320 
321  bool numeric = (model->getSortType(m_sortColumn) ==
323 
324 // cerr << "resort: numeric == " << numeric << endl;
325 
326  m_sort.clear();
327  m_rsort.clear();
328 
329  if (numeric) resortNumeric();
330  else resortAlphabetical();
331 
332  std::map<int, int> tmp;
333 
334  // rsort maps from sorted row number to original row number
335 
336  for (int i = 0; i < (int)m_rsort.size(); ++i) {
337  tmp[m_rsort[i]] = i;
338  }
339 
340  // tmp now maps from original row number to sorted row number
341 
342  for (std::map<int, int>::const_iterator i = tmp.begin(); i != tmp.end(); ++i) {
343  m_sort.push_back(i->second);
344  }
345 
346  // and sort now maps from original row number to sorted row number
347 }
348 
349 void
351 {
352  auto model = getTabularModel();
353  if (!model) return;
354 
355  typedef std::multimap<double, int> MapType;
356 
357  MapType rowMap;
358  int rows = model->getRowCount();
359 
360  for (int i = 0; i < rows; ++i) {
361  QVariant value = model->getData(i, m_sortColumn, TabularModel::SortRole);
362  rowMap.insert(MapType::value_type(value.toDouble(), i));
363  }
364 
365  for (MapType::iterator i = rowMap.begin(); i != rowMap.end(); ++i) {
366 // cerr << "resortNumeric: " << i->second << ": " << i->first << endl;
367  m_rsort.push_back(i->second);
368  }
369 
370  // rsort now maps from sorted row number to original row number
371 }
372 
373 void
375 {
376  auto model = getTabularModel();
377  if (!model) return;
378 
379  typedef std::multimap<QString, int> MapType;
380 
381  MapType rowMap;
382  int rows = model->getRowCount();
383 
384  for (int i = 0; i < rows; ++i) {
385  QVariant value =
386  model->getData(i, m_sortColumn, TabularModel::SortRole);
387  rowMap.insert(MapType::value_type(value.toString(), i));
388  }
389 
390  for (MapType::iterator i = rowMap.begin(); i != rowMap.end(); ++i) {
391 // cerr << "resortAlphabetical: " << i->second << ": " << i->first << endl;
392  m_rsort.push_back(i->second);
393  }
394 
395  // rsort now maps from sorted row number to original row number
396 }
397 
398 int
400 {
401  return getSorted(m_currentRow);
402 }
403 
404 void
406 {
407  m_currentRow = getUnsorted(row);
408 }
409 
410 void
412 {
413 // int prevCurrent = getCurrentRow();
414  m_sort.clear();
415 // int current = getCurrentRow(); //!!! no -- not until the sort criteria have changed
416 // if (current != prevCurrent) {
417 // cerr << "Current row changed from " << prevCurrent << " to " << current << " for underlying row " << m_currentRow << endl;
418 // emit currentRowChanged(createIndex(current, 0, 0));
419 // }
420 }
421 
422 
void modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)
ModelDataTableModel(ModelId modelId)
int getUnsorted(int row) const
bool removeRow(int row, const QModelIndex &parent=QModelIndex())
int64_t sv_frame_t
Frame index, the unit of our time axis.
Definition: BaseTypes.h:31
QModelIndex parent(const QModelIndex &index) const override
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
QModelIndex getModelIndexForFrame(sv_frame_t frame) const
int rowCount(const QModelIndex &parent=QModelIndex()) const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
int getSorted(int row) const
void resortAlphabetical() const
bool insertRow(int row, const QModelIndex &parent=QModelIndex())
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role) const override
Qt::SortOrder m_sortOrdering
bool setData(const QModelIndex &index, const QVariant &value, int role) override
std::shared_ptr< TabularModel > getTabularModel() const
Qt::ItemFlags flags(const QModelIndex &index) const override
#define SVDEBUG
Definition: Debug.h:106
sv_frame_t getFrameForModelIndex(const QModelIndex &) const
void addCommand(Command *)
QModelIndex findText(QString text) const
void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
Definition: ById.h:115
void currentChanged(const QModelIndex &)
static std::shared_ptr< Item > get(Id id)
Definition: ById.h:251