📄 qsortfilterproxymodel.cpp
字号:
Sorts the given \a source_rows according to current sort column and order.*/void QSortFilterProxyModelPrivate::sort_source_rows( QVector<int> &source_rows, const QModelIndex &source_parent) const{ Q_Q(const QSortFilterProxyModel); if (sort_column >= 0) { if (sort_order == Qt::AscendingOrder) { QSortFilterProxyModelLessThan lt(sort_column, source_parent, model, q); qStableSort(source_rows.begin(), source_rows.end(), lt); } else { QSortFilterProxyModelGreaterThan gt(sort_column, source_parent, model, q); qStableSort(source_rows.begin(), source_rows.end(), gt); } }}/*! \internal Given source-to-proxy mapping \a source_to_proxy and the set of source items \a source_items (which are part of that mapping), determines the corresponding proxy item intervals that should be removed from the proxy model. The result is a vector of pairs, where each pair represents a (start, end) tuple, sorted in ascending order.*/QVector<QPair<int, int > > QSortFilterProxyModelPrivate::proxy_intervals_for_source_items( const QVector<int> &source_to_proxy, const QVector<int> &source_items) const{ QVector<QPair<int, int> > proxy_intervals; if (source_items.isEmpty()) return proxy_intervals; int source_items_index = 0; while (source_items_index < source_items.size()) { int first_proxy_item = source_to_proxy.at(source_items.at(source_items_index)); Q_ASSERT(first_proxy_item != -1); int last_proxy_item = first_proxy_item; ++source_items_index; // Find end of interval while ((source_items_index < source_items.size()) && (source_to_proxy.at(source_items.at(source_items_index)) == last_proxy_item + 1)) { ++last_proxy_item; ++source_items_index; } // Add interval to result proxy_intervals.append(QPair<int, int>(first_proxy_item, last_proxy_item)); } qStableSort(proxy_intervals.begin(), proxy_intervals.end()); return proxy_intervals;}/*! \internal Given source-to-proxy mapping \a src_to_proxy and proxy-to-source mapping \a proxy_to_source, removes \a source_items from this proxy model. The corresponding proxy items are removed in intervals, so that the proper rows/columnsRemoved(start, end) signals will be generated.*/void QSortFilterProxyModelPrivate::remove_source_items( QVector<int> &source_to_proxy, QVector<int> &proxy_to_source, const QVector<int> &source_items, const QModelIndex &source_parent, Qt::Orientation orient, bool emit_signal){ QModelIndex proxy_parent = QSortFilterProxyModelPrivate::source_to_proxy(source_parent); if (!proxy_parent.isValid() && source_parent.isValid()) return; // nothing to do (already removed) QVector<QPair<int, int> > proxy_intervals; proxy_intervals = proxy_intervals_for_source_items(source_to_proxy, source_items); for (int i = proxy_intervals.size()-1; i >= 0; --i) { QPair<int, int> interval = proxy_intervals.at(i); int proxy_start = interval.first; int proxy_end = interval.second; remove_proxy_interval(source_to_proxy, proxy_to_source, proxy_start, proxy_end, proxy_parent, orient, emit_signal); }}/*! \internal Given source-to-proxy mapping \a source_to_proxy and proxy-to-source mapping \a proxy_to_source, removes items from \a proxy_start to \a proxy_end (inclusive) from this proxy model.*/void QSortFilterProxyModelPrivate::remove_proxy_interval( QVector<int> &source_to_proxy, QVector<int> &proxy_to_source, int proxy_start, int proxy_end, const QModelIndex &proxy_parent, Qt::Orientation orient, bool emit_signal){ Q_Q(QSortFilterProxyModel); if (emit_signal) { if (orient == Qt::Vertical) q->beginRemoveRows(proxy_parent, proxy_start, proxy_end); else q->beginRemoveColumns(proxy_parent, proxy_start, proxy_end); } // Remove items from proxy-to-source mapping proxy_to_source.remove(proxy_start, proxy_end - proxy_start + 1); build_source_to_proxy_mapping(proxy_to_source, source_to_proxy); if (emit_signal) { if (orient == Qt::Vertical) q->endRemoveRows(); else q->endRemoveColumns(); }}/*! \internal Given proxy-to-source mapping \a proxy_to_source and a set of unmapped source items \a source_items, determines the proxy item intervals at which the subsets of source items should be inserted (but does not actually add them to the mapping). The result is a vector of pairs, each pair representing a tuple (start, items), where items is a vector containing the (sorted) source items that should be inserted at that proxy model location.*/QVector<QPair<int, QVector<int > > > QSortFilterProxyModelPrivate::proxy_intervals_for_source_items_to_add( const QVector<int> &proxy_to_source, const QVector<int> &source_items, const QModelIndex &source_parent, Qt::Orientation orient) const{ Q_Q(const QSortFilterProxyModel); QVector<QPair<int, QVector<int> > > proxy_intervals; if (source_items.isEmpty()) return proxy_intervals; int proxy_low = 0; int proxy_item = 0; int source_items_index = 0; QVector<int> source_items_in_interval; bool compare = (orient == Qt::Vertical && sort_column >= 0); while (source_items_index < source_items.size()) { source_items_in_interval.clear(); int first_new_source_item = source_items.at(source_items_index); source_items_in_interval.append(first_new_source_item); ++source_items_index; // Find proxy item at which insertion should be started int proxy_high = proxy_to_source.size() - 1; QModelIndex i1 = compare ? model->index(first_new_source_item, sort_column, source_parent) : QModelIndex(); while (proxy_low <= proxy_high) { proxy_item = (proxy_low + proxy_high) / 2; if (compare) { QModelIndex i2 = model->index(proxy_to_source.at(proxy_item), sort_column, source_parent); if ((sort_order == Qt::AscendingOrder) ? q->lessThan(i1, i2) : q->lessThan(i2, i1)) proxy_high = proxy_item - 1; else proxy_low = proxy_item + 1; } else { if (first_new_source_item < proxy_to_source.at(proxy_item)) proxy_high = proxy_item - 1; else proxy_low = proxy_item + 1; } } proxy_item = proxy_low; // Find the sequence of new source items that should be inserted here if (proxy_item >= proxy_to_source.size()) { for ( ; source_items_index < source_items.size(); ++source_items_index) source_items_in_interval.append(source_items.at(source_items_index)); } else { i1 = compare ? model->index(proxy_to_source.at(proxy_item), sort_column, source_parent) : QModelIndex(); for ( ; source_items_index < source_items.size(); ++source_items_index) { int new_source_item = source_items.at(source_items_index); if (compare) { QModelIndex i2 = model->index(new_source_item, sort_column, source_parent); if ((sort_order == Qt::AscendingOrder) ? q->lessThan(i1, i2) : q->lessThan(i2, i1)) break; } else { if (proxy_to_source.at(proxy_item) < new_source_item) break; } source_items_in_interval.append(new_source_item); } } // Add interval to result proxy_intervals.append(QPair<int, QVector<int> >(proxy_item, source_items_in_interval)); } return proxy_intervals;}/*! \internal Given source-to-proxy mapping \a source_to_proxy and proxy-to-source mapping \a proxy_to_source, inserts the given \a source_items into this proxy model. The source items are inserted in intervals (based on some sorted order), so that the proper rows/columnsInserted(start, end) signals will be generated.*/void QSortFilterProxyModelPrivate::insert_source_items( QVector<int> &source_to_proxy, QVector<int> &proxy_to_source, const QVector<int> &source_items, const QModelIndex &source_parent, Qt::Orientation orient, bool emit_signal){ Q_Q(QSortFilterProxyModel); QModelIndex proxy_parent = QSortFilterProxyModelPrivate::source_to_proxy(source_parent); if (!proxy_parent.isValid() && source_parent.isValid()) return; // nothing to do (source_parent is not mapped) QVector<QPair<int, QVector<int> > > proxy_intervals; proxy_intervals = proxy_intervals_for_source_items_to_add( proxy_to_source, source_items, source_parent, orient); for (int i = proxy_intervals.size()-1; i >= 0; --i) { QPair<int, QVector<int> > interval = proxy_intervals.at(i); int proxy_start = interval.first; QVector<int> source_items = interval.second; int proxy_end = proxy_start + source_items.size() - 1; if (emit_signal) { if (orient == Qt::Vertical) q->beginInsertRows(proxy_parent, proxy_start, proxy_end); else q->beginInsertColumns(proxy_parent, proxy_start, proxy_end); } for (int i = 0; i < source_items.size(); ++i) proxy_to_source.insert(proxy_start + i, source_items.at(i)); build_source_to_proxy_mapping(proxy_to_source, source_to_proxy); if (emit_signal) { if (orient == Qt::Vertical) q->endInsertRows(); else q->endInsertColumns(); } }}/*! \internal Handles source model items insertion (columnsInserted(), rowsInserted()). Determines 1) which of the inserted items to also insert into proxy model (filtering), 2) where to insert the items into the proxy model (sorting), then inserts those items. The items are inserted into the proxy model in intervals (based on sorted order), so that the proper rows/columnsInserted(start, end) signals will be generated.*/void QSortFilterProxyModelPrivate::source_items_inserted( const QModelIndex &source_parent, int start, int end, Qt::Orientation orient){ Q_Q(QSortFilterProxyModel); if ((start < 0) || (end < 0)) return; IndexMap::const_iterator it = source_index_mapping.constFind(source_parent); if (it == source_index_mapping.constEnd()) { if (source_parent.isValid()) { QModelIndex source_grand_parent = source_parent.parent(); it = source_index_mapping.constFind(source_grand_parent); if (it == source_index_mapping.constEnd()) { // Don't care, since we don't have mapping for the grand parent return; } Mapping *gm = it.value(); if (gm->proxy_rows.at(source_parent.row()) == -1) { // Don't care, since parent is filtered return; } } it = create_mapping(source_parent); Mapping *m = it.value(); QModelIndex proxy_parent = source_to_proxy(source_parent); if (m->source_rows.count() > 0) { q->beginInsertRows(proxy_parent, 0, m->source_rows.count() - 1); q->endInsertRows(); } if (m->source_columns.count() > 0) { q->beginInsertColumns(proxy_parent, 0, m->source_columns.count() - 1); q->endInsertColumns(); } return; } Mapping *m = it.value(); QVector<int> &source_to_proxy = (orient == Qt::Vertical) ? m->proxy_rows : m->proxy_columns; QVector<int> &proxy_to_source = (orient == Qt::Vertical) ? m->source_rows : m->source_columns; int delta_item_count = end - start + 1; int old_item_count = source_to_proxy.size(); updateChildrenMapping(source_parent, m, orient, start, end, delta_item_count, false); // Expand source-to-proxy mapping to account for new items source_to_proxy.insert(start, delta_item_count, -1); if (start < old_item_count) { // Adjust existing "stale" indexes in proxy-to-source mapping int proxy_count = proxy_to_source.size(); for (int proxy_item = 0; proxy_item < proxy_count; ++proxy_item) { int source_item = proxy_to_source.at(proxy_item); if (source_item >= start) proxy_to_source.replace(proxy_item, source_item + delta_item_count); } build_source_to_proxy_mapping(proxy_to_source, source_to_proxy); } // Figure out which items to add to mapping based on filter QVector<int> source_items; for (int i = start; i <= end; ++i) { if ((orient == Qt::Vertical) ? q->filterAcceptsRow(i, source_parent) : q->filterAcceptsColumn(i, source_parent)) { source_items.append(i); } } // Sort and insert the items if (orient == Qt::Vertical) // Only sort rows sort_source_rows(source_items, source_parent); insert_source_items(source_to_proxy, proxy_to_source, source_items, source_parent, orient);}/*! \internal Handles source model items removal (columnsAboutToBeRemoved(), rowsAboutToBeRemoved()).*/void QSortFilterProxyModelPrivate::source_items_about_to_be_removed( const QModelIndex &source_parent, int start, int end, Qt::Orientation orient){ if ((start < 0) || (end < 0)) return; IndexMap::const_iterator it = source_index_mapping.constFind(source_parent); if (it == source_index_mapping.constEnd()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -