qtqmlqtlocation

How to monitor a filtering map process with a progressbar


I want to inform the user of the process of filtering points on a QML map by a progress bar. This process takes place in three phases: filterAcceptsRow call rowCount and then call data. The values returned by data are compared with the filter and validate or not.

here is the filterAcceptsRow() :

bool NavaidsFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{

    if(!m_boundaryZone.isValid()){
        return false;
    }
    QModelIndex ix = sourceModel()->index(sourceRow, 0, sourceParent);
    QGeoCoordinate pos = ix.data(NavaidsModel::PositionRole).value<QGeoCoordinate>();

    return m_boundaryZone.contains(pos);
}

Here is the rowCount() :

    Q_INVOKABLE int rowCount(const QModelIndex & parent = QModelIndex()) const{
    Q_UNUSED(parent)

    return mPoints.count();
}

And here is the data(), with a faulty QProgressDialog implemented :

    QVariant data(const QModelIndex & index, int role=Qt::DisplayRole) const {

    QProgressDialog filterDialog;
    filterDialog.setMinimum(0);
    filterDialog.setMaximum(mPoints.count());
    filterDialog.show();
    filterDialog.setValue(index.row());


    const NavaidsPoint &point = mPoints[index.row()];

    if (role == PositionRole){
        return QVariant::fromValue(point.position());}
    else if (role == OACICodeRole){
        return point.oaciCode();}
    else if (role == CountryCodeRole){
        return point.countryCode();}
    return QVariant();
}

Data seems to me the good part of the code in which we know the index of the current value via index.row() and the total of values via rowCount().

Knowing the progress by comparing the two numbers is obvious, but displaying it in a progress bar does not work as I coded it.

I tried to implement a QFutureWatcher to do this job, but unsuccessfully.

Do you have an idea about the solution to implement.

Thanks in advance


Solution

  • If you want to monitor the progress, you have to implement an async worker. It has to complete one step, pause, notify the GUI, give it time to reflect the change, and only then do the next step, and so until finished.

    If you do it in a tight loop, this will absolutely massacre your performance, so you have to take care that it is not too finely grained. Something like a progress bar should not get more than 10 updates a second.

    The reason it doesn't work for you is that the tread is blocked while the work is being done, so the progress bar cannot update until it all the work is finished.