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-11-13 16:39:59 +03:00
* license : Lightweight profiler library for c + +
* : Copyright ( C ) 2016 Sergey Yagovtsev , Victor Zarubkin
* :
* :
* : Licensed under the Apache License , Version 2.0 ( the " License " ) ;
* : you may not use this file except in compliance with the License .
* : You may obtain a copy of the License at
* :
* : http : //www.apache.org/licenses/LICENSE-2.0
* :
* : Unless required by applicable law or agreed to in writing , software
* : distributed under the License is distributed on an " AS IS " BASIS ,
* : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* : See the License for the specific language governing permissions and
* : limitations under the License .
* :
* :
* : GNU General Public License Usage
* : Alternatively , this file may be used 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
2016-09-06 21:49:32 +03:00
* : 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-20 22:57:34 +03:00
# include <QAction>
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-11-20 21:01:33 +03:00
# include <QLineEdit>
# include <QLabel>
# include <QToolBar>
# include <QHBoxLayout>
# include <QVBoxLayout>
2016-12-18 15:56:08 +03:00
# include <QByteArray>
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-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 ;
2016-12-18 15:56:08 +03:00
const bool SIMPLIFIED_REGIME_COLUMNS [ COL_COLUMNS_NUMBER ] = {
true , //COL_NAME,
true , //COL_BEGIN,
true , //COL_DURATION,
true , //COL_SELF_DURATION,
false , //COL_DURATION_SUM_PER_PARENT,
2016-12-18 17:59:41 +03:00
false , //COL_DURATION_SUM_PER_FRAME,
2016-12-18 15:56:08 +03:00
true , //COL_DURATION_SUM_PER_THREAD,
true , //COL_SELF_DURATION_PERCENT,
false , //COL_PERCENT_PER_PARENT,
2016-12-18 17:59:41 +03:00
true , //COL_PERCENT_PER_FRAME,
2016-12-18 15:56:08 +03:00
false , //COL_PERCENT_SUM_PER_PARENT,
2016-12-18 17:59:41 +03:00
false , //COL_PERCENT_SUM_PER_FRAME,
2016-12-18 15:56:08 +03:00
true , //COL_PERCENT_SUM_PER_THREAD,
true , //COL_END,
true , //COL_MIN_PER_FRAME,
true , //COL_MAX_PER_FRAME,
true , //COL_AVERAGE_PER_FRAME,
true , //COL_NCALLS_PER_FRAME,
true , //COL_MIN_PER_THREAD,
true , //COL_MAX_PER_THREAD,
true , //COL_AVERAGE_PER_THREAD,
true , //COL_NCALLS_PER_THREAD,
false , //COL_MIN_PER_PARENT,
false , //COL_MAX_PER_PARENT,
false , //COL_AVERAGE_PER_PARENT,
2016-12-18 17:59:41 +03:00
false , //COL_NCALLS_PER_PARENT,
true , //COL_ACTIVE_TIME,
true //COL_ACTIVE_PERCENT,
2016-12-18 15:56:08 +03:00
} ;
2016-08-21 22:44:03 +03:00
//////////////////////////////////////////////////////////////////////////
EasyTreeWidget : : EasyTreeWidget ( QWidget * _parent )
: Parent ( _parent )
, m_beginTime ( : : std : : numeric_limits < decltype ( m_beginTime ) > : : max ( ) )
2016-11-20 21:01:33 +03:00
, m_lastFound ( nullptr )
2016-08-21 22:44:03 +03:00
, m_progress ( nullptr )
2016-12-18 15:56:08 +03:00
, m_mode ( EasyTreeMode_Plain )
2016-08-21 22:44:03 +03:00
, m_bColorRows ( true )
, m_bLocked ( false )
, m_bSilentExpandCollapse ( false )
2016-06-26 18:46:51 +03:00
{
2016-12-18 15:56:08 +03:00
memset ( m_columnsHiddenStatus , 0 , sizeof ( m_columnsHiddenStatus ) ) ;
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-11-30 21:59:40 +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, "");
2016-12-12 21:39:16 +03:00
header_item - > setText ( COL_DURATION_SUM_PER_PARENT , " Sum Dur./Parent " ) ;
header_item - > setText ( COL_DURATION_SUM_PER_FRAME , " Sum Dur./Frame " ) ;
header_item - > setText ( COL_DURATION_SUM_PER_THREAD , " Sum Dur./Thread " ) ;
2016-09-14 23:14:24 +03:00
header_item - > setText ( COL_SELF_DURATION_PERCENT , " Self % " ) ;
header_item - > setText ( COL_PERCENT_PER_PARENT , " % / Parent " ) ;
header_item - > setText ( COL_PERCENT_PER_FRAME , " % / Frame " ) ;
2016-12-12 21:39:16 +03:00
header_item - > setText ( COL_PERCENT_SUM_PER_FRAME , " Sum % / Frame " ) ;
header_item - > setText ( COL_PERCENT_SUM_PER_PARENT , " Sum % / Parent " ) ;
header_item - > setText ( COL_PERCENT_SUM_PER_THREAD , " Sum % / Thread " ) ;
2016-09-14 23:14:24 +03:00
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 " ) ;
2016-12-18 17:59:41 +03:00
header_item - > setText ( COL_ACTIVE_TIME , " Active time " ) ;
header_item - > setText ( COL_ACTIVE_PERCENT , " Active % " ) ;
2016-09-14 23:14:24 +03:00
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
2016-12-18 15:56:08 +03:00
if ( m_mode = = EasyTreeMode_Full )
{
for ( int i = 0 ; i < COL_COLUMNS_NUMBER ; + + i )
m_columnsHiddenStatus [ i ] = isColumnHidden ( i ) ? 1 : 0 ;
}
else
{
for ( int i = 0 ; i < COL_COLUMNS_NUMBER ; + + i )
{
if ( SIMPLIFIED_REGIME_COLUMNS [ i ] )
{
if ( isColumnHidden ( i ) )
m_columnsHiddenStatus [ i ] = 1 ;
}
else if ( ! isColumnHidden ( i ) )
{
setColumnHidden ( i , true ) ;
}
}
}
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 ) ;
2016-12-18 15:56:08 +03:00
sortByColumn ( COL_BEGIN , Qt : : AscendingOrder ) ; // sort by begin time
if ( m_mode = = EasyTreeMode_Plain ) // and after that, sort by frame %
2016-12-18 17:59:41 +03:00
sortByColumn ( COL_PERCENT_PER_FRAME , Qt : : DescendingOrder ) ;
2016-12-18 15:56:08 +03:00
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-12-18 15:56:08 +03:00
m_hierarchyBuilder . fillTree ( m_beginTime , _blocksNumber , _blocksTree , m_bColorRows , m_mode ) ;
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-12-18 15:56:08 +03:00
m_hierarchyBuilder . fillTreeBlocks ( m_inputBlocks , _session_begin_time , _left , _right , _strict , m_bColorRows , m_mode ) ;
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-11-20 21:01:33 +03:00
m_lastFound = nullptr ;
m_lastSearch . clear ( ) ;
2016-06-30 02:57:57 +03:00
2016-08-04 22:38:45 +03:00
if ( ! _global )
{
2016-12-12 21:39:16 +03:00
if ( EASY_GLOBALS . collapse_items_on_tree_close )
# ifdef EASY_TREE_WIDGET__USE_VECTOR
for ( auto item : m_items )
# else
for ( auto & item : m_items )
# endif
2016-08-04 22:38:45 +03:00
{
2016-12-12 21:39:16 +03:00
# ifdef EASY_TREE_WIDGET__USE_VECTOR
2016-08-30 22:51:18 +03:00
auto & gui_block = item - > guiBlock ( ) ;
2016-08-18 23:26:41 +03:00
gui_block . expanded = false ;
2016-12-12 21:39:16 +03:00
: : profiler_gui : : set_max ( gui_block . tree_item ) ;
# else
item . second - > guiBlock ( ) . expanded = false ;
# endif
2016-08-04 22:38:45 +03:00
}
2016-12-12 21:39:16 +03:00
# ifdef EASY_TREE_WIDGET__USE_VECTOR
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-12-12 21:39:16 +03:00
# endif
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-11-20 21:40:05 +03:00
int EasyTreeWidget : : findNext ( const QString & _str , Qt : : MatchFlags _flags )
2016-11-20 21:01:33 +03:00
{
if ( m_bLocked | | _str . isEmpty ( ) )
return 0 ;
const bool isNewSearch = ( m_lastSearch ! = _str ) ;
2016-11-20 21:40:05 +03:00
auto itemsList = findItems ( _str , Qt : : MatchContains | Qt : : MatchRecursive | _flags , COL_NAME ) ;
2016-11-20 21:01:33 +03:00
if ( ! isNewSearch )
{
if ( ! itemsList . empty ( ) )
{
bool stop = false ;
decltype ( m_lastFound ) next = nullptr ;
for ( auto item : itemsList )
{
if ( item - > parent ( ) = = nullptr )
continue ;
if ( stop )
{
next = item ;
break ;
}
stop = item = = m_lastFound ;
}
m_lastFound = next = = nullptr ? itemsList . front ( ) : next ;
}
else
{
m_lastFound = nullptr ;
}
}
else
{
m_lastSearch = _str ;
m_lastFound = ! itemsList . empty ( ) ? itemsList . front ( ) : nullptr ;
}
if ( m_lastFound ! = nullptr )
{
scrollToItem ( m_lastFound , QAbstractItemView : : PositionAtCenter ) ;
setCurrentItem ( m_lastFound ) ;
}
return itemsList . size ( ) ;
}
2016-11-20 21:40:05 +03:00
int EasyTreeWidget : : findPrev ( const QString & _str , Qt : : MatchFlags _flags )
2016-11-20 21:01:33 +03:00
{
if ( m_bLocked | | _str . isEmpty ( ) )
return 0 ;
const bool isNewSearch = ( m_lastSearch ! = _str ) ;
2016-11-20 21:40:05 +03:00
auto itemsList = findItems ( _str , Qt : : MatchContains | Qt : : MatchRecursive | _flags , COL_NAME ) ;
2016-11-20 21:01:33 +03:00
if ( ! isNewSearch )
{
if ( ! itemsList . empty ( ) )
{
decltype ( m_lastFound ) prev = nullptr ;
for ( auto item : itemsList )
{
if ( item - > parent ( ) = = nullptr )
continue ;
if ( item = = m_lastFound )
break ;
prev = item ;
}
m_lastFound = prev = = nullptr ? itemsList . back ( ) : prev ;
}
else
{
m_lastFound = nullptr ;
}
}
else
{
m_lastSearch = _str ;
m_lastFound = ! itemsList . empty ( ) ? itemsList . front ( ) : nullptr ;
}
if ( m_lastFound ! = nullptr )
{
scrollToItem ( m_lastFound , QAbstractItemView : : PositionAtCenter ) ;
setCurrentItem ( m_lastFound ) ;
}
return itemsList . size ( ) ;
}
//////////////////////////////////////////////////////////////////////////
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-09-25 11:51:39 +03:00
menu . setToolTipsVisible ( true ) ;
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-12-18 15:56:08 +03:00
action = menu . addAction ( " Hierarchy mode " ) ;
action - > setToolTip ( " Display full blocks hierarchy " ) ;
action - > setCheckable ( true ) ;
action - > setChecked ( m_mode = = EasyTreeMode_Full ) ;
action - > setData ( ( quint32 ) EasyTreeMode_Full ) ;
connect ( action , & QAction : : triggered , this , & This : : onModeChange ) ;
action = menu . addAction ( " Plain mode " ) ;
action - > setToolTip ( " Display plain list of blocks per frame. \n Some columns are disabled with this mode. " ) ;
action - > setCheckable ( true ) ;
action - > setChecked ( m_mode = = EasyTreeMode_Plain ) ;
action - > setData ( ( quint32 ) EasyTreeMode_Plain ) ;
connect ( action , & QAction : : triggered , this , & This : : onModeChange ) ;
menu . addSeparator ( ) ;
2016-08-23 23:50:30 +03:00
action = menu . addAction ( " Color rows " ) ;
2016-12-18 15:56:08 +03:00
action - > setToolTip ( " Colorize rows with same colors as on diagram " ) ;
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
2016-09-20 22:57:34 +03:00
const auto & desc = easyDescriptor ( item - > block ( ) . node - > id ( ) ) ;
auto submenu = menu . addMenu ( " Block status " ) ;
2016-09-25 11:51:39 +03:00
submenu - > setToolTipsVisible ( true ) ;
2016-09-20 22:57:34 +03:00
2016-09-25 11:51:39 +03:00
# define ADD_STATUS_ACTION(NameValue, StatusValue, ToolTipValue)\
2016-09-20 22:57:34 +03:00
action = submenu - > addAction ( NameValue ) ; \
action - > setCheckable ( true ) ; \
action - > setChecked ( desc . status ( ) = = StatusValue ) ; \
action - > setData ( static_cast < quint32 > ( StatusValue ) ) ; \
2016-09-25 11:51:39 +03:00
action - > setToolTip ( ToolTipValue ) ; \
2016-09-20 22:57:34 +03:00
connect ( action , & QAction : : triggered , this , & This : : onBlockStatusChangeClicked )
2016-09-25 11:51:39 +03:00
ADD_STATUS_ACTION ( " Off " , : : profiler : : OFF , " Do not profile this block. " ) ;
ADD_STATUS_ACTION ( " On " , : : profiler : : ON , " Profile this block \n if parent enabled children. " ) ;
ADD_STATUS_ACTION ( " Force-On " , : : profiler : : FORCE_ON , " Always profile this block even \n if it's parent disabled children. " ) ;
ADD_STATUS_ACTION ( " Off-recursive " , : : profiler : : OFF_RECURSIVE , " Do not profile neither this block \n nor it's children. " ) ;
ADD_STATUS_ACTION ( " On-without-children " , : : profiler : : ON_WITHOUT_CHILDREN , " Profile this block, but \n do not profile it's children. " ) ;
ADD_STATUS_ACTION ( " Force-On-without-children " , : : profiler : : FORCE_ON_WITHOUT_CHILDREN , " Always profile this block, but \n do not profile it's children. " ) ;
2016-09-20 22:57:34 +03:00
# undef ADD_STATUS_ACTION
2016-09-25 11:51:39 +03:00
submenu - > setEnabled ( EASY_GLOBALS . connected ) ;
if ( ! EASY_GLOBALS . connected )
submenu - > setTitle ( QString ( " %1 (connection needed) " ) . arg ( submenu - > title ( ) ) ) ;
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-12-18 15:56:08 +03:00
columnAction - > setChecked ( m_columnsHiddenStatus [ i ] = = 0 ) ; // !isColumnHidden(i));
if ( m_mode = = EasyTreeMode_Full | | SIMPLIFIED_REGIME_COLUMNS [ i ] )
connect ( columnAction , & QAction : : triggered , this , & This : : onHideShowColumn ) ;
else
columnAction - > setEnabled ( false ) ;
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 ;
2016-11-30 21:59:40 +03:00
if ( block_index < EASY_GLOBALS . gui_blocks . size ( ) )
EASY_GLOBALS . selected_block_id = easyBlock ( block_index ) . tree . node - > id ( ) ;
else
: : profiler_gui : : set_max ( EASY_GLOBALS . selected_block_id ) ;
2016-09-06 21:49:32 +03:00
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
{
2016-12-12 21:39:16 +03:00
# ifdef EASY_TREE_WIDGET__USE_VECTOR
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 ;
2016-12-12 21:39:16 +03:00
# else
for ( auto & item : m_items )
item . second - > guiBlock ( ) . expanded = false ;
# endif
2016-08-30 22:51:18 +03:00
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
{
2016-12-12 21:39:16 +03:00
# ifdef EASY_TREE_WIDGET__USE_VECTOR
for ( auto item : m_items ) {
2016-08-30 22:51:18 +03:00
auto & b = item - > guiBlock ( ) ;
2016-12-12 21:39:16 +03:00
# else
for ( auto & item : m_items ) {
auto & b = item . second - > guiBlock ( ) ;
# endif
2016-08-30 22:51:18 +03:00
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-20 22:57:34 +03:00
void EasyTreeWidget : : onBlockStatusChangeClicked ( bool _checked )
2016-09-17 15:39:31 +03:00
{
2016-09-20 22:57:34 +03:00
if ( ! _checked )
return ;
auto item = static_cast < EasyTreeWidgetItem * > ( currentItem ( ) ) ;
if ( item = = nullptr )
return ;
2016-09-17 15:39:31 +03:00
auto action = qobject_cast < QAction * > ( sender ( ) ) ;
if ( action ! = nullptr )
{
2016-09-20 22:57:34 +03:00
auto & desc = easyDescriptor ( item - > block ( ) . node - > id ( ) ) ;
desc . setStatus ( static_cast < : : profiler : : EasyBlockStatus > ( action - > data ( ) . toUInt ( ) ) ) ;
emit EASY_GLOBALS . events . blockStatusChanged ( desc . id ( ) , desc . status ( ) ) ;
2016-09-17 15:39:31 +03:00
}
}
//////////////////////////////////////////////////////////////////////////
2016-08-18 23:26:41 +03:00
void EasyTreeWidget : : onItemExpand ( QTreeWidgetItem * _item )
2016-06-26 18:46:51 +03:00
{
2016-10-02 17:45:55 +03:00
if ( ! EASY_GLOBALS . bind_scene_and_tree_expand_status | | _item - > parent ( ) = = nullptr )
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-10-02 17:45:55 +03:00
if ( ! EASY_GLOBALS . bind_scene_and_tree_expand_status | | _item - > parent ( ) = = nullptr )
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
//////////////////////////////////////////////////////////////////////////
2016-11-30 21:59:40 +03:00
void EasyTreeWidget : : onCurrentItemChange ( QTreeWidgetItem * _item , QTreeWidgetItem * _previous )
2016-08-23 23:50:30 +03:00
{
2016-11-30 21:59:40 +03:00
if ( _previous ! = nullptr )
{
auto f = font ( ) ;
for ( int i = 0 ; i < COL_COLUMNS_NUMBER ; + + i )
_previous - > setFont ( i , f ) ;
}
2016-08-23 23:50:30 +03:00
if ( _item = = nullptr )
2016-11-30 21:59:40 +03:00
{
2016-08-30 22:51:18 +03:00
: : profiler_gui : : set_max ( EASY_GLOBALS . selected_block ) ;
2016-11-30 21:59:40 +03:00
: : profiler_gui : : set_max ( EASY_GLOBALS . selected_block_id ) ;
}
2016-08-23 23:50:30 +03:00
else
2016-11-30 21:59:40 +03:00
{
auto f = font ( ) ;
f . setBold ( true ) ;
for ( int i = 0 ; i < COL_COLUMNS_NUMBER ; + + i )
_item - > setFont ( i , f ) ;
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . selected_block = static_cast < EasyTreeWidgetItem * > ( _item ) - > block_index ( ) ;
2016-11-30 21:59:40 +03:00
if ( EASY_GLOBALS . selected_block < EASY_GLOBALS . gui_blocks . size ( ) )
EASY_GLOBALS . selected_block_id = easyBlock ( EASY_GLOBALS . selected_block ) . tree . node - > id ( ) ;
else
: : profiler_gui : : set_max ( EASY_GLOBALS . selected_block_id ) ;
}
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.
2016-12-12 21:39:16 +03:00
# ifdef EASY_TREE_WIDGET__USE_VECTOR
2016-06-27 22:11:26 +03:00
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
}
2016-12-12 21:39:16 +03:00
# else
for ( auto & item : m_items )
{
if ( item . second - > parent ( ) ! = nullptr )
item . second - > colorize ( m_bColorRows ) ;
}
# endif
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-12-12 21:39:16 +03:00
# ifdef EASY_TREE_WIDGET__USE_VECTOR
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-12-12 21:39:16 +03:00
# else
auto it = m_items . find ( _block_index ) ;
if ( it ! = m_items . end ( ) )
item = it - > second ;
# endif
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-11-30 21:59:40 +03:00
auto previous = currentItem ( ) ;
auto f = font ( ) ;
if ( previous ! = nullptr ) for ( int i = 0 ; i < COL_COLUMNS_NUMBER ; + + i )
previous - > setFont ( i , f ) ;
2016-08-21 22:44:03 +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
{
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-11-30 21:59:40 +03:00
f . setBold ( true ) ;
for ( int i = 0 ; i < COL_COLUMNS_NUMBER ; + + i )
item - > setFont ( i , f ) ;
2016-08-18 23:26:41 +03:00
}
else
{
2016-11-30 21:59:40 +03:00
auto previous = currentItem ( ) ;
if ( previous ! = nullptr )
{
auto f = font ( ) ;
for ( int i = 0 ; i < COL_COLUMNS_NUMBER ; + + i )
previous - > setFont ( i , f ) ;
}
2016-08-18 23:26:41 +03:00
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 ;
2016-12-18 15:56:08 +03:00
const auto col = action - > data ( ) . toInt ( ) ;
const bool hideCol = m_columnsHiddenStatus [ col ] = = 0 ;
setColumnHidden ( col , hideCol ) ;
m_columnsHiddenStatus [ col ] = hideCol ? 1 : 0 ;
}
void EasyTreeWidget : : onModeChange ( bool )
{
auto action = qobject_cast < QAction * > ( sender ( ) ) ;
if ( action = = nullptr )
return ;
const auto prev = m_mode ;
m_mode = static_cast < EasyTreeMode > ( action - > data ( ) . toUInt ( ) ) ;
if ( m_mode = = prev )
return ;
if ( m_mode = = EasyTreeMode_Full )
{
for ( int i = 0 ; i < COL_COLUMNS_NUMBER ; + + i )
setColumnHidden ( i , m_columnsHiddenStatus [ i ] ! = 0 ) ;
}
2016-08-03 23:00:04 +03:00
else
2016-12-18 15:56:08 +03:00
{
for ( int i = 0 ; i < COL_COLUMNS_NUMBER ; + + i )
setColumnHidden ( i , m_columnsHiddenStatus [ i ] ! = 0 | | ! SIMPLIFIED_REGIME_COLUMNS [ i ] ) ;
}
emit EASY_GLOBALS . events . blocksTreeModeChanged ( ) ;
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 " ) ;
2016-12-18 15:56:08 +03:00
auto val = settings . value ( " color_rows " ) ;
if ( ! val . isNull ( ) )
m_bColorRows = val . toBool ( ) ;
val = settings . value ( " regime " ) ;
if ( ! val . isNull ( ) )
m_mode = static_cast < EasyTreeMode > ( val . toUInt ( ) ) ;
val = settings . value ( " columns " ) ;
if ( ! val . isNull ( ) )
{
auto byteArray = val . toByteArray ( ) ;
2016-12-18 17:59:41 +03:00
memcpy ( m_columnsHiddenStatus , byteArray . constData ( ) , : : std : : min ( sizeof ( m_columnsHiddenStatus ) , ( size_t ) byteArray . size ( ) ) ) ;
2016-12-18 15:56:08 +03:00
}
2016-08-07 19:38:31 +03:00
2016-11-30 21:59:40 +03:00
auto state = settings . value ( " headerState " ) . toByteArray ( ) ;
if ( ! state . isEmpty ( ) )
header ( ) - > restoreState ( state ) ;
2016-08-07 19:38:31 +03:00
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 " ) ;
settings . setValue ( " color_rows " , m_bColorRows ) ;
2016-12-18 15:56:08 +03:00
settings . setValue ( " regime " , static_cast < uint8_t > ( m_mode ) ) ;
settings . setValue ( " columns " , QByteArray ( m_columnsHiddenStatus , COL_COLUMNS_NUMBER ) ) ;
2016-11-30 21:59:40 +03:00
settings . setValue ( " headerState " , header ( ) - > saveState ( ) ) ;
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
//////////////////////////////////////////////////////////////////////////
2016-11-20 21:01:33 +03:00
//////////////////////////////////////////////////////////////////////////
EasyHierarchyWidget : : EasyHierarchyWidget ( QWidget * _parent ) : Parent ( _parent )
2016-11-20 21:40:05 +03:00
, m_tree ( new EasyTreeWidget ( this ) )
, m_searchBox ( new QLineEdit ( this ) )
, m_foundNumber ( new QLabel ( " Found 0 matches " , this ) )
, m_searchButton ( nullptr )
, m_bCaseSensitiveSearch ( false )
2016-11-20 21:01:33 +03:00
{
2016-11-20 21:40:05 +03:00
loadSettings ( ) ;
2016-11-20 21:01:33 +03:00
m_searchBox - > setFixedWidth ( 200 ) ;
m_searchBox - > setContentsMargins ( 5 , 0 , 0 , 0 ) ;
QMenu * menu = new QMenu ( this ) ;
m_searchButton = menu - > menuAction ( ) ;
m_searchButton - > setText ( " Find next " ) ;
m_searchButton - > setIcon ( QIcon ( " :/Search-next " ) ) ;
m_searchButton - > setData ( true ) ;
connect ( m_searchButton , & QAction : : triggered , this , & This : : findNext ) ;
auto actionGroup = new QActionGroup ( this ) ;
actionGroup - > setExclusive ( true ) ;
auto a = new QAction ( tr ( " Find next " ) , actionGroup ) ;
a - > setCheckable ( true ) ;
a - > setChecked ( true ) ;
connect ( a , & QAction : : triggered , this , & This : : findNextFromMenu ) ;
menu - > addAction ( a ) ;
a = new QAction ( tr ( " Find previous " ) , actionGroup ) ;
a - > setCheckable ( true ) ;
connect ( a , & QAction : : triggered , this , & This : : findPrevFromMenu ) ;
menu - > addAction ( a ) ;
2016-11-20 21:40:05 +03:00
menu - > addSeparator ( ) ;
a = menu - > addAction ( " Case sensitive " ) ;
a - > setCheckable ( true ) ;
a - > setChecked ( m_bCaseSensitiveSearch ) ;
connect ( a , & QAction : : triggered , [ this ] ( bool _checked ) { m_bCaseSensitiveSearch = _checked ; } ) ;
menu - > addAction ( a ) ;
2016-11-20 21:01:33 +03:00
auto tb = new QToolBar ( this ) ;
2016-12-18 19:16:21 +03:00
tb - > setIconSize ( : : profiler_gui : : ICONS_SIZE ) ;
2016-11-20 21:40:05 +03:00
tb - > setContentsMargins ( 0 , 0 , 0 , 0 ) ;
2016-11-20 21:01:33 +03:00
tb - > addAction ( m_searchButton ) ;
tb - > addWidget ( m_searchBox ) ;
auto searchbox = new QHBoxLayout ( ) ;
searchbox - > setContentsMargins ( 0 , 0 , 5 , 0 ) ;
searchbox - > addWidget ( tb ) ;
searchbox - > addStretch ( 100 ) ;
searchbox - > addWidget ( m_foundNumber , Qt : : AlignRight ) ;
auto lay = new QVBoxLayout ( this ) ;
lay - > setContentsMargins ( 1 , 1 , 1 , 1 ) ;
lay - > addLayout ( searchbox ) ;
lay - > addWidget ( m_tree ) ;
connect ( m_searchBox , & QLineEdit : : returnPressed , this , & This : : onSeachBoxReturnPressed ) ;
}
EasyHierarchyWidget : : ~ EasyHierarchyWidget ( )
{
2016-11-20 21:40:05 +03:00
saveSettings ( ) ;
}
void EasyHierarchyWidget : : loadSettings ( )
{
QSettings settings ( : : profiler_gui : : ORGANAZATION_NAME , : : profiler_gui : : APPLICATION_NAME ) ;
settings . beginGroup ( " EasyHierarchyWidget " ) ;
auto val = settings . value ( " case_sensitive " ) ;
if ( ! val . isNull ( ) )
m_bCaseSensitiveSearch = val . toBool ( ) ;
2016-11-20 21:01:33 +03:00
2016-11-20 21:40:05 +03:00
settings . endGroup ( ) ;
}
void EasyHierarchyWidget : : saveSettings ( )
{
QSettings settings ( : : profiler_gui : : ORGANAZATION_NAME , : : profiler_gui : : APPLICATION_NAME ) ;
settings . beginGroup ( " EasyHierarchyWidget " ) ;
settings . setValue ( " case_sensitive " , m_bCaseSensitiveSearch ) ;
settings . endGroup ( ) ;
2016-11-20 21:01:33 +03:00
}
void EasyHierarchyWidget : : keyPressEvent ( QKeyEvent * _event )
{
if ( _event - > key ( ) = = Qt : : Key_F3 )
{
if ( _event - > modifiers ( ) & Qt : : ShiftModifier )
findPrev ( true ) ;
else
findNext ( true ) ;
}
_event - > accept ( ) ;
}
2016-12-18 15:56:08 +03:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void EasyHierarchyWidget : : contextMenuEvent ( QContextMenuEvent * _event )
{
m_tree - > contextMenuEvent ( _event ) ;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2016-11-20 21:01:33 +03:00
EasyTreeWidget * EasyHierarchyWidget : : tree ( )
{
return m_tree ;
}
void EasyHierarchyWidget : : clear ( bool _global )
{
m_tree - > clearSilent ( _global ) ;
m_foundNumber - > setText ( QString ( " Found 0 matches " ) ) ;
}
void EasyHierarchyWidget : : onSeachBoxReturnPressed ( )
{
2016-11-20 21:40:05 +03:00
if ( m_searchButton - > data ( ) . toBool ( ) = = true )
findNext ( true ) ;
2016-11-20 21:01:33 +03:00
else
2016-11-20 21:40:05 +03:00
findPrev ( true ) ;
2016-11-20 21:01:33 +03:00
}
void EasyHierarchyWidget : : findNext ( bool )
{
2016-11-20 21:40:05 +03:00
auto matches = m_tree - > findNext ( m_searchBox - > text ( ) , m_bCaseSensitiveSearch ? Qt : : MatchCaseSensitive : Qt : : MatchFlags ( ) ) ;
2016-11-20 21:01:33 +03:00
if ( matches = = 1 )
m_foundNumber - > setText ( QString ( " Found 1 match " ) ) ;
else
m_foundNumber - > setText ( QString ( " Found %1 matches " ) . arg ( matches ) ) ;
}
void EasyHierarchyWidget : : findPrev ( bool )
{
2016-11-20 21:40:05 +03:00
auto matches = m_tree - > findPrev ( m_searchBox - > text ( ) , m_bCaseSensitiveSearch ? Qt : : MatchCaseSensitive : Qt : : MatchFlags ( ) ) ;
2016-11-20 21:01:33 +03:00
if ( matches = = 1 )
m_foundNumber - > setText ( QString ( " Found 1 match " ) ) ;
else
m_foundNumber - > setText ( QString ( " Found %1 matches " ) . arg ( matches ) ) ;
}
void EasyHierarchyWidget : : findNextFromMenu ( bool _checked )
{
if ( ! _checked )
return ;
if ( m_searchButton - > data ( ) . toBool ( ) = = false )
{
m_searchButton - > setData ( true ) ;
m_searchButton - > setText ( tr ( " Find next " ) ) ;
m_searchButton - > setIcon ( QIcon ( " :/Search-next " ) ) ;
disconnect ( m_searchButton , & QAction : : triggered , this , & This : : findPrev ) ;
connect ( m_searchButton , & QAction : : triggered , this , & This : : findNext ) ;
}
findNext ( true ) ;
}
void EasyHierarchyWidget : : findPrevFromMenu ( bool _checked )
{
if ( ! _checked )
return ;
if ( m_searchButton - > data ( ) . toBool ( ) = = true )
{
m_searchButton - > setData ( false ) ;
m_searchButton - > setText ( tr ( " Find prev " ) ) ;
m_searchButton - > setIcon ( QIcon ( " :/Search-prev " ) ) ;
disconnect ( m_searchButton , & QAction : : triggered , this , & This : : findNext ) ;
connect ( m_searchButton , & QAction : : triggered , this , & This : : findPrev ) ;
}
findPrev ( true ) ;
}
//////////////////////////////////////////////////////////////////////////