📄 qsortfilterproxymodel.cpp
字号:
// Don't care, since we don't have mapping for this index 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; // figure out which items to remove QVector<int> source_items_to_remove; 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) && (source_item <= end)) source_items_to_remove.append(source_item); } remove_source_items(source_to_proxy, proxy_to_source, source_items_to_remove, source_parent, orient);}/*! \internal Handles source model items removal (columnsRemoved(), rowsRemoved()).*/void QSortFilterProxyModelPrivate::source_items_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()) { // Don't care, since we don't have mapping for this index 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; if (end >= source_to_proxy.size()) end = source_to_proxy.size() - 1; // Shrink the source-to-proxy mapping to reflect the new item count int delta_item_count = end - start + 1; source_to_proxy.remove(start, delta_item_count); int proxy_count = proxy_to_source.size(); if (proxy_count > source_to_proxy.size()) { // mapping is in an inconsistent state -- redo the whole mapping qWarning("QSortFilterProxyModel: inconsistent changes reported by source model"); remove_from_mapping(source_parent); return; } // Adjust "stale" indexes in proxy-to-source mapping for (int proxy_item = 0; proxy_item < proxy_count; ++proxy_item) { int source_item = proxy_to_source.at(proxy_item); if (source_item >= start) { Q_ASSERT(source_item - delta_item_count >= 0); proxy_to_source.replace(proxy_item, source_item - delta_item_count); } } build_source_to_proxy_mapping(proxy_to_source, source_to_proxy); updateChildrenMapping(source_parent, m, orient, start, end, delta_item_count, true);}/*! \internal updates the mapping of the children when inserting or removing items*/void QSortFilterProxyModelPrivate::updateChildrenMapping(const QModelIndex &source_parent, Mapping *parent_mapping, Qt::Orientation orient, int start, int end, int delta_item_count, bool remove){ // see if any mapped children should be (re)moved QVector<QPair<QModelIndex, Mapping*> > moved_source_index_mappings; QVector<QModelIndex>::iterator it2 = parent_mapping->mapped_children.begin(); for ( ; it2 != parent_mapping->mapped_children.end();) { const QModelIndex source_child_index = *it2; const int pos = (orient == Qt::Vertical) ? source_child_index.row() : source_child_index.column(); if (pos < start) { // not affected ++it2; } else if (remove && pos <= end) { // in the removed interval it2 = parent_mapping->mapped_children.erase(it2); remove_from_mapping(source_child_index); } else { // below the removed items -- recompute the index QModelIndex new_index; const int newpos = remove ? pos - delta_item_count : pos + delta_item_count; if (orient == Qt::Vertical) { new_index = model->index(newpos, source_child_index.column(), source_parent); } else { new_index = model->index(source_child_index.row(), newpos, source_parent); } *it2 = new_index; ++it2; // update mapping Mapping *cm = source_index_mapping.take(source_child_index); Q_ASSERT(cm); // we do not reinsert right away, because the new index might be identical with another, old index moved_source_index_mappings.append(QPair<QModelIndex, Mapping*>(new_index, cm)); } } // reinsert moved, mapped indexes QVector<QPair<QModelIndex, Mapping*> >::iterator it = moved_source_index_mappings.begin(); for (; it != moved_source_index_mappings.end(); ++it) (*it).second->map_iter = source_index_mapping.insert((*it).first, (*it).second);}/*! \internal*/void QSortFilterProxyModelPrivate::proxy_item_range( const QVector<int> &source_to_proxy, const QVector<int> &source_items, int &proxy_low, int &proxy_high) const{ proxy_low = INT_MAX; proxy_high = INT_MIN; foreach (int source_item, source_items) { int proxy_item = source_to_proxy.at(source_item); Q_ASSERT(proxy_item != -1); if (proxy_item < proxy_low) proxy_low = proxy_item; if (proxy_item > proxy_high) proxy_high = proxy_item; }}/*! \internal*/void QSortFilterProxyModelPrivate::build_source_to_proxy_mapping( const QVector<int> &proxy_to_source, QVector<int> &source_to_proxy) const{ source_to_proxy.fill(-1); int proxy_count = proxy_to_source.size(); for (int i = 0; i < proxy_count; ++i) source_to_proxy[proxy_to_source.at(i)] = i;}/*! \internal Maps the persistent proxy indexes to source indexes and returns the list of source indexes.*/QModelIndexList QSortFilterProxyModelPrivate::store_persistent_indexes(){ QModelIndexList source_indexes; int persistent_count = persistent.indexes.count(); for (int i = 0; i < persistent_count; ++i) { QModelIndex proxy_index = persistent.indexes.at(i)->index; QModelIndex source_index = proxy_to_source(proxy_index); source_indexes.append(source_index); } return source_indexes;}/*! \internal Maps \a source_indexes to proxy indexes and stores those as persistent indexes.*/void QSortFilterProxyModelPrivate::update_persistent_indexes( const QModelIndexList &source_indexes){ for (int i = 0; i < source_indexes.count(); ++i) { QModelIndex source_index = source_indexes.at(i); create_mapping(source_index.parent()); QModelIndex proxy_index = source_to_proxy(source_index); persistent.indexes[i]->index = proxy_index; }}/*! \internal Updates the proxy model (adds/removes rows) based on the new filter.*/void QSortFilterProxyModelPrivate::filter_changed(){ QMap<QModelIndex, Mapping *>::const_iterator it; for (it = source_index_mapping.constBegin(); it != source_index_mapping.constEnd(); ++it) { QModelIndex source_parent = it.key(); Mapping *m = it.value(); handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical); handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal); }}/*! \internal*/void QSortFilterProxyModelPrivate::handle_filter_changed( QVector<int> &source_to_proxy, QVector<int> &proxy_to_source, const QModelIndex &source_parent, Qt::Orientation orient){ Q_Q(QSortFilterProxyModel); // Figure out which mapped items to remove QVector<int> source_items_remove; foreach (int source_item, proxy_to_source) { if ((orient == Qt::Vertical) ? !q->filterAcceptsRow(source_item, source_parent) : !q->filterAcceptsColumn(source_item, source_parent)) { // This source item does not satisfy the filter, so it must be removed source_items_remove.append(source_item); } } // Figure out which non-mapped items to insert QVector<int> source_items_insert; int source_count = source_to_proxy.size(); for (int source_item = 0; source_item < source_count; ++source_item) { if (source_to_proxy.at(source_item) == -1) { if ((orient == Qt::Vertical) ? q->filterAcceptsRow(source_item, source_parent) : q->filterAcceptsColumn(source_item, source_parent)) { // This source item satisfies the filter, so it must be added source_items_insert.append(source_item); } } } if (!source_items_remove.isEmpty() || !source_items_insert.isEmpty()) { // Do item removal and insertion remove_source_items(source_to_proxy, proxy_to_source, source_items_remove, source_parent, orient); if (orient == Qt::Vertical) sort_source_rows(source_items_insert, source_parent); insert_source_items(source_to_proxy, proxy_to_source, source_items_insert, source_parent, orient); }}void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &source_top_left, const QModelIndex &source_bottom_right){ Q_Q(QSortFilterProxyModel); if (!source_top_left.isValid() || !source_bottom_right.isValid()) return; QModelIndex source_parent = source_top_left.parent(); IndexMap::const_iterator it = create_mapping(source_parent); if (it == source_index_mapping.constEnd()) { // Don't care, since we don't have mapping for this index return; } Mapping *m = it.value(); // Figure out how the source changes affect us QVector<int> source_rows_remove; QVector<int> source_rows_insert; QVector<int> source_rows_change; QVector<int> source_rows_resort; int end = qMin(source_bottom_right.row(), m->proxy_rows.count() - 1); for (int source_row = source_top_left.row(); source_row <= end; ++source_row) { if (dynamic_sortfilter) { if (m->proxy_rows.at(source_row) != -1) { if (!q->filterAcceptsRow(source_row, source_parent)) { // This source row no longer satisfies the filter, so it must be removed source_rows_remove.append(source_row); } else if (sort_column >= source_top_left.column() && sort_column <= source_bottom_right.column()) { // This source row has changed in a way that may affect sorted order source_rows_resort.append(source_row); } else { // This row has simply changed, without affecting filtering nor sorting source_rows_change.append(source_row); } } else { if (q->filterAcceptsRow(source_row, source_parent)) { // This source row now satisfies the filter, so it must be added source_rows_insert.append(source_row); } } } else { if (m->proxy_rows.at(source_row) != -1) source_rows_change.append(source_row); } } if (!source_rows_remove.isEmpty()) remove_source_items(m->proxy_rows, m->source_rows, source_rows_remove, source_parent, Qt::Vertical); if (!source_rows_resort.isEmpty()) { // Re-sort the rows emit q->layoutAboutToBeChanged(); QModelIndexList source_indexes = store_persistent_indexes(); remove_source_items(m->proxy_rows, m->source_rows, source_rows_resort, source_parent, Qt::Vertical, false); sort_source_rows(source_rows_resort, source_parent); insert_source_items(m->proxy_rows, m->source_rows, source_rows_resort, source_parent, Qt::Vertical, false); update_persistent_indexes(source_indexes); emit q->layoutChanged(); // Make sure we also emit dataChanged for the rows source_rows_change += source_rows_resort; } if (!source_rows_change.isEmpty()) { // Find the proxy row range int proxy_start_row; int proxy_end_row; proxy_item_range(m->proxy_rows, source_rows_change, proxy_start_row, proxy_end_row); // ### Find the proxy column range also if (proxy_end_row >= 0) { QModelIndex proxy_top_left = create_index( proxy_start_row, m->proxy_columns.at(source_top_left.column()), it); QModelIndex proxy_bottom_right = create_index( proxy_end_row, m->proxy_columns.at(source_bottom_right.column()), it); emit q->dataChanged(proxy_top_left, proxy_bottom_right); } } if (!source_rows_insert.isEmpty()) { sort_source_rows(source_rows_insert, source_parent); insert_source_items(m->proxy_rows, m->source_rows, source_rows_insert, source_parent, Qt::Vertical); }}void QSortFilterProxyModelPrivate::_q_sourceHeaderDataChanged(Qt::Orientation orientation, int start, int end){ Q_Q(QSortFilterProxyModel); Mapping *m = create_mapping(QModelIndex()).value(); int proxy_start = (orientation == Qt::Vertical ? m->proxy_rows.at(start)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -