-
Felix de las Pozas authored14a51123
Summary.cpp 52.38 KiB
/*
* Copyright (c) 2015-2022 VG-Lab/URJC.
*
* Authors: Sergio E. Galindo <sergio.galindo@urjc.es>
*
* This file is part of ViSimpl <https://github.com/vg-lab/visimpl>
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 3.0 as published
* by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include "Summary.h"
#include <QMouseEvent>
#include <QComboBox>
#include <QPushButton>
#include <QVBoxLayout>
#include <QScrollArea>
#include <QInputDialog>
#include <QScrollBar>
#include <QApplication>
#include <QToolBox>
#include <QDebug>
unsigned int visimpl::Selection::_counter = 0;
constexpr unsigned int DEFAULT_BINS = 2500;
constexpr float DEFAULT_ZOOM_FACTOR = 1.5f;
constexpr float DEFAULT_SCALE = 1.0f;
constexpr float DEFAULT_SCALE_STEP = 0.3f;
static QString colorScaleToString( visimpl::TColorScale colorScale )
{
switch( colorScale )
{
case visimpl::T_COLOR_LINEAR:
return "Linear";
case visimpl::T_COLOR_LOGARITHMIC:
return "Logarithmic";
default:
return { };
}
}
namespace visimpl
{
Summary::Summary( QWidget* parent_,
TStackType stackType )
: QWidget( parent_ )
, _bins( DEFAULT_BINS )
, _zoomFactor( DEFAULT_ZOOM_FACTOR )
, _flagUpdateChartSize( true )
, _sizeChartVerticalDefault( 50 )
, _sizeChartHorizontal( 500 )
, _sizeChartVertical( _sizeChartVerticalDefault )
, _sizeView( 200 )
, _sizeMargin( 0 )
, _scaleCurrentHorizontal( DEFAULT_SCALE )
, _scaleCurrentVertical( DEFAULT_SCALE )
, _scaleStep( DEFAULT_SCALE_STEP )
, _gridLinesNumber( 3 )
, _simData( nullptr )
, _spikeReport( nullptr )
, _player( nullptr )
, _mainHistogram( nullptr )
, _focusedHistogram( nullptr )
, _mousePressed( false )
, _stackType( stackType )
, _colorScaleLocal( visimpl::T_COLOR_LINEAR )
, _colorScaleGlobal( visimpl::T_COLOR_LOGARITHMIC )
, _colorLocal( 0, 0, 128, 50 )
, _colorGlobal( 255, 0, 0, 100 )
, _focusWidget( nullptr )
, _spinBoxScaleHorizontal( nullptr )
, _spinBoxScaleVertical( nullptr )
, _layoutHistoLabels( nullptr )
, _scrollHistoLabels( nullptr )
, _layoutEventLabels( nullptr )
, _eventLabelsScroll( nullptr )
, _layoutHistograms( nullptr )
, _scrollHistogram( nullptr )
, _layoutEvents( nullptr )
, _scrollEvent( nullptr )
, _layoutMain( nullptr )
, _splitVertEventsHisto( nullptr )
, _splitHorizEvents( nullptr )
, _splitHorizHisto( nullptr )
, _maxNumEvents( 8 )
, _syncScrollsHorizontally( true )
, _syncScrollsVertically( true )
, _heightPerRow( 50 )
, _maxLabelWidth( 200 )
, _footHeightMax( 320)
, _footHeightMin( _footHeightMax )
, _footWidthMax( 250 )
, _footToolBox{nullptr}
, _showMarker( false )
, _regionPercentage( 0.0f )
, _regionWidthPixels( -1 )
, _overRegionEdgeLower( false )
, _selectedEdgeLower( false )
, _regionEdgePointLower( -1 )
, _regionEdgeLower( 0.0f )
, _overRegionEdgeUpper( false )
, _selectedEdgeUpper( false )
, _regionEdgePointUpper( -1 )
, _regionEdgeUpper( 0.0f )
, _autoNameSelection( false )
, _fillPlots( true )
, _defaultCorrelationDeltaTime( 0.125f )
{
setMouseTracking( true );
_initCentralGUI();
auto footWidget = _initFootGUI();
if( _stackType == T_STACK_EXPANDABLE )
{
_splitVertEventsHisto = new QSplitter( Qt::Vertical, this );
_splitVertEventsHisto->addWidget( _splitHorizEvents );
_splitVertEventsHisto->addWidget( _splitHorizHisto );
_splitVertEventsHisto->addWidget( footWidget );
_splitVertEventsHisto->setSizes( { 1000, 1000, 2000 } );
_layoutMain->addWidget(_splitVertEventsHisto );
}
#ifdef VISIMPL_USE_ZEROEQ
_insertionTimer.setSingleShot( false );
_insertionTimer.setInterval( 250 );
connect( &_insertionTimer, SIGNAL( timeout()),
this, SLOT(deferredInsertion()));
_insertionTimer.start();
#endif
// Fill the palette with ColorbBewer qualitative palette with 10 classes
// but rearranging to have consecutive colors with different hue.
_eventsPalette = scoop::ColorPalette::colorBrewerQualitative(
scoop::ColorPalette::ColorBrewerQualitative::Set1, 9 );
}
void Summary::Init( simil::SimulationData* data_ )
{
_simData = data_;
switch( data_->simulationType())
{
case simil::TSimSpikes:
{
auto *spikeData = dynamic_cast< simil::SpikeData * >( _simData );
_spikeReport = spikeData;
break;
}
default:
break;
}
_gids = GIDUSet( data_->gids().begin(), data_->gids().end());
Init();
}
void Summary::_initCentralGUI( )
{
if ( _stackType == T_STACK_FIXED )
{
_layoutHistograms = new QGridLayout( );
this->setLayout( _layoutHistograms );
}
else if ( _stackType == T_STACK_EXPANDABLE )
{
_maxColumns = 20;
_regionWidth = 0.1f;
_summaryColumns = _maxColumns - 2;
_layoutMain = new QVBoxLayout( );
_layoutMain->setAlignment( Qt::AlignTop );
this->setLayout( _layoutMain );
_layoutEventLabels = new QGridLayout( );
_layoutEventLabels->setAlignment( Qt::AlignTop );
_layoutEventLabels->setVerticalSpacing( 0 );
_layoutEventLabels->setMargin(2);
auto eventLabelsContainer = new QWidget( );
eventLabelsContainer->setLayout( _layoutEventLabels );
eventLabelsContainer->setMaximumWidth( 150 );
eventLabelsContainer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
_eventLabelsScroll = new QScrollArea();
_eventLabelsScroll->setWidgetResizable( true );
_eventLabelsScroll->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
_eventLabelsScroll->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
_eventLabelsScroll->setVisible( false );
_eventLabelsScroll->setWidget( eventLabelsContainer );
_layoutEvents = new QGridLayout();
_layoutEvents->setAlignment( Qt::AlignTop );
_layoutEvents->setVerticalSpacing( 0 );
auto *eventsContainer = new QWidget( );
eventsContainer->setLayout( _layoutEvents );
_scrollEvent = new QScrollArea( );
_scrollEvent->setWidgetResizable( true );
_scrollEvent->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
_scrollEvent->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
_scrollEvent->setVisible( false );
_scrollEvent->setWidget( eventsContainer );
_scrollEvent->horizontalScrollBar()->setMinimum(0);
_scrollEvent->horizontalScrollBar()->setMaximum(1000);
connect(
_scrollEvent->horizontalScrollBar( ) , SIGNAL( actionTriggered( int )) ,
this , SLOT( moveHoriScrollSync( int ))
);
connect(
_scrollEvent->verticalScrollBar( ) , SIGNAL( valueChanged( int )) ,
_eventLabelsScroll->verticalScrollBar(), SLOT(setValue(int))
);
_layoutHistoLabels = new QGridLayout( );
_layoutHistoLabels->setAlignment( Qt::AlignTop );
_layoutHistoLabels->setVerticalSpacing( 0 );
_layoutHistoLabels->setMargin(2);
auto histogramLabelsContainer = new QWidget( );
histogramLabelsContainer->setLayout( _layoutHistoLabels );
histogramLabelsContainer->setMaximumWidth( 150 );
histogramLabelsContainer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
_scrollHistoLabels = new QScrollArea( );
_scrollHistoLabels->setWidgetResizable( true );
_scrollHistoLabels->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff);
_scrollHistoLabels->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
_scrollHistoLabels->setWidget( histogramLabelsContainer );
_layoutHistograms = new QGridLayout( );
_layoutHistograms->setAlignment( Qt::AlignTop );
_layoutHistograms->setVerticalSpacing( 0 );
auto histogramsContainer = new QWidget( );
histogramsContainer->setLayout( _layoutHistograms );
_scrollHistogram = new QScrollArea( );
_scrollHistogram->setWidgetResizable( true );
_scrollHistogram->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
_scrollHistogram->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
_scrollHistogram->setWidget( histogramsContainer );
_scrollHistogram->horizontalScrollBar( )->setMinimum( 0 );
_scrollHistogram->horizontalScrollBar( )->setMaximum( 1000 );
connect(_scrollHistogram->verticalScrollBar(), SIGNAL(valueChanged(int)),
_scrollHistoLabels->verticalScrollBar(), SLOT(setValue(int)));
connect(
_scrollHistogram->horizontalScrollBar( ) ,
SIGNAL( actionTriggered( int )) ,
this , SLOT( moveHoriScrollSync( int ))
);
_splitHorizEvents = new QSplitter( Qt::Horizontal );
_splitHorizHisto = new QSplitter( Qt::Horizontal );
_splitHorizEvents->addWidget( _eventLabelsScroll );
_splitHorizEvents->addWidget( _scrollEvent );
_splitHorizEvents->setCollapsible(0, false);
_splitHorizEvents->setCollapsible(1, false);
_splitHorizEvents->setStretchFactor(0, 0);
_splitHorizEvents->setStretchFactor(1, 1);
_splitHorizHisto->addWidget( _scrollHistoLabels );
_splitHorizHisto->addWidget( _scrollHistogram );
_splitHorizHisto->setCollapsible(0, false);
_splitHorizHisto->setCollapsible(1, false);
_splitHorizHisto->setStretchFactor(0, 0);
_splitHorizHisto->setStretchFactor(1, 1);
connect(
_splitHorizEvents , SIGNAL( splitterMoved( int , int )) ,
this , SLOT( syncSplitters( ))
);
connect(
_splitHorizHisto , SIGNAL( splitterMoved( int , int )) ,
this , SLOT( syncSplitters( ))
);
}
}
QWidget* Summary::_initFootGUI( void )
{
auto foot = new QWidget( );
auto footLayout = new QGridLayout( );
_footToolBox = new QToolBox( );
_footToolBox->setMaximumWidth( 300 );
// FOCUS
_focusWidget = new FocusFrame( );
_focusWidget->colorLocal( _colorLocal );
_focusWidget->colorGlobal( _colorGlobal );
_focusWidget->setMinimumHeight( 200 );
_focusWidget->setMinimumWidth( 200 );
// NORMALIZATION
_localColorWidget = new QWidget( );
_localColorWidget->setPalette( QPalette( _colorLocal ));
_localColorWidget->setAutoFillBackground( true );
_localColorWidget->setFixedSize(30, 30);
_globalColorWidget = new QWidget( );
_globalColorWidget->setPalette( QPalette( _colorGlobal ));
_globalColorWidget->setAutoFillBackground( true );
_globalColorWidget->setFixedSize(30, 30);
QStringList csItems;
csItems.push_back( QString( colorScaleToString( visimpl::T_COLOR_LINEAR )));
csItems.push_back(
QString( colorScaleToString( visimpl::T_COLOR_LOGARITHMIC )));
auto localComboBox = new QComboBox( );
localComboBox->addItems( csItems );
auto globalComboBox = new QComboBox( );
globalComboBox->addItems( csItems );
auto groupBoxNorm = new QWidget( );
auto layoutNorm = new QGridLayout( );
layoutNorm->setAlignment( Qt::AlignTop );
groupBoxNorm->setLayout( layoutNorm );
layoutNorm->addWidget( new QLabel( "Local:" ) , 0 , 0 , 1 , 1 );
layoutNorm->addWidget( _localColorWidget , 0 , 1 , 1 , 1 );
layoutNorm->addWidget( localComboBox , 0 , 2 , 1 , 1 );
layoutNorm->addWidget( new QLabel( "Global:" ) , 1 , 0 , 1 , 1 );
layoutNorm->addWidget( _globalColorWidget , 1 , 1 , 1 , 1 );
layoutNorm->addWidget( globalComboBox , 1 , 2 , 1 , 1 );
localComboBox->setCurrentIndex(( int ) _colorScaleLocal );
globalComboBox->setCurrentIndex(( int ) _colorScaleGlobal );
connect(
localComboBox , SIGNAL( currentIndexChanged( int )) ,
this , SLOT( colorScaleLocal( int ))
);
connect(
globalComboBox , SIGNAL( currentIndexChanged( int )) ,
this , SLOT( colorScaleGlobal( int ))
);
// SCALE ADJUSTMENT
_spinBoxScaleHorizontal = new QDoubleSpinBox( );
_spinBoxScaleHorizontal->setMinimum( 1.0 );
_spinBoxScaleHorizontal->setMaximum( 500 );
_spinBoxScaleHorizontal->setSingleStep( 0.1 );
_spinBoxScaleHorizontal->setValue( DEFAULT_SCALE );
_spinBoxScaleVertical = new QDoubleSpinBox( );
_spinBoxScaleVertical->setMinimum( 1.0 );
_spinBoxScaleVertical->setMaximum( 5 );
_spinBoxScaleVertical->setSingleStep( 0.1 );
_spinBoxScaleVertical->setValue( DEFAULT_SCALE );
auto groupBoxScale = new QWidget( );
auto layoutScale = new QGridLayout( );
layoutScale->setAlignment( Qt::AlignTop );
groupBoxScale->setLayout( layoutScale );
layoutScale->addWidget( new QLabel( "Horizontal: " ) , 0 , 0 , 1 , 1 );
layoutScale->addWidget( _spinBoxScaleHorizontal , 0 , 1 , 1 , 1 );
layoutScale->addWidget( new QLabel( "Vertical: " ) , 1 , 0 , 1 , 1 );
layoutScale->addWidget( _spinBoxScaleVertical , 1 , 1 , 1 , 1 );
connect(
_spinBoxScaleHorizontal , SIGNAL( editingFinished( void )) ,
this , SLOT( _updateScaleHorizontal( void ))
);
connect(
_spinBoxScaleVertical , SIGNAL( editingFinished( void )) ,
this , SLOT( _updateScaleVertical( void ))
);
// BIN CONFIGURATION
_spinBoxBins = new QSpinBox( );
_spinBoxBins->setMinimum( 50 );
_spinBoxBins->setMaximum( 100000 );
_spinBoxBins->setSingleStep( 50 );
_spinBoxBins->setValue( static_cast<int>(_bins));
_spinBoxZoomFactor = new QDoubleSpinBox( );
_spinBoxZoomFactor->setMinimum( 1.0 );
_spinBoxZoomFactor->setMaximum( 1000.0 );
_spinBoxZoomFactor->setSingleStep( 0.5 );
_spinBoxZoomFactor->setValue( _zoomFactor );
auto groupBoxBinConfig = new QWidget( );
auto layoutBinConfig = new QGridLayout( );
layoutBinConfig->setAlignment( Qt::AlignTop );
groupBoxBinConfig->setLayout( layoutBinConfig );
layoutBinConfig->addWidget( new QLabel( "Bins number:" ) , 0 , 0 , 1 , 1 );
layoutBinConfig->addWidget( _spinBoxBins , 0 , 1 , 1 , 1 );
layoutBinConfig->addWidget( new QLabel( "Zoom factor:" ) , 1 , 0 , 1 , 1 );
layoutBinConfig->addWidget( _spinBoxZoomFactor , 1 , 1 , 1 , 1 );
connect(
_spinBoxBins , SIGNAL( editingFinished( void )) ,
this , SLOT( binsChanged( void ))
);
connect(
_spinBoxZoomFactor , SIGNAL( editingFinished( void )) ,
this , SLOT( zoomFactorChanged( void ))
);
// DATA INSPECTOR
_currentValueLabel = new QLabel( "" );
_currentValueLabel->setMaximumWidth( 50 );
_globalMaxLabel = new QLabel( "" );
_globalMaxLabel->setMaximumWidth( 50 );
_localMaxLabel = new QLabel( "" );
_localMaxLabel->setMaximumWidth( 50 );
auto groupBoxInformation = new QWidget( );
auto layoutInformation = new QGridLayout( );
layoutInformation->setAlignment( Qt::AlignTop );
groupBoxInformation->setLayout( layoutInformation );
layoutInformation->addWidget( new QLabel( "Current value: " ) , 2 , 9 , 1 ,
2 );
layoutInformation->addWidget( _currentValueLabel , 2 , 11 , 1 , 1 );
layoutInformation->addWidget( new QLabel( "Local max: " ) , 3 , 9 , 1 , 2 );
layoutInformation->addWidget( _localMaxLabel , 3 , 11 , 1 , 1 );
layoutInformation->addWidget( new QLabel( "Global max: " ) , 4 , 9 , 1 ,
2 );
layoutInformation->addWidget( _globalMaxLabel , 4 , 11 , 1 , 1 );
// RULE CONFIGURATION
auto *gridSpinBox = new QSpinBox( );
gridSpinBox->setMinimum( 0 );
gridSpinBox->setMaximum( 10000 );
gridSpinBox->setSingleStep( 1 );
gridSpinBox->setValue( 3 );
auto *groupBoxRuleConfig = new QWidget( );
auto *layoutRuleConfig = new QGridLayout( );
layoutRuleConfig->setAlignment( Qt::AlignTop );
groupBoxRuleConfig->setLayout( layoutRuleConfig );
layoutRuleConfig->addWidget( new QLabel( "Rule sectors: " ) , 0 , 0 , 1 ,
1 );
layoutRuleConfig->addWidget( gridSpinBox , 0 , 1 , 1 , 1 );
connect(
gridSpinBox , SIGNAL( valueChanged( int )) ,
this , SLOT( gridLinesNumber( int ))
);
//
_footToolBox->addItem( groupBoxNorm , "Normalization" );
_footToolBox->addItem( groupBoxScale , "Scale adjustment" );
_footToolBox->addItem( groupBoxBinConfig , "Bin configuration" );
_footToolBox->addItem( groupBoxInformation , "Data inspector" );
_footToolBox->addItem( groupBoxRuleConfig , "Rule configuration" );
footLayout->addWidget( _focusWidget , 0 , 0 , 1 , 1 );
footLayout->addWidget( _footToolBox , 0 , 1 , 1 , 1 );
footLayout->setColumnStretch(0, 1);
footLayout->setColumnStretch(1, 0);
foot->setLayout( footLayout );
return foot;
}
void Summary::Init()
{
if( !_spikeReport )
return;
_mainHistogram = new visimpl::HistogramWidget( *_spikeReport );
_mainHistogram->setMinimumHeight( _heightPerRow );
_mainHistogram->setMaximumHeight( _heightPerRow );
_mainHistogram->colorScaleLocal( _colorScaleLocal );
_mainHistogram->colorScaleGlobal( _colorScaleGlobal );
_mainHistogram->colorLocal( _colorLocal );
_mainHistogram->colorGlobal( _colorGlobal );
_mainHistogram->representationMode( visimpl::T_REP_CURVE );
_mainHistogram->regionWidth( _regionWidth );
_mainHistogram->gridLinesNumber( _gridLinesNumber );
_mainHistogram->firstHistogram( true );
_mainHistogram->setMinimumWidth( _sizeChartHorizontal );
_mainHistogram->simPlayer( _player );
TColorMapper colorMapper;
colorMapper.Insert( 0.0f, glm::vec4( 157, 206, 111, 255 ));
colorMapper.Insert( 0.25f, glm::vec4( 125, 195, 90, 255 ));
colorMapper.Insert( 0.50f, glm::vec4( 109, 178, 113, 255 ));
colorMapper.Insert( 0.75f, glm::vec4( 76, 165, 86, 255 ));
colorMapper.Insert( 1.0f, glm::vec4( 63, 135, 61, 255 ));
_mainHistogram->colorMapper( colorMapper );
_mainHistogram->mousePosition( &_lastMousePosition );
_mainHistogram->regionPosition( &_regionPercentage );
connect( _mainHistogram, SIGNAL( mousePositionChanged( QPoint )),
this, SLOT( updateMouseMarker( QPoint )));
_mainHistogram->init( _bins, _zoomFactor );
if( _stackType == T_STACK_FIXED)
{
_layoutHistograms->addWidget( _mainHistogram, 0, 1, 1, 1 );
_mainHistogram->paintRegion( false );
_mainHistogram->simPlayer( _player );
_histogramWidgets.push_back( _mainHistogram );
connect( _mainHistogram, SIGNAL( mousePressed( QPoint, float )),
this, SLOT( childHistogramPressed( QPoint, float )));
}
else if( _stackType == T_STACK_EXPANDABLE )
{
const QString text{"All"};
HistogramRow mainRow;
mainRow.histogram = _mainHistogram;
mainRow.histogram->_events = &_events;
mainRow.histogram->name( text.toStdString() );
mainRow.label = new QLabel( text );
mainRow.label->setMaximumWidth( _maxLabelWidth );
mainRow.label->setMinimumHeight( _heightPerRow );
mainRow.label->setMaximumHeight( _heightPerRow );
const unsigned int row = _histogramWidgets.size();
_layoutHistoLabels->addWidget( mainRow.label, row , 0, 1, 1 );
_layoutHistograms->addWidget( _mainHistogram, row, 1, 1, _summaryColumns );
_histogramRows.push_back( mainRow );
_histogramWidgets.push_back( _mainHistogram );
connect( _mainHistogram, SIGNAL( mousePressed( QPoint, float )),
this, SLOT( childHistogramPressed( QPoint, float )));
connect( _mainHistogram, SIGNAL( mouseReleased( QPoint, float )),
this, SLOT( childHistogramReleased( QPoint, float )));
connect( _mainHistogram, SIGNAL( mouseModifierPressed( float, Qt::KeyboardModifiers )),
this, SLOT( childHistogramClicked( float, Qt::KeyboardModifiers )));
if( _eventLabelsScroll )
_eventLabelsScroll->setVisible( false );
if( _scrollEvent )
_scrollEvent->setVisible( false );
}
update();
}
void Summary::generateEventsRep( void )
{
if( _simData->subsetsEvents()->numEvents() > 0 )
{
_eventLabelsScroll->setVisible( true );
_scrollEvent->setVisible( true );
const simil::EventRange timeFrames = _simData->subsetsEvents()->events();
float invTotal = 1.0f / ( _spikeReport->endTime() - _spikeReport->startTime());
unsigned int counter = 0;
for( auto it = timeFrames.first; it != timeFrames.second; ++it, ++counter )
{
TEvent timeFrame;
timeFrame.name = it->first;
timeFrame.visible = true;
for( auto time : it->second )
{
float startPercentage =
std::max( 0.0f,
( time.first - _spikeReport->startTime()) * invTotal);
float endPercentage =
std::min( 1.0f,
( time.second - _spikeReport->startTime()) * invTotal);
timeFrame.percentages.push_back(
std::make_pair( startPercentage, endPercentage ));
}
timeFrame.color = _eventsPalette.colors()[
counter /* % _eventsPalette.size() */ ];
_events.push_back( timeFrame );
QLabel* label = new QLabel( timeFrame.name.c_str());
label->setMinimumHeight( 20 );
label->setMaximumWidth( _maxLabelWidth );
label->setMinimumHeight( _heightPerRow );
label->setMaximumHeight( _heightPerRow );
label->setToolTip( timeFrame.name.c_str());
EventWidget* eventWidget = new EventWidget();
eventWidget->name( timeFrame.name );
eventWidget->setSizePolicy( QSizePolicy::Expanding,
QSizePolicy::Expanding );
eventWidget->timeFrames( &_events );
eventWidget->setMinimumWidth( _sizeChartHorizontal );
eventWidget->setMinimumHeight( _heightPerRow );
eventWidget->setMaximumHeight( _heightPerRow );
eventWidget->index( counter );
EventRow eventrow;
eventrow.widget = eventWidget;
eventrow.label = label;
_eventRows.push_back( eventrow );
_eventWidgets.push_back( eventWidget );
_layoutEventLabels->addWidget( label, counter, 0, 1, 1 );
_layoutEvents->addWidget( eventWidget, counter, 1, 1, _summaryColumns );
}
updateLabelsWidth();
}
}
void Summary::importSubsetsFromSubsetMngr( void )
{
simil::SubsetMapRange subsets =
_spikeReport->subsetsEvents()->subsets();
for( auto it = subsets.first; it != subsets.second; ++it )
{
GIDUSet subset( it->second.begin(), it->second.end());
insertSubset( it->first, subset );
}
}
void Summary::AddNewHistogram( const visimpl::Selection& selection
#ifdef VISIMPL_USE_ZEROEQ
, bool deferred
#endif
)
{
const GIDUSet& selected = selection.gids;
if( selected.size() == _gids.size() || selected.size() == 0)
return;
if( _stackType == TStackType::T_STACK_EXPANDABLE )
{
#ifdef VISIMPL_USE_ZEROEQ
if( deferred )
{
_pendingSelections.push_back( selection );
}
else
#endif
{
insertSubset( selection );
}
}
}
#ifdef VISIMPL_USE_ZEROEQ
void Summary::deferredInsertion( void )
{
if( _pendingSelections.size() > 0 )
{
auto selection = _pendingSelections.front();
_pendingSelections.pop_front();
QString labelText = "Selection ";
if(selection.id != 0)
{
labelText += QString::number(selection.id);
}
else
{
labelText += QString::number(histogramsNumber());
}
bool ok = true;
if ( !_autoNameSelection )
labelText = QInputDialog::getText( this,
tr( "Selection Name" ),
tr( "Please, introduce selection name: "),
QLineEdit::Normal,
labelText,
&ok );
if( !ok )
return;
selection.name = labelText.toStdString();
insertSubset( selection );
}
}
#endif
void Summary::UpdateHistograms( void )
{
auto updateHistogram = [&](HistogramWidget *h)
{
h->Spikes(*_spikeReport);
h->Update();
h->update();
};
std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), updateHistogram);
}
void Summary::insertSubset( const Selection& selection )
{
insertSubset( selection.name, selection.gids );
}
void Summary::insertSubset( const std::string& name, const GIDUSet& subset )
{
HistogramRow currentRow;
auto histogram = new visimpl::HistogramWidget( *_spikeReport );
histogram->filteredGIDs( subset );
histogram->name( name );
histogram->colorMapper( _mainHistogram->colorMapper());
histogram->colorScaleLocal( _colorScaleLocal );
histogram->colorScaleGlobal( _colorScaleGlobal );
histogram->colorLocal( _colorLocal );
histogram->colorGlobal( _colorGlobal );
histogram->normalizeRule( visimpl::T_NORM_MAX );
histogram->representationMode( visimpl::T_REP_CURVE );
histogram->regionWidth( _regionWidth );
histogram->gridLinesNumber( _gridLinesNumber );
histogram->init( _bins, _zoomFactor );
if( histogram->empty())
{
delete histogram;
return;
}
histogram->setMinimumHeight( _heightPerRow );
histogram->setMaximumHeight( _heightPerRow );
histogram->setMinimumWidth( _sizeChartHorizontal );
histogram->simPlayer( _player );
histogram->_events = &_events;
currentRow.histogram = histogram;
currentRow.label = new QLabel( name.c_str());
currentRow.label->setMaximumWidth( _maxLabelWidth );
currentRow.label->setMinimumHeight( _heightPerRow );
currentRow.label->setMaximumHeight( _heightPerRow );
currentRow.label->setToolTip( name.c_str());
const unsigned int row = _histogramWidgets.size();
_layoutHistoLabels->addWidget( currentRow.label, row , 0, 1, 1 );
_layoutHistograms->addWidget( histogram, row, 1, 1, _summaryColumns );
_histogramRows.push_back( currentRow );
histogram->mousePosition( &_lastMousePosition );
histogram->regionPosition( &_regionPercentage );
connect( histogram, SIGNAL( mousePositionChanged( QPoint )),
this, SLOT( updateMouseMarker( QPoint )));
connect( histogram, SIGNAL( mousePressed( QPoint, float )),
this, SLOT( childHistogramPressed( QPoint, float )));
connect( histogram, SIGNAL( mouseReleased( QPoint, float )),
this, SLOT( childHistogramReleased( QPoint, float )));
connect( histogram, SIGNAL( mouseModifierPressed( float, Qt::KeyboardModifiers )),
this, SLOT( childHistogramClicked( float, Qt::KeyboardModifiers )));
_histogramWidgets.push_back( histogram );
updateLabelsWidth();
update();
}
void Summary::childHistogramPressed( const QPoint& position, float /*percentage*/ )
{
if( _stackType == T_STACK_FIXED )
{
const QPoint cursorLocalPoint = _mainHistogram->mapFromGlobal( position );
const float percentage = float( cursorLocalPoint.x()) / _mainHistogram->width();
emit histogramClicked( percentage );
return;
}
if( _focusedHistogram != sender())
{
_focusedHistogram =
dynamic_cast< visimpl::HistogramWidget* >( sender());
_focusedHistogram->regionWidth( _regionWidth );
}
const QPoint cursorLocalPoint = _focusedHistogram->mapFromGlobal( position );
const float percentage = float( cursorLocalPoint.x()) / _focusedHistogram->width();
_currentValueLabel->setText(
QString::number( _focusedHistogram->focusValueAt( percentage )));
_localMaxLabel->setText( QString::number( _focusedHistogram->focusMaxLocal()));
_globalMaxLabel->setText( QString::number( _focusedHistogram->focusMaxGlobal()));
if( _overRegionEdgeLower )
{
_selectedEdgeLower = true;
_selectedEdgeUpper = false;
}
else if( _overRegionEdgeUpper )
{
_selectedEdgeLower = false;
_selectedEdgeUpper = true;
}
else
{
_regionGlobalPosition = position;
_regionWidthPixels = _regionWidth * _focusedHistogram->width();
SetFocusRegionPosition( cursorLocalPoint );
_selectedEdgeLower = _selectedEdgeUpper = false;
}
_mousePressed = true;
auto focusedHistogram = _focusedHistogram;
auto setPaintRegion = [&focusedHistogram](HistogramWidget *w)
{
w->paintRegion(w == focusedHistogram);
w->update();
};
std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), setPaintRegion);
}
void Summary::childHistogramReleased( const QPoint& /*position*/, float /*percentage*/ )
{
_mousePressed = false;
}
void Summary::childHistogramClicked( float percentage,
Qt::KeyboardModifiers modifiers )
{
if( _stackType == T_STACK_FIXED )
{
emit histogramClicked( percentage );
}
else if( _stackType == T_STACK_EXPANDABLE )
{
if( modifiers == Qt::ControlModifier )
emit histogramClicked(
dynamic_cast< visimpl::HistogramWidget* >( sender()));
else if( modifiers == Qt::ShiftModifier )
emit histogramClicked( percentage );
}
}
void Summary::mouseMoveEvent( QMouseEvent* event_ )
{
QWidget::mouseMoveEvent( event_ );
QApplication::setOverrideCursor( Qt::ArrowCursor );
}
constexpr int regionEditMarginPixels = 2;
void Summary::SetFocusRegionPosition( const QPoint& cursorLocalPosition )
{
if( _stackType == T_STACK_FIXED )
return;
_regionLocalPosition = cursorLocalPosition;
// Limit the region position with borders
_regionLocalPosition.setX( std::max( _regionWidthPixels, _regionLocalPosition.x( )));
_regionLocalPosition.setX( std::min( _regionLocalPosition.x( ),
_focusedHistogram->width() - _regionWidthPixels));
setFocusAt( static_cast<float>(_regionLocalPosition.x()) / _focusedHistogram->width() );
}
void Summary::updateRegionBounds( void )
{
if( _focusedHistogram )
{
_regionLocalPosition =
QPoint( _focusedHistogram->width() * _regionPercentage,
_focusedHistogram->height() * 0.5f );
_regionWidthPixels = _regionWidth * _focusedHistogram->width();
_regionLocalPosition.setX(
std::max( _regionWidthPixels, _regionLocalPosition.x( )));
_regionLocalPosition.setX( std::min( _regionLocalPosition.x( ),
_focusedHistogram->width() - _regionWidthPixels));
calculateRegionBounds();
_focusWidget->update();
}
}
void Summary::calculateRegionBounds( void )
{
_regionEdgeLower = std::max( _regionPercentage - _regionWidth, _regionWidth );
_regionEdgePointLower = _regionLocalPosition.x() - _regionWidthPixels;
_regionEdgeUpper = std::min( _regionPercentage + _regionWidth, 1.0f - _regionWidth);
_regionEdgePointUpper = _regionLocalPosition.x() + _regionWidthPixels;
}
void Summary::updateMouseMarker( QPoint point )
{
auto focusedHistogram = qobject_cast< visimpl::HistogramWidget* >( sender());
if(!focusedHistogram)
return;
_lastMousePosition = point;
if( _stackType != T_STACK_EXPANDABLE )
{
_mainHistogram->update();
return;
}
const float invWidth = 1.0f / float( focusedHistogram->width());
const QPoint cursorLocalPoint = focusedHistogram->mapFromGlobal( point );
if( focusedHistogram == _focusedHistogram )
{
if( _mousePressed )
{
if( _selectedEdgeLower )
{
float diffPerc = ( cursorLocalPoint.x() - _regionEdgePointLower ) * invWidth;
_regionWidth -= diffPerc;
const float regionMinSize = 5.0f / focusedHistogram->width();
_regionWidth = std::max( regionMinSize, std::min( 0.5f, _regionWidth ));
_regionWidthPixels = _regionWidth * _focusedHistogram->width();
calculateRegionBounds();
_focusWidget->viewRegion( *_focusedHistogram, _regionPercentage, _regionWidth );
_focusWidget->update();
QApplication::setOverrideCursor( Qt::SizeHorCursor );
}
else if ( _selectedEdgeUpper )
{
const float diffPerc = ( cursorLocalPoint.x() - _regionEdgePointUpper ) * invWidth;
_regionWidth += diffPerc;
const float regionMinSize = 5.0f / focusedHistogram->width();
_regionWidth = std::max( regionMinSize,
std::min( 0.5f, _regionWidth ));
_regionWidthPixels = _regionWidth * _focusedHistogram->width();
calculateRegionBounds();
_focusWidget->viewRegion( *_focusedHistogram, _regionPercentage,
_regionWidth );
_focusWidget->update();
QApplication::setOverrideCursor( Qt::SizeHorCursor );
}
else
{
_regionGlobalPosition = point;
SetFocusRegionPosition( cursorLocalPoint );
QApplication::setOverrideCursor( Qt::ArrowCursor );
}
_focusedHistogram->regionWidth( _regionWidth );
} // end mousePressed
else
{
if( abs(cursorLocalPoint.x() - _regionEdgePointLower) < regionEditMarginPixels )
{
_overRegionEdgeLower = true;
QApplication::setOverrideCursor( Qt::SizeHorCursor );
}
else if( abs(_regionEdgePointUpper - cursorLocalPoint.x()) < regionEditMarginPixels )
{
_overRegionEdgeUpper = true;
QApplication::setOverrideCursor( Qt::SizeHorCursor );
}
else
{
QApplication::setOverrideCursor( Qt::ArrowCursor );
_overRegionEdgeLower = _overRegionEdgeUpper = false;
}
}
}
else
{
QApplication::setOverrideCursor( Qt::ArrowCursor );
_overRegionEdgeLower = _overRegionEdgeUpper = false;
}
if( _stackType == T_STACK_EXPANDABLE && _mousePressed )
{
auto setPaintRegion = [&focusedHistogram](HistogramWidget *w)
{
w->paintRegion(w == focusedHistogram);
w->update();
};
std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), setPaintRegion);
}
}
void Summary::CreateSummarySpikes()
{
auto initHistogram = [this](HistogramWidget *w)
{
if( !w->isInitialized() )
w->init( _bins, _zoomFactor );
};
std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), initHistogram);
}
void Summary::UpdateGradientColors( bool replace )
{
auto updateColors = [&replace](HistogramWidget *w)
{
if( !w->isInitialized() || replace)
w->CalculateColors();
};
std::for_each( _histogramWidgets.begin(), _histogramWidgets.end(), updateColors);
}
unsigned int Summary::histogramsNumber( void )
{
return _histogramWidgets.size();
}
void Summary::binsChanged( void )
{
const unsigned int binsNumber = _spinBoxBins->value();
bins( binsNumber );
}
void Summary::bins( unsigned int bins_ )
{
if(_bins == bins_) return;
_bins = bins_;
#ifdef VISIMPL_USE_OPENMP
#pragma omp parallel for
for( int i = 0; i < static_cast<int>(_histogramWidgets.size()); ++i )
{
auto histogram = _histogramWidgets[ i ];
#else
for( auto histogram : _histogramWidgets )
{
#endif
histogram->bins( _bins );
histogram->update();
}
if(_focusedHistogram)
{
_focusWidget->viewRegion( *_focusedHistogram, _regionPercentage, _regionWidth );
_focusWidget->update();
}
}
void Summary::zoomFactorChanged( void )
{
double value = _spinBoxZoomFactor->value();
zoomFactor( value );
}
void Summary::zoomFactor( double zoom )
{
if(_zoomFactor == zoom) return;
_zoomFactor = zoom;
#ifdef VISIMPL_USE_OPENMP
#pragma omp parallel for
for( int i = 0; i < static_cast<int>(_histogramWidgets.size()); ++i )
{
auto histogram = _histogramWidgets[ i ];
#else
for( auto histogram : _histogramWidgets )
{
#endif
histogram->zoomFactor( _zoomFactor );
histogram->update();
}
}
void Summary::fillPlots( bool fillPlots_ )
{
_fillPlots = fillPlots_;
auto setFill = [&fillPlots_](HistogramWidget *w)
{
w->fillPlots( fillPlots_ );
w->update();
};
std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), setFill);
_focusWidget->fillPlots( _fillPlots );
_focusWidget->update();
}
void Summary::toggleAutoNameSelections( void )
{
_autoNameSelection = !_autoNameSelection;
}
unsigned int Summary::bins( void )
{
return _bins;
}
float Summary::zoomFactor( void )
{
return _zoomFactor;
}
void Summary::heightPerRow( unsigned int height_ )
{
_heightPerRow = height_;
auto updateHeight = [&height_](HistogramWidget *w)
{
w->setMinimumHeight( height_ );
w->setMaximumHeight( height_ );
w->update();
};
std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), updateHeight);
}
unsigned int Summary::heightPerRow( void )
{
return _heightPerRow;
}
void Summary::showMarker( bool show_ )
{
_showMarker = show_;
}
const std::vector< EventWidget* >* Summary::eventWidgets( void ) const
{
return &_eventWidgets;
}
const std::vector< HistogramWidget* >* Summary::histogramWidgets( void ) const
{
return &_histogramWidgets;
}
void Summary::hideRemoveEvent( unsigned int i, bool hideDelete )
{
if( hideDelete )
{
eventVisibility( i, !_eventWidgets[ i ]->isVisible());
}
else
{
removeEvent( i );
}
}
void Summary::hideRemoveSubset( unsigned int i, bool hideDelete )
{
if( hideDelete )
{
subsetVisibility( i, !_histogramWidgets[ i ]->isVisible());
}
else
{
removeSubset( i );
}
}
void Summary::updateEventWidgets( void )
{
unsigned int counter = 0;
auto updateWidget = [&counter](EventWidget *w)
{
if( w->isVisible())
{
w->index( counter );
++counter;
}
w->update();
};
std::for_each(_eventWidgets.begin(), _eventWidgets.end(), updateWidget);
}
void Summary::updateHistogramWidgets( void )
{
unsigned int counter = 0;
auto updateHistogram = [&counter](HistogramWidget *w)
{
if( !w->isVisible())
return;
w->firstHistogram( counter == 0 );
++counter;
w->update();
};
std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), updateHistogram);
}
void Summary::eventVisibility( unsigned int i, bool show )
{
EventRow& row = _eventRows[ i ];
row.widget->setVisible( show );
row.label->setVisible( show );
_events[ i ].visible = show;
updateEventWidgets();
repaintHistograms();
}
void Summary::subsetVisibility( unsigned int i, bool show )
{
HistogramRow& row = _histogramRows[ i ];
row.histogram->setVisible( show );
row.label->setVisible( show );
updateHistogramWidgets();
}
void Summary::clearEvents( void )
{
auto removeRow = [this](visimpl::Summary::EventRow &event)
{
_layoutEventLabels->removeWidget( event.label );
_layoutEvents->removeWidget( event.widget );
delete event.label;
delete event.widget;
};
std::for_each(_eventRows.begin(), _eventRows.end(), removeRow);
_events.clear();
_eventWidgets.clear();
_eventRows.clear();
updateEventWidgets();
_eventLabelsScroll->setVisible( false );
_scrollEvent->setVisible( false );
update();
}
void Summary::removeEvent( unsigned int i )
{
auto& timeFrameRow = _eventRows[ i ];
_layoutEventLabels->removeWidget( timeFrameRow.label );
_layoutEvents->removeWidget( timeFrameRow.widget );
delete timeFrameRow.label;
delete timeFrameRow.widget;
_events.erase( _events.begin() + i );
_eventWidgets.erase( _eventWidgets.begin() + i );
_eventRows.erase( _eventRows.begin() + i);
updateEventWidgets();
if( _eventRows.size() == 0 )
{
_eventLabelsScroll->setVisible( false );
_scrollEvent->setVisible( false );
}
}
void Summary::removeSubset( unsigned int i )
{
auto& summaryRow = _histogramRows[ i ];
// Avoid deleting last histogram
if( _mainHistogram == summaryRow.histogram && _histogramRows.size() <= 1 )
return;
if( _focusedHistogram == summaryRow.histogram )
{
_focusedHistogram = nullptr;
_focusWidget->clear();
_focusWidget->update();
}
_layoutHistoLabels->removeWidget( summaryRow.label );
_layoutHistograms->removeWidget( summaryRow.histogram );
delete summaryRow.label;
delete summaryRow.histogram;
delete summaryRow.checkBox;
_histogramWidgets.erase( _histogramWidgets.begin() + i );
_histogramRows.erase( _histogramRows.begin() + i );
updateHistogramWidgets();
}
void Summary::colorScaleLocal( int value )
{
if( value >= 0 && value < visimpl::T_COLOR_UNDEFINED )
{
colorScaleLocal( static_cast<visimpl::TColorScale>(value) );
}
}
void Summary::colorScaleGlobal( int value )
{
if( value >= 0 && value < visimpl::T_COLOR_UNDEFINED )
{
colorScaleGlobal( static_cast<visimpl::TColorScale>(value) );
}
}
void Summary::colorScaleLocal( visimpl::TColorScale colorScale )
{
_colorScaleLocal = colorScale;
auto setScaleLocal = [&colorScale](HistogramWidget *w)
{
w->colorScaleLocal( colorScale );
w->CalculateColors( visimpl::HistogramWidget::T_HIST_MAIN );
w->CalculateColors( visimpl::HistogramWidget::T_HIST_FOCUS );
w->update();
};
std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), setScaleLocal);
if(_focusedHistogram)
{
_focusWidget->viewRegion( *_focusedHistogram, _regionPercentage, _regionWidth );
}
_focusWidget->update();
}
visimpl::TColorScale Summary::colorScaleLocal( void )
{
return _colorScaleLocal;
}
void Summary::colorScaleGlobal( visimpl::TColorScale colorScale )
{
_colorScaleGlobal = colorScale;
auto setScaleGlobal = [&colorScale](HistogramWidget *w)
{
w->colorScaleGlobal( colorScale );
w->CalculateColors( visimpl::HistogramWidget::T_HIST_MAIN );
w->CalculateColors( visimpl::HistogramWidget::T_HIST_FOCUS );
w->update();
};
std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), setScaleGlobal);
if(_focusedHistogram)
{
_focusWidget->viewRegion( *_focusedHistogram, _regionPercentage, _regionWidth );
}
_focusWidget->update();
}
visimpl::TColorScale Summary::colorScaleGlobal( void )
{
return _colorScaleGlobal;
}
void Summary::regionWidth( float region )
{
_regionWidth = region;
}
float Summary::regionWidth( void )
{
return _regionWidth;
}
const GIDUSet& Summary::gids( void )
{
return _gids;
}
void Summary::gridLinesNumber( int linesNumber )
{
_gridLinesNumber = linesNumber;
auto updateGridLinesNumber = [&linesNumber](HistogramWidget *w)
{
w->gridLinesNumber( linesNumber );
w->update();
};
std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), updateGridLinesNumber);
}
unsigned int Summary::gridLinesNumber( void )
{
return _gridLinesNumber;
}
void Summary::simulationPlayer( simil::SimulationPlayer* player )
{
_player = player;
auto assignPlayer = [&player](HistogramWidget *w)
{
w->simPlayer(player);
};
std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), assignPlayer);
}
void Summary::repaintHistograms( void )
{
auto updateHistograms = [](HistogramWidget *w)
{
w->update();
};
std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), updateHistograms);
}
void Summary::_resizeCharts( unsigned int newMinSize, Qt::Orientation orientation )
{
auto resizeHistogramRow = [&newMinSize, &orientation](visimpl::Summary::HistogramRow &h)
{
if( orientation == Qt::Horizontal )
h.histogram->setMinimumWidth( newMinSize );
else
{
h.histogram->setMinimumHeight( newMinSize );
h.histogram->setMaximumHeight( newMinSize );
h.label->setMinimumHeight( newMinSize );
h.label->setMaximumHeight( newMinSize );
}
};
std::for_each(_histogramRows.begin(), _histogramRows.end(), resizeHistogramRow);
if(orientation != Qt::Horizontal)
_scrollHistogram->setMinimumHeight( newMinSize );
}
void Summary::_resizeEvents( unsigned int newMinSize )
{
auto updateEventWidth = [&newMinSize](EventWidget *w)
{
w->setMinimumWidth(newMinSize);
};
std::for_each(_eventWidgets.begin(), _eventWidgets.end(), updateEventWidth);
}
void Summary::_updateEventRepSizes( unsigned int newSize )
{
auto updateEventSize = [&newSize](EventWidget *w)
{
w->updateCommonRepSizeVert(newSize);
};
std::for_each(_eventWidgets.begin(), _eventWidgets.end(), updateEventSize);
}
void Summary::_updateScaleHorizontal( void )
{
_scaleCurrentHorizontal = std::max( 1.0, _spinBoxScaleHorizontal->value());
unsigned int rightMarginFactor = 1;
if( _scaleCurrentHorizontal == 1.0 )
rightMarginFactor = 2;
const unsigned int viewSize = _scrollHistogram->width();
_sizeView = viewSize - _sizeMargin * rightMarginFactor;
_sizeChartHorizontal = ( _scaleCurrentHorizontal * _sizeView );
_resizeCharts( _sizeChartHorizontal, Qt::Horizontal );
_resizeEvents( _sizeChartHorizontal );
}
void Summary::_updateScaleVertical( void )
{
_scaleCurrentVertical = std::max( 1.0, _spinBoxScaleVertical->value());
_sizeChartVertical = _sizeChartVerticalDefault * _scaleCurrentVertical;
_updateEventRepSizes( _sizeChartVertical );
_resizeCharts( _sizeChartVertical, Qt::Vertical );
}
void Summary::showEvent(QShowEvent *e)
{
QWidget::showEvent(e);
int maxWidth = -1;
for(auto &c: _footToolBox->children())
{
auto w = qobject_cast<QWidget *>(c);
if(w)
{
maxWidth = std::max(maxWidth, w->sizeHint().width());
}
}
if(maxWidth != -1) _footToolBox->setMinimumWidth(maxWidth);
}
void Summary::resizeEvent( QResizeEvent* event_ )
{
QWidget::resizeEvent( event_ );
if( ( _stackType != T_STACK_EXPANDABLE) || !_layoutMain || !_scrollHistogram )
return;
_layoutMain->activate();
_layoutHistograms->activate();
const unsigned int splitterRightSide = _scrollHistogram->width();
_sizeChartHorizontal = _mainHistogram->size().width();
if( _flagUpdateChartSize && _mainHistogram->size().width() > 0)
{
_sizeMargin = ( splitterRightSide - _sizeChartHorizontal ) / 2;
_flagUpdateChartSize = false;
}
const auto rightMarginFactor = splitterRightSide > _sizeChartHorizontal ? 2 : 1;
_sizeView = splitterRightSide - _sizeMargin * rightMarginFactor;
_scaleCurrentHorizontal = static_cast<float>(_sizeChartHorizontal) / _sizeView;
_spinBoxScaleHorizontal->setValue( _scaleCurrentHorizontal );
}
void Summary::wheelEvent( QWheelEvent* event_ )
{
constexpr float minScale = 1.0f;
const bool sign = ( event_->angleDelta().y() > 0 );
const float adjustment = ( _scaleStep * ( sign ? 1 : ( -1 )));
if( event_->modifiers().testFlag( Qt::ControlModifier ))
{
if( _scaleCurrentHorizontal == minScale )
_sizeView = _mainHistogram->size().width() - _sizeMargin * 2;
_scaleCurrentHorizontal = std::max( minScale, _scaleCurrentHorizontal + adjustment );
_sizeChartHorizontal = ( _scaleCurrentHorizontal * _sizeView );
_resizeCharts( _sizeChartHorizontal, Qt::Horizontal );
_resizeEvents( _sizeChartHorizontal );
_spinBoxScaleHorizontal->setValue( _scaleCurrentHorizontal );
}
else if( event_->modifiers().testFlag( Qt::ShiftModifier ))
{
_scaleCurrentVertical =
std::max( minScale, _scaleCurrentVertical + adjustment );
_sizeChartVertical = ( _scaleCurrentVertical * _sizeChartVerticalDefault);
_resizeCharts( _sizeChartVertical, Qt::Vertical );
_spinBoxScaleVertical->setValue( _scaleCurrentVertical );
}
else
{
if(_scrollHistogram)
{
const auto pos = _scrollHistogram->horizontalScrollBar()->value() + (10 * adjustment);
_scrollHistoLabels->horizontalScrollBar()->setValue( pos );
_scrollHistogram->horizontalScrollBar()->setValue( pos );
}
if(_scrollEvent)
{
const auto pos = _scrollEvent->horizontalScrollBar()->value() + (10 * adjustment);
_eventLabelsScroll->horizontalScrollBar()->setValue( pos );
_scrollEvent->horizontalScrollBar()->setValue( pos );
}
}
updateRegionBounds();
event_->ignore();
}
void Summary::moveHoriScrollSync( int /*action*/ )
{
const auto sbar = qobject_cast<QScrollBar *>(sender());
if(!sbar) return;
if( sbar && _syncScrollsHorizontally &&
(sbar == _scrollEvent->horizontalScrollBar() ||
sbar == _scrollHistogram->horizontalScrollBar()))
{
int newPos = sbar->sliderPosition();
_scrollEvent->horizontalScrollBar()->setValue( newPos );
_scrollHistogram->horizontalScrollBar()->setValue( newPos );
}
}
void Summary::syncSplitters()
{
if( sender() == _splitHorizEvents )
_splitHorizHisto->setSizes( _splitHorizEvents->sizes());
else
_splitHorizEvents->setSizes( _splitHorizHisto->sizes());
unsigned int splitterRightSide = _scrollHistogram->size().width();
unsigned int rightMarginFactor = splitterRightSide > _sizeChartHorizontal ? 2 : 1;
_sizeView = splitterRightSide - ( _sizeMargin * rightMarginFactor );
_sizeChartHorizontal =
_mainHistogram ? _mainHistogram->size().width() : _sizeView * _scaleCurrentHorizontal;
_scaleCurrentHorizontal = static_cast<float> (_sizeChartHorizontal) / _sizeView;
}
void Summary::adjustSplittersSize()
{
int lhs = width() * 0.2;
int rhs = width() - lhs;
QList< int > sizes;
sizes << lhs << rhs;
_splitHorizEvents->setSizes( sizes );
_splitHorizHisto->setSizes( sizes );
}
void Summary::focusPlayback( void )
{
setFocusAt( _player->GetRelativeTime() );
}
void Summary::setFocusAt( float perc )
{
perc = std::max(0.f, std::min(perc, 1.f));
_regionPercentage = perc;
for(QScrollArea *w: {_scrollEvent, _scrollHistogram})
{
auto hs = w->horizontalScrollBar();
hs->setValue(hs->maximum()*perc);
hs->update();
}
if(!_histogramWidgets.empty())
{
if(!_focusedHistogram)
{
_focusedHistogram = _histogramWidgets.front();
}
updateRegionBounds();
_focusWidget->viewRegion( *_focusedHistogram, _regionPercentage, _regionWidth );
_focusWidget->update();
_focusedHistogram->regionWidth( _regionWidth );
_focusedHistogram->paintRegion(true);
_focusedHistogram->focusValueAt(perc);
_focusedHistogram->update();
auto setPaintRegion = [&](HistogramWidget *w)
{
if(w == _focusedHistogram)
{
w->regionWidth(_regionWidth);
w->focusValueAt(perc);
}
w->paintRegion(w == _focusedHistogram);
w->update();
};
std::for_each(_histogramWidgets.begin(), _histogramWidgets.end(), setPaintRegion);
}
}
void Summary::changeHistogramName(unsigned int idx, const QString &name)
{
if(idx < _histogramRows.size())
{
auto row = _histogramRows.at(idx);
row.label->setText(name);
row.histogram->name(name.toStdString());
}
updateLabelsWidth();
}
void Summary::changeHistogramVisibility(unsigned int idx, const bool state)
{
if(idx < _histogramRows.size())
{
auto row = _histogramRows.at(idx);
row.label->setVisible(state);
auto histogram = _histogramWidgets.at(idx);
histogram->setVisible(state);
}
}
void Summary::updateLabelsWidth()
{
int maxWidth = -1;
auto computeHistWidth = [&maxWidth](const HistogramRow &r)
{
maxWidth = std::max(maxWidth, r.label->sizeHint().width());
};
std::for_each(_histogramRows.cbegin(), _histogramRows.cend(), computeHistWidth);
auto computeEventWidth = [&maxWidth](const EventRow &r)
{
maxWidth = std::max(maxWidth, r.label->sizeHint().width());
};
std::for_each(_eventRows.cbegin(), _eventRows.cend(), computeEventWidth);
if(maxWidth != -1)
{
// + 2*layout margin
_scrollHistoLabels->setMinimumWidth(maxWidth + 4);
_eventLabelsScroll->setMinimumWidth(maxWidth + 4);
}
}
}