TocWidget: clean-up the timer logic

The timer logic introduced to solve bug #7138 was not entirely reliable; in
particular it resulted in spurious updates (noticeable by the treeview
collapsing just after one opens a branch, in particular).

This commit cleans up the timer logic. I followed the original design decision
of having an immediate update followed by a delayed update. Now the updates are
appropriately compressed and done after a delay of 2s (as can be noticed with
the treeview still collapsing, unfortunately, but after a more predictable
delay...).
This commit is contained in:
Guillaume Munch 2016-04-29 22:48:53 +01:00
parent 90c8b0697f
commit 5bfdaef980
3 changed files with 42 additions and 31 deletions

View File

@ -50,7 +50,6 @@ GuiToc::~GuiToc()
void GuiToc::updateView() void GuiToc::updateView()
{ {
widget_->updateView(); widget_->updateView();
return;
} }
@ -71,7 +70,7 @@ void GuiToc::enableView(bool enable)
widget_->checkModelChanged(); widget_->checkModelChanged();
if (!enable) if (!enable)
// In the opposite case, updateView() will be called anyway. // In the opposite case, updateView() will be called anyway.
widget_->updateViewForce(); widget_->updateViewNow();
} }

View File

@ -35,19 +35,18 @@
#include <QHeaderView> #include <QHeaderView>
#include <QMenu> #include <QMenu>
#include <QTimer>
#include <vector> #include <vector>
#define DELAY_UPDATE_VIEW
using namespace std; using namespace std;
namespace lyx { namespace lyx {
namespace frontend { namespace frontend {
TocWidget::TocWidget(GuiView & gui_view, QWidget * parent) TocWidget::TocWidget(GuiView & gui_view, QWidget * parent)
: QWidget(parent), depth_(0), persistent_(false), gui_view_(gui_view), update_delay_(0) : QWidget(parent), depth_(0), persistent_(false), gui_view_(gui_view),
update_timer_short_(new QTimer(this)),
update_timer_long_(new QTimer(this))
{ {
setupUi(this); setupUi(this);
@ -89,6 +88,16 @@ TocWidget::TocWidget(GuiView & gui_view, QWidget * parent)
connect(filterLE, SIGNAL(textEdited(QString)), connect(filterLE, SIGNAL(textEdited(QString)),
this, SLOT(filterContents())); this, SLOT(filterContents()));
// setting the update timer
update_timer_short_->setSingleShot(true);
update_timer_long_->setSingleShot(true);
update_timer_short_->setInterval(0);
update_timer_long_->setInterval(2000);
connect(update_timer_short_, SIGNAL(timeout()),
this, SLOT(realUpdateView()));
connect(update_timer_long_, SIGNAL(timeout()),
this, SLOT(realUpdateView()));
init(QString()); init(QString());
} }
@ -256,7 +265,7 @@ void TocWidget::on_updateTB_clicked()
void TocWidget::on_sortCB_stateChanged(int state) void TocWidget::on_sortCB_stateChanged(int state)
{ {
gui_view_.tocModels().sort(current_type_, state == Qt::Checked); gui_view_.tocModels().sort(current_type_, state == Qt::Checked);
updateViewForce(); updateViewNow();
} }
@ -308,7 +317,7 @@ void TocWidget::on_typeCO_currentIndexChanged(int index)
if (index == -1) if (index == -1)
return; return;
current_type_ = typeCO->itemData(index).toString(); current_type_ = typeCO->itemData(index).toString();
updateViewForce(); updateViewNow();
if (typeCO->hasFocus()) if (typeCO->hasFocus())
gui_view_.setFocus(); gui_view_.setFocus();
} }
@ -380,27 +389,24 @@ void TocWidget::enableControls(bool enable)
void TocWidget::updateView() void TocWidget::updateView()
{ {
// Enable if you dont want the delaying business, cf #7138.
#ifndef DELAY_UPDATE_VIEW
updateViewForce();
return;
#endif
// already scheduled?
if (update_delay_ == -1)
return;
QTimer::singleShot(update_delay_, this, SLOT(updateViewForce()));
// Subtler optimization for having the delay more UI invisible. // Subtler optimization for having the delay more UI invisible.
// We trigger update immediately for sparse editation actions, // We trigger update immediately for sparse editation actions,
// i.e. there was no editation/cursor movement in last 2 sec. // i.e. there was no editation/cursor movement in last 2 sec.
// At worst there will be +1 redraw after 2s in a such "calm" mode. // At worst there will be +1 redraw after 2s in a such "calm" mode.
if (update_delay_ != 0) if (!update_timer_long_->isActive())
updateViewForce(); update_timer_short_->start();
update_delay_ = -1; // resets the timer to trigger after 2s
update_timer_long_->start();
} }
void TocWidget::updateViewForce() void TocWidget::updateViewNow()
{
update_timer_long_->stop();
update_timer_short_->start();
}
void TocWidget::realUpdateView()
{ {
update_delay_ = 2000;
if (!gui_view_.documentBufferView()) { if (!gui_view_.documentBufferView()) {
tocTV->setModel(0); tocTV->setModel(0);
depthSL->setMaximum(0); depthSL->setMaximum(0);
@ -456,7 +462,7 @@ void TocWidget::checkModelChanged()
{ {
if (!gui_view_.documentBufferView() || if (!gui_view_.documentBufferView() ||
gui_view_.tocModels().model(current_type_) != tocTV->model()) gui_view_.tocModels().model(current_type_) != tocTV->model())
updateViewForce(); realUpdateView();
} }
@ -528,9 +534,6 @@ void TocWidget::init(QString const & str)
typeCO->blockSignals(true); typeCO->blockSignals(true);
typeCO->setCurrentIndex(new_index); typeCO->setCurrentIndex(new_index);
typeCO->blockSignals(false); typeCO->blockSignals(false);
// no delay when the whole outliner is reseted.
update_delay_ = 0;
} }
} // namespace frontend } // namespace frontend

View File

@ -18,6 +18,7 @@
#include "Cursor.h" #include "Cursor.h"
#include "FuncCode.h" #include "FuncCode.h"
#include <QTimer>
#include <QWidget> #include <QWidget>
class QModelIndex; class QModelIndex;
@ -46,10 +47,10 @@ public:
void checkModelChanged(); void checkModelChanged();
public Q_SLOTS: public Q_SLOTS:
/// Schedule new update of the display unless already scheduled. /// Schedule an update of the dialog after a delay
void updateView(); void updateView();
/// Update the display of the dialog whilst it is still visible. /// Schedule an update of the dialog immediately
void updateViewForce(); void updateViewNow();
protected Q_SLOTS: protected Q_SLOTS:
/// ///
@ -72,6 +73,10 @@ protected Q_SLOTS:
void showContextMenu(const QPoint & pos); void showContextMenu(const QPoint & pos);
private Q_SLOTS:
/// Update the display of the dialog
void realUpdateView();
private: private:
/// ///
void enableControls(bool enable = true); void enableControls(bool enable = true);
@ -103,8 +108,12 @@ private:
bool persistent_; bool persistent_;
/// ///
GuiView & gui_view_; GuiView & gui_view_;
// next delay for outliner update in ms. -1 when already scheduled. // Timers for scheduling updates: one immediately and one after a delay.
int update_delay_; // This is according to the logic of the previous code: when at rest, the
// update is carried out immediately, and when an update was done recently,
// we schedule an update to occur 2s after resting.
QTimer * update_timer_short_;
QTimer * update_timer_long_;
}; };
} // namespace frontend } // namespace frontend