7#include <private/qitemselectionmodel_p.h>
8#include <private/qabstractitemmodel_p.h>
9#include <private/qduplicatetracker_p.h>
10#include <private/qoffsetstringarray_p.h>
192 && isValid() &&
other.isValid()
262template<
typename ModelIndexContainer>
280template<
typename ModelIndexContainer>
283 ModelIndexContainer
result;
377 select(topLeft, bottomRight);
394 qWarning(
"Can't select indexes from different model or with different parents");
420 if ((*it).contains(
index))
432 return qSelectionIndexes<QModelIndexList>(*
this);
455 if (
other.isEmpty() ||
466 if (!
range.isValid())
469 for (
int t = 0;
t <
size(); ++
t) {
476 for (
int i = 0;
i < intersections.
size(); ++
i) {
477 for (
int t = 0;
t <
size();) {
478 if (
at(
t).intersects(intersections.
at(
i))) {
488 split(newSelection.
at(
n), intersections.
at(
i), &newSelection);
518 int other_top =
other.top();
519 int other_left =
other.left();
520 int other_bottom =
other.bottom();
521 int other_right =
other.right();
524 if (other_top >
top) {
530 if (other_bottom <
bottom) {
536 if (other_left >
left) {
542 if (other_right <
right) {
591 model.setValueBypassingBindings(
m);
608 QItemSelectionModel::SelectionFlags command)
const
655 }
else if (
model.value() && end < model->rowCount(
parent) - 1) {
670 bool indexesOfSelectionChanged =
false;
671 QItemSelection::iterator
it = ranges.
begin();
672 while (
it != ranges.
end()) {
673 if (
it->topLeft().parent() !=
parent) {
676 itParent = itParent.
parent();
683 indexesOfSelectionChanged =
true;
686 }
else if (start <= it->
bottom() &&
it->bottom() <=
end
687 && start <= it->
top() &&
it->top() <=
end) {
690 }
else if (start <= it->
top() &&
it->top() <=
end) {
694 }
else if (start <= it->
bottom() &&
it->bottom() <=
end) {
705 deselected.
append(removedRange);
708 }
else if (end < it->
top()) {
709 indexesOfSelectionChanged =
true;
715 ranges.append(newParts);
717 if (!deselected.
isEmpty() || indexesOfSelectionChanged)
736 }
else if (
model.value() && end < model->columnCount() - 1) {
768 for (;
it != ranges.
end(); ) {
770 if ((*it).isValid() && itParent ==
parent
771 && (*it).left() <
start && (*it).right() >=
start) {
799 bool indexesOfSelectionChanged =
false;
800 for (;
it != ranges.
end(); ) {
802 if ((*it).isValid() && itParent ==
parent
803 && (*it).top() <
start && (*it).bottom() >=
start) {
811 }
else if ((*it).isValid() && itParent ==
parent
812 && (*it).top() >=
start) {
813 indexesOfSelectionChanged =
true;
821 if (indexesOfSelectionChanged)
876 if (rowLengths.isEmpty())
881 while (
i < rowLengths.size()) {
889 while (++
i < rowLengths.size()) {
893 const uint nextLength = rowLengths.at(
i).second;
894 if ((nextLength ==
length)
895 && (
next.row() == br.
row() + 1)
919 while (
i < indexes.
size()) {
927 int brRow = br.
row();
928 int brColumn = br.
column();
929 while (++
i < indexes.
size()) {
934 const int nextRow =
next.row();
935 const int nextColumn =
next.column();
936 if ((nextParent == brParent)
937 && (nextRow == brRow)
938 && (nextColumn == brColumn + 1)) {
940 brParent = nextParent;
942 brColumn = nextColumn;
952 while (
i < colSpans.
size()) {
956 while (++
i < colSpans.
size()) {
964 && (nextTl.
row() == prevTl.
row() + 1) && (nextBr.
row() == br.
row() + 1)) {
989 return parent1 == parent2 ? i1 < i2 : parent1 < parent2;
1083 model.setValueBypassingBindings(
nullptr);
1132 d_func()->initModel(
model);
1141 d_func()->initModel(
model);
1259 typedef bool result_type;
1260 struct is_transparent : std::true_type {};
1261 template <
typename T>
1262 constexpr bool operator()(T &
t)
const noexcept(
noexcept(
t.isValid()))
1263 {
return !
t.isValid(); }
1264 template <
typename T>
1265 constexpr bool operator()(T *
t)
const noexcept(
noexcept(
t->isValid()))
1266 {
return !
t->isValid(); }
1280 if (!
d->model.value()) {
1281 qWarning(
"QItemSelectionModel: Selecting when no model has been set will result in a no-op.");
1294 d->ranges.removeIf(QtFunctionObjects::IsNotValid());
1297 old.
merge(
d->currentSelection,
d->currentCommand);
1301 sel =
d->expandSelection(sel, command);
1304 if (command &
Clear) {
1306 d->currentSelection.clear();
1315 d->currentCommand = command;
1316 d->currentSelection = sel;
1321 newSelection.
merge(
d->currentSelection,
d->currentCommand);
1365 if (
d->ranges.size() == 0 &&
d->currentSelection.size() == 0)
1385 if (!
d->model.value()) {
1386 qWarning(
"QItemSelectionModel: Setting the current index when no model has been set will result in a no-op.");
1389 if (
index ==
d->currentIndex) {
1397 select(
d->currentIndex, command);
1399 if (
d->currentIndex.row() != previous.
row() ||
1400 d->currentIndex.parent() != previous.
parent())
1402 if (
d->currentIndex.column() != previous.
column() ||
1403 d->currentIndex.parent() != previous.
parent())
1413 return static_cast<QModelIndex>(d_func()->currentIndex);
1422 if (
d->model !=
index.model() || !
index.isValid())
1425 bool selected =
false;
1428 for (;
it !=
d->ranges.end(); ++
it) {
1429 if ((*it).isValid() && (*it).contains(
index)) {
1436 if (
d->currentSelection.size()) {
1437 if ((
d->currentCommand &
Deselect) && selected)
1438 selected = !
d->currentSelection.contains(
index);
1439 else if (
d->currentCommand &
Toggle)
1440 selected ^=
d->currentSelection.contains(
index);
1441 else if ((
d->currentCommand &
Select) && !selected)
1442 selected =
d->currentSelection.contains(
index);
1465 if (!
d->model.value())
1471 if (
d->currentCommand &
Deselect &&
d->currentSelection.size()) {
1472 for (
int i=0;
i<
d->currentSelection.size(); ++
i) {
1473 if (
d->currentSelection.at(
i).parent() ==
parent &&
1474 row >=
d->currentSelection.at(
i).top() &&
1475 row <= d->currentSelection.at(
i).bottom())
1481 if (
d->currentCommand &
Toggle &&
d->currentSelection.size()) {
1482 for (
int i=0;
i<
d->currentSelection.size(); ++
i)
1483 if (
d->currentSelection.at(
i).top() <=
row &&
1484 d->currentSelection.at(
i).bottom() >=
row)
1485 for (
int j=0;
j<
d->ranges.size(); ++
j)
1486 if (
d->ranges.at(
j).top() <=
row &&
d->ranges.at(
j).bottom() >=
row
1487 &&
d->currentSelection.at(
i).intersected(
d->ranges.at(
j)).isValid())
1491 auto isSelectable = [&](
int row,
int column) {
1495 const int colCount =
d->model->columnCount(
parent);
1496 int unselectable = 0;
1500 if (
d->currentSelection.size())
1501 joined +=
d->currentSelection;
1510 for (
int i =
column;
i <= (*it).right(); ++
i) {
1511 if (!isSelectable(
row,
i))
1522 return unselectable < colCount;
1539 if (!
d->model.value())
1545 if (
d->currentCommand &
Deselect &&
d->currentSelection.size()) {
1546 for (
int i = 0;
i <
d->currentSelection.size(); ++
i) {
1547 if (
d->currentSelection.at(
i).parent() ==
parent &&
1548 column >=
d->currentSelection.at(
i).left() &&
1549 column <= d->currentSelection.at(
i).right())
1555 if (
d->currentCommand &
Toggle &&
d->currentSelection.size()) {
1556 for (
int i = 0;
i <
d->currentSelection.size(); ++
i) {
1557 if (
d->currentSelection.at(
i).left() <=
column &&
1558 d->currentSelection.at(
i).right() >=
column) {
1559 for (
int j = 0;
j <
d->ranges.size(); ++
j) {
1561 &&
d->currentSelection.at(
i).intersected(
d->ranges.at(
j)).isValid()) {
1569 auto isSelectable = [&](
int row,
int column) {
1572 const int rowCount =
d->model->rowCount(
parent);
1573 int unselectable = 0;
1578 if (
d->currentSelection.size())
1579 joined +=
d->currentSelection;
1580 for (
int row = 0;
row < rowCount; ++
row) {
1587 for (
int i =
row;
i <= (*it).bottom(); ++
i) {
1588 if (!isSelectable(
i,
column)) {
1599 return unselectable < rowCount;
1612 if (!
d->model.value())
1618 sel.
merge(
d->currentSelection,
d->currentCommand);
1626 if (top <= row && bottom >=
row) {
1647 if (!
d->model.value())
1653 sel.
merge(
d->currentSelection,
d->currentCommand);
1661 if (left <= column && right >=
column) {
1703 if (
model !=
nullptr) {
1710 sel.
merge(
d->currentSelection,
d->currentCommand);
1725 selected.
merge(
d->currentSelection,
d->currentCommand);
1734 {
return lhs.parent == rhs.parent && lhs.rowOrColumn == rhs.rowOrColumn; }
1762 for (
int i = 0;
i < ranges.
size(); ++
i) {
1766 if (!rowsSeen.
hasSeen({parent, row})) {
1791 for (
int i = 0;
i < ranges.
size(); ++
i) {
1795 if (!columnsSeen.
hasSeen({parent, column})) {
1813 selected.
merge(
d->currentSelection,
d->currentCommand);
1816 selected.
removeIf(QtFunctionObjects::IsNotValid());
1857 return d_func()->model.value();
1865 return d_func()->model.value();
1870 return &d_func()->model;
1883 d->model.removeBindingUnlessInWrapper();
1900 oldSelection == newSelection)
1914 for (
int o = 0;
o < deselected.
size(); ++
o) {
1916 for (
int s = 0;
s < selected.
size() &&
o < deselected.
size();) {
1917 if (deselected.
at(
o) == selected.
at(
s)) {
1931 for (
int o = 0;
o < deselected.
size(); ++
o) {
1932 for (
int s = 0;
s < selected.
size(); ++
s) {
1939 for (
int i = 0;
i < intersections.
size(); ++
i) {
1941 for (
int o = 0;
o < deselected.
size();) {
1950 for (
int s = 0;
s < selected.
size();) {
1964#ifndef QT_NO_DEBUG_STREAM
1968 dbg.nospace() <<
"QItemSelectionRange(" <<
range.topLeft()
1969 <<
',' <<
range.bottomRight() <<
')';
1976#include "moc_qitemselectionmodel.cpp"
virtual void executePendingOperations() const
LayoutChangeHint
This enum describes the way the model changes layout.
virtual Q_INVOKABLE QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const =0
Returns the index of the item in the model specified by the given row, column and parent index.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Returns the index of the data in row and column with parent.
QPersistentModelIndex tableParent
void _q_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
void _q_columnsAboutToBeInserted(const QModelIndex &parent, int start, int end)
void _q_layoutChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
QList< QPair< QPersistentModelIndex, uint > > savedPersistentRowLengths
QList< QPair< QPersistentModelIndex, uint > > savedPersistentCurrentRowLengths
void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
QPersistentModelIndex currentIndex
QItemSelection currentSelection
QList< QPersistentModelIndex > savedPersistentCurrentIndexes
void initModel(QAbstractItemModel *model)
void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
QList< QPersistentModelIndex > savedPersistentIndexes
QItemSelection expandSelection(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) const
void _q_layoutAboutToBeChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
Q_INVOKABLE bool isColumnSelected(int column, const QModelIndex &parent=QModelIndex()) const
Returns true if all items are selected in the column with the given parent.
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
This signal is emitted whenever the selection changes.
void emitSelectionChanged(const QItemSelection &newSelection, const QItemSelection &oldSelection)
Compares the two selections newSelection and oldSelection and emits selectionChanged() with the desel...
void setModel(QAbstractItemModel *model)
QBindable< QAbstractItemModel * > bindableModel()
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
This signal is emitted whenever the current item changes.
Q_INVOKABLE bool isSelected(const QModelIndex &index) const
Returns true if the given model item index is selected.
QModelIndexList selectedIndexes
virtual ~QItemSelectionModel()
Destroys the selection model.
virtual void setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
Sets the model item index to be the current item, and emits currentChanged().
virtual void reset()
Clears the selection model.
virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
Selects the model item index using the specified command, and emits selectionChanged().
virtual void clearCurrentIndex()
Clears the current index.
Q_INVOKABLE bool isRowSelected(int row, const QModelIndex &parent=QModelIndex()) const
Returns true if all items are selected in the row with the given parent.
Q_INVOKABLE bool columnIntersectsSelection(int column, const QModelIndex &parent=QModelIndex()) const
Returns true if there are any items selected in the column with the given parent.
void currentColumnChanged(const QModelIndex ¤t, const QModelIndex &previous)
This signal is emitted if the current item changes and its column is different to the column of the p...
virtual void clear()
Clears the selection model.
void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous)
This signal is emitted if the current item changes and its row is different to the row of the previou...
QAbstractItemModel * model
QItemSelectionModel(QAbstractItemModel *model=nullptr)
Constructs a selection model that operates on the specified item model.
Q_INVOKABLE bool rowIntersectsSelection(int row, const QModelIndex &parent=QModelIndex()) const
Returns true if there are any items selected in the row with the given parent.
Q_INVOKABLE QModelIndexList selectedColumns(int row=0) const
bool intersects(const QItemSelectionRange &other) const
Returns true if this selection range intersects (overlaps with) the other range given; otherwise retu...
int bottom() const
Returns the row index corresponding to the lowermost selected row in the selection range.
const QPersistentModelIndex & topLeft() const
Returns the index for the item located at the top-left corner of the selection range.
int top() const
Returns the row index corresponding to the uppermost selected row in the selection range.
QItemSelectionRange()=default
Constructs an empty selection range.
QItemSelectionRange intersected(const QItemSelectionRange &other) const
bool isEmpty() const
Returns true if the selection range contains either no items or only items which are either disabled ...
QModelIndexList indexes() const
Returns the list of model index items stored in the selection.
const QPersistentModelIndex & bottomRight() const
Returns the index for the item located at the bottom-right corner of the selection range.
int right() const
Returns the column index corresponding to the rightmost selected column in the selection range.
const QAbstractItemModel * model() const
Returns the model that the items in the selection range belong to.
QModelIndex parent() const
Returns the parent model item index of the items in the selection range.
int left() const
Returns the column index corresponding to the leftmost selected column in the selection range.
bool isValid() const
Returns true if the selection range is valid; otherwise returns false.
static Q_CORE_EXPORT void split(const QItemSelectionRange &range, const QItemSelectionRange &other, QItemSelection *result)
Splits the selection range using the selection other range.
Q_CORE_EXPORT QModelIndexList indexes() const
Returns a list of model indexes that correspond to the selected items.
Q_CORE_EXPORT void select(const QModelIndex &topLeft, const QModelIndex &bottomRight)
Adds the items in the range that extends from the top-left model item, specified by the topLeft index...
Q_CORE_EXPORT QItemSelection(const QModelIndex &topLeft, const QModelIndex &bottomRight)
Constructs an empty selection.
Q_CORE_EXPORT void merge(const QItemSelection &other, QItemSelectionModel::SelectionFlags command)
Merges the other selection with this QItemSelection using the command given.
Q_CORE_EXPORT bool contains(const QModelIndex &index) const
Returns true if the selection contains the given index; otherwise returns false.
qsizetype size() const noexcept
bool isEmpty() const noexcept
void removeAt(qsizetype i)
QList< QItemSelectionRange > & operator+=(const QList< QItemSelectionRange > &l)
void push_back(parameter_type t)
const_reference at(qsizetype i) const noexcept
const_iterator constBegin() const noexcept
qsizetype removeIf(Predicate pred)
const T & constFirst() const noexcept
void reserve(qsizetype size)
void append(parameter_type t)
const_iterator constEnd() const noexcept
constexpr int row() const noexcept
Returns the row this model index refers to.
QModelIndex parent() const
Returns the parent of the model index, or QModelIndex() if it has no parent.
constexpr const QAbstractItemModel * model() const noexcept
Returns a pointer to the model containing the item that this index refers to.
constexpr int column() const noexcept
Returns the column this model index refers to.
constexpr bool isValid() const noexcept
Returns {true} if this model index is valid; otherwise returns {false}.
QModelIndex sibling(int row, int column) const
Returns the sibling at row and column.
QAtomicPointer< ConnectionData > connections
static QObjectPrivate * get(QObject *o)
QObject * parent() const
Returns a pointer to the parent object.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
bool isValid() const
Returns {true} if this persistent model index is valid; otherwise returns {false}.
QModelIndex sibling(int row, int column) const
Returns the sibling at row and column or an invalid QModelIndex if there is no sibling at this positi...
QModelIndex parent() const
Returns the parent QModelIndex for this persistent index, or an invalid QModelIndex if it has no pare...
int column() const
Returns the column this persistent model index refers to.
int row() const
Returns the row this persistent model index refers to.
iterator erase(const_iterator i)
Exception-safe wrapper around QObject::blockSignals().
int rowCount(const QModelIndex &parent=QModelIndex()) const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
\reimp
QHash< int, QWidget * > hash
[35multi]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
std::pair< T1, T2 > QPair
#define QT_SPECIALIZE_STD_HASH_TO_CALL_QHASH_BY_CREF(Class)
static bool selectionIsEmpty(const QItemSelection &selection)
static QItemSelection mergeIndexes(const QList< QPersistentModelIndex > &indexes)
static bool qt_PersistentModelIndexLessThan(const QPersistentModelIndex &i1, const QPersistentModelIndex &i2)
static QList< QPair< QPersistentModelIndex, uint > > qSelectionPersistentRowLengths(const QItemSelection &sel)
static ModelIndexContainer qSelectionIndexes(const QItemSelection &selection)
static void rowLengthsFromRange(const QItemSelectionRange &range, QList< QPair< QPersistentModelIndex, uint > > &result)
static QItemSelection mergeRowLengths(const QList< QPair< QPersistentModelIndex, uint > > &rowLengths)
static void indexesFromRange(const QItemSelectionRange &range, ModelIndexContainer &result)
QDebug operator<<(QDebug dbg, const QItemSelectionRange &range)
static bool isSelectableAndEnabled(Qt::ItemFlags flags)
size_t qHash(const RowOrColumnDefinition &key, size_t seed=0) noexcept
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
#define QT_STRINGIFY_SIGNAL(a)
#define QT_STRINGIFY_SLOT(a)
constexpr auto qOffsetStringArray(const char(&...strings)[Nx]) noexcept
GLenum GLuint GLenum GLsizei length
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei void GLsizei void * column
GLdouble GLdouble GLdouble GLdouble q
GLenum GLenum GLsizei void * row
constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
static void split(QT_FT_Vector *b)
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
QSqlQueryModel * model
[16]
QItemSelection * selection
[0]
friend bool operator==(const RowOrColumnDefinition &lhs, const RowOrColumnDefinition &rhs) noexcept
friend bool operator!=(const RowOrColumnDefinition &lhs, const RowOrColumnDefinition &rhs) noexcept
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent