0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-29 10:05:48 +08:00
easy_profiler/profiler_gui/main_window.cpp

1087 lines
36 KiB
C++
Raw Normal View History

/************************************************************************
* 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-09-15 23:56:20 +03:00
#include <QApplication>
#include <QStatusBar>
#include <QDockWidget>
#include <QFileDialog>
#include <QAction>
#include <QMenu>
#include <QMenuBar>
#include <QCoreApplication>
#include <QCloseEvent>
#include <QSettings>
#include <QTextCodec>
#include <QFont>
#include <QProgressDialog>
#include <QSignalBlocker>
#include <QDebug>
2016-09-08 21:03:05 +03:00
#include <QToolBar>
#include <QMessageBox>
2016-09-13 21:42:38 +03:00
#include <QDialog>
#include <QFormLayout>
#include <QPushButton>
#include "main_window.h"
#include "blocks_tree_widget.h"
#include "blocks_graphics_view.h"
#include "globals.h"
2016-09-08 21:03:05 +03:00
#include "profiler/easy_net.h"
#include <thread>
#include <chrono>
#include <fstream>
2016-09-15 22:41:47 +03:00
2016-09-16 02:11:11 +03:00
2016-09-15 22:41:47 +03:00
#undef max
//////////////////////////////////////////////////////////////////////////
const int LOADER_TIMER_INTERVAL = 40;
//////////////////////////////////////////////////////////////////////////
EasyMainWindow::EasyMainWindow() : Parent(), m_treeWidget(nullptr), m_graphicsView(nullptr), m_progress(nullptr)
{
2016-09-15 23:56:20 +03:00
{ QIcon icon(":/logo"); if (!icon.isNull()) QApplication::setWindowIcon(icon); }
setObjectName("ProfilerGUI_MainWindow");
setWindowTitle("EasyProfiler Reader beta");
setDockNestingEnabled(true);
resize(800, 600);
setStatusBar(new QStatusBar());
auto graphicsView = new EasyGraphicsViewWidget();
m_graphicsView = new QDockWidget("Blocks diagram");
m_graphicsView->setMinimumHeight(50);
m_graphicsView->setAllowedAreas(Qt::AllDockWidgetAreas);
m_graphicsView->setWidget(graphicsView);
auto treeWidget = new EasyTreeWidget();
m_treeWidget = new QDockWidget("Blocks hierarchy");
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-08 21:03:05 +03:00
QToolBar *fileToolBar = addToolBar(tr("File"));
m_connectAct = new QAction(tr("&Connect"), this);
SET_ICON(m_connectAct, ":/WiFi");
2016-09-15 22:41:47 +03:00
2016-09-08 21:03:05 +03:00
QAction *newAct = new QAction(tr("&Capture"), this);
2016-09-16 01:37:50 +03:00
SET_ICON(newAct, ":/Start");
fileToolBar->addAction(m_connectAct);
2016-09-08 21:03:05 +03:00
fileToolBar->addAction(newAct);
2016-09-13 21:42:38 +03:00
2016-09-08 21:03:05 +03:00
connect(newAct, &QAction::triggered, this, &This::onCaptureClicked);
connect(m_connectAct, &QAction::triggered, this, &This::onConnectClicked);
2016-09-08 21:03:05 +03:00
2016-09-13 21:42:38 +03:00
m_hostString = new QLineEdit();
QRegExp rx("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}");
QRegExpValidator regValidator(rx, 0);
m_hostString->setInputMask("000.000.000.000;");
m_hostString->setValidator(&regValidator);
m_hostString->setText("127.0.0.1");
fileToolBar->addWidget(m_hostString);
2016-09-08 21:03:05 +03:00
2016-09-13 21:42:38 +03:00
m_portString = new QLineEdit();
m_portString->setValidator(new QIntValidator(1024, 65536, this));
m_portString->setText(QString::number(profiler::DEFAULT_PORT));
fileToolBar->addWidget(m_portString);
2016-09-14 22:04:15 +03:00
/*m_server = new QTcpSocket( );
m_server->setSocketOption(QAbstractSocket::LowDelayOption, 0);
m_server->setReadBufferSize(16 * 1024);
2016-09-12 22:10:45 +03:00
2016-09-14 22:04:15 +03:00
//connect(m_server, SIGNAL(readyRead()), SLOT(readTcpData()));
2016-09-13 21:42:38 +03:00
connect(m_server, SIGNAL(connected()), SLOT(onConnected()));
connect(m_server, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(onErrorConnection(QAbstractSocket::SocketError)), Qt::UniqueConnection);
connect(m_server, SIGNAL(disconnected()), SLOT(onDisconnect()), Qt::UniqueConnection);
2016-09-14 22:04:15 +03:00
m_receiver = new TcpReceiverThread(this, this);
connect(m_receiver, &TcpReceiverThread::resultReady, this, &This::handleResults);
connect(m_receiver, &TcpReceiverThread::finished, m_receiver, &QObject::deleteLater);
m_receiver->start();
*/
2016-09-16 02:11:11 +03:00
//m_thread = std::thread(&This::listen, this);
2016-09-13 21:42:38 +03:00
2016-09-14 22:04:15 +03:00
//connect(m_server, &QAbstractSocket::readyRead, m_receiver, &TcpReceiverThread::readTcpData);
//m_receiver->run();
//m_server->connectToHost(m_hostString->text(), m_portString->text().toUShort());
2016-09-13 21:42:38 +03:00
//TODO:
//connected
//error
2016-09-08 21:03:05 +03:00
2016-09-12 21:28:15 +03:00
/*if (!m_server->listen(QHostAddress(QHostAddress::Any), 28077)) {
2016-09-08 21:03:05 +03:00
QMessageBox::critical(0,
"Server Error",
"Unable to start the server:"
+ m_server->errorString()
);
m_server->close();
}
connect(m_server, SIGNAL(newConnection()),
2016-09-12 21:28:15 +03:00
this, SLOT(onNewConnection())
2016-09-08 21:03:05 +03:00
);
2016-09-12 21:28:15 +03:00
*/
loadSettings();
auto menu = new QMenu("&File");
auto action = menu->addAction("&Open");
connect(action, &QAction::triggered, this, &This::onOpenFileClicked);
2016-09-15 23:56:20 +03:00
SET_ICON(action, ":/Open");
action = menu->addAction("&Reload");
connect(action, &QAction::triggered, this, &This::onReloadFileClicked);
2016-09-15 23:56:20 +03:00
SET_ICON(action, ":/Reload");
menu->addSeparator();
action = menu->addAction("&Exit");
connect(action, &QAction::triggered, this, &This::onExitClicked);
2016-09-15 23:56:20 +03:00
SET_ICON(action, ":/Exit");
menuBar()->addMenu(menu);
menu = new QMenu("&View");
action = menu->addAction("Expand all");
connect(action, &QAction::triggered, this, &This::onExpandAllClicked);
2016-09-15 23:56:20 +03:00
SET_ICON(action, ":/Expand");
action = menu->addAction("Collapse all");
connect(action, &QAction::triggered, this, &This::onCollapseAllClicked);
2016-09-15 23:56:20 +03:00
SET_ICON(action, ":/Collapse");
menu->addSeparator();
action = menu->addAction("Draw items' borders");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.draw_graphics_items_borders);
connect(action, &QAction::triggered, this, &This::onDrawBordersChanged);
action = menu->addAction("Collapse items on tree reset");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.collapse_items_on_tree_close);
connect(action, &QAction::triggered, this, &This::onCollapseItemsAfterCloseChanged);
action = menu->addAction("Expand all on file open");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.all_items_expanded_by_default);
connect(action, &QAction::triggered, this, &This::onAllItemsExpandedByDefaultChange);
action = menu->addAction("Bind scene and tree expand");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.bind_scene_and_tree_expand_status);
connect(action, &QAction::triggered, this, &This::onBindExpandStatusChange);
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));
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Top)
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));
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Center)
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));
if (EASY_GLOBALS.chrono_text_position == ::profiler_gui::ChronoTextPosition_Bottom)
action->setChecked(true);
submenu->addAction(action);
connect(action, &QAction::triggered, this, &This::onChronoTextPosChanged);
menuBar()->addMenu(menu);
menu = new QMenu("&Settings");
action = new QAction("Statistics enabled", nullptr);
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");
}
else
{
action->setText("Statistics disabled");
2016-09-15 23:56:20 +03:00
SET_ICON(action, ":/Stats-off");
}
menu->addAction(action);
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);
}
menuBar()->addMenu(menu);
connect(graphicsView->view(), &EasyGraphicsView::intervalChanged, treeWidget, &EasyTreeWidget::setTreeBlocks);
connect(&m_readerTimer, &QTimer::timeout, this, &This::onFileReaderTimeout);
2016-09-16 02:11:11 +03:00
connect(&m_downloadedTimer, &QTimer::timeout, this, &This::onDownloadTimeout);
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);
m_downloadingProgress = new QProgressDialog("Loading file...", "Cancel", 0, 100, this);
m_downloadingProgress->setFixedWidth(300);
m_downloadingProgress->setWindowTitle("EasyProfiler");
m_downloadingProgress->setModal(true);
m_downloadingProgress->setValue(100);
//m_downloadedTimer.start(10);
loadGeometry();
if(QCoreApplication::arguments().size() > 1)
{
auto opened_filename = QCoreApplication::arguments().at(1);
loadFile(opened_filename);
}
2016-09-14 22:04:15 +03:00
}
void EasyMainWindow::listen()
{
profiler::net::Message request(profiler::net::MESSAGE_TYPE_REQUEST_START_CAPTURE);
2016-09-16 02:11:11 +03:00
2016-09-14 22:04:15 +03:00
//std::this_thread::sleep_for(std::chrono::seconds(2));
2016-09-16 02:11:11 +03:00
const int buffer_size = 8 * 1024 * 1024;
char* buffer = new char[buffer_size];
2016-09-14 22:04:15 +03:00
int seek = 0;
2016-09-16 02:11:11 +03:00
int bytes = 0;
2016-09-14 22:04:15 +03:00
static auto timeBegin = std::chrono::system_clock::now();
2016-09-16 22:51:15 +03:00
bool isListen = true;
while (isListen)
2016-09-14 22:04:15 +03:00
{
2016-09-16 02:11:11 +03:00
if ((bytes - seek) == 0){
bytes = m_easySocket.receive(buffer, buffer_size);
2016-09-16 22:51:15 +03:00
if(bytes == -1)
{
2016-09-18 16:43:43 +03:00
if(m_easySocket.state() == EasySocket::CONNECTION_STATE_DISCONNECTED)
{
isListen = false;
}
seek = 0;
bytes = 0;
2016-09-16 22:51:15 +03:00
continue;
}
2016-09-16 02:11:11 +03:00
seek = 0;
}
2016-09-14 22:04:15 +03:00
char *buf = &buffer[seek];
2016-09-16 02:11:11 +03:00
2016-09-18 16:43:43 +03:00
if(bytes == 0){
isListen = false;
continue;
}
2016-09-14 22:04:15 +03:00
if (bytes > 0)
{
profiler::net::Message* message = (profiler::net::Message*)buf;
if (!message->isEasyNetMessage()){
continue;
}
switch (message->type) {
case profiler::net::MESSAGE_TYPE_ACCEPTED_CONNECTION:
{
qInfo() << "Receive MESSAGE_TYPE_ACCEPTED_CONNECTION";
2016-09-16 02:11:11 +03:00
//m_easySocket.send(&request, sizeof(request));
seek += sizeof(profiler::net::Message);
2016-09-14 22:04:15 +03:00
}
break;
case profiler::net::MESSAGE_TYPE_REPLY_START_CAPTURING:
{
qInfo() << "Receive MESSAGE_TYPE_REPLY_START_CAPTURING";
2016-09-16 02:11:11 +03:00
seek += sizeof(profiler::net::Message);
2016-09-14 22:04:15 +03:00
}
break;
case profiler::net::MESSAGE_TYPE_REPLY_PREPARE_BLOCKS:
{
qInfo() << "Receive MESSAGE_TYPE_REPLY_PREPARE_BLOCKS";
m_isClientPreparedBlocks = true;
2016-09-16 02:11:11 +03:00
seek += sizeof(profiler::net::Message);
2016-09-14 22:04:15 +03:00
}
break;
case profiler::net::MESSAGE_TYPE_REPLY_END_SEND_BLOCKS:
{
qInfo() << "Receive MESSAGE_TYPE_REPLY_END_SEND_BLOCKS";
2016-09-16 02:11:11 +03:00
seek += sizeof(profiler::net::Message);
2016-09-14 22:04:15 +03:00
auto timeEnd = std::chrono::system_clock::now();
auto dT = std::chrono::duration_cast<std::chrono::milliseconds>(timeEnd - timeBegin);
auto dTsec = std::chrono::duration_cast<std::chrono::seconds>(timeEnd - timeBegin);
qInfo() << "recieve" << m_receivedProfileData.str().size() << dT.count() << "ms" << double(m_receivedProfileData.str().size())*1000.0 / double(dT.count()) / 1024.0 << "kBytes/sec";
m_recFrames = false;
qInfo() << "Write FILE";
std::string tempfilename = "test_rec.prof";
std::ofstream of(tempfilename, std::fstream::binary);
of << m_receivedProfileData.str();
of.close();
m_receivedProfileData.str(std::string());
m_receivedProfileData.clear();
2016-09-16 02:11:11 +03:00
//loadFile(QString(tempfilename.c_str()));
2016-09-14 22:04:15 +03:00
m_recFrames = false;
2016-09-16 22:51:15 +03:00
isListen = false;
continue;
2016-09-14 22:04:15 +03:00
}
break;
case profiler::net::MESSAGE_TYPE_REPLY_BLOCKS:
{
qInfo() << "Receive MESSAGE_TYPE_REPLY_BLOCKS";
2016-09-16 02:11:11 +03:00
seek += sizeof(profiler::net::DataMessage);
profiler::net::DataMessage* dm = (profiler::net::DataMessage*)message;
2016-09-14 22:04:15 +03:00
timeBegin = std::chrono::system_clock::now();
2016-09-16 02:11:11 +03:00
int neededSize = dm->size;
buf = &buffer[seek];
m_receivedProfileData.write(buf, bytes - seek);
neededSize -= bytes - seek;
seek = 0;
bytes = 0;
int loaded = 0;
while (neededSize > 0)
{
bytes = m_easySocket.receive(buffer, buffer_size);
2016-09-16 22:51:15 +03:00
if(bytes == -1)
{
2016-09-18 16:43:43 +03:00
if(m_easySocket.state() == EasySocket::CONNECTION_STATE_DISCONNECTED)
{
isListen = false;
neededSize = 0;
}
2016-09-16 22:51:15 +03:00
continue;
}
2016-09-16 02:11:11 +03:00
buf = &buffer[0];
int toWrite = std::min(bytes, neededSize);
m_receivedProfileData.write(buf, toWrite);
neededSize -= toWrite;
loaded += toWrite;
seek = toWrite;
m_downloadedBytes.store((loaded / (neededSize+1)) * 100);
}
2016-09-14 22:04:15 +03:00
} break;
default:
//qInfo() << "Receive unknown " << message->type;
break;
}
}
}
2016-09-18 16:43:43 +03:00
2016-09-16 22:51:15 +03:00
delete [] buffer;
}
EasyMainWindow::~EasyMainWindow()
{
delete m_progress;
2016-09-16 02:11:11 +03:00
if (m_thread.joinable())
m_thread.join();
}
//////////////////////////////////////////////////////////////////////////
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);
}
//////////////////////////////////////////////////////////////////////////
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);
}
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow::onReloadFileClicked(bool)
{
if (m_lastFile.isEmpty())
return;
loadFile(m_lastFile);
}
//////////////////////////////////////////////////////////////////////////
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());
EASY_GLOBALS.chrono_text_position = static_cast<::profiler_gui::ChronometerTextPosition>(_sender->data().toInt());
emit EASY_GLOBALS.events.chronoPositionChanged();
}
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");
}
else
{
action->setText("Statistics disabled");
2016-09-15 23:56:20 +03:00
SET_ICON(action, ":/Stats-off");
}
}
}
void EasyMainWindow::onDrawBordersChanged(bool _checked)
{
EASY_GLOBALS.draw_graphics_items_borders = _checked;
emit EASY_GLOBALS.events.drawBordersChanged();
}
void EasyMainWindow::onCollapseItemsAfterCloseChanged(bool _checked)
{
EASY_GLOBALS.collapse_items_on_tree_close = _checked;
}
void EasyMainWindow::onAllItemsExpandedByDefaultChange(bool _checked)
{
EASY_GLOBALS.all_items_expanded_by_default = _checked;
}
void EasyMainWindow::onBindExpandStatusChange(bool _checked)
{
EASY_GLOBALS.bind_scene_and_tree_expand_status = _checked;
}
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow::onExpandAllClicked(bool)
{
for (auto& block : EASY_GLOBALS.gui_blocks)
block.expanded = true;
emit EASY_GLOBALS.events.itemsExpandStateChanged();
auto tree = static_cast<EasyTreeWidget*>(m_treeWidget->widget());
const QSignalBlocker b(tree);
tree->expandAll();
}
void EasyMainWindow::onCollapseAllClicked(bool)
{
for (auto& block : EASY_GLOBALS.gui_blocks)
block.expanded = false;
emit EASY_GLOBALS.events.itemsExpandStateChanged();
auto tree = static_cast<EasyTreeWidget*>(m_treeWidget->widget());
const QSignalBlocker b(tree);
tree->collapseAll();
}
2016-09-13 21:42:38 +03:00
void EasyMainWindow::onConnectClicked(bool)
{
2016-09-16 22:51:15 +03:00
if(m_isConnected)
return;
m_easySocket.flush();
m_easySocket.init();
2016-09-16 02:11:11 +03:00
int res = m_easySocket.setAddress(m_hostString->text().toStdString().c_str(), m_portString->text().toUShort());
//TODO: flush socket after disconenct
2016-09-16 02:11:11 +03:00
res = m_easySocket.connect();
if (res == -1)
{
QMessageBox::warning(this, "Warning", "Cannot connect with application", QMessageBox::Close);
return;
}
qInfo() << "Connect with application successful";
m_isConnected = true;
2016-09-18 16:46:35 +03:00
auto _sender = qobject_cast<QAction*>(sender());
if (_sender)
SET_ICON(_sender, ":/WiFi-on");
2016-09-13 21:42:38 +03:00
}
2016-09-08 21:03:05 +03:00
void EasyMainWindow::onCaptureClicked(bool)
{
2016-09-13 21:42:38 +03:00
if (!m_isConnected)
{
QMessageBox::warning(this, "Warning", "No connection with profiling app", QMessageBox::Close);
return;
}
2016-09-16 02:11:11 +03:00
profiler::net::Message request(profiler::net::MESSAGE_TYPE_REQUEST_START_CAPTURE);
m_easySocket.send(&request, sizeof(request));
m_thread = std::thread(&This::listen, this);
2016-09-12 22:10:45 +03:00
2016-09-08 21:03:05 +03:00
QMessageBox::information(this,"Capturing frames..." ,"Close this window to stop capturing.",QMessageBox::Close);
2016-09-16 02:11:11 +03:00
request.type = profiler::net::MESSAGE_TYPE_REQUEST_STOP_CAPTURE;
m_easySocket.send(&request, sizeof(request));
m_thread.join();
m_downloading = false;
2016-09-16 22:51:15 +03:00
if(m_easySocket.state() == EasySocket::CONNECTION_STATE_DISCONNECTED)
{
QMessageBox::warning(this,"Warning" ,"Application was disconnected",QMessageBox::Close);
m_isConnected = false;
SET_ICON(m_connectAct, ":/WiFi");
2016-09-16 22:51:15 +03:00
return;
}
2016-09-16 02:11:11 +03:00
std::string tempfilename = "test_rec.prof";
loadFile(QString(tempfilename.c_str()));
2016-09-13 21:42:38 +03:00
2016-09-14 22:04:15 +03:00
}
void EasyMainWindow::handleResults(const QString &s)
{
}
2016-09-08 21:03:05 +03:00
void EasyMainWindow::readTcpData()
{
2016-09-13 21:42:38 +03:00
static qint64 necessarySize = 0;
static qint64 loadedSize = 0;
2016-09-14 22:04:15 +03:00
static auto timeBegin = std::chrono::system_clock::now();
2016-09-13 21:42:38 +03:00
while(m_server->bytesAvailable())
2016-09-08 21:03:05 +03:00
{
2016-09-13 21:42:38 +03:00
auto bytesExpected = necessarySize - loadedSize;
QByteArray data;
if (m_recFrames){
data = m_server->read(qMin(bytesExpected, m_server->bytesAvailable()));
}
else
{
data = m_server->readAll();
}
2016-09-08 21:03:05 +03:00
profiler::net::Message* message = (profiler::net::Message*)data.data();
2016-09-08 23:15:01 +03:00
//qInfo() << "rec size: " << data.size() << " " << QString(data);;
2016-09-08 21:03:05 +03:00
if(!m_recFrames && !message->isEasyNetMessage()){
return;
2016-09-13 21:42:38 +03:00
}
else if (m_recFrames){
2016-09-14 22:04:15 +03:00
2016-09-13 21:42:38 +03:00
if (m_receivedProfileData.str().size() == necessarySize)
2016-09-11 18:23:47 +03:00
{
2016-09-12 22:10:45 +03:00
m_recFrames = false;
2016-09-14 22:04:15 +03:00
auto timeEnd = std::chrono::system_clock::now();
auto dT = std::chrono::duration_cast<std::chrono::milliseconds>(timeEnd - timeBegin);
auto dTsec = std::chrono::duration_cast<std::chrono::seconds>(timeEnd - timeBegin);
qInfo() << "recieve" << m_receivedProfileData.str().size() << dT.count() << "ms" << double(m_receivedProfileData.str().size())*1000.0 / double(dT.count()) / 1024.0 << "kBytes/sec";
2016-09-13 21:42:38 +03:00
m_recFrames = false;
qInfo() << "Write FILE";
std::string tempfilename = "test_rec.prof";
std::ofstream of(tempfilename, std::fstream::binary);
of << m_receivedProfileData.str();
of.close();
m_receivedProfileData.str(std::string());
m_receivedProfileData.clear();
loadFile(QString(tempfilename.c_str()));
m_recFrames = false;
2016-09-14 22:04:15 +03:00
2016-09-13 21:42:38 +03:00
}
2016-09-14 22:04:15 +03:00
2016-09-13 21:42:38 +03:00
if (m_receivedProfileData.str().size() > necessarySize)
{
qInfo() << "recieve more than necessary d=" << m_receivedProfileData.str().size() - necessarySize;
2016-09-11 18:23:47 +03:00
}
2016-09-12 22:10:45 +03:00
if (m_recFrames)
2016-09-14 22:04:15 +03:00
{
m_receivedProfileData.write(data.data(), data.size());
loadedSize += data.size();
2016-09-12 22:10:45 +03:00
continue;
2016-09-14 22:04:15 +03:00
}
2016-09-08 21:03:05 +03:00
}
switch (message->type) {
2016-09-12 22:10:45 +03:00
case profiler::net::MESSAGE_TYPE_ACCEPTED_CONNECTION:
{
qInfo() << "Receive MESSAGE_TYPE_ACCEPTED_CONNECTION";
}
break;
2016-09-08 21:03:05 +03:00
case profiler::net::MESSAGE_TYPE_REPLY_START_CAPTURING:
{
qInfo() << "Receive MESSAGE_TYPE_REPLY_START_CAPTURING";
m_isClientCaptured = true;
}
break;
case profiler::net::MESSAGE_TYPE_REPLY_PREPARE_BLOCKS:
{
qInfo() << "Receive MESSAGE_TYPE_REPLY_PREPARE_BLOCKS";
m_isClientPreparedBlocks = true;
}
break;
case profiler::net::MESSAGE_TYPE_REPLY_END_SEND_BLOCKS:
{
qInfo() << "Receive MESSAGE_TYPE_REPLY_END_SEND_BLOCKS";
}
break;
case profiler::net::MESSAGE_TYPE_REPLY_BLOCKS:
{
qInfo() << "Receive MESSAGE_TYPE_REPLY_BLOCKS";
m_recFrames = true;
2016-09-11 18:23:47 +03:00
profiler::net::DataMessage* dm = (profiler::net::DataMessage*)message;
necessarySize = dm->size;
2016-09-13 21:42:38 +03:00
loadedSize = 0;
2016-09-08 21:03:05 +03:00
m_receivedProfileData.write(data.data()+sizeof(profiler::net::DataMessage),data.size() - sizeof(profiler::net::DataMessage));
2016-09-11 18:23:47 +03:00
loadedSize += data.size() - sizeof(profiler::net::DataMessage);
2016-09-14 22:04:15 +03:00
//std::this_thread::sleep_for(std::chrono::seconds(2));
timeBegin = std::chrono::system_clock::now();
2016-09-08 21:03:05 +03:00
} break;
default:
2016-09-08 23:15:01 +03:00
//qInfo() << "Receive unknown " << message->type;
2016-09-08 21:03:05 +03:00
break;
}
}
}
2016-09-13 21:42:38 +03:00
void EasyMainWindow::onConnected()
2016-09-08 21:03:05 +03:00
{
2016-09-13 21:42:38 +03:00
qInfo() << "onConnected()";
2016-09-14 22:04:15 +03:00
2016-09-13 21:42:38 +03:00
m_isConnected = true;
}
void EasyMainWindow::onErrorConnection(QAbstractSocket::SocketError socketError)
{
qInfo() << m_server->error();
}
2016-09-08 21:03:05 +03:00
2016-09-13 21:42:38 +03:00
void EasyMainWindow::onDisconnect()
{
qInfo() << "onDisconnect()";
m_isConnected = false;
}
void EasyMainWindow::onNewConnection()
{
2016-09-12 21:28:15 +03:00
//m_client = m_server->nextPendingConnection();
2016-09-08 21:03:05 +03:00
2016-09-14 22:04:15 +03:00
//qInfo() << "New connection!" << m_client;
2016-09-13 21:42:38 +03:00
2016-09-14 22:04:15 +03:00
//connect(m_client, SIGNAL(disconnected()), this, SLOT(onDisconnection())) ;
//connect(m_client, SIGNAL(readyRead()), this, SLOT(readTcpData()) );
2016-09-08 23:15:01 +03:00
}
void EasyMainWindow::onDisconnection()
{
2016-09-14 22:04:15 +03:00
//m_client = nullptr;
2016-09-08 21:03:05 +03:00
}
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow::closeEvent(QCloseEvent* close_event)
{
saveSettingsAndGeometry();
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();
}
auto val = settings.value("chrono_text_position");
if (!val.isNull())
{
EASY_GLOBALS.chrono_text_position = static_cast<::profiler_gui::ChronometerTextPosition>(val.toInt());
}
auto flag = settings.value("draw_graphics_items_borders");
if (!flag.isNull())
{
EASY_GLOBALS.draw_graphics_items_borders = flag.toBool();
}
flag = settings.value("collapse_items_on_tree_close");
if (!flag.isNull())
{
EASY_GLOBALS.collapse_items_on_tree_close = flag.toBool();
}
flag = settings.value("all_items_expanded_by_default");
if (!flag.isNull())
{
EASY_GLOBALS.all_items_expanded_by_default = flag.toBool();
}
flag = settings.value("bind_scene_and_tree_expand_status");
if (!flag.isNull())
{
EASY_GLOBALS.bind_scene_and_tree_expand_status = flag.toBool();
}
flag = settings.value("enable_statistics");
if (!flag.isNull())
{
EASY_GLOBALS.enable_statistics = flag.toBool();
}
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");
auto geometry = settings.value("geometry").toByteArray();
if (!geometry.isEmpty())
restoreGeometry(geometry);
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-09-06 22:23:55 +03:00
settings.setValue("geometry", this->saveGeometry());
settings.setValue("last_file", m_lastFile);
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);
settings.setValue("enable_statistics", EASY_GLOBALS.enable_statistics);
settings.setValue("encoding", QTextCodec::codecForLocale()->name());
2016-09-06 22:23:55 +03:00
settings.endGroup();
}
//////////////////////////////////////////////////////////////////////////
2016-09-16 02:11:11 +03:00
void EasyMainWindow::onDownloadTimeout()
{
if (!m_downloading){
m_downloadingProgress->setValue(100);
//m_downloadingProgress->hide();
m_downloadedTimer.stop();
}
else{
m_downloadingProgress->setValue(m_downloadedBytes.load());
}
}
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;
::profiler::blocks_t blocks;
::profiler::thread_blocks_tree_t threads_map;
QString filename;
m_reader.get(serialized_blocks, serialized_descriptors, descriptors, blocks, threads_map, filename);
if (threads_map.size() > 0xff)
{
qWarning() << "Warning: file " << filename << " contains " << threads_map.size() << " threads!";
qWarning() << "Warning: Currently, maximum number of displayed threads is 255! Some threads will not be displayed.";
}
m_lastFile = ::std::move(filename);
m_serializedBlocks = ::std::move(serialized_blocks);
m_serializedDescriptors = ::std::move(serialized_descriptors);
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();
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);
}
else
{
qWarning() << "Warning: Can not open file " << m_reader.filename() << " or file is corrupted";
}
m_reader.interrupt();
m_readerTimer.stop();
m_progress->setValue(100);
//m_progress->hide();
if (EASY_GLOBALS.all_items_expanded_by_default)
{
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();
}
bool EasyFileReader::done() const
{
return m_bDone.load();
}
int EasyFileReader::progress() const
{
return m_progress.load();
}
unsigned int EasyFileReader::size() const
{
return m_size.load();
}
const QString& EasyFileReader::filename() const
{
return m_filename;
}
void EasyFileReader::load(const QString& _filename)
{
interrupt();
m_filename = _filename;
m_thread = ::std::move(::std::thread([this](bool _enableStatistics) {
m_size.store(fillTreesFromFile(m_progress, m_filename.toStdString().c_str(), m_serializedBlocks, m_serializedDescriptors, m_descriptors, m_blocks, m_blocksTree, _enableStatistics));
m_progress.store(100);
m_bDone.store(true);
}, EASY_GLOBALS.enable_statistics));
}
void EasyFileReader::interrupt()
{
m_progress.store(-100);
if (m_thread.joinable())
m_thread.join();
m_bDone.store(false);
m_progress.store(0);
m_size.store(0);
m_serializedBlocks.clear();
m_serializedDescriptors.clear();
m_descriptors.clear();
m_blocks.clear();
m_blocksTree.clear();
}
void EasyFileReader::get(::profiler::SerializedData& _serializedBlocks, ::profiler::SerializedData& _serializedDescriptors,
::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& _tree,
QString& _filename)
{
if (done())
{
m_serializedBlocks.swap(_serializedBlocks);
m_serializedDescriptors.swap(_serializedDescriptors);
::profiler::descriptors_list_t(::std::move(m_descriptors)).swap(_descriptors);
m_blocks.swap(_blocks);
m_blocksTree.swap(_tree);
m_filename.swap(_filename);
}
}
//////////////////////////////////////////////////////////////////////////