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 | |
50 | QT_BEGIN_HEADER |
51 | |
52 | QT_BEGIN_NAMESPACE |
53 | |
54 | QT_MODULE(Gui) |
55 | |
56 | #ifndef QT_NO_ITEMVIEWS |
57 | |
58 | class Q_GUI_EXPORT QItemSelectionRange |
59 | { |
60 | |
61 | public: |
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 | |
139 | private: |
140 | QPersistentModelIndex tl, br; |
141 | }; |
142 | Q_DECLARE_TYPEINFO(QItemSelectionRange, Q_MOVABLE_TYPE); |
143 | |
144 | inline QItemSelectionRange::QItemSelectionRange(const QModelIndex &atopLeft, |
145 | const QModelIndex &abottomRight) |
146 | { tl = atopLeft; br = abottomRight; } |
147 | |
148 | class QItemSelection; |
149 | class QItemSelectionModelPrivate; |
150 | |
151 | class Q_GUI_EXPORT QItemSelectionModel : public QObject |
152 | { |
153 | Q_OBJECT |
154 | Q_DECLARE_PRIVATE(QItemSelectionModel) |
155 | Q_FLAGS(SelectionFlags) |
156 | |
157 | public: |
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 | |
197 | public 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 | |
206 | Q_SIGNALS: |
207 | void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); |
208 | void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); |
209 | void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous); |
210 | void currentColumnChanged(const QModelIndex ¤t, const QModelIndex &previous); |
211 | |
212 | protected: |
213 | QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstractItemModel *model); |
214 | void emitSelectionChanged(const QItemSelection &newSelection, const QItemSelection &oldSelection); |
215 | |
216 | private: |
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 | |
226 | Q_DECLARE_OPERATORS_FOR_FLAGS(QItemSelectionModel::SelectionFlags) |
227 | |
228 | // dummy implentation of qHash() necessary for instantiating QList<QItemSelectionRange>::toSet() with MSVC |
229 | inline uint qHash(const QItemSelectionRange &) { return 0; } |
230 | |
231 | class Q_GUI_EXPORT QItemSelection : public QList<QItemSelectionRange> |
232 | { |
233 | public: |
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 |
246 | Q_GUI_EXPORT QDebug operator<<(QDebug, const QItemSelectionRange &); |
247 | #endif |
248 | |
249 | #endif // QT_NO_ITEMVIEWS |
250 | |
251 | QT_END_NAMESPACE |
252 | |
253 | QT_END_HEADER |
254 | |
255 | #endif // QITEMSELECTIONMODEL_H |
256 | |