2016-06-26 22:34:51 +03:00
/************************************************************************
* file name : blocks_tree_widget . cpp
* - - - - - - - - - - - - - - - - - :
* creation time : 2016 / 06 / 26
* author : Victor Zarubkin
* email : v . s . zarubkin @ gmail . com
* - - - - - - - - - - - - - - - - - :
2016-08-18 23:26:41 +03:00
* description : The file contains implementation of EasyTreeWidget and it ' s auxiliary classes
2016-06-26 22:34:51 +03:00
* : for displyaing easy_profiler blocks tree .
* - - - - - - - - - - - - - - - - - :
2016-06-27 22:11:26 +03:00
* change log : * 2016 / 06 / 26 Victor Zarubkin : Moved sources from tree_view . h
2016-06-26 22:34:51 +03:00
* : and renamed classes from My * to Prof * .
2016-06-30 02:57:57 +03:00
* :
2016-06-27 22:11:26 +03:00
* : * 2016 / 06 / 27 Victor Zarubkin : Added possibility to colorize rows
* : with profiler blocks ' colors .
* : Also added displaying frame statistics for blocks .
2016-06-27 23:24:04 +03:00
* : Disabled sorting by name to save order of threads displayed on graphics view .
2016-06-30 02:57:57 +03:00
* :
* : * 2016 / 06 / 29 Victor Zarubkin : Added clearSilent ( ) method .
* :
2016-08-18 23:26:41 +03:00
* : * 2016 / 08 / 18 Victor Zarubkin : Moved sources of TreeWidgetItem into tree_widget_item . h / . cpp
2016-06-26 22:34:51 +03:00
* - - - - - - - - - - - - - - - - - :
2016-09-06 21:49:32 +03:00
* license : Lightweight profiler library for c + +
* : Copyright ( C ) 2016 Sergey Yagovtsev , Victor Zarubkin
* :
* : This program is free software : you can redistribute it and / or modify
* : it under the terms of the GNU General Public License as published by
* : the Free Software Foundation , either version 3 of the License , or
* : ( at your option ) any later version .
* :
* : This program 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 General Public License for more details .
* :
* : You should have received a copy of the GNU General Public License
* : along with this program . If not , see < http : //www.gnu.org/licenses/>.
2016-06-26 18:56:40 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-06-26 18:46:51 +03:00
# include <QMenu>
2016-09-14 23:14:24 +03:00
# include <QHeaderView>
2016-06-26 18:46:51 +03:00
# include <QContextMenuEvent>
2016-06-27 22:11:26 +03:00
# include <QSignalBlocker>
2016-08-04 23:12:41 +03:00
# include <QSettings>
2016-08-18 23:26:41 +03:00
# include <QProgressDialog>
# include <QResizeEvent>
# include <QMoveEvent>
2016-08-28 21:10:16 +03:00
# include <QDebug>
2016-06-26 18:46:51 +03:00
# include "blocks_tree_widget.h"
2016-08-18 23:26:41 +03:00
# include "tree_widget_item.h"
2016-08-08 22:45:57 +03:00
# include "globals.h"
2016-06-26 18:46:51 +03:00
2016-09-17 15:39:31 +03:00
# ifdef _WIN32
# include <Windows.h>
# endif
# ifdef max
# undef max
# endif
# ifdef min
# undef min
2016-08-14 16:05:10 +03:00
# endif
2016-06-26 18:46:51 +03:00
//////////////////////////////////////////////////////////////////////////
2016-08-21 22:44:03 +03:00
const int HIERARCHY_BUILDER_TIMER_INTERVAL = 40 ;
//////////////////////////////////////////////////////////////////////////
EasyTreeWidget : : EasyTreeWidget ( QWidget * _parent )
: Parent ( _parent )
, m_beginTime ( : : std : : numeric_limits < decltype ( m_beginTime ) > : : max ( ) )
, m_progress ( nullptr )
, m_bColorRows ( true )
, m_bLocked ( false )
, m_bSilentExpandCollapse ( false )
2016-06-26 18:46:51 +03:00
{
2016-06-27 22:11:26 +03:00
setAutoFillBackground ( false ) ;
2016-06-26 18:46:51 +03:00
setAlternatingRowColors ( true ) ;
setItemsExpandable ( true ) ;
setAnimated ( true ) ;
setSortingEnabled ( false ) ;
2016-06-27 22:11:26 +03:00
setColumnCount ( COL_COLUMNS_NUMBER ) ;
2016-06-26 18:46:51 +03:00
2016-09-14 23:14:24 +03:00
auto header_item = new QTreeWidgetItem ( ) ;
auto f = header ( ) - > font ( ) ;
f . setBold ( true ) ;
header ( ) - > setFont ( f ) ; // ::profiler_gui::EFont("Helvetica", 9, QFont::Bold));
header_item - > setText ( COL_NAME , " Name " ) ;
header_item - > setText ( COL_BEGIN , " Begin, ms " ) ;
header_item - > setText ( COL_DURATION , " Duration " ) ;
header_item - > setText ( COL_SELF_DURATION , " Self Dur. " ) ;
//header_item->setToolTip(COL_SELF_DURATION, "");
header_item - > setText ( COL_DURATION_SUM_PER_PARENT , " Tot. Dur./Parent " ) ;
header_item - > setText ( COL_DURATION_SUM_PER_FRAME , " Tot. Dur./Frame " ) ;
header_item - > setText ( COL_DURATION_SUM_PER_THREAD , " Tot. Dur./Thread " ) ;
header_item - > setText ( COL_SELF_DURATION_PERCENT , " Self % " ) ;
header_item - > setText ( COL_PERCENT_PER_PARENT , " % / Parent " ) ;
header_item - > setText ( COL_PERCENT_PER_FRAME , " % / Frame " ) ;
header_item - > setText ( COL_PERCENT_SUM_PER_FRAME , " Tot. % / Frame " ) ;
header_item - > setText ( COL_PERCENT_SUM_PER_PARENT , " Tot. % / Parent " ) ;
header_item - > setText ( COL_PERCENT_SUM_PER_THREAD , " Tot. % / Thread " ) ;
header_item - > setText ( COL_END , " End, ms " ) ;
header_item - > setText ( COL_MIN_PER_FRAME , " Min dur./Frame " ) ;
header_item - > setText ( COL_MAX_PER_FRAME , " Max dur./Frame " ) ;
header_item - > setText ( COL_AVERAGE_PER_FRAME , " Average dur./Frame " ) ;
header_item - > setText ( COL_NCALLS_PER_FRAME , " N Calls/Frame " ) ;
header_item - > setText ( COL_MIN_PER_PARENT , " Min dur./Parent " ) ;
header_item - > setText ( COL_MAX_PER_PARENT , " Max dur./Parent " ) ;
header_item - > setText ( COL_AVERAGE_PER_PARENT , " Average dur./Parent " ) ;
header_item - > setText ( COL_NCALLS_PER_PARENT , " N Calls/Parent " ) ;
header_item - > setText ( COL_MIN_PER_THREAD , " Min dur./Thread " ) ;
header_item - > setText ( COL_MAX_PER_THREAD , " Max dur./Thread " ) ;
header_item - > setText ( COL_AVERAGE_PER_THREAD , " Average dur./Thread " ) ;
header_item - > setText ( COL_NCALLS_PER_THREAD , " N Calls/Thread " ) ;
auto color = QColor : : fromRgb ( : : profiler : : colors : : DeepOrange900 ) ;
header_item - > setForeground ( COL_MIN_PER_THREAD , color ) ;
header_item - > setForeground ( COL_MAX_PER_THREAD , color ) ;
header_item - > setForeground ( COL_AVERAGE_PER_THREAD , color ) ;
header_item - > setForeground ( COL_NCALLS_PER_THREAD , color ) ;
header_item - > setForeground ( COL_PERCENT_SUM_PER_THREAD , color ) ;
header_item - > setForeground ( COL_DURATION_SUM_PER_THREAD , color ) ;
color = QColor : : fromRgb ( : : profiler : : colors : : Blue900 ) ;
header_item - > setForeground ( COL_MIN_PER_FRAME , color ) ;
header_item - > setForeground ( COL_MAX_PER_FRAME , color ) ;
header_item - > setForeground ( COL_AVERAGE_PER_FRAME , color ) ;
header_item - > setForeground ( COL_NCALLS_PER_FRAME , color ) ;
header_item - > setForeground ( COL_PERCENT_SUM_PER_FRAME , color ) ;
header_item - > setForeground ( COL_DURATION_SUM_PER_FRAME , color ) ;
header_item - > setForeground ( COL_PERCENT_PER_FRAME , color ) ;
color = QColor : : fromRgb ( : : profiler : : colors : : Teal900 ) ;
header_item - > setForeground ( COL_MIN_PER_PARENT , color ) ;
header_item - > setForeground ( COL_MAX_PER_PARENT , color ) ;
header_item - > setForeground ( COL_AVERAGE_PER_PARENT , color ) ;
header_item - > setForeground ( COL_NCALLS_PER_PARENT , color ) ;
header_item - > setForeground ( COL_PERCENT_SUM_PER_PARENT , color ) ;
header_item - > setForeground ( COL_DURATION_SUM_PER_PARENT , color ) ;
header_item - > setForeground ( COL_PERCENT_PER_PARENT , color ) ;
setHeaderItem ( header_item ) ;
2016-08-04 23:12:41 +03:00
2016-08-30 22:51:18 +03:00
connect ( & EASY_GLOBALS . events , & : : profiler_gui : : EasyGlobalSignals : : selectedThreadChanged , this , & This : : onSelectedThreadChange ) ;
connect ( & EASY_GLOBALS . events , & : : profiler_gui : : EasyGlobalSignals : : selectedBlockChanged , this , & This : : onSelectedBlockChange ) ;
2016-08-18 23:26:41 +03:00
connect ( & m_fillTimer , & QTimer : : timeout , this , & This : : onFillTimerTimeout ) ;
2016-08-07 19:38:31 +03:00
loadSettings ( ) ;
2016-08-18 23:26:41 +03:00
m_progress = new QProgressDialog ( " Building blocks hierarchy... " , " " , 0 , 100 , this , Qt : : FramelessWindowHint ) ;
m_progress - > setAttribute ( Qt : : WA_TranslucentBackground ) ;
m_progress - > setCancelButton ( nullptr ) ;
2016-08-21 22:44:03 +03:00
m_progress - > setValue ( 100 ) ;
//m_progress->hide();
2016-08-18 23:26:41 +03:00
2016-08-28 21:10:16 +03:00
QTimer : : singleShot ( 1500 , this , & This : : alignProgressBar ) ;
2016-06-26 20:54:16 +03:00
}
2016-06-26 18:46:51 +03:00
2016-08-18 23:26:41 +03:00
EasyTreeWidget : : ~ EasyTreeWidget ( )
2016-06-26 20:54:16 +03:00
{
2016-09-06 22:23:55 +03:00
saveSettings ( ) ;
2016-08-18 23:26:41 +03:00
delete m_progress ;
2016-06-26 20:54:16 +03:00
}
2016-08-21 22:44:03 +03:00
//////////////////////////////////////////////////////////////////////////
2016-07-31 18:48:41 +03:00
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : onFillTimerTimeout ( )
2016-06-26 18:46:51 +03:00
{
2016-08-18 23:26:41 +03:00
if ( m_hierarchyBuilder . done ( ) )
{
m_fillTimer . stop ( ) ;
ThreadedItems toplevelitems ;
m_hierarchyBuilder . takeItems ( m_items ) ;
m_hierarchyBuilder . takeTopLevelItems ( toplevelitems ) ;
m_hierarchyBuilder . interrupt ( ) ;
{
const QSignalBlocker b ( this ) ;
for ( auto & item : toplevelitems )
{
addTopLevelItem ( item . second ) ;
m_roots [ item . first ] = item . second ;
}
}
if ( m_progress )
{
m_progress - > setValue ( 100 ) ;
2016-08-21 22:44:03 +03:00
//m_progress->hide();
2016-08-18 23:26:41 +03:00
}
m_bLocked = false ;
m_inputBlocks . clear ( ) ;
setSortingEnabled ( true ) ;
sortByColumn ( COL_BEGIN , Qt : : AscendingOrder ) ;
2016-08-21 22:44:03 +03:00
//resizeColumnToContents(COL_NAME);
resizeColumnsToContents ( ) ;
2016-08-18 23:26:41 +03:00
connect ( this , & Parent : : itemExpanded , this , & This : : onItemExpand ) ;
connect ( this , & Parent : : itemCollapsed , this , & This : : onItemCollapse ) ;
2016-08-23 23:50:30 +03:00
connect ( this , & Parent : : currentItemChanged , this , & This : : onCurrentItemChange ) ;
2016-08-30 22:51:18 +03:00
onSelectedThreadChange ( EASY_GLOBALS . selected_thread ) ;
onSelectedBlockChange ( EASY_GLOBALS . selected_block ) ;
2016-08-18 23:26:41 +03:00
}
else
{
m_progress - > setValue ( m_hierarchyBuilder . progress ( ) ) ;
}
}
2016-06-26 18:46:51 +03:00
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : setTree ( const unsigned int _blocksNumber , const : : profiler : : thread_blocks_tree_t & _blocksTree )
{
clearSilent ( ) ;
2016-06-26 18:46:51 +03:00
2016-08-18 23:26:41 +03:00
if ( ! _blocksTree . empty ( ) )
{
m_bLocked = true ;
m_progress - > setValue ( 0 ) ;
2016-08-23 22:44:04 +03:00
m_progress - > show ( ) ;
2016-08-18 23:26:41 +03:00
m_hierarchyBuilder . fillTree ( m_beginTime , _blocksNumber , _blocksTree , m_bColorRows ) ;
2016-08-21 22:44:03 +03:00
m_fillTimer . start ( HIERARCHY_BUILDER_TIMER_INTERVAL ) ;
2016-08-18 23:26:41 +03:00
}
2016-06-26 18:46:51 +03:00
2016-08-18 23:26:41 +03:00
//StubLocker l;
//ThreadedItems toplevelitems;
//FillTreeClass<StubLocker>::setTreeInternal1(l, m_items, toplevelitems, m_beginTime, _blocksNumber, _blocksTree, m_bColorRows);
//{
// const QSignalBlocker b(this);
// for (auto& item : toplevelitems)
// {
// addTopLevelItem(item.second);
// m_roots[item.first] = item.second;
2016-08-30 22:51:18 +03:00
// if (item.first == EASY_GLOBALS.selected_thread)
2016-08-18 23:26:41 +03:00
// item.second->colorize(true);
// }
//}
2016-06-26 18:46:51 +03:00
}
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : setTreeBlocks ( const : : profiler_gui : : TreeBlocks & _blocks , : : profiler : : timestamp_t _session_begin_time , : : profiler : : timestamp_t _left , : : profiler : : timestamp_t _right , bool _strict )
2016-07-31 18:48:41 +03:00
{
clearSilent ( ) ;
2016-08-01 22:21:59 +03:00
m_beginTime = _session_begin_time ;
_left + = m_beginTime ; // - ::std::min(m_beginTime, 1000ULL);
_right + = m_beginTime ; // + 1000;
2016-08-14 16:05:10 +03:00
2016-08-18 23:26:41 +03:00
m_inputBlocks = _blocks ;
if ( ! m_inputBlocks . empty ( ) )
{
m_bLocked = true ;
m_progress - > setValue ( 0 ) ;
2016-08-23 22:44:04 +03:00
m_progress - > show ( ) ;
2016-08-18 23:26:41 +03:00
m_hierarchyBuilder . fillTreeBlocks ( m_inputBlocks , _session_begin_time , _left , _right , _strict , m_bColorRows ) ;
2016-08-21 22:44:03 +03:00
m_fillTimer . start ( HIERARCHY_BUILDER_TIMER_INTERVAL ) ;
2016-08-18 23:26:41 +03:00
}
2016-07-31 18:48:41 +03:00
2016-08-18 23:26:41 +03:00
//StubLocker l;
//ThreadedItems toplevelitems;
//FillTreeClass<StubLocker>::setTreeInternal2(l, m_items, toplevelitems, m_beginTime, _blocks, _left, _right, _strict, m_bColorRows);
//{
// const QSignalBlocker b(this);
// for (auto& item : toplevelitems)
// {
// addTopLevelItem(item.second);
// m_roots[item.first] = item.second;
2016-08-30 22:51:18 +03:00
// if (item.first == EASY_GLOBALS.selected_thread)
2016-08-18 23:26:41 +03:00
// item.second->colorize(true);
// }
//}
//setSortingEnabled(true);
//sortByColumn(COL_BEGIN, Qt::AscendingOrder);
//resizeColumnToContents(COL_NAME);
2016-07-31 18:48:41 +03:00
2016-08-18 23:26:41 +03:00
//connect(this, &Parent::itemExpanded, this, &This::onItemExpand);
//connect(this, &Parent::itemCollapsed, this, &This::onItemCollapse);
2016-08-30 22:51:18 +03:00
//onSelectedBlockChange(EASY_GLOBALS.selected_block);
2016-07-31 18:48:41 +03:00
}
2016-08-21 22:44:03 +03:00
//////////////////////////////////////////////////////////////////////////
2016-07-31 18:48:41 +03:00
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : clearSilent ( bool _global )
2016-06-30 02:57:57 +03:00
{
2016-08-28 21:10:16 +03:00
const QSignalBlocker b ( this ) ;
2016-08-18 23:26:41 +03:00
m_hierarchyBuilder . interrupt ( ) ;
if ( m_progress )
{
m_progress - > setValue ( 100 ) ;
2016-08-21 22:44:03 +03:00
//m_progress->hide();
2016-08-18 23:26:41 +03:00
}
m_bLocked = false ;
2016-08-11 23:43:34 +03:00
m_beginTime = : : std : : numeric_limits < decltype ( m_beginTime ) > : : max ( ) ;
2016-06-30 02:57:57 +03:00
setSortingEnabled ( false ) ;
disconnect ( this , & Parent : : itemExpanded , this , & This : : onItemExpand ) ;
2016-08-18 23:26:41 +03:00
disconnect ( this , & Parent : : itemCollapsed , this , & This : : onItemCollapse ) ;
2016-08-23 23:50:30 +03:00
disconnect ( this , & Parent : : currentItemChanged , this , & This : : onCurrentItemChange ) ;
2016-06-30 02:57:57 +03:00
2016-08-04 22:38:45 +03:00
if ( ! _global )
{
2016-08-30 22:51:18 +03:00
if ( EASY_GLOBALS . collapse_items_on_tree_close ) for ( auto item : m_items )
2016-08-04 22:38:45 +03:00
{
2016-08-30 22:51:18 +03:00
auto & gui_block = item - > guiBlock ( ) ;
2016-08-18 23:26:41 +03:00
: : profiler_gui : : set_max ( gui_block . tree_item ) ;
gui_block . expanded = false ;
2016-08-04 22:38:45 +03:00
}
2016-08-23 22:44:04 +03:00
else for ( auto item : m_items )
{
2016-08-30 22:51:18 +03:00
: : profiler_gui : : set_max ( item - > guiBlock ( ) . tree_item ) ;
2016-08-23 22:44:04 +03:00
}
2016-08-04 22:38:45 +03:00
}
2016-06-30 02:57:57 +03:00
m_items . clear ( ) ;
2016-08-07 19:38:31 +03:00
m_roots . clear ( ) ;
2016-06-30 02:57:57 +03:00
2016-08-28 21:10:16 +03:00
: : std : : vector < QTreeWidgetItem * > topLevelItems ;
topLevelItems . reserve ( topLevelItemCount ( ) ) ;
for ( int i = topLevelItemCount ( ) - 1 ; i > = 0 ; - - i )
topLevelItems . push_back ( takeTopLevelItem ( i ) ) ;
2016-09-06 22:23:55 +03:00
auto deleter_thread = : : std : : thread ( [ ] ( decltype ( topLevelItems ) _items ) {
for ( auto item : _items )
delete item ;
} , : : std : : move ( topLevelItems ) ) ;
2016-09-17 15:39:31 +03:00
# ifdef _WIN32
SetThreadPriority ( deleter_thread . native_handle ( ) , THREAD_PRIORITY_LOWEST ) ;
# endif
2016-08-28 21:10:16 +03:00
deleter_thread . detach ( ) ;
//clear();
2016-06-26 18:46:51 +03:00
2016-08-18 23:26:41 +03:00
if ( ! _global )
2016-08-30 22:51:18 +03:00
emit EASY_GLOBALS . events . itemsExpandStateChanged ( ) ;
2016-08-14 16:05:10 +03:00
}
2016-08-18 23:26:41 +03:00
//////////////////////////////////////////////////////////////////////////
2016-06-26 18:46:51 +03:00
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : contextMenuEvent ( QContextMenuEvent * _event )
2016-06-26 18:46:51 +03:00
{
2016-08-18 23:26:41 +03:00
if ( m_bLocked )
2016-06-26 18:46:51 +03:00
{
2016-08-18 23:26:41 +03:00
_event - > accept ( ) ;
return ;
2016-06-26 18:46:51 +03:00
}
2016-08-01 22:21:59 +03:00
2016-06-26 18:46:51 +03:00
const auto col = currentColumn ( ) ;
2016-08-18 23:26:41 +03:00
auto item = static_cast < EasyTreeWidgetItem * > ( currentItem ( ) ) ;
2016-06-26 18:46:51 +03:00
QMenu menu ;
2016-08-23 23:50:30 +03:00
QAction * action = nullptr ;
2016-06-26 18:46:51 +03:00
2016-08-23 23:50:30 +03:00
if ( ! m_items . empty ( ) )
{
action = menu . addAction ( " Expand all " ) ;
connect ( action , & QAction : : triggered , this , & This : : onExpandAllClicked ) ;
2016-09-15 23:56:20 +03:00
SET_ICON ( action , " :/Expand " ) ;
2016-06-26 18:46:51 +03:00
2016-08-23 23:50:30 +03:00
action = menu . addAction ( " Collapse all " ) ;
connect ( action , & QAction : : triggered , this , & This : : onCollapseAllClicked ) ;
2016-09-16 00:18:51 +03:00
SET_ICON ( action , " :/Collapse " ) ;
2016-06-27 22:11:26 +03:00
2016-08-23 23:50:30 +03:00
if ( item ! = nullptr & & col > = 0 )
{
menu . addSeparator ( ) ;
2016-06-27 22:11:26 +03:00
2016-08-23 23:50:30 +03:00
action = menu . addAction ( " Expand all children " ) ;
connect ( action , & QAction : : triggered , this , & This : : onExpandAllChildrenClicked ) ;
2016-09-15 23:56:20 +03:00
SET_ICON ( action , " :/Expand " ) ;
2016-07-31 18:48:41 +03:00
2016-08-23 23:50:30 +03:00
action = menu . addAction ( " Collapse all children " ) ;
connect ( action , & QAction : : triggered , this , & This : : onCollapseAllChildrenClicked ) ;
2016-09-15 23:56:20 +03:00
SET_ICON ( action , " :/Collapse " ) ;
2016-08-23 23:50:30 +03:00
}
2016-07-31 18:48:41 +03:00
2016-08-23 23:50:30 +03:00
menu . addSeparator ( ) ;
}
2016-07-31 18:48:41 +03:00
2016-08-23 23:50:30 +03:00
action = menu . addAction ( " Color rows " ) ;
2016-06-27 22:11:26 +03:00
action - > setCheckable ( true ) ;
action - > setChecked ( m_bColorRows ) ;
connect ( action , & QAction : : triggered , this , & This : : onColorizeRowsTriggered ) ;
2016-09-14 23:14:24 +03:00
if ( m_bColorRows ) {
auto f = action - > font ( ) ;
f . setBold ( true ) ;
action - > setFont ( f ) ;
2016-09-15 23:56:20 +03:00
SET_ICON ( action , " :/Color " ) ;
2016-09-14 23:14:24 +03:00
}
2016-09-15 23:56:20 +03:00
else SET_ICON ( action , " :/NoColor " ) ;
2016-06-26 18:46:51 +03:00
2016-08-30 22:51:18 +03:00
if ( item ! = nullptr & & item - > parent ( ) ! = nullptr )
2016-06-26 18:46:51 +03:00
{
2016-08-08 22:17:56 +03:00
if ( col > = 0 )
{
switch ( col )
2016-08-01 22:21:59 +03:00
{
2016-08-08 22:17:56 +03:00
case COL_MIN_PER_THREAD :
case COL_MIN_PER_PARENT :
case COL_MIN_PER_FRAME :
case COL_MAX_PER_THREAD :
case COL_MAX_PER_PARENT :
case COL_MAX_PER_FRAME :
{
2016-08-30 22:51:18 +03:00
auto & block = item - > block ( ) ;
2016-09-06 21:49:32 +03:00
auto i = : : profiler_gui : : numeric_max < uint32_t > ( ) ;
2016-08-08 22:17:56 +03:00
switch ( col )
{
2016-08-30 22:51:18 +03:00
case COL_MIN_PER_THREAD : i = block . per_thread_stats - > min_duration_block ; break ;
case COL_MIN_PER_PARENT : i = block . per_parent_stats - > min_duration_block ; break ;
case COL_MIN_PER_FRAME : i = block . per_frame_stats - > min_duration_block ; break ;
case COL_MAX_PER_THREAD : i = block . per_thread_stats - > max_duration_block ; break ;
case COL_MAX_PER_PARENT : i = block . per_parent_stats - > max_duration_block ; break ;
case COL_MAX_PER_FRAME : i = block . per_frame_stats - > max_duration_block ; break ;
2016-08-08 22:17:56 +03:00
}
2016-08-11 23:43:34 +03:00
if ( i ! = : : profiler_gui : : numeric_max ( i ) )
2016-08-08 22:17:56 +03:00
{
menu . addSeparator ( ) ;
2016-09-06 21:49:32 +03:00
auto itemAction = new QAction ( " Jump to such item " , nullptr ) ;
itemAction - > setData ( i ) ;
2016-08-08 22:17:56 +03:00
itemAction - > setToolTip ( " Jump to item with min/max duration (depending on clicked column) " ) ;
2016-09-06 21:49:32 +03:00
connect ( itemAction , & QAction : : triggered , this , & This : : onJumpToItemClicked ) ;
2016-08-08 22:17:56 +03:00
menu . addAction ( itemAction ) ;
}
break ;
}
2016-08-01 22:21:59 +03:00
}
2016-06-26 18:46:51 +03:00
}
2016-09-17 15:39:31 +03:00
auto id = item - > block ( ) . node - > id ( ) ;
action = menu . addAction ( " Block enabled " ) ;
action - > setCheckable ( true ) ;
action - > setChecked ( easyDescriptor ( id ) . enabled ( ) ) ;
action - > setData ( id ) ;
connect ( action , & QAction : : triggered , this , & This : : onBlockEnableDisable ) ;
if ( action - > isChecked ( ) ) {
auto f = action - > font ( ) ;
f . setBold ( true ) ;
action - > setFont ( f ) ;
}
2016-06-26 18:46:51 +03:00
}
2016-08-03 23:00:04 +03:00
menu . addSeparator ( ) ;
auto hidemenu = menu . addMenu ( " Select columns " ) ;
auto hdr = headerItem ( ) ;
2016-08-04 23:12:41 +03:00
2016-09-06 22:23:55 +03:00
for ( int i = 0 ; i < COL_COLUMNS_NUMBER ; + + i )
2016-08-03 23:00:04 +03:00
{
2016-09-06 21:49:32 +03:00
auto columnAction = new QAction ( hdr - > text ( i ) , nullptr ) ;
columnAction - > setData ( i ) ;
2016-08-03 23:00:04 +03:00
columnAction - > setCheckable ( true ) ;
2016-09-06 22:23:55 +03:00
columnAction - > setChecked ( ! isColumnHidden ( i ) ) ;
2016-09-06 21:49:32 +03:00
connect ( columnAction , & QAction : : triggered , this , & This : : onHideShowColumn ) ;
2016-08-03 23:00:04 +03:00
hidemenu - > addAction ( columnAction ) ;
}
2016-06-26 18:46:51 +03:00
menu . exec ( QCursor : : pos ( ) ) ;
_event - > accept ( ) ;
}
2016-08-18 23:26:41 +03:00
//////////////////////////////////////////////////////////////////////////
void EasyTreeWidget : : resizeEvent ( QResizeEvent * _event )
{
Parent : : resizeEvent ( _event ) ;
alignProgressBar ( ) ;
}
2016-07-31 18:48:41 +03:00
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : moveEvent ( QMoveEvent * _event )
{
Parent : : moveEvent ( _event ) ;
alignProgressBar ( ) ;
}
void EasyTreeWidget : : alignProgressBar ( )
{
2016-09-06 22:23:55 +03:00
auto pos = mapToGlobal ( rect ( ) . center ( ) ) ;
2016-08-18 23:26:41 +03:00
m_progress - > move ( pos . x ( ) - ( m_progress - > width ( ) > > 1 ) , pos . y ( ) - ( m_progress - > height ( ) > > 1 ) ) ;
}
//////////////////////////////////////////////////////////////////////////
2016-09-06 21:49:32 +03:00
void EasyTreeWidget : : onJumpToItemClicked ( bool )
2016-06-26 18:46:51 +03:00
{
2016-09-06 21:49:32 +03:00
auto action = qobject_cast < QAction * > ( sender ( ) ) ;
if ( action = = nullptr )
return ;
auto block_index = action - > data ( ) . toUInt ( ) ;
EASY_GLOBALS . selected_block = block_index ;
emit EASY_GLOBALS . events . selectedBlockChanged ( block_index ) ;
2016-06-26 18:46:51 +03:00
}
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : onCollapseAllClicked ( bool )
2016-06-26 18:46:51 +03:00
{
2016-08-18 23:26:41 +03:00
const QSignalBlocker b ( this ) ;
2016-08-21 22:44:03 +03:00
m_bSilentExpandCollapse = true ;
2016-06-26 18:46:51 +03:00
collapseAll ( ) ;
2016-08-21 22:44:03 +03:00
m_bSilentExpandCollapse = false ;
2016-08-18 23:26:41 +03:00
2016-08-30 22:51:18 +03:00
if ( EASY_GLOBALS . bind_scene_and_tree_expand_status )
2016-08-23 23:50:30 +03:00
{
for ( auto item : m_items )
2016-08-30 22:51:18 +03:00
item - > guiBlock ( ) . expanded = false ;
emit EASY_GLOBALS . events . itemsExpandStateChanged ( ) ;
2016-08-23 23:50:30 +03:00
}
2016-06-26 18:46:51 +03:00
}
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : onExpandAllClicked ( bool )
2016-06-26 18:46:51 +03:00
{
2016-08-18 23:26:41 +03:00
const QSignalBlocker b ( this ) ;
2016-08-21 22:44:03 +03:00
m_bSilentExpandCollapse = true ;
2016-06-26 18:46:51 +03:00
expandAll ( ) ;
2016-08-03 23:00:04 +03:00
resizeColumnsToContents ( ) ;
2016-08-21 22:44:03 +03:00
m_bSilentExpandCollapse = false ;
2016-08-18 23:26:41 +03:00
2016-08-30 22:51:18 +03:00
if ( EASY_GLOBALS . bind_scene_and_tree_expand_status )
2016-08-23 23:50:30 +03:00
{
for ( auto item : m_items )
2016-08-30 22:51:18 +03:00
{
auto & b = item - > guiBlock ( ) ;
b . expanded = ! b . tree . children . empty ( ) ;
}
emit EASY_GLOBALS . events . itemsExpandStateChanged ( ) ;
2016-08-23 23:50:30 +03:00
}
2016-06-26 18:46:51 +03:00
}
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : onCollapseAllChildrenClicked ( bool )
2016-07-31 18:48:41 +03:00
{
2016-08-18 23:26:41 +03:00
auto current = static_cast < EasyTreeWidgetItem * > ( currentItem ( ) ) ;
2016-07-31 18:48:41 +03:00
if ( current ! = nullptr )
{
2016-08-18 23:26:41 +03:00
const QSignalBlocker b ( this ) ;
2016-08-21 22:44:03 +03:00
m_bSilentExpandCollapse = true ;
2016-07-31 18:48:41 +03:00
current - > collapseAll ( ) ;
2016-08-21 22:44:03 +03:00
m_bSilentExpandCollapse = false ;
2016-08-30 22:51:18 +03:00
emit EASY_GLOBALS . events . itemsExpandStateChanged ( ) ;
2016-07-31 18:48:41 +03:00
}
}
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : onExpandAllChildrenClicked ( bool )
2016-07-31 18:48:41 +03:00
{
2016-08-18 23:26:41 +03:00
auto current = static_cast < EasyTreeWidgetItem * > ( currentItem ( ) ) ;
2016-07-31 18:48:41 +03:00
if ( current ! = nullptr )
{
2016-08-18 23:26:41 +03:00
const QSignalBlocker b ( this ) ;
2016-08-21 22:44:03 +03:00
m_bSilentExpandCollapse = true ;
2016-07-31 18:48:41 +03:00
current - > expandAll ( ) ;
2016-08-03 23:00:04 +03:00
resizeColumnsToContents ( ) ;
2016-08-21 22:44:03 +03:00
m_bSilentExpandCollapse = false ;
2016-08-30 22:51:18 +03:00
emit EASY_GLOBALS . events . itemsExpandStateChanged ( ) ;
2016-07-31 18:48:41 +03:00
}
}
2016-08-23 23:50:30 +03:00
//////////////////////////////////////////////////////////////////////////
2016-09-17 15:39:31 +03:00
void EasyTreeWidget : : onBlockEnableDisable ( bool _checked )
{
auto action = qobject_cast < QAction * > ( sender ( ) ) ;
if ( action ! = nullptr )
{
auto id = action - > data ( ) . toUInt ( ) ;
easyDescriptor ( id ) . setEnabled ( _checked ) ;
emit EASY_GLOBALS . events . enableStatusChanged ( id , _checked ) ;
}
}
//////////////////////////////////////////////////////////////////////////
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : onItemExpand ( QTreeWidgetItem * _item )
2016-06-26 18:46:51 +03:00
{
2016-08-30 22:51:18 +03:00
if ( ! EASY_GLOBALS . bind_scene_and_tree_expand_status )
2016-08-23 23:50:30 +03:00
{
resizeColumnsToContents ( ) ;
return ;
}
2016-08-30 22:51:18 +03:00
static_cast < EasyTreeWidgetItem * > ( _item ) - > guiBlock ( ) . expanded = true ;
2016-08-21 22:44:03 +03:00
if ( ! m_bSilentExpandCollapse )
{
resizeColumnsToContents ( ) ;
2016-08-30 22:51:18 +03:00
emit EASY_GLOBALS . events . itemsExpandStateChanged ( ) ;
2016-08-21 22:44:03 +03:00
}
2016-06-27 22:11:26 +03:00
}
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : onItemCollapse ( QTreeWidgetItem * _item )
{
2016-08-30 22:51:18 +03:00
if ( ! EASY_GLOBALS . bind_scene_and_tree_expand_status )
2016-08-23 23:50:30 +03:00
return ;
2016-08-30 22:51:18 +03:00
static_cast < EasyTreeWidgetItem * > ( _item ) - > guiBlock ( ) . expanded = false ;
2016-08-21 22:44:03 +03:00
if ( ! m_bSilentExpandCollapse )
2016-08-30 22:51:18 +03:00
emit EASY_GLOBALS . events . itemsExpandStateChanged ( ) ;
2016-08-18 23:26:41 +03:00
}
2016-08-23 23:50:30 +03:00
//////////////////////////////////////////////////////////////////////////
void EasyTreeWidget : : onCurrentItemChange ( QTreeWidgetItem * _item , QTreeWidgetItem * )
{
if ( _item = = nullptr )
2016-08-30 22:51:18 +03:00
: : profiler_gui : : set_max ( EASY_GLOBALS . selected_block ) ;
2016-08-23 23:50:30 +03:00
else
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . selected_block = static_cast < EasyTreeWidgetItem * > ( _item ) - > block_index ( ) ;
2016-08-23 23:50:30 +03:00
2016-08-30 22:51:18 +03:00
disconnect ( & EASY_GLOBALS . events , & : : profiler_gui : : EasyGlobalSignals : : selectedBlockChanged , this , & This : : onSelectedBlockChange ) ;
emit EASY_GLOBALS . events . selectedBlockChanged ( EASY_GLOBALS . selected_block ) ;
connect ( & EASY_GLOBALS . events , & : : profiler_gui : : EasyGlobalSignals : : selectedBlockChanged , this , & This : : onSelectedBlockChange ) ;
2016-08-23 23:50:30 +03:00
}
//////////////////////////////////////////////////////////////////////////
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : onColorizeRowsTriggered ( bool _colorize )
2016-06-27 22:11:26 +03:00
{
const QSignalBlocker b ( this ) ;
m_bColorRows = _colorize ;
auto current = currentItem ( ) ;
collapseAll ( ) ; // Without collapseAll() changing items process is VERY VERY SLOW.
// TODO: Find the reason of such behavior. QSignalBlocker(this) does not help. QSignalBlocker(item) does not work, because items are not inherited from QObject.
for ( auto item : m_items )
{
2016-08-03 23:00:04 +03:00
if ( item - > parent ( ) ! = nullptr )
item - > colorize ( m_bColorRows ) ;
2016-06-27 22:11:26 +03:00
}
// Scroll back to previously selected item
if ( current )
{
scrollToItem ( current , QAbstractItemView : : PositionAtCenter ) ;
setCurrentItem ( current ) ;
}
2016-06-26 18:46:51 +03:00
}
//////////////////////////////////////////////////////////////////////////
2016-08-03 23:00:04 +03:00
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : onSelectedThreadChange ( : : profiler : : thread_id_t _id )
2016-08-03 23:00:04 +03:00
{
for ( auto & it : m_roots )
{
it . second - > colorize ( it . first = = _id ) ;
}
}
2016-09-17 15:39:31 +03:00
void EasyTreeWidget : : onSelectedBlockChange ( uint32_t _block_index )
2016-08-08 22:17:56 +03:00
{
2016-08-23 23:50:30 +03:00
disconnect ( this , & Parent : : currentItemChanged , this , & This : : onCurrentItemChange ) ;
2016-08-18 23:26:41 +03:00
EasyTreeWidgetItem * item = nullptr ;
2016-08-11 23:43:34 +03:00
2016-08-30 22:51:18 +03:00
if ( _block_index < EASY_GLOBALS . gui_blocks . size ( ) )
2016-08-08 22:17:56 +03:00
{
2016-08-30 22:51:18 +03:00
const auto i = easyBlock ( _block_index ) . tree_item ;
2016-08-11 23:43:34 +03:00
if ( i < m_items . size ( ) )
item = m_items [ i ] ;
2016-08-08 22:17:56 +03:00
}
2016-08-11 23:43:34 +03:00
if ( item ! = nullptr )
2016-08-18 23:26:41 +03:00
{
2016-08-21 22:44:03 +03:00
//const QSignalBlocker b(this);
2016-08-30 22:51:18 +03:00
if ( EASY_GLOBALS . bind_scene_and_tree_expand_status )
2016-08-23 23:50:30 +03:00
{
m_bSilentExpandCollapse = true ;
setCurrentItem ( item ) ;
scrollToItem ( item , QAbstractItemView : : PositionAtCenter ) ;
2016-08-30 22:51:18 +03:00
if ( item - > guiBlock ( ) . expanded )
2016-08-23 23:50:30 +03:00
expandItem ( item ) ;
else
collapseItem ( item ) ;
resizeColumnsToContents ( ) ;
m_bSilentExpandCollapse = false ;
2016-08-30 22:51:18 +03:00
emit EASY_GLOBALS . events . itemsExpandStateChanged ( ) ;
2016-08-23 23:50:30 +03:00
}
2016-08-21 22:44:03 +03:00
else
2016-08-23 23:50:30 +03:00
{
disconnect ( this , & Parent : : itemExpanded , this , & This : : onItemExpand ) ;
setCurrentItem ( item ) ;
scrollToItem ( item , QAbstractItemView : : PositionAtCenter ) ;
resizeColumnsToContents ( ) ;
connect ( this , & Parent : : itemExpanded , this , & This : : onItemExpand ) ;
}
2016-08-18 23:26:41 +03:00
}
else
{
setCurrentItem ( item ) ;
}
2016-08-23 23:50:30 +03:00
connect ( this , & Parent : : currentItemChanged , this , & This : : onCurrentItemChange ) ;
2016-08-08 22:17:56 +03:00
}
2016-08-03 23:00:04 +03:00
//////////////////////////////////////////////////////////////////////////
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : resizeColumnsToContents ( )
2016-08-03 23:00:04 +03:00
{
for ( int i = 0 ; i < COL_COLUMNS_NUMBER ; + + i )
{
resizeColumnToContents ( i ) ;
}
}
//////////////////////////////////////////////////////////////////////////
2016-09-06 21:49:32 +03:00
void EasyTreeWidget : : onHideShowColumn ( bool )
2016-08-03 23:00:04 +03:00
{
2016-09-06 21:49:32 +03:00
auto action = qobject_cast < QAction * > ( sender ( ) ) ;
if ( action = = nullptr )
return ;
auto col = action - > data ( ) . toInt ( ) ;
if ( isColumnHidden ( col ) )
showColumn ( col ) ;
2016-08-03 23:00:04 +03:00
else
2016-09-06 21:49:32 +03:00
hideColumn ( col ) ;
2016-08-03 23:00:04 +03:00
}
//////////////////////////////////////////////////////////////////////////
2016-08-04 23:12:41 +03:00
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : loadSettings ( )
2016-08-07 19:38:31 +03:00
{
QSettings settings ( : : profiler_gui : : ORGANAZATION_NAME , : : profiler_gui : : APPLICATION_NAME ) ;
settings . beginGroup ( " tree_widget " ) ;
auto color_rows_set = settings . value ( " color_rows " ) ;
if ( ! color_rows_set . isNull ( ) )
m_bColorRows = color_rows_set . toBool ( ) ;
for ( int i = 0 ; i < columnCount ( ) ; i + + )
{
if ( settings . value ( QString ( " Column " ) + QString : : number ( i ) ) . toBool ( ) )
hideColumn ( i ) ;
}
settings . endGroup ( ) ;
}
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : saveSettings ( )
2016-08-04 23:12:41 +03:00
{
2016-09-06 22:23:55 +03:00
QSettings settings ( : : profiler_gui : : ORGANAZATION_NAME , : : profiler_gui : : APPLICATION_NAME ) ;
settings . beginGroup ( " tree_widget " ) ;
2016-08-04 23:12:41 +03:00
2016-09-06 22:23:55 +03:00
settings . setValue ( " color_rows " , m_bColorRows ) ;
2016-08-04 23:12:41 +03:00
2016-09-06 22:23:55 +03:00
for ( int i = 0 ; i < columnCount ( ) ; i + + )
{
settings . setValue ( QString ( " Column " ) + QString : : number ( i ) , isColumnHidden ( i ) ) ;
}
2016-08-04 23:12:41 +03:00
2016-09-06 22:23:55 +03:00
settings . endGroup ( ) ;
2016-08-04 23:12:41 +03:00
}
2016-08-07 19:38:31 +03:00
//////////////////////////////////////////////////////////////////////////