/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qitemselectionmodel.h"
#include <private/qitemselectionmodel_p.h>
#include <qdebug.h>

#include <algorithm>
#include <functional>

QT_BEGIN_NAMESPACE

/*!
    \class QItemSelectionRange
    \inmodule QtCore

    \brief The QItemSelectionRange class manages information about a
    range of selected items in a model.

    \ingroup model-view

    A QItemSelectionRange contains information about a range of
    selected items in a model. A range of items is a contiguous array
    of model items, extending to cover a number of adjacent rows and
    columns with a common parent item; this can be visualized as a
    two-dimensional block of cells in a table. A selection range has a
    top(), left() a bottom(), right() and a parent().

    The QItemSelectionRange class is one of the \l{Model/View Classes}
    and is part of Qt's \l{Model/View Programming}{model/view framework}.

    The model items contained in the selection range can be obtained
    using the indexes() function. Use QItemSelectionModel::selectedIndexes()
    to get a list of all selected items for a view.

    You can determine whether a given model item lies within a
    particular range by using the contains() function. Ranges can also
    be compared using the overloaded operators for equality and
    inequality, and the intersects() function allows you to determine
    whether two ranges overlap.

    \sa {Model/View Programming}, QAbstractItemModel, QItemSelection,
        QItemSelectionModel
*/

/*!
    \fn QItemSelectionRange::QItemSelectionRange()

    Constructs an empty selection range.
*/

/*!
    \fn QItemSelectionRange::QItemSelectionRange(const QItemSelectionRange &other)

    Copy constructor. Constructs a new selection range with the same contents
    as the \a other range given.

*/

/*!
    \fn QItemSelectionRange::QItemSelectionRange(const QModelIndex &topLeft, const QModelIndex &bottomRight)

    Constructs a new selection range containing only the index specified
    by the \a topLeft and the index \a bottomRight.

*/

/*!
    \fn QItemSelectionRange::QItemSelectionRange(const QModelIndex &index)

    Constructs a new selection range containing only the model item specified
    by the model index \a index.
*/

/*!
    \fn QItemSelectionRange::swap(QItemSelectionRange &other)
    \since 5.6

    Swaps this selection range's contents with \a other.
    This function is very fast and never fails.
*/

/*!
    \fn int QItemSelectionRange::top() const

    Returns the row index corresponding to the uppermost selected row in the
    selection range.

*/

/*!
    \fn int QItemSelectionRange::left() const

    Returns the column index corresponding to the leftmost selected column in the
    selection range.
*/

/*!
    \fn int QItemSelectionRange::bottom() const

    Returns the row index corresponding to the lowermost selected row in the
    selection range.

*/

/*!
    \fn int QItemSelectionRange::right() const

    Returns the column index corresponding to the rightmost selected column in
    the selection range.

*/

/*!
    \fn int QItemSelectionRange::width() const

    Returns the number of selected columns in the selection range.

*/

/*!
    \fn int QItemSelectionRange::height() const

    Returns the number of selected rows in the selection range.

*/

/*!
    \fn const QAbstractItemModel *QItemSelectionRange::model() const

    Returns the model that the items in the selection range belong to.
*/

/*!
    \fn QModelIndex QItemSelectionRange::topLeft() const

    Returns the index for the item located at the top-left corner of
    the selection range.

    \sa top(), left(), bottomRight()
*/

/*!
    \fn QModelIndex QItemSelectionRange::bottomRight() const

    Returns the index for the item located at the bottom-right corner
    of the selection range.

    \sa bottom(), right(), topLeft()
*/

/*!
    \fn QModelIndex QItemSelectionRange::parent() const

    Returns the parent model item index of the items in the selection range.

*/

/*!
    \fn bool QItemSelectionRange::contains(const QModelIndex &index) const

    Returns \c true if the model item specified by the \a index lies within the
    range of selected items; otherwise returns \c false.
*/

/*!
    \fn bool QItemSelectionRange::contains(int row, int column,
                                           const QModelIndex &parentIndex) const
    \overload

    Returns \c true if the model item specified by (\a row, \a column)
    and with \a parentIndex as the parent item lies within the range
    of selected items; otherwise returns \c false.
*/

/*!
    \fn bool QItemSelectionRange::intersects(const QItemSelectionRange &other) const

    Returns \c true if this selection range intersects (overlaps with) the \a other
    range given; otherwise returns \c false.

*/
bool QItemSelectionRange::intersects(const QItemSelectionRange &other) const
{
    // isValid() and parent() last since they are more expensive
    return (model() == other.model()
            && ((top() <= other.top() && bottom() >= other.top())
                || (top() >= other.top() && top() <= other.bottom()))
            && ((left() <= other.left() && right() >= other.left())
                || (left() >= other.left() && left() <= other.right()))
            && parent() == other.parent()
            && isValid() && other.isValid()
            );
}

/*!
    \fn QItemSelectionRange QItemSelectionRange::intersect(const QItemSelectionRange &other) const
    \obsolete

    Use intersected(\a other) instead.
*/

/*!
    \fn QItemSelectionRange QItemSelectionRange::intersected(const QItemSelectionRange &other) const
    \since 4.2

    Returns a new selection range containing only the items that are found in
    both the selection range and the \a other selection range.
*/

QItemSelectionRange QItemSelectionRange::intersected(const QItemSelectionRange &other) const
{
    if (model() == other.model() && parent() == other.parent()) {
        QModelIndex topLeft = model()->index(qMax(top(), other.top()),
                                             qMax(left(), other.left()),
                                             other.parent());
        QModelIndex bottomRight = model()->index(qMin(bottom(), other.bottom()),
                                                 qMin(right(), other.right()),
                                                 other.parent());
        return QItemSelectionRange(topLeft, bottomRight);
    }
    return QItemSelectionRange();
}

/*!
    \fn bool QItemSelectionRange::operator==(const QItemSelectionRange &other) const

    Returns \c true if the selection range is exactly the same as the \a other
    range given; otherwise returns \c false.

*/

/*!
    \fn bool QItemSelectionRange::operator!=(const QItemSelectionRange &other) const

    Returns \c true if the selection range differs from the \a other range given;
    otherwise returns \c false.

*/

/*!
    Returns \c true if the selection range is less than the \a other
    range given; otherwise returns \c false.

    The less than calculation is not directly useful to developers - the way that ranges
    with different parents compare is not defined. This operator only exists so that the
    class can be used with QMap.

*/
bool QItemSelectionRange::operator<(const QItemSelectionRange &other) const
{
    // ### Qt 6: This is inconsistent with op== and needs to be fixed, nay,
    // ###       removed, but cannot, because it was inline up to and including 5.9

    // Comparing parents will compare the models, but if two equivalent ranges
    // in two different models have invalid parents, they would appear the same
    if (other.tl.model() == tl.model()) {
        // parent has to be calculated, so we only do so once.
        const QModelIndex topLeftParent = tl.parent();
        const QModelIndex otherTopLeftParent = other.tl.parent();
        if (topLeftParent == otherTopLeftParent) {
            if (other.tl.row() == tl.row()) {
                if (other.tl.column() == tl.column()) {
                    if (other.br.row() == br.row()) {
                        return br.column() < other.br.column();
                    }
                    return br.row() < other.br.row();
                }
                return tl.column() < other.tl.column();
            }
            return tl.row() < other.tl.row();
        }
        return topLeftParent < otherTopLeftParent;
    }

    std::less<const QAbstractItemModel *> less;
    return less(tl.model(), other.tl.model());
}

/*!
    \fn bool QItemSelectionRange::isValid() const

    Returns \c true if the selection range is valid; otherwise returns \c false.

*/

static void rowLengthsFromRange(const QItemSelectionRange &range, QVector<QPair<QPersistentModelIndex, uint> > &result)
{
    if (range.isValid() && range.model()) {
        const QModelIndex topLeft = range.topLeft();
        const int bottom = range.bottom();
        const uint width = range.width();
        const int column = topLeft.column();
        for (int row = topLeft.row(); row <= bottom; ++row) {
            // We don't need to keep track of ItemIsSelectable and ItemIsEnabled here. That is
            // required in indexesFromRange() because that method is called from public API
            // which requires the limitation.
            result.push_back(qMakePair(QPersistentModelIndex(topLeft.sibling(row, column)), width));
        }
    }
}

template<typename ModelIndexContainer>
static void indexesFromRange(const QItemSelectionRange &range, ModelIndexContainer &result)
{
    if (range.isValid() && range.model()) {
        const QModelIndex topLeft = range.topLeft();
        const int bottom = range.bottom();
        const int right = range.right();
        for (int row = topLeft.row(); row <= bottom; ++row) {
            const QModelIndex columnLeader = topLeft.sibling(row, topLeft.column());
            for (int column = topLeft.column(); column <= right; ++column) {
                QModelIndex index = columnLeader.sibling(row, column);
                Qt::ItemFlags flags = range.model()->flags(index);
                if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled))
                    result.push_back(index);
            }
        }
    }
}

template<typename ModelIndexContainer>
static ModelIndexContainer qSelectionIndexes(const QItemSelection &selection)
{
    ModelIndexContainer result;
    for (const auto &range : selection)
        indexesFromRange(range, result);
    return result;
}

/*!
    Returns \c true if the selection range contains no selectable item
    \since 4.7
*/

bool QItemSelectionRange::isEmpty() const
{
    if (!isValid() || !model())
        return true;

    for (int column = left(); column <= right(); ++column) {
        for (int row = top(); row <= bottom(); ++row) {
            QModelIndex index = model()->index(row, column, parent());
            Qt::ItemFlags flags = model()->flags(index);
            if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled))
                return false;
        }
    }
    return true;
}

/*!
    Returns the list of model index items stored in the selection.
*/

QModelIndexList QItemSelectionRange::indexes() const
{
    QModelIndexList result;
    indexesFromRange(*this, result);
    return result;
}

/*!
    \class QItemSelection
    \inmodule QtCore

    \brief The QItemSelection class manages information about selected items in a model.

    \ingroup model-view

    A QItemSelection describes the items in a model that have been
    selected by the user. A QItemSelection is basically a list of
    selection ranges, see QItemSelectionRange. It provides functions for
    creating and manipulating selections, and selecting a range of items
    from a model.

    The QItemSelection class is one of the \l{Model/View Classes}
    and is part of Qt's \l{Model/View Programming}{model/view framework}.

    An item selection can be constructed and initialized to contain a
    range of items from an existing model. The following example constructs
    a selection that contains a range of items from the given \c model,
    beginning at the \c topLeft, and ending at the \c bottomRight.

    \snippet code/src_gui_itemviews_qitemselectionmodel.cpp 0

    An empty item selection can be constructed, and later populated as
    required. So, if the model is going to be unavailable when we construct
    the item selection, we can rewrite the above code in the following way:

    \snippet code/src_gui_itemviews_qitemselectionmodel.cpp 1

    QItemSelection saves memory, and avoids unnecessary work, by working with
    selection ranges rather than recording the model item index for each
    item in the selection. Generally, an instance of this class will contain
    a list of non-overlapping selection ranges.

    Use merge() to merge one item selection into another without making
    overlapping ranges. Use split() to split one selection range into
    smaller ranges based on a another selection range.

    \sa {Model/View Programming}, QItemSelectionModel
*/

/*!
    \fn QItemSelection::QItemSelection()

    Constructs an empty selection.
*/

/*!
    Constructs an item selection that extends from the top-left model item,
    specified by the \a topLeft index, to the bottom-right item, specified
    by \a bottomRight.
*/
QItemSelection::QItemSelection(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
    select(topLeft, bottomRight);
}

/*!
    Adds the items in the range that extends from the top-left model
    item, specified by the \a topLeft index, to the bottom-right item,
    specified by \a bottomRight to the list.

    \note \a topLeft and \a bottomRight must have the same parent.
*/
void QItemSelection::select(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
    if (!topLeft.isValid() || !bottomRight.isValid())
        return;

    if ((topLeft.model() != bottomRight.model())
        || topLeft.parent() != bottomRight.parent()) {
        qWarning("Can't select indexes from different model or with different parents");
        return;
    }
    if (topLeft.row() > bottomRight.row() || topLeft.column() > bottomRight.column()) {
        int top = qMin(topLeft.row(), bottomRight.row());
        int bottom = qMax(topLeft.row(), bottomRight.row());
        int left = qMin(topLeft.column(), bottomRight.column());
        int right = qMax(topLeft.column(), bottomRight.column());
        QModelIndex tl = topLeft.sibling(top, left);
        QModelIndex br = bottomRight.sibling(bottom, right);
        append(QItemSelectionRange(tl, br));
        return;
    }
    append(QItemSelectionRange(topLeft, bottomRight));
}

/*!
    Returns \c true if the selection contains the given \a index; otherwise
    returns \c false.
*/

bool QItemSelection::contains(const QModelIndex &index) const
{
    if (index.flags() & Qt::ItemIsSelectable) {
        QList<QItemSelectionRange>::const_iterator it = begin();
        for (; it != end(); ++it)
            if ((*it).contains(index))
                return true;
    }
    return false;
}

/*!
    Returns a list of model indexes that correspond to the selected items.
*/

QModelIndexList QItemSelection::indexes() const
{
    return qSelectionIndexes<QModelIndexList>(*this);
}

static QVector<QPair<QPersistentModelIndex, uint> > qSelectionPersistentRowLengths(const QItemSelection &sel)
{
    QVector<QPair<QPersistentModelIndex, uint> > result;
    for (const QItemSelectionRange &range : sel)
        rowLengthsFromRange(range, result);
    return result;
}

/*!
    Merges the \a other selection with this QItemSelection using the
    \a command given. This method guarantees that no ranges are overlapping.

    Note that only QItemSelectionModel::Select,
    QItemSelectionModel::Deselect, and QItemSelectionModel::Toggle are
    supported.

    \sa split()
*/
void QItemSelection::merge(const QItemSelection &other, QItemSelectionModel::SelectionFlags command)
{
    if (other.isEmpty() ||
          !(command & QItemSelectionModel::Select ||
          command & QItemSelectionModel::Deselect ||
          command & QItemSelectionModel::Toggle))
        return;

    QItemSelection newSelection = other;
    // Collect intersections
    QItemSelection intersections;
    QItemSelection::iterator it = newSelection.begin();
    while (it != newSelection.end()) {
        if (!(*it).isValid()) {
            it = newSelection.erase(it);
            continue;
        }
        for (int t = 0; t < count(); ++t) {
            if ((*it).intersects(at(t)))
                intersections.append(at(t).intersected(*it));
        }
        ++it;
    }

    //  Split the old (and new) ranges using the intersections
    for (int i = 0; i < intersections.count(); ++i) { // for each intersection
        for (int t = 0; t < count();) { // splitt each old range
            if (at(t).intersects(intersections.at(i))) {
                split(at(t), intersections.at(i), this);
                removeAt(t);
            } else {
                ++t;
            }
        }
        // only split newSelection if Toggle is specified
        for (int n = 0; (command & QItemSelectionModel::Toggle) && n < newSelection.count();) {
            if (newSelection.at(n).intersects(intersections.at(i))) {
                split(newSelection.at(n), intersections.at(i), &newSelection);
                newSelection.removeAt(n);
            } else {
                ++n;
            }
        }
    }
    // do not add newSelection for Deselect
    if (!(command & QItemSelectionModel::Deselect))
        operator+=(newSelection);
}

/*!
    Splits the selection \a range using the selection \a other range.
    Removes all items in \a other from \a range and puts the result in \a result.
    This can be compared with the semantics of the \e subtract operation of a set.
    \sa merge()
*/

void QItemSelection::split(const QItemSelectionRange &range,
                           const QItemSelectionRange &other, QItemSelection *result)
{
    if (range.parent() != other.parent() || range.model() != other.model())
        return;

    QModelIndex parent = other.parent();
    int top = range.top();
    int left = range.left();
    int bottom = range.bottom();
    int right = range.right();
    int other_top = other.top();
    int other_left = other.left();
    int other_bottom = other.bottom();
    int other_right = other.right();
    const QAbstractItemModel *model = range.model();
    Q_ASSERT(model);
    if (other_top > top) {
        QModelIndex tl = model->index(top, left, parent);
        QModelIndex br = model->index(other_top - 1, right, parent);
        result->append(QItemSelectionRange(tl, br));
        top = other_top;
    }
    if (other_bottom < bottom) {
        QModelIndex tl = model->index(other_bottom + 1, left, parent);
        QModelIndex br = model->index(bottom, right, parent);
        result->append(QItemSelectionRange(tl, br));
        bottom = other_bottom;
    }
    if (other_left > left) {
        QModelIndex tl = model->index(top, left, parent);
        QModelIndex br = model->index(bottom, other_left - 1, parent);
        result->append(QItemSelectionRange(tl, br));
        left = other_left;
    }
    if (other_right < right) {
        QModelIndex tl = model->index(top, other_right + 1, parent);
        QModelIndex br = model->index(bottom, right, parent);
        result->append(QItemSelectionRange(tl, br));
        right = other_right;
    }
}


void QItemSelectionModelPrivate::initModel(QAbstractItemModel *m)
{
    struct Cx {
        const char *signal;
        const char *slot;
    };
    static const Cx connections[] = {
        { SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
          SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)) },
        { SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
          SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)) },
        { SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
          SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int)) },
        { SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
          SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int)) },
        { SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
          SLOT(_q_layoutAboutToBeChanged()) },
        { SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
          SLOT(_q_layoutAboutToBeChanged()) },
        { SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
          SLOT(_q_layoutChanged()) },
        { SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
          SLOT(_q_layoutChanged()) },
        { SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
          SLOT(_q_layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)) },
        { SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
          SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)) },
        { SIGNAL(modelReset()),
          SLOT(reset()) },
        { 0, 0 }
    };

    if (model == m)
        return;

    Q_Q(QItemSelectionModel);
    if (model) {
        for (const Cx *cx = &connections[0]; cx->signal; cx++)
            QObject::disconnect(model, cx->signal, q, cx->slot);
        q->reset();
    }
    model = m;
    if (model) {
        for (const Cx *cx = &connections[0]; cx->signal; cx++)
            QObject::connect(model, cx->signal, q, cx->slot);
    }
}

/*!
    \internal

    returns a QItemSelection where all ranges have been expanded to:
    Rows: left: 0 and right: columnCount()-1
    Columns: top: 0 and bottom: rowCount()-1
*/

QItemSelection QItemSelectionModelPrivate::expandSelection(const QItemSelection &selection,
                                                           QItemSelectionModel::SelectionFlags command) const
{
    if (selection.isEmpty() && !((command & QItemSelectionModel::Rows) ||
                                 (command & QItemSelectionModel::Columns)))
        return selection;

    QItemSelection expanded;
    if (command & QItemSelectionModel::Rows) {
        for (int i = 0; i < selection.count(); ++i) {
            QModelIndex parent = selection.at(i).parent();
            int colCount = model->columnCount(parent);
            QModelIndex tl = model->index(selection.at(i).top(), 0, parent);
            QModelIndex br = model->index(selection.at(i).bottom(), colCount - 1, parent);
            //we need to merge because the same row could have already been inserted
            expanded.merge(QItemSelection(tl, br), QItemSelectionModel::Select);
        }
    }
    if (command & QItemSelectionModel::Columns) {
        for (int i = 0; i < selection.count(); ++i) {
            QModelIndex parent = selection.at(i).parent();
            int rowCount = model->rowCount(parent);
            QModelIndex tl = model->index(0, selection.at(i).left(), parent);
            QModelIndex br = model->index(rowCount - 1, selection.at(i).right(), parent);
            //we need to merge because the same column could have already been inserted
            expanded.merge(QItemSelection(tl, br), QItemSelectionModel::Select);
        }
    }
    return expanded;
}

/*!
    \internal
*/
void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &parent,
                                                         int start, int end)
{
    Q_Q(QItemSelectionModel);
    finalize();

    // update current index
    if (currentIndex.isValid() && parent == currentIndex.parent()
        && currentIndex.row() >= start && currentIndex.row() <= end) {
        QModelIndex old = currentIndex;
        if (start > 0) // there are rows left above the change
            currentIndex = model->index(start - 1, old.column(), parent);
        else if (model && end < model->rowCount(parent) - 1) // there are rows left below the change
            currentIndex = model->index(end + 1, old.column(), parent);
        else // there are no rows left in the table
            currentIndex = QModelIndex();
        emit q->currentChanged(currentIndex, old);
        emit q->currentRowChanged(currentIndex, old);
        if (currentIndex.column() != old.column())
            emit q->currentColumnChanged(currentIndex, old);
    }

    QItemSelection deselected;
    QItemSelection newParts;
    QItemSelection::iterator it = ranges.begin();
    while (it != ranges.end()) {
        if (it->topLeft().parent() != parent) {  // Check parents until reaching root or contained in range
            QModelIndex itParent = it->topLeft().parent();
            while (itParent.isValid() && itParent.parent() != parent)
                itParent = itParent.parent();

            if (itParent.isValid() && start <= itParent.row() && itParent.row() <= end) {
                deselected.append(*it);
                it = ranges.erase(it);
            } else {
                ++it;
            }
        } else if (start <= it->bottom() && it->bottom() <= end    // Full inclusion
                   && start <= it->top() && it->top() <= end) {
            deselected.append(*it);
            it = ranges.erase(it);
        } else if (start <= it->top() && it->top() <= end) {      // Top intersection
            deselected.append(QItemSelectionRange(it->topLeft(), model->index(end, it->right(), it->parent())));
            *it = QItemSelectionRange(model->index(end + 1, it->left(), it->parent()), it->bottomRight());
            ++it;
        } else if (start <= it->bottom() && it->bottom() <= end) {    // Bottom intersection
            deselected.append(QItemSelectionRange(model->index(start, it->left(), it->parent()), it->bottomRight()));
            *it = QItemSelectionRange(it->topLeft(), model->index(start - 1, it->right(), it->parent()));
            ++it;
        } else if (it->top() < start && end < it->bottom()) { // Middle intersection
            // If the parent contains (1, 2, 3, 4, 5, 6, 7, 8) and [3, 4, 5, 6] is selected,
            // and [4, 5] is removed, we need to split [3, 4, 5, 6] into [3], [4, 5] and [6].
            // [4, 5] is appended to deselected, and [3] and [6] remain part of the selection
            // in ranges.
            const QItemSelectionRange removedRange(model->index(start, it->left(), it->parent()),
                                                    model->index(end, it->right(), it->parent()));
            deselected.append(removedRange);
            QItemSelection::split(*it, removedRange, &newParts);
            it = ranges.erase(it);
        } else
            ++it;
    }
    ranges.append(newParts);

    if (!deselected.isEmpty())
        emit q->selectionChanged(QItemSelection(), deselected);
}

/*!
    \internal
*/
void QItemSelectionModelPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &parent,
                                                            int start, int end)
{
    Q_Q(QItemSelectionModel);

    // update current index
    if (currentIndex.isValid() && parent == currentIndex.parent()
        && currentIndex.column() >= start && currentIndex.column() <= end) {
        QModelIndex old = currentIndex;
        if (start > 0) // there are columns to the left of the change
            currentIndex = model->index(old.row(), start - 1, parent);
        else if (model && end < model->columnCount() - 1) // there are columns to the right of the change
            currentIndex = model->index(old.row(), end + 1, parent);
        else // there are no columns left in the table
            currentIndex = QModelIndex();
        emit q->currentChanged(currentIndex, old);
        if (currentIndex.row() != old.row())
            emit q->currentRowChanged(currentIndex, old);
        emit q->currentColumnChanged(currentIndex, old);
    }

    // update selections
    QModelIndex tl = model->index(0, start, parent);
    QModelIndex br = model->index(model->rowCount(parent) - 1, end, parent);
    q->select(QItemSelection(tl, br), QItemSelectionModel::Deselect);
    finalize();
}

/*!
    \internal

    Split selection ranges if columns are about to be inserted in the middle.
*/
void QItemSelectionModelPrivate::_q_columnsAboutToBeInserted(const QModelIndex &parent,
                                                             int start, int end)
{
    Q_UNUSED(end);
    finalize();
    QList<QItemSelectionRange> split;
    QList<QItemSelectionRange>::iterator it = ranges.begin();
    for (; it != ranges.end(); ) {
        if ((*it).isValid() && (*it).parent() == parent
            && (*it).left() < start && (*it).right() >= start) {
            QModelIndex bottomMiddle = model->index((*it).bottom(), start - 1, (*it).parent());
            QItemSelectionRange left((*it).topLeft(), bottomMiddle);
            QModelIndex topMiddle = model->index((*it).top(), start, (*it).parent());
            QItemSelectionRange right(topMiddle, (*it).bottomRight());
            it = ranges.erase(it);
            split.append(left);
            split.append(right);
        } else {
            ++it;
        }
    }
    ranges += split;
}

/*!
    \internal

    Split selection ranges if rows are about to be inserted in the middle.
*/
void QItemSelectionModelPrivate::_q_rowsAboutToBeInserted(const QModelIndex &parent,
                                                          int start, int end)
{
    Q_UNUSED(end);
    finalize();
    QList<QItemSelectionRange> split;
    QList<QItemSelectionRange>::iterator it = ranges.begin();
    for (; it != ranges.end(); ) {
        if ((*it).isValid() && (*it).parent() == parent
            && (*it).top() < start && (*it).bottom() >= start) {
            QModelIndex middleRight = model->index(start - 1, (*it).right(), (*it).parent());
            QItemSelectionRange top((*it).topLeft(), middleRight);
            QModelIndex middleLeft = model->index(start, (*it).left(), (*it).parent());
            QItemSelectionRange bottom(middleLeft, (*it).bottomRight());
            it = ranges.erase(it);
            split.append(top);
            split.append(bottom);
        } else {
            ++it;
        }
    }
    ranges += split;
}

/*!
    \internal

    Split selection into individual (persistent) indexes. This is done in
    preparation for the layoutChanged() signal, where the indexes can be
    merged again.
*/
void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint hint)
{
    savedPersistentIndexes.clear();
    savedPersistentCurrentIndexes.clear();
    savedPersistentRowLengths.clear();
    savedPersistentCurrentRowLengths.clear();

    // optimization for when all indexes are selected
    // (only if there is lots of items (1000) because this is not entirely correct)
    if (ranges.isEmpty() && currentSelection.count() == 1) {
        QItemSelectionRange range = currentSelection.constFirst();
        QModelIndex parent = range.parent();
        tableRowCount = model->rowCount(parent);
        tableColCount = model->columnCount(parent);
        if (tableRowCount * tableColCount > 1000
            && range.top() == 0
            && range.left() == 0
            && range.bottom() == tableRowCount - 1
            && range.right() == tableColCount - 1) {
            tableSelected = true;
            tableParent = parent;
            return;
        }
    }
    tableSelected = false;

    if (hint == QAbstractItemModel::VerticalSortHint) {
        // Special case when we know we're sorting vertically. We can assume that all indexes for columns
        // are displaced the same way, and therefore we only need to track an index from one column per
        // row with a QPersistentModelIndex together with the length of items to the right of it
        // which are displaced the same way.
        // An algorithm which contains the same assumption is used to process layoutChanged.
        savedPersistentRowLengths = qSelectionPersistentRowLengths(ranges);
        savedPersistentCurrentRowLengths = qSelectionPersistentRowLengths(currentSelection);
    } else {
        savedPersistentIndexes = qSelectionIndexes<QVector<QPersistentModelIndex>>(ranges);
        savedPersistentCurrentIndexes = qSelectionIndexes<QVector<QPersistentModelIndex>>(currentSelection);
    }
}
/*!
    \internal
*/
static QItemSelection mergeRowLengths(const QVector<QPair<QPersistentModelIndex, uint> > &rowLengths)
{
    if (rowLengths.isEmpty())
      return QItemSelection();

    QItemSelection result;
    int i = 0;
    while (i < rowLengths.count()) {
        const QPersistentModelIndex &tl = rowLengths.at(i).first;
        if (!tl.isValid()) {
            ++i;
            continue;
        }
        QPersistentModelIndex br = tl;
        const uint length = rowLengths.at(i).second;
        while (++i < rowLengths.count()) {
            const QPersistentModelIndex &next = rowLengths.at(i).first;
            if (!next.isValid())
                continue;
            const uint nextLength = rowLengths.at(i).second;
            if ((nextLength == length)
                && (next.row() == br.row() + 1)
                && (next.column() == br.column())
                && (next.parent() == br.parent())) {
                br = next;
            } else {
                break;
            }
        }
        result.append(QItemSelectionRange(tl, br.sibling(br.row(), br.column() + length - 1)));
    }
    return result;
}

/*!
    \internal

    Merges \a indexes into an item selection made up of ranges.
    Assumes that the indexes are sorted.
*/
static QItemSelection mergeIndexes(const QVector<QPersistentModelIndex> &indexes)
{
    QItemSelection colSpans;
    // merge columns
    int i = 0;
    while (i < indexes.count()) {
        const QPersistentModelIndex &tl = indexes.at(i);
        if (!tl.isValid()) {
            ++i;
            continue;
        }
        QPersistentModelIndex br = tl;
        QModelIndex brParent = br.parent();
        int brRow = br.row();
        int brColumn = br.column();
        while (++i < indexes.count()) {
            const QPersistentModelIndex &next = indexes.at(i);
            if (!next.isValid())
                continue;
            const QModelIndex nextParent = next.parent();
            const int nextRow = next.row();
            const int nextColumn = next.column();
            if ((nextParent == brParent)
                 && (nextRow == brRow)
                 && (nextColumn == brColumn + 1)) {
                br = next;
                brParent = nextParent;
                brRow = nextRow;
                brColumn = nextColumn;
            } else {
                break;
            }
        }
        colSpans.append(QItemSelectionRange(tl, br));
    }
    // merge rows
    QItemSelection rowSpans;
    i = 0;
    while (i < colSpans.count()) {
        QModelIndex tl = colSpans.at(i).topLeft();
        QModelIndex br = colSpans.at(i).bottomRight();
        QModelIndex prevTl = tl;
        while (++i < colSpans.count()) {
            QModelIndex nextTl = colSpans.at(i).topLeft();
            QModelIndex nextBr = colSpans.at(i).bottomRight();

            if (nextTl.parent() != tl.parent())
                break; // we can't merge selection ranges from different parents

            if ((nextTl.column() == prevTl.column()) && (nextBr.column() == br.column())
                && (nextTl.row() == prevTl.row() + 1) && (nextBr.row() == br.row() + 1)) {
                br = nextBr;
                prevTl = nextTl;
            } else {
                break;
            }
        }
        rowSpans.append(QItemSelectionRange(tl, br));
    }
    return rowSpans;
}

/*!
    \internal

    Sort predicate function for QItemSelectionModelPrivate::_q_layoutChanged(),
    sorting by parent first in addition to operator<(). This is to prevent
    fragmentation of the selection by grouping indexes with the same row, column
    of different parents next to each other, which may happen when a selection
    spans sub-trees.
*/
static bool qt_PersistentModelIndexLessThan(const QPersistentModelIndex &i1, const QPersistentModelIndex &i2)
{
    const QModelIndex parent1 = i1.parent();
    const QModelIndex parent2 = i2.parent();
    return parent1 == parent2 ? i1 < i2 : parent1 < parent2;
}

/*!
    \internal

    Merge the selected indexes into selection ranges again.
*/
void QItemSelectionModelPrivate::_q_layoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint hint)
{
    // special case for when all indexes are selected
    if (tableSelected && tableColCount == model->columnCount(tableParent)
        && tableRowCount == model->rowCount(tableParent)) {
        ranges.clear();
        currentSelection.clear();
        int bottom = tableRowCount - 1;
        int right = tableColCount - 1;
        QModelIndex tl = model->index(0, 0, tableParent);
        QModelIndex br = model->index(bottom, right, tableParent);
        currentSelection << QItemSelectionRange(tl, br);
        tableParent = QModelIndex();
        tableSelected = false;
        return;
    }

    if ((hint != QAbstractItemModel::VerticalSortHint && savedPersistentCurrentIndexes.isEmpty() && savedPersistentIndexes.isEmpty())
     || (hint == QAbstractItemModel::VerticalSortHint && savedPersistentRowLengths.isEmpty() && savedPersistentCurrentRowLengths.isEmpty())) {
        // either the selection was actually empty, or we
        // didn't get the layoutAboutToBeChanged() signal
        return;
    }

    // clear the "old" selection
    ranges.clear();
    currentSelection.clear();

    if (hint != QAbstractItemModel::VerticalSortHint) {
        // sort the "new" selection, as preparation for merging
        std::stable_sort(savedPersistentIndexes.begin(), savedPersistentIndexes.end(),
                         qt_PersistentModelIndexLessThan);
        std::stable_sort(savedPersistentCurrentIndexes.begin(), savedPersistentCurrentIndexes.end(),
                         qt_PersistentModelIndexLessThan);

        // update the selection by merging the individual indexes
        ranges = mergeIndexes(savedPersistentIndexes);
        currentSelection = mergeIndexes(savedPersistentCurrentIndexes);

        // release the persistent indexes
        savedPersistentIndexes.clear();
        savedPersistentCurrentIndexes.clear();
    } else {
        // sort the "new" selection, as preparation for merging
        std::stable_sort(savedPersistentRowLengths.begin(), savedPersistentRowLengths.end());
        std::stable_sort(savedPersistentCurrentRowLengths.begin(), savedPersistentCurrentRowLengths.end());

        // update the selection by merging the individual indexes
        ranges = mergeRowLengths(savedPersistentRowLengths);
        currentSelection = mergeRowLengths(savedPersistentCurrentRowLengths);

        // release the persistent indexes
        savedPersistentRowLengths.clear();
        savedPersistentCurrentRowLengths.clear();
    }
}

/*!
    \class QItemSelectionModel
    \inmodule QtCore

    \brief The QItemSelectionModel class keeps track of a view's selected items.

    \ingroup model-view

    A QItemSelectionModel keeps track of the selected items in a view, or
    in several views onto the same model. It also keeps track of the
    currently selected item in a view.

    The QItemSelectionModel class is one of the \l{Model/View Classes}
    and is part of Qt's \l{Model/View Programming}{model/view framework}.

    The selected items are stored using ranges. Whenever you want to
    modify the selected items use select() and provide either a
    QItemSelection, or a QModelIndex and a QItemSelectionModel::SelectionFlag.

    The QItemSelectionModel takes a two layer approach to selection
    management, dealing with both selected items that have been committed
    and items that are part of the current selection. The current
    selected items are part of the current interactive selection (for
    example with rubber-band selection or keyboard-shift selections).

    To update the currently selected items, use the bitwise OR of
    QItemSelectionModel::Current and any of the other SelectionFlags.
    If you omit the QItemSelectionModel::Current command, a new current
    selection will be created, and the previous one added to the whole
    selection. All functions operate on both layers; for example,
    \l {QTableWidget::selectedItems()}{selecteditems()} will return items from both layers.

    \note Since 5.5, \l{QItemSelectionModel::model()}{model},
    \l{QItemSelectionModel::hasSelection()}{hasSelection}, and
    \l{QItemSelectionModel::currentIndex()}{currentIndex} are meta-object properties.

    \sa {Model/View Programming}, QAbstractItemModel, {Chart Example}
*/

/*!
    Constructs a selection model that operates on the specified item \a model.
*/
QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model)
    : QObject(*new QItemSelectionModelPrivate, model)
{
    d_func()->initModel(model);
}

/*!
    Constructs a selection model that operates on the specified item \a model with \a parent.
*/
QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model, QObject *parent)
    : QObject(*new QItemSelectionModelPrivate, parent)
{
    d_func()->initModel(model);
}

/*!
    \internal
*/
QItemSelectionModel::QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstractItemModel *model)
    : QObject(dd, model)
{
    dd.initModel(model);
}

/*!
    Destroys the selection model.
*/
QItemSelectionModel::~QItemSelectionModel()
{
}

/*!
    Selects the model item \a index using the specified \a command, and emits
    selectionChanged().

    \sa QItemSelectionModel::SelectionFlags
*/
void QItemSelectionModel::select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
{
    QItemSelection selection(index, index);
    select(selection, command);
}

/*!
    \fn void QItemSelectionModel::currentChanged(const QModelIndex &current, const QModelIndex &previous)

    This signal is emitted whenever the current item changes. The \a previous
    model item index is replaced by the \a current index as the selection's
    current item.

    Note that this signal will not be emitted when the item model is reset.

    \sa currentIndex(), setCurrentIndex(), selectionChanged()
*/

/*!
    \fn void QItemSelectionModel::currentColumnChanged(const QModelIndex &current, const QModelIndex &previous)

    This signal is emitted if the \a current item changes and its column is
    different to the column of the \a previous current item.

    Note that this signal will not be emitted when the item model is reset.

    \sa currentChanged(), currentRowChanged(), currentIndex(), setCurrentIndex()
*/

/*!
    \fn void QItemSelectionModel::currentRowChanged(const QModelIndex &current, const QModelIndex &previous)

    This signal is emitted if the \a current item changes and its row is
    different to the row of the \a previous current item.

    Note that this signal will not be emitted when the item model is reset.

    \sa currentChanged(), currentColumnChanged(), currentIndex(), setCurrentIndex()
*/

/*!
    \fn void QItemSelectionModel::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)

    This signal is emitted whenever the selection changes. The change in the
    selection is represented as an item selection of \a deselected items and
    an item selection of \a selected items.

    Note the that the current index changes independently from the selection.
    Also note that this signal will not be emitted when the item model is reset.

    \sa select(), currentChanged()
*/

/*!
    \fn void QItemSelectionModel::modelChanged(QAbstractItemModel *model)
    \since 5.5

    This signal is emitted when the \a model is successfully set with setModel().

    \sa model(), setModel()
*/


/*!
    \enum QItemSelectionModel::SelectionFlag

    This enum describes the way the selection model will be updated.

    \value NoUpdate       No selection will be made.
    \value Clear          The complete selection will be cleared.
    \value Select         All specified indexes will be selected.
    \value Deselect       All specified indexes will be deselected.
    \value Toggle         All specified indexes will be selected or
                          deselected depending on their current state.
    \value Current        The current selection will be updated.
    \value Rows           All indexes will be expanded to span rows.
    \value Columns        All indexes will be expanded to span columns.
    \value SelectCurrent  A combination of Select and Current, provided for
                          convenience.
    \value ToggleCurrent  A combination of Toggle and Current, provided for
                          convenience.
    \value ClearAndSelect A combination of Clear and Select, provided for
                          convenience.
*/

namespace {
namespace QtFunctionObjects {
struct IsNotValid {
    typedef bool result_type;
    struct is_transparent : std::true_type {};
    template <typename T>
    Q_DECL_CONSTEXPR bool operator()(T &t) const noexcept(noexcept(t.isValid()))
    { return !t.isValid(); }
    template <typename T>
    Q_DECL_CONSTEXPR bool operator()(T *t) const noexcept(noexcept(t->isValid()))
    { return !t->isValid(); }
};
}
} // unnamed namespace

/*!
    Selects the item \a selection using the specified \a command, and emits
    selectionChanged().

    \sa QItemSelectionModel::SelectionFlag
*/
void QItemSelectionModel::select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command)
{
    Q_D(QItemSelectionModel);
    if (!d->model) {
        qWarning("QItemSelectionModel: Selecting when no model has been set will result in a no-op.");
        return;
    }
    if (command == NoUpdate)
        return;

    // store old selection
    QItemSelection sel = selection;
    // If d->ranges is non-empty when the source model is reset the persistent indexes
    // it contains will be invalid. We can't clear them in a modelReset slot because that might already
    // be too late if another model observer is connected to the same modelReset slot and is invoked first
    // it might call select() on this selection model before any such QItemSelectionModelPrivate::_q_modelReset() slot
    // is invoked, so it would not be cleared yet. We clear it invalid ranges in it here.
    using namespace QtFunctionObjects;
    d->ranges.erase(std::remove_if(d->ranges.begin(), d->ranges.end(), IsNotValid()),
                    d->ranges.end());

    QItemSelection old = d->ranges;
    old.merge(d->currentSelection, d->currentCommand);

    // expand selection according to SelectionBehavior
    if (command & Rows || command & Columns)
        sel = d->expandSelection(sel, command);

    // clear ranges and currentSelection
    if (command & Clear) {
        d->ranges.clear();
        d->currentSelection.clear();
    }

    // merge and clear currentSelection if Current was not set (ie. start new currentSelection)
    if (!(command & Current))
        d->finalize();

    // update currentSelection
    if (command & Toggle || command & Select || command & Deselect) {
        d->currentCommand = command;
        d->currentSelection = sel;
    }

    // generate new selection, compare with old and emit selectionChanged()
    QItemSelection newSelection = d->ranges;
    newSelection.merge(d->currentSelection, d->currentCommand);
    emitSelectionChanged(newSelection, old);
}

/*!
    Clears the selection model. Emits selectionChanged() and currentChanged().
*/
void QItemSelectionModel::clear()
{
    clearSelection();
    clearCurrentIndex();
}

/*!
    Clears the current index. Emits currentChanged().
 */
void QItemSelectionModel::clearCurrentIndex()
{
    Q_D(QItemSelectionModel);
    QModelIndex previous = d->currentIndex;
    d->currentIndex = QModelIndex();
    if (previous.isValid()) {
        emit currentChanged(d->currentIndex, previous);
        emit currentRowChanged(d->currentIndex, previous);
        emit currentColumnChanged(d->currentIndex, previous);
    }
}

/*!
    Clears the selection model. Does not emit any signals.
*/
void QItemSelectionModel::reset()
{
    const QSignalBlocker blocker(this);
    clear();
}

/*!
    \since 4.2
    Clears the selection in the selection model. Emits selectionChanged().
*/
void QItemSelectionModel::clearSelection()
{
    Q_D(QItemSelectionModel);
    if (d->ranges.count() == 0 && d->currentSelection.count() == 0)
        return;

    select(QItemSelection(), Clear);
}


/*!
    Sets the model item \a index to be the current item, and emits
    currentChanged(). The current item is used for keyboard navigation and
    focus indication; it is independent of any selected items, although a
    selected item can also be the current item.

    Depending on the specified \a command, the \a index can also become part
    of the current selection.
    \sa select()
*/
void QItemSelectionModel::setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
{
    Q_D(QItemSelectionModel);
    if (!d->model) {
        qWarning("QItemSelectionModel: Setting the current index when no model has been set will result in a no-op.");
        return;
    }
    if (index == d->currentIndex) {
        if (command != NoUpdate)
            select(index, command); // select item
        return;
    }
    QPersistentModelIndex previous = d->currentIndex;
    d->currentIndex = index; // set current before emitting selection changed below
    if (command != NoUpdate)
        select(d->currentIndex, command); // select item
    emit currentChanged(d->currentIndex, previous);
    if (d->currentIndex.row() != previous.row() ||
            d->currentIndex.parent() != previous.parent())
        emit currentRowChanged(d->currentIndex, previous);
    if (d->currentIndex.column() != previous.column() ||
            d->currentIndex.parent() != previous.parent())
        emit currentColumnChanged(d->currentIndex, previous);
}

/*!
    Returns the model item index for the current item, or an invalid index
    if there is no current item.
*/
QModelIndex QItemSelectionModel::currentIndex() const
{
    return static_cast<QModelIndex>(d_func()->currentIndex);
}

/*!
    Returns \c true if the given model item \a index is selected.
*/
bool QItemSelectionModel::isSelected(const QModelIndex &index) const
{
    Q_D(const QItemSelectionModel);
    if (d->model != index.model() || !index.isValid())
        return false;

    bool selected = false;
    //  search model ranges
    QList<QItemSelectionRange>::const_iterator it = d->ranges.begin();
    for (; it != d->ranges.end(); ++it) {
        if ((*it).isValid() && (*it).contains(index)) {
            selected = true;
            break;
        }
    }

    // check  currentSelection
    if (d->currentSelection.count()) {
        if ((d->currentCommand & Deselect) && selected)
            selected = !d->currentSelection.contains(index);
        else if (d->currentCommand & Toggle)
            selected ^= d->currentSelection.contains(index);
        else if ((d->currentCommand & Select) && !selected)
            selected = d->currentSelection.contains(index);
    }

    if (selected) {
        Qt::ItemFlags flags = d->model->flags(index);
        return (flags & Qt::ItemIsSelectable);
    }

    return false;
}

/*!
    Returns \c true if all items are selected in the \a row with the given
    \a parent.

    Note that this function is usually faster than calling isSelected()
    on all items in the same row and that unselectable items are
    ignored.
*/
bool QItemSelectionModel::isRowSelected(int row, const QModelIndex &parent) const
{
    Q_D(const QItemSelectionModel);
    if (!d->model)
        return false;
    if (parent.isValid() && d->model != parent.model())
        return false;

    // return false if row exist in currentSelection (Deselect)
    if (d->currentCommand & Deselect && d->currentSelection.count()) {
        for (int i=0; i<d->currentSelection.count(); ++i) {
            if (d->currentSelection.at(i).parent() == parent &&
                row >= d->currentSelection.at(i).top() &&
                row <= d->currentSelection.at(i).bottom())
                return false;
        }
    }
    // return false if ranges in both currentSelection and ranges
    // intersect and have the same row contained
    if (d->currentCommand & Toggle && d->currentSelection.count()) {
        for (int i=0; i<d->currentSelection.count(); ++i)
            if (d->currentSelection.at(i).top() <= row &&
                d->currentSelection.at(i).bottom() >= row)
                for (int j=0; j<d->ranges.count(); ++j)
                    if (d->ranges.at(j).top() <= row && d->ranges.at(j).bottom() >= row
                        && d->currentSelection.at(i).intersected(d->ranges.at(j)).isValid())
                        return false;
    }

    auto isSelectable = [&](int row, int column) {
        Qt::ItemFlags flags = d->model->index(row, column, parent).flags();
        return (flags & Qt::ItemIsSelectable);
    };

    const int colCount = d->model->columnCount(parent);
    int unselectable = 0;
    // add ranges and currentSelection and check through them all
    QList<QItemSelectionRange>::const_iterator it;
    QList<QItemSelectionRange> joined = d->ranges;
    if (d->currentSelection.count())
        joined += d->currentSelection;
    for (int column = 0; column < colCount; ++column) {
        if (!isSelectable(row, column)) {
            ++unselectable;
            continue;
        }

        for (it = joined.constBegin(); it != joined.constEnd(); ++it) {
            if ((*it).contains(row, column, parent)) {
                for (int i = column; i <= (*it).right(); ++i) {
                    if (!isSelectable(row, i))
                        ++unselectable;
                }

                column = qMax(column, (*it).right());
                break;
            }
        }
        if (it == joined.constEnd())
            return false;
    }
    return unselectable < colCount;
}

/*!
    Returns \c true if all items are selected in the \a column with the given
    \a parent.

    Note that this function is usually faster than calling isSelected()
    on all items in the same column and that unselectable items are
    ignored.
*/
bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent) const
{
    Q_D(const QItemSelectionModel);
    if (!d->model)
        return false;
    if (parent.isValid() && d->model != parent.model())
        return false;

    // return false if column exist in currentSelection (Deselect)
    if (d->currentCommand & Deselect && d->currentSelection.count()) {
        for (int i = 0; i < d->currentSelection.count(); ++i) {
            if (d->currentSelection.at(i).parent() == parent &&
                column >= d->currentSelection.at(i).left() &&
                column <= d->currentSelection.at(i).right())
                return false;
        }
    }
    // return false if ranges in both currentSelection and the selection model
    // intersect and have the same column contained
    if (d->currentCommand & Toggle && d->currentSelection.count()) {
        for (int i = 0; i < d->currentSelection.count(); ++i) {
            if (d->currentSelection.at(i).left() <= column &&
                d->currentSelection.at(i).right() >= column) {
                for (int j = 0; j < d->ranges.count(); ++j) {
                    if (d->ranges.at(j).left() <= column && d->ranges.at(j).right() >= column
                        && d->currentSelection.at(i).intersected(d->ranges.at(j)).isValid()) {
                        return false;
                    }
                }
            }
        }
    }

    auto isSelectable = [&](int row, int column) {
        Qt::ItemFlags flags = d->model->index(row, column, parent).flags();
        return (flags & Qt::ItemIsSelectable);
    };
    const int rowCount = d->model->rowCount(parent);
    int unselectable = 0;

    // add ranges and currentSelection and check through them all
    QList<QItemSelectionRange>::const_iterator it;
    QList<QItemSelectionRange> joined = d->ranges;
    if (d->currentSelection.count())
        joined += d->currentSelection;
    for (int row = 0; row < rowCount; ++row) {
        if (!isSelectable(row, column)) {
            ++unselectable;
            continue;
        }
        for (it = joined.constBegin(); it != joined.constEnd(); ++it) {
            if ((*it).contains(row, column, parent)) {
                for (int i = row; i <= (*it).bottom(); ++i) {
                    if (!isSelectable(i, column)) {
                        ++unselectable;
                    }
                }
                row = qMax(row, (*it).bottom());
                break;
            }
        }
        if (it == joined.constEnd())
            return false;
    }
    return unselectable < rowCount;
}

/*!
    Returns \c true if there are any items selected in the \a row with the given
    \a parent.
*/
bool QItemSelectionModel::rowIntersectsSelection(int row, const QModelIndex &parent) const
{
    Q_D(const QItemSelectionModel);
    if (!d->model)
        return false;
    if (parent.isValid() && d->model != parent.model())
         return false;

    QItemSelection sel = d->ranges;
    sel.merge(d->currentSelection, d->currentCommand);
    for (const QItemSelectionRange &range : qAsConst(sel)) {
        if (range.parent() != parent)
            return false;
        int top = range.top();
        int bottom = range.bottom();
        int left = range.left();
        int right = range.right();
        if (top <= row && bottom >= row) {
            for (int j = left; j <= right; j++) {
                const Qt::ItemFlags flags = d->model->index(row, j, parent).flags();
                if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled))
                    return true;
            }
        }
    }

    return false;
}

/*!
    Returns \c true if there are any items selected in the \a column with the given
    \a parent.
*/
bool QItemSelectionModel::columnIntersectsSelection(int column, const QModelIndex &parent) const
{
    Q_D(const QItemSelectionModel);
    if (!d->model)
        return false;
    if (parent.isValid() && d->model != parent.model())
        return false;

    QItemSelection sel = d->ranges;
    sel.merge(d->currentSelection, d->currentCommand);
    for (const QItemSelectionRange &range : qAsConst(sel)) {
        if (range.parent() != parent)
            return false;
        int top = range.top();
        int bottom = range.bottom();
        int left = range.left();
        int right = range.right();
        if (left <= column && right >= column) {
            for (int j = top; j <= bottom; j++) {
                const Qt::ItemFlags flags = d->model->index(j, column, parent).flags();
                if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled))
                    return true;
            }
        }
    }

    return false;
}

/*!
    \since 4.2

    Returns \c true if the selection model contains any selection ranges;
    otherwise returns \c false.
*/
bool QItemSelectionModel::hasSelection() const
{
    Q_D(const QItemSelectionModel);
    if (d->currentCommand & (Toggle | Deselect)) {
        QItemSelection sel = d->ranges;
        sel.merge(d->currentSelection, d->currentCommand);
        return !sel.isEmpty();
    } else {
        return !(d->ranges.isEmpty() && d->currentSelection.isEmpty());
    }
}

/*!
    Returns a list of all selected model item indexes. The list contains no
    duplicates, and is not sorted.
*/
QModelIndexList QItemSelectionModel::selectedIndexes() const
{
    Q_D(const QItemSelectionModel);
    QItemSelection selected = d->ranges;
    selected.merge(d->currentSelection, d->currentCommand);
    return selected.indexes();
}

/*!
    \since 4.2
    Returns the indexes in the given \a column for the rows where all columns are selected.

    \sa selectedIndexes(), selectedColumns()
*/

QModelIndexList QItemSelectionModel::selectedRows(int column) const
{
    QModelIndexList indexes;
    //the QSet contains pairs of parent modelIndex
    //and row number
    QSet< QPair<QModelIndex, int> > rowsSeen;

    const QItemSelection ranges = selection();
    for (int i = 0; i < ranges.count(); ++i) {
        const QItemSelectionRange &range = ranges.at(i);
        QModelIndex parent = range.parent();
        for (int row = range.top(); row <= range.bottom(); row++) {
            QPair<QModelIndex, int> rowDef = qMakePair(parent, row);
            if (!rowsSeen.contains(rowDef)) {
                rowsSeen << rowDef;
                if (isRowSelected(row, parent)) {
                    indexes.append(model()->index(row, column, parent));
                }
            }
        }
    }

    return indexes;
}

/*!
    \since 4.2
    Returns the indexes in the given \a row for columns where all rows are selected.

    \sa selectedIndexes(), selectedRows()
*/

QModelIndexList QItemSelectionModel::selectedColumns(int row) const
{
    QModelIndexList indexes;
    //the QSet contains pairs of parent modelIndex
    //and column number
    QSet< QPair<QModelIndex, int> > columnsSeen;

    const QItemSelection ranges = selection();
    for (int i = 0; i < ranges.count(); ++i) {
        const QItemSelectionRange &range = ranges.at(i);
        QModelIndex parent = range.parent();
        for (int column = range.left(); column <= range.right(); column++) {
            QPair<QModelIndex, int> columnDef = qMakePair(parent, column);
            if (!columnsSeen.contains(columnDef)) {
                columnsSeen << columnDef;
                if (isColumnSelected(column, parent)) {
                    indexes.append(model()->index(row, column, parent));
                }
            }
        }
    }

    return indexes;
}

/*!
    Returns the selection ranges stored in the selection model.
*/
const QItemSelection QItemSelectionModel::selection() const
{
    Q_D(const QItemSelectionModel);
    QItemSelection selected = d->ranges;
    selected.merge(d->currentSelection, d->currentCommand);
    // make sure we have no invalid ranges
    // ###  should probably be handled more generic somewhere else
    using namespace QtFunctionObjects;
    selected.erase(std::remove_if(selected.begin(), selected.end(),
                                  IsNotValid()),
                   selected.end());
    return selected;
}

/*!
    \since 5.5

    \property QItemSelectionModel::hasSelection
    \internal
*/
/*!
    \since 5.5

    \property QItemSelectionModel::currentIndex
    \internal
*/
/*!
    \since 5.5

    \property QItemSelectionModel::selectedIndexes
*/

/*!
    \since 5.5

    \property QItemSelectionModel::selection
    \internal
*/
/*!
    \since 5.5

    \property QItemSelectionModel::model
    \internal
*/
/*!
    \since 5.5

    Returns the item model operated on by the selection model.
*/
QAbstractItemModel *QItemSelectionModel::model()
{
    return d_func()->model;
}

/*!
    Returns the item model operated on by the selection model.
*/
const QAbstractItemModel *QItemSelectionModel::model() const
{
    return d_func()->model;
}

/*!
    \since 5.5

    Sets the model to \a model. The modelChanged() signal will be emitted.

    \sa model(), modelChanged()
*/
void QItemSelectionModel::setModel(QAbstractItemModel *model)
{
    Q_D(QItemSelectionModel);
    if (d->model == model)
        return;

    d->initModel(model);
    emit modelChanged(model);
}

/*!
    Compares the two selections \a newSelection and \a oldSelection
    and emits selectionChanged() with the deselected and selected items.
*/
void QItemSelectionModel::emitSelectionChanged(const QItemSelection &newSelection,
                                               const QItemSelection &oldSelection)
{
    // if both selections are empty or equal we return
    if ((oldSelection.isEmpty() && newSelection.isEmpty()) ||
        oldSelection == newSelection)
        return;

    // if either selection is empty we do not need to compare
    if (oldSelection.isEmpty() || newSelection.isEmpty()) {
        emit selectionChanged(newSelection, oldSelection);
        return;
    }

    QItemSelection deselected = oldSelection;
    QItemSelection selected = newSelection;

    // remove equal ranges
    bool advance;
    for (int o = 0; o < deselected.count(); ++o) {
        advance = true;
        for (int s = 0; s < selected.count() && o < deselected.count();) {
            if (deselected.at(o) == selected.at(s)) {
                deselected.removeAt(o);
                selected.removeAt(s);
                advance = false;
            } else {
                ++s;
            }
        }
        if (advance)
            ++o;
    }

    // find intersections
    QItemSelection intersections;
    for (int o = 0; o < deselected.count(); ++o) {
        for (int s = 0; s < selected.count(); ++s) {
            if (deselected.at(o).intersects(selected.at(s)))
                intersections.append(deselected.at(o).intersected(selected.at(s)));
        }
    }

    // compare remaining ranges with intersections and split them to find deselected and selected
    for (int i = 0; i < intersections.count(); ++i) {
        // split deselected
        for (int o = 0; o < deselected.count();) {
            if (deselected.at(o).intersects(intersections.at(i))) {
                QItemSelection::split(deselected.at(o), intersections.at(i), &deselected);
                deselected.removeAt(o);
            } else {
                ++o;
            }
        }
        // split selected
        for (int s = 0; s < selected.count();) {
            if (selected.at(s).intersects(intersections.at(i))) {
                QItemSelection::split(selected.at(s), intersections.at(i), &selected);
                selected.removeAt(s);
            } else {
                ++s;
            }
        }
    }

    if (!selected.isEmpty() || !deselected.isEmpty())
        emit selectionChanged(selected, deselected);
}

#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QItemSelectionRange &range)
{
    QDebugStateSaver saver(dbg);
    dbg.nospace() << "QItemSelectionRange(" << range.topLeft()
                  << ',' << range.bottomRight() << ')';
    return dbg;
}
#endif

QT_END_NAMESPACE

#include "moc_qitemselectionmodel.cpp"
