1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore 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 The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QITEMSELECTIONMODEL_H
41#define QITEMSELECTIONMODEL_H
42
43#include <QtCore/qglobal.h>
44
45#include <QtCore/qabstractitemmodel.h>
46#include <QtCore/qlist.h>
47#include <QtCore/qset.h>
48
49QT_REQUIRE_CONFIG(itemmodel);
50
51QT_BEGIN_NAMESPACE
52
53class Q_CORE_EXPORT QItemSelectionRange
54{
55
56public:
57 QItemSelectionRange() = default;
58 QItemSelectionRange(const QModelIndex &topL, const QModelIndex &bottomR) : tl(topL), br(bottomR) {}
59 explicit QItemSelectionRange(const QModelIndex &index) : tl(index), br(tl) {}
60
61 void swap(QItemSelectionRange &other) noexcept
62 {
63 qSwap(tl, other.tl);
64 qSwap(br, other.br);
65 }
66
67 inline int top() const { return tl.row(); }
68 inline int left() const { return tl.column(); }
69 inline int bottom() const { return br.row(); }
70 inline int right() const { return br.column(); }
71 inline int width() const { return br.column() - tl.column() + 1; }
72 inline int height() const { return br.row() - tl.row() + 1; }
73
74 inline const QPersistentModelIndex &topLeft() const { return tl; }
75 inline const QPersistentModelIndex &bottomRight() const { return br; }
76 inline QModelIndex parent() const { return tl.parent(); }
77 inline const QAbstractItemModel *model() const { return tl.model(); }
78
79 inline bool contains(const QModelIndex &index) const
80 {
81 return (parent() == index.parent()
82 && tl.row() <= index.row() && tl.column() <= index.column()
83 && br.row() >= index.row() && br.column() >= index.column());
84 }
85
86 inline bool contains(int row, int column, const QModelIndex &parentIndex) const
87 {
88 return (parent() == parentIndex
89 && tl.row() <= row && tl.column() <= column
90 && br.row() >= row && br.column() >= column);
91 }
92
93 bool intersects(const QItemSelectionRange &other) const;
94 QItemSelectionRange intersected(const QItemSelectionRange &other) const;
95
96
97 inline bool operator==(const QItemSelectionRange &other) const
98 { return (tl == other.tl && br == other.br); }
99 inline bool operator!=(const QItemSelectionRange &other) const
100 { return !operator==(other); }
101 bool operator<(const QItemSelectionRange &other) const;
102
103 inline bool isValid() const
104 {
105 return (tl.isValid() && br.isValid() && tl.parent() == br.parent()
106 && top() <= bottom() && left() <= right());
107 }
108
109 bool isEmpty() const;
110
111 QModelIndexList indexes() const;
112
113private:
114 QPersistentModelIndex tl, br;
115};
116Q_DECLARE_TYPEINFO(QItemSelectionRange, Q_MOVABLE_TYPE);
117
118class QItemSelection;
119class QItemSelectionModelPrivate;
120
121class Q_CORE_EXPORT QItemSelectionModel : public QObject
122{
123 Q_OBJECT
124 Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged)
125 Q_PROPERTY(bool hasSelection READ hasSelection NOTIFY selectionChanged STORED false DESIGNABLE false)
126 Q_PROPERTY(QModelIndex currentIndex READ currentIndex NOTIFY currentChanged STORED false DESIGNABLE false)
127 Q_PROPERTY(QItemSelection selection READ selection NOTIFY selectionChanged STORED false DESIGNABLE false)
128 Q_PROPERTY(QModelIndexList selectedIndexes READ selectedIndexes NOTIFY selectionChanged STORED false DESIGNABLE false)
129
130 Q_DECLARE_PRIVATE(QItemSelectionModel)
131
132public:
133
134 enum SelectionFlag {
135 NoUpdate = 0x0000,
136 Clear = 0x0001,
137 Select = 0x0002,
138 Deselect = 0x0004,
139 Toggle = 0x0008,
140 Current = 0x0010,
141 Rows = 0x0020,
142 Columns = 0x0040,
143 SelectCurrent = Select | Current,
144 ToggleCurrent = Toggle | Current,
145 ClearAndSelect = Clear | Select
146 };
147
148 Q_DECLARE_FLAGS(SelectionFlags, SelectionFlag)
149 Q_FLAG(SelectionFlags)
150
151 explicit QItemSelectionModel(QAbstractItemModel *model = nullptr);
152 explicit QItemSelectionModel(QAbstractItemModel *model, QObject *parent);
153 virtual ~QItemSelectionModel();
154
155 QModelIndex currentIndex() const;
156
157 Q_INVOKABLE bool isSelected(const QModelIndex &index) const;
158 Q_INVOKABLE bool isRowSelected(int row, const QModelIndex &parent = QModelIndex()) const;
159 Q_INVOKABLE bool isColumnSelected(int column, const QModelIndex &parent = QModelIndex()) const;
160
161 Q_INVOKABLE bool rowIntersectsSelection(int row, const QModelIndex &parent = QModelIndex()) const;
162 Q_INVOKABLE bool columnIntersectsSelection(int column, const QModelIndex &parent = QModelIndex()) const;
163
164 bool hasSelection() const;
165
166 QModelIndexList selectedIndexes() const;
167 Q_INVOKABLE QModelIndexList selectedRows(int column = 0) const;
168 Q_INVOKABLE QModelIndexList selectedColumns(int row = 0) const;
169 const QItemSelection selection() const;
170
171 const QAbstractItemModel *model() const;
172 QAbstractItemModel *model();
173
174 void setModel(QAbstractItemModel *model);
175
176public Q_SLOTS:
177 virtual void setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command);
178 virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command);
179 virtual void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command);
180 virtual void clear();
181 virtual void reset();
182
183 void clearSelection();
184 virtual void clearCurrentIndex();
185
186Q_SIGNALS:
187 void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
188 void currentChanged(const QModelIndex &current, const QModelIndex &previous);
189 void currentRowChanged(const QModelIndex &current, const QModelIndex &previous);
190 void currentColumnChanged(const QModelIndex &current, const QModelIndex &previous);
191 void modelChanged(QAbstractItemModel *model);
192
193protected:
194 QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstractItemModel *model);
195 void emitSelectionChanged(const QItemSelection &newSelection, const QItemSelection &oldSelection);
196
197private:
198 Q_DISABLE_COPY(QItemSelectionModel)
199 Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeRemoved(const QModelIndex&, int, int))
200 Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeRemoved(const QModelIndex&, int, int))
201 Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeInserted(const QModelIndex&, int, int))
202 Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeInserted(const QModelIndex&, int, int))
203 Q_PRIVATE_SLOT(d_func(), void _q_layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoHint))
204 Q_PRIVATE_SLOT(d_func(), void _q_layoutChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoHint))
205};
206
207Q_DECLARE_OPERATORS_FOR_FLAGS(QItemSelectionModel::SelectionFlags)
208
209// We export each out-of-line method invidually to prevent MSVC from
210// exporting the whole QList class.
211class QItemSelection : public QList<QItemSelectionRange>
212{
213public:
214 QItemSelection() noexcept : QList<QItemSelectionRange>() {}
215 Q_CORE_EXPORT QItemSelection(const QModelIndex &topLeft, const QModelIndex &bottomRight);
216
217 // reusing QList::swap() here is OK!
218
219 Q_CORE_EXPORT void select(const QModelIndex &topLeft, const QModelIndex &bottomRight);
220 Q_CORE_EXPORT bool contains(const QModelIndex &index) const;
221 Q_CORE_EXPORT QModelIndexList indexes() const;
222 Q_CORE_EXPORT void merge(const QItemSelection &other, QItemSelectionModel::SelectionFlags command);
223 Q_CORE_EXPORT static void split(const QItemSelectionRange &range,
224 const QItemSelectionRange &other,
225 QItemSelection *result);
226};
227Q_DECLARE_SHARED(QItemSelection)
228
229#ifndef QT_NO_DEBUG_STREAM
230Q_CORE_EXPORT QDebug operator<<(QDebug, const QItemSelectionRange &);
231#endif
232
233QT_END_NAMESPACE
234
235Q_DECLARE_METATYPE(QItemSelectionRange)
236Q_DECLARE_METATYPE(QItemSelection)
237
238#endif // QITEMSELECTIONMODEL_H
239