Qt: Что испустить при вставке элементов в мою модель, чтобы намекнуть на представление, чтобы перепроверить canFetchMore?

У меня есть кастомная модель (расширяет QAbstractTableModel) где данные строки добавляются прагматично. Из соображений производительности я использую функцию извлечения (canFetchMore, fetchMore), чтобы избежать задержки интерфейса, когда элементы не видны.

Когда новая строка вставлена, я не хочу, чтобы вызвать QAbstractItemModel::rowsInserted, Но если эти строки будут видны на виде, я бы хотел, чтобы они появлялись автоматически. Они появляются, если пользователь взаимодействует с представлением, например, выбирая последний элемент (представление вызывает 'canFetchMore' и будет вызывать fetchMore только если эти предметы будут видны).

Как я могу сигнализировать представлению, что больше строк доступно для отображения, но их нужно извлечь?

1 ответ

Решение для Qt 5.6.1 - не протестировано для других версий!

Покопавшись в источниках QAbstractItemViewЯ нашел самый простой способ вызвать fetchMore это начать QAbstractItemViewPrivate's внутренний и недокументированный fetchMoreTimer,

Это сильно зависит от реализации и может измениться в будущих версиях Qt!

Подкласс ваш QAbstractItemView дериват (например, QListView,...) чтобы получить доступ к одной из защищенных функций запуска таймера:

class CFetchMoreListView : public QListView
{
    Q_OBJECT

public:
    explicit CFetchMoreListView(QWidget *parent = Q_NULLPTR)
        : QListView(parent)
    { }

    inline void CheckFetchMore()
    {
        int mode = 0;
        switch(mode)
        {
        case 0: // works - but I didn't check how much unneccessary updating it performs
            updateGeometries();
            break;

        case 1: // updates the view allright, but also loads items not currently in view
            verticalScrollbarValueChanged(verticalScrollBar()->maximum());
            break;

        case 2: // needs at least one item already inserted
            if(currentIndex().isValid())
            {
                QModelIndex const curr = currentIndex();
                currentChanged(curr, curr);
            }
            break;

        case 3: // leads to flicker
            setVisible(false);
            rowsInserted(QModelIndex(), 0, 0);
            setVisible(true);
            break;
        }
    }
};

Теперь, после добавления предметов в вашу модель, вы можете позвонить view->CheckFetchMore();

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

Может быть возможно переопределить rowsInserted(...) и вызывать базовую реализацию, только если добавленные строки будут видны.
Но это тоже кажется клёвым.

void QListView::rowsInserted(const QModelIndex &parent, int start, int end)
{
    Q_D(QListView);
    // ### be smarter about inserted items
    d->clear();
    d->doDelayedItemsLayout();
    QAbstractItemView::rowsInserted(parent, start, end);
}

(Мне нравится, как комментарий в коде Qt определяет вашу проблему...)

Другие вопросы по тегам