#include "main_widget.hpp"
#include <qmath.h>
#include <QCheckBox>
#include <QComboBox>
#include <QDebug>
#include <QDesktopWidget>
#include <QFileDialog>
#include <QGroupBox>
#include <QMessageBox>
#include <QMutexLocker>
#include <QPushButton>
#include <QRadioButton>
#include <QWeakPointer>
#include <cvb/device_factory.hpp>
MainWidget::MainWidget()
: QWidget(),
gbStatEntriesLayout_(new QVBoxLayout), pbSnap_(new QPushButton("Sna&p", this)),
chkGrab_(new QCheckBox("&Grab", this)), gbSelectedPort_(new QGroupBox("Selected Port", this)),
gbStatistics_(new QGroupBox("Statistic", this)), cbSelectedPort_(new QComboBox(gbSelectedPort_)),
view_(new
Cvb::UI::ImageView(this)), device_(
Cvb::DeviceFactory::Open(
Cvb::InstallPath() + CVB_LIT(
"drivers/CVMock.vin"),
Cvb::AcquisitionStack::Vin)),
streamH_(
Cvb::Async::SingleStreamHandler::Create(device_->Stream())), updateStatTimer_(new QTimer(this))
{
qDebug() << "Please wait for the setup to load...";
QPushButton* pbOpen = new QPushButton("&Open Image", this);
QPushButton* pbOpenDev = new QPushButton("&Discover Devices", this);
QPushButton* pbSave = new QPushButton("&Save Image", this);
QHBoxLayout* mainLayout = new QHBoxLayout;
QVBoxLayout* sideLayout = new QVBoxLayout;
QVBoxLayout* gbSelectedPortLayout = new QVBoxLayout;
sideLayout->addWidget(pbOpen);
sideLayout->addWidget(pbOpenDev);
sideLayout->addWidget(pbSave);
sideLayout->addWidget(chkGrab_);
sideLayout->addWidget(pbSnap_);
onDiscover();
gbStatistics_->setLayout(gbStatEntriesLayout_);
sideLayout->addWidget(gbStatistics_);
sideLayout->addStretch();
gbSelectedPortLayout->addWidget(cbSelectedPort_);
gbSelectedPort_->setLayout(gbSelectedPortLayout);
sideLayout->addWidget(gbSelectedPort_);
mainLayout->addLayout(sideLayout);
mainLayout->addStretch();
mainLayout->addWidget(view_);
setLayout(mainLayout);
connect(pbOpen, SIGNAL(clicked()), this, SLOT(onOpen()));
connect(pbOpenDev, SIGNAL(clicked()), this, SLOT(onDiscover()));
connect(pbSave, SIGNAL(clicked()), this, SLOT(onSave()));
connect(pbSnap_, SIGNAL(clicked()), this, SLOT(onSnaped()));
connect(chkGrab_, SIGNAL(stateChanged(int)), this, SLOT(onGrabChanged(int)));
connect(cbSelectedPort_, SIGNAL(currentIndexChanged(int)), this, SLOT(onPortIndexChanged(const int)));
connect(updateStatTimer_, SIGNAL(timeout()), SLOT(updateStatistics()));
updateStatTimer_->start(100);
view_->SetUploadMode(Cvb::UI::UploadMode::Viewport);
view_->SetRenderEngine(Cvb::UI::RenderEngine::Raster);
view_->Refresh(device_->DeviceImage(), Cvb::UI::AutoRefresh::On);
view_->SetWaitForRepaintEnabled(false);
initalizeTooltip();
}
MainWidget::~MainWidget()
{
streamH_->Finish();
}
void MainWidget::onGrabChanged(int state)
{
state == Qt::Unchecked ? streamH_->Finish() : streamH_->Run();
}
void MainWidget::onOpen()
{
SignalGuard guard(this);
try
{
if (streamH_->IsActive())
{
streamH_->Finish();
chkGrab_->setChecked(false);
}
QString filename = QFileDialog::getOpenFileName(
this, tr("Open Image"), QString("/"), tr("CImages (*.bmp *.jpg *.png *.tif *.tiff)"));
if (!filename.isEmpty())
{
if (img)
img.reset();
view_->Refresh(img, Cvb::UI::RefreshMode::UploadAndScheduleRepaint, Cvb::UI::AutoRefresh::Off);
}
}
{
std::cout << e.what() << "\nError opening image!" << std::endl;
}
}
void MainWidget::onDiscover()
{
SignalGuard guard(this);
std::cout << "Discovering devices..." << std::endl;
cbSelectedPort_->clear();
gbSelectedPort_->setEnabled(true);
for (const auto& device : discover_)
{
if (device.TryGetProperty(Cvb::Driver::DiscoveryProperties::DeviceModel, devModel))
cbSelectedPort_->addItem(QString::fromStdString(devModel), static_cast<int32_t>(device.Index()));
else
cbSelectedPort_->addItem(QString("Device %1").arg(device.Index()), static_cast<int32_t>(device.Index()));
}
cbSelectedPort_->setCurrentIndex(0);
loadDiscoveredDevice(0ul);
}
void MainWidget::onSave()
{
SignalGuard guard(this);
if (streamH_->IsActive())
{
streamH_->Finish();
chkGrab_->setChecked(false);
}
QString filename = QFileDialog::getSaveFileName(
this, tr("Save Image"), QString("~/"), tr("CImages (*.bmp *.jpg *.png *.tif *.tiff)"));
if (!filename.isEmpty())
view_->Image()->Save(filename.toLatin1().toStdString());
}
void MainWidget::onSnaped()
{
if (streamH_->IsActive())
{
streamH_->Finish();
chkGrab_->setChecked(false);
}
auto waitResult = device_->Stream()->GetSnapshot();
if (waitResult.Image == nullptr)
throw std::runtime_error("Could not snap image.");
}
void MainWidget::onPortIndexChanged(const int index)
{
loadDiscoveredDevice(index);
}
void MainWidget::loadDiscoveredDevice(const unsigned long devNum)
{
SignalGuard guard(this);
std::cout << "Loading device..." << std::endl;
if (streamH_->IsActive())
{
streamH_->Finish();
chkGrab_->setChecked(false);
}
try
{
if (tmpDevPtr)
{
std::cout << "Loading device " << discover_.at(devNum).AccessToken() << std::endl;
streamH_.reset();
device_.reset();
device_ = tmpDevPtr;
view_->Refresh(device_->DeviceImage(), Cvb::UI::AutoRefresh::On);
initializeStatistics();
}
}
{
std::cout << e.what() << "\nError changing discovered device!" << std::endl;
}
}
void MainWidget::updateStatistics()
{
SignalGuard guard(this);
unsigned long currentStat = 0;
for (auto const& stat : statisticsList_)
{
auto const statEnumName = std::get<0>(stat);
auto value = device_->Stream()->Statistics(statEnumName);
auto statValue = QString::number(value);
statValues_.at(currentStat)->setText(statValue);
++currentStat;
}
}
void MainWidget::initializeStatistics()
{
std::cout << "Creating device statistic..." << std::endl;
for (auto& valWdg : statValues_)
{
gbStatEntriesLayout_->removeWidget(valWdg);
delete valWdg;
}
for (auto& nameWdg : statNames_)
{
gbStatEntriesLayout_->removeWidget(nameWdg);
delete nameWdg;
}
for (auto& lay : gbHStatNameValLayout_)
{
gbStatEntriesLayout_->removeItem(lay);
delete lay;
}
statisticsList_.clear();
statisticsList_.push_back(tuple_element(StreamInfo::IsCameraDetected, "IsCameraDetected"));
statisticsList_.push_back(tuple_element(StreamInfo::NumBuffersAcquired, "NumBuffersAcquired"));
statisticsList_.push_back(tuple_element(StreamInfo::NumBuffersAnnounced, "NumBuffersAnnounced"));
statisticsList_.push_back(tuple_element(StreamInfo::NumBuffersPending, "NumBuffersPending"));
statisticsList_.push_back(tuple_element(StreamInfo::NumBuffersBeingFilled, "NumBuffersBeingFilled"));
statisticsList_.push_back(tuple_element(StreamInfo::NumBuffersDelivered, "NumBuffersDelivered"));
statisticsList_.push_back(tuple_element(StreamInfo::NumBuffersLocked, "NumBuffersLocked"));
statisticsList_.push_back(tuple_element(StreamInfo::NumBuffersLost, "NumBuffersLost"));
statisticsList_.push_back(tuple_element(StreamInfo::NumBuffersLostLocked, "NumBuffersLostLocked"));
statisticsList_.push_back(tuple_element(StreamInfo::NumBuffersLostTransfer, "NumBuffersLostTransfer"));
statisticsList_.push_back(tuple_element(StreamInfo::NumBuffersQueued, "NumBuffersQueued"));
statisticsList_.push_back(tuple_element(StreamInfo::NumPacketsReceived, "NumPacketsReceived"));
statisticsList_.push_back(tuple_element(StreamInfo::NumResends, "NumResends"));
statisticsList_.push_back(tuple_element(StreamInfo::NumTriggersLost, "NumTriggersLost"));
statNames_.clear();
statValues_.clear();
gbHStatNameValLayout_.clear();
unsigned long currentStat = 0;
int unavailableStatisticPos = -1;
std::vector<int> delEntries{};
for (auto const& stat : statisticsList_)
{
try
{
++unavailableStatisticPos;
auto const statEnumName = std::get<0>(stat);
auto value = device_->Stream()->Statistics(statEnumName);
std::string statValue = std::to_string(value);
statValues_.push_back(new QLabel(tr(statValue.c_str())));
statValues_.back()->setAlignment(Qt::AlignLeft);
statValues_.back()->updatesEnabled();
statNames_.push_back(new QLabel(tr(std::get<1>(stat).c_str())));
gbHStatNameValLayout_.push_back(new QHBoxLayout);
gbHStatNameValLayout_.at(currentStat)->addWidget(statNames_.back());
statValues_.back()->setAlignment(Qt::AlignRight);
gbHStatNameValLayout_.at(currentStat)->addWidget(statValues_.back());
gbStatEntriesLayout_->addLayout(gbHStatNameValLayout_.at(currentStat));
++currentStat;
}
catch (const std::exception& e)
{
std::cout << "Removing statistic due to error: " << e.what() << std::endl;
delEntries.push_back(unavailableStatisticPos);
}
}
for (auto ri = delEntries.rbegin(); ri != delEntries.rend(); ++ri)
statisticsList_.erase(statisticsList_.begin() + *ri);
std::cout << "Done initializing" << std::endl;
}
void MainWidget::initalizeTooltip()
{
view_->setMouseTracking(true);
QApplication::setOverrideCursor(Qt::ArrowCursor);
view_->RegisterEventMouseMoved([&](
Cvb::Point2D<int> mousePos,
const std::vector<double>& pixelVal) {
if (pixelVal.size() == 3)
{
titleStream <<
"(X:" << mousePos.
X() <<
", Y:" << mousePos.
Y() <<
") (R:" << qFloor(pixelVal[0])
<< ", G:" << qFloor(pixelVal[1]) << ", B:" << qFloor(pixelVal[2]) << ")";
}
else if (pixelVal.size() == 1)
{
titleStream <<
"(X:" << mousePos.
X() <<
", Y:" << mousePos.
Y() <<
") (Mono:" << qFloor(pixelVal[0]) <<
")";
}
else
{
titleStream <<
"(X:" << mousePos.
X() <<
", Y:" << mousePos.
Y() <<
") (Mono:";
for (auto& pix : pixelVal)
titleStream << qFloor(pix) << " | ";
titleStream << ")";
}
view_->setToolTip(QString::fromStdString(titleStream.str()));
});
}
void MainWidget::blockUI(const bool block)
{
chkGrab_->blockSignals(block);
pbSnap_->blockSignals(block);
cbSelectedPort_->blockSignals(block);
view_->blockSignals(block);
gbSelectedPort_->blockSignals(block);
gbStatistics_->blockSignals(block);
updateStatTimer_->blockSignals(block);
}
static std::vector< DiscoveryInformation > Discover()
static std::shared_ptr< T > Open(const String &provider, AcquisitionStack acquisitionStack=AcquisitionStack::PreferVin)
static std::unique_ptr< Image > Load(const String &fileName)
static std::unique_ptr< SingleStreamHandler > Create(const Driver::StreamPtr &stream)
std::stringstream StringStream
std::shared_ptr< Device > DevicePtr