on d5f8aef help sign in
unity8/plugins/Utils/qlimitproxymodelqml.cpp
212 lines 7.5 kB history raw
1/*
2 * Copyright (C) 2012, 2013 Canonical, Ltd.
3 *
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.
7 *
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.
12 *
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/>.
15 */
17// self
18#include "qlimitproxymodelqml.h"
20// Qt
21#include <QDebug>
23QLimitProxyModelQML::QLimitProxyModelQML(QObject *parent)
24 : QIdentityProxyModel(parent)
25 , m_limit(-1)
26 , m_sourceInserting(false)
27 , m_sourceRemoving(false)
28 , m_dataChangedBegin(-1)
29 , m_dataChangedEnd(-1)
31 connect(this, SIGNAL(modelReset()), SIGNAL(countChanged()));
32 connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(countChanged()));
33 connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(countChanged()));
36QHash<int, QByteArray> QLimitProxyModelQML::roleNames() const
38 return sourceModel() ? sourceModel()->roleNames() : QHash<int, QByteArray>();
41void
42QLimitProxyModelQML::setModel(QAbstractItemModel *itemModel)
44 if (itemModel != sourceModel()) {
45 if (sourceModel() != NULL) {
46 sourceModel()->disconnect(this);
47 }
49 setSourceModel(itemModel);
51 if (sourceModel() != NULL) {
52 // Disconnect the QIdentityProxyModel handling for rows removed/added...
53 disconnect(sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, NULL);
54 disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), this, NULL);
55 disconnect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, NULL);
56 disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), this, NULL);
58 // ... and use our own
59 connect(sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
60 this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int)));
61 connect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
62 this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
63 connect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
64 this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int)));
65 connect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
66 this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
67 }
68 Q_EMIT modelChanged();
69 }
72int
73QLimitProxyModelQML::rowCount(const QModelIndex &parent) const
75 if (parent.isValid()) // We are not a tree
76 return 0;
78 const int unlimitedCount = QIdentityProxyModel::rowCount(parent);
79 return m_limit < 0 ? unlimitedCount : qMin(m_limit, unlimitedCount);
82int
83QLimitProxyModelQML::limit() const
85 return m_limit;
88void
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();
96 if (m_limit < 0) {
97 if (limit < oldCount) {
98 removing = true;
99 beginRemoveRows(QModelIndex(), limit, oldCount - 1);
100 }
101 } else if (limit < 0) {
102 if (m_limit < unlimitedCount) {
103 inserting = true;
104 beginInsertRows(QModelIndex(), m_limit, unlimitedCount - 1);
105 }
106 } else {
107 if (limit > m_limit && unlimitedCount > m_limit) {
108 inserting = true;
109 beginInsertRows(QModelIndex(), m_limit, qMin(limit, unlimitedCount) - 1);
110 } else if (limit < m_limit && limit < oldCount) {
111 removing = true;
112 beginRemoveRows(QModelIndex(), limit, oldCount - 1);
113 }
114 }
116 m_limit = limit;
118 if (inserting) {
119 endInsertRows();
120 } else if (removing) {
121 endRemoveRows();
122 }
124 Q_EMIT limitChanged();
125 }
128void
129QLimitProxyModelQML::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
131 if (m_limit < 0) {
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 beginInsertRows(mapFromSource(parent), start, end);
139 m_sourceInserting = true;
140 } else if (currentCount < m_limit) {
141 const int nItemsToInsert = m_limit - currentCount;
142 beginInsertRows(mapFromSource(parent), start, start + nItemsToInsert - 1);
143 m_sourceInserting = true;
144 m_dataChangedBegin = start + nItemsToInsert;
145 m_dataChangedEnd = m_limit - 1;
146 if (m_dataChangedBegin > m_dataChangedEnd) {
147 m_dataChangedBegin = -1;
148 m_dataChangedEnd = -1;
149 }
150 } else {
151 m_dataChangedBegin = start;
152 m_dataChangedEnd = m_limit - 1;
153 }
154 }
157void
158QLimitProxyModelQML::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
160 if (m_limit < 0) {
161 beginRemoveRows(mapFromSource(parent), start, end);
162 m_sourceRemoving = true;
163 } else if (start < m_limit) {
164 const int nSourceRemovedItems = end - start + 1;
165 const int currentCount = QIdentityProxyModel::rowCount();
166 if (currentCount <= m_limit) {
167 beginRemoveRows(mapFromSource(parent), start, end);
168 m_sourceRemoving = true;
169 } else if (currentCount - nSourceRemovedItems < m_limit) {
170 const int nItemsToRemove = m_limit - (currentCount - nSourceRemovedItems);
171 beginRemoveRows(mapFromSource(parent), m_limit - nItemsToRemove, m_limit - 1);
172 m_sourceRemoving = true;
173 m_dataChangedBegin = start;
174 m_dataChangedEnd = m_limit - nItemsToRemove - 1;
175 if (m_dataChangedBegin > m_dataChangedEnd) {
176 m_dataChangedBegin = -1;
177 m_dataChangedEnd = -1;
178 }
179 } else {
180 m_dataChangedBegin = start;
181 m_dataChangedEnd = m_limit - 1;
182 }
183 }
186void
187QLimitProxyModelQML::sourceRowsInserted(const QModelIndex & /*parent*/, int /*start*/, int /*end*/)
189 if (m_sourceInserting) {
190 endInsertRows();
191 m_sourceInserting = false;
192 }
193 if (m_dataChangedBegin != -1 && m_dataChangedEnd != -1) {
194 dataChanged(index(m_dataChangedBegin, 0), index(m_dataChangedEnd, 0));
195 m_dataChangedBegin = -1;
196 m_dataChangedEnd = -1;
197 }
200void
201QLimitProxyModelQML::sourceRowsRemoved(const QModelIndex & /*parent*/, int /*start*/, int /*end*/)
203 if (m_sourceRemoving) {
204 endRemoveRows();
205 m_sourceRemoving = false;
206 }
207 if (m_dataChangedBegin != -1 && m_dataChangedEnd != -1) {
208 dataChanged(index(m_dataChangedBegin, 0), index(m_dataChangedEnd, 0));
209 m_dataChangedBegin = -1;
210 m_dataChangedEnd = -1;
211 }