226 lines
8.2 KiB
C++
226 lines
8.2 KiB
C++
|
|
#include "Widget.h"
|
|||
|
|
#include "ui_Widget.h"
|
|||
|
|
#include <QFileDialog>
|
|||
|
|
#include <QDebug>
|
|||
|
|
#include <QMessageBox>
|
|||
|
|
#include <QDateTime>
|
|||
|
|
#include <QLabel>
|
|||
|
|
#include <QMdiSubWindow>
|
|||
|
|
|
|||
|
|
/// \~chinese 用于限制显示帧率的时间戳 \~english Time stamp to limit the rate of display
|
|||
|
|
QMap<QString, QDateTime> gLastDisplay;
|
|||
|
|
|
|||
|
|
Widget::Widget(QWidget *parent) :
|
|||
|
|
QWidget(parent),
|
|||
|
|
ui(new Ui::Widget)
|
|||
|
|
{
|
|||
|
|
ui->setupUi(this);
|
|||
|
|
ui->tableWidget_cameras->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|||
|
|
|
|||
|
|
mCtrlThread = DeviceControlThread::instance();
|
|||
|
|
connect(mCtrlThread, &DeviceControlThread::signalControlFinish, this, &Widget::onControlFinish);
|
|||
|
|
connect(mCtrlThread, &DeviceControlThread::signalSelectGrabConfig, this, &Widget::onSelectGrabConfig, Qt::BlockingQueuedConnection);
|
|||
|
|
/// \~chinese 连接采图回调到主线程,需要等待显示完成后再释放缓冲区数据。主线程的耗时操作影响界面刷新时,会对采集速度造成影响
|
|||
|
|
connect(mCtrlThread, &DeviceControlThread::signalImageGrabbed, this, &Widget::onImageGrabbed, Qt::BlockingQueuedConnection);
|
|||
|
|
|
|||
|
|
ui->tableWidget_cameras->setColumnCount(3);
|
|||
|
|
ui->tableWidget_cameras->setHorizontalHeaderLabels({"Name", "Open Status", "Grab Status"});
|
|||
|
|
ui->tableWidget_cameras->setEditTriggers(QTableWidget::NoEditTriggers);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Widget::~Widget()
|
|||
|
|
{
|
|||
|
|
delete ui;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// \~chinese 扫描相机按钮的槽函数 \~english Slot function of probe push button
|
|||
|
|
void Widget::on_pushButton_probe_clicked()
|
|||
|
|
{
|
|||
|
|
mCtrlThread->StartProbe();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// \~chinese 打开相机按钮的槽函数 \~english Slot function of open camera push button
|
|||
|
|
void Widget::on_pushButton_openCamera_clicked()
|
|||
|
|
{
|
|||
|
|
QList<int> select_index;
|
|||
|
|
for (int i = 0; i < ui->tableWidget_cameras->rowCount(); ++i) {
|
|||
|
|
if (ui->tableWidget_cameras->item(i,0)->checkState() != Qt::Checked)
|
|||
|
|
continue;
|
|||
|
|
|
|||
|
|
select_index << i;
|
|||
|
|
mCtrlThread->StartOpen(i);
|
|||
|
|
}
|
|||
|
|
if (select_index.isEmpty()) {
|
|||
|
|
QMessageBox::critical(this, "Critical", "Please select the camera to operate");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// \~chinese 开始采集按钮的槽函数 \~english Slot function of start acquisitio push button
|
|||
|
|
void Widget::on_pushButton_startGrab_clicked()
|
|||
|
|
{
|
|||
|
|
QList<int> select_index;
|
|||
|
|
for (int i = 0; i < ui->tableWidget_cameras->rowCount(); ++i) {
|
|||
|
|
if (ui->tableWidget_cameras->item(i, 0)->checkState() != Qt::Checked)
|
|||
|
|
continue;
|
|||
|
|
|
|||
|
|
select_index << i;
|
|||
|
|
mCtrlThread->StartGrab(i);
|
|||
|
|
}
|
|||
|
|
if (select_index.isEmpty()) {
|
|||
|
|
QMessageBox::critical(this, "Critical", "Please select the camera to operate");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// \~chinese 关闭相机按钮的槽函数 \~english Slot function of close camera push button
|
|||
|
|
void Widget::on_pushButton_closeCamera_clicked()
|
|||
|
|
{
|
|||
|
|
QList<int> select_index;
|
|||
|
|
for (int i = 0; i < ui->tableWidget_cameras->rowCount(); ++i) {
|
|||
|
|
if (ui->tableWidget_cameras->item(i, 0)->checkState() != Qt::Checked)
|
|||
|
|
continue;
|
|||
|
|
|
|||
|
|
select_index << i;
|
|||
|
|
mCtrlThread->StartClose(i);
|
|||
|
|
}
|
|||
|
|
if (select_index.isEmpty()) {
|
|||
|
|
QMessageBox::critical(this, "Critical", "Please select the camera to operate");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// \~chinese 停止采集按钮的槽函数 \~english Slot function of stop acquisitio push button
|
|||
|
|
void Widget::on_pushButton_stopGrab_clicked()
|
|||
|
|
{
|
|||
|
|
QList<int> select_index;
|
|||
|
|
for (int i = 0; i < ui->tableWidget_cameras->rowCount(); ++i) {
|
|||
|
|
if (ui->tableWidget_cameras->item(i, 0)->checkState() != Qt::Checked)
|
|||
|
|
continue;
|
|||
|
|
|
|||
|
|
select_index << i;
|
|||
|
|
mCtrlThread->StartStopGrab(i);
|
|||
|
|
}
|
|||
|
|
if (select_index.isEmpty()) {
|
|||
|
|
QMessageBox::critical(this, "Critical", "Please select the camera to operate");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Widget::onControlFinish(int nIndex, ITK_DEVICE_CONTROL_TYPE nType, bool bSuccess)
|
|||
|
|
{
|
|||
|
|
QString devName;
|
|||
|
|
if (nType != ITK_DEVICE_CONTROL_PROBE)
|
|||
|
|
devName = ui->tableWidget_cameras->item(nIndex, 0)->text();
|
|||
|
|
switch (nType) {
|
|||
|
|
case ITK_DEVICE_CONTROL_PROBE:
|
|||
|
|
{
|
|||
|
|
if (!bSuccess) {
|
|||
|
|
QMessageBox::critical(this, "Critical", "Probe failed!");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
QStringList camList = mCtrlThread->GetDeviceList();
|
|||
|
|
ui->tableWidget_cameras->clearContents();
|
|||
|
|
ui->tableWidget_cameras->setRowCount(camList.size());
|
|||
|
|
for (int i = 0; i < camList.size(); ++i) {
|
|||
|
|
ui->tableWidget_cameras->setItem(i, 0, new QTableWidgetItem(camList[i]));
|
|||
|
|
ui->tableWidget_cameras->setItem(i, 1, new QTableWidgetItem("0"));
|
|||
|
|
ui->tableWidget_cameras->setItem(i, 2, new QTableWidgetItem("0"));
|
|||
|
|
ui->tableWidget_cameras->item(i, 0)->setCheckState(Qt::Checked);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ITK_DEVICE_CONTROL_OPEN:
|
|||
|
|
{
|
|||
|
|
if (!bSuccess) {
|
|||
|
|
QMessageBox::critical(this, "Critical", tr("Failed to open camera: %1!").arg(devName));
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
ui->pushButton_probe->setEnabled(!mCtrlThread->IsCamOpened());
|
|||
|
|
ui->tableWidget_cameras->item(nIndex, 1)->setText("1");
|
|||
|
|
|
|||
|
|
// check if exist a sub-window
|
|||
|
|
bool exist = false;
|
|||
|
|
auto list = ui->mdiArea_image->subWindowList();
|
|||
|
|
for (int i = 0; i < list.size(); ++i) {
|
|||
|
|
if (list[i]->windowTitle() != devName)
|
|||
|
|
continue;
|
|||
|
|
exist = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
if (exist)
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
QLabel* label = new QLabel(ui->mdiArea_image);
|
|||
|
|
label->setWindowTitle(devName);
|
|||
|
|
label->setAttribute(Qt::WA_DeleteOnClose);
|
|||
|
|
label->setMinimumSize(240, 160);
|
|||
|
|
ui->mdiArea_image->addSubWindow(label, Qt::WindowMinMaxButtonsHint); // disable close manually
|
|||
|
|
label->show();
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ITK_DEVICE_CONTROL_CLOSE:
|
|||
|
|
{
|
|||
|
|
if (!bSuccess) {
|
|||
|
|
QMessageBox::critical(this, "Critical", tr("Failed to close camera: %1!").arg(devName));
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
ui->pushButton_probe->setEnabled(!mCtrlThread->IsCamOpened());
|
|||
|
|
ui->tableWidget_cameras->item(nIndex, 1)->setText("0");
|
|||
|
|
ui->tableWidget_cameras->item(nIndex, 2)->setText("0");
|
|||
|
|
auto list = ui->mdiArea_image->subWindowList();
|
|||
|
|
for (int i = 0; i < list.size(); ++i) {
|
|||
|
|
if (list[i]->windowTitle() != devName)
|
|||
|
|
continue;
|
|||
|
|
list[i]->close();
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case ITK_DEVICE_CONTROL_GRAB:
|
|||
|
|
if (!bSuccess) {
|
|||
|
|
QMessageBox::critical(this, "Critical", tr("Failed to start grab: %1!").arg(devName));
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
ui->tableWidget_cameras->item(nIndex, 2)->setText("1");
|
|||
|
|
break;
|
|||
|
|
case ITK_DEVICE_CONTROL_STOP:
|
|||
|
|
if (!bSuccess) {
|
|||
|
|
QMessageBox::critical(this, "Critical", tr("Failed to stop grab: %1!").arg(devName));
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
ui->tableWidget_cameras->item(nIndex, 2)->setText("0");
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QString Widget::onSelectGrabConfig(const QString &devName)
|
|||
|
|
{
|
|||
|
|
QString fileName = QFileDialog::getOpenFileName(this, tr("Select Vlcf for %1").arg(devName), "", "*.vlcf");
|
|||
|
|
if (fileName.isEmpty()) {
|
|||
|
|
QMessageBox::information(this, "Info", tr("No config file selected, %1 will grab with default paramter").arg(devName));
|
|||
|
|
}
|
|||
|
|
return fileName;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Widget::onImageGrabbed(const QString& devName, const QImage &img)
|
|||
|
|
{
|
|||
|
|
QDateTime now = QDateTime::currentDateTime();
|
|||
|
|
/// \~chinese 控制刷新帧率小于5 \~english Limit the rate of diaply less than 5
|
|||
|
|
if (gLastDisplay[devName].isValid() && gLastDisplay[devName].msecsTo(now) < 200)
|
|||
|
|
return;
|
|||
|
|
gLastDisplay[devName] = now;
|
|||
|
|
|
|||
|
|
QLabel* label = nullptr;
|
|||
|
|
auto list = ui->mdiArea_image->subWindowList();
|
|||
|
|
for (int i = 0; i < list.size(); ++i) {
|
|||
|
|
if (list[i]->windowTitle() != devName)
|
|||
|
|
continue;
|
|||
|
|
label = qobject_cast<QLabel*>(list[i]->widget());
|
|||
|
|
}
|
|||
|
|
if (label == nullptr)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
label->setPixmap(QPixmap::fromImage(img).scaled(label->size()));
|
|||
|
|
}
|