Project

General

Profile

Actions

Bug #926

closed

WBoxLayout : insert and remove operations are very very very slow

Added by Momo LALMI almost 13 years ago. Updated almost 13 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Target version:
Start date:
07/24/2011
Due date:
% Done:

0%

Estimated time:

Description

Hi guys ,

Since I have upgraded to 3.9.10 my operations related to WVBoxLayout , WHBoxLayout , WBoxLayout are very very very very slow

it took about 10 seconds to remove and reinsert a simple widget into a WVBoxLayout with only 25 items .....

Could you take a look at this mysterious slow-down ?

Best regards.

Mohamed


Files

WVBoxLayout.png (26.3 KB) WVBoxLayout.png Momo LALMI, 07/25/2011 03:39 PM
test29.cc (2.95 KB) test29.cc Koen Deforche, 08/01/2011 10:37 AM
Actions #1

Updated by Momo LALMI almost 13 years ago

This seems to happen only with Google chrome (latest version).

When reordering layout items using insertItem , removeItem , all layout elements became invisible for some seconds and sometimes do not reappear at all (until the mouse is moved over)

Actions #2

Updated by Koen Deforche almost 13 years ago

Hey Mohammed,

Unfortunately, with Chrome's self-update mechanism it will not be easy to reproduce this... But still, would you be able to provide a test case that triggers this for you?

Regards,

koen

Actions #3

Updated by Koen Deforche almost 13 years ago

  • Status changed from New to InProgress
  • Target version changed from 3.1.10 to 3.1.11
Actions #4

Updated by Momo LALMI almost 13 years ago

Hi Koen,

The main idea of the following widget is to show/hide/reorder columns in a WTreeView :

I am using a WVBoxLayout to hold all checkboxes, and two buttons to reorder the elements : (actions are : move up/down). When moving up/down WVBoxLayout elements on Google Chrome (latest): they disappear until the mouse is moved over the layout....

My WTreeView is connected to a model of type : dbo::QueryModel< dbo::ptr >();

My model does not react on ::removeColumns(....)

@@

//#############################################

// FILE : myWidget.h

//#############################################

#pragma once

#include

#include

namespace Wt

{

class WScrollArea;

class WIconPair;

class WPushButton;

class WCheckBox;

class WGridLayout;

class WHBoxLayout;

class WVBoxLayout;

}

using namespace Wt ;

using namespace std;

class MyWidget : public WDialog

{

public:

MyWidget(void);

~MyWidget(void);

private:

void move_up();

void move_down();

void item_clicked() ;

private:

WScrollArea * _scroll_area ;

WIconPair * _up ;

WIconPair * _down;

WPushButton * _apply ;

WPushButton * _close ;

WGridLayout * _grid ;

WVBoxLayout * _hbox;

//--------- check boxes ----------------

WCheckBox * id;

WCheckBox * start_date_time;

WCheckBox * end_date_time;

WCheckBox * duration;

WCheckBox * calling_number;

WCheckBox * calling_name;

WCheckBox * called_number;

WCheckBox * called_name;

WCheckBox * ring_duration;

WCheckBox * channel_number;

WCheckBox * channel_name;

WCheckBox * direction;

WCheckBox * username;

WCheckBox * short_comment;

WCheckBox * case_number;

WCheckBox * dtmf_received;

WCheckBox * dtmf_sent;

WCheckBox * signaling_src_ip;

WCheckBox * signaling_src_port;

WCheckBox * signaling_src_mac;

WCheckBox * signaling_dst_ip;

WCheckBox * signaling_dst_port;

WCheckBox * signaling_dst_mac;

WCheckBox * audio_src_ip;

WCheckBox * audio_src_port;

WCheckBox * audio_src_mac;

WCheckBox * audio_dst_ip;

WCheckBox * audio_dst_port;

WCheckBox * audio_dst_mac;

//---------------------------------------

WCheckBox * selected_item ;

};

//################################################

// FILE : MyWidget.h

//################################################

#include "Wt_RecordListColumnsWidget.h"

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

// boost headers ------------------

#include <boost/algorithm/string/split.hpp>

#include <boost/algorithm/string/classification.hpp>

#include <boost/algorithm/string/trim.hpp>

#include <boost/algorithm/string/replace.hpp>

#include <boost/algorithm/string/erase.hpp>

#include <boost/algorithm/string/find_format.hpp>

#include <boost/lexical_cast.hpp>

//---xml ---------------------------

#include <rapidxml.hpp>

#include <rapidxml_print.hpp>

//---std ---------------------------

#include

#include

#include

#include

#include

#include

// using namespace Wt;

using namespace std;

using namespace rapidxml;

//---------------------------------------------------------------------------------------------------------------------------

MyWidget::MyWidget(void)

//---------------------------------------------------------------------------------------------------------------------------

{

selected_item = NULL ;

this->setWindowTitle(tr("recordlist.columns"));

_grid = new WGridLayout();

_grid->setContentsMargins(10,10,10,10);

_scroll_area = new WScrollArea();

_scroll_area->resize( 300 , 400 ) ;

_scroll_area->setMinimumSize( 300 , 400 ) ;

_scroll_area->setScrollBarPolicy( WScrollArea::ScrollBarAsNeeded );

_scroll_area->setPositionScheme(Absolute);

_scroll_area->setMargin(10);

_hbox = new WVBoxLayout();

WContainerWidget * scrollContainer = new WContainerWidget();

_scroll_area->setWidget(scrollContainer );

scrollContainer->resize( WLength::Auto , WLength::Auto );

//scrollContainer->setMinimumSize(290, WLength::Auto );

scrollContainer->setLayout ( _hbox ) ;

// up button ----------------------------------------------------------------------------------

_up = new WIconPair( "icons/up_48.png","icons/up_48.png" );

_up->icon1Clicked().connect ( this, & Wt_RecordListColumnsWidget::move_up ) ;

_up->icon2Clicked().connect ( this, & Wt_RecordListColumnsWidget::move_up ) ;

_up->setToolTip(tr("recordlist.columns.up"));

// down button ----------------------------------------------------------------------------------

_down = new WIconPair( "icons/down_48.png","icons/down_48.png" );

_down->icon1Clicked().connect ( this, & Wt_RecordListColumnsWidget::move_down ) ;

_down->icon2Clicked().connect ( this, & Wt_RecordListColumnsWidget::move_down ) ;

_down->setToolTip(tr("recordlist.columns.down"));

//------- up down container ----------------------------------------------------------------

WContainerWidget * upDownContainer = new WContainerWidget();

upDownContainer->addWidget(_up);

upDownContainer->addWidget(new WBreak());

upDownContainer->addWidget(_down);

//---------------------- apply/close buttons ---------------------

WContainerWidget * buttonsContainer = new WContainerWidget();

WHBoxLayout * buttonsLayout = new WHBoxLayout();

buttonsContainer->setLayout( buttonsLayout ) ;

//---------- apply

_apply = new WPushButton( tr("recordlist.filterdialog.applybutton") );

_apply->clicked().connect( this, &Wt_RecordListColumnsWidget::accept);

_apply->resize( 80, 30 ) ;

_apply->setMaximumSize( 80, 30 ) ;

buttonsLayout->addWidget( _apply ) ;

//---------- cancel

_close = new WPushButton( tr("recordlist.filterdialog.closebutton") );

_close->clicked().connect( this, &Wt_RecordListColumnsWidget::reject);

_close->resize( 80, 30 ) ;

_close->setMaximumSize( 80, 30 ) ;

buttonsLayout->addWidget( _close ) ;

// check boxes ------------------

id = new WCheckBox(tr("recordlist.field.id"));

start_date_time = new WCheckBox(tr("recordlist.field.start_date_time"));

end_date_time = new WCheckBox(tr("recordlist.field.end_date_time"));

duration = new WCheckBox(tr("recordlist.field.duration"));

calling_number = new WCheckBox(tr("recordlist.field.calling_number"));

calling_name = new WCheckBox(tr("recordlist.field.calling_name"));

called_number = new WCheckBox(tr("recordlist.field.called_number"));

called_name = new WCheckBox(tr("recordlist.field.called_name"));

ring_duration = new WCheckBox(tr("recordlist.field.ring_duration"));

channel_number = new WCheckBox(tr("recordlist.field.channel_number"));

channel_name = new WCheckBox(tr("recordlist.field.channel_name"));

direction = new WCheckBox(tr("recordlist.field.direction"));

username = new WCheckBox(tr("recordlist.field.username"));

short_comment = new WCheckBox(tr("recordlist.field.short_comment"));

case_number = new WCheckBox(tr("recordlist.field.case_number"));

dtmf_received = new WCheckBox(tr("recordlist.field.dtmf_received"));

dtmf_sent = new WCheckBox(tr("recordlist.field.dtmf_sent"));

signaling_src_ip = new WCheckBox(tr("recordlist.field.signaling.src.ip"));

signaling_src_port = new WCheckBox(tr("recordlist.field.signaling.src.port"));

signaling_src_mac = new WCheckBox(tr("recordlist.field.signaling.src.mac"));

signaling_dst_ip = new WCheckBox(tr("recordlist.field.signaling.dst.ip"));

signaling_dst_port = new WCheckBox(tr("recordlist.field.signaling.dst.port"));

signaling_dst_mac = new WCheckBox(tr("recordlist.field.signaling.dst.mac"));

audio_src_ip = new WCheckBox(tr("recordlist.field.audio.src.ip"));

audio_src_port = new WCheckBox(tr("recordlist.field.audio.src.port"));

audio_src_mac = new WCheckBox(tr("recordlist.field.audio.src.mac"));

audio_dst_ip = new WCheckBox(tr("recordlist.field.audio.dst.ip"));

audio_dst_port = new WCheckBox(tr("recordlist.field.audio.dst.port"));

audio_dst_mac = new WCheckBox(tr("recordlist.field.audio.dst.mac"));

id->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

start_date_time->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

end_date_time->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

duration->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

calling_number->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

calling_name->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

called_number->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

called_name->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

ring_duration->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

channel_number->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

channel_name->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

direction->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

username->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

short_comment->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

case_number->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

dtmf_received->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

dtmf_sent->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

signaling_src_ip->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

signaling_src_port->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

signaling_src_mac->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

signaling_dst_ip->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

signaling_dst_port->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

signaling_dst_mac->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

audio_src_ip->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

audio_src_port->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

audio_src_mac->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

audio_dst_ip->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

audio_dst_port->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

audio_dst_mac->clicked().connect( this, & Wt_RecordListColumnsWidget::item_clicked ) ;

_hbox->addWidget(id);

_hbox->addWidget(start_date_time);

_hbox->addWidget(end_date_time);

_hbox->addWidget(duration);

_hbox->addWidget(calling_number);

_hbox->addWidget(calling_name);

_hbox->addWidget(called_number);

_hbox->addWidget(called_name);

_hbox->addWidget(ring_duration);

_hbox->addWidget(channel_number);

_hbox->addWidget(channel_name);

_hbox->addWidget(direction);

_hbox->addWidget(username);

_hbox->addWidget(short_comment);

_hbox->addWidget(case_number);

_hbox->addWidget(dtmf_received);

_hbox->addWidget(dtmf_sent);

_hbox->addWidget(signaling_src_ip);

_hbox->addWidget(signaling_src_port);

_hbox->addWidget(signaling_src_mac);

_hbox->addWidget(signaling_dst_ip);

_hbox->addWidget(signaling_dst_port);

_hbox->addWidget(signaling_dst_mac);

_hbox->addWidget(audio_src_ip);

_hbox->addWidget(audio_src_port);

_hbox->addWidget(audio_src_mac);

_hbox->addWidget(audio_dst_ip);

_hbox->addWidget(audio_dst_port);

_hbox->addWidget(audio_dst_mac);

int row = 0 ; int column = 0 ;

_grid->addWidget( _scroll_area , row , column , AlignTop | AlignLeft ) ;

column ;

_grid->addWidget( upDownContainer , row , column, AlignMiddle | AlignRight ) ;

column = 0 ; row ;

_grid->addWidget( buttonsContainer , row , column, 1 , 2 , AlignBottom | AlignCenter) ;

_grid->setRowStretch(0, 1 ) ;

_grid->setRowStretch(1, 0 ) ;

_grid->setColumnStretch( 0 , 1 ) ;

_grid->setColumnStretch( 1 , 0 ) ;

//----

this~~contents()>setLayout(_grid);

this->resize( 400 , 500 ) ;

}

//---------------------------------------------------------------------------------------------------------------------------

MyWidget::~MyWidget(void)

//---------------------------------------------------------------------------------------------------------------------------

{

}

//---------------------------------------------------------------------------------------------------------------------------

void MyWidget::move_up(void)

//---------------------------------------------------------------------------------------------------------------------------

{

if ( selected_item != NULL )

{

WWidgetItem* item = _hbox->findWidgetItem(selected_item);

if ( item != NULL )

{

int index = _hbox->indexOf( (Wt::WLayoutItem *)item ) ;

if ( index > 0 )

{

_hbox->removeWidget( selected_item ) ;

_hbox
insertWidget( index~~ 1 , selected_item ) ;

}

}

}

_scroll_area->refresh();

}

//---------------------------------------------------------------------------------------------------------------------------

void MyWidget::move_down(void)

//---------------------------------------------------------------------------------------------------------------------------

{

if ( selected_item != NULL )

{

WWidgetItem* item = _hbox->findWidgetItem(selected_item);

if ( item != NULL )

{

int index = _hbox->indexOf( (Wt::WLayoutItem *)item ) ;

if ( index >= 0 )

{

_hbox->removeWidget( selected_item ) ;

_hbox->insertWidget( index + 1 , selected_item ) ;

}

}

}

_scroll_area->refresh();

}

//---------------------------------------------------------------------------------------------------------------------------

void MyWidget::item_clicked()

//---------------------------------------------------------------------------------------------------------------------------

{

selected_item = (WCheckBox *) this->sender();

}

Actions #5

Updated by Koen Deforche almost 13 years ago

Hey,

Does the problem disappear when you do:

scrollContainer->setLayout ( _hbox, AlignJustify | AlignTop) ;

Regards,

koen

Actions #6

Updated by Koen Deforche almost 13 years ago

Hey,

I could not reproduce the slowness --- see attached test case. Can you modify it so that it reproduces your problem ?

Regards,

koen

Actions #7

Updated by Koen Deforche almost 13 years ago

  • Status changed from InProgress to Feedback
Actions #8

Updated by Koen Deforche almost 13 years ago

  • Status changed from Feedback to Resolved
Actions #9

Updated by Koen Deforche almost 13 years ago

  • Status changed from Resolved to Closed

Resolved in Wt 3.1.11

Actions

Also available in: Atom PDF