svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2008 QMUL. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "ModelDataTableModel.h" 00017 00018 #include "TabularModel.h" 00019 #include "Model.h" 00020 00021 #include <map> 00022 #include <algorithm> 00023 #include <iostream> 00024 00025 ModelDataTableModel::ModelDataTableModel(TabularModel *m) : 00026 m_model(m), 00027 m_sortColumn(0), 00028 m_sortOrdering(Qt::AscendingOrder), 00029 m_currentRow(0) 00030 { 00031 Model *baseModel = dynamic_cast<Model *>(m); 00032 00033 connect(baseModel, SIGNAL(modelChanged()), this, SLOT(modelChanged())); 00034 connect(baseModel, SIGNAL(modelChangedWithin(int, int)), 00035 this, SLOT(modelChangedWithin(int, int))); 00036 connect(baseModel, SIGNAL(aboutToBeDeleted()), 00037 this, SLOT(modelAboutToBeDeleted())); 00038 } 00039 00040 ModelDataTableModel::~ModelDataTableModel() 00041 { 00042 } 00043 00044 QVariant 00045 ModelDataTableModel::data(const QModelIndex &index, int role) const 00046 { 00047 if (!m_model) return QVariant(); 00048 if (role != Qt::EditRole && role != Qt::DisplayRole) return QVariant(); 00049 if (!index.isValid()) return QVariant(); 00050 return m_model->getData(getUnsorted(index.row()), index.column(), role); 00051 } 00052 00053 bool 00054 ModelDataTableModel::setData(const QModelIndex &index, const QVariant &value, int role) 00055 { 00056 if (!m_model) return false; 00057 if (!index.isValid()) return false; 00058 Command *command = m_model->getSetDataCommand(getUnsorted(index.row()), 00059 index.column(), 00060 value, role); 00061 if (command) { 00062 emit addCommand(command); 00063 return true; 00064 } else { 00065 return false; 00066 } 00067 } 00068 00069 bool 00070 ModelDataTableModel::insertRow(int row, const QModelIndex &parent) 00071 { 00072 if (!m_model) return false; 00073 if (parent.isValid()) return false; 00074 00075 emit beginInsertRows(parent, row, row); 00076 00077 Command *command = m_model->getInsertRowCommand(getUnsorted(row)); 00078 00079 if (command) { 00080 emit addCommand(command); 00081 } 00082 00083 emit endInsertRows(); 00084 00085 return (command ? true : false); 00086 } 00087 00088 bool 00089 ModelDataTableModel::removeRow(int row, const QModelIndex &parent) 00090 { 00091 if (!m_model) return false; 00092 if (parent.isValid()) return false; 00093 00094 emit beginRemoveRows(parent, row, row); 00095 00096 Command *command = m_model->getRemoveRowCommand(getUnsorted(row)); 00097 00098 if (command) { 00099 emit addCommand(command); 00100 } 00101 00102 emit endRemoveRows(); 00103 00104 return (command ? true : false); 00105 } 00106 00107 Qt::ItemFlags 00108 ModelDataTableModel::flags(const QModelIndex &) const 00109 { 00110 Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsEditable | 00111 Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsSelectable; 00112 return flags; 00113 } 00114 00115 QVariant 00116 ModelDataTableModel::headerData(int section, Qt::Orientation orientation, int role) const 00117 { 00118 if (!m_model) return QVariant(); 00119 00120 if (orientation == Qt::Vertical && role == Qt::DisplayRole) { 00121 return section + 1; 00122 } 00123 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { 00124 return m_model->getHeading(section); 00125 } 00126 return QVariant(); 00127 } 00128 00129 QModelIndex 00130 ModelDataTableModel::index(int row, int column, const QModelIndex &) const 00131 { 00132 return createIndex(row, column, (void *)0); 00133 } 00134 00135 QModelIndex 00136 ModelDataTableModel::parent(const QModelIndex &) const 00137 { 00138 return QModelIndex(); 00139 } 00140 00141 int 00142 ModelDataTableModel::rowCount(const QModelIndex &parent) const 00143 { 00144 if (!m_model) return 0; 00145 if (parent.isValid()) return 0; 00146 return m_model->getRowCount(); 00147 } 00148 00149 int 00150 ModelDataTableModel::columnCount(const QModelIndex &parent) const 00151 { 00152 if (!m_model) return 0; 00153 if (parent.isValid()) return 0; 00154 return m_model->getColumnCount(); 00155 } 00156 00157 QModelIndex 00158 ModelDataTableModel::getModelIndexForFrame(int frame) const 00159 { 00160 if (!m_model) return createIndex(0, 0); 00161 int row = m_model->getRowForFrame(frame); 00162 return createIndex(getSorted(row), 0, (void *)0); 00163 } 00164 00165 int 00166 ModelDataTableModel::getFrameForModelIndex(const QModelIndex &index) const 00167 { 00168 if (!m_model) return 0; 00169 return m_model->getFrameForRow(getUnsorted(index.row())); 00170 } 00171 00172 QModelIndex 00173 ModelDataTableModel::findText(QString text) const 00174 { 00175 if (text == "") return QModelIndex(); 00176 int rows = rowCount(); 00177 int cols = columnCount(); 00178 int current = getCurrentRow(); 00179 for (int row = 1; row <= rows; ++row) { 00180 int wrapped = (row + current) % rows; 00181 for (int col = 0; col < cols; ++col) { 00182 if (m_model->getSortType(col) != TabularModel::SortAlphabetical) { 00183 continue; 00184 } 00185 QString cell = m_model->getData(getUnsorted(wrapped), col, 00186 Qt::DisplayRole).toString(); 00187 if (cell.contains(text, Qt::CaseInsensitive)) { 00188 return createIndex(wrapped, col); 00189 } 00190 } 00191 } 00192 return QModelIndex(); 00193 } 00194 00195 void 00196 ModelDataTableModel::sort(int column, Qt::SortOrder sortOrder) 00197 { 00198 // SVDEBUG << "ModelDataTableModel::sort(" << column << ", " << sortOrder 00199 // << ")" << endl; 00200 int prevCurrent = getCurrentRow(); 00201 if (m_sortColumn != column) { 00202 clearSort(); 00203 } 00204 m_sortColumn = column; 00205 m_sortOrdering = sortOrder; 00206 int current = getCurrentRow(); 00207 if (current != prevCurrent) { 00208 // cerr << "Current row changed from " << prevCurrent << " to " << current << " for underlying row " << m_currentRow << endl; 00209 emit currentChanged(createIndex(current, 0, (void *)0)); 00210 } 00211 emit layoutChanged(); 00212 } 00213 00214 void 00215 ModelDataTableModel::modelChanged() 00216 { 00217 clearSort(); 00218 emit layoutChanged(); 00219 } 00220 00221 void 00222 ModelDataTableModel::modelChangedWithin(int, int) 00223 { 00225 clearSort(); 00226 emit layoutChanged(); 00227 } 00228 00229 void 00230 ModelDataTableModel::modelAboutToBeDeleted() 00231 { 00232 m_model = 0; 00233 emit modelRemoved(); 00234 } 00235 00236 int 00237 ModelDataTableModel::getSorted(int row) const 00238 { 00239 if (!m_model) return row; 00240 00241 if (m_model->isColumnTimeValue(m_sortColumn)) { 00242 if (m_sortOrdering == Qt::AscendingOrder) { 00243 return row; 00244 } else { 00245 return rowCount() - row - 1; 00246 } 00247 } 00248 00249 if (m_sort.empty()) { 00250 resort(); 00251 } 00252 int result = 0; 00253 if (row >= 0 && row < (int)m_sort.size()) { 00254 result = m_sort[row]; 00255 } 00256 if (m_sortOrdering == Qt::DescendingOrder) { 00257 result = rowCount() - result - 1; 00258 } 00259 00260 return result; 00261 } 00262 00263 int 00264 ModelDataTableModel::getUnsorted(int row) const 00265 { 00266 if (!m_model) return row; 00267 00268 if (m_model->isColumnTimeValue(m_sortColumn)) { 00269 if (m_sortOrdering == Qt::AscendingOrder) { 00270 return row; 00271 } else { 00272 return rowCount() - row - 1; 00273 } 00274 } 00275 00276 if (m_sort.empty()) { 00277 resort(); 00278 } 00279 00280 int result = 0; 00281 if (row >= 0 && row < (int)m_sort.size()) { 00282 if (m_sortOrdering == Qt::AscendingOrder) { 00283 result = m_rsort[row]; 00284 } else { 00285 result = m_rsort[rowCount() - row - 1]; 00286 } 00287 } 00288 00289 return result; 00290 } 00291 00292 void 00293 ModelDataTableModel::resort() const 00294 { 00295 if (!m_model) return; 00296 00297 bool numeric = (m_model->getSortType(m_sortColumn) == 00298 TabularModel::SortNumeric); 00299 00300 // cerr << "resort: numeric == " << numeric << endl; 00301 00302 m_sort.clear(); 00303 m_rsort.clear(); 00304 00305 if (numeric) resortNumeric(); 00306 else resortAlphabetical(); 00307 00308 std::map<int, int> tmp; 00309 00310 // rsort maps from sorted row number to original row number 00311 00312 for (int i = 0; i < (int)m_rsort.size(); ++i) { 00313 tmp[m_rsort[i]] = i; 00314 } 00315 00316 // tmp now maps from original row number to sorted row number 00317 00318 for (std::map<int, int>::const_iterator i = tmp.begin(); i != tmp.end(); ++i) { 00319 m_sort.push_back(i->second); 00320 } 00321 00322 // and sort now maps from original row number to sorted row number 00323 } 00324 00325 void 00326 ModelDataTableModel::resortNumeric() const 00327 { 00328 if (!m_model) return; 00329 00330 typedef std::multimap<double, int> MapType; 00331 00332 MapType rowMap; 00333 int rows = m_model->getRowCount(); 00334 00335 for (int i = 0; i < rows; ++i) { 00336 QVariant value = m_model->getData(i, m_sortColumn, TabularModel::SortRole); 00337 rowMap.insert(MapType::value_type(value.toDouble(), i)); 00338 } 00339 00340 for (MapType::iterator i = rowMap.begin(); i != rowMap.end(); ++i) { 00341 // cerr << "resortNumeric: " << i->second << ": " << i->first << endl; 00342 m_rsort.push_back(i->second); 00343 } 00344 00345 // rsort now maps from sorted row number to original row number 00346 } 00347 00348 void 00349 ModelDataTableModel::resortAlphabetical() const 00350 { 00351 if (!m_model) return; 00352 00353 typedef std::multimap<QString, int> MapType; 00354 00355 MapType rowMap; 00356 int rows = m_model->getRowCount(); 00357 00358 for (int i = 0; i < rows; ++i) { 00359 QVariant value = 00360 m_model->getData(i, m_sortColumn, TabularModel::SortRole); 00361 rowMap.insert(MapType::value_type(value.toString(), i)); 00362 } 00363 00364 for (MapType::iterator i = rowMap.begin(); i != rowMap.end(); ++i) { 00365 // cerr << "resortAlphabetical: " << i->second << ": " << i->first << endl; 00366 m_rsort.push_back(i->second); 00367 } 00368 00369 // rsort now maps from sorted row number to original row number 00370 } 00371 00372 int 00373 ModelDataTableModel::getCurrentRow() const 00374 { 00375 return getSorted(m_currentRow); 00376 } 00377 00378 void 00379 ModelDataTableModel::setCurrentRow(int row) 00380 { 00381 m_currentRow = getUnsorted(row); 00382 } 00383 00384 void 00385 ModelDataTableModel::clearSort() 00386 { 00387 // int prevCurrent = getCurrentRow(); 00388 m_sort.clear(); 00389 // int current = getCurrentRow(); //!!! no -- not until the sort criteria have changed 00390 // if (current != prevCurrent) { 00391 // cerr << "Current row changed from " << prevCurrent << " to " << current << " for underlying row " << m_currentRow << endl; 00392 // emit currentRowChanged(createIndex(current, 0, 0)); 00393 // } 00394 } 00395 00396