1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Digia gives you certain additional
26** rights. These rights are described in the Digia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QITEMSELECTIONMODEL_H
43#define QITEMSELECTIONMODEL_H
44
45#include <QtCore/qset.h>
46#include <QtCore/qvector.h>
47#include <QtCore/qlist.h>
48#include <QtCore/qabstractitemmodel.h>
49
50QT_BEGIN_HEADER
51
52QT_BEGIN_NAMESPACE
53
54QT_MODULE(Gui)
55
56#ifndef QT_NO_ITEMVIEWS
57
58class Q_GUI_EXPORT QItemSelectionRange
59{
60
61public:
62 inline QItemSelectionRange() {}
63 inline QItemSelectionRange(const QItemSelectionRange &other)
64 : tl(other.tl), br(other.br) {}
65 inline QItemSelectionRange(const QModelIndex &topLeft, const QModelIndex &bottomRight);
66 explicit inline QItemSelectionRange(const QModelIndex &index)
67 { tl = index; br = tl; }
68
69 inline int top() const { return tl.row(); }
70 inline int left() const { return tl.column(); }
71 inline int bottom() const { return br.row(); }
72 inline int right() const { return br.column(); }
73 inline int width() const { return br.column() - tl.column() + 1; }
74 inline int height() const { return br.row() - tl.row() + 1; }
75
76 inline QModelIndex topLeft() const { return QModelIndex(tl); }
77 inline QModelIndex bottomRight() const { return QModelIndex(br); }
78 inline QModelIndex parent() const { return tl.parent(); }
79 inline const QAbstractItemModel *model() const { return tl.model(); }
80
81 inline bool contains(const QModelIndex &index) const
82 {
83 return (parent() == index.parent()
84 && tl.row() <= index.row() && tl.column() <= index.column()
85 && br.row() >= index.row() && br.column() >= index.column());
86 }
87
88 inline bool contains(int row, int column, const QModelIndex &parentIndex) const
89 {
90 return (parent() == parentIndex
91 && tl.row() <= row && tl.column() <= column
92 && br.row() >= row && br.column() >= column);
93 }
94
95 bool intersects(const QItemSelectionRange &other) const;
96 QItemSelectionRange intersect(const QItemSelectionRange &other) const; // ### Qt 5: make QT4_SUPPORT
97 inline QItemSelectionRange intersected(const QItemSelectionRange &other) const
98 { return intersect(other); }
99
100 inline bool operator==(const QItemSelectionRange &other) const
101 { return (tl == other.tl && br == other.br); }
102 inline bool operator!=(const QItemSelectionRange &other) const
103 { return !operator==(other); }
104 inline bool operator<(const QItemSelectionRange &other) const
105 {
106 // Comparing parents will compare the models, but if two equivalent ranges
107 // in two different models have invalid parents, they would appear the same
108 if (other.tl.model() == tl.model()) {
109 // parent has to be calculated, so we only do so once.
110 const QModelIndex topLeftParent = tl.parent();
111 const QModelIndex otherTopLeftParent = other.tl.parent();
112 if (topLeftParent == otherTopLeftParent) {
113 if (other.tl.row() == tl.row()) {
114 if (other.tl.column() == tl.column()) {
115 if (other.br.row() == br.row()) {
116 return br.column() < other.br.column();
117 }
118 return br.row() < other.br.row();
119 }
120 return tl.column() < other.tl.column();
121 }
122 return tl.row() < other.tl.row();
123 }
124 return topLeftParent < otherTopLeftParent;
125 }
126 return tl.model() < other.tl.model();
127 }
128
129 inline bool isValid() const
130 {
131 return (tl.isValid() && br.isValid() && tl.parent() == br.parent()
132 && top() <= bottom() && left() <= right());
133 }
134
135 bool isEmpty() const;
136
137 QModelIndexList indexes() const;
138
139private:
140 QPersistentModelIndex tl, br;
141};
142Q_DECLARE_TYPEINFO(QItemSelectionRange, Q_MOVABLE_TYPE);
143
144inline QItemSelectionRange::QItemSelectionRange(const QModelIndex &atopLeft,
145 const QModelIndex &abottomRight)
146{ tl = atopLeft; br = abottomRight; }
147
148class QItemSelection;
149class QItemSelectionModelPrivate;
150
151class Q_GUI_EXPORT QItemSelectionModel : public QObject
152{
153 Q_OBJECT
154 Q_DECLARE_PRIVATE(QItemSelectionModel)
155 Q_FLAGS(SelectionFlags)
156
157public:
158
159 enum SelectionFlag {
160 NoUpdate = 0x0000,
161 Clear = 0x0001,
162 Select = 0x0002,
163 Deselect = 0x0004,
164 Toggle = 0x0008,
165 Current = 0x0010,
166 Rows = 0x0020,
167 Columns = 0x0040,
168 SelectCurrent = Select | Current,
169 ToggleCurrent = Toggle | Current,
170 ClearAndSelect = Clear | Select
171 };
172
173 Q_DECLARE_FLAGS(SelectionFlags, SelectionFlag)
174
175 explicit QItemSelectionModel(QAbstractItemModel *model);
176 explicit QItemSelectionModel(QAbstractItemModel *model, QObject *parent);
177 virtual ~QItemSelectionModel();
178
179 QModelIndex currentIndex() const;
180
181 bool isSelected(const QModelIndex &index) const;
182 bool isRowSelected(int row, const QModelIndex &parent) const;
183 bool isColumnSelected(int column, const QModelIndex &parent) const;
184
185 bool rowIntersectsSelection(int row, const QModelIndex &parent) const;
186 bool columnIntersectsSelection(int column, const QModelIndex &parent) const;
187
188 bool hasSelection() const;
189
190 QModelIndexList selectedIndexes() const;
191 QModelIndexList selectedRows(int column = 0) const;
192 QModelIndexList selectedColumns(int row = 0) const;
193 const QItemSelection selection() const;
194
195 const QAbstractItemModel *model() const;
196
197public Q_SLOTS:
198 void setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command);
199 virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command);
200 virtual void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command);
201 virtual void clear();
202 virtual void reset();
203
204 void clearSelection();
205
206Q_SIGNALS:
207 void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
208 void currentChanged(const QModelIndex &current, const QModelIndex &previous);
209 void currentRowChanged(const QModelIndex &current, const QModelIndex &previous);
210 void currentColumnChanged(const QModelIndex &current, const QModelIndex &previous);
211
212protected:
213 QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstractItemModel *model);
214 void emitSelectionChanged(const QItemSelection &newSelection, const QItemSelection &oldSelection);
215
216private:
217 Q_DISABLE_COPY(QItemSelectionModel)
218 Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeRemoved(const QModelIndex&, int, int))
219 Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeRemoved(const QModelIndex&, int, int))
220 Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeInserted(const QModelIndex&, int, int))
221 Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeInserted(const QModelIndex&, int, int))
222 Q_PRIVATE_SLOT(d_func(), void _q_layoutAboutToBeChanged())
223 Q_PRIVATE_SLOT(d_func(), void _q_layoutChanged())
224};
225
226Q_DECLARE_OPERATORS_FOR_FLAGS(QItemSelectionModel::SelectionFlags)
227
228// dummy implentation of qHash() necessary for instantiating QList<QItemSelectionRange>::toSet() with MSVC
229inline uint qHash(const QItemSelectionRange &) { return 0; }
230
231class Q_GUI_EXPORT QItemSelection : public QList<QItemSelectionRange>
232{
233public:
234 QItemSelection() {}
235 QItemSelection(const QModelIndex &topLeft, const QModelIndex &bottomRight);
236 void select(const QModelIndex &topLeft, const QModelIndex &bottomRight);
237 bool contains(const QModelIndex &index) const;
238 QModelIndexList indexes() const;
239 void merge(const QItemSelection &other, QItemSelectionModel::SelectionFlags command);
240 static void split(const QItemSelectionRange &range,
241 const QItemSelectionRange &other,
242 QItemSelection *result);
243};
244
245#ifndef QT_NO_DEBUG_STREAM
246Q_GUI_EXPORT QDebug operator<<(QDebug, const QItemSelectionRange &);
247#endif
248
249#endif // QT_NO_ITEMVIEWS
250
251QT_END_NAMESPACE
252
253QT_END_HEADER
254
255#endif // QITEMSELECTIONMODEL_H
256