7#include <private/qitemselectionmodel_p.h>
8#include <private/qabstractitemmodel_p.h>
9#include <private/qduplicatetracker_p.h>
10#include <private/qoffsetstringarray_p.h>
193 && parent() ==
other.parent()
194 && isValid() &&
other.isValid()
264template<
typename ModelIndexContainer>
282template<
typename ModelIndexContainer>
285 ModelIndexContainer
result;
379 select(topLeft, bottomRight);
396 qWarning(
"Can't select indexes from different model or with different parents");
422 if ((*it).contains(
index))
434 return qSelectionIndexes<QModelIndexList>(*
this);
439 QList<std::pair<QPersistentModelIndex, uint>>
result;
457 if (
other.isEmpty() ||
468 if (!
range.isValid())
471 for (
int t = 0;
t <
size(); ++
t) {
478 for (
int i = 0;
i < intersections.
size(); ++
i) {
479 for (
int t = 0;
t <
size();) {
480 if (
at(
t).intersects(intersections.
at(
i))) {
489 if (newSelection.at(
n).intersects(intersections.
at(
i))) {
490 split(newSelection.at(
n), intersections.
at(
i), &newSelection);
491 newSelection.removeAt(
n);
520 int other_top =
other.top();
521 int other_left =
other.left();
522 int other_bottom =
other.bottom();
523 int other_right =
other.right();
526 if (other_top >
top) {
532 if (other_bottom <
bottom) {
538 if (other_left >
left) {
544 if (other_right <
right) {
566 model.setValueBypassingBindings(
m);
569 connections = std::array<QMetaObject::Connection, 12> {
613 QItemSelectionModel::SelectionFlags command)
const
660 }
else if (
model.value() && end < model->rowCount(
parent) - 1) {
675 bool indexesOfSelectionChanged =
false;
676 QItemSelection::iterator
it = ranges.
begin();
677 while (
it != ranges.
end()) {
678 if (
it->topLeft().parent() !=
parent) {
680 while (itParent.isValid() && itParent.parent() !=
parent)
681 itParent = itParent.parent();
683 if (itParent.isValid() &&
start <= itParent.row() && itParent.row() <=
end) {
684 deselected.append(*
it);
687 if (itParent.isValid() &&
end < itParent.row())
688 indexesOfSelectionChanged =
true;
691 }
else if (start <= it->
bottom() &&
it->bottom() <=
end
692 && start <= it->
top() &&
it->top() <=
end) {
693 deselected.append(*
it);
695 }
else if (start <= it->
top() &&
it->top() <=
end) {
699 }
else if (start <= it->
bottom() &&
it->bottom() <=
end) {
710 deselected.append(removedRange);
713 }
else if (end < it->
top()) {
714 indexesOfSelectionChanged =
true;
720 ranges.append(newParts);
722 if (!deselected.isEmpty() || indexesOfSelectionChanged)
741 }
else if (
model.value() && end < model->columnCount() - 1) {
771 QList<QItemSelectionRange>
split;
773 for (;
it != ranges.
end(); ) {
775 if ((*it).isValid() && itParent ==
parent
776 && (*it).left() <
start && (*it).right() >=
start) {
802 QList<QItemSelectionRange>
split;
804 bool indexesOfSelectionChanged =
false;
805 for (;
it != ranges.
end(); ) {
807 if ((*it).isValid() && itParent ==
parent
808 && (*it).top() <
start && (*it).bottom() >=
start) {
816 }
else if ((*it).isValid() && itParent ==
parent
817 && (*it).top() >=
start) {
818 indexesOfSelectionChanged =
true;
826 if (indexesOfSelectionChanged)
882 if (rowLengths.isEmpty())
887 while (
i < rowLengths.size()) {
895 while (++
i < rowLengths.size()) {
899 const uint nextLength = rowLengths.at(
i).second;
900 if ((nextLength ==
length)
901 && (
next.row() == br.
row() + 1)
925 while (
i < indexes.size()) {
933 int brRow = br.
row();
934 int brColumn = br.
column();
935 while (++
i < indexes.size()) {
940 const int nextRow =
next.row();
941 const int nextColumn =
next.column();
942 if ((nextParent == brParent)
943 && (nextRow == brRow)
944 && (nextColumn == brColumn + 1)) {
946 brParent = nextParent;
948 brColumn = nextColumn;
958 while (
i < colSpans.size()) {
962 while (++
i < colSpans.size()) {
966 if (nextTl.parent() != tl.
parent())
969 if ((nextTl.column() == prevTl.column()) && (nextBr.column() == br.
column())
970 && (nextTl.row() == prevTl.row() + 1) && (nextBr.row() == br.
row() + 1)) {
995 return parent1 == parent2 ? i1 < i2 : parent1 < parent2;
1089 model.setValueBypassingBindings(
nullptr);
1139 d_func()->initModel(
model);
1148 d_func()->initModel(
model);
1266 typedef bool result_type;
1267 struct is_transparent : std::true_type {};
1268 template <
typename T>
1269 constexpr bool operator()(T &
t)
const noexcept(
noexcept(
t.isValid()))
1270 {
return !
t.isValid(); }
1271 template <
typename T>
1272 constexpr bool operator()(T *
t)
const noexcept(
noexcept(
t->isValid()))
1273 {
return !
t->isValid(); }
1287 if (!
d->model.value()) {
1288 qWarning(
"QItemSelectionModel: Selecting when no model has been set will result in a no-op.");
1301 d->ranges.
removeIf(QtFunctionObjects::IsNotValid());
1304 old.
merge(
d->currentSelection,
d->currentCommand);
1308 sel =
d->expandSelection(sel, command);
1311 if (command &
Clear) {
1313 d->currentSelection.clear();
1322 d->currentCommand = command;
1323 d->currentSelection = sel;
1328 newSelection.
merge(
d->currentSelection,
d->currentCommand);
1372 if (
d->ranges.size() == 0 &&
d->currentSelection.size() == 0)
1392 if (!
d->model.value()) {
1393 qWarning(
"QItemSelectionModel: Setting the current index when no model has been set will result in a no-op.");
1396 if (
index ==
d->currentIndex) {
1404 select(
d->currentIndex, command);
1406 if (
d->currentIndex.row() != previous.
row() ||
1407 d->currentIndex.parent() != previous.
parent())
1409 if (
d->currentIndex.column() != previous.
column() ||
1410 d->currentIndex.parent() != previous.
parent())
1420 return static_cast<QModelIndex>(d_func()->currentIndex);
1429 if (
d->model !=
index.model() || !
index.isValid())
1432 bool selected =
false;
1435 for (;
it !=
d->ranges.
end(); ++
it) {
1436 if ((*it).isValid() && (*it).contains(
index)) {
1443 if (
d->currentSelection.size()) {
1444 if ((
d->currentCommand &
Deselect) && selected)
1445 selected = !
d->currentSelection.contains(
index);
1446 else if (
d->currentCommand &
Toggle)
1447 selected ^=
d->currentSelection.contains(
index);
1448 else if ((
d->currentCommand &
Select) && !selected)
1449 selected =
d->currentSelection.contains(
index);
1472 if (!
d->model.value())
1478 if (
d->currentCommand &
Deselect &&
d->currentSelection.size()) {
1479 for (
int i=0;
i<
d->currentSelection.size(); ++
i) {
1480 if (
d->currentSelection.at(
i).parent() ==
parent &&
1481 row >=
d->currentSelection.at(
i).top() &&
1482 row <= d->currentSelection.at(
i).bottom())
1488 if (
d->currentCommand &
Toggle &&
d->currentSelection.size()) {
1489 for (
int i=0;
i<
d->currentSelection.size(); ++
i)
1490 if (
d->currentSelection.at(
i).top() <=
row &&
1491 d->currentSelection.at(
i).bottom() >=
row)
1492 for (
int j=0;
j<
d->ranges.size(); ++
j)
1493 if (
d->ranges.at(
j).top() <=
row &&
d->ranges.at(
j).bottom() >=
row
1494 &&
d->currentSelection.at(
i).intersected(
d->ranges.at(
j)).isValid())
1498 auto isSelectable = [&](
int row,
int column) {
1502 const int colCount =
d->model->columnCount(
parent);
1503 int unselectable = 0;
1506 QList<QItemSelectionRange> joined =
d->ranges;
1507 if (
d->currentSelection.size())
1508 joined +=
d->currentSelection;
1517 for (
int i =
column;
i <= (*it).right(); ++
i) {
1518 if (!isSelectable(
row,
i))
1529 return unselectable < colCount;
1546 if (!
d->model.value())
1552 if (
d->currentCommand &
Deselect &&
d->currentSelection.size()) {
1553 for (
int i = 0;
i <
d->currentSelection.size(); ++
i) {
1554 if (
d->currentSelection.at(
i).parent() ==
parent &&
1555 column >=
d->currentSelection.at(
i).left() &&
1556 column <= d->currentSelection.at(
i).right())
1562 if (
d->currentCommand &
Toggle &&
d->currentSelection.size()) {
1563 for (
int i = 0;
i <
d->currentSelection.size(); ++
i) {
1564 if (
d->currentSelection.at(
i).left() <=
column &&
1565 d->currentSelection.at(
i).right() >=
column) {
1566 for (
int j = 0;
j <
d->ranges.size(); ++
j) {
1568 &&
d->currentSelection.at(
i).intersected(
d->ranges.at(
j)).isValid()) {
1576 auto isSelectable = [&](
int row,
int column) {
1579 const int rowCount =
d->model->rowCount(
parent);
1580 int unselectable = 0;
1584 QList<QItemSelectionRange> joined =
d->ranges;
1585 if (
d->currentSelection.size())
1586 joined +=
d->currentSelection;
1587 for (
int row = 0;
row < rowCount; ++
row) {
1594 for (
int i =
row;
i <= (*it).bottom(); ++
i) {
1595 if (!isSelectable(
i,
column)) {
1606 return unselectable < rowCount;
1619 if (!
d->model.value())
1625 sel.
merge(
d->currentSelection,
d->currentCommand);
1633 if (top <= row && bottom >=
row) {
1654 if (!
d->model.value())
1660 sel.
merge(
d->currentSelection,
d->currentCommand);
1668 if (left <= column && right >=
column) {
1710 if (
model !=
nullptr) {
1717 sel.
merge(
d->currentSelection,
d->currentCommand);
1732 selected.
merge(
d->currentSelection,
d->currentCommand);
1741 {
return lhs.parent == rhs.parent && lhs.rowOrColumn == rhs.rowOrColumn; }
1766 QDuplicateTracker<RowOrColumnDefinition> rowsSeen;
1769 for (
int i = 0;
i < ranges.
size(); ++
i) {
1773 if (!rowsSeen.hasSeen({parent, row})) {
1774 if (isRowSelected(
row, parent)) {
1795 QDuplicateTracker<RowOrColumnDefinition> columnsSeen;
1798 for (
int i = 0;
i < ranges.
size(); ++
i) {
1802 if (!columnsSeen.hasSeen({parent, column})) {
1820 selected.
merge(
d->currentSelection,
d->currentCommand);
1823 selected.
removeIf(QtFunctionObjects::IsNotValid());
1864 return d_func()->model.value();
1872 return d_func()->model.value();
1877 return &d_func()->model;
1890 d->model.removeBindingUnlessInWrapper();
1891 if (
d->model.valueBypassingBindings() ==
model)
1905 if ((oldSelection.
isEmpty() && newSelection.isEmpty()) ||
1906 oldSelection == newSelection)
1910 if (oldSelection.
isEmpty() || newSelection.isEmpty()) {
1920 for (
int o = 0;
o < deselected.size(); ++
o) {
1922 for (
int s = 0;
s < selected.
size() &&
o < deselected.size();) {
1923 if (deselected.at(
o) == selected.
at(
s)) {
1937 for (
int o = 0;
o < deselected.size(); ++
o) {
1938 for (
int s = 0;
s < selected.
size(); ++
s) {
1939 if (deselected.at(
o).intersects(selected.
at(
s)))
1940 intersections.
append(deselected.at(
o).intersected(selected.
at(
s)));
1945 for (
int i = 0;
i < intersections.
size(); ++
i) {
1947 for (
int o = 0;
o < deselected.size();) {
1948 if (deselected.at(
o).intersects(intersections.
at(
i))) {
1950 deselected.removeAt(
o);
1956 for (
int s = 0;
s < selected.
size();) {
1966 if (!selected.
isEmpty() || !deselected.isEmpty())
1970#ifndef QT_NO_DEBUG_STREAM
1974 dbg.nospace() <<
"QItemSelectionRange(" <<
range.topLeft()
1975 <<
',' <<
range.bottomRight() <<
')';
1982#include "moc_qitemselectionmodel.cpp"
virtual void executePendingOperations() const
void rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow, QPrivateSignal)
LayoutChangeHint
This enum describes the way the model changes layout.
void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted just before rows are inserted into the model.
void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted just before columns are inserted into the model.
void modelReset(QPrivateSignal)
void layoutAboutToBeChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
void columnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn, QPrivateSignal)
void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted just before columns are removed from the model.
void layoutChanged(const QList< QPersistentModelIndex > &parents=QList< QPersistentModelIndex >(), QAbstractItemModel::LayoutChangeHint hint=QAbstractItemModel::NoLayoutChangeHint)
void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted just before rows are removed from the model.
void rowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow, QPrivateSignal)
void columnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn, QPrivateSignal)
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 triggerLayoutChanged()
void layoutAboutToBeChanged(const QList< QPersistentModelIndex > &parents, QAbstractItemModel::LayoutChangeHint hint)
void rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
void columnsAboutToBeInserted(const QModelIndex &parent, int start, int end)
void columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
QPersistentModelIndex currentIndex
QList< std::pair< QPersistentModelIndex, uint > > savedPersistentCurrentRowLengths
QItemSelection currentSelection
QList< std::pair< QPersistentModelIndex, uint > > savedPersistentRowLengths
QList< QPersistentModelIndex > savedPersistentCurrentIndexes
std::array< QMetaObject::Connection, 12 > connections
void initModel(QAbstractItemModel *model)
void layoutChanged(const QList< QPersistentModelIndex > &parents, QAbstractItemModel::LayoutChangeHint hint)
QList< QPersistentModelIndex > savedPersistentIndexes
QItemSelection expandSelection(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) const
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
void triggerLayoutToBeChanged()
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
qsizetype removeIf(Predicate pred)
const T & constFirst() const noexcept
void reserve(qsizetype size)
void append(parameter_type t)
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.
static QObjectPrivate * get(QObject *o)
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
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
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
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.
const_iterator constBegin() const noexcept
const_iterator constEnd() const noexcept
iterator erase(const_iterator i)
Exception-safe wrapper around QObject::blockSignals().
int rowCount(const QModelIndex &parent=QModelIndex()) const override
If the database supports returning the size of a query (see QSqlDriver::hasFeature()),...
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.
DBusConnection * connection
#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 ModelIndexContainer qSelectionIndexes(const QItemSelection &selection)
static void indexesFromRange(const QItemSelectionRange &range, ModelIndexContainer &result)
static QList< std::pair< QPersistentModelIndex, uint > > qSelectionPersistentRowLengths(const QItemSelection &sel)
QDebug operator<<(QDebug dbg, const QItemSelectionRange &range)
static bool isSelectableAndEnabled(Qt::ItemFlags flags)
static void rowLengthsFromRange(const QItemSelectionRange &range, QList< std::pair< QPersistentModelIndex, uint > > &result)
static QItemSelection mergeRowLengths(const QList< std::pair< QPersistentModelIndex, uint > > &rowLengths)
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)
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
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