Bug 254000 - MarbleWidget and Slider for the zoom causes the application to use 100% CPU.
Summary: MarbleWidget and Slider for the zoom causes the application to use 100% CPU.
Status: RESOLVED NOT A BUG
Alias: None
Product: marble
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: unspecified Linux
: NOR normal
Target Milestone: 1.0 (KDE 4.6)
Assignee: marble-bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-10-12 20:21 UTC by Miguel Chavez Gamboa
Modified: 2010-10-13 23:47 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Miguel Chavez Gamboa 2010-10-12 20:21:00 UTC
Version:           unspecified (using Devel) 
OS:                Linux

Using marble (library) from SVN (revision r1184939) in my application.
My application is doing a programatically zoom in to an area (animated) at the begining.

Placing a slider bar for controling the zoom in/out, and making the connections for syncing both widgets, specially the next connection is causing the problem:

connect(theMap, SIGNAL(zoomChanged(int)), this, SLOT(changeSlider(int)) );

Instead of directly connecting the signal to the setValue()slot of the Slider, I used a intermediary slot (changeSlider), and i noted that the 

ui->zoomSlider->setValue(x);

code is what is causing the app to freeze for some moments (using 100% CPU) and repeated times.

The code was working for some days without the freeze, but at some point i did some updates (ubuntu, and marble's code from svn) and it appeared. 

Reproducible: Didn't try

Steps to Reproduce:
described above



Im not sure if the bug/problem is marble related or qt related, because the problem happens with qt code (slider->setValue()).

If I filter the number of times the slider->setValue() is executed, the problem minimizes but it does not disappears:

void MainWindow::changeSlider(int x)
{
    if ((x>1000 && x<1005) || (x>2397))
        ui->zoomSlider->setValue(x);
}
Comment 1 Dennis Nienhüser 2010-10-12 23:16:37 UTC
Just a quick guess (didn't look into it in detail yet): Does changeSlider(int) cause another map->zoomView() call? Then bug 249628 could be related, because there'd be a circular connection that's not broken in MarbleWidget because of the off-by-one error.
Comment 2 Miguel Chavez Gamboa 2010-10-13 04:58:40 UTC
(In reply to comment #1)
> Just a quick guess (didn't look into it in detail yet): Does changeSlider(int)
> cause another map->zoomView() call? Then bug 249628 could be related, because
> there'd be a circular connection that's not broken in MarbleWidget because of
> the off-by-one error.

I also think its a endless loop, and maybe related to the bug 249628.

I removed the animations, and before making the connection (signal->slot) of the slider, i call:
 
slider->setValue(2000);
theMap->zoomView(2000);
..
connect( ..the signal connections.. );

And it works fine the first zoomView, after the signal connection, if i click the Zoom-in button, the zoom changes from 2000 to 1000 and the app freezes.

I placed a qDebug() at the MarbleWidget::zoomView(...) and i got this:

ZomView newZoom: 2039
ZomView newZoom: 2038
ZomView newZoom: 2037
...
More output
...
ZomView newZoom: 1003
ZomView newZoom: 1002
ZomView newZoom: 1000
..here it freezes.
Comment 3 Miguel Chavez Gamboa 2010-10-13 06:00:51 UTC
(In reply to comment #1)
> Just a quick guess (didn't look into it in detail yet): Does changeSlider(int)
> cause another map->zoomView() call? Then bug 249628 could be related, because
> there'd be a circular connection that's not broken in MarbleWidget because of
> the off-by-one error.

I think its what you say, a circular signals-slot reactions (the slider changes and the map zoom changes in reaction, then as the map zoom changed the slider changes again and the loop is endless)

I can see this if I remove the 
 connect(ui->zoomSlider, SIGNAL(valueChanged(int)), theMap, SLOT(zoomView(int)) );
but keep the
 connect(theMap, SIGNAL(zoomChanged(int)), ui->zoomSlider, SLOT(setValue(int)) );

I does not freezes. This way I can get the slider updated when the marblewidget's zoom changes, but I cannot zoom with the slider.
Comment 4 Dennis Nienhüser 2010-10-13 20:44:41 UTC
SVN commit 1185567 by nienhueser:

Round, don't cut.
BUG: 249628
CCBUG: 254000

 M  +1 -1      MarbleMap.cpp  


WebSVN link: http://websvn.kde.org/?view=rev&revision=1185567
Comment 5 Dennis Nienhüser 2010-10-13 20:50:50 UTC
The implementation of our own slider has some interesting notes on this btw. Also notice the blockSignals() calls.

    // There exists a circular signal/slot connection between MarbleWidget and this widget's
    // zoom slider. MarbleWidget prevents recursion, but it still loops one time unless
    // blocked here. Note that it would be possible to only connect the sliders
    // sliderMoved signal instead of its valueChanged signal above to break up the loop.
    // This however means that the slider cannot be operated with the mouse wheel, as this
    // does not emit the sliderMoved signal for some reason. Therefore the signal is blocked
    // below before calling setValue on the slider to avoid that it calls back to MarbleWidget,
    // and then un-blocked again to make user interaction possible.

    d->m_navigationUi.zoomSlider->blockSignals( true );

    d->m_navigationUi.zoomSlider->setValue( zoom );
    d->m_navigationUi.zoomSlider->setMinimum( minimumZoom() );
    // As we have disabled all zoomSlider Signals, we have to update our buttons seperately.
    updateButtons( zoom );

    d->m_navigationUi.zoomSlider->blockSignals( false );
Comment 6 Miguel Chavez Gamboa 2010-10-13 23:47:51 UTC
Ok, that works.

As is not a marble bug, but mine, i will close it.

Thanks!