File indexing completed on 2024-05-12 05:28:35
0001 ////////////////////////////////////////////////////////////////////////////// 0002 // listmodel.h 0003 // ------------------- 0004 // 0005 // SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr> 0006 // 0007 // SPDX-License-Identifier: MIT 0008 ////////////////////////////////////////////////////////////////////////////// 0009 0010 #pragma once 0011 0012 #include "breezeitemmodel.h" 0013 0014 #include <QList> 0015 #include <QSet> 0016 0017 #include <algorithm> 0018 0019 namespace Breeze 0020 { 0021 //! Job model. Stores job information for display in lists 0022 template<class T> 0023 class ListModel : public ItemModel 0024 { 0025 public: 0026 //! value type 0027 typedef T ValueType; 0028 0029 //! reference 0030 typedef T &Reference; 0031 0032 //! pointer 0033 typedef T *Pointer; 0034 0035 //! value list and iterators 0036 typedef QList<ValueType> List; 0037 typedef QListIterator<ValueType> ListIterator; 0038 typedef QMutableListIterator<ValueType> MutableListIterator; 0039 0040 //! list of vector 0041 // typedef QSet<ValueType> Set; 0042 0043 //! constructor 0044 ListModel(QObject *parent = nullptr) 0045 : ItemModel(parent) 0046 { 0047 } 0048 0049 //! destructor 0050 virtual ~ListModel() 0051 { 0052 } 0053 0054 //!@name methods reimplemented from base class 0055 //@{ 0056 0057 //! flags 0058 Qt::ItemFlags flags(const QModelIndex &index) const override 0059 { 0060 if (!index.isValid()) { 0061 return Qt::NoItemFlags; 0062 } 0063 return Qt::ItemIsEnabled | Qt::ItemIsSelectable; 0064 } 0065 0066 //! unique index for given row, column and parent index 0067 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override 0068 { 0069 // check if index is valid 0070 if (!hasIndex(row, column, parent)) { 0071 return QModelIndex(); 0072 } 0073 0074 // return invalid index if parent is valid 0075 if (parent.isValid()) { 0076 return QModelIndex(); 0077 } 0078 0079 // check against _values 0080 return (row < (int)_values.size()) ? createIndex(row, column) : QModelIndex(); 0081 } 0082 0083 //! index of parent 0084 QModelIndex parent(const QModelIndex &) const override 0085 { 0086 return QModelIndex(); 0087 } 0088 0089 //! number of rows below given index 0090 int rowCount(const QModelIndex &parent = QModelIndex()) const override 0091 { 0092 return parent.isValid() ? 0 : _values.size(); 0093 } 0094 0095 //@} 0096 0097 //!@name selection 0098 //@{ 0099 0100 //! clear internal list selected items 0101 virtual void clearSelectedIndexes() 0102 { 0103 _selection.clear(); 0104 } 0105 0106 //! store index internal selection state 0107 virtual void setIndexSelected(const QModelIndex &index, bool value) 0108 { 0109 if (value) { 0110 _selection.push_back(get(index)); 0111 } else { 0112 _selection.erase(std::remove(_selection.begin(), _selection.end(), get(index)), _selection.end()); 0113 } 0114 } 0115 0116 //! get list of internal selected items 0117 virtual QModelIndexList selectedIndexes() const 0118 { 0119 QModelIndexList out; 0120 for (typename List::const_iterator iter = _selection.begin(); iter != _selection.end(); iter++) { 0121 QModelIndex index(ListModel::index(*iter)); 0122 if (index.isValid()) { 0123 out.push_back(index); 0124 } 0125 } 0126 return out; 0127 } 0128 0129 //@} 0130 0131 //!@name interface 0132 //@{ 0133 0134 //! add value 0135 virtual void add(const ValueType &value) 0136 { 0137 emit layoutAboutToBeChanged(); 0138 _add(value); 0139 privateSort(); 0140 emit layoutChanged(); 0141 } 0142 0143 //! add values 0144 virtual void add(const List &values) 0145 { 0146 // check if not empty 0147 // this avoids sending useless signals 0148 if (values.empty()) { 0149 return; 0150 } 0151 0152 emit layoutAboutToBeChanged(); 0153 0154 for (typename List::const_iterator iter = values.begin(); iter != values.end(); iter++) { 0155 _add(*iter); 0156 } 0157 0158 privateSort(); 0159 emit layoutChanged(); 0160 } 0161 0162 //! insert values 0163 virtual void insert(const QModelIndex &index, const ValueType &value) 0164 { 0165 emit layoutAboutToBeChanged(); 0166 _insert(index, value); 0167 emit layoutChanged(); 0168 } 0169 0170 //! insert values 0171 virtual void insert(const QModelIndex &index, const List &values) 0172 { 0173 emit layoutAboutToBeChanged(); 0174 0175 // need to loop in reverse order so that the "values" ordering is preserved 0176 ListIterator iter(values); 0177 iter.toBack(); 0178 while (iter.hasPrevious()) { 0179 _insert(index, iter.previous()); 0180 } 0181 0182 emit layoutChanged(); 0183 } 0184 0185 //! insert values 0186 virtual void replace(const QModelIndex &index, const ValueType &value) 0187 { 0188 if (!index.isValid()) { 0189 add(value); 0190 } else { 0191 emit layoutAboutToBeChanged(); 0192 setIndexSelected(index, false); 0193 _values[index.row()] = value; 0194 setIndexSelected(index, true); 0195 emit layoutChanged(); 0196 } 0197 } 0198 0199 //! remove 0200 virtual void remove(const ValueType &value) 0201 { 0202 emit layoutAboutToBeChanged(); 0203 _remove(value); 0204 emit layoutChanged(); 0205 } 0206 0207 //! remove 0208 virtual void remove(const List &values) 0209 { 0210 // check if not empty 0211 // this avoids sending useless signals 0212 if (values.empty()) { 0213 return; 0214 } 0215 0216 emit layoutAboutToBeChanged(); 0217 for (typename List::const_iterator iter = values.begin(); iter != values.end(); iter++) { 0218 _remove(*iter); 0219 } 0220 emit layoutChanged(); 0221 } 0222 0223 //! clear 0224 virtual void clear() 0225 { 0226 set(List()); 0227 } 0228 0229 //! update values from list 0230 /*! 0231 values that are not found in current are removed 0232 new values are set to the end. 0233 This is slower than the "set" method, but the selection is not cleared in the process 0234 */ 0235 virtual void update(List values) 0236 { 0237 emit layoutAboutToBeChanged(); 0238 0239 // store values to be removed 0240 List removed_values; 0241 0242 // update values that are common to both lists 0243 for (typename List::iterator iter = _values.begin(); iter != _values.end(); iter++) { 0244 // see if iterator is in list 0245 typename List::iterator found_iter(std::find(values.begin(), values.end(), *iter)); 0246 if (found_iter == values.end()) { 0247 removed_values.push_back(*iter); 0248 } else { 0249 *iter = *found_iter; 0250 values.erase(found_iter); 0251 } 0252 } 0253 0254 // remove values that have not been found in new list 0255 for (typename List::const_iterator iter = removed_values.constBegin(); iter != removed_values.constEnd(); iter++) { 0256 _remove(*iter); 0257 } 0258 0259 // add remaining values 0260 for (typename List::const_iterator iter = values.constBegin(); iter != values.constEnd(); iter++) { 0261 _add(*iter); 0262 } 0263 0264 privateSort(); 0265 emit layoutChanged(); 0266 } 0267 0268 //! set all values 0269 virtual void set(const List &values) 0270 { 0271 emit layoutAboutToBeChanged(); 0272 _values = values; 0273 _selection.clear(); 0274 privateSort(); 0275 emit layoutChanged(); 0276 } 0277 0278 //! return all values 0279 const List &get(void) const 0280 { 0281 return _values; 0282 } 0283 0284 //! return value for given index 0285 virtual ValueType get(const QModelIndex &index) const 0286 { 0287 return (index.isValid() && index.row() < int(_values.size())) ? _values[index.row()] : ValueType(); 0288 } 0289 0290 //! return value for given index 0291 virtual ValueType &get(const QModelIndex &index) 0292 { 0293 Q_ASSERT(index.isValid() && index.row() < int(_values.size())); 0294 return _values[index.row()]; 0295 } 0296 0297 //! return all values 0298 List get(const QModelIndexList &indexes) const 0299 { 0300 List out; 0301 for (QModelIndexList::const_iterator iter = indexes.begin(); iter != indexes.end(); iter++) { 0302 if (iter->isValid() && iter->row() < int(_values.size())) { 0303 out.push_back(get(*iter)); 0304 } 0305 } 0306 return out; 0307 } 0308 0309 //! return index associated to a given value 0310 virtual QModelIndex index(const ValueType &value, int column = 0) const 0311 { 0312 for (int row = 0; row < _values.size(); ++row) { 0313 if (value == _values[row]) { 0314 return index(row, column); 0315 } 0316 } 0317 return QModelIndex(); 0318 } 0319 0320 //@} 0321 0322 //! return true if model contains given index 0323 virtual bool contains(const QModelIndex &index) const 0324 { 0325 return index.isValid() && index.row() < _values.size(); 0326 } 0327 0328 protected: 0329 //! return all values 0330 List &_get(void) 0331 { 0332 return _values; 0333 } 0334 0335 //! add, without update 0336 virtual void _add(const ValueType &value) 0337 { 0338 typename List::iterator iter = std::find(_values.begin(), _values.end(), value); 0339 if (iter == _values.end()) { 0340 _values.push_back(value); 0341 } else { 0342 *iter = value; 0343 } 0344 } 0345 0346 //! add, without update 0347 virtual void _insert(const QModelIndex &index, const ValueType &value) 0348 { 0349 if (!index.isValid()) { 0350 add(value); 0351 } 0352 int row = 0; 0353 typename List::iterator iter(_values.begin()); 0354 for (; iter != _values.end() && row != index.row(); iter++, row++) { } 0355 0356 _values.insert(iter, value); 0357 } 0358 0359 //! remove, without update 0360 virtual void _remove(const ValueType &value) 0361 { 0362 _values.erase(std::remove(_values.begin(), _values.end(), value), _values.end()); 0363 _selection.erase(std::remove(_selection.begin(), _selection.end(), value), _selection.end()); 0364 } 0365 0366 private: 0367 //! values 0368 List _values; 0369 0370 //! selection 0371 List _selection; 0372 }; 0373 }