Russian Qt Forum

Qt => Model-View (MV) => Тема начата: jasmine от Июнь 12, 2014, 12:53



Название: QFileSystemModel-QSortFilterProxyModel-QTreeView - sigsegv
Отправлено: jasmine от Июнь 12, 2014, 12:53
Всем доброго дня.
Я в Qt новичок...Пишу на с++/Qt 5.2.1. Уже неделю не могу разобраться с одной проблемой, может кто подскажет, как решить...
У меня есть исходная_модель-прокси_модель-тривью. В виде дерева отображается вся файловая система, начиная с указанного абс.пути. Дерево строится после нажатия на кнопку "перестроить". В исходной модели реализован один фильтр, с ним все нормально. В прокси-модели еще два, через переопределение
bool filterAcceptsRow() const;

Код:
bool FilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
    if (filterAcceptsRowItself(sourceRow, sourceParent))
        return true;
    //accept if any of the children is accepted on it's own merits
    if (hasAcceptedChildren(sourceRow, sourceParent)) {
        return true;
    }
    return false;
}

bool FilterProxyModel::filterAcceptsRowItself(int sourceRow, const QModelIndex &sourceParent) const
{
    QModelIndex index0 = sourceModel()->index(sourceRow, 3, sourceParent); // получаю индекс по столбцу времени после.модиф.
    QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent); // размер файла

    QDateTime now = QDateTime::currentDateTime();
    QDateTime fileMtime = QDateTime::fromString((sourceModel()->data(index0)).toString(),Qt::LocalDate).addYears(100);


    bool timeFilter = mdtime < fileMtime.daysTo(now);
    bool sizeFilter = filterFileSize(sourceModel()->data(index1).toString());

    return (timeFilter && sizeFilter);
}

bool FilterProxyModel::hasAcceptedChildren(int sourceRow, const QModelIndex &sourceParent) const
{
    QModelIndex item = sourceModel()->index(sourceRow,0,sourceParent);
    if (!item.isValid()) {
        //qDebug() << "item invalid" << sourceParent << sourceRow;
        return false;
    }

    //check if there are children
    int childCount = item.model()->rowCount(item);
    if (childCount == 0)
        return false;

    for (int i = 0; i < childCount; ++i) {
        if (filterAcceptsRowItself(i, item))
            return true;
        //recursive call -> NOTICE that this is depth-first searching, you're probably better off with breadth first search...
        if (hasAcceptedChildren(i, item))
            return true;
    }
    return false;
}

Собственно правила фильтрации указаны в filterAcceptsRowItself(). Функция bool filterFileSize() принимает строку с размером, парсит ее и возвращает true, если файл удовлетворяет фильтру. Тут все тоже работает корректно...

Проблема возникает на этапе передачи индекса в представление. Передаю так:
Код:
filterModel->setSourceModel(treemodel);
// ...
ui->treeView->setModel(filterModel);
QModelIndex ind = filterModel->mapFromSource(treemodel->setRootPath(path)); // path считывается из виджета lineEdit
if (!ind.isValid()) return;
ui->treeView->setRootIndex(ind);

Если после фильтрации в модели есть данные, то все отлично. Но как только фильтрации не удовлетворяет ни один файл, происходит какая-то неведомая...чудо:
1) либо модель отображается пустой (как и должна, собственно - фильтрация-то вернула false),
2) либо отображается иконка каталога "/" (я так понимаю, это значит, что индекс потерялся или что-то вроде того)
Если первый случай, то после попытки изменить значение фильтра так, чтобы в модель попали данные, программа вылетает. причем не на моих функциях а на цикле exec(), где-то на ассемблерных командах при попытке mov что-то куда-то.
Если второй случай, то после повторного нажатия на кнопку "перестроить дерево", есть шанс, что все-таки отобразятся верные данные.

Может кто подскажет, как мне не терять этот гребаный индекс?

Заранее спасибо.