2 * Copyright (C) 2012, 2013 Canonical, Ltd.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18#include "qlimitproxymodelqml.h"
23QLimitProxyModelQML::QLimitProxyModelQML(QObject *parent)
24 : QIdentityProxyModel(parent)
26 , m_sourceInserting(false)
27 , m_sourceRemoving(false)
28 , m_dataChangedBegin(-1)
29 , m_dataChangedEnd(-1)
31 connect(this, &QLimitProxyModelQML::modelReset, this, &QLimitProxyModelQML::countChanged);
32 connect(this, &QLimitProxyModelQML::rowsInserted, this, &QLimitProxyModelQML::countChanged);
33 connect(this, &QLimitProxyModelQML::rowsRemoved, this, &QLimitProxyModelQML::countChanged);
36QHash<int, QByteArray> QLimitProxyModelQML::roleNames() const
38 return sourceModel() ? sourceModel()->roleNames() : QHash<int, QByteArray>();
42QLimitProxyModelQML::setModel(QAbstractItemModel *itemModel)
44 if (itemModel != sourceModel()) {
45 if (sourceModel() != nullptr) {
46 sourceModel()->disconnect(this);
49 setSourceModel(itemModel);
51 if (sourceModel() != nullptr) {
52 // Disconnect the QIdentityProxyModel handling for rows removed/added...
53 disconnect(sourceModel(), &QAbstractItemModel::rowsAboutToBeInserted, this, nullptr);
54 disconnect(sourceModel(), &QAbstractItemModel::rowsInserted, this, nullptr);
55 disconnect(sourceModel(), &QAbstractItemModel::rowsAboutToBeRemoved, this, nullptr);
56 disconnect(sourceModel(), &QAbstractItemModel::rowsRemoved, this, nullptr);
58 // ... and use our own
59 connect(sourceModel(), &QAbstractItemModel::rowsAboutToBeInserted,
60 this, &QLimitProxyModelQML::sourceRowsAboutToBeInserted);
61 connect(sourceModel(), &QAbstractItemModel::rowsInserted,
62 this, &QLimitProxyModelQML::sourceRowsInserted);
63 connect(sourceModel(), &QAbstractItemModel::rowsAboutToBeRemoved,
64 this, &QLimitProxyModelQML::sourceRowsAboutToBeRemoved);
65 connect(sourceModel(), &QAbstractItemModel::rowsRemoved,
66 this, &QLimitProxyModelQML::sourceRowsRemoved);
68 Q_EMIT modelChanged();
73QLimitProxyModelQML::rowCount(const QModelIndex &parent) const
75 if (parent.isValid()) // We are not a tree
78 const int unlimitedCount = QIdentityProxyModel::rowCount(parent);
79 return m_limit < 0 ? unlimitedCount : qMin(m_limit, unlimitedCount);
83QLimitProxyModelQML::limit() const
89QLimitProxyModelQML::setLimit(int limit)
91 if (limit != m_limit) {
92 bool inserting = false;
93 bool removing = false;
94 const int oldCount = rowCount();
95 const int unlimitedCount = QIdentityProxyModel::rowCount();
97 if (limit < oldCount) {
99 beginRemoveRows(QModelIndex(), limit, oldCount - 1);
101 } else if (limit < 0) {
102 if (m_limit < unlimitedCount) {
104 beginInsertRows(QModelIndex(), m_limit, unlimitedCount - 1);
107 if (limit > m_limit && unlimitedCount > m_limit) {
109 beginInsertRows(QModelIndex(), m_limit, qMin(limit, unlimitedCount) - 1);
110 } else if (limit < m_limit && limit < oldCount) {
112 beginRemoveRows(QModelIndex(), limit, oldCount - 1);
120 } else if (removing) {
124 Q_EMIT limitChanged();
129QLimitProxyModelQML::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
132 beginInsertRows(mapFromSource(parent), start, end);
133 m_sourceInserting = true;
134 } else if (start < m_limit) {
135 const int nSourceAddedItems = end - start + 1;
136 const int currentCount = QIdentityProxyModel::rowCount();
137 if (currentCount + nSourceAddedItems <= m_limit) {
138 // After Inserting items we will be under the limit
139 // so just proceed with the insertion normally
140 beginInsertRows(mapFromSource(parent), start, end);
141 m_sourceInserting = true;
142 } else if (currentCount >= m_limit) {
143 // We are already over the limit so to our users we are not adding items, just
144 // changing it's data, i.e we had something like
147 // after inserting (let's say three 'F' at position 1) we will have
149 // so we just need to signal a dataChanged from 1 to 4
150 m_dataChangedBegin = start;
151 m_dataChangedEnd = m_limit - 1;
152 } else { // currentCount < m_limit && currentCount + nSourceAddedItems > m_limit
153 // We have less items than the limit but after adding them we will be over
154 // To our users this means we need to insert some items and change the
155 // data of some others, i.e we had something like
158 // after inserting (let's say three 'F' at position 1) we will have
160 // so we need to signal an insetion from position 1 to 2, instead of from
161 // position 1 to 3 and a after that a data changed from 3 to 4
162 const int nItemsToInsert = m_limit - currentCount;
163 beginInsertRows(mapFromSource(parent), start, start + nItemsToInsert - 1);
164 m_sourceInserting = true;
165 m_dataChangedBegin = start + nItemsToInsert;
166 m_dataChangedEnd = m_limit - 1;
167 if (m_dataChangedBegin > m_dataChangedEnd) {
168 // Just in case we were empty and insert 6 items with a limit of 5
169 // We don't want to signal a dataChanged from 5 to 4
170 m_dataChangedBegin = -1;
171 m_dataChangedEnd = -1;
178QLimitProxyModelQML::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
181 beginRemoveRows(mapFromSource(parent), start, end);
182 m_sourceRemoving = true;
183 } else if (start < m_limit) {
184 const int nSourceRemovedItems = end - start + 1;
185 const int currentCount = QIdentityProxyModel::rowCount();
186 if (currentCount <= m_limit) {
187 // We are already under the limit so
188 // so just proceed with the removal normally
189 beginRemoveRows(mapFromSource(parent), start, end);
190 m_sourceRemoving = true;
191 } else if (currentCount - nSourceRemovedItems >= m_limit) {
192 // Even after removing items we will be at or over the limit
193 // So to our users we are not removing anything, just changing the data
194 // i.e. we had a internal model with
196 // and a limit of 5, our users just see
198 // so if we remove 3 items starting at 1 we have to expose
200 // that is, a dataChanged from 1 to 4
201 m_dataChangedBegin = start;
202 m_dataChangedEnd = m_limit - 1;
203 } else { // currentCount > m_limit && currentCount - nSourceRemovedItems < m_limit
204 // We have more items than the limit but after removing we will be below it
205 // So to our users we both removing and changing the data
206 // i.e. we had a internal model with
208 // and a limit of 5, our users just see
210 // so if we remove items from 1 to 3 we have to expose
212 // that is, a remove from 4 to 4 and a dataChanged from 1 to 3
213 const int nItemsToRemove = m_limit - (currentCount - nSourceRemovedItems);
214 beginRemoveRows(mapFromSource(parent), m_limit - nItemsToRemove, m_limit - 1);
215 m_sourceRemoving = true;
216 m_dataChangedBegin = start;
217 m_dataChangedEnd = m_limit - nItemsToRemove - 1;
218 if (m_dataChangedBegin > m_dataChangedEnd) {
219 m_dataChangedBegin = -1;
220 m_dataChangedEnd = -1;
227QLimitProxyModelQML::sourceRowsInserted(const QModelIndex & /*parent*/, int /*start*/, int /*end*/)
229 if (m_sourceInserting) {
231 m_sourceInserting = false;
233 if (m_dataChangedBegin != -1 && m_dataChangedEnd != -1) {
234 dataChanged(index(m_dataChangedBegin, 0), index(m_dataChangedEnd, 0));
235 m_dataChangedBegin = -1;
236 m_dataChangedEnd = -1;
241QLimitProxyModelQML::sourceRowsRemoved(const QModelIndex & /*parent*/, int /*start*/, int /*end*/)
243 if (m_sourceRemoving) {
245 m_sourceRemoving = false;
247 if (m_dataChangedBegin != -1 && m_dataChangedEnd != -1) {
248 dataChanged(index(m_dataChangedBegin, 0), index(m_dataChangedEnd, 0));
249 m_dataChangedBegin = -1;
250 m_dataChangedEnd = -1;
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list