Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: QSortFilterProxyModel или как сделать фильтр с условием (a | b)?
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Модель/Представление
ViGOur
При использовании модели, если я хочу сделать фильтр вроде:
select *
from mytable
where id_begin=1 or id_end=1

пишем такой код, и нет проблем:
QString szFilter = QString("id_begin='%1' or id_end='%1'").arg(nId);
pModel->setFilter(szFilter);

А как изобразить подобное использую QAbstractProxyModel или QSortFilterProxyModel?
Гость
Можно переопределить QSortFilterProxyModel::filterAcceptsRow и заимлементить возможность задавать больше одной колонки для фильтра.
PAFOS
А можно костыльнуть и наложить одну QSortFilterProxyModel на другую QSortFilterProxyModel
у первой sourceModel() - целевая модель, у второй sourceModel() - первая QSortFilterProxyModel .
и соответственно в первой QSortFilterProxyModel прописываешь одно условие, во второй QSortFilterProxyModel другое)
Tonal
Так получится только пересечение организовать - будут видны элементы удовлетворяющие обоим условиям сразу.
Так что придётся таки filterAcceptsRow переопределять. :)
Гость_FantasyOR_*
Цитата(PAFOS @ 3.4.2012, 7:55) *
А можно костыльнуть и наложить одну QSortFilterProxyModel на другую QSortFilterProxyModel
у первой sourceModel() - целевая модель, у второй sourceModel() - первая QSortFilterProxyModel .
и соответственно в первой QSortFilterProxyModel прописываешь одно условие, во второй QSortFilterProxyModel другое)


о_О господи, за что!!! не претендую, на супер пупер код, но всё же лучше чем 100500 QSortFilterProxyModel вложеных друг в друга

.h
Раскрывающийся текст

class SMuliFilterProxyModel : public QSortFilterProxyModel
{
    Q_OBJECT

public:
    SMuliFilterProxyModel(QObject *parent = 0);

//-------------------------------------------------------------------------
    void clear(int _col)
    {
        if (_col == -1)
        {    filterData.clear();    }
        else
        {    filterData.remove(_col);    }

        invalidateFilter();
    }
//-------------------------------------------------------------------------
    void removeFilter(int _col)
    {
        filterData.remove(_col);
    }
//-------------------------------------------------------------------------
    void
    setFilter(QHash<int, QString> _value)
    {
        filterData.clear();

        QHashIterator<int, QString> it(_value);
        while (it.hasNext())
        {
            it.next();
            setFilterValue(it.key(), it.value());
        }

        invalidateFilter();
    }
//-------------------------------------------------------------------------
    void setFilterValue(int _col, QString _value)
    {        
        filterData.insert(_col, QRegExp(_RegExpString(_value)));
    }
//-------------------------------------------------------------------------
    void beginSorting()
    {
        invalidateFilter();
    }

protected:
    bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;

private:
    QString stringEkvival;
    QString _RegExpString(const QString _value) const;
    QHash<int, QRegExp> filterData;
    bool dateInRange(const QDate &date) const;

};
#endif //MULTIFILTERPROXIMODEL_H



.cpp

Раскрывающийся текст

SMuliFilterProxyModel::SMuliFilterProxyModel(QObject *parent)
    : QSortFilterProxyModel(parent)
{
    stringEkvival = QString::fromUtf8(
                        "АA "
                        "БB "
                        "ВV "
                        "ГG "
                        "ДD "
                        "ЕE "
                        "ЗZ "
                        "ИI "
                        "ЙJ "
                        "КK "
                        "ЛL "
                        "МM "
                        "НN "
                        "ОO "
                        "ПP "
                        "РR "
                        "СS "
                        "ТT "
                        "УU "
                        "ФF "
                        "ХH "
                        "ЦC "
                        "ЫY ");

}

bool SMuliFilterProxyModel::filterAcceptsRow(int sourceRow,
        const QModelIndex &sourceParent) const
{
    bool res = true;
    QHashIterator<int, QRegExp> it(filterData);

    while (it.hasNext() && res)
    {
        it.next();
        res &= sourceModel()->data(
                        sourceModel()->index(
                                sourceRow, it.key(), sourceParent
                        )
                ).toString().contains(it.value());
            
    }

    return res;
}

QString
SMuliFilterProxyModel::_RegExpString(const QString _value) const
{
    if (_value.isEmpty())
    {    return QString();    }
    
    QString _val = _value;
    QString _valP = "";
    QString res;

    res += "(("+_val+")|";

    QRegExp re("[A-Z]");
    int idx = notFound;
    int cnt = _val.size();
    for (int i=0; i<cnt; ++i)
    {            
      // проверяем входит ли символ в заменяемые, Рус En не важно
        idx = stringEkvival.indexOf(_val.at(i));

        if (idx == notFound)
        {    _val.replace(i, 1, " ");    }        // не входит - ставим пробел
        else
        {
          // входит - смотрим это англ или русский симавол
            if (re.indexIn(_val.at(i)) == notFound)
            {    ++idx;    }    // если == -1 то русский => нужно взять следующий символ из строки замены
            else
            {    --idx;    }    // если != -1 то английский => нужно взять предыдущий символ из строки замены

            _val.replace(i, 1, stringEkvival.at(idx));
        }
    }
    res += "("+_val+"))";

    return res;
}




таким образом, получается фильтрация одновременно по множеству столбцов одновременно.
Можно не обращать внимания на транслитерацию, по заданию нужно было, чтоб при вводе "AСD" фильтровалось по "AСD" и "АЦД", и наоборот.

ViGOur
Ребят, всем спасибо.
Я еще после 2 поста всё реализовал, только забыл сказать об этом... :blush2:
По поводу двух QSortFilterProxyModel знаю, но как уже было сказано, в таком случае будет как (a && c), а нужно именно (a || c) или вариации.
Гость_FantasyOR_*
Добавь переключатель в сортФильтрМодели ("и" или "или")
в зависимости от переключателя выбирается нужная ветка "res &= " или "res |= "

всё равно рано или поздно понадобиться фильтровать по &&, это классика: посмотреть сколько ивановых занимают должность программист.

P.S.: Пожалуйста посмотрите мой код выше, укажите на нелепости в плане качества кода.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.