#include "Widget.h" #include "BoostLog.h" #include "CategoryLogSinkBackend.h" #include "ModuleCommunication.h" #include #include #include #include #include #include #include #include #include #include #include #include Widget::Widget(QWidget *parent) : QWidget{parent} { auto serialGroupBox = new QGroupBox("串口设置"); auto serialLayout = new QGridLayout(); auto label = new QLabel("端口"); serialLayout->addWidget(label, 0, 0); m_serialComboBox = new QComboBox(); serialLayout->addWidget(m_serialComboBox, 0, 1); label = new QLabel("波特率"); serialLayout->addWidget(label, 1, 0); label = new QLabel("115200"); serialLayout->addWidget(label, 1, 1); auto refreshButton = new QPushButton("刷新"); connect(refreshButton, &QPushButton::clicked, this, &Widget::onSerialRefreshButtonClicked); m_serialConnectButton = new QPushButton("连接"); connect(m_serialConnectButton, &QPushButton::clicked, this, &Widget::onSerialConnectButtonClicked); serialLayout->addWidget(refreshButton, 2, 0); serialLayout->addWidget(m_serialConnectButton, 2, 1); serialGroupBox->setLayout(serialLayout); auto connectLayout = new QHBoxLayout(); connectLayout->addWidget(serialGroupBox); connectLayout->addWidget(initializeUvcGroupBox()); m_logBrowser = new QTextBrowser(); m_logBrowser->setReadOnly(true); auto logLayout = new QVBoxLayout(); m_logBrowser->setLayout(logLayout); auto btn = new QPushButton("清空"); connect(btn, &QPushButton::clicked, this, &Widget::onClearLogButtonClicked); logLayout->addWidget(btn, 0, Qt::AlignBottom | Qt::AlignRight); auto tabWidget = new QTabWidget(); tabWidget->addTab(m_logBrowser, "日志"); tabWidget->addTab(new QWidget(), "视频流"); tabWidget->addTab(new QWidget(), "已注册列表"); m_commandGroupBox = initializeCommandGroupBox(); auto operatorLayout = new QVBoxLayout(); operatorLayout->addLayout(connectLayout); operatorLayout->addWidget(m_commandGroupBox); operatorLayout->addStretch(2); auto layout = new QHBoxLayout(this); layout->addLayout(operatorLayout, 1); layout->addWidget(tabWidget, 3); m_database = std::make_shared(); QTimer::singleShot(0, this, [this]() { onSerialRefreshButtonClicked(); m_commandGroupBox->setEnabled(false); if (!m_database->open("database.db")) { LOG(error) << "open database failed."; } }); } void Widget::initializeLogger() { auto backend = boost::make_shared("GUI", m_logBrowser); using SynchronousCategorySink = boost::log::sinks::synchronous_sink; auto sink = boost::make_shared(backend); // sink->set_formatter(&zlogFormatter); boost::log::core::get()->add_sink(sink); } QGroupBox *Widget::initializeCommandGroupBox() { auto ret = new QGroupBox("命令"); auto layout = new QGridLayout(); layout->addWidget(initializeEnrollGroupBox(), 0, 0); layout->addWidget(initializeVerifyGroupBox(), 0, 1); layout->addWidget(initializeDeleteGroupBox(), 1, 0); layout->addWidget(initializePalmFeatureGroupBox(), 1, 1); auto resetButton = new QPushButton("复位"); connect(resetButton, &QPushButton::clicked, this, &Widget::onResetButtonClicked); layout->addWidget(resetButton, 2, 0); ret->setLayout(layout); return ret; } void Widget::onClearLogButtonClicked() { m_logBrowser->clear(); } QGroupBox *Widget::initializeEnrollGroupBox() { auto ret = new QGroupBox("注册用户"); auto layout = new QFormLayout(); m_enrollNameEdit = new QLineEdit(); layout->addRow("用户姓名:", m_enrollNameEdit); m_enrollTimeoutEdit = new QLineEdit("10"); layout->addRow("超时时间:", m_enrollTimeoutEdit); m_enrollButton = new QPushButton("注册"); connect(m_enrollButton, &QPushButton::clicked, this, &Widget::onEnrollButtonClicked); layout->addRow("", m_enrollButton); ret->setLayout(layout); return ret; } QGroupBox *Widget::initializeVerifyGroupBox() { auto ret = new QGroupBox("识别用户"); auto layout = new QFormLayout(); m_verifyTimeoutEdit = new QLineEdit("10"); layout->addRow("超时时间:", m_verifyTimeoutEdit); m_verifyButton = new QPushButton("识别"); connect(m_verifyButton, &QPushButton::clicked, this, &Widget::onVerifyButtonClicked); layout->addRow("", m_verifyButton); ret->setLayout(layout); return ret; } QGroupBox *Widget::initializeDeleteGroupBox() { auto ret = new QGroupBox("删除用户"); auto layout = new QFormLayout(); m_deleteIdEdit = new QLineEdit(""); layout->addRow("用户ID:", m_deleteIdEdit); m_deleteButton = new QPushButton("删除"); connect(m_deleteButton, &QPushButton::clicked, this, &Widget::onDeleteButtonClicked); layout->addRow("", m_deleteButton); m_deleteAllButton = new QPushButton("删除所有"); connect(m_deleteAllButton, &QPushButton::clicked, this, &Widget::onDeleteAllButtonClicked); layout->addRow("", m_deleteAllButton); ret->setLayout(layout); return ret; } QGroupBox *Widget::initializePalmFeatureGroupBox() { auto ret = new QGroupBox("特征值下发/上报"); auto layout = new QFormLayout(); m_palmFeatureEdit = new QLineEdit(""); layout->addRow("用户ID:", m_palmFeatureEdit); auto button1 = new QPushButton("特征值上报"); layout->addRow("", button1); connect(button1, &QPushButton::clicked, this, &Widget::onRequestPalmFeatureButtonClicked); auto button = new QPushButton("特征值下发"); connect(button, &QPushButton::clicked, this, &Widget::onRegisterPalmFeatureButtonClicked); layout->addRow("", button); ret->setLayout(layout); return ret; } QGroupBox *Widget::initializeUvcGroupBox() { auto ret = new QGroupBox("UVC设置"); auto uvcLayout = new QGridLayout(); auto label = new QLabel("设备名"); uvcLayout->addWidget(label, 0, 0); auto comboBox = new QComboBox(); uvcLayout->addWidget(comboBox, 0, 1); auto uvcRefreshButton = new QPushButton("刷新"); auto uvcConnectButton = new QPushButton("连接"); uvcLayout->addWidget(uvcRefreshButton, 1, 0); uvcLayout->addWidget(uvcConnectButton, 1, 1); ret->setLayout(uvcLayout); return ret; } void Widget::onNewPalmFeature(const PalmFeature &feature) { if (!m_database->addPalmFeature(feature)) { LOG(error) << "add palm feature failed."; } auto palms = m_database->palmFeatures(); for (auto &p : palms) { LOG(info) << p.id << " " << p.username << " " << p.feature.size(); } } void Widget::onSerialConnectButtonClicked() { auto button = dynamic_cast(sender()); if (button == nullptr) return; auto text = button->text(); if (text == "连接") { auto portName = m_serialComboBox->currentText(); m_communication = std::make_shared(); connect(m_communication.get(), &ModuleCommunication::newPalmFeature, this, &Widget::onNewPalmFeature); bool status = m_communication->open(portName); if (status) { m_commandGroupBox->setEnabled(true); button->setText("关闭"); } } else if (text == "关闭") { m_communication.reset(); m_commandGroupBox->setEnabled(false); button->setText("连接"); } } void Widget::onSerialRefreshButtonClicked() { m_serialComboBox->clear(); auto ports = QSerialPortInfo::availablePorts(); for (auto &port : ports) { m_serialComboBox->addItem(port.portName()); } } void Widget::onUvcRefreshButtonClicked() { } void Widget::onEnrollButtonClicked() { auto name = m_enrollNameEdit->text(); auto timeout = m_enrollTimeoutEdit->text().toInt(); m_communication->enroll(name.toStdString(), timeout); } void Widget::onVerifyButtonClicked() { if (!m_communication) return; auto timeout = m_verifyTimeoutEdit->text().toInt(); m_communication->verify(timeout); } void Widget::onDeleteAllButtonClicked() { if (!m_communication) return; m_communication->deleteAll(); } void Widget::onDeleteButtonClicked() { if (!m_communication) return; auto id = m_deleteIdEdit->text().toInt(); m_communication->deleteUser(id); } void Widget::onRequestPalmFeatureButtonClicked() { if (!m_communication) return; auto id = m_palmFeatureEdit->text().toInt(); m_communication->requestPalmFeature(id); } void Widget::onRegisterPalmFeatureButtonClicked() { if (!m_communication) return; auto features = m_database->palmFeatures(); if (features.empty()) { LOG(error) << "feature is empty."; return; } m_communication->enrollPalmFeature(264, features.at(0)); } void Widget::onResetButtonClicked() { if (!m_communication) return; m_communication->reset(); }