2016-08-28 21:06:23 +03:00
/************************************************************************
* file name : main_window . cpp
* - - - - - - - - - - - - - - - - - :
* creation time : 2016 / 06 / 26
* author : Victor Zarubkin
* email : v . s . zarubkin @ gmail . com
* - - - - - - - - - - - - - - - - - :
* description : The file contains implementation of MainWindow for easy_profiler GUI .
* - - - - - - - - - - - - - - - - - :
* change log : * 2016 / 06 / 26 Victor Zarubkin : Initial commit .
* :
* : * 2016 / 06 / 27 Victor Zarubkin : Passing blocks number to EasyTreeWidget : : setTree ( ) .
* :
* : * 2016 / 06 / 29 Victor Zarubkin : Added menu with tests .
* :
* : * 2016 / 06 / 30 Sergey Yagovtsev : Open file by command line argument
* :
* : *
* - - - - - - - - - - - - - - - - - :
2016-09-06 22:23:55 +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
2016-09-06 21:49:32 +03:00
* : along with this program . If not , see < http : //www.gnu.org/licenses/>.
2016-08-28 21:06:23 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-09-18 20:20:37 +03:00
# include <chrono>
# include <fstream>
2016-09-15 23:56:20 +03:00
# include <QApplication>
2016-09-18 20:20:37 +03:00
# include <QCoreApplication>
2016-08-28 21:06:23 +03:00
# include <QStatusBar>
# include <QDockWidget>
# include <QFileDialog>
# include <QAction>
# include <QMenu>
# include <QMenuBar>
# include <QCloseEvent>
# include <QSettings>
# include <QTextCodec>
2016-09-14 23:13:38 +03:00
# include <QFont>
2016-08-28 21:06:23 +03:00
# include <QProgressDialog>
# include <QSignalBlocker>
# include <QDebug>
2016-09-08 21:03:05 +03:00
# include <QToolBar>
# include <QMessageBox>
2016-09-18 20:20:37 +03:00
# include <QLineEdit>
# include <QLabel>
2016-09-17 15:39:31 +03:00
# include <QDialog>
# include <QVBoxLayout>
2016-09-18 20:20:37 +03:00
2016-08-28 21:06:23 +03:00
# include "main_window.h"
# include "blocks_tree_widget.h"
# include "blocks_graphics_view.h"
2016-09-17 15:39:31 +03:00
# include "descriptors_tree_widget.h"
2016-08-28 21:06:23 +03:00
# include "globals.h"
2016-09-08 21:03:05 +03:00
# include "profiler/easy_net.h"
2016-09-18 20:20:37 +03:00
# ifdef max
2016-09-15 22:41:47 +03:00
# undef max
2016-09-18 20:20:37 +03:00
# endif
# ifdef min
# undef min
# endif
2016-09-15 22:41:47 +03:00
2016-08-28 21:06:23 +03:00
//////////////////////////////////////////////////////////////////////////
const int LOADER_TIMER_INTERVAL = 40 ;
//////////////////////////////////////////////////////////////////////////
2016-09-17 18:43:06 +03:00
EasyMainWindow : : EasyMainWindow ( ) : Parent ( )
2016-08-28 21:06:23 +03:00
{
2016-09-15 23:56:20 +03:00
{ QIcon icon ( " :/logo " ) ; if ( ! icon . isNull ( ) ) QApplication : : setWindowIcon ( icon ) ; }
2016-08-28 21:06:23 +03:00
setObjectName ( " ProfilerGUI_MainWindow " ) ;
2016-09-14 21:52:11 +03:00
setWindowTitle ( " EasyProfiler Reader beta " ) ;
2016-08-28 21:06:23 +03:00
setDockNestingEnabled ( true ) ;
resize ( 800 , 600 ) ;
setStatusBar ( new QStatusBar ( ) ) ;
auto graphicsView = new EasyGraphicsViewWidget ( ) ;
2016-09-17 18:43:06 +03:00
m_graphicsView = new QDockWidget ( " Diagram " ) ;
m_graphicsView - > setObjectName ( " ProfilerGUI_Diagram " ) ;
2016-08-28 21:06:23 +03:00
m_graphicsView - > setMinimumHeight ( 50 ) ;
m_graphicsView - > setAllowedAreas ( Qt : : AllDockWidgetAreas ) ;
m_graphicsView - > setWidget ( graphicsView ) ;
auto treeWidget = new EasyTreeWidget ( ) ;
2016-09-17 18:43:06 +03:00
m_treeWidget = new QDockWidget ( " Hierarchy " ) ;
m_treeWidget - > setObjectName ( " ProfilerGUI_Hierarchy " ) ;
2016-08-28 21:06:23 +03:00
m_treeWidget - > setMinimumHeight ( 50 ) ;
m_treeWidget - > setAllowedAreas ( Qt : : AllDockWidgetAreas ) ;
m_treeWidget - > setWidget ( treeWidget ) ;
addDockWidget ( Qt : : TopDockWidgetArea , m_graphicsView ) ;
addDockWidget ( Qt : : BottomDockWidgetArea , m_treeWidget ) ;
2016-09-17 18:43:06 +03:00
# if EASY_GUI_USE_DESCRIPTORS_DOCK_WINDOW != 0
auto descTree = new EasyDescWidget ( ) ;
m_descTreeWidget = new QDockWidget ( " Blocks " ) ;
m_descTreeWidget - > setObjectName ( " ProfilerGUI_Blocks " ) ;
m_descTreeWidget - > setMinimumHeight ( 50 ) ;
m_descTreeWidget - > setAllowedAreas ( Qt : : AllDockWidgetAreas ) ;
m_descTreeWidget - > setWidget ( descTree ) ;
addDockWidget ( Qt : : BottomDockWidgetArea , m_descTreeWidget ) ;
# endif
2016-09-13 21:42:38 +03:00
2016-09-18 20:20:37 +03:00
auto toolbar = addToolBar ( " MainToolBar " ) ;
toolbar - > setObjectName ( " ProfilerGUI_MainToolBar " ) ;
2016-09-21 22:09:04 +03:00
toolbar - > addAction ( QIcon ( " :/Delete " ) , tr ( " Clear all " ) , this , SLOT ( onDeleteClicked ( bool ) ) ) ;
2016-09-08 21:03:05 +03:00
2016-09-25 11:49:49 +03:00
toolbar - > addAction ( QIcon ( " :/List " ) , tr ( " Blocks " ) , this , SLOT ( onEditBlocksClicked ( bool ) ) ) ;
2016-09-20 01:24:53 +03:00
m_captureAction = toolbar - > addAction ( QIcon ( " :/Start " ) , tr ( " Capture " ) , this , SLOT ( onCaptureClicked ( bool ) ) ) ;
2016-09-18 20:20:37 +03:00
m_captureAction - > setEnabled ( false ) ;
2016-09-13 21:42:38 +03:00
2016-09-18 20:20:37 +03:00
toolbar - > addSeparator ( ) ;
2016-09-20 01:24:53 +03:00
m_connectAction = toolbar - > addAction ( QIcon ( " :/Connection " ) , tr ( " Connect " ) , this , SLOT ( onConnectClicked ( bool ) ) ) ;
2016-09-08 21:03:05 +03:00
2016-09-18 20:20:37 +03:00
toolbar - > addWidget ( new QLabel ( " IP: " ) ) ;
m_ipEdit = new QLineEdit ( ) ;
2016-09-20 22:30:39 +03:00
m_ipEdit - > setMaximumWidth ( 100 ) ;
2016-09-18 20:20:37 +03:00
QRegExp rx ( " [0-9]{1,3} \\ .[0-9]{1,3} \\ .[0-9]{1,3} \\ .[0-9]{1,3} " ) ;
m_ipEdit - > setInputMask ( " 000.000.000.000; " ) ;
m_ipEdit - > setValidator ( new QRegExpValidator ( rx , m_ipEdit ) ) ;
m_ipEdit - > setText ( " 127.0.0.1 " ) ;
toolbar - > addWidget ( m_ipEdit ) ;
toolbar - > addWidget ( new QLabel ( " Port: " ) ) ;
m_portEdit = new QLineEdit ( ) ;
2016-09-20 22:30:39 +03:00
m_portEdit - > setMaximumWidth ( 80 ) ;
2016-09-18 20:20:37 +03:00
m_portEdit - > setValidator ( new QIntValidator ( 1024 , 65536 , m_portEdit ) ) ;
m_portEdit - > setText ( QString : : number ( : : profiler : : DEFAULT_PORT ) ) ;
toolbar - > addWidget ( m_portEdit ) ;
2016-09-13 21:42:38 +03:00
2016-09-14 22:04:15 +03:00
2016-08-28 21:06:23 +03:00
loadSettings ( ) ;
2016-09-27 21:57:46 +03:00
if ( ! m_lastAddress . isEmpty ( ) )
m_ipEdit - > setText ( m_lastAddress ) ;
if ( m_lastPort ! = 0 )
m_portEdit - > setText ( QString : : number ( m_lastPort ) ) ;
2016-08-28 21:06:23 +03:00
2016-09-18 20:20:37 +03:00
auto menu = menuBar ( ) - > addMenu ( " &File " ) ;
2016-09-20 01:24:53 +03:00
menu - > addAction ( QIcon ( " :/Open " ) , " &Open " , this , SLOT ( onOpenFileClicked ( bool ) ) ) ;
menu - > addAction ( QIcon ( " :/Reload " ) , " &Reload " , this , SLOT ( onReloadFileClicked ( bool ) ) ) ;
2016-08-28 21:06:23 +03:00
menu - > addSeparator ( ) ;
2016-09-20 01:24:53 +03:00
menu - > addAction ( QIcon ( " :/Exit " ) , " &Exit " , this , SLOT ( onExitClicked ( bool ) ) ) ;
2016-08-28 21:06:23 +03:00
2016-09-18 20:20:37 +03:00
menu = menuBar ( ) - > addMenu ( " &View " ) ;
2016-08-28 21:06:23 +03:00
2016-09-20 01:24:53 +03:00
menu - > addAction ( QIcon ( " :/Expand " ) , " Expand all " , this , SLOT ( onExpandAllClicked ( bool ) ) ) ;
menu - > addAction ( QIcon ( " :/Collapse " ) , " Collapse all " , this , SLOT ( onCollapseAllClicked ( bool ) ) ) ;
2016-08-28 21:06:23 +03:00
menu - > addSeparator ( ) ;
2016-09-18 20:20:37 +03:00
auto action = menu - > addAction ( " Draw items' borders " ) ;
2016-08-28 21:06:23 +03:00
action - > setCheckable ( true ) ;
2016-08-30 22:51:18 +03:00
action - > setChecked ( EASY_GLOBALS . draw_graphics_items_borders ) ;
2016-08-28 21:06:23 +03:00
connect ( action , & QAction : : triggered , this , & This : : onDrawBordersChanged ) ;
action = menu - > addAction ( " Collapse items on tree reset " ) ;
action - > setCheckable ( true ) ;
2016-08-30 22:51:18 +03:00
action - > setChecked ( EASY_GLOBALS . collapse_items_on_tree_close ) ;
2016-08-28 21:06:23 +03:00
connect ( action , & QAction : : triggered , this , & This : : onCollapseItemsAfterCloseChanged ) ;
action = menu - > addAction ( " Expand all on file open " ) ;
action - > setCheckable ( true ) ;
2016-08-30 22:51:18 +03:00
action - > setChecked ( EASY_GLOBALS . all_items_expanded_by_default ) ;
2016-08-28 21:06:23 +03:00
connect ( action , & QAction : : triggered , this , & This : : onAllItemsExpandedByDefaultChange ) ;
action = menu - > addAction ( " Bind scene and tree expand " ) ;
action - > setCheckable ( true ) ;
2016-08-30 22:51:18 +03:00
action - > setChecked ( EASY_GLOBALS . bind_scene_and_tree_expand_status ) ;
2016-08-28 21:06:23 +03:00
connect ( action , & QAction : : triggered , this , & This : : onBindExpandStatusChange ) ;
2016-09-24 00:00:31 +03:00
action = menu - > addAction ( " Draw event indicators " ) ;
2016-09-23 23:50:43 +03:00
action - > setCheckable ( true ) ;
action - > setChecked ( EASY_GLOBALS . enable_event_indicators ) ;
connect ( action , & QAction : : triggered , this , & This : : onEventIndicatorsChange ) ;
2016-08-28 21:06:23 +03:00
menu - > addSeparator ( ) ;
auto submenu = menu - > addMenu ( " Chronometer text " ) ;
auto actionGroup = new QActionGroup ( this ) ;
actionGroup - > setExclusive ( true ) ;
action = new QAction ( " At top " , actionGroup ) ;
action - > setCheckable ( true ) ;
action - > setData ( static_cast < int > ( : : profiler_gui : : ChronoTextPosition_Top ) ) ;
2016-08-30 22:51:18 +03:00
if ( EASY_GLOBALS . chrono_text_position = = : : profiler_gui : : ChronoTextPosition_Top )
2016-08-28 21:06:23 +03:00
action - > setChecked ( true ) ;
submenu - > addAction ( action ) ;
connect ( action , & QAction : : triggered , this , & This : : onChronoTextPosChanged ) ;
action = new QAction ( " At center " , actionGroup ) ;
action - > setCheckable ( true ) ;
action - > setData ( static_cast < int > ( : : profiler_gui : : ChronoTextPosition_Center ) ) ;
2016-08-30 22:51:18 +03:00
if ( EASY_GLOBALS . chrono_text_position = = : : profiler_gui : : ChronoTextPosition_Center )
2016-08-28 21:06:23 +03:00
action - > setChecked ( true ) ;
submenu - > addAction ( action ) ;
connect ( action , & QAction : : triggered , this , & This : : onChronoTextPosChanged ) ;
action = new QAction ( " At bottom " , actionGroup ) ;
action - > setCheckable ( true ) ;
action - > setData ( static_cast < int > ( : : profiler_gui : : ChronoTextPosition_Bottom ) ) ;
2016-08-30 22:51:18 +03:00
if ( EASY_GLOBALS . chrono_text_position = = : : profiler_gui : : ChronoTextPosition_Bottom )
2016-08-28 21:06:23 +03:00
action - > setChecked ( true ) ;
submenu - > addAction ( action ) ;
connect ( action , & QAction : : triggered , this , & This : : onChronoTextPosChanged ) ;
2016-09-18 20:20:37 +03:00
menu = menuBar ( ) - > addMenu ( " &Settings " ) ;
2016-09-17 15:39:31 +03:00
action = menu - > addAction ( " Statistics enabled " ) ;
2016-09-14 23:13:38 +03:00
action - > setCheckable ( true ) ;
action - > setChecked ( EASY_GLOBALS . enable_statistics ) ;
connect ( action , & QAction : : triggered , this , & This : : onEnableDisableStatistics ) ;
if ( EASY_GLOBALS . enable_statistics )
{
auto f = action - > font ( ) ;
f . setBold ( true ) ;
action - > setFont ( f ) ;
2016-09-15 23:56:20 +03:00
SET_ICON ( action , " :/Stats " ) ;
2016-09-14 23:13:38 +03:00
}
else
{
action - > setText ( " Statistics disabled " ) ;
2016-09-15 23:56:20 +03:00
SET_ICON ( action , " :/Stats-off " ) ;
2016-09-14 23:13:38 +03:00
}
2016-08-28 21:06:23 +03:00
submenu = menu - > addMenu ( " &Encoding " ) ;
actionGroup = new QActionGroup ( this ) ;
actionGroup - > setExclusive ( true ) ;
auto default_codec_mib = QTextCodec : : codecForLocale ( ) - > mibEnum ( ) ;
foreach ( int mib , QTextCodec : : availableMibs ( ) )
{
auto codec = QTextCodec : : codecForMib ( mib ) - > name ( ) ;
action = new QAction ( codec , actionGroup ) ;
action - > setCheckable ( true ) ;
if ( mib = = default_codec_mib )
action - > setChecked ( true ) ;
submenu - > addAction ( action ) ;
connect ( action , & QAction : : triggered , this , & This : : onEncodingChanged ) ;
}
2016-09-18 20:20:37 +03:00
2016-08-28 21:06:23 +03:00
connect ( graphicsView - > view ( ) , & EasyGraphicsView : : intervalChanged , treeWidget , & EasyTreeWidget : : setTreeBlocks ) ;
connect ( & m_readerTimer , & QTimer : : timeout , this , & This : : onFileReaderTimeout ) ;
2016-09-25 11:49:49 +03:00
connect ( & m_listenerTimer , & QTimer : : timeout , this , & This : : onListenerTimerTimeout ) ;
2016-09-16 02:11:11 +03:00
2016-08-28 21:06:23 +03:00
m_progress = new QProgressDialog ( " Loading file... " , " Cancel " , 0 , 100 , this ) ;
m_progress - > setFixedWidth ( 300 ) ;
m_progress - > setWindowTitle ( " EasyProfiler " ) ;
m_progress - > setModal ( true ) ;
m_progress - > setValue ( 100 ) ;
//m_progress->hide();
connect ( m_progress , & QProgressDialog : : canceled , this , & This : : onFileReaderCancel ) ;
loadGeometry ( ) ;
if ( QCoreApplication : : arguments ( ) . size ( ) > 1 )
{
auto opened_filename = QCoreApplication : : arguments ( ) . at ( 1 ) ;
loadFile ( opened_filename ) ;
}
2016-09-16 22:51:15 +03:00
2016-09-25 11:49:49 +03:00
connect ( & EASY_GLOBALS . events , & : : profiler_gui : : EasyGlobalSignals : : blockStatusChanged , this , & This : : onBlockStatusChange ) ;
connect ( & EASY_GLOBALS . events , & : : profiler_gui : : EasyGlobalSignals : : blocksRefreshRequired , this , & This : : onGetBlockDescriptionsClicked ) ;
2016-08-28 21:06:23 +03:00
}
EasyMainWindow : : ~ EasyMainWindow ( )
{
delete m_progress ;
}
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow : : onOpenFileClicked ( bool )
{
auto filename = QFileDialog : : getOpenFileName ( this , " Open profiler log " , m_lastFile , " Profiler Log File (*.prof);;All Files (*.*) " ) ;
2016-09-15 23:56:20 +03:00
if ( ! filename . isEmpty ( ) )
loadFile ( filename ) ;
2016-08-28 21:06:23 +03:00
}
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow : : loadFile ( const QString & filename )
{
const auto i = filename . lastIndexOf ( QChar ( ' / ' ) ) ;
const auto j = filename . lastIndexOf ( QChar ( ' \\ ' ) ) ;
m_progress - > setLabelText ( QString ( " Loading %1... " ) . arg ( filename . mid ( : : std : : max ( i , j ) + 1 ) ) ) ;
m_progress - > setValue ( 0 ) ;
m_progress - > show ( ) ;
m_readerTimer . start ( LOADER_TIMER_INTERVAL ) ;
m_reader . load ( filename ) ;
}
2016-09-25 11:49:49 +03:00
void EasyMainWindow : : readStream ( : : std : : stringstream & data )
{
m_progress - > setLabelText ( tr ( " Reading from stream... " ) ) ;
m_progress - > setValue ( 0 ) ;
m_progress - > show ( ) ;
m_readerTimer . start ( LOADER_TIMER_INTERVAL ) ;
m_reader . load ( data ) ;
}
2016-08-28 21:06:23 +03:00
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow : : onReloadFileClicked ( bool )
{
if ( m_lastFile . isEmpty ( ) )
return ;
loadFile ( m_lastFile ) ;
}
//////////////////////////////////////////////////////////////////////////
2016-09-21 22:09:04 +03:00
void EasyMainWindow : : onDeleteClicked ( bool )
{
static_cast < EasyTreeWidget * > ( m_treeWidget - > widget ( ) ) - > clearSilent ( true ) ;
static_cast < EasyGraphicsViewWidget * > ( m_graphicsView - > widget ( ) ) - > clear ( ) ;
# if EASY_GUI_USE_DESCRIPTORS_DOCK_WINDOW != 0
static_cast < EasyDescWidget * > ( m_descTreeWidget - > widget ( ) ) - > clear ( ) ;
# endif
if ( m_dialogDescTree ! = nullptr )
m_dialogDescTree - > clear ( ) ;
EASY_GLOBALS . selected_thread = 0 ;
: : profiler_gui : : set_max ( EASY_GLOBALS . selected_block ) ;
EASY_GLOBALS . profiler_blocks . clear ( ) ;
EASY_GLOBALS . descriptors . clear ( ) ;
EASY_GLOBALS . gui_blocks . clear ( ) ;
m_serializedBlocks . clear ( ) ;
m_serializedDescriptors . clear ( ) ;
}
//////////////////////////////////////////////////////////////////////////
2016-08-28 21:06:23 +03:00
void EasyMainWindow : : onExitClicked ( bool )
{
close ( ) ;
}
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow : : onEncodingChanged ( bool )
{
auto _sender = qobject_cast < QAction * > ( sender ( ) ) ;
auto name = _sender - > text ( ) ;
QTextCodec * codec = QTextCodec : : codecForName ( name . toStdString ( ) . c_str ( ) ) ;
QTextCodec : : setCodecForLocale ( codec ) ;
}
void EasyMainWindow : : onChronoTextPosChanged ( bool )
{
auto _sender = qobject_cast < QAction * > ( sender ( ) ) ;
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . chrono_text_position = static_cast < : : profiler_gui : : ChronometerTextPosition > ( _sender - > data ( ) . toInt ( ) ) ;
2016-09-24 00:00:31 +03:00
static_cast < EasyGraphicsViewWidget * > ( m_graphicsView - > widget ( ) ) - > view ( ) - > scene ( ) - > update ( ) ;
2016-08-28 21:06:23 +03:00
}
2016-09-23 23:50:43 +03:00
void EasyMainWindow : : onEventIndicatorsChange ( bool _checked )
{
EASY_GLOBALS . enable_event_indicators = _checked ;
static_cast < EasyGraphicsViewWidget * > ( m_graphicsView - > widget ( ) ) - > view ( ) - > scene ( ) - > update ( ) ;
}
2016-09-14 23:13:38 +03:00
void EasyMainWindow : : onEnableDisableStatistics ( bool _checked )
{
EASY_GLOBALS . enable_statistics = _checked ;
auto action = qobject_cast < QAction * > ( sender ( ) ) ;
if ( action ! = nullptr )
{
auto f = action - > font ( ) ;
f . setBold ( _checked ) ;
action - > setFont ( f ) ;
if ( _checked )
{
action - > setText ( " Statistics enabled " ) ;
2016-09-15 23:56:20 +03:00
SET_ICON ( action , " :/Stats " ) ;
2016-09-14 23:13:38 +03:00
}
else
{
action - > setText ( " Statistics disabled " ) ;
2016-09-15 23:56:20 +03:00
SET_ICON ( action , " :/Stats-off " ) ;
2016-09-14 23:13:38 +03:00
}
}
}
2016-08-28 21:06:23 +03:00
void EasyMainWindow : : onDrawBordersChanged ( bool _checked )
{
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . draw_graphics_items_borders = _checked ;
2016-09-24 00:00:31 +03:00
static_cast < EasyGraphicsViewWidget * > ( m_graphicsView - > widget ( ) ) - > view ( ) - > scene ( ) - > update ( ) ;
2016-08-28 21:06:23 +03:00
}
void EasyMainWindow : : onCollapseItemsAfterCloseChanged ( bool _checked )
{
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . collapse_items_on_tree_close = _checked ;
2016-08-28 21:06:23 +03:00
}
void EasyMainWindow : : onAllItemsExpandedByDefaultChange ( bool _checked )
{
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . all_items_expanded_by_default = _checked ;
2016-08-28 21:06:23 +03:00
}
void EasyMainWindow : : onBindExpandStatusChange ( bool _checked )
{
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . bind_scene_and_tree_expand_status = _checked ;
2016-08-28 21:06:23 +03:00
}
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow : : onExpandAllClicked ( bool )
{
2016-08-30 22:51:18 +03:00
for ( auto & block : EASY_GLOBALS . gui_blocks )
2016-08-28 21:06:23 +03:00
block . expanded = true ;
2016-08-30 22:51:18 +03:00
emit EASY_GLOBALS . events . itemsExpandStateChanged ( ) ;
2016-08-28 21:06:23 +03:00
auto tree = static_cast < EasyTreeWidget * > ( m_treeWidget - > widget ( ) ) ;
const QSignalBlocker b ( tree ) ;
tree - > expandAll ( ) ;
}
void EasyMainWindow : : onCollapseAllClicked ( bool )
{
2016-08-30 22:51:18 +03:00
for ( auto & block : EASY_GLOBALS . gui_blocks )
2016-08-28 21:06:23 +03:00
block . expanded = false ;
2016-08-30 22:51:18 +03:00
emit EASY_GLOBALS . events . itemsExpandStateChanged ( ) ;
2016-08-28 21:06:23 +03:00
auto tree = static_cast < EasyTreeWidget * > ( m_treeWidget - > widget ( ) ) ;
const QSignalBlocker b ( tree ) ;
tree - > collapseAll ( ) ;
}
//////////////////////////////////////////////////////////////////////////
2016-09-17 15:39:31 +03:00
void EasyMainWindow : : onEditBlocksClicked ( bool )
{
2016-09-17 18:43:06 +03:00
if ( m_descTreeDialog ! = nullptr )
{
m_descTreeDialog - > raise ( ) ;
return ;
}
2016-09-17 15:39:31 +03:00
2016-09-17 18:43:06 +03:00
m_descTreeDialog = new QDialog ( ) ;
2016-09-25 11:49:49 +03:00
m_descTreeDialog - > setAttribute ( Qt : : WA_DeleteOnClose , true ) ;
2016-09-17 18:43:06 +03:00
m_descTreeDialog - > setWindowTitle ( " EasyProfiler " ) ;
m_descTreeDialog - > resize ( 800 , 600 ) ;
connect ( m_descTreeDialog , & QDialog : : finished , this , & This : : onDescTreeDialogClose ) ;
auto l = new QVBoxLayout ( m_descTreeDialog ) ;
2016-09-25 11:49:49 +03:00
m_dialogDescTree = new EasyDescWidget ( m_descTreeDialog ) ;
2016-09-17 18:43:06 +03:00
l - > addWidget ( m_dialogDescTree ) ;
m_descTreeDialog - > setLayout ( l ) ;
2016-09-25 11:49:49 +03:00
m_dialogDescTree - > build ( ) ;
2016-09-17 18:43:06 +03:00
m_descTreeDialog - > show ( ) ;
}
void EasyMainWindow : : onDescTreeDialogClose ( int )
{
disconnect ( m_descTreeDialog , & QDialog : : finished , this , & This : : onDescTreeDialogClose ) ;
2016-09-25 11:49:49 +03:00
m_dialogDescTree = nullptr ;
2016-09-17 18:43:06 +03:00
m_descTreeDialog = nullptr ;
2016-09-17 15:39:31 +03:00
}
//////////////////////////////////////////////////////////////////////////
2016-08-28 21:06:23 +03:00
void EasyMainWindow : : closeEvent ( QCloseEvent * close_event )
{
saveSettingsAndGeometry ( ) ;
2016-09-25 11:49:49 +03:00
if ( m_descTreeDialog ! = nullptr )
{
m_descTreeDialog - > reject ( ) ;
m_descTreeDialog = nullptr ;
m_dialogDescTree = nullptr ;
}
2016-08-28 21:06:23 +03:00
Parent : : closeEvent ( close_event ) ;
}
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow : : loadSettings ( )
{
QSettings settings ( : : profiler_gui : : ORGANAZATION_NAME , : : profiler_gui : : APPLICATION_NAME ) ;
settings . beginGroup ( " main " ) ;
auto last_file = settings . value ( " last_file " ) ;
if ( ! last_file . isNull ( ) )
m_lastFile = last_file . toString ( ) ;
2016-09-27 21:57:46 +03:00
auto last_addr = settings . value ( " ip_address " ) ;
if ( ! last_addr . isNull ( ) )
m_lastAddress = last_addr . toString ( ) ;
auto last_port = settings . value ( " port " ) ;
if ( ! last_port . isNull ( ) )
m_lastPort = ( uint16_t ) last_port . toUInt ( ) ;
2016-08-28 21:06:23 +03:00
auto val = settings . value ( " chrono_text_position " ) ;
if ( ! val . isNull ( ) )
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . chrono_text_position = static_cast < : : profiler_gui : : ChronometerTextPosition > ( val . toInt ( ) ) ;
2016-08-28 21:06:23 +03:00
auto flag = settings . value ( " draw_graphics_items_borders " ) ;
if ( ! flag . isNull ( ) )
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . draw_graphics_items_borders = flag . toBool ( ) ;
2016-08-28 21:06:23 +03:00
flag = settings . value ( " collapse_items_on_tree_close " ) ;
if ( ! flag . isNull ( ) )
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . collapse_items_on_tree_close = flag . toBool ( ) ;
2016-08-28 21:06:23 +03:00
flag = settings . value ( " all_items_expanded_by_default " ) ;
if ( ! flag . isNull ( ) )
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . all_items_expanded_by_default = flag . toBool ( ) ;
2016-08-28 21:06:23 +03:00
flag = settings . value ( " bind_scene_and_tree_expand_status " ) ;
if ( ! flag . isNull ( ) )
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . bind_scene_and_tree_expand_status = flag . toBool ( ) ;
2016-09-23 23:50:43 +03:00
flag = settings . value ( " enable_event_indicators " ) ;
if ( ! flag . isNull ( ) )
EASY_GLOBALS . enable_event_indicators = flag . toBool ( ) ;
2016-08-28 21:06:23 +03:00
2016-09-14 23:13:38 +03:00
flag = settings . value ( " enable_statistics " ) ;
if ( ! flag . isNull ( ) )
EASY_GLOBALS . enable_statistics = flag . toBool ( ) ;
2016-08-28 21:06:23 +03:00
QString encoding = settings . value ( " encoding " , " UTF-8 " ) . toString ( ) ;
auto default_codec_mib = QTextCodec : : codecForName ( encoding . toStdString ( ) . c_str ( ) ) - > mibEnum ( ) ;
auto default_codec = QTextCodec : : codecForMib ( default_codec_mib ) ;
QTextCodec : : setCodecForLocale ( default_codec ) ;
settings . endGroup ( ) ;
}
void EasyMainWindow : : loadGeometry ( )
{
QSettings settings ( : : profiler_gui : : ORGANAZATION_NAME , : : profiler_gui : : APPLICATION_NAME ) ;
settings . beginGroup ( " main " ) ;
2016-09-17 18:43:06 +03:00
2016-08-28 21:06:23 +03:00
auto geometry = settings . value ( " geometry " ) . toByteArray ( ) ;
if ( ! geometry . isEmpty ( ) )
restoreGeometry ( geometry ) ;
2016-09-17 18:43:06 +03:00
auto state = settings . value ( " windowState " ) . toByteArray ( ) ;
if ( ! state . isEmpty ( ) )
restoreState ( state ) ;
2016-08-28 21:06:23 +03:00
settings . endGroup ( ) ;
}
void EasyMainWindow : : saveSettingsAndGeometry ( )
{
2016-09-06 22:23:55 +03:00
QSettings settings ( : : profiler_gui : : ORGANAZATION_NAME , : : profiler_gui : : APPLICATION_NAME ) ;
settings . beginGroup ( " main " ) ;
2016-08-28 21:06:23 +03:00
2016-09-06 22:23:55 +03:00
settings . setValue ( " geometry " , this - > saveGeometry ( ) ) ;
2016-09-17 18:43:06 +03:00
settings . setValue ( " windowState " , this - > saveState ( ) ) ;
2016-08-28 21:06:23 +03:00
settings . setValue ( " last_file " , m_lastFile ) ;
2016-09-27 21:57:46 +03:00
settings . setValue ( " ip_address " , m_lastAddress ) ;
settings . setValue ( " port " , ( quint32 ) m_lastPort ) ;
2016-08-30 22:51:18 +03:00
settings . setValue ( " chrono_text_position " , static_cast < int > ( EASY_GLOBALS . chrono_text_position ) ) ;
settings . setValue ( " draw_graphics_items_borders " , EASY_GLOBALS . draw_graphics_items_borders ) ;
settings . setValue ( " collapse_items_on_tree_close " , EASY_GLOBALS . collapse_items_on_tree_close ) ;
settings . setValue ( " all_items_expanded_by_default " , EASY_GLOBALS . all_items_expanded_by_default ) ;
settings . setValue ( " bind_scene_and_tree_expand_status " , EASY_GLOBALS . bind_scene_and_tree_expand_status ) ;
2016-09-23 23:50:43 +03:00
settings . setValue ( " enable_event_indicators " , EASY_GLOBALS . enable_event_indicators ) ;
2016-09-14 23:13:38 +03:00
settings . setValue ( " enable_statistics " , EASY_GLOBALS . enable_statistics ) ;
2016-08-28 21:06:23 +03:00
settings . setValue ( " encoding " , QTextCodec : : codecForLocale ( ) - > name ( ) ) ;
2016-09-06 22:23:55 +03:00
settings . endGroup ( ) ;
2016-08-28 21:06:23 +03:00
}
//////////////////////////////////////////////////////////////////////////
2016-09-25 11:49:49 +03:00
void EasyMainWindow : : onListenerTimerTimeout ( )
{
if ( ! m_listener . connected ( ) )
m_listenerDialog - > reject ( ) ;
}
void EasyMainWindow : : onListenerDialogClose ( int )
2016-09-16 02:11:11 +03:00
{
2016-09-25 11:49:49 +03:00
m_listenerTimer . stop ( ) ;
disconnect ( m_listenerDialog , & QDialog : : finished , this , & This : : onListenerDialogClose ) ;
m_listenerDialog = nullptr ;
switch ( m_listener . regime ( ) )
{
case LISTENER_CAPTURE :
{
m_listenerDialog = new QMessageBox ( QMessageBox : : Information , " Receiving data... " , " This process may take some time. " , QMessageBox : : NoButton , this ) ;
m_listenerDialog - > setAttribute ( Qt : : WA_DeleteOnClose , true ) ;
m_listenerDialog - > show ( ) ;
m_listener . stopCapture ( ) ;
m_listenerDialog - > reject ( ) ;
m_listenerDialog = nullptr ;
if ( m_listener . size ( ) ! = 0 )
{
readStream ( m_listener . data ( ) ) ;
m_listener . clearData ( ) ;
}
break ;
}
case LISTENER_DESCRIBE :
{
break ;
}
default :
return ;
2016-09-16 02:11:11 +03:00
}
2016-09-25 11:49:49 +03:00
if ( ! m_listener . connected ( ) )
{
QMessageBox : : warning ( this , " Warning " , " Application was disconnected " , QMessageBox : : Close ) ;
EASY_GLOBALS . connected = false ;
m_captureAction - > setEnabled ( false ) ;
SET_ICON ( m_connectAction , " :/Connection " ) ;
emit EASY_GLOBALS . events . connectionChanged ( false ) ;
2016-09-16 02:11:11 +03:00
}
}
2016-09-25 11:49:49 +03:00
//////////////////////////////////////////////////////////////////////////
2016-08-28 21:06:23 +03:00
void EasyMainWindow : : onFileReaderTimeout ( )
{
if ( m_reader . done ( ) )
{
auto nblocks = m_reader . size ( ) ;
if ( nblocks ! = 0 )
{
static_cast < EasyTreeWidget * > ( m_treeWidget - > widget ( ) ) - > clearSilent ( true ) ;
: : profiler : : SerializedData serialized_blocks , serialized_descriptors ;
: : profiler : : descriptors_list_t descriptors ;
2016-08-30 22:51:18 +03:00
: : profiler : : blocks_t blocks ;
: : profiler : : thread_blocks_tree_t threads_map ;
2016-08-28 21:06:23 +03:00
QString filename ;
2016-08-30 22:51:18 +03:00
m_reader . get ( serialized_blocks , serialized_descriptors , descriptors , blocks , threads_map , filename ) ;
2016-08-28 21:06:23 +03:00
2016-08-30 22:51:18 +03:00
if ( threads_map . size ( ) > 0xff )
2016-08-28 21:06:23 +03:00
{
2016-09-25 11:49:49 +03:00
if ( m_reader . isFile ( ) )
qWarning ( ) < < " Warning: file " < < filename < < " contains " < < threads_map . size ( ) < < " threads! " ;
else
qWarning ( ) < < " Warning: input stream contains " < < threads_map . size ( ) < < " threads! " ;
2016-08-28 21:06:23 +03:00
qWarning ( ) < < " Warning: Currently, maximum number of displayed threads is 255! Some threads will not be displayed. " ;
}
2016-09-25 11:49:49 +03:00
if ( m_reader . isFile ( ) )
m_lastFile = : : std : : move ( filename ) ;
2016-08-28 21:06:23 +03:00
m_serializedBlocks = : : std : : move ( serialized_blocks ) ;
m_serializedDescriptors = : : std : : move ( serialized_descriptors ) ;
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . selected_thread = 0 ;
: : profiler_gui : : set_max ( EASY_GLOBALS . selected_block ) ;
EASY_GLOBALS . profiler_blocks . swap ( threads_map ) ;
EASY_GLOBALS . descriptors . swap ( descriptors ) ;
2016-09-01 22:24:13 +03:00
EASY_GLOBALS . gui_blocks . clear ( ) ;
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . gui_blocks . resize ( nblocks ) ;
memset ( EASY_GLOBALS . gui_blocks . data ( ) , 0 , sizeof ( : : profiler_gui : : EasyBlock ) * nblocks ) ;
for ( decltype ( nblocks ) i = 0 ; i < nblocks ; + + i ) {
auto & guiblock = EASY_GLOBALS . gui_blocks [ i ] ;
guiblock . tree = : : std : : move ( blocks [ i ] ) ;
: : profiler_gui : : set_max ( guiblock . tree_item ) ;
}
static_cast < EasyGraphicsViewWidget * > ( m_graphicsView - > widget ( ) ) - > view ( ) - > setTree ( EASY_GLOBALS . profiler_blocks ) ;
2016-09-17 15:39:31 +03:00
2016-09-17 18:43:06 +03:00
# if EASY_GUI_USE_DESCRIPTORS_DOCK_WINDOW != 0
static_cast < EasyDescWidget * > ( m_descTreeWidget - > widget ( ) ) - > build ( ) ;
# endif
if ( m_dialogDescTree ! = nullptr )
m_dialogDescTree - > build ( ) ;
2016-08-28 21:06:23 +03:00
}
2016-09-25 11:49:49 +03:00
else
{
2016-09-27 22:28:04 +03:00
QMessageBox : : warning ( this , " Warning " , QString ( " Can not read profiled blocks. \n \n Reason: \n %1 " ) . arg ( m_reader . getError ( ) ) , QMessageBox : : Close ) ;
2016-09-25 11:49:49 +03:00
}
2016-08-28 21:06:23 +03:00
m_reader . interrupt ( ) ;
m_readerTimer . stop ( ) ;
m_progress - > setValue ( 100 ) ;
//m_progress->hide();
2016-08-30 22:51:18 +03:00
if ( EASY_GLOBALS . all_items_expanded_by_default )
2016-08-28 21:06:23 +03:00
{
onExpandAllClicked ( true ) ;
}
}
else
{
m_progress - > setValue ( m_reader . progress ( ) ) ;
}
}
void EasyMainWindow : : onFileReaderCancel ( )
{
m_readerTimer . stop ( ) ;
m_reader . interrupt ( ) ;
m_progress - > setValue ( 100 ) ;
//m_progress->hide();
}
//////////////////////////////////////////////////////////////////////////
EasyFileReader : : EasyFileReader ( )
{
}
EasyFileReader : : ~ EasyFileReader ( )
{
interrupt ( ) ;
}
2016-09-25 11:49:49 +03:00
const bool EasyFileReader : : isFile ( ) const
{
return m_isFile ;
}
2016-08-28 21:06:23 +03:00
bool EasyFileReader : : done ( ) const
{
2016-09-21 22:09:04 +03:00
return m_bDone . load ( : : std : : memory_order_acquire ) ;
2016-08-28 21:06:23 +03:00
}
int EasyFileReader : : progress ( ) const
{
2016-09-21 22:09:04 +03:00
return m_progress . load ( : : std : : memory_order_acquire ) ;
2016-08-28 21:06:23 +03:00
}
unsigned int EasyFileReader : : size ( ) const
{
2016-09-21 22:09:04 +03:00
return m_size . load ( : : std : : memory_order_acquire ) ;
2016-08-28 21:06:23 +03:00
}
const QString & EasyFileReader : : filename ( ) const
{
return m_filename ;
}
void EasyFileReader : : load ( const QString & _filename )
{
interrupt ( ) ;
2016-09-25 11:49:49 +03:00
m_isFile = true ;
2016-08-28 21:06:23 +03:00
m_filename = _filename ;
2016-09-14 23:13:38 +03:00
m_thread = : : std : : move ( : : std : : thread ( [ this ] ( bool _enableStatistics ) {
2016-09-27 22:28:04 +03:00
m_size . store ( fillTreesFromFile ( m_progress , m_filename . toStdString ( ) . c_str ( ) , m_serializedBlocks , m_serializedDescriptors , m_descriptors , m_blocks , m_blocksTree , _enableStatistics , m_errorMessage ) , : : std : : memory_order_release ) ;
2016-09-21 22:09:04 +03:00
m_progress . store ( 100 , : : std : : memory_order_release ) ;
m_bDone . store ( true , : : std : : memory_order_release ) ;
2016-09-14 23:13:38 +03:00
} , EASY_GLOBALS . enable_statistics ) ) ;
2016-08-28 21:06:23 +03:00
}
2016-09-25 11:49:49 +03:00
void EasyFileReader : : load ( : : std : : stringstream & _stream )
{
interrupt ( ) ;
m_isFile = false ;
m_filename . clear ( ) ;
m_stream . swap ( _stream ) ;
m_thread = : : std : : move ( : : std : : thread ( [ this ] ( bool _enableStatistics ) {
2016-09-27 22:28:04 +03:00
m_size . store ( fillTreesFromStream ( m_progress , m_stream , m_serializedBlocks , m_serializedDescriptors , m_descriptors , m_blocks , m_blocksTree , _enableStatistics , m_errorMessage ) , : : std : : memory_order_release ) ;
2016-09-25 11:49:49 +03:00
m_progress . store ( 100 , : : std : : memory_order_release ) ;
m_bDone . store ( true , : : std : : memory_order_release ) ;
} , EASY_GLOBALS . enable_statistics ) ) ;
}
2016-08-28 21:06:23 +03:00
void EasyFileReader : : interrupt ( )
{
2016-09-21 22:09:04 +03:00
m_progress . store ( - 100 , : : std : : memory_order_release ) ;
2016-08-28 21:06:23 +03:00
if ( m_thread . joinable ( ) )
m_thread . join ( ) ;
2016-09-21 22:09:04 +03:00
m_bDone . store ( false , : : std : : memory_order_release ) ;
m_progress . store ( 0 , : : std : : memory_order_release ) ;
m_size . store ( 0 , : : std : : memory_order_release ) ;
2016-08-28 21:06:23 +03:00
m_serializedBlocks . clear ( ) ;
m_serializedDescriptors . clear ( ) ;
m_descriptors . clear ( ) ;
2016-08-30 22:51:18 +03:00
m_blocks . clear ( ) ;
2016-08-28 21:06:23 +03:00
m_blocksTree . clear ( ) ;
2016-09-25 11:49:49 +03:00
2016-09-27 22:28:04 +03:00
{ decltype ( m_stream ) dummy ; dummy . swap ( m_stream ) ; }
{ decltype ( m_errorMessage ) dummy ; dummy . swap ( m_errorMessage ) ; }
2016-08-28 21:06:23 +03:00
}
void EasyFileReader : : get ( : : profiler : : SerializedData & _serializedBlocks , : : profiler : : SerializedData & _serializedDescriptors ,
2016-08-30 22:51:18 +03:00
: : profiler : : descriptors_list_t & _descriptors , : : profiler : : blocks_t & _blocks , : : profiler : : thread_blocks_tree_t & _tree ,
QString & _filename )
2016-08-28 21:06:23 +03:00
{
if ( done ( ) )
{
m_serializedBlocks . swap ( _serializedBlocks ) ;
m_serializedDescriptors . swap ( _serializedDescriptors ) ;
2016-08-30 22:51:18 +03:00
: : profiler : : descriptors_list_t ( : : std : : move ( m_descriptors ) ) . swap ( _descriptors ) ;
m_blocks . swap ( _blocks ) ;
2016-08-28 21:06:23 +03:00
m_blocksTree . swap ( _tree ) ;
m_filename . swap ( _filename ) ;
}
}
2016-09-27 22:28:04 +03:00
QString EasyFileReader : : getError ( )
{
return QString ( m_errorMessage . str ( ) . c_str ( ) ) ;
}
2016-08-28 21:06:23 +03:00
//////////////////////////////////////////////////////////////////////////
2016-09-18 19:02:12 +03:00
void EasyMainWindow : : onConnectClicked ( bool )
{
2016-09-25 11:49:49 +03:00
if ( EASY_GLOBALS . connected )
2016-09-18 19:02:12 +03:00
return ;
2016-09-18 20:20:37 +03:00
2016-09-27 21:57:46 +03:00
m_lastAddress = m_ipEdit - > text ( ) ;
m_lastPort = m_portEdit - > text ( ) . toUShort ( ) ;
if ( ! m_listener . connect ( m_lastAddress . toStdString ( ) . c_str ( ) , m_lastPort ) )
2016-09-18 19:02:12 +03:00
{
QMessageBox : : warning ( this , " Warning " , " Cannot connect with application " , QMessageBox : : Close ) ;
return ;
}
2016-09-18 20:20:37 +03:00
qInfo ( ) < < " Connected successfully " ;
2016-09-25 11:49:49 +03:00
EASY_GLOBALS . connected = true ;
2016-09-18 20:20:37 +03:00
m_captureAction - > setEnabled ( true ) ;
SET_ICON ( m_connectAction , " :/Connection-on " ) ;
2016-09-25 11:49:49 +03:00
emit EASY_GLOBALS . events . connectionChanged ( true ) ;
2016-09-18 19:02:12 +03:00
}
void EasyMainWindow : : onCaptureClicked ( bool )
{
2016-09-25 11:49:49 +03:00
if ( ! EASY_GLOBALS . connected )
2016-09-18 19:02:12 +03:00
{
QMessageBox : : warning ( this , " Warning " , " No connection with profiling app " , QMessageBox : : Close ) ;
return ;
}
2016-09-25 11:49:49 +03:00
if ( m_listener . regime ( ) ! = LISTENER_IDLE )
{
if ( m_listener . regime ( ) = = LISTENER_CAPTURE )
QMessageBox : : warning ( this , " Warning " , " Already capturing frames. \n Finish old capturing session first. " , QMessageBox : : Close ) ;
else
QMessageBox : : warning ( this , " Warning " , " Capturing blocks description. \n Finish old capturing session first. " , QMessageBox : : Close ) ;
return ;
}
2016-09-18 20:20:37 +03:00
2016-09-25 11:49:49 +03:00
m_listener . startCapture ( ) ;
m_listenerTimer . start ( 250 ) ;
2016-09-18 20:20:37 +03:00
2016-09-25 11:49:49 +03:00
m_listenerDialog = new QMessageBox ( QMessageBox : : Information , " Capturing frames... " , " Close this dialog to stop capturing. " , QMessageBox : : Close , this ) ;
m_listenerDialog - > setAttribute ( Qt : : WA_DeleteOnClose , true ) ;
connect ( m_listenerDialog , & QDialog : : finished , this , & This : : onListenerDialogClose ) ;
m_listenerDialog - > show ( ) ;
}
2016-09-18 20:20:37 +03:00
2016-09-25 11:49:49 +03:00
void EasyMainWindow : : onGetBlockDescriptionsClicked ( bool )
{
if ( ! EASY_GLOBALS . connected )
{
QMessageBox : : warning ( this , " Warning " , " No connection with profiling app " , QMessageBox : : Close ) ;
return ;
}
if ( m_listener . regime ( ) ! = LISTENER_IDLE )
{
if ( m_listener . regime ( ) = = LISTENER_DESCRIBE )
QMessageBox : : warning ( this , " Warning " , " Already capturing blocks description. \n Finish old capturing session first. " , QMessageBox : : Close ) ;
else
QMessageBox : : warning ( this , " Warning " , " Capturing capturing frames. \n Finish old capturing session first. " , QMessageBox : : Close ) ;
return ;
}
m_listenerDialog = new QMessageBox ( QMessageBox : : Information , " Waiting for blocks... " , " This may take some time. " , QMessageBox : : NoButton , this ) ;
m_listenerDialog - > setAttribute ( Qt : : WA_DeleteOnClose , true ) ;
m_listenerDialog - > show ( ) ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
m_listener . requestBlocksDescription ( ) ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
m_listenerDialog - > reject ( ) ;
m_listenerDialog = nullptr ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
if ( m_listener . size ( ) ! = 0 )
2016-09-18 19:02:12 +03:00
{
2016-09-25 11:49:49 +03:00
// Read descriptions from stream
decltype ( EASY_GLOBALS . descriptors ) descriptors ;
decltype ( m_serializedDescriptors ) serializedDescriptors ;
2016-09-27 22:28:04 +03:00
: : std : : stringstream errorMessage ;
if ( readDescriptionsFromStream ( m_listener . data ( ) , serializedDescriptors , descriptors , errorMessage ) )
2016-09-25 11:49:49 +03:00
{
if ( EASY_GLOBALS . descriptors . size ( ) > descriptors . size ( ) )
onDeleteClicked ( true ) ; // Clear all contents because new descriptors list conflicts with old one
EASY_GLOBALS . descriptors . swap ( descriptors ) ;
m_serializedDescriptors . swap ( serializedDescriptors ) ;
if ( m_descTreeDialog ! = nullptr )
{
# if EASY_GUI_USE_DESCRIPTORS_DOCK_WINDOW != 0
static_cast < EasyDescWidget * > ( m_descTreeWidget - > widget ( ) ) - > build ( ) ;
# endif
m_dialogDescTree - > build ( ) ;
m_descTreeDialog - > raise ( ) ;
}
else
{
onEditBlocksClicked ( true ) ;
}
}
2016-09-27 22:28:04 +03:00
else
{
QMessageBox : : warning ( this , " Warning " , QString ( " Can not read blocks description from stream. \n \n Reason: \n %1 " ) . arg ( errorMessage . str ( ) . c_str ( ) ) , QMessageBox : : Close ) ;
}
2016-09-25 11:49:49 +03:00
m_listener . clearData ( ) ;
}
if ( ! m_listener . connected ( ) )
{
QMessageBox : : warning ( this , " Warning " , " Application was disconnected " , QMessageBox : : Close ) ;
EASY_GLOBALS . connected = false ;
2016-09-18 20:20:37 +03:00
m_captureAction - > setEnabled ( false ) ;
SET_ICON ( m_connectAction , " :/Connection " ) ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
emit EASY_GLOBALS . events . connectionChanged ( false ) ;
}
2016-09-18 19:02:12 +03:00
}
2016-09-25 11:49:49 +03:00
//////////////////////////////////////////////////////////////////////////
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
void EasyMainWindow : : onBlockStatusChange ( : : profiler : : block_id_t _id , : : profiler : : EasyBlockStatus _status )
{
if ( EASY_GLOBALS . connected )
m_listener . sendBlockStatus ( _id , _status ) ;
2016-09-18 19:02:12 +03:00
}
2016-09-25 11:49:49 +03:00
//////////////////////////////////////////////////////////////////////////
EasySocketListener : : EasySocketListener ( ) : m_receivedSize ( 0 ) , m_regime ( LISTENER_IDLE )
{
m_bInterrupt = ATOMIC_VAR_INIT ( false ) ;
m_bConnected = ATOMIC_VAR_INIT ( false ) ;
}
EasySocketListener : : ~ EasySocketListener ( )
{
m_bInterrupt . store ( true , : : std : : memory_order_release ) ;
if ( m_thread . joinable ( ) )
m_thread . join ( ) ;
}
bool EasySocketListener : : connected ( ) const
{
return m_bConnected . load ( : : std : : memory_order_acquire ) ;
}
EasyListenerRegime EasySocketListener : : regime ( ) const
{
return m_regime ;
}
uint64_t EasySocketListener : : size ( ) const
{
return m_receivedSize ;
}
: : std : : stringstream & EasySocketListener : : data ( )
{
return m_receivedData ;
}
void EasySocketListener : : clearData ( )
{
decltype ( m_receivedData ) dummy ;
dummy . swap ( m_receivedData ) ;
m_receivedSize = 0 ;
}
bool EasySocketListener : : connect ( const char * _ipaddress , uint16_t _port )
{
if ( connected ( ) )
return true ;
m_easySocket . flush ( ) ;
m_easySocket . init ( ) ;
int res = m_easySocket . setAddress ( _ipaddress , _port ) ;
res = m_easySocket . connect ( ) ;
bool isConnected = res = = 0 ;
m_bConnected . store ( isConnected , : : std : : memory_order_release ) ;
return isConnected ;
}
void EasySocketListener : : startCapture ( )
{
clearData ( ) ;
profiler : : net : : Message request ( profiler : : net : : MESSAGE_TYPE_REQUEST_START_CAPTURE ) ;
m_easySocket . send ( & request , sizeof ( request ) ) ;
m_regime = LISTENER_CAPTURE ;
m_thread = : : std : : move ( : : std : : thread ( & EasySocketListener : : listenCapture , this ) ) ;
}
void EasySocketListener : : stopCapture ( )
{
if ( ! m_thread . joinable ( ) | | m_regime ! = LISTENER_CAPTURE )
return ;
profiler : : net : : Message request ( profiler : : net : : MESSAGE_TYPE_REQUEST_STOP_CAPTURE ) ;
m_easySocket . send ( & request , sizeof ( request ) ) ;
m_thread . join ( ) ;
m_regime = LISTENER_IDLE ;
}
void EasySocketListener : : requestBlocksDescription ( )
{
clearData ( ) ;
profiler : : net : : Message request ( profiler : : net : : MESSAGE_TYPE_REQUEST_BLOCKS_DESCRIPTION ) ;
m_easySocket . send ( & request , sizeof ( request ) ) ;
m_regime = LISTENER_DESCRIBE ;
listenDescription ( ) ;
m_regime = LISTENER_IDLE ;
}
void EasySocketListener : : sendBlockStatus ( : : profiler : : block_id_t _id , : : profiler : : EasyBlockStatus _status )
{
profiler : : net : : BlockStatusMessage message ( _id , static_cast < uint8_t > ( _status ) ) ;
m_easySocket . send ( & message , sizeof ( message ) ) ;
}
//////////////////////////////////////////////////////////////////////////
void EasySocketListener : : listenCapture ( )
2016-09-18 19:02:12 +03:00
{
2016-09-25 11:49:49 +03:00
// TODO: Merge functions listenCapture() and listenDescription()
static const int buffer_size = 8 * 1024 * 1024 ;
char * buffer = new char [ buffer_size ] ;
int seek = 0 , bytes = 0 ;
auto timeBegin = : : std : : chrono : : system_clock : : now ( ) ;
bool isListen = true , disconnected = false ;
while ( isListen & & ! m_bInterrupt . load ( : : std : : memory_order_acquire ) )
2016-09-18 19:02:12 +03:00
{
2016-09-25 11:49:49 +03:00
if ( ( bytes - seek ) = = 0 )
{
bytes = m_easySocket . receive ( buffer , buffer_size ) ;
if ( bytes = = - 1 )
{
if ( m_easySocket . state ( ) = = EasySocket : : CONNECTION_STATE_DISCONNECTED )
{
m_bConnected . store ( false , : : std : : memory_order_release ) ;
isListen = false ;
disconnected = true ;
}
seek = 0 ;
bytes = 0 ;
continue ;
}
seek = 0 ;
2016-09-18 19:02:12 +03:00
}
2016-09-25 11:49:49 +03:00
if ( bytes = = 0 )
2016-09-18 19:02:12 +03:00
{
2016-09-25 11:49:49 +03:00
isListen = false ;
break ;
2016-09-18 19:02:12 +03:00
}
2016-09-25 11:49:49 +03:00
char * buf = buffer + seek ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
if ( bytes > 0 )
{
auto message = reinterpret_cast < const : : profiler : : net : : Message * > ( buf ) ;
if ( ! message - > isEasyNetMessage ( ) )
continue ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
switch ( message - > type )
2016-09-18 19:02:12 +03:00
{
2016-09-25 11:49:49 +03:00
case profiler : : net : : MESSAGE_TYPE_ACCEPTED_CONNECTION :
{
qInfo ( ) < < " Receive MESSAGE_TYPE_ACCEPTED_CONNECTION " ;
//m_easySocket.send(&request, sizeof(request));
seek + = sizeof ( profiler : : net : : Message ) ;
break ;
}
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
case profiler : : net : : MESSAGE_TYPE_REPLY_START_CAPTURING :
{
qInfo ( ) < < " Receive MESSAGE_TYPE_REPLY_START_CAPTURING " ;
seek + = sizeof ( profiler : : net : : Message ) ;
break ;
}
case profiler : : net : : MESSAGE_TYPE_REPLY_BLOCKS_END :
{
qInfo ( ) < < " Receive MESSAGE_TYPE_REPLY_BLOCKS_END " ;
seek + = sizeof ( profiler : : net : : Message ) ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
const auto dt = : : std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( : : std : : chrono : : system_clock : : now ( ) - timeBegin ) ;
const auto bytesNumber = m_receivedData . str ( ) . size ( ) ;
qInfo ( ) < < " recieved " < < bytesNumber < < " bytes, " < < dt . count ( ) < < " ms, average speed = " < < double ( bytesNumber ) * 1e3 / double ( dt . count ( ) ) / 1024. < < " kBytes/sec " ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
seek = 0 ;
bytes = 0 ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
isListen = false ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
break ;
}
case profiler : : net : : MESSAGE_TYPE_REPLY_BLOCKS :
{
qInfo ( ) < < " Receive MESSAGE_TYPE_REPLY_BLOCKS " ;
seek + = sizeof ( profiler : : net : : DataMessage ) ;
profiler : : net : : DataMessage * dm = ( profiler : : net : : DataMessage * ) message ;
timeBegin = std : : chrono : : system_clock : : now ( ) ;
int neededSize = dm - > size ;
buf = buffer + seek ;
auto bytesNumber = : : std : : min ( ( int ) dm - > size , bytes - seek ) ;
m_receivedSize + = bytesNumber ;
m_receivedData . write ( buf , bytesNumber ) ;
neededSize - = bytesNumber ;
if ( neededSize = = 0 )
seek + = bytesNumber ;
else
{
seek = 0 ;
bytes = 0 ;
}
int loaded = 0 ;
while ( neededSize > 0 )
{
bytes = m_easySocket . receive ( buffer , buffer_size ) ;
if ( bytes = = - 1 )
{
if ( m_easySocket . state ( ) = = EasySocket : : CONNECTION_STATE_DISCONNECTED )
{
m_bConnected . store ( false , : : std : : memory_order_release ) ;
isListen = false ;
disconnected = true ;
neededSize = 0 ;
}
break ;
}
buf = buffer ;
int toWrite = : : std : : min ( bytes , neededSize ) ;
m_receivedSize + = toWrite ;
m_receivedData . write ( buf , toWrite ) ;
neededSize - = toWrite ;
loaded + = toWrite ;
seek = toWrite ;
}
break ;
}
default :
//qInfo() << "Receive unknown " << message->type;
break ;
2016-09-18 19:02:12 +03:00
}
2016-09-25 11:49:49 +03:00
}
}
if ( disconnected )
clearData ( ) ;
delete [ ] buffer ;
}
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
void EasySocketListener : : listenDescription ( )
{
// TODO: Merge functions listenDescription() and listenCapture()
static const int buffer_size = 8 * 1024 * 1024 ;
char * buffer = new char [ buffer_size ] ;
int seek = 0 , bytes = 0 ;
bool isListen = true , disconnected = false ;
while ( isListen & & ! m_bInterrupt . load ( : : std : : memory_order_acquire ) )
{
if ( ( bytes - seek ) = = 0 )
{
bytes = m_easySocket . receive ( buffer , buffer_size ) ;
if ( bytes = = - 1 )
2016-09-18 19:02:12 +03:00
{
2016-09-25 11:49:49 +03:00
if ( m_easySocket . state ( ) = = EasySocket : : CONNECTION_STATE_DISCONNECTED )
{
m_bConnected . store ( false , : : std : : memory_order_release ) ;
isListen = false ;
disconnected = true ;
}
seek = 0 ;
bytes = 0 ;
2016-09-18 19:02:12 +03:00
continue ;
}
2016-09-25 11:49:49 +03:00
seek = 0 ;
2016-09-18 19:02:12 +03:00
}
2016-09-25 11:49:49 +03:00
if ( bytes = = 0 )
{
isListen = false ;
break ;
}
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
char * buf = buffer + seek ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
if ( bytes > 0 )
{
auto message = reinterpret_cast < const : : profiler : : net : : Message * > ( buf ) ;
if ( ! message - > isEasyNetMessage ( ) )
continue ;
switch ( message - > type )
2016-09-18 19:02:12 +03:00
{
2016-09-25 11:49:49 +03:00
case profiler : : net : : MESSAGE_TYPE_ACCEPTED_CONNECTION :
{
qInfo ( ) < < " Receive MESSAGE_TYPE_ACCEPTED_CONNECTION " ;
seek + = sizeof ( profiler : : net : : Message ) ;
break ;
}
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
case profiler : : net : : MESSAGE_TYPE_REPLY_BLOCKS_DESCRIPTION_END :
{
qInfo ( ) < < " Receive MESSAGE_TYPE_REPLY_BLOCKS_DESCRIPTION_END " ;
seek + = sizeof ( profiler : : net : : Message ) ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
seek = 0 ;
bytes = 0 ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
isListen = false ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
break ;
}
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
case profiler : : net : : MESSAGE_TYPE_REPLY_BLOCKS_DESCRIPTION :
{
qInfo ( ) < < " Receive MESSAGE_TYPE_REPLY_BLOCKS " ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
seek + = sizeof ( profiler : : net : : DataMessage ) ;
profiler : : net : : DataMessage * dm = ( profiler : : net : : DataMessage * ) message ;
int neededSize = dm - > size ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
buf = buffer + seek ;
auto bytesNumber = : : std : : min ( ( int ) dm - > size , bytes - seek ) ;
m_receivedSize + = bytesNumber ;
m_receivedData . write ( buf , bytesNumber ) ;
neededSize - = bytesNumber ;
if ( neededSize = = 0 )
seek + = bytesNumber ;
else {
seek = 0 ;
bytes = 0 ;
}
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
int loaded = 0 ;
while ( neededSize > 0 )
{
bytes = m_easySocket . receive ( buffer , buffer_size ) ;
2016-09-18 19:02:12 +03:00
2016-09-25 11:49:49 +03:00
if ( bytes = = - 1 )
{
if ( m_easySocket . state ( ) = = EasySocket : : CONNECTION_STATE_DISCONNECTED )
{
m_bConnected . store ( false , : : std : : memory_order_release ) ;
isListen = false ;
disconnected = true ;
neededSize = 0 ;
}
break ;
}
buf = buffer ;
int toWrite = : : std : : min ( bytes , neededSize ) ;
m_receivedSize + = toWrite ;
m_receivedData . write ( buf , toWrite ) ;
neededSize - = toWrite ;
loaded + = toWrite ;
seek = toWrite ;
}
break ;
}
default :
break ;
}
}
}
if ( disconnected )
clearData ( ) ;
delete [ ] buffer ;
2016-09-20 01:24:53 +03:00
}
2016-09-25 11:49:49 +03:00
//////////////////////////////////////////////////////////////////////////