2010-09-16 6 views
4

Я использую QSortFilterProxyModel для фильтрации результатов из QAbstractListModel. Тем не менее, я бы хотел вернуть первую запись, которой нет в исходной модели, то есть она как-то искусственна.QSortFilterProxyModel возвращает искусственную строку

Это то, что я до сих пор:

class ActivedAccountModel(QSortFilterProxyModel):                                 
    def __init__(self, model, parent=None): 
     super(ActiveAccountModel, self).__init__(parent) 
     self.setSourceModel(model) 
     self.setDynamicSortFilter(True) 

    def data(self, index, role=Qt.DisplayRole): 
     account_info = super(ActiveAccountModel, self).data(index, Qt.UserRole).toPyObject() 
     if role == Qt.DisplayRole: 
      return account_info.name 
     elif role == Qt.UserRole: 
      return account_info 
     return None 

    def filterAcceptsRow(self, source_row, source_parent): 
     source_model = self.sourceModel() 
     source_index = source_model.index(source_row, 0, source_parent) 
     account_info = source_model.data(source_index, Qt.UserRole) 
     return isinstance(account_info.account, Account) and account_info.account.enabled 

Это возвращает список в виде:

Account 1 
Account 2 
... 

Id», как вернуть дополнительный элемент в начале возвращаемой список F элементы:

Extra Element 
Account 1 
Account 2 
... 

Я попытался переописать сверку, чтобы вернуть реальную ROWCOUNT() + 1, но почему-то я бы необходимо, чтобы сдвиг все предметы, чтобы вернуть этот искусственный элемент в индекс 0, и я немного потерялся там.

Любой ключ? До сих пор я не мог найти какой-либо пример кода ... Спасибо!

+0

Я не уверен, что QSortFilterProxyModel лучшее место, чтобы попытаться сделать это. Оперативные условия: _sort_ и _filter_. Я думаю, что делать это в пользовательской модели было бы лучше. –

ответ

1

Я сделал это, только на работе, поэтому я не могу дать вам много кода. Я могу дать вам общее представление о том, что делать.

Он работает лучше, если вы используете подкласс QAbstractProxyModel, который предназначен для общих манипуляций, а не для сортировки или фильтрации. Вы хотите переопределить rowCount, а также переопределить columnCount (хотя это должно просто вернуть информацию из исходной модели). Вам нужно будет переопределить функцию данных и вернуть свои собственные данные для первой строки или снова вызвать исходную модель.

Вы хотите переопределить функции mapFromSource и mapToSource, чтобы разрешить переключение между индексами прокси-модели и индексами исходной модели.

Чтобы выполнить надежную реализацию, вам нужно будет создать несколько слотов и подключиться к сигналам исходной модели для изменения данных, сброса модели и строк/столбцов, которые нужно будет вставить/удалить. Затем вы должны испускать свои собственные сигналы, правильно адаптируя их для учета дополнительной строки.

В нашем классе мы сделали текст для первой строки, которая может быть установлена, поэтому мы можем использовать одну и ту же прокси-модель в разных ситуациях. Это стоит исследовать для вас, так как это добавляет минимальные усилия.

Редактировать

Per прокомментировал просьбу, грубый взгляд на mapToSource и mapFromSource. Это примерно то, о чем вам нужно подумать.

// Remember that this maps from the proxy's index to the source's index, 
// which is invalid for the extra row the proxy adds. 
mapToSource(proxy_index): 
    if proxy_index isn't valid: 
     return invalid QModelIndex 
    else if proxy_index is for the first row: 
     return invalid QModelIndex 
    else 
     return source model index for (proxy_index.row - 1, proxy_index.column) 

mapFromSource(source_index): 
    if source_index isn't valid: 
     return invalid QModelIndex 
    else if source_index has a parent: 
     // This would occur if you are adding an extra top-level 
     // row onto a tree model. 
     // You would need to decide how to handle that condition 
     return invalid QModelIndex 
    else 
     return proxy model index for (source_index.row + 1, source_index.column) 
+0

Я тоже поехал по этому пути, но я немного потерял функции mapFrom/mapTo: -S Можете ли вы добавить более подробную информацию об этом, даже если вы не можете показать код? Общая идея должна быть достаточной :-) Спасибо! – saghul

+1

Большое вам спасибо! – saghul

2

Потому что я боролся немного с осуществлением этого и потому, что я не мог найти любой другой образец кода во всей сети, я отправляю этот пример реализации.

Я надеюсь, что это поможет другим людям тоже ...

/** 
** Written by Sven Anders (ANDURAS AG). Public domain code. 
**/ 

#include <QDebug> 
#include <QBrush> 
#include <QFont> 
#include <QSortFilterProxyModel> 

/** Definition **/ 

class ProxyModelNoneEntry : public QSortFilterProxyModel 
{ 
    Q_OBJECT 
public: 
    ProxyModelNoneEntry(QString _entry_text = tr("(None)"), QObject *parent=0); 
    int rowCount(const QModelIndex &parent = QModelIndex()) const; 
    /* lessThan() is not necessary for this model to work, but can be 
    implemented in a derived class if a custom sorting method is required. */ 
    // bool lessThan(const QModelIndex &left, const QModelIndex &right) const; 
    QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; 
    QModelIndex mapToSource(const QModelIndex &proxyIndex) const; 
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 
    Qt::ItemFlags flags(const QModelIndex &index) const; 
    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; 
    QModelIndex parent(const QModelIndex &child) const; 

private: 
    QString entry_text; 
}; 

/** Implementation **/ 

ProxyModelNoneEntry::ProxyModelNoneEntry(QString _entry_text, QObject *parent) : QSortFilterProxyModel(parent) 
{ 
    entry_text = _entry_text; 
} 

int ProxyModelNoneEntry::rowCount(const QModelIndex &parent) const 
{ 
    Q_UNUSED(parent) 
    return QSortFilterProxyModel::rowCount()+1; 
} 

QModelIndex ProxyModelNoneEntry::mapFromSource(const QModelIndex &sourceIndex) const 
{ 
    if (!sourceIndex.isValid()) return QModelIndex(); 
    else if (sourceIndex.parent().isValid()) return QModelIndex(); 
    return createIndex(sourceIndex.row()+1, sourceIndex.column()); 
} 

QModelIndex ProxyModelNoneEntry::mapToSource(const QModelIndex &proxyIndex) const 
{ 
    if (!proxyIndex.isValid()) return QModelIndex(); 
    else if (proxyIndex.row() == 0) return QModelIndex(); 
    return sourceModel()->index(proxyIndex.row()-1, proxyIndex.column()); 
} 

QVariant ProxyModelNoneEntry::data(const QModelIndex &index, int role) const 
{ 
    if (!index.isValid()) return QVariant(); 

    if (index.row() == 0) 
    { 
    if (role == Qt::DisplayRole) 
     return entry_text; 
    else if (role == Qt::DecorationRole) 
     return QVariant(); 
    else if (role == Qt::FontRole) 
    { QFont font; font.setItalic(true); return font; } 
    else 
     return QVariant(); 
    } 
    return QSortFilterProxyModel::data(createIndex(index.row(),index.column()), role); 
} 

Qt::ItemFlags ProxyModelNoneEntry::flags(const QModelIndex &index) const 
{ 
    if (!index.isValid()) return Qt::NoItemFlags; 
    if (index.row() == 0) return Qt::ItemIsSelectable | Qt::ItemIsEnabled; 
    return QSortFilterProxyModel::flags(createIndex(index.row(),index.column())); 
} 

QModelIndex ProxyModelNoneEntry::index(int row, int column, const QModelIndex &parent) const 
{ 
    if (row > rowCount()) return QModelIndex(); 
    return createIndex(row, column); 
} 

QModelIndex ProxyModelNoneEntry::parent(const QModelIndex &child) const 
{ 
    Q_UNUSED(child) 
    return QModelIndex(); 
} 

С уважением Sven

0

я имел такую ​​же проблему в последнее время, и есть много проблем с родителями и картографирование с исходной моделью ,

Моя версия должна обрабатывать виртуальные столбцы слева, несколько связанных с действиями и, возможно, один, который является флажком.

Hopes это может помочь кому-то тоже :)

Тем не менее, примечание к мудрым, я подклассов в QSortFilterProxyModel, и, делая это, я, кажется, теряет способность использовать сортировки. Я думаю, это потому, что я переопределяю методы индекса/данных. Если раньше я пришел к подклассу QIdentityProxyModel, а затем добавлю QSortFilterProxyModel, я вместо этого потеряю возможность проверить/снять отметку со своего столбца флажка ... хотя флаги установлены в Qt :: ItemIsEnabled | Qt :: ItemIsUserCheckable | Qt :: ItemIsEditable ... сложно еще :)

QModelIndex GenericProxy::mapToSource(const QModelIndex & proxy) const { 
    if(not proxy.isValid()) 
    return QModelIndex(); 

    if((action || checkbox)) { 
    int column = proxy.column() - addedCount(); 
    if(column < 0) // this index is local. 
     return QModelIndex(); 

    QModelIndex idx = sourceModel()->index(proxy.row(), column, mapToSource(proxy.parent())); 
    return idx ; 
    } 

    QModelIndex idx = sourceModel()->index(proxy.row(), proxy.column(), mapToSource(proxy.parent())); 
    return idx; 
} 

QModelIndex GenericProxy::mapFromSource(const QModelIndex & source) const { 
    if(not source.isValid()) 
    return QModelIndex(); 


    if((action || checkbox)) { 
    // simply add appropriate informations .. 
    int column = source.column() + addedCount(); 
    QModelIndex idx = index(source.row(), column, mapFromSource(source.parent())); 
    return idx; 
    } 
    QModelIndex idx = index(source.row(), source.column(), mapFromSource(source.parent())); 
    return idx; 
} 

GenericItem * GenericProxy::convert(const QModelIndex & idx) const { 
    if(idx.isValid()) 
    return _convert(index(idx.row(), firstRealColumn(), idx.parent())); 
    else 
    return _convert(idx); 
} 

// _convert doesn't take care of index not really at the rightplace_ness :) 
GenericItem * GenericProxy::_convert(const QModelIndex & index) const { 
    if(not index.isValid()) 
    return dynamic_cast<GenericModel *>(sourceModel())->convert(QModelIndex()); 

    return static_cast<GenericItem*>(index.internalPointer()); 
} 
QModelIndex GenericProxy::parent(const QModelIndex & item) const { 
    if(not item.isValid()) 
    return QModelIndex(); 

    GenericItem * child = _convert(item); 
    if(!child) 
    return QModelIndex(); 
    GenericItem * parent = child->parentItem(); 
    if(parent == _convert(QModelIndex())) 
    return QModelIndex(); 

    int column = addedCount(); 
    return sourceModel()->parent(mapToSource(createIndex(item.row(), column, parent))); 
} 

QModelIndex GenericProxy::index(int row, int column, const QModelIndex & parent) const { 
    if(not hasIndex(row,column,parent)) 
    return QModelIndex(); 

    GenericItem * pitem = convert(parent); 
    GenericItem * pchild = pitem->child(row); 

    if(pchild) 
    return createIndex(row, column, pchild); 
    else 
    return QModelIndex(); 

} 
Смежные вопросы