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 }