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
* :
2016-11-13 16:39:59 +03:00
* :
* : 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 .
2016-09-06 22:23:55 +03:00
* :
* : 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>
2016-11-18 22:58:44 +03:00
# include <QToolButton>
2016-09-29 22:40:19 +03:00
# include <QWidgetAction>
2016-11-19 04:52:45 +03:00
# include <QSpinBox>
2016-09-08 21:03:05 +03:00
# 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-10-02 12:13:12 +03:00
# include <QFile>
2016-11-19 05:39:41 +03:00
# include <QDragEnterEvent>
# include <QDragMoveEvent>
# include <QDragLeaveEvent>
# include <QDropEvent>
# include <QMimeData>
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-29 23:29:57 +03:00
# include "easy/easy_net.h"
2016-09-08 21:03:05 +03:00
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-10-02 12:13:12 +03:00
const auto NETWORK_CACHE_FILE = " easy_profiler_stream.cache " ;
2016-08-28 21:06:23 +03:00
//////////////////////////////////////////////////////////////////////////
2016-11-06 14:47:01 +03:00
inline void clear_stream ( std : : stringstream & _stream )
{
# if defined(__GNUC__) && __GNUC__ < 5
// gcc 4 has a known bug which has been solved in gcc 5:
// std::stringstream has no swap() method :(
_stream . str ( std : : string ( ) ) ;
# else
std : : stringstream ( ) . swap ( _stream ) ;
# endif
}
//////////////////////////////////////////////////////////////////////////
2016-09-29 22:40:19 +03:00
EasyMainWindow : : EasyMainWindow ( ) : Parent ( ) , m_lastAddress ( " 127.0.0.1 " ) , m_lastPort ( : : profiler : : DEFAULT_PORT )
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-11-06 14:47:01 +03:00
setWindowTitle ( " EasyProfiler " ) ;
2016-08-28 21:06:23 +03:00
setDockNestingEnabled ( true ) ;
2016-11-19 05:39:41 +03:00
setAcceptDrops ( true ) ;
2016-08-28 21:06:23 +03:00
resize ( 800 , 600 ) ;
setStatusBar ( new QStatusBar ( ) ) ;
2016-11-20 21:01:33 +03:00
m_graphicsView = new QDockWidget ( " Diagram " , this ) ;
2016-09-17 18:43:06 +03:00
m_graphicsView - > setObjectName ( " ProfilerGUI_Diagram " ) ;
2016-08-28 21:06:23 +03:00
m_graphicsView - > setMinimumHeight ( 50 ) ;
m_graphicsView - > setAllowedAreas ( Qt : : AllDockWidgetAreas ) ;
2016-11-20 21:01:33 +03:00
auto graphicsView = new EasyGraphicsViewWidget ( this ) ;
2016-08-28 21:06:23 +03:00
m_graphicsView - > setWidget ( graphicsView ) ;
2016-11-20 21:01:33 +03:00
m_treeWidget = new QDockWidget ( " Hierarchy " , this ) ;
2016-09-17 18:43:06 +03:00
m_treeWidget - > setObjectName ( " ProfilerGUI_Hierarchy " ) ;
2016-08-28 21:06:23 +03:00
m_treeWidget - > setMinimumHeight ( 50 ) ;
m_treeWidget - > setAllowedAreas ( Qt : : AllDockWidgetAreas ) ;
2016-11-20 21:01:33 +03:00
auto treeWidget = new EasyHierarchyWidget ( this ) ;
2016-08-28 21:06:23 +03:00
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-29 22:40:19 +03:00
loadSettings ( ) ;
auto toolbar = addToolBar ( " FileToolbar " ) ;
toolbar - > setObjectName ( " ProfilerGUI_FileToolbar " ) ;
toolbar - > setContentsMargins ( 1 , 0 , 1 , 0 ) ;
toolbar - > addAction ( QIcon ( " :/Open " ) , tr ( " Open " ) , this , SLOT ( onOpenFileClicked ( bool ) ) ) ;
2016-10-02 17:52:14 +03:00
toolbar - > addAction ( QIcon ( " :/Reopen " ) , tr ( " Reload last file " ) , this , SLOT ( onReloadFileClicked ( bool ) ) ) ;
2016-09-29 22:40:19 +03:00
m_saveAction = toolbar - > addAction ( QIcon ( " :/Save " ) , tr ( " Save " ) , this , SLOT ( onSaveFileClicked ( bool ) ) ) ;
m_deleteAction = toolbar - > addAction ( QIcon ( " :/Delete " ) , tr ( " Clear all " ) , this , SLOT ( onDeleteClicked ( bool ) ) ) ;
m_saveAction - > setEnabled ( false ) ;
m_deleteAction - > setEnabled ( false ) ;
toolbar = addToolBar ( " ProfileToolbar " ) ;
toolbar - > setObjectName ( " ProfilerGUI_ProfileToolbar " ) ;
toolbar - > setContentsMargins ( 1 , 0 , 1 , 0 ) ;
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-29 22:40:19 +03:00
auto lbl = new QLabel ( " IP: " , toolbar ) ;
2016-11-13 22:02:47 +03:00
lbl - > setContentsMargins ( 5 , 0 , 2 , 0 ) ;
2016-09-29 22:40:19 +03:00
toolbar - > addWidget ( lbl ) ;
2016-09-18 20:20:37 +03:00
m_ipEdit = new QLineEdit ( ) ;
2016-09-27 22:43:02 +03:00
QRegExp rx ( " ^0*(2(5[0-5]|[0-4] \\ d) | 1 ? \ \ d { 1 , 2 } ) ( \ \ .0 * ( 2 ( 5 [ 0 - 5 ] | [ 0 - 4 ] \ \ d ) | 1 ? \ \ d { 1 , 2 } ) ) { 3 } $ " );
2016-09-18 20:20:37 +03:00
m_ipEdit - > setValidator ( new QRegExpValidator ( rx , m_ipEdit ) ) ;
2016-09-29 22:40:19 +03:00
m_ipEdit - > setText ( m_lastAddress ) ;
2016-09-27 23:45:33 +03:00
m_ipEdit - > setFixedWidth ( m_ipEdit - > fontMetrics ( ) . width ( QString ( " 255.255.255.255 " ) ) + 20 ) ;
2016-09-18 20:20:37 +03:00
toolbar - > addWidget ( m_ipEdit ) ;
2016-09-29 22:40:19 +03:00
lbl = new QLabel ( " Port: " , toolbar ) ;
2016-11-13 22:02:47 +03:00
lbl - > setContentsMargins ( 5 , 0 , 2 , 0 ) ;
2016-09-29 22:40:19 +03:00
toolbar - > addWidget ( lbl ) ;
2016-09-18 20:20:37 +03:00
m_portEdit = new QLineEdit ( ) ;
2016-09-27 22:43:02 +03:00
m_portEdit - > setValidator ( new QIntValidator ( 1 , 65535 , m_portEdit ) ) ;
2016-09-29 22:40:19 +03:00
m_portEdit - > setText ( QString : : number ( m_lastPort ) ) ;
2016-09-27 22:43:02 +03:00
m_portEdit - > setFixedWidth ( m_portEdit - > fontMetrics ( ) . width ( QString ( " 000000 " ) ) + 10 ) ;
2016-09-18 20:20:37 +03:00
toolbar - > addWidget ( m_portEdit ) ;
2016-09-13 21:42:38 +03:00
2016-09-27 23:45:33 +03:00
connect ( m_ipEdit , & QLineEdit : : returnPressed , [ this ] ( ) { onConnectClicked ( true ) ; } ) ;
connect ( m_portEdit , & QLineEdit : : returnPressed , [ this ] ( ) { onConnectClicked ( true ) ; } ) ;
2016-09-14 22:04:15 +03:00
2016-08-28 21:06:23 +03:00
2016-09-29 22:40:19 +03:00
toolbar = addToolBar ( " SetupToolbar " ) ;
toolbar - > setObjectName ( " ProfilerGUI_SetupToolbar " ) ;
toolbar - > setContentsMargins ( 1 , 0 , 1 , 0 ) ;
2016-08-28 21:06:23 +03:00
2016-09-29 22:40:19 +03:00
toolbar - > addAction ( QIcon ( " :/Expand " ) , " Expand all " , this , SLOT ( onExpandAllClicked ( bool ) ) ) ;
toolbar - > addAction ( QIcon ( " :/Collapse " ) , " Collapse all " , this , SLOT ( onCollapseAllClicked ( bool ) ) ) ;
2016-08-28 21:06:23 +03:00
2016-09-29 22:40:19 +03:00
toolbar - > addSeparator ( ) ;
auto menu = new QMenu ( " Settings " , this ) ;
QToolButton * toolButton = new QToolButton ( toolbar ) ;
toolButton - > setIcon ( QIcon ( " :/Settings " ) ) ;
toolButton - > setMenu ( menu ) ;
toolButton - > setPopupMode ( QToolButton : : InstantPopup ) ;
toolbar - > addWidget ( toolButton ) ;
auto action = menu - > addAction ( " Statistics enabled " ) ;
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 ) ;
SET_ICON ( action , " :/Stats " ) ;
}
else
{
action - > setText ( " Statistics disabled " ) ;
SET_ICON ( action , " :/Stats-off " ) ;
}
2016-08-28 21:06:23 +03:00
menu - > addSeparator ( ) ;
2016-09-29 22:40:19 +03:00
auto submenu = menu - > addMenu ( " View " ) ;
2016-12-04 16:51:27 +03:00
submenu - > setToolTipsVisible ( true ) ;
2016-09-29 22:40:19 +03:00
action = submenu - > addAction ( " Draw items' borders " ) ;
2016-12-04 16:51:27 +03:00
action - > setToolTip ( " Draw borders for blocks on diagram. \n This reduces performance. " ) ;
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 ) ;
2016-09-29 22:40:19 +03:00
action = submenu - > addAction ( " Hide narrow children " ) ;
2016-12-04 16:51:27 +03:00
action - > setToolTip ( " Children blocks will be hidden by narrow \n parent blocks. See also \" Blocks narrow size \" . \n This improves performance. " ) ;
2016-09-29 22:40:19 +03:00
action - > setCheckable ( true ) ;
action - > setChecked ( EASY_GLOBALS . hide_narrow_children ) ;
connect ( action , & QAction : : triggered , this , & This : : onHideNarrowChildrenChanged ) ;
2016-11-20 21:01:33 +03:00
action = submenu - > addAction ( " Build hierarchy only for current thread " ) ;
2016-12-04 16:51:27 +03:00
action - > setToolTip ( " Hierarchy tree will be built \n for blocks from current thread only. \n This improves performance \n and saves a lot of memory. " ) ;
2016-11-20 21:01:33 +03:00
action - > setCheckable ( true ) ;
action - > setChecked ( EASY_GLOBALS . only_current_thread_hierarchy ) ;
connect ( action , & QAction : : triggered , this , & This : : onHierarchyFlagChange ) ;
2016-11-26 18:08:02 +03:00
action = submenu - > addAction ( " Add zero blocks to hierarchy " ) ;
2016-12-04 16:51:27 +03:00
action - > setToolTip ( " Zero duration blocks will be added into hierarchy tree. \n This reduces performance and increases memory consumption. " ) ;
2016-11-26 18:08:02 +03:00
action - > setCheckable ( true ) ;
action - > setChecked ( EASY_GLOBALS . add_zero_blocks_to_hierarchy ) ;
connect ( action , & QAction : : triggered , [ this ] ( bool _checked )
{
EASY_GLOBALS . add_zero_blocks_to_hierarchy = _checked ;
emit EASY_GLOBALS . events . hierarchyFlagChanged ( _checked ) ;
} ) ;
2016-12-04 16:51:27 +03:00
action = submenu - > addAction ( " Enable zero duration blocks on diagram " ) ;
action - > setToolTip ( " If checked then allows diagram to paint zero duration blocks \n with 1px width on each scale. Otherwise, such blocks will be resized \n to 250ns duration. " ) ;
2016-11-23 22:54:59 +03:00
action - > setCheckable ( true ) ;
action - > setChecked ( EASY_GLOBALS . enable_zero_length ) ;
connect ( action , & QAction : : triggered , [ this ] ( bool _checked ) { EASY_GLOBALS . enable_zero_length = _checked ; refreshDiagram ( ) ; } ) ;
2016-11-30 21:59:40 +03:00
action = submenu - > addAction ( " Highlight similar blocks " ) ;
2016-12-04 16:51:27 +03:00
action - > setToolTip ( " Highlight all visible blocks which are similar \n to the current selected block. \n This reduces performance. " ) ;
2016-11-30 21:59:40 +03:00
action - > setCheckable ( true ) ;
action - > setChecked ( EASY_GLOBALS . highlight_blocks_with_same_id ) ;
connect ( action , & QAction : : triggered , [ this ] ( bool _checked ) { EASY_GLOBALS . highlight_blocks_with_same_id = _checked ; refreshDiagram ( ) ; } ) ;
2016-12-04 16:51:27 +03:00
action = submenu - > addAction ( " Collapse blocks on tree reset " ) ;
action - > setToolTip ( " This collapses all blocks on diagram \n after hierarchy tree reset. " ) ;
2016-08-28 21:06:23 +03:00
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 ) ;
2016-09-29 22:40:19 +03:00
action = submenu - > addAction ( " Expand all on file open " ) ;
2016-12-04 16:51:27 +03:00
action - > setToolTip ( " If checked then all blocks on diagram \n will be initially expanded. " ) ;
2016-08-28 21:06:23 +03:00
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 ) ;
2016-12-04 16:51:27 +03:00
action = submenu - > addAction ( " Bind diagram and tree expand " ) ;
action - > setToolTip ( " Expanding/collapsing blocks at diagram expands/collapses \n blocks at hierarchy tree and wise versa. " ) ;
2016-08-28 21:06:23 +03:00
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-12-04 16:51:27 +03:00
action = submenu - > addAction ( " Selecting block changes current thread " ) ;
action - > setToolTip ( " Automatically select thread while selecting a block. \n If not checked then you will have to select current thread \n manually double clicking on thread name on a diagram. " ) ;
action - > setCheckable ( true ) ;
action - > setChecked ( EASY_GLOBALS . selecting_block_changes_thread ) ;
connect ( action , & QAction : : triggered , [ this ] ( bool _checked ) { EASY_GLOBALS . selecting_block_changes_thread = _checked ; } ) ;
2016-09-29 22:40:19 +03:00
action = submenu - > addAction ( " Draw event indicators " ) ;
2016-12-04 16:51:27 +03:00
action - > setToolTip ( " Display event indicators under the blocks \n (even if event-blocks are not visible). \n This slightly reduces performance. " ) ;
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-09-29 22:40:19 +03:00
submenu - > addSeparator ( ) ;
2016-08-28 21:06:23 +03:00
auto actionGroup = new QActionGroup ( this ) ;
actionGroup - > setExclusive ( true ) ;
2016-09-29 22:40:19 +03:00
action = new QAction ( " Chrono text at top " , actionGroup ) ;
2016-12-04 16:51:27 +03:00
action - > setToolTip ( " Draw duration of selected interval \n at the top of the screen. " ) ;
2016-08-28 21:06:23 +03:00
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 ) ;
2016-09-29 22:40:19 +03:00
action = new QAction ( " Chrono text at center " , actionGroup ) ;
2016-12-04 16:51:27 +03:00
action - > setToolTip ( " Draw duration of selected interval \n at the center of the screen. " ) ;
2016-08-28 21:06:23 +03:00
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 ) ;
2016-09-29 22:40:19 +03:00
action = new QAction ( " Chrono text at bottom " , actionGroup ) ;
2016-12-04 16:51:27 +03:00
action - > setToolTip ( " Draw duration of selected interval \n at the bottom of the screen. " ) ;
2016-08-28 21:06:23 +03:00
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-11-19 04:52:45 +03:00
submenu - > addSeparator ( ) ;
auto w = new QWidget ( submenu ) ;
auto l = new QHBoxLayout ( w ) ;
l - > setContentsMargins ( 33 , 1 , 1 , 1 ) ;
2016-12-04 16:51:27 +03:00
l - > addWidget ( new QLabel ( " Min blocks spacing, px " , w ) , 0 , Qt : : AlignLeft ) ;
2016-11-19 04:52:45 +03:00
auto spinbox = new QSpinBox ( w ) ;
spinbox - > setMinimum ( 0 ) ;
spinbox - > setValue ( EASY_GLOBALS . blocks_spacing ) ;
spinbox - > setFixedWidth ( 50 ) ;
connect ( spinbox , SIGNAL ( valueChanged ( int ) ) , this , SLOT ( onSpacingChange ( int ) ) ) ;
l - > addWidget ( spinbox ) ;
w - > setLayout ( l ) ;
auto waction = new QWidgetAction ( submenu ) ;
waction - > setDefaultWidget ( w ) ;
submenu - > addAction ( waction ) ;
w = new QWidget ( submenu ) ;
l = new QHBoxLayout ( w ) ;
l - > setContentsMargins ( 33 , 1 , 1 , 1 ) ;
2016-12-04 16:51:27 +03:00
l - > addWidget ( new QLabel ( " Min blocks size, px " , w ) , 0 , Qt : : AlignLeft ) ;
2016-11-19 04:52:45 +03:00
spinbox = new QSpinBox ( w ) ;
spinbox - > setMinimum ( 1 ) ;
spinbox - > setValue ( EASY_GLOBALS . blocks_size_min ) ;
spinbox - > setFixedWidth ( 50 ) ;
connect ( spinbox , SIGNAL ( valueChanged ( int ) ) , this , SLOT ( onMinSizeChange ( int ) ) ) ;
l - > addWidget ( spinbox ) ;
w - > setLayout ( l ) ;
waction = new QWidgetAction ( submenu ) ;
waction - > setDefaultWidget ( w ) ;
submenu - > addAction ( waction ) ;
w = new QWidget ( submenu ) ;
l = new QHBoxLayout ( w ) ;
l - > setContentsMargins ( 33 , 1 , 1 , 1 ) ;
2016-12-04 16:51:27 +03:00
l - > addWidget ( new QLabel ( " Blocks narrow size, px " , w ) , 0 , Qt : : AlignLeft ) ;
2016-11-19 04:52:45 +03:00
spinbox = new QSpinBox ( w ) ;
spinbox - > setMinimum ( 1 ) ;
spinbox - > setValue ( EASY_GLOBALS . blocks_narrow_size ) ;
spinbox - > setFixedWidth ( 50 ) ;
connect ( spinbox , SIGNAL ( valueChanged ( int ) ) , this , SLOT ( onNarrowSizeChange ( int ) ) ) ;
l - > addWidget ( spinbox ) ;
w - > setLayout ( l ) ;
waction = new QWidgetAction ( submenu ) ;
waction - > setDefaultWidget ( w ) ;
submenu - > addAction ( waction ) ;
2016-08-28 21:06:23 +03:00
2016-11-30 21:59:40 +03:00
submenu = menu - > addMenu ( " Units " ) ;
actionGroup = new QActionGroup ( this ) ;
actionGroup - > setExclusive ( true ) ;
action = new QAction ( " Auto " , actionGroup ) ;
action - > setCheckable ( true ) ;
action - > setData ( static_cast < int > ( : : profiler_gui : : TimeUnits_auto ) ) ;
if ( EASY_GLOBALS . time_units = = : : profiler_gui : : TimeUnits_auto )
action - > setChecked ( true ) ;
submenu - > addAction ( action ) ;
connect ( action , & QAction : : triggered , this , & This : : onUnitsChanged ) ;
action = new QAction ( " Milliseconds " , actionGroup ) ;
action - > setCheckable ( true ) ;
action - > setData ( static_cast < int > ( : : profiler_gui : : TimeUnits_ms ) ) ;
if ( EASY_GLOBALS . time_units = = : : profiler_gui : : TimeUnits_ms )
action - > setChecked ( true ) ;
submenu - > addAction ( action ) ;
connect ( action , & QAction : : triggered , this , & This : : onUnitsChanged ) ;
action = new QAction ( " Microseconds " , actionGroup ) ;
action - > setCheckable ( true ) ;
action - > setData ( static_cast < int > ( : : profiler_gui : : TimeUnits_us ) ) ;
if ( EASY_GLOBALS . time_units = = : : profiler_gui : : TimeUnits_us )
action - > setChecked ( true ) ;
submenu - > addAction ( action ) ;
connect ( action , & QAction : : triggered , this , & This : : onUnitsChanged ) ;
action = new QAction ( " Nanoseconds " , actionGroup ) ;
action - > setCheckable ( true ) ;
action - > setData ( static_cast < int > ( : : profiler_gui : : TimeUnits_ns ) ) ;
if ( EASY_GLOBALS . time_units = = : : profiler_gui : : TimeUnits_ns )
action - > setChecked ( true ) ;
submenu - > addAction ( action ) ;
connect ( action , & QAction : : triggered , this , & This : : onUnitsChanged ) ;
2016-09-29 22:40:19 +03:00
submenu = menu - > addMenu ( " Remote " ) ;
2016-09-28 00:37:20 +03:00
m_eventTracingEnableAction = submenu - > addAction ( " Event tracing enabled " ) ;
m_eventTracingEnableAction - > setCheckable ( true ) ;
m_eventTracingEnableAction - > setEnabled ( false ) ;
connect ( m_eventTracingEnableAction , & QAction : : triggered , this , & This : : onEventTracingEnableChange ) ;
m_eventTracingPriorityAction = submenu - > addAction ( " Low priority event tracing " ) ;
m_eventTracingPriorityAction - > setCheckable ( true ) ;
m_eventTracingPriorityAction - > setChecked ( EASY_LOW_PRIORITY_EVENT_TRACING ) ;
m_eventTracingPriorityAction - > setEnabled ( false ) ;
connect ( m_eventTracingPriorityAction , & QAction : : triggered , this , & This : : onEventTracingPriorityChange ) ;
2016-09-29 22:40:19 +03:00
submenu = menu - > addMenu ( " Encoding " ) ;
2016-08-28 21:06:23 +03:00
actionGroup = new QActionGroup ( this ) ;
actionGroup - > setExclusive ( true ) ;
auto default_codec_mib = QTextCodec : : codecForLocale ( ) - > mibEnum ( ) ;
2016-09-29 22:40:19 +03:00
foreach ( int mib , QTextCodec : : availableMibs ( ) )
2016-08-28 21:06:23 +03:00
{
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-11-13 22:02:47 +03:00
auto tb_height = toolbar - > height ( ) + 4 ;
toolbar = addToolBar ( " FrameToolbar " ) ;
toolbar - > setObjectName ( " ProfilerGUI_FrameToolbar " ) ;
toolbar - > setContentsMargins ( 1 , 0 , 1 , 0 ) ;
toolbar - > setMinimumHeight ( tb_height ) ;
lbl = new QLabel ( " Frame time: " , toolbar ) ;
lbl - > setContentsMargins ( 5 , 2 , 2 , 2 ) ;
toolbar - > addWidget ( lbl ) ;
m_frameTimeEdit = new QLineEdit ( ) ;
m_frameTimeEdit - > setFixedWidth ( 70 ) ;
auto val = new QDoubleValidator ( m_frameTimeEdit ) ;
val - > setLocale ( QLocale : : c ( ) ) ;
val - > setBottom ( 0 ) ;
m_frameTimeEdit - > setValidator ( val ) ;
m_frameTimeEdit - > setText ( QString : : number ( EASY_GLOBALS . frame_time * 1e-3 ) ) ;
connect ( m_frameTimeEdit , & QLineEdit : : editingFinished , this , & This : : onFrameTimeEditFinish ) ;
toolbar - > addWidget ( m_frameTimeEdit ) ;
lbl = new QLabel ( " ms " , toolbar ) ;
lbl - > setContentsMargins ( 5 , 2 , 1 , 1 ) ;
toolbar - > addWidget ( lbl ) ;
2016-09-18 20:20:37 +03:00
2016-08-28 21:06:23 +03:00
2016-11-20 21:01:33 +03:00
connect ( graphicsView - > view ( ) , & EasyGraphicsView : : intervalChanged , treeWidget - > tree ( ) , & EasyTreeWidget : : setTreeBlocks ) ;
2016-08-28 21:06:23 +03:00
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 ;
}
//////////////////////////////////////////////////////////////////////////
2016-11-19 05:39:41 +03:00
void EasyMainWindow : : dragEnterEvent ( QDragEnterEvent * drag_event )
{
if ( drag_event - > mimeData ( ) - > hasUrls ( ) )
drag_event - > acceptProposedAction ( ) ;
}
void EasyMainWindow : : dragMoveEvent ( QDragMoveEvent * drag_event )
{
if ( drag_event - > mimeData ( ) - > hasUrls ( ) )
drag_event - > acceptProposedAction ( ) ;
}
void EasyMainWindow : : dragLeaveEvent ( QDragLeaveEvent * drag_event )
{
drag_event - > accept ( ) ;
}
void EasyMainWindow : : dropEvent ( QDropEvent * drop_event )
{
const auto & urls = drop_event - > mimeData ( ) - > urls ( ) ;
if ( ! urls . empty ( ) )
loadFile ( urls . front ( ) . toLocalFile ( ) ) ;
}
//////////////////////////////////////////////////////////////////////////
2016-08-28 21:06:23 +03:00
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-29 22:40:19 +03:00
void EasyMainWindow : : onSaveFileClicked ( bool )
{
2016-10-02 12:13:12 +03:00
if ( m_serializedBlocks . empty ( ) )
2016-09-29 22:40:19 +03:00
return ;
const auto i = m_lastFile . lastIndexOf ( QChar ( ' / ' ) ) ;
const auto j = m_lastFile . lastIndexOf ( QChar ( ' \\ ' ) ) ;
auto k = : : std : : max ( i , j ) ;
QString dir ;
if ( k > 0 )
dir = m_lastFile . mid ( 0 , + + k ) ;
auto filename = QFileDialog : : getSaveFileName ( this , " Save profiler log " , dir , " Profiler Log File (*.prof);;All Files (*.*) " ) ;
if ( ! filename . isEmpty ( ) )
{
2016-10-02 16:17:22 +03:00
bool inOk = false , outOk = false ;
int8_t retry1 = - 1 ;
while ( + + retry1 < 4 )
2016-10-02 12:13:12 +03:00
{
2016-10-02 16:17:22 +03:00
: : std : : ifstream inFile ( m_bNetworkFileRegime ? NETWORK_CACHE_FILE : m_lastFile . toStdString ( ) . c_str ( ) , : : std : : fstream : : binary ) ;
if ( ! inFile . is_open ( ) )
2016-10-02 12:13:12 +03:00
{
2016-10-02 16:17:22 +03:00
: : std : : this_thread : : sleep_for ( : : std : : chrono : : milliseconds ( 500 ) ) ;
continue ;
}
inOk = true ;
int8_t retry2 = - 1 ;
while ( + + retry2 < 4 )
{
: : std : : ofstream outFile ( filename . toStdString ( ) , : : std : : fstream : : binary ) ;
if ( ! outFile . is_open ( ) )
{
: : std : : this_thread : : sleep_for ( : : std : : chrono : : milliseconds ( 500 ) ) ;
continue ;
}
outFile < < inFile . rdbuf ( ) ;
outOk = true ;
break ;
2016-10-02 12:13:12 +03:00
}
2016-10-02 16:17:22 +03:00
break ;
2016-10-02 12:13:12 +03:00
}
2016-10-02 16:17:22 +03:00
if ( outOk )
2016-10-02 12:13:12 +03:00
{
2016-10-02 16:17:22 +03:00
if ( m_bNetworkFileRegime )
QFile : : remove ( QString ( NETWORK_CACHE_FILE ) ) ;
m_lastFile = filename ;
m_bNetworkFileRegime = false ;
}
else if ( inOk )
{
QMessageBox : : warning ( this , " Warning " , " Can not open destination file. \n Saving incomplete. " , QMessageBox : : Close ) ;
2016-10-02 12:13:12 +03:00
}
2016-09-29 22:40:19 +03:00
else
2016-10-02 12:13:12 +03:00
{
2016-10-02 16:17:22 +03:00
if ( m_bNetworkFileRegime )
QMessageBox : : warning ( this , " Warning " , " Can not open network cache file. \n Saving incomplete. " , QMessageBox : : Close ) ;
else
QMessageBox : : warning ( this , " Warning " , " Can not open source file. \n Saving incomplete. " , QMessageBox : : Close ) ;
2016-10-02 12:13:12 +03:00
}
2016-09-29 22:40:19 +03:00
}
}
//////////////////////////////////////////////////////////////////////////
2016-10-02 12:13:12 +03:00
void EasyMainWindow : : clear ( )
2016-09-21 22:09:04 +03:00
{
2016-11-20 21:01:33 +03:00
static_cast < EasyHierarchyWidget * > ( m_treeWidget - > widget ( ) ) - > clear ( true ) ;
2016-09-21 22:09:04 +03:00
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 ) ;
2016-11-30 21:59:40 +03:00
: : profiler_gui : : set_max ( EASY_GLOBALS . selected_block_id ) ;
2016-09-21 22:09:04 +03:00
EASY_GLOBALS . profiler_blocks . clear ( ) ;
EASY_GLOBALS . descriptors . clear ( ) ;
EASY_GLOBALS . gui_blocks . clear ( ) ;
m_serializedBlocks . clear ( ) ;
m_serializedDescriptors . clear ( ) ;
2016-09-29 22:40:19 +03:00
m_saveAction - > setEnabled ( false ) ;
m_deleteAction - > setEnabled ( false ) ;
2016-10-02 12:13:12 +03:00
m_bNetworkFileRegime = false ;
}
2016-11-23 22:54:59 +03:00
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow : : refreshDiagram ( )
{
static_cast < EasyGraphicsViewWidget * > ( m_graphicsView - > widget ( ) ) - > view ( ) - > scene ( ) - > update ( ) ;
}
//////////////////////////////////////////////////////////////////////////
2016-10-02 12:13:12 +03:00
void EasyMainWindow : : onDeleteClicked ( bool )
{
auto button = QMessageBox : : question ( this , " Clear all profiled data " , " All profiled data is going to be deleted! \n Continue? " , QMessageBox : : Yes , QMessageBox : : No ) ;
if ( button = = QMessageBox : : Yes )
clear ( ) ;
2016-09-21 22:09:04 +03:00
}
//////////////////////////////////////////////////////////////////////////
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-11-23 22:54:59 +03:00
refreshDiagram ( ) ;
2016-08-28 21:06:23 +03:00
}
2016-11-30 21:59:40 +03:00
void EasyMainWindow : : onUnitsChanged ( bool )
{
auto _sender = qobject_cast < QAction * > ( sender ( ) ) ;
EASY_GLOBALS . time_units = static_cast < : : profiler_gui : : TimeUnits > ( _sender - > data ( ) . toInt ( ) ) ;
}
2016-09-23 23:50:43 +03:00
void EasyMainWindow : : onEventIndicatorsChange ( bool _checked )
{
EASY_GLOBALS . enable_event_indicators = _checked ;
2016-11-23 22:54:59 +03:00
refreshDiagram ( ) ;
2016-09-23 23:50:43 +03:00
}
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-11-23 22:54:59 +03:00
refreshDiagram ( ) ;
2016-08-28 21:06:23 +03:00
}
2016-09-29 22:40:19 +03:00
void EasyMainWindow : : onHideNarrowChildrenChanged ( bool _checked )
{
EASY_GLOBALS . hide_narrow_children = _checked ;
2016-11-23 22:54:59 +03:00
refreshDiagram ( ) ;
2016-09-29 22:40:19 +03:00
}
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
}
2016-11-20 21:01:33 +03:00
void EasyMainWindow : : onHierarchyFlagChange ( bool _checked )
{
EASY_GLOBALS . only_current_thread_hierarchy = _checked ;
emit EASY_GLOBALS . events . hierarchyFlagChanged ( _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
2016-11-20 21:01:33 +03:00
auto tree = static_cast < EasyHierarchyWidget * > ( m_treeWidget - > widget ( ) ) - > tree ( ) ;
2016-08-28 21:06:23 +03:00
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
2016-11-20 21:01:33 +03:00
auto tree = static_cast < EasyHierarchyWidget * > ( m_treeWidget - > widget ( ) ) - > tree ( ) ;
2016-08-28 21:06:23 +03:00
const QSignalBlocker b ( tree ) ;
tree - > collapseAll ( ) ;
}
//////////////////////////////////////////////////////////////////////////
2016-11-19 04:52:45 +03:00
void EasyMainWindow : : onSpacingChange ( int _value )
{
EASY_GLOBALS . blocks_spacing = _value ;
2016-11-23 22:54:59 +03:00
refreshDiagram ( ) ;
2016-11-19 04:52:45 +03:00
}
void EasyMainWindow : : onMinSizeChange ( int _value )
{
EASY_GLOBALS . blocks_size_min = _value ;
2016-11-23 22:54:59 +03:00
refreshDiagram ( ) ;
2016-11-19 04:52:45 +03:00
}
void EasyMainWindow : : onNarrowSizeChange ( int _value )
{
EASY_GLOBALS . blocks_narrow_size = _value ;
2016-11-23 22:54:59 +03:00
refreshDiagram ( ) ;
2016-11-19 04:52:45 +03:00
}
//////////////////////////////////////////////////////////////////////////
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
2016-11-30 21:59:40 +03:00
val = settings . value ( " time_units " ) ;
if ( ! val . isNull ( ) )
EASY_GLOBALS . time_units = static_cast < : : profiler_gui : : TimeUnits > ( val . toInt ( ) ) ;
2016-08-28 21:06:23 +03:00
2016-11-13 22:02:47 +03:00
val = settings . value ( " frame_time " ) ;
if ( ! val . isNull ( ) )
EASY_GLOBALS . frame_time = val . toFloat ( ) ;
2016-11-19 04:52:45 +03:00
val = settings . value ( " blocks_spacing " ) ;
if ( ! val . isNull ( ) )
EASY_GLOBALS . blocks_spacing = val . toInt ( ) ;
val = settings . value ( " blocks_size_min " ) ;
if ( ! val . isNull ( ) )
EASY_GLOBALS . blocks_size_min = val . toInt ( ) ;
val = settings . value ( " blocks_narrow_size " ) ;
if ( ! val . isNull ( ) )
EASY_GLOBALS . blocks_narrow_size = val . toInt ( ) ;
2016-11-13 22:02:47 +03:00
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
2016-09-29 22:40:19 +03:00
flag = settings . value ( " hide_narrow_children " ) ;
if ( ! flag . isNull ( ) )
EASY_GLOBALS . hide_narrow_children = 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
2016-11-20 21:01:33 +03:00
flag = settings . value ( " only_current_thread_hierarchy " ) ;
if ( ! flag . isNull ( ) )
EASY_GLOBALS . only_current_thread_hierarchy = flag . toBool ( ) ;
2016-11-23 22:54:59 +03:00
flag = settings . value ( " enable_zero_length " ) ;
if ( ! flag . isNull ( ) )
EASY_GLOBALS . enable_zero_length = flag . toBool ( ) ;
2016-11-26 18:08:02 +03:00
flag = settings . value ( " add_zero_blocks_to_hierarchy " ) ;
if ( ! flag . isNull ( ) )
EASY_GLOBALS . add_zero_blocks_to_hierarchy = flag . toBool ( ) ;
2016-11-30 21:59:40 +03:00
flag = settings . value ( " highlight_blocks_with_same_id " ) ;
if ( ! flag . isNull ( ) )
EASY_GLOBALS . highlight_blocks_with_same_id = 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
2016-12-04 16:51:27 +03:00
flag = settings . value ( " selecting_block_changes_thread " ) ;
if ( ! flag . isNull ( ) )
EASY_GLOBALS . selecting_block_changes_thread = 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 ) ) ;
2016-11-30 21:59:40 +03:00
settings . setValue ( " time_units " , static_cast < int > ( EASY_GLOBALS . time_units ) ) ;
2016-11-13 22:02:47 +03:00
settings . setValue ( " frame_time " , EASY_GLOBALS . frame_time ) ;
2016-11-19 04:52:45 +03:00
settings . setValue ( " blocks_spacing " , EASY_GLOBALS . blocks_spacing ) ;
settings . setValue ( " blocks_size_min " , EASY_GLOBALS . blocks_size_min ) ;
settings . setValue ( " blocks_narrow_size " , EASY_GLOBALS . blocks_narrow_size ) ;
2016-08-30 22:51:18 +03:00
settings . setValue ( " draw_graphics_items_borders " , EASY_GLOBALS . draw_graphics_items_borders ) ;
2016-09-29 22:40:19 +03:00
settings . setValue ( " hide_narrow_children " , EASY_GLOBALS . hide_narrow_children ) ;
2016-08-30 22:51:18 +03:00
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 ) ;
2016-11-20 21:01:33 +03:00
settings . setValue ( " only_current_thread_hierarchy " , EASY_GLOBALS . only_current_thread_hierarchy ) ;
2016-11-23 22:54:59 +03:00
settings . setValue ( " enable_zero_length " , EASY_GLOBALS . enable_zero_length ) ;
2016-11-26 18:08:02 +03:00
settings . setValue ( " add_zero_blocks_to_hierarchy " , EASY_GLOBALS . add_zero_blocks_to_hierarchy ) ;
2016-11-30 21:59:40 +03:00
settings . setValue ( " highlight_blocks_with_same_id " , EASY_GLOBALS . highlight_blocks_with_same_id ) ;
2016-08-30 22:51:18 +03:00
settings . setValue ( " bind_scene_and_tree_expand_status " , EASY_GLOBALS . bind_scene_and_tree_expand_status ) ;
2016-12-04 16:51:27 +03:00
settings . setValue ( " selecting_block_changes_thread " , EASY_GLOBALS . selecting_block_changes_thread ) ;
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-12-08 22:22:09 +03:00
void EasyMainWindow : : setDisconnected ( bool _showMessage )
2016-11-18 22:58:44 +03:00
{
2016-12-08 22:22:09 +03:00
if ( _showMessage )
QMessageBox : : warning ( this , " Warning " , " Application was disconnected " , QMessageBox : : Close ) ;
2016-11-18 22:58:44 +03:00
EASY_GLOBALS . connected = false ;
m_captureAction - > setEnabled ( false ) ;
SET_ICON ( m_connectAction , " :/Connection " ) ;
m_eventTracingEnableAction - > setEnabled ( false ) ;
m_eventTracingPriorityAction - > setEnabled ( false ) ;
emit EASY_GLOBALS . events . connectionChanged ( false ) ;
}
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 ;
}
2016-09-29 23:29:57 +03:00
default :
2016-09-25 11:49:49 +03:00
return ;
2016-09-16 02:11:11 +03:00
}
2016-09-25 11:49:49 +03:00
if ( ! m_listener . connected ( ) )
{
2016-11-18 22:58:44 +03:00
setDisconnected ( ) ;
2016-09-16 02:11:11 +03:00
}
}
2016-11-18 22:58:44 +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 )
{
2016-11-20 21:01:33 +03:00
static_cast < EasyHierarchyWidget * > ( m_treeWidget - > widget ( ) ) - > clear ( true ) ;
2016-08-28 21:06:23 +03:00
2016-11-18 22:58:44 +03:00
: : profiler : : SerializedData serialized_blocks ;
2016-10-02 12:13:12 +03:00
: : profiler : : SerializedData serialized_descriptors ;
2016-08-28 21:06:23 +03:00
: : 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-10-02 12:13:12 +03:00
uint32_t descriptorsNumberInFile = 0 ;
m_reader . get ( serialized_blocks , serialized_descriptors , descriptors , blocks , threads_map , descriptorsNumberInFile , 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-10-02 12:13:12 +03:00
m_bNetworkFileRegime = ! m_reader . isFile ( ) ;
if ( ! m_bNetworkFileRegime )
2016-09-25 11:49:49 +03:00
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-10-02 12:13:12 +03:00
m_descriptorsNumberInFile = descriptorsNumberInFile ;
2016-08-30 22:51:18 +03:00
EASY_GLOBALS . selected_thread = 0 ;
: : 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-30 22:51:18 +03:00
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-09-29 22:40:19 +03:00
m_saveAction - > setEnabled ( true ) ;
m_deleteAction - > setEnabled ( true ) ;
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-10-02 12:13:12 +03:00
m_size . store ( fillTreesFromFile ( m_progress , m_filename . toStdString ( ) . c_str ( ) , m_serializedBlocks , m_serializedDescriptors ,
m_descriptors , m_blocks , m_blocksTree , m_descriptorsNumberInFile , _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 ( ) ;
2016-11-06 14:47:01 +03:00
# if defined(__GNUC__) && __GNUC__ < 5
// gcc 4 has a known bug which has been solved in gcc 5:
// std::stringstream has no swap() method :(
// have to copy all contents... Use gcc 5 or higher!
# pragma message "Warning: in gcc 4 and lower std::stringstream has no swap()! Memory consumption may increase! Better use gcc 5 or higher instead."
m_stream . str ( _stream . str ( ) ) ;
# else
2016-09-25 11:49:49 +03:00
m_stream . swap ( _stream ) ;
2016-11-06 14:47:01 +03:00
# endif
2016-09-25 11:49:49 +03:00
m_thread = : : std : : move ( : : std : : thread ( [ this ] ( bool _enableStatistics ) {
2016-10-02 12:13:12 +03:00
: : std : : ofstream cache_file ( NETWORK_CACHE_FILE , : : std : : fstream : : binary ) ;
if ( cache_file . is_open ( ) ) {
cache_file < < m_stream . str ( ) ;
cache_file . close ( ) ;
}
m_size . store ( fillTreesFromStream ( m_progress , m_stream , m_serializedBlocks , m_serializedDescriptors , m_descriptors ,
m_blocks , m_blocksTree , m_descriptorsNumberInFile , _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-10-02 12:13:12 +03:00
m_descriptorsNumberInFile = 0 ;
2016-09-25 11:49:49 +03:00
2016-11-06 14:47:01 +03:00
clear_stream ( m_stream ) ;
clear_stream ( m_errorMessage ) ;
2016-08-28 21:06:23 +03:00
}
void EasyFileReader : : get ( : : profiler : : SerializedData & _serializedBlocks , : : profiler : : SerializedData & _serializedDescriptors ,
2016-10-02 12:13:12 +03:00
: : profiler : : descriptors_list_t & _descriptors , : : profiler : : blocks_t & _blocks ,
: : profiler : : thread_blocks_tree_t & _tree , uint32_t & _descriptorsNumberInFile , 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-10-02 12:13:12 +03:00
_descriptorsNumberInFile = m_descriptorsNumberInFile ;
2016-08-28 21:06:23 +03:00
}
}
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
2016-09-28 00:37:20 +03:00
void EasyMainWindow : : onEventTracingPriorityChange ( bool _checked )
{
if ( EASY_GLOBALS . connected )
m_listener . send ( profiler : : net : : BoolMessage ( profiler : : net : : MESSAGE_TYPE_EVENT_TRACING_PRIORITY , _checked ) ) ;
}
void EasyMainWindow : : onEventTracingEnableChange ( bool _checked )
{
if ( EASY_GLOBALS . connected )
m_listener . send ( profiler : : net : : BoolMessage ( profiler : : net : : MESSAGE_TYPE_EVENT_TRACING_STATUS , _checked ) ) ;
}
//////////////////////////////////////////////////////////////////////////
2016-11-13 22:02:47 +03:00
void EasyMainWindow : : onFrameTimeEditFinish ( )
{
auto text = m_frameTimeEdit - > text ( ) ;
if ( text . contains ( QChar ( ' , ' ) ) )
{
text . remove ( QChar ( ' . ' ) ) . replace ( QChar ( ' , ' ) , QChar ( ' . ' ) ) ;
m_frameTimeEdit - > setText ( text ) ;
}
EASY_GLOBALS . frame_time = text . toFloat ( ) * 1e3 f ;
emit EASY_GLOBALS . events . timelineMarkerChanged ( ) ;
}
//////////////////////////////////////////////////////////////////////////
2016-09-18 19:02:12 +03:00
void EasyMainWindow : : onConnectClicked ( bool )
{
2016-09-27 22:43:02 +03:00
auto text = m_ipEdit - > text ( ) ;
2016-09-27 23:45:33 +03:00
auto parts = text . split ( QChar ( ' . ' ) ) ;
if ( parts . size ( ) ! = 4 )
2016-09-27 22:43:02 +03:00
{
QMessageBox : : warning ( this , " Warning " , " Invalid IP-Address " , QMessageBox : : Close ) ;
2016-12-08 22:28:02 +03:00
if ( EASY_GLOBALS . connected )
{
// Restore last values
m_ipEdit - > setText ( m_lastAddress ) ;
m_portEdit - > setText ( QString : : number ( m_lastPort ) ) ;
}
2016-09-27 22:43:02 +03:00
return ;
}
2016-09-27 23:45:33 +03:00
for ( auto & part : parts )
{
int i = 0 ;
for ( ; i < part . size ( ) ; + + i )
{
if ( part [ i ] ! = QChar ( ' 0 ' ) )
break ;
}
if ( i < part . size ( ) )
part = part . mid ( i ) ;
else
part = " 0 " ;
}
2016-12-08 22:22:09 +03:00
QString address = parts . join ( QChar ( ' . ' ) ) ;
const decltype ( m_lastPort ) port = m_portEdit - > text ( ) . toUShort ( ) ;
m_ipEdit - > setText ( address ) ;
const bool isReconnecting = ( EASY_GLOBALS . connected & & m_listener . port ( ) = = port & & address . toStdString ( ) = = m_listener . address ( ) ) ;
if ( EASY_GLOBALS . connected )
{
if ( QMessageBox : : question ( this , isReconnecting ? " Reconnect " : " New connection " , QString ( " Are you sure you want to %1? \n Current connection will be broken. " )
. arg ( isReconnecting ? " re-connect " : " connect to the new address " ) ,
QMessageBox : : Yes , QMessageBox : : No ) ! = QMessageBox : : Yes )
{
if ( ! isReconnecting )
{
// Restore last values
m_ipEdit - > setText ( m_lastAddress ) ;
m_portEdit - > setText ( QString : : number ( m_lastPort ) ) ;
}
return ;
}
}
2016-09-28 00:37:20 +03:00
profiler : : net : : EasyProfilerStatus reply ( false , false , false ) ;
2016-12-08 22:22:09 +03:00
if ( ! m_listener . connect ( address . toStdString ( ) . c_str ( ) , port , reply ) )
2016-09-18 19:02:12 +03:00
{
2016-12-08 22:22:09 +03:00
if ( EASY_GLOBALS . connected & & ! isReconnecting )
{
m_ipEdit - > setText ( m_lastAddress ) ;
m_portEdit - > setText ( QString : : number ( m_lastPort ) ) ;
if ( ! m_listener . connect ( m_lastAddress . toStdString ( ) . c_str ( ) , m_lastPort , reply ) )
{
QMessageBox : : warning ( this , " Warning " , QString ( " Cannot connect to %1. \n Previous connection lost. " ) . arg ( address ) , QMessageBox : : Close ) ;
setDisconnected ( false ) ;
}
else
{
QMessageBox : : information ( this , " Information " , QString ( " Cannot connect to %1. \n Restored previous connection. " ) . arg ( address ) , QMessageBox : : Close ) ;
}
}
else
{
QMessageBox : : warning ( this , " Warning " , QString ( " Cannot connect to %1 " ) . arg ( address ) , QMessageBox : : Close ) ;
if ( EASY_GLOBALS . connected )
setDisconnected ( false ) ;
}
2016-09-18 19:02:12 +03:00
return ;
}
2016-12-08 22:22:09 +03:00
m_lastAddress = : : std : : move ( address ) ;
m_lastPort = port ;
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
2016-09-28 00:37:20 +03:00
disconnect ( m_eventTracingEnableAction , & QAction : : triggered , this , & This : : onEventTracingEnableChange ) ;
disconnect ( m_eventTracingPriorityAction , & QAction : : triggered , this , & This : : onEventTracingPriorityChange ) ;
m_eventTracingEnableAction - > setEnabled ( true ) ;
m_eventTracingPriorityAction - > setEnabled ( true ) ;
m_eventTracingEnableAction - > setChecked ( reply . isEventTracingEnabled ) ;
m_eventTracingPriorityAction - > setChecked ( reply . isLowPriorityEventTracing ) ;
connect ( m_eventTracingEnableAction , & QAction : : triggered , this , & This : : onEventTracingEnableChange ) ;
connect ( m_eventTracingPriorityAction , & QAction : : triggered , this , & This : : onEventTracingPriorityChange ) ;
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-12-04 16:51:27 +03:00
m_listenerDialog = new QMessageBox ( QMessageBox : : Information , " Capturing frames... " , " Close this dialog to stop capturing. " , QMessageBox : : NoButton , this ) ;
m_listenerDialog - > addButton ( " Stop " , QMessageBox : : AcceptRole ) ;
2016-09-25 11:49:49 +03:00
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
2016-10-02 16:17:22 +03:00
2016-09-25 11:49:49 +03:00
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
{
2016-10-02 16:17:22 +03:00
// Merge old and new descriptions
2016-09-25 11:49:49 +03:00
2016-09-29 22:40:19 +03:00
bool cancel = false ;
2016-10-02 16:17:22 +03:00
const bool doFlush = m_descriptorsNumberInFile > descriptors . size ( ) ;
2016-10-02 12:13:12 +03:00
if ( doFlush & & ! m_serializedBlocks . empty ( ) )
2016-09-29 22:40:19 +03:00
{
auto button = QMessageBox : : question ( this , " Information " ,
2016-10-02 16:17:22 +03:00
QString ( " New blocks description number = %1 \n is less than the old one = %2. \n To avoid possible conflicts \n all profiled data will be deleted. \n Continue? " )
2016-09-29 22:40:19 +03:00
. arg ( descriptors . size ( ) )
2016-10-02 12:13:12 +03:00
. arg ( m_descriptorsNumberInFile ) ,
2016-09-29 22:40:19 +03:00
QMessageBox : : Yes , QMessageBox : : No ) ;
if ( button = = QMessageBox : : Yes )
2016-10-02 12:13:12 +03:00
clear ( ) ; // Clear all contents because new descriptors list conflicts with old one
2016-09-29 22:40:19 +03:00
else
cancel = true ;
}
2016-09-25 11:49:49 +03:00
2016-09-29 22:40:19 +03:00
if ( ! cancel )
2016-09-25 11:49:49 +03:00
{
2016-10-02 16:17:22 +03:00
if ( ! doFlush & & m_descriptorsNumberInFile < EASY_GLOBALS . descriptors . size ( ) )
2016-09-29 22:40:19 +03:00
{
// There are dynamically added descriptors, add them to the new list too
2016-10-02 16:17:22 +03:00
auto newnumber = static_cast < decltype ( m_descriptorsNumberInFile ) > ( descriptors . size ( ) ) ;
auto size = static_cast < decltype ( m_descriptorsNumberInFile ) > ( EASY_GLOBALS . descriptors . size ( ) ) ;
auto diff = newnumber - size ;
decltype ( newnumber ) failnumber = 0 ;
descriptors . reserve ( descriptors . size ( ) + EASY_GLOBALS . descriptors . size ( ) - m_descriptorsNumberInFile ) ;
for ( auto i = m_descriptorsNumberInFile ; i < size ; + + i )
2016-09-29 22:40:19 +03:00
{
2016-10-02 16:17:22 +03:00
auto id = EASY_GLOBALS . descriptors [ i ] - > id ( ) ;
if ( id < newnumber )
descriptors . push_back ( descriptors [ id ] ) ;
else
+ + failnumber ;
}
2016-09-29 22:40:19 +03:00
2016-10-02 16:17:22 +03:00
if ( failnumber ! = 0 )
{
// There are some errors...
// revert changes
descriptors . resize ( newnumber ) ;
// clear all profiled data to avoid conflicts
auto button = QMessageBox : : question ( this , " Information " ,
" There are errors while merging block descriptions lists. \n To avoid possible conflicts \n all profiled data will be deleted. \n Continue? " ,
QMessageBox : : Yes , QMessageBox : : No ) ;
if ( button = = QMessageBox : : Yes )
clear ( ) ; // Clear all contents because new descriptors list conflicts with old one
else
2016-09-29 22:40:19 +03:00
cancel = true ;
2016-10-02 16:17:22 +03:00
}
if ( ! cancel & & diff ! = 0 )
{
for ( auto & b : EASY_GLOBALS . gui_blocks )
{
if ( b . tree . node - > id ( ) > = m_descriptorsNumberInFile )
b . tree . node - > setId ( b . tree . node - > id ( ) + diff ) ;
2016-09-29 22:40:19 +03:00
}
2016-10-02 16:17:22 +03:00
m_descriptorsNumberInFile = newnumber ;
2016-09-29 22:40:19 +03:00
}
}
if ( ! cancel )
{
2016-10-02 16:17:22 +03:00
EASY_GLOBALS . descriptors . swap ( descriptors ) ;
m_serializedDescriptors . swap ( serializedDescriptors ) ;
2016-11-20 18:33:56 +03:00
m_descriptorsNumberInFile = static_cast < uint32_t > ( EASY_GLOBALS . descriptors . size ( ) ) ;
2016-10-02 16:17:22 +03:00
2016-09-29 22:40:19 +03:00
if ( m_descTreeDialog ! = nullptr )
{
2016-09-25 11:49:49 +03:00
# if EASY_GUI_USE_DESCRIPTORS_DOCK_WINDOW != 0
2016-09-29 22:40:19 +03:00
static_cast < EasyDescWidget * > ( m_descTreeWidget - > widget ( ) ) - > build ( ) ;
2016-09-25 11:49:49 +03:00
# endif
2016-09-29 22:40:19 +03:00
m_dialogDescTree - > build ( ) ;
m_descTreeDialog - > raise ( ) ;
}
else
{
onEditBlocksClicked ( true ) ;
}
}
2016-09-25 11:49:49 +03:00
}
}
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 ( ) )
{
2016-11-18 22:58:44 +03:00
setDisconnected ( ) ;
2016-09-25 11:49:49 +03:00
}
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 )
2016-09-28 00:37:20 +03:00
m_listener . send ( profiler : : net : : BlockStatusMessage ( _id , static_cast < uint8_t > ( _status ) ) ) ;
2016-09-18 19:02:12 +03:00
}
2016-09-25 11:49:49 +03:00
//////////////////////////////////////////////////////////////////////////
2016-12-08 22:22:09 +03:00
EasySocketListener : : EasySocketListener ( ) : m_receivedSize ( 0 ) , m_port ( 0 ) , m_regime ( LISTENER_IDLE )
2016-09-29 23:29:57 +03:00
{
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 ;
}
2016-12-08 22:22:09 +03:00
const : : std : : string & EasySocketListener : : address ( ) const
{
return m_address ;
}
uint16_t EasySocketListener : : port ( ) const
{
return m_port ;
}
2016-09-29 23:29:57 +03:00
void EasySocketListener : : clearData ( )
{
2016-11-06 14:47:01 +03:00
clear_stream ( m_receivedData ) ;
2016-09-29 23:29:57 +03:00
m_receivedSize = 0 ;
}
bool EasySocketListener : : connect ( const char * _ipaddress , uint16_t _port , profiler : : net : : EasyProfilerStatus & _reply )
{
if ( connected ( ) )
2016-12-08 22:22:09 +03:00
{
m_bInterrupt . store ( true , : : std : : memory_order_release ) ;
if ( m_thread . joinable ( ) )
m_thread . join ( ) ;
m_bConnected . store ( false , : : std : : memory_order_release ) ;
m_bInterrupt . store ( false , : : std : : memory_order_release ) ;
}
m_address . clear ( ) ;
m_port = 0 ;
2016-09-29 23:29:57 +03:00
2016-09-25 11:49:49 +03:00
m_easySocket . flush ( ) ;
m_easySocket . init ( ) ;
int res = m_easySocket . setAddress ( _ipaddress , _port ) ;
2016-09-29 23:29:57 +03:00
res = m_easySocket . connect ( ) ;
const bool isConnected = res = = 0 ;
if ( isConnected )
{
static const size_t buffer_size = sizeof ( profiler : : net : : EasyProfilerStatus ) < < 1 ;
2016-09-28 00:37:20 +03:00
char buffer [ buffer_size ] = { } ;
int bytes = 0 ;
while ( true )
{
bytes = m_easySocket . receive ( buffer , buffer_size ) ;
if ( bytes = = - 1 )
{
2016-11-18 22:58:44 +03:00
if ( m_easySocket . isDisconnected ( ) )
2016-09-28 00:37:20 +03:00
return false ;
bytes = 0 ;
continue ;
}
break ;
}
if ( bytes = = 0 )
{
2016-12-08 22:22:09 +03:00
m_address = _ipaddress ;
m_port = _port ;
2016-09-29 23:29:57 +03:00
m_bConnected . store ( isConnected , : : std : : memory_order_release ) ;
2016-09-28 00:37:20 +03:00
return isConnected ;
}
2016-11-13 15:20:25 +03:00
size_t seek = bytes ;
2016-09-28 00:37:20 +03:00
while ( seek < sizeof ( profiler : : net : : EasyProfilerStatus ) )
{
bytes = m_easySocket . receive ( buffer + seek , buffer_size - seek ) ;
if ( bytes = = - 1 )
{
2016-11-18 22:58:44 +03:00
if ( m_easySocket . isDisconnected ( ) )
2016-09-28 00:37:20 +03:00
return false ;
break ;
}
seek + = bytes ;
}
auto message = reinterpret_cast < const : : profiler : : net : : EasyProfilerStatus * > ( buffer ) ;
if ( message - > isEasyNetMessage ( ) & & message - > type = = profiler : : net : : MESSAGE_TYPE_ACCEPTED_CONNECTION )
_reply = * message ;
2016-12-08 22:22:09 +03:00
m_address = _ipaddress ;
m_port = _port ;
2016-09-29 23:29:57 +03:00
}
m_bConnected . store ( isConnected , : : std : : memory_order_release ) ;
return isConnected ;
}
void EasySocketListener : : startCapture ( )
{
clearData ( ) ;
2016-09-25 11:49:49 +03:00
profiler : : net : : Message request ( profiler : : net : : MESSAGE_TYPE_REQUEST_START_CAPTURE ) ;
2016-09-29 23:29:57 +03:00
m_easySocket . send ( & request , sizeof ( request ) ) ;
2016-11-18 22:58:44 +03:00
if ( m_easySocket . isDisconnected ( ) ) {
m_bConnected . store ( false , : : std : : memory_order_release ) ;
}
2016-09-29 23:29:57 +03:00
m_regime = LISTENER_CAPTURE ;
2016-09-25 11:49:49 +03:00
m_thread = : : std : : move ( : : std : : thread ( & EasySocketListener : : listenCapture , this ) ) ;
2016-09-29 23:29:57 +03:00
}
void EasySocketListener : : stopCapture ( )
{
if ( ! m_thread . joinable ( ) | | m_regime ! = LISTENER_CAPTURE )
return ;
2016-09-25 11:49:49 +03:00
profiler : : net : : Message request ( profiler : : net : : MESSAGE_TYPE_REQUEST_STOP_CAPTURE ) ;
m_easySocket . send ( & request , sizeof ( request ) ) ;
2016-11-18 22:58:44 +03:00
if ( m_easySocket . isDisconnected ( ) ) {
m_bConnected . store ( false , : : std : : memory_order_release ) ;
}
2016-09-29 23:29:57 +03:00
m_thread . join ( ) ;
m_regime = LISTENER_IDLE ;
}
void EasySocketListener : : requestBlocksDescription ( )
{
clearData ( ) ;
2016-09-25 11:49:49 +03:00
profiler : : net : : Message request ( profiler : : net : : MESSAGE_TYPE_REQUEST_BLOCKS_DESCRIPTION ) ;
2016-09-29 23:29:57 +03:00
m_easySocket . send ( & request , sizeof ( request ) ) ;
2016-11-18 22:58:44 +03:00
if ( m_easySocket . isDisconnected ( ) ) {
m_bConnected . store ( false , : : std : : memory_order_release ) ;
}
2016-09-29 23:29:57 +03:00
m_regime = LISTENER_DESCRIBE ;
listenDescription ( ) ;
m_regime = LISTENER_IDLE ;
}
//////////////////////////////////////////////////////////////////////////
2016-09-25 11:49:49 +03:00
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 )
{
2016-11-18 22:58:44 +03:00
if ( m_easySocket . isDisconnected ( ) )
2016-09-25 11:49:49 +03:00
{
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 )
{
2016-11-18 22:58:44 +03:00
if ( m_easySocket . isDisconnected ( ) )
2016-09-25 11:49:49 +03:00
{
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-11-18 22:58:44 +03:00
if ( m_easySocket . isDisconnected ( ) )
2016-09-25 11:49:49 +03:00
{
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 )
{
2016-11-18 22:58:44 +03:00
if ( m_easySocket . isDisconnected ( ) )
2016-09-25 11:49:49 +03:00
{
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
//////////////////////////////////////////////////////////////////////////